Revision: 9482
Author: b...@google.com
Date: Thu Dec 23 07:05:27 2010
Log: Ensure that enum types reachable through AutoBean method parameterizations are included in the EnumMap.
Patch by: bobv
Review by: jbrosenberg

Review at http://gwt-code-reviews.appspot.com/1240801

http://code.google.com/p/google-web-toolkit/source/detail?r=9482

Modified:
/trunk/user/src/com/google/gwt/autobean/rebind/model/AutoBeanFactoryModel.java
 /trunk/user/src/com/google/gwt/autobean/rebind/model/AutoBeanMethod.java
 /trunk/user/test/com/google/gwt/autobean/shared/AutoBeanCodexTest.java

=======================================
--- /trunk/user/src/com/google/gwt/autobean/rebind/model/AutoBeanFactoryModel.java Wed Nov 10 11:04:47 2010 +++ /trunk/user/src/com/google/gwt/autobean/rebind/model/AutoBeanFactoryModel.java Thu Dec 23 07:05:27 2010
@@ -249,7 +249,7 @@
       AutoBeanMethod toAdd = builder.build();

       // Collect referenced enums
-      if (toAdd.isEnum()) {
+      if (toAdd.hasEnumMap()) {
         allEnumConstants.putAll(toAdd.getEnumMap());
       }

=======================================
--- /trunk/user/src/com/google/gwt/autobean/rebind/model/AutoBeanMethod.java Wed Nov 10 11:04:47 2010 +++ /trunk/user/src/com/google/gwt/autobean/rebind/model/AutoBeanMethod.java Thu Dec 23 07:05:27 2010
@@ -21,6 +21,7 @@
 import com.google.gwt.core.ext.typeinfo.JEnumType;
 import com.google.gwt.core.ext.typeinfo.JMethod;
 import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
+import com.google.gwt.core.ext.typeinfo.JType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.editor.rebind.model.ModelUtils;

@@ -158,40 +159,29 @@
       toReturn.method = method;
       TypeOracle oracle = method.getEnclosingType().getOracle();

-      toReturn.isValueType = ModelUtils.isValueType(oracle,
-          method.getReturnType());
+      JType returnType = method.getReturnType();
+      toReturn.isValueType = ModelUtils.isValueType(oracle, returnType);

       if (!toReturn.isValueType) {
         // See if it's a collection or a map
- JClassType returnClass = method.getReturnType().isClassOrInterface();
+        JClassType returnClass = returnType.isClassOrInterface();
JClassType collectionInterface = oracle.findType(Collection.class.getCanonicalName()); JClassType mapInterface = oracle.findType(Map.class.getCanonicalName());
         if (collectionInterface.isAssignableFrom(returnClass)) {
JClassType[] parameterizations = ModelUtils.findParameterizationOf(
               collectionInterface, returnClass);
           toReturn.elementType = parameterizations[0];
+          maybeProcessEnumType(toReturn.elementType);
         } else if (mapInterface.isAssignableFrom(returnClass)) {
JClassType[] parameterizations = ModelUtils.findParameterizationOf(
               mapInterface, returnClass);
           toReturn.keyType = parameterizations[0];
           toReturn.valueType = parameterizations[1];
-        }
-      }
-
-      JEnumType enumType = method.getReturnType().isEnum();
-      if (enumType != null) {
- Map<JEnumConstant, String> map = new LinkedHashMap<JEnumConstant, String>();
-        for (JEnumConstant e : enumType.getEnumConstants()) {
-          String name;
-          PropertyName annotation = e.getAnnotation(PropertyName.class);
-          if (annotation == null) {
-            name = e.getName();
-          } else {
-            name = annotation.value();
-          }
-          map.put(e, name);
-        }
-        toReturn.enumMap = map;
+          maybeProcessEnumType(toReturn.keyType);
+          maybeProcessEnumType(toReturn.valueType);
+        }
+      } else {
+        maybeProcessEnumType(returnType);
       }
     }

@@ -202,6 +192,39 @@
     public void setStaticImp(JMethod staticImpl) {
       toReturn.staticImpl = staticImpl;
     }
+
+    /**
+     * Call {...@link #processEnumType(JEnumType)} if {...@code type} is a
+     * {...@link JEnumType}.
+     */
+    private void maybeProcessEnumType(JType type) {
+      assert type != null : "type == null";
+      JEnumType enumType = type.isEnum();
+      if (enumType != null) {
+        processEnumType(enumType);
+      }
+    }
+
+    /**
+     * Adds a JEnumType to the AutoBeanMethod's enumMap so that the
+ * AutoBeanFactoryGenerator can embed extra metadata about the enum values.
+     */
+    private void processEnumType(JEnumType enumType) {
+      Map<JEnumConstant, String> map = toReturn.enumMap;
+      if (map == null) {
+ map = toReturn.enumMap = new LinkedHashMap<JEnumConstant, String>();
+      }
+      for (JEnumConstant e : enumType.getEnumConstants()) {
+        String name;
+        PropertyName annotation = e.getAnnotation(PropertyName.class);
+        if (annotation == null) {
+          name = e.getName();
+        } else {
+          name = annotation.value();
+        }
+        map.put(e, name);
+      }
+    }
   }

   private Action action;
@@ -255,12 +278,12 @@
     return valueType;
   }

-  public boolean isCollection() {
-    return elementType != null;
+  public boolean hasEnumMap() {
+    return enumMap != null;
   }

-  public boolean isEnum() {
-    return enumMap != null;
+  public boolean isCollection() {
+    return elementType != null;
   }

   public boolean isMap() {
=======================================
--- /trunk/user/test/com/google/gwt/autobean/shared/AutoBeanCodexTest.java Wed Nov 24 12:33:58 2010 +++ /trunk/user/test/com/google/gwt/autobean/shared/AutoBeanCodexTest.java Thu Dec 23 07:05:27 2010
@@ -48,6 +48,22 @@

     AutoBean<Simple> simple();
   }
+
+  /*
+ * These enums are used to verify that a List<Enum> or Map<Enum, Enum> pulls
+   * in the necessary metadata.
+   */
+  enum EnumReachableThroughList {
+    FOO_LIST
+  }
+
+  enum EnumReachableThroughMapKey {
+    FOO_KEY
+  }
+
+  enum EnumReachableThroughMapValue {
+    FOO_VALUE
+  }

   interface HasAutoBean {
     Splittable getSimple();
@@ -79,6 +95,10 @@

     Map<MyEnum, Integer> getMap();

+    List<EnumReachableThroughList> getParameterizedList();
+
+ Map<EnumReachableThroughMapKey, EnumReachableThroughMapValue> getParameterizedMap();
+
     void setEnum(MyEnum value);

     void setEnums(List<MyEnum> value);
@@ -156,13 +176,6 @@
     assertNotNull(decodedBean.as().getList());
     assertTrue(decodedBean.as().getList().isEmpty());
   }
-
-  private <T> AutoBean<T> checkEncode(AutoBean<T> bean) {
-    Splittable split = AutoBeanCodex.encode(bean);
-    AutoBean<T> decoded = AutoBeanCodex.decode(f, bean.getType(), split);
-    assertTrue(AutoBeanUtils.deepEquals(bean, decoded));
-    return decoded;
-  }

   public void testEnum() {
     EnumMap map = (EnumMap) f;
@@ -191,6 +204,24 @@
     assertEquals(arrayValue, decoded.as().getEnums());
     assertEquals(mapValue, decoded.as().getMap());
   }
+
+  /**
+   * Ensures that enum types that are reachable only through a method
+   * parameterization are included in the enum map.
+   */
+  public void testEnumReachableOnlyThroughParameterization() {
+    EnumMap map = (EnumMap) f;
+ assertEquals("FOO_LIST", map.getToken(EnumReachableThroughList.FOO_LIST)); + assertEquals("FOO_KEY", map.getToken(EnumReachableThroughMapKey.FOO_KEY));
+    assertEquals("FOO_VALUE",
+        map.getToken(EnumReachableThroughMapValue.FOO_VALUE));
+    assertEquals(EnumReachableThroughList.FOO_LIST,
+        map.getEnum(EnumReachableThroughList.class, "FOO_LIST"));
+    assertEquals(EnumReachableThroughMapKey.FOO_KEY,
+        map.getEnum(EnumReachableThroughMapKey.class, "FOO_KEY"));
+    assertEquals(EnumReachableThroughMapValue.FOO_VALUE,
+        map.getEnum(EnumReachableThroughMapValue.class, "FOO_VALUE"));
+  }

   public void testMap() {
     AutoBean<HasMap> bean = f.hasMap();
@@ -291,4 +322,11 @@
   protected void gwtSetUp() throws Exception {
     f = GWT.create(Factory.class);
   }
-}
+
+  private <T> AutoBean<T> checkEncode(AutoBean<T> bean) {
+    Splittable split = AutoBeanCodex.encode(bean);
+    AutoBean<T> decoded = AutoBeanCodex.decode(f, bean.getType(), split);
+    assertTrue(AutoBeanUtils.deepEquals(bean, decoded));
+    return decoded;
+  }
+}

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to