Revision: 9339
Author: [email protected]
Date: Thu Dec  2 08:37:28 2010
Log: Support upcasting Date, BigInteger, and BigDecimal types.

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

Added:
 /releases/2.1/user/src/com/google/gwt/autobean/shared/ValueCodexHelper.java
/releases/2.1/user/super/com/google/gwt/autobean/super/com/google/gwt/autobean/shared/ValueCodexHelper.java
Modified:
 /releases/2.1/tools/api-checker/config/gwt20_21userApi.conf
 /releases/2.1/tools/api-checker/config/gwt21_22userApi.conf
 /releases/2.1/user/src/com/google/gwt/autobean/shared/AutoBeanCodex.java
 /releases/2.1/user/src/com/google/gwt/autobean/shared/ValueCodex.java
 /releases/2.1/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java
/releases/2.1/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java /releases/2.1/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java /releases/2.1/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
 /releases/2.1/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
/releases/2.1/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java

=======================================
--- /dev/null
+++ /releases/2.1/user/src/com/google/gwt/autobean/shared/ValueCodexHelper.java Thu Dec 2 08:37:28 2010
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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.google.gwt.autobean.shared;
+
+import com.google.gwt.core.client.GWT;
+
+/**
+ * Provides reflection-based operation for server (JVM) implementation. There is
+ * a no-op super-source version for client (dev- and web-mode) code.
+ */
+class ValueCodexHelper {
+  /**
+ * Returns {...@code true} if {...@code clazz} is assignable to any of the value
+   * types.
+   */
+  static boolean canDecode(Class<?> clazz) {
+    assert !GWT.isClient();
+    for (Class<?> valueType : ValueCodex.getAllValueTypes()) {
+      if (valueType.isAssignableFrom(clazz)) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
=======================================
--- /dev/null
+++ /releases/2.1/user/super/com/google/gwt/autobean/super/com/google/gwt/autobean/shared/ValueCodexHelper.java Thu Dec 2 08:37:28 2010
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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.google.gwt.autobean.shared;
+
+/**
+ * A no-op super-source version of ValueCodexHelper for web-mode compilations.
+ */
+class ValueCodexHelper {
+  /**
+   * Returns {...@code false}.
+   */
+  static boolean canDecode(Class<?> clazz) {
+    return false;
+  }
+}
=======================================
--- /releases/2.1/tools/api-checker/config/gwt20_21userApi.conf Wed Nov 24 06:41:26 2010 +++ /releases/2.1/tools/api-checker/config/gwt20_21userApi.conf Thu Dec 2 08:37:28 2010
@@ -66,6 +66,7 @@
 :**/server/**\
 :**/tools/**\
 :user/src/com/google/gwt/regexp/shared/**\
+:user/src/com/google/gwt/autobean/shared/ValueCodexHelper.java\
 :user/src/com/google/gwt/autobean/shared/impl/StringQuoter.java\
 :user/src/com/google/gwt/core/client/impl/WeakMapping.java\
 :user/src/com/google/gwt/junit/*.java\
=======================================
--- /releases/2.1/tools/api-checker/config/gwt21_22userApi.conf Wed Dec 1 07:51:56 2010 +++ /releases/2.1/tools/api-checker/config/gwt21_22userApi.conf Thu Dec 2 08:37:28 2010
@@ -73,6 +73,7 @@
 :**/server/**\
 :**/tools/**\
 :user/src/com/google/gwt/regexp/shared/**\
+:user/src/com/google/gwt/autobean/shared/ValueCodexHelper.java\
 :user/src/com/google/gwt/autobean/shared/impl/StringQuoter.java\
 :user/src/com/google/gwt/core/client/impl/WeakMapping.java\
 :user/src/com/google/gwt/junit/*.java\
=======================================
--- /releases/2.1/user/src/com/google/gwt/autobean/shared/AutoBeanCodex.java Wed Nov 24 06:41:26 2010 +++ /releases/2.1/user/src/com/google/gwt/autobean/shared/AutoBeanCodex.java Thu Dec 2 08:37:28 2010
@@ -295,7 +295,8 @@

       if (ValueCodex.canDecode(ctx.getElementType())) {
         for (Object element : collection) {
-          sb.append(",").append(encodeValue(element).getPayload());
+          sb.append(",").append(
+              encodeValue(ctx.getElementType(), element).getPayload());
         }
       } else {
         boolean isEncoded = Splittable.class.equals(ctx.getElementType());
@@ -330,15 +331,18 @@
         return false;
       }

-      boolean isEncodedKey = Splittable.class.equals(ctx.getKeyType());
-      boolean isEncodedValue = Splittable.class.equals(ctx.getValueType());
-      boolean isValueKey = ValueCodex.canDecode(ctx.getKeyType());
-      boolean isValueValue = ValueCodex.canDecode(ctx.getValueType());
+      Class<?> keyType = ctx.getKeyType();
+      Class<?> valueType = ctx.getValueType();
+      boolean isEncodedKey = Splittable.class.equals(keyType);
+      boolean isEncodedValue = Splittable.class.equals(valueType);
+      boolean isValueKey = ValueCodex.canDecode(keyType);
+      boolean isValueValue = ValueCodex.canDecode(valueType);

       if (isValueKey) {
-        writeValueKeyMap(map, isEncodedValue, isValueValue);
+ writeValueKeyMap(map, keyType, valueType, isEncodedValue, isValueValue);
       } else {
-        writeObjectKeyMap(map, isEncodedKey, isEncodedValue, isValueValue);
+        writeObjectKeyMap(map, valueType, isEncodedKey, isEncodedValue,
+            isValueValue);
       }

       return false;
@@ -377,7 +381,7 @@

       // Special handling for enums if we have an obfuscation map
       Splittable split;
-      split = encodeValue(value);
+      split = encodeValue(type, value);
       sb.append(",\"").append(propertyName).append("\":").append(
           split.getPayload());
       return false;
@@ -409,12 +413,13 @@
* Encodes a value, with special handling for enums to allow the field name
      * to be overridden.
      */
-    private Splittable encodeValue(Object value) {
+    private Splittable encodeValue(Class<?> expectedType, Object value) {
       Splittable split;
       if (value instanceof Enum<?> && enumMap != null) {
-        split = ValueCodex.encode(enumMap.getToken((Enum<?>) value));
+        split = ValueCodex.encode(String.class,
+            enumMap.getToken((Enum<?>) value));
       } else {
-        split = ValueCodex.encode(value);
+        split = ValueCodex.encode(expectedType, value);
       }
       return split;
     }
@@ -429,8 +434,8 @@
* encoded as a list of two lists, since it's possible that two distinct
      * objects have the same encoded form.
      */
-    private void writeObjectKeyMap(Map<?, ?> map, boolean isEncodedKey,
-        boolean isEncodedValue, boolean isValueValue) {
+    private void writeObjectKeyMap(Map<?, ?> map, Class<?> valueType,
+ boolean isEncodedKey, boolean isEncodedValue, boolean isValueValue) {
       StringBuilder keys = new StringBuilder();
       StringBuilder values = new StringBuilder();

@@ -445,7 +450,8 @@
           values.append(",").append(
               ((Splittable) entry.getValue()).getPayload());
         } else if (isValueValue) {
- values.append(",").append(encodeValue(entry.getValue()).getPayload());
+          values.append(",").append(
+              encodeValue(valueType, entry.getValue()).getPayload());
         } else {
           encodeToStringBuilder(values.append(","), entry.getValue());
         }
@@ -462,15 +468,15 @@
     /**
      * Writes a map JSON literal where the keys are value types.
      */
-    private void writeValueKeyMap(Map<?, ?> map, boolean isEncodedValue,
-        boolean isValueValue) {
+    private void writeValueKeyMap(Map<?, ?> map, Class<?> keyType,
+        Class<?> valueType, boolean isEncodedValue, boolean isValueValue) {
       for (Map.Entry<?, ?> entry : map.entrySet()) {
- sb.append(",").append(encodeValue(entry.getKey()).getPayload()).append( + sb.append(",").append(encodeValue(keyType, entry.getKey()).getPayload()).append(
             ":");
         if (isEncodedValue) {
           sb.append(((Splittable) entry.getValue()).getPayload());
         } else if (isValueValue) {
-          sb.append(encodeValue(entry.getValue()).getPayload());
+          sb.append(encodeValue(valueType, entry.getValue()).getPayload());
         } else {
           encodeToStringBuilder(sb, entry.getValue());
         }
=======================================
--- /releases/2.1/user/src/com/google/gwt/autobean/shared/ValueCodex.java Tue Nov 30 10:36:06 2010 +++ /releases/2.1/user/src/com/google/gwt/autobean/shared/ValueCodex.java Thu Dec 2 08:37:28 2010
@@ -20,9 +20,11 @@

 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;

 /**
  * Provides unified encoding and decoding of value objects.
@@ -30,6 +32,11 @@
 public class ValueCodex {
   enum Type {
     BIG_DECIMAL(BigDecimal.class) {
+      @Override
+      public boolean canUpcast(Object value) {
+        return value instanceof BigDecimal;
+      }
+
       @Override
       public BigDecimal decode(Class<?> clazz, String value) {
         return new BigDecimal(value);
@@ -41,6 +48,11 @@
       }
     },
     BIG_INTEGER(BigInteger.class) {
+      @Override
+      public boolean canUpcast(Object value) {
+        return value instanceof BigInteger;
+      }
+
       @Override
       public BigInteger decode(Class<?> clazz, String value) {
         return new BigInteger(value);
@@ -70,6 +82,11 @@
       }
     },
     DATE(Date.class) {
+      @Override
+      public boolean canUpcast(Object value) {
+        return value instanceof Date;
+      }
+
       @Override
       public Date decode(Class<?> clazz, String value) {
         return new Date(Long.valueOf(value));
@@ -157,6 +174,15 @@
       this.primitiveType = primitiveType;
       this.defaultValue = defaultValue;
     }
+
+    /**
+     * Determines whether or not the Type can handle the given value via
+     * upcasting semantics.
+     */
+    public boolean canUpcast(Object value) {
+      // Most value types are final, so this method is meaningless
+      return false;
+    }

     public abstract Object decode(Class<?> clazz, String value);

@@ -177,14 +203,18 @@
     }
   }

- private static Map<Class<?>, Type> typesByClass = new HashMap<Class<?>, Type>();
+  private static final Set<Class<?>> ALL_VALUE_TYPES;
+  private static final Map<Class<?>, Type> TYPES_BY_CLASS;
   static {
+    Map<Class<?>, Type> temp = new HashMap<Class<?>, Type>();
     for (Type t : Type.values()) {
-      typesByClass.put(t.getType(), t);
+      temp.put(t.getType(), t);
       if (t.getPrimitiveType() != null) {
-        typesByClass.put(t.getPrimitiveType(), t);
+        temp.put(t.getPrimitiveType(), t);
       }
     }
+    ALL_VALUE_TYPES = Collections.unmodifiableSet(temp.keySet());
+    TYPES_BY_CLASS = Collections.unmodifiableMap(temp);
   }

   /**
@@ -194,7 +224,11 @@
    * @return {...@code true} if the given object type can be decoded
    */
   public static boolean canDecode(Class<?> clazz) {
-    return findType(clazz) != null;
+    if (findType(clazz) != null) {
+      return true;
+    }
+    // Use other platform-specific tests
+    return ValueCodexHelper.canDecode(clazz);
   }

   public static <T> T decode(Class<T> clazz, Splittable split) {
@@ -211,13 +245,43 @@
     }
     return (T) getTypeOrDie(clazz).decode(clazz, string);
   }
+
+  /**
+   * Encode a value object when the wire format type is known. This method
+   * should be preferred over {...@link #encode(Object)} when possible.
+   */
+  public static Splittable encode(Class<?> clazz, Object obj) {
+    if (obj == null) {
+      return LazySplittable.NULL;
+    }
+    return new LazySplittable(getTypeOrDie(clazz).toJsonExpression(obj));
+  }

   public static Splittable encode(Object obj) {
     if (obj == null) {
       return LazySplittable.NULL;
     }
-    return new LazySplittable(
-        getTypeOrDie(obj.getClass()).toJsonExpression(obj));
+    Type t = findType(obj.getClass());
+    // Try upcasting
+    if (t == null) {
+      for (Type maybe : Type.values()) {
+        if (maybe.canUpcast(obj)) {
+          t = maybe;
+          break;
+        }
+      }
+    }
+    if (t == null) {
+      throw new UnsupportedOperationException(obj.getClass().getName());
+    }
+    return new LazySplittable(t.toJsonExpression(obj));
+  }
+
+  /**
+   * Return all Value types that can be processed by the ValueCodex.
+   */
+  public static Set<Class<?>> getAllValueTypes() {
+    return ALL_VALUE_TYPES;
   }

   /**
@@ -235,13 +299,10 @@
    * May return <code>null</code>.
    */
   private static <T> Type findType(Class<T> clazz) {
-    Type type = typesByClass.get(clazz);
-    if (type == null) {
-      if (clazz.isEnum()) {
-        return Type.ENUM;
-      }
-    }
-    return type;
+    if (clazz.isEnum()) {
+      return Type.ENUM;
+    }
+    return TYPES_BY_CLASS.get(clazz);
   }

   private static <T> Type getTypeOrDie(Class<T> clazz) {
=======================================
--- /releases/2.1/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java Wed Nov 24 06:41:26 2010 +++ /releases/2.1/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java Thu Dec 2 08:37:28 2010
@@ -15,15 +15,14 @@
  */
 package com.google.gwt.editor.rebind.model;

+import com.google.gwt.autobean.shared.ValueCodex;
 import com.google.gwt.core.ext.typeinfo.JArrayType;
 import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.JParameterizedType;
 import com.google.gwt.core.ext.typeinfo.JType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;

-import java.util.Arrays;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.Set;

@@ -32,16 +31,12 @@
  */
 public class ModelUtils {

-  @SuppressWarnings("unchecked")
- static final Set<Class<?>> VALUE_TYPES = Collections.unmodifiableSet(new HashSet<Class<?>>( - Arrays.asList(Boolean.class, Character.class, Class.class, Date.class,
-          Enum.class, Number.class, String.class, Void.class)));
-
   static final Set<String> VALUE_TYPE_NAMES;

   static {
-    Set<String> names = new HashSet<String>(VALUE_TYPES.size());
-    for (Class<?> clazz : VALUE_TYPES) {
+    Set<Class<?>> valueTypes = ValueCodex.getAllValueTypes();
+    Set<String> names = new HashSet<String>(valueTypes.size());
+    for (Class<?> clazz : valueTypes) {
       names.add(clazz.getName());
     }
     VALUE_TYPE_NAMES = Collections.unmodifiableSet(names);
@@ -110,11 +105,14 @@
     if (classType == null) {
       return true;
     }
+    if (type.isEnum() != null) {
+      return true;
+    }

     for (String valueType : VALUE_TYPE_NAMES) {
       JClassType found = oracle.findType(valueType);
       // null check to accommodate limited mock CompilationStates
-      if (found != null && found.isAssignableFrom(classType)) {
+      if (found != null && found.equals(classType)) {
         return true;
       }
     }
=======================================
--- /releases/2.1/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java Tue Nov 30 13:01:46 2010 +++ /releases/2.1/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java Thu Dec 2 03:55:49 2010
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.requestfactory.server;

+import com.google.gwt.autobean.shared.ValueCodex;
 import com.google.gwt.dev.asm.AnnotationVisitor;
 import com.google.gwt.dev.asm.ClassReader;
 import com.google.gwt.dev.asm.ClassVisitor;
@@ -44,9 +45,7 @@
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -517,10 +516,7 @@
     }
   }

-  @SuppressWarnings("unchecked")
- static final Set<Class<?>> VALUE_TYPES = Collections.unmodifiableSet(new HashSet<Class<?>>( - Arrays.asList(Boolean.class, Character.class, Class.class, Date.class,
-          Enum.class, Number.class, String.class, Void.class)));
+  static final Set<Class<?>> VALUE_TYPES = ValueCodex.getAllValueTypes();

   public static void main(String[] args) {
     if (args.length == 0) {
@@ -578,6 +574,10 @@
    */
   private final Type entityProxyIntf = Type.getType(EntityProxy.class);
   /**
+   * The type {...@link Enum}.
+   */
+  private final Type enumType = Type.getType(Enum.class);
+  /**
* A placeholder type for client types that could not be resolved to a domain
    * type.
    */
@@ -1361,12 +1361,8 @@
       return true;
     }
     logger = logger.setType(type);
-    List<Type> types = getSupertypes(logger, type);
-    for (Type t : types) {
-      if (valueTypes.contains(t)) {
-        valueTypes.add(type);
-        return true;
-      }
+    if (isAssignable(logger, enumType, type)) {
+      return true;
     }
     return false;
   }
=======================================
--- /releases/2.1/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java Wed Nov 24 12:53:58 2010 +++ /releases/2.1/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java Thu Dec 2 03:55:49 2010
@@ -434,7 +434,10 @@
             if (properties.containsKey(propertyName)) {
               Splittable raw = properties.get(propertyName);
               Object decoded = ValueCodex.decode(ctx.getType(), raw);
- // Hack for Date, consider generalizing for "custom serializers"
+              /*
+               * Hack for Date subtypes, consider generalizing for
+               * "custom serializers"
+               */
               if (decoded != null && Date.class.equals(ctx.getType())) {
                 decoded = new DatePoser((Date) decoded);
               }
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java Tue Nov 30 18:03:50 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java Thu Dec 2 03:55:49 2010
@@ -32,11 +32,16 @@
 import com.google.gwt.requestfactory.shared.Violation;
 import com.google.gwt.requestfactory.shared.impl.SimpleEntityProxyId;

+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Time;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;

@@ -1801,20 +1806,71 @@
     });
   }

-  public void testPrimitiveListDateAsParameter() {
+  public void testPrimitiveListBigDecimalAsParameter() {
     delayTestFinish(DELAY_TEST_FINISH);

-    @SuppressWarnings("deprecation")
-    final Date date = new Date(90, 0, 1);
-    Request<Date> procReq = simpleFooRequest().processDateList(
-        Arrays.asList(date));
-    procReq.fire(new Receiver<Date>() {
-      @Override
-      public void onSuccess(Date response) {
-        assertEquals(date, response);
-        finishTestAndReset();
-      }
+    // Keep these values in sync with SimpleFoo.processBigIntegerList
+    final List<BigDecimal> testList = new ArrayList<BigDecimal>();
+    testList.add(BigDecimal.TEN);
+    testList.add(new BigDecimal("12345.6789") {
+      // This is an anonymous subtype
     });
+    simpleFooRequest().processBigDecimalList(testList).fire(
+        new Receiver<List<BigDecimal>>() {
+          @Override
+          public void onSuccess(List<BigDecimal> response) {
+            // Check upcasted values only
+            assertEquals(testList, response);
+            finishTestAndReset();
+          }
+        });
+  }
+
+  public void testPrimitiveListBigIntegerAsParameter() {
+    delayTestFinish(DELAY_TEST_FINISH);
+
+    // Keep these values in sync with SimpleFoo.processBigIntegerList
+    final List<BigInteger> testList = new ArrayList<BigInteger>();
+    testList.add(BigInteger.TEN);
+    testList.add(new BigInteger("12345") {
+      // This is an anonymous subtype
+    });
+    simpleFooRequest().processBigIntegerList(testList).fire(
+        new Receiver<List<BigInteger>>() {
+          @Override
+          public void onSuccess(List<BigInteger> response) {
+            // Check upcasted values only
+            assertEquals(testList, response);
+            finishTestAndReset();
+          }
+        });
+  }
+
+  @SuppressWarnings("deprecation")
+  public void testPrimitiveListDateAsParameter() {
+    delayTestFinish(DELAY_TEST_FINISH);
+
+    // Keep these values in sync with SimpleFoo.processDateList
+    Date date = new Date(90, 0, 1);
+    java.sql.Date sqlDate = new java.sql.Date(90, 0, 2);
+    Time sqlTime = new Time(1, 2, 3);
+    Timestamp sqlTimestamp = new Timestamp(12345L);
+    final List<Date> testList = Arrays.asList(date, sqlDate, sqlTime,
+        sqlTimestamp);
+    simpleFooRequest().processDateList(testList).fire(
+        new Receiver<List<Date>>() {
+          @Override
+          public void onSuccess(List<Date> response) {
+            // Check upcasted values only
+            assertEquals(testList.size(), response.size());
+            Iterator<Date> expected = testList.iterator();
+            Iterator<Date> actual = response.iterator();
+            while (expected.hasNext()) {
+ assertEquals(expected.next().getTime(), actual.next().getTime());
+            }
+            finishTestAndReset();
+          }
+        });
   }

   public void testPrimitiveListEnumAsParameter() {
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java Tue Nov 30 13:01:46 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java Thu Dec 2 03:55:49 2010
@@ -87,6 +87,10 @@
     int foo(int a) {
       return 0;
     }
+
+    java.sql.Date getSqlDate() {
+      return null;
+    }
   }

   @ProxyFor(Domain.class)
@@ -111,10 +115,16 @@
       return 0;
     }
   }
+
   @ProxyFor(DomainWithOverloads.class)
   interface DomainWithOverloadsProxy extends EntityProxy {
     void foo();
   }
+
+  @ProxyFor(Domain.class)
+  interface DomainWithSqlDateProxy extends EntityProxy {
+    java.sql.Date getSqlDate();
+  }

   class Foo {
   }
@@ -268,6 +278,14 @@
v.validateRequestContext(RequestContextMissingAnnotation.class.getName());
     assertTrue(v.isPoisoned());
   };
+
+  /**
+   * Test that subclasses of {...@code java.util.Date} are not transportable.
+   */
+  public void testDateSubclass() {
+    v.validateEntityProxy(DomainWithSqlDateProxy.class.getName());
+    assertTrue(v.isPoisoned());
+  }

   /**
    * Test the {...@link FindRequest} context used to implement find().
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java Wed Nov 24 06:41:26 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java Thu Dec 2 03:55:49 2010
@@ -19,11 +19,14 @@

 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.sql.Time;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -156,13 +159,73 @@
     foo.setUnpersisted(true);
     return foo;
   }
+
+  /**
+ * Check client-side upcasting to BigDecimal and return a list of BigDecimals
+   * that should be upcast.
+   */
+ public static List<BigDecimal> processBigDecimalList(List<BigDecimal> values) {
+    List<BigDecimal> toReturn = new ArrayList<BigDecimal>();
+    toReturn.add(BigDecimal.TEN);
+    toReturn.add(new BigDecimal("12345.6789") {
+      // This is an anonymous subtype
+    });
+    if (!toReturn.equals(values)) {
+      throw new IllegalArgumentException(toReturn + " != " + values);
+    }
+    return toReturn;
+  }
+
+  /**
+ * Check client-side upcasting to BigInteger and return a list of BigIntegers
+   * that should be upcast.
+   */
+ public static List<BigInteger> processBigIntegerList(List<BigInteger> values) {
+    List<BigInteger> toReturn = new ArrayList<BigInteger>();
+    toReturn.add(BigInteger.TEN);
+    toReturn.add(new BigInteger("12345") {
+      // This is an anonymous subtype
+    });
+    if (!toReturn.equals(values)) {
+      throw new IllegalArgumentException(toReturn + " != " + values);
+    }
+    return toReturn;
+  }

   public static Boolean processBooleanList(List<Boolean> values) {
     return values.get(0);
   }

-  public static Date processDateList(List<Date> values) {
-    return values.get(0);
+  /**
+ * Check client-side upcasting to Date and return a list of Dates that should
+   * be upcast.
+   */
+  @SuppressWarnings("deprecation")
+  public static List<Date> processDateList(List<Date> values) {
+    // Keep these values in sync with SimpleFoo.processDateList
+    Date date = new Date(90, 0, 1);
+    java.sql.Date sqlDate = new java.sql.Date(90, 0, 2);
+    Time sqlTime = new Time(1, 2, 3);
+    Timestamp sqlTimestamp = new Timestamp(12345L);
+ List<Date> toReturn = Arrays.asList(date, sqlDate, sqlTime, sqlTimestamp);
+
+    if (toReturn.size() != values.size()) {
+      throw new IllegalArgumentException("size");
+    }
+
+    Iterator<Date> expected = toReturn.iterator();
+    Iterator<Date> actual = values.iterator();
+    while (expected.hasNext()) {
+      Date expectedDate = expected.next();
+      long expectedTime = expectedDate.getTime();
+      long actualTime = actual.next().getTime();
+      if (expectedTime != actualTime) {
+ throw new IllegalArgumentException(expectedDate.getClass().getName()
+            + " " + expectedTime + " != " + actualTime);
+      }
+    }
+
+    return toReturn;
   }

   public static SimpleEnum processEnumList(List<SimpleEnum> values) {
@@ -278,7 +341,7 @@
   public static String returnNullString() {
     return null;
   }
-
+
   public static SimpleFoo returnSimpleFooSubclass() {
     return new SimpleFoo() {
     };
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java Wed Nov 24 06:41:26 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java Thu Dec 2 03:55:49 2010
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.requestfactory.shared;

+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.Date;
 import java.util.List;
 import java.util.Set;
@@ -61,9 +63,13 @@

InstanceRequest<SimpleFooProxy, SimpleFooProxy> persistCascadingAndReturnSelf();

+  Request<List<BigInteger>> processBigIntegerList(List<BigInteger> values);
+
+  Request<List<BigDecimal>> processBigDecimalList(List<BigDecimal> values);
+
   Request<Boolean> processBooleanList(List<Boolean> values);

-  Request<Date> processDateList(List<Date> values);
+  Request<List<Date>> processDateList(List<Date> values);

   Request<SimpleEnum> processEnumList(List<SimpleEnum> values);

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

Reply via email to