]> source.dussan.org Git - vaadin-framework.git/commitdiff
#8515 Additional fix for sets, and lists from client to server
authorArtur Signell <artur@vaadin.com>
Mon, 19 Mar 2012 13:46:24 +0000 (15:46 +0200)
committerArtur Signell <artur@vaadin.com>
Wed, 21 Mar 2012 13:27:46 +0000 (15:27 +0200)
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/SerializerGenerator.java
src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java

index 4bc9431d49da521c9914695030c299af9896cf48..86a64cb47cfea3cfd64a2a2fe52504e539ec283b 100644 (file)
@@ -6,9 +6,11 @@ package com.vaadin.terminal.gwt.client.communication;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.json.client.JSONArray;
@@ -63,6 +65,8 @@ public class JsonDecoder {
             val = decodeMap((JSONObject) value, idMapper, connection);
         } else if (JsonEncoder.VTYPE_LIST.equals(variableType)) {
             val = decodeList((JSONArray) value, idMapper, connection);
+        } else if (JsonEncoder.VTYPE_SET.equals(variableType)) {
+            val = decodeSet((JSONArray) value, idMapper, connection);
         } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) {
             val = decodeStringArray((JSONArray) value);
         } else if (JsonEncoder.VTYPE_STRING.equals(variableType)) {
@@ -135,4 +139,15 @@ public class JsonDecoder {
         }
         return tokens;
     }
+
+    private static Set<Object> decodeSet(JSONArray jsonArray,
+            ConnectorMap idMapper, ApplicationConnection connection) {
+        Set<Object> tokens = new HashSet<Object>();
+        for (int i = 0; i < jsonArray.size(); ++i) {
+            // each entry always has two elements: type and value
+            JSONArray entryArray = (JSONArray) jsonArray.get(i);
+            tokens.add(decodeValue(entryArray, idMapper, connection));
+        }
+        return tokens;
+    }
 }
index cc8b36dfa4a37e7ae9fb744d7a55eb04746542ff..121574379081918f4cc888cc52a25cc8d92208f7 100644 (file)
@@ -4,8 +4,10 @@
 
 package com.vaadin.terminal.gwt.client.communication;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONBoolean;
@@ -41,6 +43,7 @@ public class JsonEncoder {
     public static final String VTYPE_STRINGARRAY = "S";
     public static final String VTYPE_MAP = "m";
     public static final String VTYPE_LIST = "L";
+    public static final String VTYPE_SET = "q";
     public static final String VTYPE_NULL = "n";
 
     /**
@@ -72,13 +75,7 @@ public class JsonEncoder {
             return combineTypeAndValue(VTYPE_BOOLEAN,
                     JSONBoolean.getInstance((Boolean) value));
         } else if (value instanceof Object[]) {
-            Object[] array = (Object[]) value;
-            JSONArray jsonArray = new JSONArray();
-            for (int i = 0; i < array.length; ++i) {
-                // TODO handle object graph loops?
-                jsonArray.set(i, encode(array[i], connectorMap, connection));
-            }
-            return combineTypeAndValue(VTYPE_ARRAY, jsonArray);
+            return encodeObjectArray((Object[]) value, connectorMap, connection);
         } else if (value instanceof Map) {
             Map<String, Object> map = (Map<String, Object>) value;
             JSONObject jsonMap = new JSONObject();
@@ -92,6 +89,9 @@ public class JsonEncoder {
             Connector connector = (Connector) value;
             return combineTypeAndValue(VTYPE_CONNECTOR, new JSONString(
                     connector.getConnectorId()));
+        } else if (value instanceof Collection) {
+            return encodeCollection((Collection) value, connectorMap,
+                    connection);
         } else {
             String transportType = getTransportType(value);
             if (transportType != null) {
@@ -111,6 +111,35 @@ public class JsonEncoder {
         }
     }
 
+    private static JSONValue encodeObjectArray(Object[] array,
+            ConnectorMap connectorMap, ApplicationConnection connection) {
+        JSONArray jsonArray = new JSONArray();
+        for (int i = 0; i < array.length; ++i) {
+            // TODO handle object graph loops?
+            jsonArray.set(i, encode(array[i], connectorMap, connection));
+        }
+        return combineTypeAndValue(VTYPE_ARRAY, jsonArray);
+    }
+
+    private static JSONValue encodeCollection(Collection collection,
+            ConnectorMap connectorMap, ApplicationConnection connection) {
+        JSONArray jsonArray = new JSONArray();
+        int idx = 0;
+        for (Object o : collection) {
+            JSONValue encodedObject = encode(o, connectorMap, connection);
+            jsonArray.set(idx++, encodedObject);
+        }
+        if (collection instanceof Set) {
+            return combineTypeAndValue(VTYPE_SET, jsonArray);
+        } else if (collection instanceof List) {
+            return combineTypeAndValue(VTYPE_LIST, jsonArray);
+        } else {
+            throw new RuntimeException("Unsupport collection type: "
+                    + collection.getClass().getName());
+        }
+
+    }
+
     private static JSONValue combineTypeAndValue(String type, JSONValue value) {
         JSONArray outerArray = new JSONArray();
         outerArray.set(0, new JSONString(type));
@@ -137,6 +166,8 @@ public class JsonEncoder {
             return VTYPE_LONG;
         } else if (value instanceof List) {
             return VTYPE_LIST;
+        } else if (value instanceof Set) {
+            return VTYPE_SET;
         } else if (value instanceof Enum) {
             return VTYPE_STRING; // transported as string representation
         } else if (value instanceof String[]) {
index 9fea64a1c7e44759c43c7485a24e5db9cc93c053..402d219a70e6a5a519656fae65c7e7958a493b67 100644 (file)
@@ -11,10 +11,13 @@ import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import com.vaadin.Application;
 import com.vaadin.external.json.JSONArray;
@@ -38,16 +41,22 @@ public class JsonCodec implements Serializable {
         registerType(String.class, JsonEncoder.VTYPE_STRING);
         registerType(Connector.class, JsonEncoder.VTYPE_CONNECTOR);
         registerType(Boolean.class, JsonEncoder.VTYPE_BOOLEAN);
+        registerType(boolean.class, JsonEncoder.VTYPE_BOOLEAN);
         registerType(Integer.class, JsonEncoder.VTYPE_INTEGER);
+        registerType(int.class, JsonEncoder.VTYPE_INTEGER);
         registerType(Float.class, JsonEncoder.VTYPE_FLOAT);
+        registerType(float.class, JsonEncoder.VTYPE_FLOAT);
         registerType(Double.class, JsonEncoder.VTYPE_DOUBLE);
+        registerType(double.class, JsonEncoder.VTYPE_FLOAT);
         registerType(Long.class, JsonEncoder.VTYPE_LONG);
+        registerType(long.class, JsonEncoder.VTYPE_LONG);
         // transported as string representation
         registerType(Enum.class, JsonEncoder.VTYPE_STRING);
         registerType(String[].class, JsonEncoder.VTYPE_STRINGARRAY);
         registerType(Object[].class, JsonEncoder.VTYPE_ARRAY);
         registerType(Map.class, JsonEncoder.VTYPE_MAP);
         registerType(List.class, JsonEncoder.VTYPE_LIST);
+        registerType(Set.class, JsonEncoder.VTYPE_SET);
     }
 
     private static void registerType(Class<?> type, String transportType) {
@@ -80,6 +89,8 @@ public class JsonCodec implements Serializable {
             val = decodeArray((JSONArray) value, application);
         } else if (JsonEncoder.VTYPE_LIST.equals(variableType)) {
             val = decodeList((JSONArray) value, application);
+        } else if (JsonEncoder.VTYPE_SET.equals(variableType)) {
+            val = decodeSet((JSONArray) value, application);
         } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) {
             val = decodeMap((JSONObject) value, application);
         } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) {
@@ -141,8 +152,8 @@ public class JsonCodec implements Serializable {
         return list.toArray(new Object[list.size()]);
     }
 
-    private static List decodeList(JSONArray jsonArray, Application application)
-            throws JSONException {
+    private static List<Object> decodeList(JSONArray jsonArray,
+            Application application) throws JSONException {
         List<Object> list = new ArrayList<Object>();
         for (int i = 0; i < jsonArray.length(); ++i) {
             // each entry always has two elements: type and value
@@ -152,6 +163,13 @@ public class JsonCodec implements Serializable {
         return list;
     }
 
+    private static Set<Object> decodeSet(JSONArray jsonArray,
+            Application application) throws JSONException {
+        HashSet<Object> set = new HashSet<Object>();
+        set.addAll(decodeList(jsonArray, application));
+        return set;
+    }
+
     /**
      * Encode a value to a JSON representation for transport from the server to
      * the client.
@@ -174,7 +192,14 @@ public class JsonCodec implements Serializable {
 
         if (null == value) {
             return combineTypeAndValue(JsonEncoder.VTYPE_NULL, JSONObject.NULL);
-        } else if (value instanceof String[]) {
+        }
+
+        if (valueType == null) {
+            valueType = value.getClass();
+        }
+
+        String transportType = getTransportType(valueType);
+        if (value instanceof String[]) {
             String[] array = (String[]) value;
             JSONArray jsonArray = new JSONArray();
             for (int i = 0; i < array.length; ++i) {
@@ -186,11 +211,16 @@ public class JsonCodec implements Serializable {
         } else if (value instanceof Boolean) {
             return combineTypeAndValue(JsonEncoder.VTYPE_BOOLEAN, value);
         } else if (value instanceof Number) {
-            return combineTypeAndValue(getTransportType(value), value);
-        } else if (value instanceof List) {
-            List list = (List) value;
-            JSONArray jsonArray = encodeList(list, application);
-            return combineTypeAndValue(JsonEncoder.VTYPE_LIST, jsonArray);
+            return combineTypeAndValue(transportType, value);
+        } else if (value instanceof Collection) {
+            if (transportType == null) {
+                throw new RuntimeException(
+                        "Unable to serialize unsupported type: " + valueType);
+            }
+            Collection<?> collection = (Collection<?>) value;
+            JSONArray jsonArray = encodeCollection(collection, application);
+
+            return combineTypeAndValue(transportType, jsonArray);
         } else if (value instanceof Object[]) {
             Object[] array = (Object[]) value;
             JSONArray jsonArray = encodeArrayContents(array, application);
@@ -203,16 +233,11 @@ public class JsonCodec implements Serializable {
             Connector connector = (Connector) value;
             return combineTypeAndValue(JsonEncoder.VTYPE_CONNECTOR,
                     connector.getConnectorId());
-        } else if (getTransportType(value) != null) {
-            return combineTypeAndValue(getTransportType(value),
-                    String.valueOf(value));
+        } else if (transportType != null) {
+            return combineTypeAndValue(transportType, String.valueOf(value));
         } else {
             // Any object that we do not know how to encode we encode by looping
             // through fields
-            if (valueType == null) {
-                valueType = value.getClass();
-            }
-
             return combineTypeAndValue(valueType.getCanonicalName(),
                     encodeObject(value, application));
         }
@@ -290,10 +315,10 @@ public class JsonCodec implements Serializable {
         return jsonArray;
     }
 
-    private static JSONArray encodeList(List list, Application application)
-            throws JSONException {
+    private static JSONArray encodeCollection(Collection collection,
+            Application application) throws JSONException {
         JSONArray jsonArray = new JSONArray();
-        for (Object o : list) {
+        for (Object o : collection) {
             // TODO handle object graph loops?
             jsonArray.put(encode(o, application));
         }
@@ -312,6 +337,10 @@ public class JsonCodec implements Serializable {
     }
 
     private static JSONArray combineTypeAndValue(String type, Object value) {
+        if (type == null) {
+            throw new RuntimeException("Type for value " + value
+                    + " cannot be null!");
+        }
         JSONArray outerArray = new JSONArray();
         outerArray.put(type);
         outerArray.put(value);
@@ -326,12 +355,25 @@ public class JsonCodec implements Serializable {
      * @return
      * @throws JSONException
      */
-    private static String getTransportType(Object value) throws JSONException {
+    private static String getTransportType(Object value) {
         if (null == value) {
             return JsonEncoder.VTYPE_NULL;
         }
-        String transportType = typeToTransportType.get(value.getClass());
-        return transportType;
+        return getTransportType(value.getClass());
+    }
+
+    /**
+     * Gets the transport type for the given class. Returns null if no transport
+     * type can be found.
+     * 
+     * @param valueType
+     *            The type that should be transported
+     * @return
+     * @throws JSONException
+     */
+    private static String getTransportType(Class<?> valueType) {
+        return typeToTransportType.get(valueType);
+
     }
 
 }
index bb0543296494340e62e49b7e7ca365ca6c0f2e79..0fe5a38096f010a52dfa70a5113a3c4f9273f936 100644 (file)
@@ -230,8 +230,9 @@ public class SerializerGenerator extends Generator {
 
         List<JMethod> setterMethods = new ArrayList<JMethod>();
 
-        while (!beanType.getQualifiedSourceName()
-                .equals(Object.class.getName())) {
+        while (beanType != null
+                && !beanType.getQualifiedSourceName().equals(
+                        Object.class.getName())) {
             for (JMethod method : beanType.getMethods()) {
                 // Process all setters that have corresponding fields
                 if (!method.isPublic() || method.isStatic()
index 52b599253f8c843c04b78621035f53bcd786f0ed..420c3ae6e7fc1c03135068b137193f7d1edbfae8 100644 (file)
@@ -7,6 +7,7 @@ package com.vaadin.terminal.gwt.widgetsetutils;
 import java.io.PrintWriter;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -199,7 +200,16 @@ public class SerializerMapGenerator extends Generator {
                 continue;
             }
             for (JType type : method.getParameterTypes()) {
-                types.add(type.isClass());
+                JClassType t = type.isClass();
+                JClassType interfaceType = type.isInterface();
+                if (t != null) {
+                    types.add(t);
+                } else if (interfaceType != null) {
+                    types.add(interfaceType);
+                } else {
+                    System.err.println("Unknown method parameter type: "
+                            + type.getQualifiedSourceName());
+                }
             }
         }
     }
@@ -242,6 +252,8 @@ public class SerializerMapGenerator extends Generator {
         frameworkHandledTypes.add(String[].class);
         frameworkHandledTypes.add(Object[].class);
         frameworkHandledTypes.add(Map.class);
+        frameworkHandledTypes.add(List.class);
+        frameworkHandledTypes.add(Set.class);
 
     }