Browse Source

Add DiffJSONSerializer for updating existing objects (#8879)

This is work in progress towards using declared types for data received
from the server.
tags/7.0.0.alpha3
Leif Åstrand 12 years ago
parent
commit
694a588f94

+ 2
- 3
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java View File

@@ -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);

+ 19
- 0
src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java View File

@@ -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);
}

+ 1
- 6
src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java View File

@@ -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);

/**

+ 34
- 31
src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java View File

@@ -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));
}
}
}

+ 3
- 3
src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java View File

@@ -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;

+ 48
- 36
src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java View File

@@ -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;");
}

}


Loading…
Cancel
Save