Browse Source

Initial support for sending difference in state (#8419)

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
Artur Signell 12 years ago
parent
commit
badc5c3ee4

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

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

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

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


/** /**

+ 22
- 16
src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java View File

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

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

// 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

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



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



+ 31
- 5
src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java View File

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

+ 9
- 0
src/com/vaadin/terminal/gwt/server/ClientConnector.java View File

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

} }

+ 4
- 0
src/com/vaadin/terminal/gwt/server/DragAndDropService.java View File

// 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;
}
} }

+ 69
- 16
src/com/vaadin/terminal/gwt/server/JsonCodec.java View File

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

+ 49
- 12
src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java View File

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



+ 16
- 9
src/com/vaadin/ui/AbstractComponent.java View File

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 */

+ 2
- 3
src/com/vaadin/ui/Root.java View File

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


/** /**

Loading…
Cancel
Save