Skip to content

Commit

Permalink
Deprecate pushExactTypePropertyCandidateResolver
Browse files Browse the repository at this point in the history
  • Loading branch information
seongahjo committed Jul 27, 2024
1 parent dbf39ee commit 1f35f18
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
Expand All @@ -32,6 +31,7 @@
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.api.type.GenericType;
import com.navercorp.fixturemonkey.api.type.Types;

@API(since = "1.0.16", status = Status.EXPERIMENTAL)
Expand All @@ -53,23 +53,7 @@ public List<Property> resolve(Property property) {

return concreteTypes.stream()
.map(it -> {
Type concreteGenericType = new ParameterizedType() {

@Override
public Type[] getActualTypeArguments() {
return typeArguments;
}

@Override
public Type getRawType() {
return it;
}

@Override
public Type getOwnerType() {
return null;
}
};
Type concreteGenericType = new GenericType(it, typeArguments, null);

AnnotatedType genericAnnotatedType = new AnnotatedType() {
@Override
Expand Down Expand Up @@ -125,24 +109,6 @@ public <A extends Annotation> Optional<A> getAnnotation(Class<A> annotationClass
public Object getValue(Object instance) {
return property.getValue(instance);
}

@Override
public int hashCode() {
return getType().hashCode();
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() == obj.getClass()) {
return false;
}

Property that = (Property)obj;
return getType().equals(that.getType());
}
};
})
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.fixturemonkey.api.type;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;

import javax.annotation.Nullable;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

/**
* Represents a parameterized type with a container type, type arguments, and an optional owner type.
* <p>
* It is mainly used for the type with type arguments.
* For example, {@code List<String>}, {@code Map<String, Integer>}, {@code CustomClass<String>}
* <p>
* This class is marked as experimental and may change in future releases.
*/
@API(since = "1.0.22", status = Status.EXPERIMENTAL)
public final class GenericType implements ParameterizedType {
private final Type containerType;
private final Type[] typeArguments;
@Nullable
private final Type ownerType;

/**
* Constructs a new {@code GenericType} instance with the specified container type, resolved type arguments,
* and an optional owner type.
*
* @param containerType the container type
* @param resolvedTypeArguments the resolved type arguments
* @param ownerType the owner type, or {@code null} if there is no owner type
*/
public GenericType(Type containerType, Type[] resolvedTypeArguments, @Nullable Type ownerType) {
this.containerType = containerType;
this.ownerType = ownerType;
this.typeArguments = resolvedTypeArguments;
}

@Override
public Type[] getActualTypeArguments() {
return typeArguments;
}

@Override
public Type getRawType() {
return containerType;
}

@Override
@Nullable
public Type getOwnerType() {
return this.ownerType;
}

@Override
public int hashCode() {
return Objects.hash(containerType, ownerType, Arrays.hashCode(typeArguments));
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ParameterizedType)) {
return false;
}

ParameterizedType that = (ParameterizedType)obj;
return this.containerType.equals(that.getRawType())
&& Arrays.equals(this.typeArguments, that.getActualTypeArguments())
&& Objects.equals(this.ownerType, that.getOwnerType());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -287,22 +287,7 @@ private static AnnotatedType resolvesParentTypeGenerics(
}

ParameterizedType type = (ParameterizedType)fieldParameterizedType.getType();
Type resolveType = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return resolvedTypes;
}

@Override
public Type getRawType() {
return type.getRawType();
}

@Override
public Type getOwnerType() {
return type.getOwnerType();
}
};
Type resolveType = new GenericType(type.getRawType(), resolvedTypes, type.getOwnerType());

return AnnotatedTypes.newAnnotatedParameterizedType(
resolvedGenericsTypes,
Expand All @@ -326,22 +311,11 @@ private static AnnotatedArrayType resolveGenericsArrayType(
types[i] = ownerGenericsTypes[i].getType();
}

ParameterizedType genericComponentTypeWithGeneric = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return types;
}

@Override
public Type getRawType() {
return genericComponentType.getRawType();
}

@Override
public Type getOwnerType() {
return genericComponentType.getOwnerType();
}
};
ParameterizedType genericComponentTypeWithGeneric = new GenericType(
genericComponentType.getRawType(),
types,
genericComponentType.getOwnerType()
);

Type resolveType = (GenericArrayType)() -> genericComponentTypeWithGeneric;

Expand Down Expand Up @@ -432,6 +406,9 @@ public static Class<?> wrapperToPrimitive(final Class<?> cls) {
return wrapperPrimitiveMap.get(cls);
}

/**
* It is same as {@code toClass.isAssignableFrom(cls)}.
*/
public static boolean isAssignable(Class<?> cls, Class<?> toClass) {
return isAssignable(cls, toClass, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitra
import com.navercorp.fixturemonkey.api.introspector.FactoryMethodArbitraryIntrospector
import com.navercorp.fixturemonkey.api.introspector.FailoverIntrospector
import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector
import com.navercorp.fixturemonkey.api.matcher.AssignableTypeMatcher
import com.navercorp.fixturemonkey.api.matcher.MatcherOperator
import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin
import com.navercorp.fixturemonkey.api.property.ConcreteTypeCandidateConcretePropertyResolver
Expand Down Expand Up @@ -781,12 +782,12 @@ class KotlinTest {
}

@RepeatedTest(TEST_COUNT)
fun pushExactTypePropertyCandidateResolver() {
fun interfaceImplementsExtendsInterface() {
val sut = FixtureMonkey.builder()
.plugin(KotlinPlugin())
.pushExactTypePropertyCandidateResolver(
Collection::class.java,
ConcreteTypeCandidateConcretePropertyResolver(listOf(Set::class.java))
.plugin(
InterfacePlugin()
.interfaceImplements(Collection::class.java, listOf(Set::class.java))
)
.build()

Expand Down Expand Up @@ -869,6 +870,25 @@ class KotlinTest {
then(actual.lambda).isNotNull
}

@Test
fun interfaceImplementsAssignableTypeGeneratesConcreteTypeNotThrows() {
val sut = FixtureMonkey.builder()
.plugin(KotlinPlugin())
.plugin(
InterfacePlugin()
.interfaceImplements(
AssignableTypeMatcher(Collection::class.java),
listOf(LinkedList::class.java)
)

)
.build()

val actual: ArrayList<String> = sut.giveMeOne()

then(actual).isInstanceOf(ArrayList::class.java)
}

companion object {
private val SUT: FixtureMonkey = FixtureMonkey.builder()
.plugin(KotlinPlugin())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,11 @@ public FixtureMonkeyBuilder seed(long seed) {
return this;
}

/**
* Use {@link InterfacePlugin#interfaceImplements(Class, List)}
* or {@link InterfacePlugin#abstractClassExtends(Class, List)} instead.
*/
@Deprecated
public FixtureMonkeyBuilder pushExactTypePropertyCandidateResolver(
Class<?> type,
CandidateConcretePropertyResolver candidateConcretePropertyResolver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package com.navercorp.fixturemonkey.tree;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -323,6 +324,21 @@ private List<Property> resolveCandidateProperties(Property property) {
List<Property> resolvedCandidateProperties = new ArrayList<>();
List<Property> candidateProperties = candidateConcretePropertyResolver.resolve(p);
for (Property candidateProperty : candidateProperties) {
// compares by type until a specific property implementation is created for the generic type.
Type candidateType = candidateProperty.getType();

boolean assignableType = Types.isAssignable(
Types.getActualType(candidateType),
Types.getActualType(p.getType())
);
// if (p.getType().equals(candidateType) || !assignableType) {
if (p.getType().equals(candidateType) ) {
// prevents infinite recursion
resolvedCandidateProperties.addAll(
DefaultCandidateConcretePropertyResolver.INSTANCE.resolve(p)
);
continue;
}
resolvedCandidateProperties.addAll(resolveCandidateProperties(candidateProperty));
}
return resolvedCandidateProperties;
Expand Down

0 comments on commit 1f35f18

Please sign in to comment.