]> source.dussan.org Git - vaadin-framework.git/commitdiff
Support JsonValue types as declared types in state and RPC (#15560)
authorLeif Åstrand <leif@vaadin.com>
Sat, 10 Jan 2015 10:56:52 +0000 (12:56 +0200)
committerVaadin Code Review <review@vaadin.com>
Mon, 12 Jan 2015 08:46:08 +0000 (08:46 +0000)
Change-Id: I2779a533811bb1b60c4e74789f6378574bc6ac61

client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java
client/src/com/vaadin/client/communication/JsonDecoder.java
server/src/com/vaadin/server/JsonCodec.java
uitest/src/com/vaadin/tests/serialization/SerializerTest.java
uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java
uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java
uitest/src/com/vaadin/tests/widgetset/client/SerializerTestState.java

index 13bd7051f62c336516abed18cb9a739dc5e462c7..f946d876380c7af81a3019f006f32d35ffab8698 100644 (file)
@@ -47,6 +47,7 @@ import com.google.gwt.user.rebind.SourceWriter;
 import com.vaadin.client.JsArrayObject;
 import com.vaadin.client.ServerConnector;
 import com.vaadin.client.annotations.OnStateChange;
+import com.vaadin.client.communication.JsonDecoder;
 import com.vaadin.client.metadata.ConnectorBundleLoader;
 import com.vaadin.client.metadata.ConnectorBundleLoader.CValUiInfo;
 import com.vaadin.client.metadata.InvokationHandler;
@@ -1011,7 +1012,16 @@ public class ConnectorBundleLoaderFactory extends Generator {
                 w.print(", ");
             }
             String parameterTypeName = getBoxedTypeName(parameterType);
-            w.print("(" + parameterTypeName + ") params[" + i + "]");
+
+            if (parameterTypeName.startsWith("elemental.json.Json")) {
+                // Need to pass through native method to allow casting Object to
+                // JSO if the value is a string
+                w.print("%s.<%s>obj2jso(params[%d])",
+                        JsonDecoder.class.getCanonicalName(),
+                        parameterTypeName, i);
+            } else {
+                w.print("(" + parameterTypeName + ") params[" + i + "]");
+            }
         }
         w.println(");");
 
index a8adbac0c646820f809b063c1bc229a2bb493e43..0ce89c873e44796dc1c3166531393b8ee0947b53 100644 (file)
@@ -82,13 +82,16 @@ public class JsonDecoder {
      */
     public static Object decodeValue(Type type, JsonValue jsonValue,
             Object target, ApplicationConnection connection) {
+        String baseTypeName = type.getBaseTypeName();
+        if (baseTypeName.startsWith("elemental.json.Json")) {
+            return jsonValue;
+        }
 
-        // Null is null, regardless of type
+        // Null is null, regardless of type (except JSON)
         if (jsonValue.getType() == JsonType.NULL) {
             return null;
         }
 
-        String baseTypeName = type.getBaseTypeName();
         if (Map.class.getName().equals(baseTypeName)
                 || HashMap.class.getName().equals(baseTypeName)) {
             return decodeMap(type, jsonValue, connection);
@@ -293,4 +296,14 @@ public class JsonDecoder {
             tokens.add(decodeValue(childType, entryValue, null, connection));
         }
     }
+
+    /**
+     * Called by generated deserialization code to treat a generic object as a
+     * JsonValue. This is needed because GWT refuses to directly cast String
+     * typed as Object into a JSO.
+     */
+    public static native <T extends JsonValue> T obj2jso(Object object)
+    /*-{
+        return object;
+    }-*/;
 }
index 1f7b4ead438670d51f017d614866411749f1f148..ec1ea10f2ba5f7fd6d0f71a2904ede7b449d7a4a 100644 (file)
@@ -300,7 +300,9 @@ public class JsonCodec implements Serializable {
         }
 
         // Try to decode object using fields
-        if (value.getType() == JsonType.NULL) {
+        if (isJsonType(targetType)) {
+            return value;
+        } else if (value.getType() == JsonType.NULL) {
             return null;
         } else if (targetType == byte.class || targetType == Byte.class) {
             return Byte.valueOf((byte) value.asNumber());
@@ -334,6 +336,11 @@ public class JsonCodec implements Serializable {
         }
     }
 
+    private static boolean isJsonType(Type type) {
+        return type instanceof Class<?>
+                && JsonValue.class.isAssignableFrom((Class<?>) type);
+    }
+
     private static Object decodeArray(Type componentType, JsonArray value,
             ConnectorTracker connectorTracker) {
         Class<?> componentClass = getClassForType(componentType);
index 333964e9bf9349a86397777380b9c8251c87a040..df37601f23346c23d6e77104734af60c8050e549 100644 (file)
@@ -42,10 +42,14 @@ import com.vaadin.tests.widgetset.client.SerializerTestState;
 import com.vaadin.tests.widgetset.client.SimpleTestBean;
 import com.vaadin.tests.widgetset.server.SerializerTestExtension;
 
+import elemental.json.Json;
+import elemental.json.JsonString;
+import elemental.json.JsonValue;
+
 @Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
 public class SerializerTest extends AbstractTestUI {
 
-    private Log log = new Log(40);
+    private Log log = new Log(45);
 
     @Override
     protected void setup(VaadinRequest request) {
@@ -256,6 +260,12 @@ public class SerializerTest extends AbstractTestUI {
 
         rpc.sendDate(new Date(1));
         rpc.sendDate(new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13));
+
+        state.jsonNull = Json.createNull();
+        state.jsonString = Json.create("a string");
+        state.jsonBoolean = Json.create(false);
+        rpc.sendJson(Json.create(true), Json.createNull(), Json.create("JSON"));
+
         state.date1 = new Date(1);
         state.date2 = new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13);
 
@@ -447,6 +457,13 @@ public class SerializerTest extends AbstractTestUI {
                 log.log("sendDate: " + format.format(date));
             }
 
+            @Override
+            public void sendJson(JsonValue value1, JsonValue value2,
+                    JsonString string) {
+                log.log("sendJson: " + value1.toJson() + ", " + value2.toJson()
+                        + ", " + string.toJson());
+            }
+
             @Override
             public void log(String string) {
                 log.log(string);
@@ -458,7 +475,7 @@ public class SerializerTest extends AbstractTestUI {
 
     @Override
     protected String getTestDescription() {
-        return "Test for lots of different cases of encoding and decoding variuos data types";
+        return "Test for lots of different cases of encoding and decoding various data types";
     }
 
     @Override
index dcba56159927c58c243ed3bf4806e0e3d949524b..a5216546b3557ca93593ee172acd48d4d4bb6471 100644 (file)
@@ -27,6 +27,9 @@ public class SerializerTestTest extends MultiBrowserTest {
         openTestURL();
         int logRow = 0;
 
+        Assert.assertEquals(
+                "sendJson: {\"b\":false,\"s\":\"JSON\"}, null, \"value\"",
+                getLogRow(logRow++));
         Assert.assertEquals("sendDate: May 31, 2013 8:12:13 AM UTC",
                 getLogRow(logRow++));
         Assert.assertEquals("sendDate: January 1, 1970 12:00:00 AM UTC",
@@ -77,6 +80,9 @@ public class SerializerTestTest extends MultiBrowserTest {
                 "sendBoolean: false, false, [false, false, true, false, true, true]",
                 getLogRow(logRow++));
         Assert.assertEquals("sendBeanSubclass: 43", getLogRow(logRow++));
+        Assert.assertEquals("state.jsonBoolean: false", getLogRow(logRow++));
+        Assert.assertEquals("state.jsonString: a string", getLogRow(logRow++));
+        Assert.assertEquals("state.jsonNull: NULL", getLogRow(logRow++));
         Assert.assertEquals(
                 "state.doubleArray: [1.7976931348623157e+308, 5e-324]",
                 getLogRow(logRow++));
index 7758cdc2ac1c97b0c5ef8ffa64d38b8df7557939..07acd3d02159078a45e08f1ed87405b4eac1350c 100644 (file)
@@ -35,6 +35,13 @@ import com.vaadin.shared.ui.Connect;
 import com.vaadin.shared.ui.label.ContentMode;
 import com.vaadin.tests.widgetset.server.SerializerTestExtension;
 
+import elemental.json.Json;
+import elemental.json.JsonBoolean;
+import elemental.json.JsonObject;
+import elemental.json.JsonString;
+import elemental.json.JsonType;
+import elemental.json.JsonValue;
+
 @Connect(SerializerTestExtension.class)
 public class SerializerTestConnector extends AbstractExtensionConnector {
 
@@ -258,6 +265,27 @@ public class SerializerTestConnector extends AbstractExtensionConnector {
                 rpc.sendDate(date);
             }
 
+            @Override
+            public void sendJson(JsonValue value1, JsonValue value2,
+                    JsonString string) {
+                if (value1.getType() != JsonType.BOOLEAN) {
+                    throw new RuntimeException("Expected boolean, got "
+                            + value1.toJson());
+                }
+
+                if (value2.getType() != JsonType.NULL) {
+                    throw new RuntimeException("Expected null, got "
+                            + value2.toJson());
+                }
+
+                JsonObject returnObject = Json.createObject();
+                returnObject.put("b", !((JsonBoolean) value1).asBoolean());
+                returnObject.put("s", string);
+
+                rpc.sendJson(returnObject, Json.createNull(),
+                        Json.create("value"));
+            }
+
             @Override
             public void log(String message) {
                 // Do nothing, used only in the other direction
@@ -311,6 +339,11 @@ public class SerializerTestConnector extends AbstractExtensionConnector {
         rpc.log("state.doubleObjectValue: " + getState().doubleObjectValue);
         rpc.log("state.doubleArray: " + Arrays.toString(getState().doubleArray));
 
+        rpc.log("state.jsonNull: " + getState().jsonNull.getType().name());
+        rpc.log("state.jsonString: "
+                + ((JsonString) getState().jsonString).getString());
+        rpc.log("state.jsonBoolean: " + getState().jsonBoolean.getBoolean());
+
         /*
          * TODO public double doubleValue; public Double DoubleValue; public
          * double[] doubleArray; ;
index 6b4c4e7ac11ed789e89e8684bc3b0bc4ff00b666..4baebc819ebd5799a546d419f88d59b3b78971d1 100644 (file)
@@ -26,6 +26,9 @@ import com.vaadin.shared.communication.ClientRpc;
 import com.vaadin.shared.communication.ServerRpc;
 import com.vaadin.shared.ui.label.ContentMode;
 
+import elemental.json.JsonString;
+import elemental.json.JsonValue;
+
 @SuppressWarnings("javadoc")
 public interface SerializerTestRpc extends ServerRpc, ClientRpc {
     public void sendBoolean(boolean value, Boolean boxedValue, boolean[] array);
@@ -82,5 +85,7 @@ public interface SerializerTestRpc extends ServerRpc, ClientRpc {
 
     public void sendDate(Date date);
 
+    public void sendJson(JsonValue value1, JsonValue value2, JsonString string);
+
     public void log(String string);
 }
index faf41fbf88d18cf49a6ccbd421627640f1964b6f..31ff58971fa5eeb6d4f6f1fe2c03722574011d7b 100644 (file)
@@ -24,6 +24,9 @@ import com.vaadin.shared.AbstractComponentState;
 import com.vaadin.shared.Connector;
 import com.vaadin.shared.ui.label.ContentMode;
 
+import elemental.json.JsonBoolean;
+import elemental.json.JsonValue;
+
 public class SerializerTestState extends AbstractComponentState {
 
     public boolean booleanValue;
@@ -99,4 +102,8 @@ public class SerializerTestState extends AbstractComponentState {
 
     public BeanWithAbstractSuperclass beanWithAbstractSuperclass;
 
+    public JsonValue jsonNull = null;
+    public JsonValue jsonString = null;
+    public JsonBoolean jsonBoolean = null;
+
 }