Skip to content

Commit 93ef9eb

Browse files
committed
use Type... instead of Map for generic classes
1 parent cfb0b12 commit 93ef9eb

File tree

6 files changed

+99
-25
lines changed

6 files changed

+99
-25
lines changed

src/main/java/io/javarig/RandomInstanceGenerator.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
import io.javarig.exception.InstanceGenerationException;
44
import io.javarig.exception.NestedObjectRecursionException;
55
import io.javarig.generator.CollectionGenerator;
6-
import io.javarig.generator.ObjectGenerator;
76
import io.javarig.generator.TypeGenerator;
87
import lombok.NonNull;
98
import org.apache.commons.lang3.Validate;
109

1110
import java.lang.reflect.Type;
12-
import java.util.Map;
1311
import java.util.Stack;
1412
import java.util.function.Consumer;
1513

@@ -98,16 +96,6 @@ public <T> T generate(
9896
return generate(parameterizedType);
9997
}
10098

101-
public <T> T generate(
102-
@NonNull Type objectType,
103-
@NonNull Map<String,Type> genericTypes
104-
) throws InstanceGenerationException {
105-
return generate(objectType, generator -> {
106-
if(generator instanceof ObjectGenerator objectGenerator){
107-
objectGenerator.setGenericTypes(genericTypes);
108-
}
109-
});
110-
}
11199

112100
/**
113101
* generate a random instance of a generic collection with a fixed size

src/main/java/io/javarig/generator/ObjectGenerator.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.javarig.generator;
22

3+
import io.javarig.util.GenericTypes;
34
import io.javarig.ParameterizedTypeImpl;
45
import io.javarig.RandomInstanceGenerator;
56
import io.javarig.exception.AbstractClassInstantiationException;
@@ -13,6 +14,8 @@
1314

1415
import java.lang.reflect.*;
1516
import java.util.*;
17+
import java.util.stream.Collectors;
18+
import java.util.stream.IntStream;
1619

1720
import static io.javarig.util.Utils.getOwnOrInheritedFieldByName;
1821

@@ -21,22 +24,39 @@
2124
@Slf4j
2225
public class ObjectGenerator extends TypeGenerator {
2326
private static final String SETTER_PREFIX = "set";
24-
private Map<String,Type> genericTypes = new HashMap<>();
27+
private Map<String,Type> genericTypesMap = new HashMap<>();
2528

2629
public ObjectGenerator(Type type, RandomInstanceGenerator randomInstanceGenerator) {
2730
super(type, randomInstanceGenerator);
2831
}
2932

3033
@Override
3134
public Object generate() throws InstanceGenerationException {
32-
Class<?> objectClass = (Class<?>) getType();
35+
Type objectType = getType();
36+
Class<?> objectClass;
37+
if(objectType instanceof ParameterizedType parameterizedType){
38+
objectClass = (Class<?>) parameterizedType.getRawType();
39+
constructGenericTypesMap(objectClass, parameterizedType);
40+
} else {
41+
objectClass = (Class<?>) objectType;
42+
}
3343
Object generatedObject = getNewObjectInstance(objectClass);
3444
log.info("generating object of type {} ...", objectClass.getName());
3545
generateFields(generatedObject, objectClass);
3646
log.info("created object {}", generatedObject);
3747
return generatedObject;
3848
}
3949

50+
private void constructGenericTypesMap(Class<?> objectClass, ParameterizedType parameterizedType) {
51+
List<Type> typeParametersValues = Arrays.asList(parameterizedType.getActualTypeArguments());
52+
List<String> typeParametersKeys = Arrays.stream(objectClass.getTypeParameters())
53+
.map(TypeVariable::getTypeName)
54+
.toList();
55+
genericTypesMap = IntStream.range(0, typeParametersKeys.size())
56+
.boxed()
57+
.collect(Collectors.toMap(typeParametersKeys::get, typeParametersValues::get));
58+
}
59+
4060
private void generateFields(Object generatedObject, Class<?> objectClass) throws InstanceGenerationException {
4161
List<Method> setters = getSetters(objectClass);
4262
setters.forEach((setter) -> generateFieldWithSetter(generatedObject, objectClass, setter));
@@ -63,7 +83,7 @@ private void generateField(Object generatedObject, Method setter, Field field) t
6383
if(type instanceof ParameterizedType parameterizedType){
6484
type = setTypeArguments(parameterizedType);
6585
}
66-
Object generatedField = getRandomInstanceGenerator().generate(type);
86+
Object generatedField = getRandomInstanceGenerator().generate(GenericTypes.resolve(type, genericTypesMap));
6787
try {
6888
setter.invoke(generatedObject, generatedField);
6989
} catch (IllegalAccessException ignore) {
@@ -76,13 +96,13 @@ private void generateField(Object generatedObject, Method setter, Field field) t
7696
}
7797

7898
private Type setTypeArguments(Type type) {
79-
List<Type> typeArguments = new ArrayList<>();
8099
ParameterizedType parameterizedType = (ParameterizedType) type;
81-
for(Type typeArgument : parameterizedType.getActualTypeArguments()){
82-
typeArguments.add(genericTypes.getOrDefault(typeArgument.getTypeName(),typeArgument));
83-
}
100+
List<Type> typeArguments = Arrays.stream(parameterizedType.getActualTypeArguments())
101+
.map((typeArgument -> GenericTypes.resolve(typeArgument, genericTypesMap)))
102+
.toList();
84103
Type[] typeArgumentsArray = new Type[typeArguments.size()];
85-
return new ParameterizedTypeImpl(typeArguments.toArray(typeArgumentsArray), (Class<?>) ((ParameterizedType) type).getRawType());
104+
return new ParameterizedTypeImpl(typeArguments.toArray(typeArgumentsArray),
105+
(Class<?>) ((ParameterizedType) type).getRawType());
86106
}
87107

88108
private Object getNewObjectInstance(Class<?> objectClass) throws InstanceGenerationException {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.javarig.util;
2+
3+
import java.lang.reflect.Type;
4+
import java.util.Map;
5+
6+
public class GenericTypes {
7+
public static Type resolve(Type type, Map<String, Type> genericTypesMap){
8+
if(genericTypesMap.containsKey(type.getTypeName())){
9+
return genericTypesMap.get(type.getTypeName());
10+
}
11+
return type;
12+
}
13+
}

src/test/java/io/javarig/generation/ObjectGenerationTest.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212

1313
import java.lang.reflect.InvocationTargetException;
1414
import java.lang.reflect.Type;
15-
import java.util.HashMap;
16-
import java.util.Map;
17-
import java.util.TreeMap;
1815

1916
import static org.assertj.core.api.Assertions.assertThat;
2017
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -198,8 +195,7 @@ public void shouldGenerateBaseFieldsAndInheritedFieldsWhenGivenClassExtendingAno
198195
@ValueSource(classes = {String.class, Integer.class, Double.class, BaseClass.class})
199196
public void shouldGenerateAGenericClass(Type genericType) {
200197
//given
201-
Map<String, Type> genericTypes = Map.of("T", genericType);
202-
Object generatedObject = randomInstanceGenerator.generate(GenericTestClass.class, genericTypes);
198+
Object generatedObject = randomInstanceGenerator.generate(GenericTestClass.class, genericType);
203199
// then
204200
assertThat(generatedObject)
205201
.isNotNull()
@@ -214,4 +210,32 @@ public void shouldGenerateAGenericClass(Type genericType) {
214210
.isInstanceOf((Class<?>) genericType);
215211
}
216212

213+
@Test
214+
public void shouldGenerateAGenericClassWithRightOrderTypes() {
215+
//given
216+
Class<String> classParam1 = String.class;
217+
Class<Integer> classParam2 = Integer.class;
218+
Object generatedObject = randomInstanceGenerator.generate(GenericTestClass2.class, classParam1, classParam2);
219+
// then
220+
assertThat(generatedObject)
221+
.isNotNull()
222+
.isInstanceOf(GenericTestClass2.class);
223+
224+
GenericTestClass2<String, Integer> genericTestClass2 = (GenericTestClass2) generatedObject;
225+
assertThat(genericTestClass2)
226+
.extracting(GenericTestClass2::getGenericClass3)
227+
.isNotNull()
228+
.isInstanceOf(GenericTestClass3.class)
229+
.extracting(GenericTestClass3::getT)
230+
.isNotNull()
231+
.isInstanceOf(classParam2);
232+
233+
assertThat(genericTestClass2)
234+
.extracting(GenericTestClass2::getGenericClass3)
235+
.isNotNull()
236+
.isInstanceOf(GenericTestClass3.class)
237+
.extracting(GenericTestClass3::getK)
238+
.isNotNull()
239+
.isInstanceOf(classParam1);
240+
}
217241
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.javarig.testclasses;
2+
3+
import lombok.Getter;
4+
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
6+
import lombok.ToString;
7+
8+
@NoArgsConstructor
9+
@Getter
10+
@Setter
11+
@ToString
12+
public class GenericTestClass2<T,K> {
13+
private GenericTestClass3<K,T> genericClass3;
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.javarig.testclasses;
2+
3+
import lombok.Getter;
4+
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
6+
import lombok.ToString;
7+
8+
@NoArgsConstructor
9+
@Getter
10+
@Setter
11+
@ToString
12+
public class GenericTestClass3<T,K> {
13+
private T t;
14+
private K k;
15+
}

0 commit comments

Comments
 (0)