Support upcasting Date, BigInteger, and BigDecimal types. git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.1@9339 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/tools/api-checker/config/gwt20_21userApi.conf b/tools/api-checker/config/gwt20_21userApi.conf index 697b3cc..54313db 100644 --- a/tools/api-checker/config/gwt20_21userApi.conf +++ b/tools/api-checker/config/gwt20_21userApi.conf
@@ -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\
diff --git a/tools/api-checker/config/gwt21_22userApi.conf b/tools/api-checker/config/gwt21_22userApi.conf index 9664ee9..3e4f820 100644 --- a/tools/api-checker/config/gwt21_22userApi.conf +++ b/tools/api-checker/config/gwt21_22userApi.conf
@@ -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\
diff --git a/user/src/com/google/gwt/autobean/shared/AutoBeanCodex.java b/user/src/com/google/gwt/autobean/shared/AutoBeanCodex.java index 9d228f4..2ae2f0e 100644 --- a/user/src/com/google/gwt/autobean/shared/AutoBeanCodex.java +++ b/user/src/com/google/gwt/autobean/shared/AutoBeanCodex.java
@@ -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()); }
diff --git a/user/src/com/google/gwt/autobean/shared/ValueCodex.java b/user/src/com/google/gwt/autobean/shared/ValueCodex.java index d4a452f..ca867eb 100644 --- a/user/src/com/google/gwt/autobean/shared/ValueCodex.java +++ b/user/src/com/google/gwt/autobean/shared/ValueCodex.java
@@ -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. @@ -31,6 +33,11 @@ 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); } @@ -42,6 +49,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); } @@ -71,6 +83,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)); } @@ -158,6 +175,15 @@ 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); public Object getDefaultValue() { @@ -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) { @@ -212,12 +246,42 @@ 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; - } + if (clazz.isEnum()) { + return Type.ENUM; } - return type; + return TYPES_BY_CLASS.get(clazz); } private static <T> Type getTypeOrDie(Class<T> clazz) {
diff --git a/user/src/com/google/gwt/autobean/shared/ValueCodexHelper.java b/user/src/com/google/gwt/autobean/shared/ValueCodexHelper.java new file mode 100644 index 0000000..c6f72c8 --- /dev/null +++ b/user/src/com/google/gwt/autobean/shared/ValueCodexHelper.java
@@ -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; + } +}
diff --git a/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java b/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java index 583c49d..310b9dd 100644 --- a/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java +++ b/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java
@@ -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; } }
diff --git a/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java b/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java index 2c8f005..f034b1c 100644 --- a/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java +++ b/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java
@@ -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; }
diff --git a/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java b/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java index 2a45831..839f4ee 100644 --- a/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java +++ b/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java
@@ -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); }
diff --git a/user/super/com/google/gwt/autobean/super/com/google/gwt/autobean/shared/ValueCodexHelper.java b/user/super/com/google/gwt/autobean/super/com/google/gwt/autobean/shared/ValueCodexHelper.java new file mode 100644 index 0000000..42c87e3 --- /dev/null +++ b/user/super/com/google/gwt/autobean/super/com/google/gwt/autobean/shared/ValueCodexHelper.java
@@ -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; + } +}
diff --git a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java index 85e1cb7..5d0cb95 100644 --- a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java +++ b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
@@ -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 testPrimitiveListBigDecimalAsParameter() { + delayTestFinish(DELAY_TEST_FINISH); + + // 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); - @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.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() {
diff --git a/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java b/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java index f6640da..1c6c003 100644 --- a/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java +++ b/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
@@ -87,6 +87,10 @@ int foo(int a) { return 0; } + + java.sql.Date getSqlDate() { + return null; + } } @ProxyFor(Domain.class) @@ -111,11 +115,17 @@ return 0; } } + @ProxyFor(DomainWithOverloads.class) interface DomainWithOverloadsProxy extends EntityProxy { void foo(); } + @ProxyFor(Domain.class) + interface DomainWithSqlDateProxy extends EntityProxy { + java.sql.Date getSqlDate(); + } + class Foo { } @@ -270,6 +280,14 @@ }; /** + * 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(). */ public void testFindRequestContext() {
diff --git a/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java b/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java index 4a1bfb7..1ac5987 100644 --- a/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java +++ b/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
@@ -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; @@ -157,12 +160,72 @@ 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() { };
diff --git a/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java b/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java index cd174be..bbb4c6b 100644 --- a/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java +++ b/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java
@@ -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);