Change-Id: I2779a533811bb1b60c4e74789f6378574bc6ac61tags/7.4.0.beta2
import com.vaadin.client.JsArrayObject; | import com.vaadin.client.JsArrayObject; | ||||
import com.vaadin.client.ServerConnector; | import com.vaadin.client.ServerConnector; | ||||
import com.vaadin.client.annotations.OnStateChange; | import com.vaadin.client.annotations.OnStateChange; | ||||
import com.vaadin.client.communication.JsonDecoder; | |||||
import com.vaadin.client.metadata.ConnectorBundleLoader; | import com.vaadin.client.metadata.ConnectorBundleLoader; | ||||
import com.vaadin.client.metadata.ConnectorBundleLoader.CValUiInfo; | import com.vaadin.client.metadata.ConnectorBundleLoader.CValUiInfo; | ||||
import com.vaadin.client.metadata.InvokationHandler; | import com.vaadin.client.metadata.InvokationHandler; | ||||
w.print(", "); | w.print(", "); | ||||
} | } | ||||
String parameterTypeName = getBoxedTypeName(parameterType); | 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(");"); | w.println(");"); | ||||
*/ | */ | ||||
public static Object decodeValue(Type type, JsonValue jsonValue, | public static Object decodeValue(Type type, JsonValue jsonValue, | ||||
Object target, ApplicationConnection connection) { | 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) { | if (jsonValue.getType() == JsonType.NULL) { | ||||
return null; | return null; | ||||
} | } | ||||
String baseTypeName = type.getBaseTypeName(); | |||||
if (Map.class.getName().equals(baseTypeName) | if (Map.class.getName().equals(baseTypeName) | ||||
|| HashMap.class.getName().equals(baseTypeName)) { | || HashMap.class.getName().equals(baseTypeName)) { | ||||
return decodeMap(type, jsonValue, connection); | return decodeMap(type, jsonValue, connection); | ||||
tokens.add(decodeValue(childType, entryValue, null, connection)); | 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; | |||||
}-*/; | |||||
} | } |
} | } | ||||
// Try to decode object using fields | // Try to decode object using fields | ||||
if (value.getType() == JsonType.NULL) { | |||||
if (isJsonType(targetType)) { | |||||
return value; | |||||
} else if (value.getType() == JsonType.NULL) { | |||||
return null; | return null; | ||||
} else if (targetType == byte.class || targetType == Byte.class) { | } else if (targetType == byte.class || targetType == Byte.class) { | ||||
return Byte.valueOf((byte) value.asNumber()); | return Byte.valueOf((byte) value.asNumber()); | ||||
} | } | ||||
} | } | ||||
private static boolean isJsonType(Type type) { | |||||
return type instanceof Class<?> | |||||
&& JsonValue.class.isAssignableFrom((Class<?>) type); | |||||
} | |||||
private static Object decodeArray(Type componentType, JsonArray value, | private static Object decodeArray(Type componentType, JsonArray value, | ||||
ConnectorTracker connectorTracker) { | ConnectorTracker connectorTracker) { | ||||
Class<?> componentClass = getClassForType(componentType); | Class<?> componentClass = getClassForType(componentType); |
import com.vaadin.tests.widgetset.client.SimpleTestBean; | import com.vaadin.tests.widgetset.client.SimpleTestBean; | ||||
import com.vaadin.tests.widgetset.server.SerializerTestExtension; | 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") | @Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet") | ||||
public class SerializerTest extends AbstractTestUI { | public class SerializerTest extends AbstractTestUI { | ||||
private Log log = new Log(40); | |||||
private Log log = new Log(45); | |||||
@Override | @Override | ||||
protected void setup(VaadinRequest request) { | protected void setup(VaadinRequest request) { | ||||
rpc.sendDate(new Date(1)); | rpc.sendDate(new Date(1)); | ||||
rpc.sendDate(new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13)); | 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.date1 = new Date(1); | ||||
state.date2 = new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13); | state.date2 = new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13); | ||||
log.log("sendDate: " + format.format(date)); | 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 | @Override | ||||
public void log(String string) { | public void log(String string) { | ||||
log.log(string); | log.log(string); | ||||
@Override | @Override | ||||
protected String getTestDescription() { | 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 | @Override |
openTestURL(); | openTestURL(); | ||||
int logRow = 0; | 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", | Assert.assertEquals("sendDate: May 31, 2013 8:12:13 AM UTC", | ||||
getLogRow(logRow++)); | getLogRow(logRow++)); | ||||
Assert.assertEquals("sendDate: January 1, 1970 12:00:00 AM UTC", | Assert.assertEquals("sendDate: January 1, 1970 12:00:00 AM UTC", | ||||
"sendBoolean: false, false, [false, false, true, false, true, true]", | "sendBoolean: false, false, [false, false, true, false, true, true]", | ||||
getLogRow(logRow++)); | getLogRow(logRow++)); | ||||
Assert.assertEquals("sendBeanSubclass: 43", 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( | Assert.assertEquals( | ||||
"state.doubleArray: [1.7976931348623157e+308, 5e-324]", | "state.doubleArray: [1.7976931348623157e+308, 5e-324]", | ||||
getLogRow(logRow++)); | getLogRow(logRow++)); |
import com.vaadin.shared.ui.label.ContentMode; | import com.vaadin.shared.ui.label.ContentMode; | ||||
import com.vaadin.tests.widgetset.server.SerializerTestExtension; | 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) | @Connect(SerializerTestExtension.class) | ||||
public class SerializerTestConnector extends AbstractExtensionConnector { | public class SerializerTestConnector extends AbstractExtensionConnector { | ||||
rpc.sendDate(date); | 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 | @Override | ||||
public void log(String message) { | public void log(String message) { | ||||
// Do nothing, used only in the other direction | // Do nothing, used only in the other direction | ||||
rpc.log("state.doubleObjectValue: " + getState().doubleObjectValue); | rpc.log("state.doubleObjectValue: " + getState().doubleObjectValue); | ||||
rpc.log("state.doubleArray: " + Arrays.toString(getState().doubleArray)); | 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 | * TODO public double doubleValue; public Double DoubleValue; public | ||||
* double[] doubleArray; ; | * double[] doubleArray; ; |
import com.vaadin.shared.communication.ServerRpc; | import com.vaadin.shared.communication.ServerRpc; | ||||
import com.vaadin.shared.ui.label.ContentMode; | import com.vaadin.shared.ui.label.ContentMode; | ||||
import elemental.json.JsonString; | |||||
import elemental.json.JsonValue; | |||||
@SuppressWarnings("javadoc") | @SuppressWarnings("javadoc") | ||||
public interface SerializerTestRpc extends ServerRpc, ClientRpc { | public interface SerializerTestRpc extends ServerRpc, ClientRpc { | ||||
public void sendBoolean(boolean value, Boolean boxedValue, boolean[] array); | public void sendBoolean(boolean value, Boolean boxedValue, boolean[] array); | ||||
public void sendDate(Date date); | public void sendDate(Date date); | ||||
public void sendJson(JsonValue value1, JsonValue value2, JsonString string); | |||||
public void log(String string); | public void log(String string); | ||||
} | } |
import com.vaadin.shared.Connector; | import com.vaadin.shared.Connector; | ||||
import com.vaadin.shared.ui.label.ContentMode; | import com.vaadin.shared.ui.label.ContentMode; | ||||
import elemental.json.JsonBoolean; | |||||
import elemental.json.JsonValue; | |||||
public class SerializerTestState extends AbstractComponentState { | public class SerializerTestState extends AbstractComponentState { | ||||
public boolean booleanValue; | public boolean booleanValue; | ||||
public BeanWithAbstractSuperclass beanWithAbstractSuperclass; | public BeanWithAbstractSuperclass beanWithAbstractSuperclass; | ||||
public JsonValue jsonNull = null; | |||||
public JsonValue jsonString = null; | |||||
public JsonBoolean jsonBoolean = null; | |||||
} | } |