This is work in progress towards using declared types for data received from the server.tags/7.0.0.alpha3
@@ -1412,7 +1412,7 @@ public class ApplicationConnection { | |||
states.getJavaScriptObject(connectorId)); | |||
JsonDecoder.decodeValue(stateDataAndType, | |||
connector.getState(), connectorMap, | |||
connector.getState(), | |||
ApplicationConnection.this); | |||
StateChangeEvent event = GWT | |||
@@ -1578,8 +1578,7 @@ public class ApplicationConnection { | |||
Object[] parameters = new Object[parametersJson.size()]; | |||
for (int j = 0; j < parametersJson.size(); ++j) { | |||
parameters[j] = JsonDecoder.decodeValue( | |||
(JSONArray) parametersJson.get(j), null, getConnectorMap(), | |||
this); | |||
(JSONArray) parametersJson.get(j), null, this); | |||
} | |||
return new MethodInvocation(connectorId, interfaceName, methodName, | |||
parameters); |
@@ -0,0 +1,19 @@ | |||
/* | |||
@VaadinApache2LicenseForJavaFiles@ | |||
*/ | |||
package com.vaadin.terminal.gwt.client.communication; | |||
import com.google.gwt.json.client.JSONValue; | |||
import com.vaadin.terminal.gwt.client.ApplicationConnection; | |||
public interface DiffJSONSerializer<T> extends JSONSerializer<T> { | |||
/** | |||
* Update the target object in place based on the passed JSON data. | |||
* | |||
* @param target | |||
* @param jsonValue | |||
* @param connection | |||
*/ | |||
public void update(T target, Type type, JSONValue jsonValue, | |||
ApplicationConnection connection); | |||
} |
@@ -34,14 +34,9 @@ public interface JSONSerializer<T> { | |||
* | |||
* @param jsonValue | |||
* JSON map from property name to property value | |||
* @param target | |||
* The object to write the deserialized values to | |||
* @param idMapper | |||
* mapper from paintable id to paintable, used to decode | |||
* references to paintables | |||
* @return A deserialized object | |||
*/ | |||
T deserialize(JSONValue jsonValue, T target, ConnectorMap idMapper, | |||
T deserialize(Type type, JSONValue jsonValue, | |||
ApplicationConnection connection); | |||
/** |
@@ -49,26 +49,25 @@ public class JsonDecoder { | |||
* @return decoded value (does not contain JSON types) | |||
*/ | |||
public static Object decodeValue(JSONArray jsonArray, Object target, | |||
ConnectorMap idMapper, ApplicationConnection connection) { | |||
ApplicationConnection connection) { | |||
String type = ((JSONString) jsonArray.get(0)).stringValue(); | |||
return decodeValue(type, jsonArray.get(1), target, idMapper, connection); | |||
return decodeValue(type, jsonArray.get(1), target, connection); | |||
} | |||
private static Object decodeValue(String variableType, JSONValue value, | |||
Object target, ConnectorMap idMapper, | |||
ApplicationConnection connection) { | |||
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, idMapper, connection); | |||
val = decodeArray((JSONArray) value, connection); | |||
} else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { | |||
val = decodeMap((JSONObject) value, idMapper, connection); | |||
val = decodeMap((JSONObject) value, connection); | |||
} else if (JsonEncoder.VTYPE_LIST.equals(variableType)) { | |||
val = decodeList((JSONArray) value, idMapper, connection); | |||
val = decodeList((JSONArray) value, connection); | |||
} else if (JsonEncoder.VTYPE_SET.equals(variableType)) { | |||
val = decodeSet((JSONArray) value, idMapper, connection); | |||
val = decodeSet((JSONArray) value, connection); | |||
} else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) { | |||
val = decodeStringArray((JSONArray) value); | |||
} else if (JsonEncoder.VTYPE_STRING.equals(variableType)) { | |||
@@ -89,39 +88,44 @@ public class JsonDecoder { | |||
// TODO handle properly | |||
val = Boolean.valueOf(String.valueOf(value)); | |||
} else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) { | |||
val = idMapper.getConnector(((JSONString) value).stringValue()); | |||
val = ConnectorMap.get(connection).getConnector( | |||
((JSONString) value).stringValue()); | |||
} else { | |||
return decodeObject(variableType, value, target, idMapper, | |||
return decodeObject(new Type(variableType, null), value, target, | |||
connection); | |||
} | |||
return val; | |||
} | |||
private static Object decodeObject(String variableType, | |||
JSONValue encodedValue, Object target, ConnectorMap idMapper, | |||
ApplicationConnection connection) { | |||
private static Object decodeObject(Type type, JSONValue encodedValue, | |||
Object target, ApplicationConnection connection) { | |||
// object, class name as type | |||
JSONSerializer<Object> serializer = connection.getSerializerMap() | |||
.getSerializer(variableType); | |||
.getSerializer(type.getBaseTypeName()); | |||
// TODO handle case with no serializer found | |||
Object object = serializer.deserialize(encodedValue, target, idMapper, | |||
connection); | |||
return object; | |||
if (target != null && serializer instanceof DiffJSONSerializer<?>) { | |||
DiffJSONSerializer<Object> diffSerializer = (DiffJSONSerializer<Object>) serializer; | |||
diffSerializer.update(target, type, encodedValue, connection); | |||
return target; | |||
} else { | |||
Object object = serializer.deserialize(type, encodedValue, | |||
connection); | |||
return object; | |||
} | |||
} | |||
private static Map<Object, Object> decodeMap(JSONObject jsonMap, | |||
ConnectorMap idMapper, ApplicationConnection connection) { | |||
ApplicationConnection connection) { | |||
HashMap<Object, Object> map = new HashMap<Object, Object>(); | |||
Iterator<String> it = jsonMap.keySet().iterator(); | |||
while (it.hasNext()) { | |||
String key = it.next(); | |||
JSONArray encodedKey = (JSONArray) JSONParser.parseStrict(key); | |||
JSONArray encodedValue = (JSONArray) jsonMap.get(key); | |||
Object decodedKey = decodeValue(encodedKey, null, idMapper, | |||
connection); | |||
Object decodedValue = decodeValue(encodedValue, null, idMapper, | |||
connection); | |||
Object decodedKey = decodeValue(encodedKey, null, connection); | |||
Object decodedValue = decodeValue(encodedValue, null, connection); | |||
map.put(decodedKey, decodedValue); | |||
} | |||
return map; | |||
@@ -137,32 +141,31 @@ public class JsonDecoder { | |||
} | |||
private static Object[] decodeArray(JSONArray jsonArray, | |||
ConnectorMap idMapper, ApplicationConnection connection) { | |||
List<Object> list = decodeList(jsonArray, idMapper, connection); | |||
ApplicationConnection connection) { | |||
List<Object> list = decodeList(jsonArray, connection); | |||
return list.toArray(new Object[list.size()]); | |||
} | |||
private static List<Object> decodeList(JSONArray jsonArray, | |||
ConnectorMap idMapper, ApplicationConnection connection) { | |||
ApplicationConnection connection) { | |||
List<Object> tokens = new ArrayList<Object>(); | |||
decodeIntoCollection(jsonArray, idMapper, connection, tokens); | |||
decodeIntoCollection(jsonArray, connection, tokens); | |||
return tokens; | |||
} | |||
private static Set<Object> decodeSet(JSONArray jsonArray, | |||
ConnectorMap idMapper, ApplicationConnection connection) { | |||
ApplicationConnection connection) { | |||
Set<Object> tokens = new HashSet<Object>(); | |||
decodeIntoCollection(jsonArray, idMapper, connection, tokens); | |||
decodeIntoCollection(jsonArray, connection, tokens); | |||
return tokens; | |||
} | |||
private static void decodeIntoCollection(JSONArray jsonArray, | |||
ConnectorMap idMapper, ApplicationConnection connection, | |||
Collection<Object> tokens) { | |||
ApplicationConnection connection, Collection<Object> 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, idMapper, connection)); | |||
tokens.add(decodeValue(entryArray, null, connection)); | |||
} | |||
} | |||
} |
@@ -12,14 +12,14 @@ import com.vaadin.terminal.gwt.client.ConnectorMap; | |||
public class URLReference_Serializer implements JSONSerializer<URLReference> { | |||
public URLReference deserialize(JSONValue jsonValue, URLReference target, | |||
ConnectorMap idMapper, ApplicationConnection connection) { | |||
public URLReference deserialize(Type type, JSONValue jsonValue, | |||
ApplicationConnection connection) { | |||
URLReference reference = GWT.create(URLReference.class); | |||
JSONObject json = (JSONObject) jsonValue; | |||
if (json.containsKey("URL")) { | |||
JSONArray jsonURL = (JSONArray) json.get("URL"); | |||
String URL = (String) JsonDecoder.decodeValue(jsonURL, null, | |||
idMapper, connection); | |||
connection); | |||
reference.setURL(connection.translateVaadinUri(URL)); | |||
} | |||
return reference; |
@@ -30,6 +30,7 @@ import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; | |||
import com.google.gwt.user.rebind.SourceWriter; | |||
import com.vaadin.terminal.gwt.client.ApplicationConnection; | |||
import com.vaadin.terminal.gwt.client.ConnectorMap; | |||
import com.vaadin.terminal.gwt.client.communication.DiffJSONSerializer; | |||
import com.vaadin.terminal.gwt.client.communication.JSONSerializer; | |||
import com.vaadin.terminal.gwt.client.communication.JsonDecoder; | |||
import com.vaadin.terminal.gwt.client.communication.JsonEncoder; | |||
@@ -107,13 +108,20 @@ public class SerializerGenerator extends Generator { | |||
serializerClassName); | |||
composer.addImport(GWT.class.getName()); | |||
composer.addImport(JSONArray.class.getName()); | |||
composer.addImport(com.vaadin.terminal.gwt.client.communication.Type.class | |||
.getName()); | |||
// composer.addImport(JSONObject.class.getName()); | |||
// composer.addImport(VPaintableMap.class.getName()); | |||
composer.addImport(JsonDecoder.class.getName()); | |||
// composer.addImport(VaadinSerializer.class.getName()); | |||
composer.addImplementedInterface(JSONSerializer.class.getName() + "<" | |||
+ beanQualifiedSourceName + ">"); | |||
if (isEnum) { | |||
composer.addImplementedInterface(JSONSerializer.class.getName() | |||
+ "<" + beanQualifiedSourceName + ">"); | |||
} else { | |||
composer.addImplementedInterface(DiffJSONSerializer.class.getName() | |||
+ "<" + beanQualifiedSourceName + ">"); | |||
} | |||
SourceWriter sourceWriter = composer.createSourceWriter(context, | |||
printWriter); | |||
@@ -138,20 +146,39 @@ public class SerializerGenerator extends Generator { | |||
writeBeanSerializer(logger, sourceWriter, beanType); | |||
} | |||
// } | |||
sourceWriter.outdent(); | |||
sourceWriter.println("}"); | |||
sourceWriter.println(); | |||
// 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) {"); | |||
sourceWriter.indent(); | |||
writeBeanDeserializer(logger, sourceWriter, beanType, true); | |||
sourceWriter.outdent(); | |||
sourceWriter.println("}"); | |||
} | |||
// Deserializer | |||
// T deserialize(Type type, JSONValue jsonValue, ApplicationConnection | |||
// connection); | |||
sourceWriter.println("public " + beanQualifiedSourceName | |||
+ " deserialize(" + JSONValue.class.getName() + " jsonValue, " | |||
+ beanQualifiedSourceName + " target, " | |||
+ ConnectorMap.class.getName() + " idMapper, " | |||
+ ApplicationConnection.class.getName() + " connection) {"); | |||
+ " deserialize(Type type, " + JSONValue.class.getName() | |||
+ " jsonValue, " + ApplicationConnection.class.getName() | |||
+ " connection) {"); | |||
sourceWriter.indent(); | |||
if (isEnum) { | |||
writeEnumDeserializer(logger, sourceWriter, beanType.isEnum()); | |||
} else { | |||
writeBeanDeserializer(logger, sourceWriter, beanType); | |||
writeBeanDeserializer(logger, sourceWriter, beanType, false); | |||
} | |||
sourceWriter.println("}"); | |||
sourceWriter.outdent(); | |||
@@ -183,18 +210,14 @@ public class SerializerGenerator extends Generator { | |||
} | |||
private void writeBeanDeserializer(TreeLogger logger, | |||
SourceWriter sourceWriter, JClassType beanType) { | |||
SourceWriter sourceWriter, JClassType beanType, boolean update) { | |||
String beanQualifiedSourceName = beanType.getQualifiedSourceName(); | |||
// if (target == null) { | |||
sourceWriter.println("if (target == null) {"); | |||
sourceWriter.indent(); | |||
// target = GWT.create(VButtonState.class); | |||
sourceWriter.println("target = GWT.create(" + beanQualifiedSourceName | |||
+ ".class);"); | |||
sourceWriter.outdent(); | |||
sourceWriter.println("}"); | |||
if (!update) { | |||
sourceWriter.println(beanQualifiedSourceName | |||
+ " target = GWT.create(" + beanQualifiedSourceName | |||
+ ".class);"); | |||
} | |||
// JSONOBject json = (JSONObject)jsonValue; | |||
sourceWriter.println(JSONObject.class.getName() + " json = (" | |||
@@ -230,37 +253,26 @@ public class SerializerGenerator extends Generator { | |||
fieldType = setterParameterType.getQualifiedSourceName(); | |||
} | |||
// String referenceValue; | |||
sourceWriter.println(fieldType + " referenceValue;"); | |||
// if (target == null) { | |||
sourceWriter.println("if (target == null) {"); | |||
sourceWriter.indent(); | |||
// referenceValue = null; | |||
sourceWriter.println("referenceValue = null;"); | |||
// } else { | |||
sourceWriter.println("} else {"); | |||
// referenceValue = target.getHeight(); | |||
sourceWriter.println("referenceValue = target." + getterName | |||
+ "();"); | |||
// } | |||
sourceWriter.outdent(); | |||
sourceWriter.println("}"); | |||
// String referenceValue = target.getHeight(); | |||
sourceWriter.println(fieldType + " referenceValue = target." | |||
+ getterName + "();"); | |||
// target.setHeight((String) | |||
// JsonDecoder.decodeValue(jsonFieldValue,referenceValue, idMapper, | |||
// connection)); | |||
sourceWriter.println("target." + setterName + "((" + fieldType | |||
+ ") " + JsonDecoder.class.getName() + ".decodeValue(" | |||
+ jsonFieldName | |||
+ ", referenceValue, idMapper, connection));"); | |||
+ jsonFieldName + ", referenceValue, connection));"); | |||
// } ... end of if contains | |||
sourceWriter.println("}"); | |||
sourceWriter.outdent(); | |||
} | |||
// return target; | |||
sourceWriter.println("return target;"); | |||
if (!update) { | |||
// return target; | |||
sourceWriter.println("return target;"); | |||
} | |||
} | |||