From 3702e37192c36203b74cb2694ba90a62266be079 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Fri, 1 Jun 2012 16:51:42 +0300 Subject: [PATCH] Pass declared types to JsonDecoder and use them (#8677) --- .../gwt/client/ApplicationConnection.java | 19 ++- .../gwt/client/communication/JsonDecoder.java | 126 +++++++++--------- .../URLReference_Serializer.java | 5 +- .../GeneratedRpcMethodProviderGenerator.java | 12 +- .../widgetsetutils/SerializerGenerator.java | 11 +- 5 files changed, 95 insertions(+), 78 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index c7ec5236b0..bf5c34f3f3 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -44,7 +44,9 @@ import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.communication.MethodInvocation; import com.vaadin.terminal.gwt.client.communication.RpcManager; import com.vaadin.terminal.gwt.client.communication.SerializerMap; +import com.vaadin.terminal.gwt.client.communication.SharedState; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.communication.Type; import com.vaadin.terminal.gwt.client.communication.UidlValue; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.terminal.gwt.client.ui.VContextMenu; @@ -1411,8 +1413,9 @@ public class ApplicationConnection { JSONArray stateDataAndType = new JSONArray( states.getJavaScriptObject(connectorId)); - JsonDecoder.decodeValue(stateDataAndType, - connector.getState(), + SharedState state = connector.getState(); + JsonDecoder.decodeValue(new Type(state.getClass() + .getName(), null), stateDataAndType, state, ApplicationConnection.this); StateChangeEvent event = GWT @@ -1575,13 +1578,19 @@ public class ApplicationConnection { String interfaceName = ((JSONString) rpcCall.get(1)).stringValue(); String methodName = ((JSONString) rpcCall.get(2)).stringValue(); JSONArray parametersJson = (JSONArray) rpcCall.get(3); + + MethodInvocation methodInvocation = new MethodInvocation(connectorId, + interfaceName, methodName); + Type[] parameterTypes = rpcManager.getParameterTypes(methodInvocation); + Object[] parameters = new Object[parametersJson.size()]; for (int j = 0; j < parametersJson.size(); ++j) { - parameters[j] = JsonDecoder.decodeValue( + parameters[j] = JsonDecoder.decodeValue(parameterTypes[j], (JSONArray) parametersJson.get(j), null, this); } - return new MethodInvocation(connectorId, interfaceName, methodName, - parameters); + + methodInvocation.setParameters(parameters); + return methodInvocation; } // Redirect browser, null reloads current page diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index 8d22481783..cd255ada95 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -19,6 +19,7 @@ import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.client.ServerConnector; @@ -48,75 +49,72 @@ public class JsonDecoder { * reference to the current ApplicationConnection * @return decoded value (does not contain JSON types) */ - public static Object decodeValue(JSONArray jsonArray, Object target, - ApplicationConnection connection) { - String type = ((JSONString) jsonArray.get(0)).stringValue(); + public static Object decodeValue(Type type, JSONArray jsonArray, + Object target, ApplicationConnection connection) { return decodeValue(type, jsonArray.get(1), target, connection); } - private static Object decodeValue(String variableType, JSONValue value, + private static Object decodeValue(Type type, JSONValue jsonValue, Object target, ApplicationConnection connection) { - Object val = null; - // TODO type checks etc. - if (JsonEncoder.VTYPE_NULL.equals(variableType)) { - val = null; - } else if (JsonEncoder.VTYPE_ARRAY.equals(variableType)) { - val = decodeArray((JSONArray) value, connection); - } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { - val = decodeMap((JSONObject) value, connection); - } else if (JsonEncoder.VTYPE_LIST.equals(variableType)) { - val = decodeList((JSONArray) value, connection); - } else if (JsonEncoder.VTYPE_SET.equals(variableType)) { - val = decodeSet((JSONArray) value, connection); - } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) { - val = decodeStringArray((JSONArray) value); - } else if (JsonEncoder.VTYPE_STRING.equals(variableType)) { - val = ((JSONString) value).stringValue(); - } else if (JsonEncoder.VTYPE_INTEGER.equals(variableType)) { - // TODO handle properly - val = Integer.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_LONG.equals(variableType)) { + + // Null is null, regardless of type + if (jsonValue.isNull() != null) { + return null; + } + + String baseTypeName = type.getBaseTypeName(); + if (baseTypeName.endsWith("[]")) { + return decodeArray(type, (JSONArray) jsonValue, connection); + } else if (Map.class.getName().equals(baseTypeName) + || HashMap.class.getName().equals(baseTypeName)) { + return decodeMap(type, (JSONObject) jsonValue, connection); + } else if (List.class.getName().equals(baseTypeName) + || ArrayList.class.getName().equals(baseTypeName)) { + return decodeList(type, (JSONArray) jsonValue, connection); + } else if (Set.class.getName().equals(baseTypeName)) { + return decodeSet(type, (JSONArray) jsonValue, connection); + } else if (String.class.getName().equals(baseTypeName)) { + return ((JSONString) jsonValue).stringValue(); + } else if (Integer.class.getName().equals(baseTypeName)) { + return Integer.valueOf(String.valueOf(jsonValue)); + } else if (Long.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Long.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_FLOAT.equals(variableType)) { + return Long.valueOf(String.valueOf(jsonValue)); + } else if (Float.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Float.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_DOUBLE.equals(variableType)) { + return Float.valueOf(String.valueOf(jsonValue)); + } else if (Double.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Double.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_BOOLEAN.equals(variableType)) { + return Double.valueOf(String.valueOf(jsonValue)); + } else if (Boolean.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Boolean.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) { - val = ConnectorMap.get(connection).getConnector( - ((JSONString) value).stringValue()); + return Boolean.valueOf(String.valueOf(jsonValue)); + } else if (Connector.class.getName().equals(baseTypeName)) { + return ConnectorMap.get(connection).getConnector( + ((JSONString) jsonValue).stringValue()); } else { - return decodeObject(new Type(variableType, null), value, target, - connection); + return decodeObject(type, jsonValue, target, connection); } - - return val; } - private static Object decodeObject(Type type, JSONValue encodedValue, + private static Object decodeObject(Type type, JSONValue jsonValue, Object target, ApplicationConnection connection) { - // object, class name as type JSONSerializer serializer = connection.getSerializerMap() .getSerializer(type.getBaseTypeName()); // TODO handle case with no serializer found + // Currently getSerializer throws exception if not found if (target != null && serializer instanceof DiffJSONSerializer) { DiffJSONSerializer diffSerializer = (DiffJSONSerializer) serializer; - diffSerializer.update(target, type, encodedValue, connection); + diffSerializer.update(target, type, jsonValue, connection); return target; } else { - Object object = serializer.deserialize(type, encodedValue, - connection); + Object object = serializer.deserialize(type, jsonValue, connection); return object; } } - private static Map decodeMap(JSONObject jsonMap, + private static Map decodeMap(Type type, JSONObject jsonMap, ApplicationConnection connection) { HashMap map = new HashMap(); Iterator it = jsonMap.keySet().iterator(); @@ -124,48 +122,48 @@ public class JsonDecoder { String key = it.next(); JSONArray encodedKey = (JSONArray) JSONParser.parseStrict(key); JSONArray encodedValue = (JSONArray) jsonMap.get(key); - Object decodedKey = decodeValue(encodedKey, null, connection); - Object decodedValue = decodeValue(encodedValue, null, connection); + Object decodedKey = decodeValue(type.getParameterTypes()[0], + encodedKey, null, connection); + Object decodedValue = decodeValue(type.getParameterTypes()[1], + encodedValue, null, connection); map.put(decodedKey, decodedValue); } return map; } - private static String[] decodeStringArray(JSONArray jsonArray) { - int size = jsonArray.size(); - List tokens = new ArrayList(size); - for (int i = 0; i < size; ++i) { - tokens.add(String.valueOf(jsonArray.get(i))); - } - return tokens.toArray(new String[tokens.size()]); - } - - private static Object[] decodeArray(JSONArray jsonArray, + private static Object[] decodeArray(Type type, JSONArray jsonArray, ApplicationConnection connection) { - List list = decodeList(jsonArray, connection); + String arrayTypeName = type.getBaseTypeName(); + String chldTypeName = arrayTypeName.substring(0, + arrayTypeName.length() - 2); + List list = decodeList(new Type(chldTypeName, null), jsonArray, + connection); return list.toArray(new Object[list.size()]); } - private static List decodeList(JSONArray jsonArray, + private static List decodeList(Type type, JSONArray jsonArray, ApplicationConnection connection) { List tokens = new ArrayList(); - decodeIntoCollection(jsonArray, connection, tokens); + decodeIntoCollection(type.getParameterTypes()[0], jsonArray, + connection, tokens); return tokens; } - private static Set decodeSet(JSONArray jsonArray, + private static Set decodeSet(Type type, JSONArray jsonArray, ApplicationConnection connection) { Set tokens = new HashSet(); - decodeIntoCollection(jsonArray, connection, tokens); + decodeIntoCollection(type.getParameterTypes()[0], jsonArray, + connection, tokens); return tokens; } - private static void decodeIntoCollection(JSONArray jsonArray, - ApplicationConnection connection, Collection tokens) { + private static void decodeIntoCollection(Type childType, + JSONArray jsonArray, ApplicationConnection connection, + Collection tokens) { 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, null, connection)); + tokens.add(decodeValue(childType, entryArray, null, connection)); } } } diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java index 1ae8cc4755..5db487d867 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -18,8 +18,9 @@ public class URLReference_Serializer implements JSONSerializer { JSONObject json = (JSONObject) jsonValue; if (json.containsKey("URL")) { JSONArray jsonURL = (JSONArray) json.get("URL"); - String URL = (String) JsonDecoder.decodeValue(jsonURL, null, - connection); + String URL = (String) JsonDecoder.decodeValue( + new Type(String.class.getCanonicalName(), null), jsonURL, + null, connection); reference.setURL(connection.translateVaadinUri(URL)); } return reference; diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java index f0db4886e4..ba3dcd85b9 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java @@ -178,9 +178,15 @@ public class GeneratedRpcMethodProviderGenerator extends Generator { } - private void writeTypeCreator(SourceWriter sourceWriter, JType type) { - sourceWriter.print("new Type(\"" - + type.getErasedType().getQualifiedSourceName() + "\", "); + 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(); + } + sourceWriter.print("new Type(\"" + typeName + "\", "); JParameterizedType parameterized = type.isParameterized(); if (parameterized != null) { sourceWriter.print("new Type[] {"); diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index 6aa6b073ee..8e34e28999 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -260,13 +260,16 @@ public class SerializerGenerator extends Generator { // target.setHeight((String) // JsonDecoder.decodeValue(jsonFieldValue,referenceValue, idMapper, // connection)); - sourceWriter.println("target." + setterName + "((" + fieldType - + ") " + JsonDecoder.class.getName() + ".decodeValue(" - + jsonFieldName + ", referenceValue, connection));"); + sourceWriter.print("target." + setterName + "((" + fieldType + ") " + + JsonDecoder.class.getName() + ".decodeValue("); + GeneratedRpcMethodProviderGenerator.writeTypeCreator(sourceWriter, + setterParameterType); + sourceWriter.println(", " + jsonFieldName + + ", referenceValue, connection));"); // } ... end of if contains - sourceWriter.println("}"); sourceWriter.outdent(); + sourceWriter.println("}"); } if (!update) { -- 2.39.5