Skip to content

Commit 28fe83c

Browse files
committed
Merge pull request DozerMapper#19 from Tetradeus/GenericTypeFromSuperClass
Added support for generic superclass typed properties
2 parents 86f2ed7 + c2cddc3 commit 28fe83c

File tree

7 files changed

+108
-9
lines changed

7 files changed

+108
-9
lines changed

core/src/main/java/org/dozer/propertydescriptor/GetterSetterPropertyDescriptor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ protected void writeDeepDestinationValue(Object destObj, Object destFieldValue,
170170
hierarchyElement.getIndex());
171171
} else if (Collection.class.isAssignableFrom(clazz)) {
172172

173-
Class<?> genericType = ReflectionUtils.determineGenericsType(pd);
173+
Class<?> genericType = ReflectionUtils.determineGenericsType(parentObj.getClass(), pd);
174174
if (genericType != null) {
175175
collectionEntryType = genericType;
176176
} else {
@@ -206,7 +206,7 @@ protected void writeDeepDestinationValue(Object destObj, Object destFieldValue,
206206
collectionEntryType = pd.getPropertyType().getComponentType();
207207

208208
if (collectionEntryType == null) {
209-
collectionEntryType = ReflectionUtils.determineGenericsType(pd);
209+
collectionEntryType = ReflectionUtils.determineGenericsType(parentObj.getClass(), pd);
210210

211211
// if the target list is a List that doesn't have type specified, we can
212212
// try to use the deep-index-hint. If the list has more than 1 element, there is no
@@ -360,7 +360,7 @@ public Class<?> genericType() {
360360
Class<?> genericType = null;
361361
try {
362362
Method method = getWriteMethod();
363-
genericType = ReflectionUtils.determineGenericsType(method, false);
363+
genericType = ReflectionUtils.determineGenericsType(clazz, method, false);
364364
} catch (NoSuchMethodException e) {
365365
log.warn("The destination object: {} does not have a write method for property : {}", e);
366366
}

core/src/main/java/org/dozer/util/ReflectionUtils.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public static DeepHierarchyElement[] getDeepFieldHierarchy(Class<?> parentClass,
156156
if (latestClass.isArray()) {
157157
latestClass = latestClass.getComponentType();
158158
} else if (Collection.class.isAssignableFrom(latestClass)) {
159-
Class<?> genericType = determineGenericsType(propDescriptor);
159+
Class<?> genericType = determineGenericsType(parentClass.getClass(), propDescriptor);
160160

161161
if (genericType == null && deepIndexHintContainer == null) {
162162
MappingUtils
@@ -371,21 +371,21 @@ public static <T> T newInstance(Class<T> clazz) {
371371
return result;
372372
}
373373

374-
public static Class<?> determineGenericsType(PropertyDescriptor propDescriptor) {
374+
public static Class<?> determineGenericsType(Class<?> parentClazz, PropertyDescriptor propDescriptor) {
375375
Class<?> result = null;
376376
//Try getter and setter to determine the Generics type in case one does not exist
377377
if (propDescriptor.getWriteMethod() != null) {
378-
result = determineGenericsType(propDescriptor.getWriteMethod(), false);
378+
result = determineGenericsType(parentClazz, propDescriptor.getWriteMethod(), false);
379379
}
380380

381381
if (result == null && propDescriptor.getReadMethod() != null) {
382-
result = determineGenericsType(propDescriptor.getReadMethod(), true);
382+
result = determineGenericsType(parentClazz, propDescriptor.getReadMethod(), true);
383383
}
384384

385385
return result;
386386
}
387387

388-
public static Class<?> determineGenericsType(Method method, boolean isReadMethod) {
388+
public static Class<?> determineGenericsType(Class<?> clazz, Method method, boolean isReadMethod) {
389389
Class<?> result = null;
390390
if (isReadMethod) {
391391
Type parameterType = method.getGenericReturnType();
@@ -397,6 +397,14 @@ public static Class<?> determineGenericsType(Method method, boolean isReadMethod
397397
}
398398
}
399399

400+
if(result == null) {
401+
// Have a look at generic superclass
402+
Type genericSuperclass = clazz.getGenericSuperclass();
403+
if (genericSuperclass != null) {
404+
result = determineGenericsType(genericSuperclass);
405+
}
406+
}
407+
400408
return result;
401409
}
402410

@@ -405,7 +413,9 @@ public static Class<?> determineGenericsType(Type type) {
405413
if (type != null && ParameterizedType.class.isAssignableFrom(type.getClass())) {
406414
Type genericType = ((ParameterizedType) type).getActualTypeArguments()[0];
407415
if (genericType != null) {
408-
result = (Class<?>) genericType;
416+
if(! (genericType instanceof TypeVariable)) {
417+
result = (Class<?>) genericType;
418+
}
409419
}
410420
}
411421
return result;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.dozer.propertydescriptor;
2+
3+
import org.dozer.AbstractDozerTest;
4+
import org.dozer.fieldmap.DozerField;
5+
import org.dozer.vo.deep3.Dest;
6+
import org.dozer.vo.deep3.NestedDest;
7+
import org.junit.Test;
8+
9+
import java.lang.reflect.Method;
10+
11+
/**
12+
* GetterSetterPropertyDescriptorWithGenericSuperClassTest
13+
*
14+
* @author tetra
15+
* @version $Id$
16+
*/
17+
public class GetterSetterPropertyDescriptorWithGenericSuperClassTest extends AbstractDozerTest {
18+
@Test
19+
public void testGetReadMethod() throws Exception {
20+
DozerField dozerField = new DozerField("nestedList", "generic");
21+
22+
JavaBeanPropertyDescriptor pd = new JavaBeanPropertyDescriptor(Dest.class, dozerField.getName(), dozerField.isIndexed(),
23+
dozerField.getIndex(), null, null);
24+
Class<?> clazz = pd.genericType();
25+
26+
assertNotNull("clazz should not be null", clazz);
27+
assertEquals("NestedDest generic type", NestedDest.class, clazz);
28+
}
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.dozer.vo.deep3;
2+
3+
import java.util.List;
4+
5+
/**
6+
* AbstractDest
7+
*
8+
* @author tetra
9+
* @version $Id$
10+
*/
11+
public class AbstractDest<T> {
12+
private List<T> nestedList;
13+
14+
public List<T> getNestedList() {
15+
return nestedList;
16+
}
17+
18+
public void setNestedList(List<T> nestedList) {
19+
this.nestedList = nestedList;
20+
}
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.dozer.vo.deep3;
2+
3+
/**
4+
* Dest
5+
*
6+
* @author tetra
7+
* @version $Id$
8+
*/
9+
public class Dest extends AbstractDest<NestedDest> {
10+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.dozer.vo.deep3;
2+
3+
/**
4+
* NestedDest
5+
*
6+
* @author tetra
7+
* @version $Id$
8+
*/
9+
public class NestedDest {
10+
private NestedNestedDest nestedNestedDest;
11+
12+
public NestedNestedDest getNestedNestedDest() {
13+
return nestedNestedDest;
14+
}
15+
16+
public void setNestedNestedDest(NestedNestedDest nestedNestedDest) {
17+
this.nestedNestedDest = nestedNestedDest;
18+
}
19+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.dozer.vo.deep3;
2+
3+
/**
4+
* NestedNestedDest
5+
*
6+
* @author tetra
7+
* @version $Id$
8+
*/
9+
public class NestedNestedDest {
10+
}

0 commit comments

Comments
 (0)