From 43794ef1b830047e6a5d8270efb86abde56c0e0c Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 4 May 2012 00:28:25 +0300 Subject: [PATCH] Added support for serializing enums (#8675) Changed JSONSerializer to use JSONValue instead of JSONObject --- .../client/communication/JSONSerializer.java | 5 +- .../gwt/client/communication/JsonDecoder.java | 9 +- .../gwt/client/communication/JsonEncoder.java | 11 +- .../URLReference_Serializer.java | 10 +- .../vaadin/terminal/gwt/server/JsonCodec.java | 18 +++ .../widgetsetutils/SerializerGenerator.java | 131 ++++++++++++------ .../SerializerMapGenerator.java | 3 - 7 files changed, 133 insertions(+), 54 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java b/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java index 5f82e339f4..f7b3df6b05 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java @@ -5,6 +5,7 @@ package com.vaadin.terminal.gwt.client.communication; import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.server.JsonCodec; @@ -40,7 +41,7 @@ public interface JSONSerializer { * references to paintables * @return A deserialized object */ - T deserialize(JSONObject jsonValue, T target, ConnectorMap idMapper, + T deserialize(JSONValue jsonValue, T target, ConnectorMap idMapper, ApplicationConnection connection); /** @@ -56,7 +57,7 @@ public interface JSONSerializer { * references to paintables * @return A JSON serialized version of the object */ - JSONObject serialize(T value, ConnectorMap idMapper, + JSONValue serialize(T value, ConnectorMap idMapper, ApplicationConnection connection); } diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index 790b5cb305..d7cf764f75 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -15,6 +15,7 @@ import java.util.Set; 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; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.ConnectorMap; @@ -52,7 +53,7 @@ public class JsonDecoder { return decodeValue(type, jsonArray.get(1), target, idMapper, connection); } - private static Object decodeValue(String variableType, Object value, + private static Object decodeValue(String variableType, JSONValue value, Object target, ConnectorMap idMapper, ApplicationConnection connection) { Object val = null; @@ -91,15 +92,15 @@ public class JsonDecoder { } else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) { val = idMapper.getConnector(((JSONString) value).stringValue()); } else { - return decodeObject(variableType, (JSONObject) value, target, - idMapper, connection); + return decodeObject(variableType, value, target, idMapper, + connection); } return val; } private static Object decodeObject(String variableType, - JSONObject encodedValue, Object target, ConnectorMap idMapper, + JSONValue encodedValue, Object target, ConnectorMap idMapper, ApplicationConnection connection) { // object, class name as type JSONSerializer serializer = connection.getSerializerMap() diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index 4a3515ff13..599022b78c 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -80,6 +80,9 @@ public class JsonEncoder { JSONBoolean.getInstance((Boolean) value)); } else if (value instanceof Object[]) { return encodeObjectArray((Object[]) value, connectorMap, connection); + } else if (value instanceof Enum) { + Enum e = (Enum) value; + return encodeEnum(e, connectorMap, connection); } else if (value instanceof Map) { Map map = (Map) value; JSONObject jsonMap = new JSONObject(); @@ -127,6 +130,12 @@ public class JsonEncoder { } } + private static JSONValue encodeEnum(Enum e, ConnectorMap connectorMap, + ApplicationConnection connection) { + return combineTypeAndValue(e.getClass().getName(), + new JSONString(e.toString())); + } + private static JSONValue encodeObjectArray(Object[] array, ConnectorMap connectorMap, ApplicationConnection connection) { JSONArray jsonArray = new JSONArray(); @@ -193,8 +202,6 @@ public class JsonEncoder { 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[]) { return VTYPE_STRINGARRAY; } else if (value instanceof Object[]) { 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 27a0d0118e..3ddae493b7 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -6,16 +6,18 @@ package com.vaadin.terminal.gwt.client.communication; import com.google.gwt.core.client.GWT; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ConnectorMap; public class URLReference_Serializer implements JSONSerializer { - public URLReference deserialize(JSONObject jsonValue, URLReference target, + public URLReference deserialize(JSONValue jsonValue, URLReference target, ConnectorMap idMapper, ApplicationConnection connection) { URLReference reference = GWT.create(URLReference.class); - if (jsonValue.containsKey("URL")) { - JSONArray jsonURL = (JSONArray) jsonValue.get("URL"); + JSONObject json = (JSONObject) jsonValue; + if (json.containsKey("URL")) { + JSONArray jsonURL = (JSONArray) json.get("URL"); String URL = (String) JsonDecoder.decodeValue(jsonURL, null, idMapper, connection); reference.setURL(connection.translateVaadinUri(URL)); @@ -23,7 +25,7 @@ public class URLReference_Serializer implements JSONSerializer { return reference; } - public JSONObject serialize(URLReference value, ConnectorMap idMapper, + public JSONValue serialize(URLReference value, ConnectorMap idMapper, ApplicationConnection connection) { JSONObject json = new JSONObject(); json.put("URL", diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index c88a1c828c..750aa7c15b 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -321,6 +321,11 @@ public class JsonCodec implements Serializable { } } + private static Object decodeEnum(Class cls, JSONObject value) { + String enumIdentifier = String.valueOf(value); + return Enum.valueOf(cls, enumIdentifier); + } + private static String[] decodeStringArray(JSONArray jsonArray) throws JSONException { int length = jsonArray.length(); @@ -384,6 +389,11 @@ public class JsonCodec implements Serializable { throws JSONException { Class targetClass = getClassForType(targetType); + if (Enum.class.isAssignableFrom(targetClass)) { + return decodeEnum(targetClass.asSubclass(Enum.class), + serializedObject); + } + try { Object decodedObject = targetClass.newInstance(); for (PropertyDescriptor pd : Introspector.getBeanInfo(targetClass) @@ -484,6 +494,8 @@ public class JsonCodec implements Serializable { } else if (internalTransportType != null) { return combineTypeAndValue(internalTransportType, String.valueOf(value)); + } else if (value instanceof Enum) { + return encodeEnum((Enum) value, application); } else { // Any object that we do not know how to encode we encode by looping // through fields @@ -558,6 +570,12 @@ public class JsonCodec implements Serializable { return false; } + private static JSONArray encodeEnum(Enum e, Application application) + throws JSONException { + String enumIdentifier = e.name(); + return combineTypeAndValue(e.getClass().getName(), enumIdentifier); + } + private static JSONArray encodeArrayContents(Object[] array, Application application) throws JSONException { JSONArray jsonArray = new JSONArray(); diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index 3b6ab8cdba..0f0ca80426 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -16,12 +16,16 @@ 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.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.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONString; +import com.google.gwt.json.client.JSONValue; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; import com.vaadin.terminal.gwt.client.ApplicationConnection; @@ -89,6 +93,8 @@ public class SerializerGenerator extends Generator { if (printWriter == null) { return; } + boolean isEnum = (beanType.isEnum() != null); + Date date = new Date(); TypeOracle typeOracle = context.getTypeOracle(); String beanQualifiedSourceName = beanType.getQualifiedSourceName(); @@ -117,7 +123,7 @@ public class SerializerGenerator extends Generator { // public JSONValue serialize(Object value, ConnectorMap idMapper, // ApplicationConnection connection) { - sourceWriter.println("public " + JSONObject.class.getName() + sourceWriter.println("public " + JSONValue.class.getName() + " serialize(" + beanQualifiedSourceName + " value, " + ConnectorMap.class.getName() + " idMapper, " + ApplicationConnection.class.getName() + " connection) {"); @@ -125,48 +131,75 @@ public class SerializerGenerator extends Generator { // MouseEventDetails castedValue = (MouseEventDetails) value; sourceWriter.println(beanQualifiedSourceName + " castedValue = (" + beanQualifiedSourceName + ") value;"); - // JSONObject json = new JSONObject(); - sourceWriter.println(JSONObject.class.getName() + " json = new " - + JSONObject.class.getName() + "();"); - for (JMethod setterMethod : getSetters(beanType)) { - String setterName = setterMethod.getName(); - String fieldName = setterName.substring(3); // setZindex() -> ZIndex - String getterName = findGetter(beanType, setterMethod); - - if (getterName == null) { - logger.log(TreeLogger.ERROR, "No getter found for " + fieldName - + ". Serialization will likely fail"); - } - // json.put("button", - // JsonEncoder.encode(castedValue.getButton(), idMapper, - // connection)); - sourceWriter.println("json.put(\"" + fieldName + "\", " - + JsonEncoder.class.getName() + ".encode(castedValue." - + getterName + "(), idMapper, connection));"); + if (isEnum) { + writeEnumSerializer(logger, sourceWriter, beanType); + } else { + writeBeanSerializer(logger, sourceWriter, beanType); } - // return json; - sourceWriter.println("return json;"); // } sourceWriter.println("}"); // Deserializer sourceWriter.println("public " + beanQualifiedSourceName - + " deserialize(" + JSONObject.class.getName() + " jsonValue, " + + " deserialize(" + JSONValue.class.getName() + " jsonValue, " + beanQualifiedSourceName + " target, " + ConnectorMap.class.getName() + " idMapper, " + ApplicationConnection.class.getName() + " connection) {"); sourceWriter.indent(); + if (isEnum) { + writeEnumDeserializer(logger, sourceWriter, beanType.isEnum()); + } else { + writeBeanDeserializer(logger, sourceWriter, beanType); + } + sourceWriter.println("}"); + sourceWriter.outdent(); + + // End of class + sourceWriter.println("}"); + sourceWriter.outdent(); + + // commit generated class + context.commit(logger, printWriter); + logger.log(TreeLogger.INFO, "Generated Serializer class " + + getFullyQualifiedSerializerClassName(beanType)); + } + + private void writeEnumDeserializer(TreeLogger logger, + SourceWriter sourceWriter, JEnumType enumType) { + sourceWriter.println("String enumIdentifier = ((" + + JSONString.class.getName() + ")jsonValue).stringValue();"); + for (JEnumConstant e : enumType.getEnumConstants()) { + sourceWriter.println("if (\"" + e.getName() + + "\".equals(enumIdentifier)) {"); + sourceWriter.indent(); + sourceWriter.println("return " + enumType.getQualifiedSourceName() + + "." + e.getName() + ";"); + sourceWriter.outdent(); + sourceWriter.println("}"); + } + sourceWriter.println("return null;"); + } + + private void writeBeanDeserializer(TreeLogger logger, + SourceWriter sourceWriter, JClassType beanType) { + 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("}"); + // JSONOBject json = (JSONObject)jsonValue; + sourceWriter.println(JSONObject.class.getName() + " json = (" + + JSONObject.class.getName() + ")jsonValue;"); + for (JMethod method : getSetters(beanType)) { String setterName = method.getName(); String fieldName = setterName.substring(3); // setZIndex() -> ZIndex @@ -175,14 +208,14 @@ public class SerializerGenerator extends Generator { logger.log(Type.DEBUG, "* Processing field " + fieldName + " in " + beanQualifiedSourceName + " (" + beanType.getName() + ")"); - // if (jsonValue.containsKey("height")) { - sourceWriter.println("if (jsonValue.containsKey(\"" + fieldName + // if (json.containsKey("height")) { + sourceWriter.println("if (json.containsKey(\"" + fieldName + "\")) {"); sourceWriter.indent(); String jsonFieldName = "json_" + fieldName; - // JSONArray json_Height = (JSONArray) jsonValue.get("height"); + // JSONArray json_Height = (JSONArray) json.get("height"); sourceWriter.println("JSONArray " + jsonFieldName - + " = (JSONArray) jsonValue.get(\"" + fieldName + "\");"); + + " = (JSONArray) json.get(\"" + fieldName + "\");"); String fieldType; String getterName = "get" + fieldName; @@ -228,17 +261,41 @@ public class SerializerGenerator extends Generator { // return target; sourceWriter.println("return target;"); - sourceWriter.println("}"); - sourceWriter.outdent(); - // End of class - sourceWriter.println("}"); - sourceWriter.outdent(); + } - // commit generated class - context.commit(logger, printWriter); - logger.log(TreeLogger.INFO, "Generated Serializer class " - + getFullyQualifiedSerializerClassName(beanType)); + private void writeEnumSerializer(TreeLogger logger, + SourceWriter sourceWriter, JClassType beanType) { + // return new JSONString(castedValue.name()); + sourceWriter.println("return new " + JSONString.class.getName() + + "(castedValue.name());"); + } + + private void writeBeanSerializer(TreeLogger logger, + SourceWriter sourceWriter, JClassType beanType) { + + // JSONObject json = new JSONObject(); + sourceWriter.println(JSONObject.class.getName() + " json = new " + + JSONObject.class.getName() + "();"); + + for (JMethod setterMethod : getSetters(beanType)) { + String setterName = setterMethod.getName(); + String fieldName = setterName.substring(3); // setZIndex() -> ZIndex + String getterName = findGetter(beanType, setterMethod); + + if (getterName == null) { + logger.log(TreeLogger.ERROR, "No getter found for " + fieldName + + ". Serialization will likely fail"); + } + // json.put("button", + // JsonEncoder.encode(castedValue.getButton(), idMapper, + // connection)); + sourceWriter.println("json.put(\"" + fieldName + "\", " + + JsonEncoder.class.getName() + ".encode(castedValue." + + getterName + "(), idMapper, connection));"); + } + // return json; + sourceWriter.println("return json;"); } @@ -283,10 +340,6 @@ public class SerializerGenerator extends Generator { return setterMethods; } - private String decapitalize(String name) { - return name.substring(0, 1).toLowerCase() + name.substring(1); - } - private static String getSerializerSimpleClassName(JClassType beanType) { return getSimpleClassName(beanType) + "_Serializer"; } diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java index 013df4710c..07efcda91b 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java @@ -301,9 +301,6 @@ public class SerializerMapGenerator extends Generator { if (setterType.isArray() != null) { return true; } - if (setterType.isEnum() != null) { - return true; - } if (setterType.isPrimitive() != null) { return true; } -- 2.39.5