}
String baseTypeName = type.getBaseTypeName();
- if (baseTypeName.endsWith("[]")) {
- return decodeArray(type, (JSONArray) jsonValue, connection);
- } else if (Map.class.getName().equals(baseTypeName)
+ if (Map.class.getName().equals(baseTypeName)
|| HashMap.class.getName().equals(baseTypeName)) {
return decodeMap(type, jsonValue, connection);
} else if (List.class.getName().equals(baseTypeName)
} else if (Boolean.class.getName().equals(baseTypeName)) {
// TODO handle properly
return Boolean.valueOf(String.valueOf(jsonValue));
+ } else if (Byte.class.getName().equals(baseTypeName)) {
+ // TODO handle properly
+ return Byte.valueOf(String.valueOf(jsonValue));
+ } else if (Character.class.getName().equals(baseTypeName)) {
+ // TODO handle properly
+ return Character.valueOf(((JSONString) jsonValue).stringValue()
+ .charAt(0));
} else if (Connector.class.getName().equals(baseTypeName)) {
return ConnectorMap.get(connection).getConnector(
((JSONString) jsonValue).stringValue());
return map;
}
- private static Object[] decodeArray(Type type, JSONArray jsonArray,
- ApplicationConnection connection) {
- String arrayTypeName = type.getBaseTypeName();
- String chldTypeName = arrayTypeName.substring(0,
- arrayTypeName.length() - 2);
- List<Object> list = decodeList(new Type(chldTypeName, null), jsonArray,
- connection);
- return list.toArray(new Object[list.size()]);
- }
-
private static List<Object> decodeList(Type type, JSONArray jsonArray,
ApplicationConnection connection) {
List<Object> tokens = new ArrayList<Object>();
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONNull;
+import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
return new JSONString((String) value);
} else if (value instanceof Boolean) {
return JSONBoolean.getInstance((Boolean) value);
+ } else if (value instanceof Byte) {
+ return new JSONNumber((Byte) value);
+ } else if (value instanceof Character) {
+ return new JSONString(String.valueOf(value));
} else if (value instanceof Object[]) {
return encodeObjectArray((Object[]) value, restrictToInternalTypes,
connection);
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
+import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
public static boolean isInternalType(Type type) {
if (type instanceof Class && ((Class<?>) type).isPrimitive()) {
+ if (type == byte.class || type == char.class) {
+ // Almost all primitive types are handled internally
+ return false;
+ }
// All primitive types are handled internally
return true;
} else if (type == UidlValue.class) {
// Try to decode object using fields
if (value == JSONObject.NULL) {
return null;
+ } else if (targetType == byte.class || targetType == Byte.class) {
+ return Byte.valueOf(String.valueOf(value));
+ } else if (targetType == char.class || targetType == Character.class) {
+ return Character.valueOf(String.valueOf(value).charAt(0));
+ } else if (targetType instanceof Class<?>
+ && ((Class<?>) targetType).isArray()) {
+ // Legacy Object[] and String[] handled elsewhere, this takes care
+ // of generic arrays
+ return decodeArray((Class<?>) targetType, (JSONArray) value,
+ application);
} else if (targetType == JSONObject.class
|| targetType == JSONArray.class) {
return value;
}
}
+ private static Object decodeArray(Class<?> targetType, JSONArray value,
+ Application application) throws JSONException {
+ Class<?> componentType = targetType.getComponentType();
+ Object array = Array.newInstance(componentType, value.length());
+ for (int i = 0; i < value.length(); i++) {
+ Object decodedValue = decodeInternalOrCustomType(componentType,
+ value.get(i), application);
+ Array.set(array, i, decodedValue);
+ }
+ return array;
+ }
+
/**
* Decodes a value that is of an internal type.
* <p>
return application.getConnector(stringValue);
}
- // Standard Java types
+ // Legacy types
if (JsonEncoder.VTYPE_STRING.equals(transportType)) {
return stringValue;
return value;
} else if (value instanceof Number) {
return value;
+ } else if (value instanceof Character) {
+ // Character is not a Number
+ return value;
} else if (value instanceof Collection) {
Collection<?> collection = (Collection<?>) value;
JSONArray jsonArray = encodeCollection(valueType, collection,
application);
return jsonArray;
- } else if (value instanceof Object[]) {
- Object[] array = (Object[]) value;
- JSONArray jsonArray = encodeArrayContents(array, application);
+ } else if (valueType instanceof Class<?>
+ && ((Class<?>) valueType).isArray()) {
+ JSONArray jsonArray = encodeArrayContents(value, application);
return jsonArray;
} else if (value instanceof Map) {
Object jsonMap = encodeMap(valueType, (Map<?, ?>) value,
return e.name();
}
- private static JSONArray encodeArrayContents(Object[] array,
+ private static JSONArray encodeArrayContents(Object array,
Application application) throws JSONException {
JSONArray jsonArray = new JSONArray();
- for (Object o : array) {
- jsonArray.put(encode(o, null, null, application));
+ Class<?> componentType = array.getClass().getComponentType();
+ for (int i = 0; i < Array.getLength(array); i++) {
+ jsonArray.put(encode(Array.get(array, i), null, componentType,
+ application));
}
return jsonArray;
}
if (i != 0) {
sourceWriter.print(", ");
}
- sourceWriter.print("("
- + parameterType.getQualifiedSourceName()
+ String parameterTypeName = getBoxedTypeName(parameterType);
+ sourceWriter.print("(" + parameterTypeName
+ ") parameters[" + i + "]");
}
sourceWriter.println(");");
}
public static void writeTypeCreator(SourceWriter sourceWriter, JType type) {
- String typeName;
- if (type.isPrimitive() != null) {
- // Used boxed types for primitives
- typeName = type.isPrimitive().getQualifiedBoxedSourceName();
- } else {
- typeName = type.getErasedType().getQualifiedBinaryName();
- }
+ String typeName = getBoxedTypeName(type);
sourceWriter.print("new Type(\"" + typeName + "\", ");
JParameterizedType parameterized = type.isParameterized();
if (parameterized != null) {
sourceWriter.print(")");
}
+ public static String getBoxedTypeName(JType type) {
+ if (type.isPrimitive() != null) {
+ // Used boxed types for primitives
+ return type.isPrimitive().getQualifiedBoxedSourceName();
+ } else {
+ return type.getErasedType().getQualifiedSourceName();
+ }
+ }
+
private String getInvokeMethodName(JClassType type) {
return "invoke" + type.getQualifiedSourceName().replaceAll("\\.", "_");
}
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashSet;
import java.util.List;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
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.core.ext.typeinfo.TypeOracleException;
+import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
public class SerializerGenerator extends Generator {
private static final String SUBTYPE_SEPARATOR = "___";
- private static String beanSerializerPackageName = SerializerMap.class
+ private static String serializerPackageName = SerializerMap.class
.getPackage().getName();
@Override
public String generate(TreeLogger logger, GeneratorContext context,
- String beanTypeName) throws UnableToCompleteException {
- JClassType beanType = context.getTypeOracle().findType(beanTypeName);
- String beanSerializerClassName = getSerializerSimpleClassName(beanType);
+ String typeName) throws UnableToCompleteException {
+ JClassType type;
+ try {
+ type = (JClassType) context.getTypeOracle().parse(typeName);
+ } catch (TypeOracleException e1) {
+ logger.log(Type.ERROR, "Could not find type " + typeName, e1);
+ throw new UnableToCompleteException();
+ }
+ String serializerClassName = getSerializerSimpleClassName(type);
try {
// Generate class source code
- generateClass(logger, context, beanType, beanSerializerPackageName,
- beanSerializerClassName);
+ generateClass(logger, context, type, serializerPackageName,
+ serializerClassName);
} catch (Exception e) {
logger.log(TreeLogger.ERROR, "SerializerGenerator failed for "
- + beanType.getQualifiedSourceName(), e);
+ + type.getQualifiedSourceName(), e);
throw new UnableToCompleteException();
}
// return the fully qualifed name of the class generated
- return getFullyQualifiedSerializerClassName(beanType);
+ return getFullyQualifiedSerializerClassName(type);
}
/**
* Logger object
* @param context
* Generator context
- * @param beanType
+ * @param type
* @param beanTypeName
* bean type for which the serializer is to be generated
* @param beanSerializerTypeName
* @throws UnableToCompleteException
*/
private void generateClass(TreeLogger logger, GeneratorContext context,
- JClassType beanType, String serializerPackageName,
+ JClassType type, String serializerPackageName,
String serializerClassName) throws UnableToCompleteException {
// get print writer that receives the source code
PrintWriter printWriter = null;
if (printWriter == null) {
return;
}
- boolean isEnum = (beanType.isEnum() != null);
+ boolean isEnum = (type.isEnum() != null);
+ boolean isArray = (type.isArray() != null);
- Date date = new Date();
- TypeOracle typeOracle = context.getTypeOracle();
- String beanQualifiedSourceName = beanType.getQualifiedSourceName();
+ String qualifiedSourceName = type.getQualifiedSourceName();
logger.log(Type.DEBUG, "Processing serializable type "
- + beanQualifiedSourceName + "...");
+ + qualifiedSourceName + "...");
// init composer, set class properties, create source writer
ClassSourceFileComposerFactory composer = null;
composer.addImport(JsonDecoder.class.getName());
// composer.addImport(VaadinSerializer.class.getName());
- if (isEnum) {
+ if (isEnum || isArray) {
composer.addImplementedInterface(JSONSerializer.class.getName()
- + "<" + beanQualifiedSourceName + ">");
+ + "<" + qualifiedSourceName + ">");
} else {
composer.addImplementedInterface(DiffJSONSerializer.class.getName()
- + "<" + beanQualifiedSourceName + ">");
+ + "<" + qualifiedSourceName + ">");
}
SourceWriter sourceWriter = composer.createSourceWriter(context,
// public JSONValue serialize(Object value,
// ApplicationConnection connection) {
sourceWriter.println("public " + JSONValue.class.getName()
- + " serialize(" + beanQualifiedSourceName + " value, "
+ + " serialize(" + qualifiedSourceName + " value, "
+ ApplicationConnection.class.getName() + " connection) {");
sourceWriter.indent();
// MouseEventDetails castedValue = (MouseEventDetails) value;
- sourceWriter.println(beanQualifiedSourceName + " castedValue = ("
- + beanQualifiedSourceName + ") value;");
+ sourceWriter.println(qualifiedSourceName + " castedValue = ("
+ + qualifiedSourceName + ") value;");
if (isEnum) {
- writeEnumSerializer(logger, sourceWriter, beanType);
+ writeEnumSerializer(logger, sourceWriter, type);
+ } else if (isArray) {
+ writeArraySerializer(logger, sourceWriter, type.isArray());
} else {
- writeBeanSerializer(logger, sourceWriter, beanType);
+ writeBeanSerializer(logger, sourceWriter, type);
}
// }
sourceWriter.outdent();
// Updater
// public void update(T target, Type type, JSONValue jsonValue,
// ApplicationConnection connection);
- if (!isEnum) {
- sourceWriter.println("public void update("
- + beanQualifiedSourceName + " target, Type type, "
- + JSONValue.class.getName() + " jsonValue, "
- + ApplicationConnection.class.getName() + " connection) {");
+ if (!isEnum && !isArray) {
+ sourceWriter.println("public void update(" + qualifiedSourceName
+ + " target, Type type, " + JSONValue.class.getName()
+ + " jsonValue, " + ApplicationConnection.class.getName()
+ + " connection) {");
sourceWriter.indent();
- writeBeanDeserializer(logger, sourceWriter, beanType);
+ writeBeanDeserializer(logger, sourceWriter, type);
sourceWriter.outdent();
sourceWriter.println("}");
// Deserializer
// T deserialize(Type type, JSONValue jsonValue, ApplicationConnection
// connection);
- sourceWriter.println("public " + beanQualifiedSourceName
+ sourceWriter.println("public " + qualifiedSourceName
+ " deserialize(Type type, " + JSONValue.class.getName()
+ " jsonValue, " + ApplicationConnection.class.getName()
+ " connection) {");
sourceWriter.indent();
if (isEnum) {
- writeEnumDeserializer(logger, sourceWriter, beanType.isEnum());
+ writeEnumDeserializer(logger, sourceWriter, type.isEnum());
+ } else if (isArray) {
+ writeArrayDeserializer(logger, sourceWriter, type.isArray());
} else {
- sourceWriter.println(beanQualifiedSourceName
- + " target = GWT.create(" + beanQualifiedSourceName
- + ".class);");
+ sourceWriter.println(qualifiedSourceName + " target = GWT.create("
+ + qualifiedSourceName + ".class);");
sourceWriter
.println("update(target, type, jsonValue, connection);");
// return target;
// commit generated class
context.commit(logger, printWriter);
logger.log(TreeLogger.INFO, "Generated Serializer class "
- + getFullyQualifiedSerializerClassName(beanType));
+ + getFullyQualifiedSerializerClassName(type));
}
private void writeEnumDeserializer(TreeLogger logger,
sourceWriter.println("return null;");
}
+ private void writeArrayDeserializer(TreeLogger logger,
+ SourceWriter sourceWriter, JArrayType type) {
+ JType leafType = type.getLeafType();
+ int rank = type.getRank();
+
+ sourceWriter.println(JSONArray.class.getName()
+ + " jsonArray = jsonValue.isArray();");
+
+ // Type value = new Type[jsonArray.size()][][];
+ sourceWriter.print(type.getQualifiedSourceName() + " value = new "
+ + leafType.getQualifiedSourceName() + "[jsonArray.size()]");
+ for (int i = 1; i < rank; i++) {
+ sourceWriter.print("[]");
+ }
+ sourceWriter.println(";");
+
+ sourceWriter.println("for(int i = 0 ; i < value.length; i++) {");
+ sourceWriter.indent();
+
+ JType componentType = type.getComponentType();
+
+ sourceWriter.print("value[i] = ("
+ + GeneratedRpcMethodProviderGenerator
+ .getBoxedTypeName(componentType) + ") "
+ + JsonDecoder.class.getName() + ".decodeValue(");
+ GeneratedRpcMethodProviderGenerator.writeTypeCreator(sourceWriter,
+ componentType);
+ sourceWriter.print(", jsonArray.get(i), null, connection)");
+
+ sourceWriter.println(";");
+
+ sourceWriter.outdent();
+ sourceWriter.println("}");
+
+ sourceWriter.println("return value;");
+ }
+
private void writeBeanDeserializer(TreeLogger logger,
SourceWriter sourceWriter, JClassType beanType) {
String beanQualifiedSourceName = beanType.getQualifiedSourceName();
+ "(castedValue.name());");
}
+ private void writeArraySerializer(TreeLogger logger,
+ SourceWriter sourceWriter, JArrayType array) {
+ sourceWriter.println(JSONArray.class.getName() + " values = new "
+ + JSONArray.class.getName() + "();");
+ JType componentType = array.getComponentType();
+ // JPrimitiveType primitive = componentType.isPrimitive();
+ sourceWriter.println("for (int i = 0; i < castedValue.length; i++) {");
+ sourceWriter.indent();
+ sourceWriter.print("values.set(i, ");
+ sourceWriter.print(JsonEncoder.class.getName()
+ + ".encode(castedValue[i], false, connection)");
+ sourceWriter.println(");");
+ sourceWriter.outdent();
+ sourceWriter.println("}");
+ sourceWriter.println("return values;");
+ }
+
private void writeBeanSerializer(TreeLogger logger,
SourceWriter sourceWriter, JClassType beanType)
throws UnableToCompleteException {
return getSimpleClassName(beanType) + "_Serializer";
}
- private static String getSimpleClassName(JClassType type) {
- if (type.isMemberType()) {
+ private static String getSimpleClassName(JType type) {
+ JArrayType arrayType = type.isArray();
+ if (arrayType != null) {
+ return "Array" + getSimpleClassName(arrayType.getComponentType());
+ }
+ JClassType classType = type.isClass();
+ if (classType != null && classType.isMemberType()) {
// Assumed to be static sub class
- String baseName = getSimpleClassName(type.getEnclosingType());
+ String baseName = getSimpleClassName(classType.getEnclosingType());
String name = baseName + SUBTYPE_SEPARATOR
+ type.getSimpleSourceName();
return name;
}
public static String getFullyQualifiedSerializerClassName(JClassType type) {
- return beanSerializerPackageName + "."
- + getSerializerSimpleClassName(type);
+ return serializerPackageName + "." + getSerializerSimpleClassName(type);
}
}
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
JClassType javaSerializable = typeOracle.findType(Serializable.class
.getName());
for (JClassType type : typesNeedingSerializers) {
+ if (type.isArray() != null) {
+ // Don't check for arrays
+ continue;
+ }
boolean serializable = type.isAssignableTo(javaSerializable);
if (!serializable) {
logger.log(
// TODO cache serializer instances in a map
for (JClassType type : typesNeedingSerializers) {
- sourceWriter.println("if (type.equals(\""
- + type.getQualifiedBinaryName() + "\")) {");
+ sourceWriter.print("if (type.equals(\""
+ + type.getQualifiedSourceName() + "\")");
+ if (type instanceof JArrayType) {
+ // Also add binary name to support encoding based on
+ // object.getClass().getName()
+ sourceWriter.print("||type.equals(\"" + type.getJNISignature()
+ + "\")");
+ }
+ sourceWriter.println(") {");
sourceWriter.indent();
String serializerName = SerializerGenerator
.getFullyQualifiedSerializerClassName(type);
serializableTypes.add(typeClass);
findSubTypesNeedingSerializers(typeClass, serializableTypes);
}
+
+ // Generate (n-1)-dimensional array serializer for n-dimensional array
+ JArrayType arrayType = type.isArray();
+ if (arrayType != null) {
+ serializableTypes.add(arrayType);
+ addTypeIfNeeded(serializableTypes, arrayType.getComponentType());
+ }
+
}
Set<Class<?>> frameworkHandledTypes = new HashSet<Class<?>>();
frameworkHandledTypes.add(Map.class);
frameworkHandledTypes.add(List.class);
frameworkHandledTypes.add(Set.class);
+ frameworkHandledTypes.add(Byte.class);
+ frameworkHandledTypes.add(Character.class);
}
private boolean serializationHandledByFramework(JType setterType) {
// Some types are handled by the framework at the moment. See #8449
// This method should be removed at some point.
- if (setterType.isArray() != null) {
- return true;
- }
if (setterType.isPrimitive() != null) {
return true;
}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.serialization;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.gwt.client.Connector;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.tests.util.Log;
+import com.vaadin.tests.widgetset.client.ComplexTestBean;
+import com.vaadin.tests.widgetset.client.SerializerTestRpc;
+import com.vaadin.tests.widgetset.client.SimpleTestBean;
+import com.vaadin.tests.widgetset.server.SerializerTestExtension;
+
+@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
+public class SerializerTest extends AbstractTestRoot {
+
+ private Log log = new Log(40);
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ final SerializerTestExtension testExtension = new SerializerTestExtension();
+ addExtension(testExtension);
+ addComponent(log);
+
+ SerializerTestRpc rpc = testExtension
+ .getRpcProxy(SerializerTestRpc.class);
+ rpc.sendBoolean(true, Boolean.FALSE, new boolean[] { true, true, false,
+ true, false, false });
+ rpc.sendByte((byte) 5, Byte.valueOf((byte) -12), new byte[] { 3, 1, 2 });
+ rpc.sendChar('∫', Character.valueOf('å'), "aBcD".toCharArray());
+ rpc.sendInt(Integer.MAX_VALUE, Integer.valueOf(0), new int[] { 5, 7 });
+ rpc.sendLong(577431841358l, Long.valueOf(0), new long[] {
+ -57841235865l, 57 });
+ rpc.sendFloat(3.14159f, Float.valueOf(Math.nextUp(1)), new float[] {
+ 57, 0, -12 });
+ rpc.sendDouble(Math.PI, Double.valueOf(-Math.E), new double[] {
+ Double.MAX_VALUE, Double.MIN_VALUE });
+ rpc.sendString("This is a tesing string ‡");
+ rpc.sendConnector(this);
+ rpc.sendBean(
+ new ComplexTestBean(new SimpleTestBean(0),
+ new SimpleTestBean(1), Arrays.asList(
+ new SimpleTestBean(3), new SimpleTestBean(4)),
+ 5), new SimpleTestBean(6),
+ new SimpleTestBean[] { new SimpleTestBean(7) });
+ rpc.sendNull("Not null", null);
+ rpc.sendNestedArray(new int[][] { { 5 }, { 7 } },
+ new SimpleTestBean[][] { { new SimpleTestBean(4),
+ new SimpleTestBean(2) } });
+ rpc.sendList(Arrays.asList(5, 8, -234), Arrays.<Connector> asList(this,
+ testExtension), Arrays.asList(new SimpleTestBean(234),
+ new SimpleTestBean(-568)));
+ // Disabled because of #8861
+ // rpc.sendArrayList(
+ // Arrays.asList(new int[] { 1, 2 }, new int[] { 3, 4 }),
+ // Arrays.asList(new Integer[] { 5, 6 }, new Integer[] { 7, 8 }),
+ // Collections
+ // .singletonList(new SimpleTestBean[] { new SimpleTestBean(
+ // 7) }));
+ // Disabled because of #8861
+ // rpc.sendListArray(
+ // new List[] { Arrays.asList(1, 2), Arrays.asList(3, 4) },
+ // new List[] { Collections.singletonList(new SimpleTestBean(-1)) });
+ rpc.sendSet(new HashSet<Integer>(Arrays.asList(4, 7, 12)), Collections
+ .singleton((Connector) this), new HashSet<SimpleTestBean>(
+ Arrays.asList(new SimpleTestBean(1), new SimpleTestBean(2))));
+
+ rpc.sendMap(new HashMap<String, SimpleTestBean>() {
+ {
+ put("1", new SimpleTestBean(1));
+ put("2", new SimpleTestBean(2));
+ }
+ }, new HashMap<Connector, Boolean>() {
+ {
+ put(testExtension, true);
+ put(getRoot(), false);
+ }
+ }, new HashMap<Integer, Connector>() {
+ {
+ put(5, testExtension);
+ put(10, getRoot());
+ }
+ }, new HashMap<SimpleTestBean, SimpleTestBean>() {
+ {
+ put(new SimpleTestBean(5), new SimpleTestBean(-5));
+ put(new SimpleTestBean(-4), new SimpleTestBean(4));
+ }
+ });
+ rpc.sendWrappedGenerics(new HashMap<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>>() {
+ {
+ put(Collections.singleton(new SimpleTestBean(42)),
+ new HashMap<Integer, List<SimpleTestBean>>() {
+ {
+ put(1, Arrays.asList(new SimpleTestBean(1),
+ new SimpleTestBean(3)));
+ }
+ });
+ }
+ });
+
+ testExtension.registerRpc(new SerializerTestRpc() {
+ public void sendBoolean(boolean value, Boolean boxedValue,
+ boolean[] array) {
+ log.log("sendBoolean: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendByte(byte value, Byte boxedValue, byte[] array) {
+ log.log("sendByte: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendChar(char value, Character boxedValue, char[] array) {
+ log.log("sendChar: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendInt(int value, Integer boxedValue, int[] array) {
+ log.log("sendInt: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendLong(long value, Long boxedValue, long[] array) {
+ log.log("sendLong: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendFloat(float value, Float boxedValue, float[] array) {
+ log.log("sendFloat: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendDouble(double value, Double boxedValue,
+ double[] array) {
+ log.log("sendDouble: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendString(String value) {
+ log.log("sendString: " + value);
+ }
+
+ public void sendConnector(Connector connector) {
+ log.log("sendConnector: " + connector.getClass().getName());
+ }
+
+ public void sendBean(ComplexTestBean complexBean,
+ SimpleTestBean simpleBean, SimpleTestBean[] array) {
+ log.log("sendBean: " + complexBean + ", " + simpleBean + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendNull(String value1, String value2) {
+ log.log("sendNull: " + value1 + ", " + value2);
+ }
+
+ public void sendNestedArray(int[][] nestedIntArray,
+ SimpleTestBean[][] nestedBeanArray) {
+ log.log("sendNestedArray: "
+ + Arrays.deepToString(nestedIntArray) + ", "
+ + Arrays.deepToString(nestedBeanArray));
+ }
+
+ public void sendList(List<Integer> intList,
+ List<Connector> connectorList, List<SimpleTestBean> beanList) {
+ log.log("sendList: " + intList + ", "
+ + connectorCollectionToString(connectorList) + ", "
+ + beanList);
+ }
+
+ private String connectorCollectionToString(
+ Collection<Connector> collection) {
+ StringBuilder sb = new StringBuilder();
+
+ for (Connector connector : collection) {
+ if (sb.length() != 0) {
+ sb.append(", ");
+ }
+ sb.append(connector.getClass());
+ }
+
+ String string = sb.toString();
+ return string;
+ }
+
+ public void sendArrayList(List<int[]> primitiveArrayList,
+ List<Integer[]> objectArrayList,
+ List<SimpleTestBean[]> beanArrayList) {
+ log.log("sendArrayList: " + primitiveArrayList + ", "
+ + objectArrayList + ", " + beanArrayList);
+ }
+
+ public void sendListArray(List<Integer>[] objectListArray,
+ List<SimpleTestBean>[] beanListArray) {
+ log.log("sendArrayList: " + Arrays.toString(objectListArray)
+ + ", " + Arrays.toString(beanListArray));
+ }
+
+ public void sendSet(Set<Integer> intSet,
+ Set<Connector> connectorSet, Set<SimpleTestBean> beanSet) {
+ log.log("sendSet: " + intSet + ", "
+ + connectorCollectionToString(connectorSet) + ", "
+ + beanSet);
+ }
+
+ public void sendMap(Map<String, SimpleTestBean> stringMap,
+ Map<Connector, Boolean> connectorMap,
+ Map<Integer, Connector> intMap,
+ Map<SimpleTestBean, SimpleTestBean> beanMap) {
+ StringBuilder sb = new StringBuilder();
+ for (Entry<Connector, Boolean> entry : connectorMap.entrySet()) {
+ if (sb.length() == 0) {
+ sb.append('[');
+ } else {
+ sb.append(", ");
+ }
+ sb.append(entry.getKey().getClass().getName());
+ sb.append('=');
+ sb.append(entry.getValue());
+ }
+ sb.append(']');
+ String connectorMapString = sb.toString();
+
+ sb = new StringBuilder();
+ for (Entry<Integer, Connector> entry : intMap.entrySet()) {
+ if (sb.length() == 0) {
+ sb.append('[');
+ } else {
+ sb.append(", ");
+ }
+ sb.append(entry.getKey());
+ sb.append('=');
+ sb.append(entry.getValue().getClass().getName());
+ }
+ sb.append(']');
+ String intMapString = sb.toString();
+
+ log.log("sendMap: " + stringMap + ", " + connectorMapString
+ + ", " + intMapString + ", " + beanMap);
+ }
+
+ public void sendWrappedGenerics(
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> generics) {
+ log.log("sendWrappedGenerics: " + generics.toString());
+ }
+
+ });
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test for lots of different cases of encoding and decoding variuos data types";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(8655);
+ }
+
+}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.util.List;
+
+import com.vaadin.terminal.gwt.client.communication.SharedState;
+
+@SuppressWarnings("javadoc")
+public class ComplexTestBean extends SharedState {
+ private SimpleTestBean innerBean1;
+ private SimpleTestBean innerBean2;
+ private List<SimpleTestBean> innerBeanCollection;
+ private int privimite;
+
+ public ComplexTestBean() {
+ // Default
+ }
+
+ public ComplexTestBean(SimpleTestBean innerBean1,
+ SimpleTestBean innerBean2,
+ List<SimpleTestBean> innerBeanCollection, int privimite) {
+ this.innerBean1 = innerBean1;
+ this.innerBean2 = innerBean2;
+ this.innerBeanCollection = innerBeanCollection;
+ this.privimite = privimite;
+ }
+
+ public SimpleTestBean getInnerBean1() {
+ return innerBean1;
+ }
+
+ public void setInnerBean1(SimpleTestBean innerBean) {
+ innerBean1 = innerBean;
+ }
+
+ public SimpleTestBean getInnerBean2() {
+ return innerBean2;
+ }
+
+ public void setInnerBean2(SimpleTestBean innerBean2) {
+ this.innerBean2 = innerBean2;
+ }
+
+ public List<SimpleTestBean> getInnerBeanCollection() {
+ return innerBeanCollection;
+ }
+
+ public void setInnerBeanCollection(List<SimpleTestBean> innerBeanCollection) {
+ this.innerBeanCollection = innerBeanCollection;
+ }
+
+ public int getPrivimite() {
+ return privimite;
+ }
+
+ public void setPrivimite(int privimite) {
+ this.privimite = privimite;
+ }
+
+ @Override
+ public String toString() {
+ return "ComplexTestBean [innerBean1=" + innerBean1 + ", innerBean2="
+ + innerBean2 + ", innerBeanCollection=" + innerBeanCollection
+ + ", privimite=" + privimite + "]";
+ }
+
+}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.Connector;
+import com.vaadin.terminal.gwt.client.communication.RpcProxy;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.tests.widgetset.server.SerializerTestExtension;
+
+@Connect(SerializerTestExtension.class)
+public class SerializerTestConnector extends AbstractExtensionConnector {
+
+ private SerializerTestRpc rpc = RpcProxy.create(SerializerTestRpc.class,
+ this);
+
+ public SerializerTestConnector() {
+ registerRpc(SerializerTestRpc.class, new SerializerTestRpc() {
+ public void sendWrappedGenerics(
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> generics) {
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> updated = new HashMap<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>>();
+
+ SimpleTestBean firstValue = generics.values().iterator().next()
+ .get(Integer.valueOf(1)).get(0);
+ Set<SimpleTestBean> key = new HashSet<SimpleTestBean>(Arrays
+ .asList(firstValue));
+
+ Map<Integer, List<SimpleTestBean>> value = new HashMap<Integer, List<SimpleTestBean>>();
+ Set<SimpleTestBean> firstKeyValue = generics.keySet()
+ .iterator().next();
+ value.put(Integer.valueOf(1), new ArrayList<SimpleTestBean>(
+ firstKeyValue));
+
+ updated.put(key, value);
+
+ rpc.sendWrappedGenerics(updated);
+ }
+
+ public void sendString(String value) {
+ char[] chars = value.toCharArray();
+ Arrays.sort(chars);
+ rpc.sendString(new String(chars));
+ }
+
+ public void sendSet(Set<Integer> intSet,
+ Set<Connector> connectorSet, Set<SimpleTestBean> beanSet) {
+
+ beanSet.iterator().next().setValue(intSet.size());
+ Set<Integer> updatedIntSet = new HashSet<Integer>();
+
+ for (Integer integer : intSet) {
+ updatedIntSet.add(Integer.valueOf(-integer.intValue()));
+ }
+ rpc.sendSet(updatedIntSet,
+ Collections.singleton(getRootConnector()), beanSet);
+ }
+
+ public void sendNestedArray(int[][] nestedIntArray,
+ SimpleTestBean[][] nestedBeanArray) {
+ rpc.sendNestedArray(new int[][] { { nestedIntArray[1][0],
+ nestedIntArray[0][0] } }, new SimpleTestBean[][] {
+ { nestedBeanArray[0][1] }, { nestedBeanArray[0][0] } });
+ }
+
+ public void sendMap(Map<String, SimpleTestBean> stringMap,
+ Map<Connector, Boolean> connectorMap,
+ Map<Integer, Connector> intMap,
+ Map<SimpleTestBean, SimpleTestBean> beanMap) {
+ Map<SimpleTestBean, SimpleTestBean> updatedBeanMap = new HashMap<SimpleTestBean, SimpleTestBean>();
+ for (Entry<SimpleTestBean, SimpleTestBean> entry : beanMap
+ .entrySet()) {
+ updatedBeanMap.put(entry.getValue(), entry.getKey());
+ }
+
+ rpc.sendMap(Collections.singletonMap("a", stringMap.get("b")),
+ Collections.singletonMap(getThisConnector(),
+ connectorMap.get(getRootConnector())),
+ Collections.singletonMap(
+ Integer.valueOf(stringMap.size()),
+ getThisConnector()), updatedBeanMap);
+ }
+
+ public void sendLong(long value, Long boxedValue, long[] array) {
+ rpc.sendLong(array[0], Long.valueOf(value), new long[] {
+ array[1], boxedValue.longValue() });
+ }
+
+ public void sendList(List<Integer> intList,
+ List<Connector> connectorList, List<SimpleTestBean> beanList) {
+ Collections.sort(intList);
+ Collections.reverse(beanList);
+ rpc.sendList(intList,
+ Arrays.asList(getThisConnector(), getRootConnector()),
+ beanList);
+ }
+
+ public void sendInt(int value, Integer boxedValue, int[] array) {
+ rpc.sendInt(array.length, Integer.valueOf(array[0]), new int[] {
+ value, boxedValue.intValue() });
+ }
+
+ public void sendFloat(float value, Float boxedValue, float[] array) {
+ Arrays.sort(array);
+ rpc.sendFloat(boxedValue.floatValue(), Float.valueOf(value),
+ array);
+ }
+
+ public void sendDouble(double value, Double boxedValue,
+ double[] array) {
+ rpc.sendDouble(value + boxedValue.doubleValue(),
+ Double.valueOf(value - boxedValue.doubleValue()),
+ new double[] { array.length, array[0], array[1] });
+ }
+
+ public void sendConnector(Connector connector) {
+ rpc.sendConnector(getThisConnector());
+ }
+
+ public void sendChar(char value, Character boxedValue, char[] array) {
+ rpc.sendChar(Character.toUpperCase(boxedValue.charValue()),
+ Character.valueOf(value), new String(array)
+ .toLowerCase().toCharArray());
+ }
+
+ public void sendByte(byte value, Byte boxedValue, byte[] array) {
+ // There will most certainly be a bug that is not discovered
+ // because this particular method doesn't do anything with it's
+ // values...
+ rpc.sendByte(value, boxedValue, array);
+ }
+
+ public void sendBoolean(boolean value, Boolean boxedValue,
+ boolean[] array) {
+ boolean[] inverseArray = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ inverseArray[i] = !array[i];
+ }
+ rpc.sendBoolean(boxedValue == Boolean.TRUE,
+ Boolean.valueOf(!value), inverseArray);
+ }
+
+ public void sendBean(ComplexTestBean complexBean,
+ SimpleTestBean simpleBean, SimpleTestBean[] array) {
+ SimpleTestBean updatedSimpleBean = new SimpleTestBean();
+ updatedSimpleBean.setValue(complexBean.getInnerBean1()
+ .getValue());
+
+ ComplexTestBean updatedComplexBean = new ComplexTestBean();
+ updatedComplexBean.setInnerBean1(complexBean.getInnerBean2());
+ updatedComplexBean.setInnerBean2(complexBean
+ .getInnerBeanCollection().get(0));
+ updatedComplexBean.setInnerBeanCollection(Arrays.asList(
+ simpleBean, updatedSimpleBean));
+ updatedComplexBean.setPrivimite(complexBean.getPrivimite() + 1);
+
+ ArrayList<SimpleTestBean> arrayList = new ArrayList<SimpleTestBean>(
+ Arrays.asList(array));
+ Collections.reverse(arrayList);
+
+ rpc.sendBean(updatedComplexBean, updatedSimpleBean,
+ arrayList.toArray(new SimpleTestBean[array.length]));
+ }
+
+ public void sendArrayList(List<int[]> primitiveArrayList,
+ List<Integer[]> objectArrayList,
+ List<SimpleTestBean[]> beanArrayList) {
+ Collections.reverse(beanArrayList);
+ List<Integer[]> updatedObjectArrayList = new ArrayList<Integer[]>();
+ for (int[] array : primitiveArrayList) {
+ updatedObjectArrayList.add(new Integer[] {
+ Integer.valueOf(array.length),
+ Integer.valueOf(array[0]) });
+ }
+
+ rpc.sendArrayList(Arrays.asList(
+ new int[] { primitiveArrayList.size() },
+ new int[] { objectArrayList.get(0).length }),
+ updatedObjectArrayList, beanArrayList);
+ }
+
+ public void sendNull(String value1, String value2) {
+ rpc.sendNull(value2, value1);
+ }
+
+ public void sendListArray(List<Integer>[] objectListArray,
+ List<SimpleTestBean>[] beanListArray) {
+ rpc.sendListArray(new List[] { objectListArray[1],
+ objectListArray[0] }, new List[] { Collections
+ .singletonList(beanListArray[0].get(0)) });
+ }
+ });
+ }
+
+ private Connector getRootConnector() {
+ return getConnection().getRootConnector();
+ }
+
+ private Connector getThisConnector() {
+ // Cast to Connector for use in e.g. Collections.singleton() to get a
+ // Set<Connector>
+ return this;
+ }
+
+ @Override
+ public ComplexTestBean getState() {
+ return (ComplexTestBean) super.getState();
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ // TODO do something clever
+ }
+
+}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.Connector;
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+
+@SuppressWarnings("javadoc")
+public interface SerializerTestRpc extends ServerRpc, ClientRpc {
+ public void sendBoolean(boolean value, Boolean boxedValue, boolean[] array);
+
+ public void sendByte(byte value, Byte boxedValue, byte[] array);
+
+ public void sendChar(char value, Character boxedValue, char[] array);
+
+ public void sendInt(int value, Integer boxedValue, int[] array);
+
+ public void sendLong(long value, Long boxedValue, long[] array);
+
+ public void sendFloat(float value, Float boxedValue, float[] array);
+
+ public void sendDouble(double value, Double boxedValue, double[] array);
+
+ public void sendString(String value);
+
+ public void sendConnector(Connector connector);
+
+ public void sendBean(ComplexTestBean complexBean,
+ SimpleTestBean simpleBean, SimpleTestBean[] array);
+
+ public void sendNull(String value1, String value2);
+
+ public void sendNestedArray(int[][] nestedIntArray,
+ SimpleTestBean[][] nestedBeanArray);
+
+ public void sendList(List<Integer> intList, List<Connector> connectorList,
+ List<SimpleTestBean> beanList);
+
+ public void sendArrayList(List<int[]> primitiveArrayList,
+ List<Integer[]> objectArrayList,
+ List<SimpleTestBean[]> beanArrayList);
+
+ public void sendListArray(List<Integer>[] objectListArray,
+ List<SimpleTestBean>[] beanListArray);
+
+ public void sendSet(Set<Integer> intSet, Set<Connector> connectorSet,
+ Set<SimpleTestBean> beanSet);
+
+ public void sendMap(Map<String, SimpleTestBean> stringMap,
+ Map<Connector, Boolean> connectorMap,
+ Map<Integer, Connector> intMap,
+ Map<SimpleTestBean, SimpleTestBean> beanMap);
+
+ public void sendWrappedGenerics(
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> generics);
+
+}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.io.Serializable;
+
+public class SimpleTestBean implements Serializable {
+ private int value;
+
+ public SimpleTestBean() {
+ this(0);
+ }
+
+ public SimpleTestBean(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "SimpleTestBean(" + value + ")";
+ }
+
+ @Override
+ public int hashCode() {
+ // Implement hash code to get consistent HashSet.toString
+ return value;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.server;
+
+import com.vaadin.terminal.AbstractExtension;
+import com.vaadin.tests.widgetset.client.ComplexTestBean;
+import com.vaadin.tests.widgetset.client.SerializerTestRpc;
+
+public class SerializerTestExtension extends AbstractExtension {
+
+ @Override
+ public ComplexTestBean getState() {
+ return (ComplexTestBean) super.getState();
+ }
+
+ public void registerRpc(SerializerTestRpc rpc) {
+ super.registerRpc(rpc);
+ }
+
+}