]> source.dussan.org Git - vaadin-framework.git/commitdiff
Support arrays in RPC and shared state + test (#8655)
authorLeif Åstrand <leif@vaadin.com>
Mon, 25 Jun 2012 09:37:36 +0000 (12:37 +0300)
committerLeif Åstrand <leif@vaadin.com>
Mon, 25 Jun 2012 09:37:36 +0000 (12:37 +0300)
12 files changed:
src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java
src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java
src/com/vaadin/terminal/gwt/server/JsonCodec.java
src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java
src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java
src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java
tests/testbench/com/vaadin/tests/serialization/SerializerTest.java [new file with mode: 0644]
tests/testbench/com/vaadin/tests/widgetset/client/ComplexTestBean.java [new file with mode: 0644]
tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestConnector.java [new file with mode: 0644]
tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestRpc.java [new file with mode: 0644]
tests/testbench/com/vaadin/tests/widgetset/client/SimpleTestBean.java [new file with mode: 0644]
tests/testbench/com/vaadin/tests/widgetset/server/SerializerTestExtension.java [new file with mode: 0644]

index 1459d8ee7d1cf871f4a06b97b43c81e764fd4ba3..23a2c30cd0fc80129d630a9d891dd56e0a53e3c5 100644 (file)
@@ -52,9 +52,7 @@ public class JsonDecoder {
         }
 
         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)
@@ -78,6 +76,13 @@ public class JsonDecoder {
         } 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());
@@ -180,16 +185,6 @@ public class JsonDecoder {
         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>();
index cb7dbe5e725b9f499a4962ceecf587d34a242942..925f0b62725a90019f6337baa19ff9bf4c94d8ae 100644 (file)
@@ -13,6 +13,7 @@ import java.util.Set;
 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;
@@ -72,6 +73,10 @@ public class JsonEncoder {
             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);
index 71e4727164cfec8f3bf00e74e173b3d19422ce8c..4fb7681e4a0f76532faded33ce8a12b2058ca9bc 100644 (file)
@@ -8,6 +8,7 @@ import java.beans.IntrospectionException;
 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;
@@ -82,6 +83,10 @@ public class JsonCodec implements Serializable {
 
     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) {
@@ -123,6 +128,16 @@ public class JsonCodec implements Serializable {
         // 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;
@@ -131,6 +146,18 @@ public class JsonCodec implements Serializable {
         }
     }
 
+    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>
@@ -203,7 +230,7 @@ public class JsonCodec implements Serializable {
             return application.getConnector(stringValue);
         }
 
-        // Standard Java types
+        // Legacy types
 
         if (JsonEncoder.VTYPE_STRING.equals(transportType)) {
             return stringValue;
@@ -494,14 +521,17 @@ public class JsonCodec implements Serializable {
             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,
@@ -604,11 +634,13 @@ public class JsonCodec implements Serializable {
         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;
     }
index ba3dcd85b93929a2b943ec3c5d72007d336bf1df..b1d69b178b4ce0a204d7ac90aa8cae65e10a71c6 100644 (file)
@@ -146,8 +146,8 @@ public class GeneratedRpcMethodProviderGenerator extends Generator {
                         if (i != 0) {
                             sourceWriter.print(", ");
                         }
-                        sourceWriter.print("("
-                                + parameterType.getQualifiedSourceName()
+                        String parameterTypeName = getBoxedTypeName(parameterType);
+                        sourceWriter.print("(" + parameterTypeName
                                 + ") parameters[" + i + "]");
                     }
                     sourceWriter.println(");");
@@ -179,13 +179,7 @@ public class GeneratedRpcMethodProviderGenerator extends Generator {
     }
 
     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) {
@@ -202,6 +196,15 @@ public class GeneratedRpcMethodProviderGenerator extends Generator {
         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("\\.", "_");
     }
index c32b54ff1cf5480b263e7016a3e0bfff0f33c754..1951f8ba40bd6e794ae88682c593672265c6490f 100644 (file)
@@ -6,7 +6,6 @@ package com.vaadin.terminal.gwt.widgetsetutils;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 
@@ -16,13 +15,15 @@ import com.google.gwt.core.ext.GeneratorContext;
 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;
@@ -46,26 +47,32 @@ import com.vaadin.terminal.gwt.client.communication.SerializerMap;
 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);
     }
 
     /**
@@ -75,7 +82,7 @@ public class SerializerGenerator extends Generator {
      *            Logger object
      * @param context
      *            Generator context
-     * @param beanType
+     * @param type
      * @param beanTypeName
      *            bean type for which the serializer is to be generated
      * @param beanSerializerTypeName
@@ -83,7 +90,7 @@ public class SerializerGenerator extends Generator {
      * @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;
@@ -94,13 +101,12 @@ public class SerializerGenerator extends Generator {
         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;
@@ -115,12 +121,12 @@ public class SerializerGenerator extends Generator {
         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,
@@ -132,17 +138,19 @@ public class SerializerGenerator extends Generator {
         // 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();
@@ -152,14 +160,14 @@ public class SerializerGenerator extends Generator {
         // 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("}");
@@ -168,18 +176,19 @@ public class SerializerGenerator extends Generator {
         // 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;
@@ -195,7 +204,7 @@ public class SerializerGenerator extends Generator {
         // commit generated class
         context.commit(logger, printWriter);
         logger.log(TreeLogger.INFO, "Generated Serializer class "
-                + getFullyQualifiedSerializerClassName(beanType));
+                + getFullyQualifiedSerializerClassName(type));
     }
 
     private void writeEnumDeserializer(TreeLogger logger,
@@ -214,6 +223,43 @@ public class SerializerGenerator extends Generator {
         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();
@@ -281,6 +327,23 @@ public class SerializerGenerator extends Generator {
                 + "(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 {
@@ -373,10 +436,15 @@ public class SerializerGenerator extends Generator {
         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;
@@ -385,7 +453,6 @@ public class SerializerGenerator extends Generator {
     }
 
     public static String getFullyQualifiedSerializerClassName(JClassType type) {
-        return beanSerializerPackageName + "."
-                + getSerializerSimpleClassName(type);
+        return serializerPackageName + "." + getSerializerSimpleClassName(type);
     }
 }
index 268877543587da1378df668f629f83c419ce7b8b..5e151323a0832e3b0d9474b3cd7ec73b1666865a 100644 (file)
@@ -17,6 +17,7 @@ import com.google.gwt.core.ext.GeneratorContext;
 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;
@@ -96,6 +97,10 @@ public class SerializerMapGenerator extends Generator {
         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(
@@ -166,8 +171,15 @@ public class SerializerMapGenerator extends Generator {
 
         // 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);
@@ -277,6 +289,14 @@ public class SerializerMapGenerator extends Generator {
             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<?>>();
@@ -293,15 +313,14 @@ public class SerializerMapGenerator extends Generator {
         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;
         }
diff --git a/tests/testbench/com/vaadin/tests/serialization/SerializerTest.java b/tests/testbench/com/vaadin/tests/serialization/SerializerTest.java
new file mode 100644 (file)
index 0000000..0f7f5cc
--- /dev/null
@@ -0,0 +1,273 @@
+/* 
+@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);
+    }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/ComplexTestBean.java b/tests/testbench/com/vaadin/tests/widgetset/client/ComplexTestBean.java
new file mode 100644 (file)
index 0000000..e465ee2
--- /dev/null
@@ -0,0 +1,70 @@
+/* 
+@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 + "]";
+    }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestConnector.java b/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
new file mode 100644 (file)
index 0000000..72bfbe2
--- /dev/null
@@ -0,0 +1,227 @@
+/* 
+@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
+    }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestRpc.java b/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestRpc.java
new file mode 100644 (file)
index 0000000..5b73e1d
--- /dev/null
@@ -0,0 +1,64 @@
+/* 
+@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);
+
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/SimpleTestBean.java b/tests/testbench/com/vaadin/tests/widgetset/client/SimpleTestBean.java
new file mode 100644 (file)
index 0000000..43ad51e
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+@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
diff --git a/tests/testbench/com/vaadin/tests/widgetset/server/SerializerTestExtension.java b/tests/testbench/com/vaadin/tests/widgetset/server/SerializerTestExtension.java
new file mode 100644 (file)
index 0000000..99c05e8
--- /dev/null
@@ -0,0 +1,22 @@
+/* 
+@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);
+    }
+
+}