Forces the shared state to be the type declared by getStateType (#8677) Creates an empty object for reference when doing a full repaint, causing only the differences between a freshly created object and the current state to be sent.tags/7.0.0.alpha3
import com.vaadin.terminal.gwt.client.communication.JsonEncoder; | import com.vaadin.terminal.gwt.client.communication.JsonEncoder; | ||||
import com.vaadin.terminal.gwt.client.communication.MethodInvocation; | import com.vaadin.terminal.gwt.client.communication.MethodInvocation; | ||||
import com.vaadin.terminal.gwt.client.communication.RpcManager; | import com.vaadin.terminal.gwt.client.communication.RpcManager; | ||||
import com.vaadin.terminal.gwt.client.communication.SerializerMap; | |||||
import com.vaadin.terminal.gwt.client.communication.SharedState; | import com.vaadin.terminal.gwt.client.communication.SharedState; | ||||
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; | import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; | ||||
import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; | import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; | ||||
public static final String PARAM_UNLOADBURST = "onunloadburst"; | public static final String PARAM_UNLOADBURST = "onunloadburst"; | ||||
private static SerializerMap serializerMap = GWT | |||||
.create(SerializerMap.class); | |||||
/** | /** | ||||
* A string that, if found in a non-JSON response to a UIDL request, will | * A string that, if found in a non-JSON response to a UIDL request, will | ||||
* cause the browser to refresh the page. If followed by a colon, optional | * cause the browser to refresh the page. If followed by a colon, optional | ||||
states.getJavaScriptObject(connectorId)); | states.getJavaScriptObject(connectorId)); | ||||
Object state = JsonDecoder.decodeValue( | Object state = JsonDecoder.decodeValue( | ||||
stateDataAndType, connectorMap, | |||||
ApplicationConnection.this); | |||||
stateDataAndType, connector.getState(), | |||||
connectorMap, ApplicationConnection.this); | |||||
connector.setState((SharedState) state); | connector.setState((SharedState) state); | ||||
StateChangeEvent event = GWT | StateChangeEvent event = GWT | ||||
Object[] parameters = new Object[parametersJson.size()]; | Object[] parameters = new Object[parametersJson.size()]; | ||||
for (int j = 0; j < parametersJson.size(); ++j) { | for (int j = 0; j < parametersJson.size(); ++j) { | ||||
parameters[j] = JsonDecoder.decodeValue( | parameters[j] = JsonDecoder.decodeValue( | ||||
(JSONArray) parametersJson.get(j), getConnectorMap(), this); | |||||
(JSONArray) parametersJson.get(j), null, getConnectorMap(), | |||||
this); | |||||
} | } | ||||
return new MethodInvocation(connectorId, interfaceName, methodName, | return new MethodInvocation(connectorId, interfaceName, methodName, | ||||
parameters); | parameters); | ||||
LayoutManager getLayoutManager() { | LayoutManager getLayoutManager() { | ||||
return layoutManager; | return layoutManager; | ||||
} | } | ||||
public SerializerMap getSerializerMap() { | |||||
return serializerMap; | |||||
} | |||||
} | } |
* | * | ||||
* @param jsonValue | * @param jsonValue | ||||
* JSON map from property name to property value | * JSON map from property name to property value | ||||
* @param target | |||||
* The object to write the deserialized values to | |||||
* @param idMapper | * @param idMapper | ||||
* mapper from paintable id to paintable, used to decode | * mapper from paintable id to paintable, used to decode | ||||
* references to paintables | * references to paintables | ||||
* @return A deserialized object | * @return A deserialized object | ||||
*/ | */ | ||||
T deserialize(JSONObject jsonValue, ConnectorMap idMapper, | |||||
T deserialize(JSONObject jsonValue, T target, ConnectorMap idMapper, | |||||
ApplicationConnection connection); | ApplicationConnection connection); | ||||
/** | /** |
import java.util.Map; | import java.util.Map; | ||||
import java.util.Set; | import java.util.Set; | ||||
import com.google.gwt.core.client.GWT; | |||||
import com.google.gwt.json.client.JSONArray; | import com.google.gwt.json.client.JSONArray; | ||||
import com.google.gwt.json.client.JSONObject; | import com.google.gwt.json.client.JSONObject; | ||||
import com.google.gwt.json.client.JSONString; | import com.google.gwt.json.client.JSONString; | ||||
* @since 7.0 | * @since 7.0 | ||||
*/ | */ | ||||
public class JsonDecoder { | public class JsonDecoder { | ||||
static SerializerMap serializerMap = GWT.create(SerializerMap.class); | |||||
/** | /** | ||||
* Decode a JSON array with two elements (type and value) into a client-side | * Decode a JSON array with two elements (type and value) into a client-side | ||||
* reference to the current ApplicationConnection | * reference to the current ApplicationConnection | ||||
* @return decoded value (does not contain JSON types) | * @return decoded value (does not contain JSON types) | ||||
*/ | */ | ||||
public static Object decodeValue(JSONArray jsonArray, | |||||
public static Object decodeValue(JSONArray jsonArray, Object target, | |||||
ConnectorMap idMapper, ApplicationConnection connection) { | ConnectorMap idMapper, ApplicationConnection connection) { | ||||
String type = ((JSONString) jsonArray.get(0)).stringValue(); | String type = ((JSONString) jsonArray.get(0)).stringValue(); | ||||
return decodeValue(type, jsonArray.get(1), idMapper, connection); | |||||
return decodeValue(type, jsonArray.get(1), target, idMapper, connection); | |||||
} | } | ||||
private static Object decodeValue(String variableType, Object value, | private static Object decodeValue(String variableType, Object value, | ||||
ConnectorMap idMapper, ApplicationConnection connection) { | |||||
Object target, ConnectorMap idMapper, | |||||
ApplicationConnection connection) { | |||||
Object val = null; | Object val = null; | ||||
// TODO type checks etc. | // TODO type checks etc. | ||||
if (JsonEncoder.VTYPE_NULL.equals(variableType)) { | if (JsonEncoder.VTYPE_NULL.equals(variableType)) { | ||||
} else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) { | } else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) { | ||||
val = idMapper.getConnector(((JSONString) value).stringValue()); | val = idMapper.getConnector(((JSONString) value).stringValue()); | ||||
} else { | } else { | ||||
// object, class name as type | |||||
JSONSerializer serializer = serializerMap | |||||
.getSerializer(variableType); | |||||
// TODO handle case with no serializer found | |||||
Object object = serializer.deserialize((JSONObject) value, | |||||
return decodeObject(variableType, (JSONObject) value, target, | |||||
idMapper, connection); | idMapper, connection); | ||||
return object; | |||||
} | } | ||||
return val; | return val; | ||||
} | } | ||||
private static Object decodeObject(String variableType, | |||||
JSONObject encodedValue, Object target, ConnectorMap idMapper, | |||||
ApplicationConnection connection) { | |||||
// object, class name as type | |||||
JSONSerializer<Object> serializer = connection.getSerializerMap() | |||||
.getSerializer(variableType); | |||||
// TODO handle case with no serializer found | |||||
Object object = serializer.deserialize(encodedValue, target, idMapper, | |||||
connection); | |||||
return object; | |||||
} | |||||
private static Map<String, Object> decodeMap(JSONObject jsonMap, | private static Map<String, Object> decodeMap(JSONObject jsonMap, | ||||
ConnectorMap idMapper, ApplicationConnection connection) { | ConnectorMap idMapper, ApplicationConnection connection) { | ||||
HashMap<String, Object> map = new HashMap<String, Object>(); | HashMap<String, Object> map = new HashMap<String, Object>(); | ||||
while (it.hasNext()) { | while (it.hasNext()) { | ||||
String key = it.next(); | String key = it.next(); | ||||
map.put(key, | map.put(key, | ||||
decodeValue((JSONArray) jsonMap.get(key), idMapper, | |||||
decodeValue((JSONArray) jsonMap.get(key), null, idMapper, | |||||
connection)); | connection)); | ||||
} | } | ||||
return map; | return map; | ||||
String connectorId = it.next(); | String connectorId = it.next(); | ||||
Connector connector = idMapper.getConnector(connectorId); | Connector connector = idMapper.getConnector(connectorId); | ||||
map.put(connector, | map.put(connector, | ||||
decodeValue((JSONArray) jsonMap.get(connectorId), idMapper, | |||||
connection)); | |||||
decodeValue((JSONArray) jsonMap.get(connectorId), null, | |||||
idMapper, connection)); | |||||
} | } | ||||
return map; | return map; | ||||
} | } | ||||
for (int i = 0; i < jsonArray.size(); ++i) { | for (int i = 0; i < jsonArray.size(); ++i) { | ||||
// each entry always has two elements: type and value | // each entry always has two elements: type and value | ||||
JSONArray entryArray = (JSONArray) jsonArray.get(i); | JSONArray entryArray = (JSONArray) jsonArray.get(i); | ||||
tokens.add(decodeValue(entryArray, idMapper, connection)); | |||||
tokens.add(decodeValue(entryArray, null, idMapper, connection)); | |||||
} | } | ||||
return tokens; | return tokens; | ||||
} | } | ||||
for (int i = 0; i < jsonArray.size(); ++i) { | for (int i = 0; i < jsonArray.size(); ++i) { | ||||
// each entry always has two elements: type and value | // each entry always has two elements: type and value | ||||
JSONArray entryArray = (JSONArray) jsonArray.get(i); | JSONArray entryArray = (JSONArray) jsonArray.get(i); | ||||
tokens.add(decodeValue(entryArray, idMapper, connection)); | |||||
tokens.add(decodeValue(entryArray, null, idMapper, connection)); | |||||
} | } | ||||
return tokens; | return tokens; | ||||
} | } |
// Try to find a generated serializer object, class name is the | // Try to find a generated serializer object, class name is the | ||||
// type | // type | ||||
transportType = value.getClass().getName(); | transportType = value.getClass().getName(); | ||||
JSONSerializer serializer = JsonDecoder.serializerMap | |||||
JSONSerializer serializer = connection.getSerializerMap() | |||||
.getSerializer(transportType); | .getSerializer(transportType); | ||||
// TODO handle case with no serializer found | // TODO handle case with no serializer found |
public class URLReference_Serializer implements JSONSerializer<URLReference> { | public class URLReference_Serializer implements JSONSerializer<URLReference> { | ||||
public URLReference deserialize(JSONObject jsonValue, | |||||
public URLReference deserialize(JSONObject jsonValue, URLReference target, | |||||
ConnectorMap idMapper, ApplicationConnection connection) { | ConnectorMap idMapper, ApplicationConnection connection) { | ||||
URLReference reference = GWT.create(URLReference.class); | URLReference reference = GWT.create(URLReference.class); | ||||
JSONArray jsonURL = (JSONArray) jsonValue.get("URL"); | |||||
String URL = (String) JsonDecoder.decodeValue(jsonURL, idMapper, | |||||
connection); | |||||
reference.setURL(connection.translateVaadinUri(URL)); | |||||
if (jsonValue.containsKey("URL")) { | |||||
JSONArray jsonURL = (JSONArray) jsonValue.get("URL"); | |||||
String URL = (String) JsonDecoder.decodeValue(jsonURL, null, | |||||
idMapper, connection); | |||||
reference.setURL(connection.translateVaadinUri(URL)); | |||||
} | |||||
return reference; | return reference; | ||||
} | } | ||||
// client after component creation but before legacy UIDL | // client after component creation but before legacy UIDL | ||||
// processing. | // processing. | ||||
JSONObject sharedStates = new JSONObject(); | JSONObject sharedStates = new JSONObject(); | ||||
for (Connector connector : dirtyVisibleConnectors) { | |||||
for (ClientConnector connector : dirtyVisibleConnectors) { | |||||
SharedState state = connector.getState(); | SharedState state = connector.getState(); | ||||
if (null != state) { | if (null != state) { | ||||
// encode and send shared state | // encode and send shared state | ||||
try { | try { | ||||
// FIXME Use declared type | |||||
Class<? extends SharedState> stateType = connector | |||||
.getStateType(); | |||||
SharedState referenceState = null; | |||||
if (repaintAll) { | |||||
// Use an empty state object as reference for full | |||||
// repaints | |||||
try { | |||||
referenceState = stateType.newInstance(); | |||||
} catch (Exception e) { | |||||
logger.log(Level.WARNING, | |||||
"Error creating reference object for state of type " | |||||
+ stateType.getName()); | |||||
} | |||||
} | |||||
JSONArray stateJsonArray = JsonCodec.encode(state, | JSONArray stateJsonArray = JsonCodec.encode(state, | ||||
state.getClass(), application); | |||||
referenceState, stateType, application); | |||||
sharedStates | sharedStates | ||||
.put(connector.getConnectorId(), stateJsonArray); | .put(connector.getConnectorId(), stateJsonArray); | ||||
} catch (JSONException e) { | } catch (JSONException e) { | ||||
invocationJson.put(invocation.getMethodName()); | invocationJson.put(invocation.getMethodName()); | ||||
JSONArray paramJson = new JSONArray(); | JSONArray paramJson = new JSONArray(); | ||||
for (int i = 0; i < invocation.getParameterTypes().length; ++i) { | for (int i = 0; i < invocation.getParameterTypes().length; ++i) { | ||||
Class<?> parameterType = invocation.getParameterTypes()[i]; | |||||
Object referenceParameter = null; | |||||
// TODO Use default values for RPC parameter types | |||||
// if (!JsonCodec.isInternalType(parameterType)) { | |||||
// try { | |||||
// referenceParameter = parameterType.newInstance(); | |||||
// } catch (Exception e) { | |||||
// logger.log(Level.WARNING, | |||||
// "Error creating reference object for parameter of type " | |||||
// + parameterType.getName()); | |||||
// } | |||||
// } | |||||
paramJson.put(JsonCodec.encode( | paramJson.put(JsonCodec.encode( | ||||
invocation.getParameters()[i], | |||||
invocation.getParameterTypes()[i], application)); | |||||
invocation.getParameters()[i], referenceParameter, | |||||
parameterType, application)); | |||||
} | } | ||||
invocationJson.put(paramJson); | invocationJson.put(paramJson); | ||||
rpcCalls.put(invocationJson); | rpcCalls.put(invocationJson); |
import java.util.List; | import java.util.List; | ||||
import com.vaadin.terminal.gwt.client.Connector; | import com.vaadin.terminal.gwt.client.Connector; | ||||
import com.vaadin.terminal.gwt.client.communication.SharedState; | |||||
/** | /** | ||||
* Interface implemented by all connectors that are capable of communicating | * Interface implemented by all connectors that are capable of communicating | ||||
* @return true if the connector can receive messages, false otherwise | * @return true if the connector can receive messages, false otherwise | ||||
*/ | */ | ||||
public boolean isConnectorEnabled(); | public boolean isConnectorEnabled(); | ||||
/** | |||||
* Returns the type of the shared state for this connector | |||||
* | |||||
* @return The type of the state. Must never return null. | |||||
*/ | |||||
public Class<? extends SharedState> getStateType(); | |||||
} | } |
// TODO Use rpc for drag'n'drop | // TODO Use rpc for drag'n'drop | ||||
return null; | return null; | ||||
} | } | ||||
public Class<? extends SharedState> getStateType() { | |||||
return SharedState.class; | |||||
} | |||||
} | } |
@Deprecated | @Deprecated | ||||
private static JSONArray encode(Object value, Application application) | private static JSONArray encode(Object value, Application application) | ||||
throws JSONException { | throws JSONException { | ||||
return encode(value, null, application); | |||||
return encode(value, null, null, application); | |||||
} | } | ||||
public static JSONArray encode(Object value, Class<?> valueType, | |||||
Application application) throws JSONException { | |||||
public static JSONArray encode(Object value, Object referenceValue, | |||||
Type valueType, Application application) throws JSONException { | |||||
if (null == value) { | if (null == value) { | ||||
return encodeNull(); | return encodeNull(); | ||||
"Unable to serialize unsupported type: " + valueType); | "Unable to serialize unsupported type: " + valueType); | ||||
} | } | ||||
Collection<?> collection = (Collection<?>) value; | Collection<?> collection = (Collection<?>) value; | ||||
JSONArray jsonArray = encodeCollection(collection, application); | |||||
JSONArray jsonArray = encodeCollection(valueType, collection, | |||||
application); | |||||
return combineTypeAndValue(internalTransportType, jsonArray); | return combineTypeAndValue(internalTransportType, jsonArray); | ||||
} else if (value instanceof Object[]) { | } else if (value instanceof Object[]) { | ||||
} else { | } else { | ||||
// Any object that we do not know how to encode we encode by looping | // Any object that we do not know how to encode we encode by looping | ||||
// through fields | // through fields | ||||
return combineTypeAndValue(getCustomTransportType(valueType), | |||||
encodeObject(value, application)); | |||||
return combineTypeAndValue( | |||||
getCustomTransportType((Class<?>) valueType), | |||||
encodeObject(value, referenceValue, application)); | |||||
} | } | ||||
} | } | ||||
return combineTypeAndValue(JsonEncoder.VTYPE_NULL, JSONObject.NULL); | return combineTypeAndValue(JsonEncoder.VTYPE_NULL, JSONObject.NULL); | ||||
} | } | ||||
private static Object encodeObject(Object value, Application application) | |||||
throws JSONException { | |||||
private static Object encodeObject(Object value, Object referenceValue, | |||||
Application application) throws JSONException { | |||||
JSONObject jsonMap = new JSONObject(); | JSONObject jsonMap = new JSONObject(); | ||||
try { | try { | ||||
for (PropertyDescriptor pd : Introspector.getBeanInfo( | for (PropertyDescriptor pd : Introspector.getBeanInfo( | ||||
value.getClass()).getPropertyDescriptors()) { | value.getClass()).getPropertyDescriptors()) { | ||||
Class<?> fieldType = pd.getPropertyType(); | |||||
String fieldName = getTransportFieldName(pd); | String fieldName = getTransportFieldName(pd); | ||||
if (fieldName == null) { | if (fieldName == null) { | ||||
continue; | continue; | ||||
} | } | ||||
Method getterMethod = pd.getReadMethod(); | Method getterMethod = pd.getReadMethod(); | ||||
// We can't use PropertyDescriptor.getPropertyType() as it does | |||||
// not support generics | |||||
Type fieldType = getterMethod.getGenericReturnType(); | |||||
Object fieldValue = getterMethod.invoke(value, (Object[]) null); | Object fieldValue = getterMethod.invoke(value, (Object[]) null); | ||||
jsonMap.put(fieldName, | |||||
encode(fieldValue, fieldType, application)); | |||||
boolean equals = false; | |||||
Object referenceFieldValue = null; | |||||
if (referenceValue != null) { | |||||
referenceFieldValue = getterMethod.invoke(referenceValue, | |||||
(Object[]) null); | |||||
equals = equals(fieldValue, referenceFieldValue); | |||||
} | |||||
if (!equals) { | |||||
jsonMap.put( | |||||
fieldName, | |||||
encode(fieldValue, referenceFieldValue, fieldType, | |||||
application)); | |||||
// } else { | |||||
// System.out.println("Skipping field " + fieldName | |||||
// + " of type " + fieldType.getName() | |||||
// + " for object " + value.getClass().getName() | |||||
// + " as " + fieldValue + "==" + referenceFieldValue); | |||||
} | |||||
} | } | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
// TODO: Should exceptions be handled in a different way? | // TODO: Should exceptions be handled in a different way? | ||||
return jsonMap; | return jsonMap; | ||||
} | } | ||||
/** | |||||
* Compares the value with the reference. If they match, returns true. | |||||
* | |||||
* @param fieldValue | |||||
* @param referenceValue | |||||
* @return | |||||
*/ | |||||
private static boolean equals(Object fieldValue, Object referenceValue) { | |||||
if (fieldValue == null) { | |||||
return referenceValue == null; | |||||
} | |||||
if (fieldValue.equals(referenceValue)) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
private static JSONArray encodeArrayContents(Object[] array, | private static JSONArray encodeArrayContents(Object[] array, | ||||
Application application) throws JSONException { | Application application) throws JSONException { | ||||
JSONArray jsonArray = new JSONArray(); | JSONArray jsonArray = new JSONArray(); | ||||
for (Object o : array) { | for (Object o : array) { | ||||
jsonArray.put(encode(o, null, application)); | |||||
jsonArray.put(encode(o, null, null, application)); | |||||
} | } | ||||
return jsonArray; | return jsonArray; | ||||
} | } | ||||
private static JSONArray encodeCollection(Collection collection, | |||||
Application application) throws JSONException { | |||||
private static JSONArray encodeCollection(Type targetType, | |||||
Collection collection, Application application) | |||||
throws JSONException { | |||||
JSONArray jsonArray = new JSONArray(); | JSONArray jsonArray = new JSONArray(); | ||||
for (Object o : collection) { | for (Object o : collection) { | ||||
jsonArray.put(encode(o, application)); | |||||
jsonArray.put(encodeChild(targetType, 0, o, application)); | |||||
} | } | ||||
return jsonArray; | return jsonArray; | ||||
} | } | ||||
private static JSONArray encodeChild(Type targetType, int typeIndex, | |||||
Object o, Application application) throws JSONException { | |||||
if (targetType instanceof ParameterizedType) { | |||||
Type childType = ((ParameterizedType) targetType) | |||||
.getActualTypeArguments()[typeIndex]; | |||||
// Encode using the given type | |||||
return encode(o, null, childType, application); | |||||
} else { | |||||
return encode(o, application); | |||||
} | |||||
} | |||||
private static JSONObject encodeMapContents(Map<Object, Object> map, | private static JSONObject encodeMapContents(Map<Object, Object> map, | ||||
Application application) throws JSONException { | Application application) throws JSONException { | ||||
JSONObject jsonMap = new JSONObject(); | JSONObject jsonMap = new JSONObject(); | ||||
"Only maps with String/Connector keys are currently supported (#8602)"); | "Only maps with String/Connector keys are currently supported (#8602)"); | ||||
} | } | ||||
jsonMap.put((String) mapKey, encode(mapValue, null, application)); | |||||
jsonMap.put((String) mapKey, | |||||
encode(mapValue, null, null, application)); | |||||
} | } | ||||
return jsonMap; | return jsonMap; | ||||
} | } |
composer.addImport(JsonDecoder.class.getName()); | composer.addImport(JsonDecoder.class.getName()); | ||||
// composer.addImport(VaadinSerializer.class.getName()); | // composer.addImport(VaadinSerializer.class.getName()); | ||||
composer.addImplementedInterface(JSONSerializer.class.getName()); | |||||
composer.addImplementedInterface(JSONSerializer.class.getName() + "<" | |||||
+ beanQualifiedSourceName + ">"); | |||||
SourceWriter sourceWriter = composer.createSourceWriter(context, | SourceWriter sourceWriter = composer.createSourceWriter(context, | ||||
printWriter); | printWriter); | ||||
// public JSONValue serialize(Object value, ConnectorMap idMapper, | // public JSONValue serialize(Object value, ConnectorMap idMapper, | ||||
// ApplicationConnection connection) { | // ApplicationConnection connection) { | ||||
sourceWriter.println("public " + JSONObject.class.getName() | sourceWriter.println("public " + JSONObject.class.getName() | ||||
+ " serialize(" + Object.class.getName() + " value, " | |||||
+ " serialize(" + beanQualifiedSourceName + " value, " | |||||
+ ConnectorMap.class.getName() + " idMapper, " | + ConnectorMap.class.getName() + " idMapper, " | ||||
+ ApplicationConnection.class.getName() + " connection) {"); | + ApplicationConnection.class.getName() + " connection) {"); | ||||
sourceWriter.indent(); | sourceWriter.indent(); | ||||
// Deserializer | // Deserializer | ||||
sourceWriter.println("public " + beanQualifiedSourceName | sourceWriter.println("public " + beanQualifiedSourceName | ||||
+ " deserialize(" + JSONObject.class.getName() + " jsonValue, " | + " deserialize(" + JSONObject.class.getName() + " jsonValue, " | ||||
+ beanQualifiedSourceName + " target, " | |||||
+ ConnectorMap.class.getName() + " idMapper, " | + ConnectorMap.class.getName() + " idMapper, " | ||||
+ ApplicationConnection.class.getName() + " connection) {"); | + ApplicationConnection.class.getName() + " connection) {"); | ||||
sourceWriter.indent(); | sourceWriter.indent(); | ||||
// VButtonState state = GWT.create(VButtonState.class); | |||||
sourceWriter.println(beanQualifiedSourceName + " state = GWT.create(" | |||||
+ beanQualifiedSourceName + ".class);"); | |||||
// 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("}"); | |||||
for (JMethod method : getSetters(beanType)) { | for (JMethod method : getSetters(beanType)) { | ||||
String setterName = method.getName(); | String setterName = method.getName(); | ||||
String fieldName = setterName.substring(3); // setZIndex() -> ZIndex | String fieldName = setterName.substring(3); // setZIndex() -> ZIndex | ||||
logger.log(Type.DEBUG, "* Processing field " + fieldName + " in " | logger.log(Type.DEBUG, "* Processing field " + fieldName + " in " | ||||
+ beanQualifiedSourceName + " (" + beanType.getName() + ")"); | + beanQualifiedSourceName + " (" + beanType.getName() + ")"); | ||||
// if (jsonValue.containsKey("height")) { | |||||
sourceWriter.println("if (jsonValue.containsKey(\"" + fieldName | |||||
+ "\")) {"); | |||||
sourceWriter.indent(); | |||||
String jsonFieldName = "json_" + fieldName; | String jsonFieldName = "json_" + fieldName; | ||||
// JSONArray json_Height = (JSONArray) jsonValue.get("height"); | // JSONArray json_Height = (JSONArray) jsonValue.get("height"); | ||||
sourceWriter.println("JSONArray " + jsonFieldName | sourceWriter.println("JSONArray " + jsonFieldName | ||||
+ " = (JSONArray) jsonValue.get(\"" + fieldName + "\");"); | + " = (JSONArray) jsonValue.get(\"" + fieldName + "\");"); | ||||
// state.setHeight((String) | |||||
// JsonDecoder.decodeValue(jsonFieldValue,idMapper, connection)); | |||||
String fieldType; | String fieldType; | ||||
String getterName = "get" + fieldName; | |||||
JPrimitiveType primitiveType = setterParameterType.isPrimitive(); | JPrimitiveType primitiveType = setterParameterType.isPrimitive(); | ||||
if (primitiveType != null) { | if (primitiveType != null) { | ||||
// This is a primitive type -> must used the boxed type | // This is a primitive type -> must used the boxed type | ||||
fieldType = primitiveType.getQualifiedBoxedSourceName(); | fieldType = primitiveType.getQualifiedBoxedSourceName(); | ||||
if (primitiveType == JPrimitiveType.BOOLEAN) { | |||||
getterName = "is" + fieldName; | |||||
} | |||||
} else { | } else { | ||||
fieldType = setterParameterType.getQualifiedSourceName(); | fieldType = setterParameterType.getQualifiedSourceName(); | ||||
} | } | ||||
sourceWriter.println("state." + setterName + "((" + fieldType | |||||
// 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("}"); | |||||
// target.setHeight((String) | |||||
// JsonDecoder.decodeValue(jsonFieldValue,referenceValue, idMapper, | |||||
// connection)); | |||||
sourceWriter.println("target." + setterName + "((" + fieldType | |||||
+ ") " + JsonDecoder.class.getName() + ".decodeValue(" | + ") " + JsonDecoder.class.getName() + ".decodeValue(" | ||||
+ jsonFieldName + ", idMapper, connection));"); | |||||
+ jsonFieldName | |||||
+ ", referenceValue, idMapper, connection));"); | |||||
// } ... end of if contains | |||||
sourceWriter.println("}"); | |||||
sourceWriter.outdent(); | |||||
} | } | ||||
// return state; | |||||
sourceWriter.println("return state;"); | |||||
// return target; | |||||
sourceWriter.println("return target;"); | |||||
sourceWriter.println("}"); | sourceWriter.println("}"); | ||||
sourceWriter.outdent(); | sourceWriter.outdent(); | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.Locale; | import java.util.Locale; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.logging.Level; | |||||
import java.util.logging.Logger; | import java.util.logging.Logger; | ||||
import java.util.regex.Matcher; | import java.util.regex.Matcher; | ||||
import java.util.regex.Pattern; | import java.util.regex.Pattern; | ||||
* @return new shared state object | * @return new shared state object | ||||
*/ | */ | ||||
protected ComponentState createState() { | protected ComponentState createState() { | ||||
try { | |||||
return getStateType().newInstance(); | |||||
} catch (Exception e) { | |||||
throw new RuntimeException( | |||||
"Error creating state of type " + getStateType().getName() | |||||
+ " for " + getClass().getName(), e); | |||||
} | |||||
} | |||||
/* (non-Javadoc) | |||||
* @see com.vaadin.terminal.gwt.server.ClientConnector#getStateType() | |||||
*/ | |||||
public Class<? extends ComponentState> getStateType() { | |||||
try { | try { | ||||
Method m = getClass().getMethod("getState", (Class[]) null); | Method m = getClass().getMethod("getState", (Class[]) null); | ||||
Class<? extends ComponentState> type = (Class<? extends ComponentState>) m | Class<? extends ComponentState> type = (Class<? extends ComponentState>) m | ||||
.getReturnType(); | .getReturnType(); | ||||
return type.newInstance(); | |||||
return type; | |||||
} catch (Exception e) { | } catch (Exception e) { | ||||
getLogger().log( | |||||
Level.INFO, | |||||
"Error determining state object class for " | |||||
+ getClass().getName()); | |||||
throw new RuntimeException("Error finding state type for " | |||||
+ getClass().getName(), e); | |||||
} | } | ||||
// Fall back to ComponentState if detection fails for some reason. | |||||
return new ComponentState(); | |||||
} | } | ||||
/* Documentation copied from interface */ | /* Documentation copied from interface */ |
import com.vaadin.terminal.Vaadin6Component; | import com.vaadin.terminal.Vaadin6Component; | ||||
import com.vaadin.terminal.WrappedRequest; | import com.vaadin.terminal.WrappedRequest; | ||||
import com.vaadin.terminal.WrappedRequest.BrowserDetails; | import com.vaadin.terminal.WrappedRequest.BrowserDetails; | ||||
import com.vaadin.terminal.gwt.client.ComponentState; | |||||
import com.vaadin.terminal.gwt.client.MouseEventDetails; | import com.vaadin.terminal.gwt.client.MouseEventDetails; | ||||
import com.vaadin.terminal.gwt.client.ui.notification.VNotification; | import com.vaadin.terminal.gwt.client.ui.notification.VNotification; | ||||
import com.vaadin.terminal.gwt.client.ui.root.RootServerRpc; | import com.vaadin.terminal.gwt.client.ui.root.RootServerRpc; | ||||
} | } | ||||
@Override | @Override | ||||
protected ComponentState createState() { | |||||
public Class<? extends RootState> getStateType() { | |||||
// This is a workaround for a problem with creating the correct state | // This is a workaround for a problem with creating the correct state | ||||
// object during build | // object during build | ||||
return new RootState(); | |||||
return RootState.class; | |||||
} | } | ||||
/** | /** |