This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch 3.2
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.2 by this push:
     new 960f6523f9 pojoutil support generic (#11914)
960f6523f9 is described below

commit 960f6523f99eb0785f4d7495f43dc1ed7163fd8d
Author: Owen.Cai <[email protected]>
AuthorDate: Thu Mar 30 20:41:12 2023 +0800

    pojoutil support generic (#11914)
    
    * pojoutil support generic
    
    * add test
    
    * generic pojo
    
    ---------
    
    Co-authored-by: caizhenqiu <[email protected]>
---
 .../org/apache/dubbo/common/utils/PojoUtils.java   |  67 +++++--
 .../apache/dubbo/common/model/person/Ageneric.java |  38 ++++
 .../apache/dubbo/common/model/person/Bgeneric.java |  38 ++++
 .../apache/dubbo/common/model/person/Cgeneric.java |  56 ++++++
 .../apache/dubbo/common/model/person/Dgeneric.java |  56 ++++++
 .../apache/dubbo/common/utils/PojoUtilsTest.java   | 208 +++++++++++++++++++++
 6 files changed, 450 insertions(+), 13 deletions(-)

diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java 
b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
index b290529ccb..60a78061f4 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
@@ -329,6 +329,10 @@ public class PojoUtils {
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     private static Object realize0(Object pojo, Class<?> type, Type 
genericType, final Map<Object, Object> history) {
+        return realize1(pojo, type, genericType, new HashMap<>(8), history);
+    }
+
+    private static Object realize1(Object pojo, Class<?> type, Type 
genericType, final Map<String, Type> mapParent, final Map<Object, Object> 
history) {
         if (pojo == null) {
             return null;
         }
@@ -352,6 +356,19 @@ public class PojoUtils {
 
         history.put(pojo, pojo);
 
+        Map<String, Type> mapGeneric = new HashMap<>(8);
+        mapGeneric.putAll(mapParent);
+        TypeVariable<? extends Class<?>>[] typeParameters = 
type.getTypeParameters();
+        if(genericType instanceof ParameterizedType && typeParameters.length > 
0) {
+            ParameterizedType parameterizedType = 
(ParameterizedType)genericType;
+            Type[] actualTypeArguments = 
parameterizedType.getActualTypeArguments();
+            for (int i = 0; i < typeParameters.length; i++) {
+                if(!(actualTypeArguments[i] instanceof TypeVariable)) {
+                    mapGeneric.put(typeParameters[i].getTypeName(), 
actualTypeArguments[i]);
+                }
+            }
+        }
+
         if (pojo.getClass().isArray()) {
             if (Collection.class.isAssignableFrom(type)) {
                 Class<?> ctype = pojo.getClass().getComponentType();
@@ -360,7 +377,7 @@ public class PojoUtils {
                 history.put(pojo, dest);
                 for (int i = 0; i < len; i++) {
                     Object obj = Array.get(pojo, i);
-                    Object value = realize0(obj, ctype, null, history);
+                    Object value = realize1(obj, ctype, null, mapGeneric, 
history);
                     dest.add(value);
                 }
                 return dest;
@@ -371,7 +388,7 @@ public class PojoUtils {
                 history.put(pojo, dest);
                 for (int i = 0; i < len; i++) {
                     Object obj = Array.get(pojo, i);
-                    Object value = realize0(obj, ctype, null, history);
+                    Object value = realize1(obj, ctype, null, mapGeneric, 
history);
                     Array.set(dest, i, value);
                 }
                 return dest;
@@ -387,7 +404,7 @@ public class PojoUtils {
                 history.put(pojo, dest);
                 int i = 0;
                 for (Object obj : src) {
-                    Object value = realize0(obj, ctype, null, history);
+                    Object value = realize1(obj, ctype, null, mapGeneric, 
history);
                     Array.set(dest, i, value);
                     i++;
                 }
@@ -403,7 +420,7 @@ public class PojoUtils {
                     if (keyType instanceof Class) {
                         keyClazz = (Class<?>) keyType;
                     }
-                    Object value = realize0(obj, keyClazz, keyType, history);
+                    Object value = realize1(obj, keyClazz, keyType, 
mapGeneric, history);
                     dest.add(value);
                 }
                 return dest;
@@ -486,8 +503,8 @@ public class PojoUtils {
                         valueClazz = entry.getValue() == null ? null : 
entry.getValue().getClass();
                     }
 
-                    Object key = keyClazz == null ? entry.getKey() : 
realize0(entry.getKey(), keyClazz, keyType, history);
-                    Object value = valueClazz == null ? entry.getValue() : 
realize0(entry.getValue(), valueClazz, valueType, history);
+                    Object key = keyClazz == null ? entry.getKey() : 
realize1(entry.getKey(), keyClazz, keyType, mapGeneric, history);
+                    Object value = valueClazz == null ? entry.getValue() : 
realize1(entry.getValue(), valueClazz, valueType, mapGeneric, history);
                     result.put(key, value);
                 }
                 return result;
@@ -509,6 +526,7 @@ public class PojoUtils {
                 }
 
                 history.put(pojo, dest);
+
                 for (Map.Entry<Object, Object> entry : map.entrySet()) {
                     Object key = entry.getKey();
                     if (key instanceof String) {
@@ -521,8 +539,24 @@ public class PojoUtils {
                                 if (!method.isAccessible()) {
                                     method.setAccessible(true);
                                 }
-                                Type ptype = 
method.getGenericParameterTypes()[0];
-                                value = realize0(value, 
method.getParameterTypes()[0], ptype, history);
+                                Type containType = 
mapGeneric.get(field.getGenericType().getTypeName());
+                                if(containType != null) {
+                                    //is generic
+                                    if(containType instanceof 
ParameterizedType) {
+                                        value = realize1(value, (Class<?>) 
((ParameterizedType)containType).getRawType(), containType, mapGeneric, 
history);
+                                    }
+                                    else if (containType instanceof Class){
+                                        value = realize1(value, (Class<?>) 
containType, containType, mapGeneric, history);
+                                    }
+                                    else {
+                                        Type ptype = 
method.getGenericParameterTypes()[0];
+                                        value = realize1(value, 
method.getParameterTypes()[0], ptype, mapGeneric, history);
+                                    }
+                                }
+                                else {
+                                    Type ptype = 
method.getGenericParameterTypes()[0];
+                                    value = realize1(value, 
method.getParameterTypes()[0], ptype, mapGeneric, history);
+                                }
                                 try {
                                     method.invoke(dest, value);
                                 } catch (Exception e) {
@@ -532,7 +566,7 @@ public class PojoUtils {
                                     throw new 
RuntimeException(exceptionDescription, e);
                                 }
                             } else if (field != null) {
-                                value = realize0(value, field.getType(), 
field.getGenericType(), history);
+                                value = realize1(value, field.getType(), 
field.getGenericType(), mapGeneric, history);
                                 try {
                                     field.set(dest, value);
                                 } catch (IllegalAccessException e) {
@@ -675,10 +709,16 @@ public class PojoUtils {
         if (CLASS_FIELD_CACHE.containsKey(cls) && 
CLASS_FIELD_CACHE.get(cls).containsKey(fieldName)) {
             return CLASS_FIELD_CACHE.get(cls).get(fieldName);
         }
-        try {
-            result = cls.getDeclaredField(fieldName);
-            result.setAccessible(true);
-        } catch (NoSuchFieldException e) {
+        for(Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) {
+            try {
+                result = acls.getDeclaredField(fieldName);
+                if (!Modifier.isPublic(result.getModifiers())) {
+                    result.setAccessible(true);
+                }
+            } catch (NoSuchFieldException e) {
+            }
+        }
+        if(result == null) {
             for (Field field : cls.getFields()) {
                 if (fieldName.equals(field.getName()) && 
ReflectUtils.isPublicInstanceField(field)) {
                     result = field;
@@ -686,6 +726,7 @@ public class PojoUtils {
                 }
             }
         }
+
         if (result != null) {
             ConcurrentMap<String, Field> fields = 
CLASS_FIELD_CACHE.computeIfAbsent(cls, k -> new ConcurrentHashMap<>());
             fields.putIfAbsent(fieldName, result);
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Ageneric.java 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Ageneric.java
new file mode 100644
index 0000000000..2662f029ab
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Ageneric.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.dubbo.common.model.person;
+
+import java.io.Serializable;
+
+public class Ageneric<T> implements Serializable {
+    public static String NAME = "A";
+
+    private String name = NAME;
+    private T data;
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Bgeneric.java 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Bgeneric.java
new file mode 100644
index 0000000000..1a4408cbb6
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Bgeneric.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.dubbo.common.model.person;
+
+import java.io.Serializable;
+
+public class Bgeneric<T> implements Serializable {
+    public static String NAME = "B";
+
+    private String name = NAME;
+    private T data;
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Cgeneric.java 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Cgeneric.java
new file mode 100644
index 0000000000..2a47cc50ad
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Cgeneric.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.dubbo.common.model.person;
+
+import java.io.Serializable;
+
+public class Cgeneric<T> implements Serializable {
+    public static String NAME = "C";
+
+    private String name = NAME;
+    private T data;
+    private Ageneric<T> a;
+    private Bgeneric<PersonInfo> b;
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Ageneric<T> getA() {
+        return a;
+    }
+
+    public void setA(Ageneric<T> a) {
+        this.a = a;
+    }
+
+    public Bgeneric<PersonInfo> getB() {
+        return b;
+    }
+
+    public void setB(Bgeneric<PersonInfo> b) {
+        this.b = b;
+    }
+}
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Dgeneric.java 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Dgeneric.java
new file mode 100644
index 0000000000..0aaabd87a5
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Dgeneric.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.dubbo.common.model.person;
+
+import java.io.Serializable;
+
+public class Dgeneric<T,Y,Z> implements Serializable {
+    public static String NAME = "D";
+
+    private String name = NAME;
+    private T t;
+    private Y y;
+    private Z z;
+
+    public T getT() {
+        return t;
+    }
+
+    public void setT(T t) {
+        this.t = t;
+    }
+
+    public Y getY() {
+        return y;
+    }
+
+    public void setY(Y y) {
+        this.y = y;
+    }
+
+    public Z getZ() {
+        return z;
+    }
+
+    public void setZ(Z z) {
+        this.z = z;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java 
b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
index 9140168ecd..4c67a41d99 100644
--- 
a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
@@ -34,11 +34,16 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import com.alibaba.fastjson.JSON;
 import org.apache.dubbo.common.model.Person;
 import org.apache.dubbo.common.model.SerializablePerson;
 import org.apache.dubbo.common.model.User;
+import org.apache.dubbo.common.model.person.Bgeneric;
 import org.apache.dubbo.common.model.person.BigPerson;
+import org.apache.dubbo.common.model.person.Cgeneric;
+import org.apache.dubbo.common.model.person.Dgeneric;
 import org.apache.dubbo.common.model.person.FullAddress;
+import org.apache.dubbo.common.model.person.Ageneric;
 import org.apache.dubbo.common.model.person.PersonInfo;
 import org.apache.dubbo.common.model.person.PersonMap;
 import org.apache.dubbo.common.model.person.PersonStatus;
@@ -790,6 +795,209 @@ class PojoUtilsTest {
         assertEquals(PersonMap.class, result.getClass());
     }
 
+
+    protected PersonInfo createPersonInfoByName(String name) {
+        PersonInfo dataPerson = new PersonInfo();
+        dataPerson.setName(name);
+        return dataPerson;
+    }
+
+    protected Ageneric<PersonInfo> createAGenericPersonInfo(String name) {
+        Ageneric<PersonInfo> ret = new Ageneric();
+        ret.setData(createPersonInfoByName(name));
+        return ret;
+    }
+
+    protected Bgeneric<PersonInfo> createBGenericPersonInfo(String name) {
+        Bgeneric<PersonInfo> ret = new Bgeneric();
+        ret.setData(createPersonInfoByName(name));
+        return ret;
+    }
+
+    @Test
+    public void testPojoGeneric1() throws NoSuchMethodException {
+        String personName = "testName";
+
+        {
+            Ageneric<PersonInfo> genericPersonInfo = 
createAGenericPersonInfo(personName);
+
+            Object o = JSON.toJSON(genericPersonInfo);
+            {
+                Ageneric personInfo = (Ageneric) PojoUtils.realize(o, 
Ageneric.class);
+
+                assertEquals(Ageneric.NAME, personInfo.getName());
+                assertTrue(personInfo.getData() instanceof Map);
+            }
+            {
+                Type[] createGenericPersonInfos = 
ReflectUtils.getReturnTypes(PojoUtilsTest.class.getDeclaredMethod("createAGenericPersonInfo",
 String.class));
+                Ageneric personInfo = (Ageneric) PojoUtils.realize(o, 
(Class)createGenericPersonInfos[0], createGenericPersonInfos[1]);
+
+                assertEquals(Ageneric.NAME, personInfo.getName());
+                assertEquals(personInfo.getData().getClass(), 
PersonInfo.class);
+                assertEquals(personName, 
((PersonInfo)personInfo.getData()).getName());
+            }
+        }
+        {
+            Bgeneric<PersonInfo> genericPersonInfo = 
createBGenericPersonInfo(personName);
+
+            Object o = JSON.toJSON(genericPersonInfo);
+            {
+                Bgeneric personInfo = (Bgeneric) PojoUtils.realize(o, 
Bgeneric.class);
+
+                assertEquals(Bgeneric.NAME, personInfo.getName());
+                assertTrue(personInfo.getData() instanceof Map);
+            }
+            {
+                Type[] createGenericPersonInfos = 
ReflectUtils.getReturnTypes(PojoUtilsTest.class.getDeclaredMethod("createBGenericPersonInfo",
 String.class));
+                Bgeneric personInfo = (Bgeneric) PojoUtils.realize(o, 
(Class)createGenericPersonInfos[0], createGenericPersonInfos[1]);
+
+                assertEquals(Bgeneric.NAME, personInfo.getName());
+                assertEquals(personInfo.getData().getClass(), 
PersonInfo.class);
+                assertEquals(personName, 
((PersonInfo)personInfo.getData()).getName());
+            }
+        }
+    }
+
+    protected Ageneric<Ageneric<PersonInfo>> createAGenericLoop(String name) {
+        Ageneric<Ageneric<PersonInfo>> ret = new Ageneric();
+        ret.setData(createAGenericPersonInfo(name));
+        return ret;
+    }
+
+    protected Bgeneric<Ageneric<PersonInfo>> createBGenericWithAgeneric(String 
name) {
+        Bgeneric<Ageneric<PersonInfo>> ret = new Bgeneric();
+        ret.setData(createAGenericPersonInfo(name));
+        return ret;
+    }
+
+    @Test
+    public void testPojoGeneric2() throws NoSuchMethodException {
+        String personName = "testName";
+
+        {
+            Ageneric<Ageneric<PersonInfo>> generic2PersonInfo = 
createAGenericLoop(personName);
+            Object o = JSON.toJSON(generic2PersonInfo);
+            {
+                Ageneric personInfo = (Ageneric) PojoUtils.realize(o, 
Ageneric.class);
+
+                assertEquals(Ageneric.NAME, personInfo.getName());
+                assertTrue(personInfo.getData() instanceof Map);
+            }
+            {
+                Type[] createGenericPersonInfos = 
ReflectUtils.getReturnTypes(PojoUtilsTest.class.getDeclaredMethod("createAGenericLoop",
 String.class));
+                Ageneric personInfo = (Ageneric) PojoUtils.realize(o, 
(Class)createGenericPersonInfos[0], createGenericPersonInfos[1]);
+
+                assertEquals(Ageneric.NAME, personInfo.getName());
+                assertEquals(personInfo.getData().getClass(), Ageneric.class);
+                assertEquals(Ageneric.NAME, 
((Ageneric)personInfo.getData()).getName());
+                
assertEquals(((Ageneric)personInfo.getData()).getData().getClass(), 
PersonInfo.class);
+                assertEquals(personName, 
((PersonInfo)((Ageneric)personInfo.getData()).getData()).getName());
+            }
+        }
+        {
+
+            Bgeneric<Ageneric<PersonInfo>> generic = 
createBGenericWithAgeneric(personName);
+            Object o = JSON.toJSON(generic);
+            {
+                Ageneric personInfo = (Ageneric) PojoUtils.realize(o, 
Ageneric.class);
+
+                assertEquals(Bgeneric.NAME, personInfo.getName());
+                assertTrue(personInfo.getData() instanceof Map);
+            }
+            {
+                Type[] createGenericPersonInfos = 
ReflectUtils.getReturnTypes(PojoUtilsTest.class.getDeclaredMethod("createBGenericWithAgeneric",
 String.class));
+                Bgeneric personInfo = (Bgeneric) PojoUtils.realize(o, 
(Class)createGenericPersonInfos[0], createGenericPersonInfos[1]);
+
+                assertEquals(Bgeneric.NAME, personInfo.getName());
+                assertEquals(personInfo.getData().getClass(), Ageneric.class);
+                assertEquals(Ageneric.NAME, 
((Ageneric)personInfo.getData()).getName());
+                
assertEquals(((Ageneric)personInfo.getData()).getData().getClass(), 
PersonInfo.class);
+                assertEquals(personName, 
((PersonInfo)((Ageneric)personInfo.getData()).getData()).getName());
+            }
+        }
+    }
+
+    protected Cgeneric<PersonInfo> createCGenericPersonInfo(String name) {
+        Cgeneric<PersonInfo> ret = new Cgeneric();
+        ret.setData(createPersonInfoByName(name));
+        ret.setA(createAGenericPersonInfo(name));
+        ret.setB(createBGenericPersonInfo(name));
+        return ret;
+    }
+
+    @Test
+    public void testPojoGeneric3() throws NoSuchMethodException {
+        String personName = "testName";
+
+        Cgeneric<PersonInfo> generic = createCGenericPersonInfo(personName);
+        Object o = JSON.toJSON(generic);
+        {
+            Cgeneric personInfo = (Cgeneric) PojoUtils.realize(o, 
Cgeneric.class);
+
+            assertEquals(Cgeneric.NAME, personInfo.getName());
+            assertTrue(personInfo.getData() instanceof Map);
+            assertTrue(personInfo.getA().getData() instanceof Map);
+            assertTrue(personInfo.getB().getData() instanceof PersonInfo);
+
+        }
+        {
+            Type[] createGenericPersonInfos = 
ReflectUtils.getReturnTypes(PojoUtilsTest.class.getDeclaredMethod("createCGenericPersonInfo",
 String.class));
+            Cgeneric personInfo = (Cgeneric) PojoUtils.realize(o, 
(Class)createGenericPersonInfos[0], createGenericPersonInfos[1]);
+
+            assertEquals(Cgeneric.NAME, personInfo.getName());
+            assertEquals(personInfo.getData().getClass(), PersonInfo.class);
+            assertEquals(personName, 
((PersonInfo)personInfo.getData()).getName());
+
+            assertEquals(personInfo.getA().getClass(), Ageneric.class);
+            assertEquals(personInfo.getA().getData().getClass(), 
PersonInfo.class);
+            assertEquals(personInfo.getB().getClass(), Bgeneric.class);
+            assertEquals(personInfo.getB().getData().getClass(), 
PersonInfo.class);
+        }
+    }
+
+    protected Dgeneric<Ageneric<PersonInfo>, Bgeneric<PersonInfo>, 
Cgeneric<PersonInfo>> createDGenericPersonInfo(String name) {
+        Dgeneric<Ageneric<PersonInfo>, Bgeneric<PersonInfo>, 
Cgeneric<PersonInfo>> ret = new Dgeneric();
+        ret.setT(createAGenericPersonInfo(name));
+        ret.setY(createBGenericPersonInfo(name));
+        ret.setZ(createCGenericPersonInfo(name));
+        return ret;
+    }
+
+    @Test
+    public void testPojoGeneric4() throws NoSuchMethodException {
+        String personName = "testName";
+
+        Dgeneric generic = createDGenericPersonInfo(personName);
+        Object o = JSON.toJSON(generic);
+        {
+            Dgeneric personInfo = (Dgeneric) PojoUtils.realize(o, 
Dgeneric.class);
+
+            assertEquals(Dgeneric.NAME, personInfo.getName());
+            assertTrue(personInfo.getT() instanceof Map);
+            assertTrue(personInfo.getY() instanceof Map);
+            assertTrue(personInfo.getZ() instanceof Map);
+        }
+        {
+            Type[] createGenericPersonInfos = 
ReflectUtils.getReturnTypes(PojoUtilsTest.class.getDeclaredMethod("createDGenericPersonInfo",
 String.class));
+            Dgeneric personInfo = (Dgeneric) PojoUtils.realize(o, 
(Class)createGenericPersonInfos[0], createGenericPersonInfos[1]);
+
+            assertEquals(Dgeneric.NAME, personInfo.getName());
+
+            assertEquals(personInfo.getT().getClass(), Ageneric.class);
+            assertEquals(((Ageneric)personInfo.getT()).getData().getClass(), 
PersonInfo.class);
+            assertEquals(personInfo.getY().getClass(), Bgeneric.class);
+            assertEquals(((Bgeneric)personInfo.getY()).getData().getClass(), 
PersonInfo.class);
+            assertEquals(personInfo.getZ().getClass(), Cgeneric.class);
+            assertEquals(((Cgeneric)personInfo.getZ()).getData().getClass(), 
PersonInfo.class);
+
+            assertEquals(personInfo.getZ().getClass(), Cgeneric.class);
+            assertEquals(((Cgeneric)personInfo.getZ()).getA().getClass(), 
Ageneric.class);
+            
assertEquals(((Cgeneric)personInfo.getZ()).getA().getData().getClass(), 
PersonInfo.class);
+            assertEquals(((Cgeneric)personInfo.getZ()).getB().getClass(), 
Bgeneric.class);
+            
assertEquals(((Cgeneric)personInfo.getZ()).getB().getData().getClass(), 
PersonInfo.class);
+        }
+    }
+
     public enum Day {
         SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
     }

Reply via email to