summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java245
-rw-r--r--client/src/com/vaadin/client/communication/StateChangeEvent.java181
-rw-r--r--client/src/com/vaadin/client/metadata/Type.java5
-rw-r--r--client/src/com/vaadin/client/metadata/TypeDataStore.java18
4 files changed, 293 insertions, 156 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index de034a65a6..1a637e3161 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -16,15 +16,13 @@
package com.vaadin.client;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -113,8 +111,15 @@ public class ApplicationConnection {
* Helper used to return two values when updating the connector hierarchy.
*/
private static class ConnectorHierarchyUpdateResult {
- private List<ConnectorHierarchyChangeEvent> events = new LinkedList<ConnectorHierarchyChangeEvent>();
- private List<ServerConnector> parentChanged = new LinkedList<ServerConnector>();
+ /**
+ * Needed at a later point when the created events are fired
+ */
+ private JsArrayObject<ConnectorHierarchyChangeEvent> events = JavaScriptObject
+ .createArray().cast();
+ /**
+ * Needed to know where captions might need to get updated
+ */
+ private FastStringSet parentChangedIds = FastStringSet.create();
}
public static final String MODIFIED_CLASSNAME = "v-modified";
@@ -153,9 +158,6 @@ public class ApplicationConnection {
// will hold the UIDL security key (for XSS protection) once received
private String uidlSecurityKey = "init";
- private static final FastStringMap<FastStringSet> allStateFieldsCache = FastStringMap
- .create();
-
private final HashMap<String, String> resourcesMap = new HashMap<String, String>();
/**
@@ -217,8 +219,6 @@ public class ApplicationConnection {
/** redirectTimer scheduling interval in seconds */
private int sessionExpirationInterval;
- private ArrayList<Widget> componentCaptionSizeChanges = new ArrayList<Widget>();
-
private Date requestStartTime;
private boolean validatingLayouts = false;
@@ -1424,16 +1424,14 @@ public class ApplicationConnection {
redirectTimer.schedule(1000 * sessionExpirationInterval);
}
- componentCaptionSizeChanges.clear();
-
double processUidlStart = Duration.currentTimeMillis();
// Ensure that all connectors that we are about to update exist
- Set<ServerConnector> createdConnectors = createConnectorsIfNeeded(json);
+ JsArrayString createdConnectorIds = createConnectorsIfNeeded(json);
// Update states, do not fire events
- Collection<StateChangeEvent> pendingStateChangeEvents = updateConnectorState(
- json, createdConnectors);
+ JsArrayObject<StateChangeEvent> pendingStateChangeEvents = updateConnectorState(
+ json, createdConnectorIds);
// Update hierarchy, do not fire events
ConnectorHierarchyUpdateResult connectorHierarchyUpdateResult = updateConnectorHierarchy(json);
@@ -1442,7 +1440,7 @@ public class ApplicationConnection {
sendHierarchyChangeEvents(connectorHierarchyUpdateResult.events);
updateCaptions(pendingStateChangeEvents,
- connectorHierarchyUpdateResult.parentChanged);
+ connectorHierarchyUpdateResult.parentChangedIds);
delegateToWidget(pendingStateChangeEvents);
@@ -1566,27 +1564,35 @@ public class ApplicationConnection {
}
private void updateCaptions(
- Collection<StateChangeEvent> pendingStateChangeEvents,
- Collection<ServerConnector> parentChanged) {
+ JsArrayObject<StateChangeEvent> pendingStateChangeEvents,
+ FastStringSet parentChangedIds) {
Profiler.enter("updateCaptions");
/*
* Find all components that might need a caption update based on
* pending state and hierarchy changes
*/
- HashSet<ServerConnector> needsCaptionUpdate = new HashSet<ServerConnector>(
- parentChanged);
+ FastStringSet needsCaptionUpdate = FastStringSet.create();
+ needsCaptionUpdate.addAll(parentChangedIds);
// Find components with potentially changed caption state
- for (StateChangeEvent event : pendingStateChangeEvents) {
+ int size = pendingStateChangeEvents.size();
+ for (int i = 0; i < size; i++) {
+ StateChangeEvent event = pendingStateChangeEvents.get(i);
if (VCaption.mightChange(event)) {
ServerConnector connector = event.getConnector();
- needsCaptionUpdate.add(connector);
+ needsCaptionUpdate.add(connector.getConnectorId());
}
}
+ ConnectorMap connectorMap = getConnectorMap();
+
// Update captions for all suitable candidates
- for (ServerConnector child : needsCaptionUpdate) {
+ JsArrayString dump = needsCaptionUpdate.dump();
+ int needsUpdateLength = dump.length();
+ for (int i = 0; i < needsUpdateLength; i++) {
+ String childId = dump.get(i);
+ ServerConnector child = connectorMap.getConnector(childId);
if (child instanceof ComponentConnector
&& ((ComponentConnector) child)
.delegateCaptionHandling()) {
@@ -1604,29 +1610,45 @@ public class ApplicationConnection {
}
private void delegateToWidget(
- Collection<StateChangeEvent> pendingStateChangeEvents) {
+ JsArrayObject<StateChangeEvent> pendingStateChangeEvents) {
Profiler.enter("@DelegateToWidget");
VConsole.log(" * Running @DelegateToWidget");
- for (StateChangeEvent sce : pendingStateChangeEvents) {
+ // Keep track of types that have no @DelegateToWidget in their
+ // state to optimize performance
+ FastStringSet noOpTypes = FastStringSet.create();
+
+ int size = pendingStateChangeEvents.size();
+ for (int eventIndex = 0; eventIndex < size; eventIndex++) {
+ StateChangeEvent sce = pendingStateChangeEvents
+ .get(eventIndex);
ServerConnector connector = sce.getConnector();
if (connector instanceof ComponentConnector) {
+ String className = connector.getClass().getName();
+ if (noOpTypes.contains(className)) {
+ continue;
+ }
ComponentConnector component = (ComponentConnector) connector;
Type stateType = AbstractConnector
.getStateType(component);
+ JsArrayString delegateToWidgetProperties = stateType
+ .getDelegateToWidgetProperties();
+ if (delegateToWidgetProperties == null) {
+ noOpTypes.add(className);
+ continue;
+ }
- FastStringSet changedProperties = sce
- .getChangedPropertiesFastSet();
- JsArrayString dump = changedProperties.dump();
- for (int i = 0; i < dump.length(); i++) {
- String propertyName = dump.get(i);
- Property property = stateType
- .getProperty(propertyName);
- String method = property
- .getDelegateToWidgetMethodName();
- if (method != null) {
+ int length = delegateToWidgetProperties.length();
+ for (int i = 0; i < length; i++) {
+ String propertyName = delegateToWidgetProperties
+ .get(i);
+ if (sce.hasPropertyChanged(propertyName)) {
+ Property property = stateType
+ .getProperty(propertyName);
+ String method = property
+ .getDelegateToWidgetMethodName();
Profiler.enter("doDelegateToWidget");
doDelegateToWidget(component, property, method);
Profiler.leave("doDelegateToWidget");
@@ -1673,11 +1695,13 @@ public class ApplicationConnection {
* The events to send
*/
private void sendStateChangeEvents(
- Collection<StateChangeEvent> pendingStateChangeEvents) {
+ JsArrayObject<StateChangeEvent> pendingStateChangeEvents) {
Profiler.enter("sendStateChangeEvents");
VConsole.log(" * Sending state change events");
- for (StateChangeEvent sce : pendingStateChangeEvents) {
+ int size = pendingStateChangeEvents.size();
+ for (int i = 0; i < size; i++) {
+ StateChangeEvent sce = pendingStateChangeEvents.get(i);
try {
sce.getConnector().fireEvent(sce);
} catch (final Throwable e) {
@@ -1723,29 +1747,29 @@ public class ApplicationConnection {
Profiler.leave("unregisterRemovedConnectors");
}
- private Set<ServerConnector> createConnectorsIfNeeded(ValueMap json) {
+ private JsArrayString createConnectorsIfNeeded(ValueMap json) {
VConsole.log(" * Creating connectors (if needed)");
+ JsArrayString createdConnectors = JavaScriptObject
+ .createArray().cast();
if (!json.containsKey("types")) {
- return Collections.emptySet();
+ return createdConnectors;
}
Profiler.enter("Creating connectors");
- Set<ServerConnector> createdConnectors = new HashSet<ServerConnector>();
-
ValueMap types = json.getValueMap("types");
JsArrayString keyArray = types.getKeyArray();
for (int i = 0; i < keyArray.length(); i++) {
try {
String connectorId = keyArray.get(i);
- int connectorType = Integer.parseInt(types
- .getString((connectorId)));
ServerConnector connector = connectorMap
.getConnector(connectorId);
if (connector != null) {
continue;
}
+ int connectorType = Integer.parseInt(types
+ .getString(connectorId));
Class<? extends ServerConnector> connectorClass = configuration
.getConnectorClassByEncodedTag(connectorType);
@@ -1757,7 +1781,7 @@ public class ApplicationConnection {
connector = getConnector(connectorId, connectorType);
Profiler.leave("ApplicationConnection.getConnector");
- createdConnectors.add(connector);
+ createdConnectors.push(connectorId);
} else {
// First UIConnector update. Before this the
// UIConnector has been created but not
@@ -1767,7 +1791,7 @@ public class ApplicationConnection {
uIConnector);
uIConnector.doInit(connectorId,
ApplicationConnection.this);
- createdConnectors.add(uIConnector);
+ createdConnectors.push(connectorId);
}
} catch (final Throwable e) {
VConsole.error(e);
@@ -1829,14 +1853,16 @@ public class ApplicationConnection {
}
private void sendHierarchyChangeEvents(
- Collection<ConnectorHierarchyChangeEvent> pendingHierarchyChangeEvents) {
- if (pendingHierarchyChangeEvents.isEmpty()) {
+ JsArrayObject<ConnectorHierarchyChangeEvent> events) {
+ int eventCount = events.size();
+ if (eventCount == 0) {
return;
}
Profiler.enter("sendHierarchyChangeEvents");
VConsole.log(" * Sending hierarchy change events");
- for (ConnectorHierarchyChangeEvent event : pendingHierarchyChangeEvents) {
+ for (int i = 0; i < eventCount; i++) {
+ ConnectorHierarchyChangeEvent event = events.get(i);
try {
logHierarchyChange(event);
event.getConnector().fireEvent(event);
@@ -1871,9 +1897,10 @@ public class ApplicationConnection {
VConsole.log(newChildren);
}
- private Collection<StateChangeEvent> updateConnectorState(
- ValueMap json, Set<ServerConnector> newConnectors) {
- ArrayList<StateChangeEvent> events = new ArrayList<StateChangeEvent>();
+ private JsArrayObject<StateChangeEvent> updateConnectorState(
+ ValueMap json, JsArrayString createdConnectorIds) {
+ JsArrayObject<StateChangeEvent> events = JavaScriptObject
+ .createArray().cast();
VConsole.log(" * Updating connector states");
if (!json.containsKey("state")) {
return events;
@@ -1881,8 +1908,8 @@ public class ApplicationConnection {
Profiler.enter("updateConnectorState");
- HashSet<ServerConnector> remainingNewConnectors = new HashSet<ServerConnector>(
- newConnectors);
+ FastStringSet remainingNewConnectors = FastStringSet.create();
+ remainingNewConnectors.addAll(createdConnectorIds);
// set states for all paintables mentioned in "state"
ValueMap states = json.getValueMap("state");
@@ -1923,22 +1950,15 @@ public class ApplicationConnection {
}
Profiler.enter("updateConnectorState create event");
- FastStringSet changedProperties = FastStringSet
- .create();
- addJsonFields(stateJson, changedProperties, "");
-
- if (newConnectors.contains(connector)) {
- remainingNewConnectors.remove(connector);
- // Fire events for properties using the default
- // value for newly created connectors
- FastStringSet allStateFields = getAllStateFields(AbstractConnector
- .getStateType(connector));
- changedProperties.addAll(allStateFields);
+
+ boolean isNewConnector = remainingNewConnectors
+ .contains(connectorId);
+ if (isNewConnector) {
+ remainingNewConnectors.remove(connectorId);
}
StateChangeEvent event = new StateChangeEvent(
- connector, changedProperties);
-
+ connector, stateJson, isNewConnector);
events.add(event);
Profiler.leave("updateConnectorState create event");
@@ -1952,12 +1972,15 @@ public class ApplicationConnection {
Profiler.enter("updateConnectorState newWithoutState");
// Fire events for properties using the default value for newly
// created connectors even if there were no state changes
- for (ServerConnector connector : remainingNewConnectors) {
- FastStringSet changedProperties = getAllStateFields(AbstractConnector
- .getStateType(connector));
+ JsArrayString dump = remainingNewConnectors.dump();
+ int length = dump.length();
+ for (int i = 0; i < length; i++) {
+ String connectorId = dump.get(i);
+ ServerConnector connector = connectorMap
+ .getConnector(connectorId);
StateChangeEvent event = new StateChangeEvent(connector,
- changedProperties);
+ new JSONObject(), true);
events.add(event);
@@ -1969,80 +1992,6 @@ public class ApplicationConnection {
return events;
}
- private FastStringSet getAllStateFields(Type type) {
- FastStringSet fields;
- fields = allStateFieldsCache.get(type.getBaseTypeName());
- if (fields == null) {
- Profiler.enter("getAllStateFields create");
- fields = FastStringSet.create();
- addAllStateFields(type, fields, "");
- allStateFieldsCache.put(type.getBaseTypeName(), fields);
- Profiler.leave("getAllStateFields create");
- }
- return fields;
- }
-
- /**
- * Recursively adds the names of all properties in the provided
- * state type.
- *
- * @param type
- * the type to process
- * @param foundProperties
- * a set of all currently added properties
- * @param context
- * the base name of the current object
- */
- private void addAllStateFields(Type type,
- FastStringSet foundProperties, String context) {
- try {
- JsArrayObject<Property> properties = type
- .getPropertiesAsArray();
- int size = properties.size();
- for (int i = 0; i < size; i++) {
- Property property = properties.get(i);
- String propertyName = context + property.getName();
- foundProperties.add(propertyName);
-
- Type propertyType = property.getType();
- if (propertyType.hasProperties()) {
- addAllStateFields(propertyType, foundProperties,
- propertyName + ".");
- }
- }
- } catch (NoDataException e) {
- throw new IllegalStateException(
- "No property info for "
- + type
- + ". Did you remember to compile the right widgetset?",
- e);
- }
- }
-
- /**
- * Recursively adds the names of all fields in all objects in the
- * provided json object.
- *
- * @param json
- * the json object to process
- * @param fields
- * a set of all currently added fields
- * @param context
- * the base name of the current object
- */
- private void addJsonFields(JSONObject json, FastStringSet fields,
- String context) {
- for (String key : json.keySet()) {
- String fieldName = context + key;
- fields.add(fieldName);
-
- JSONObject object = json.get(key).isObject();
- if (object != null) {
- addJsonFields(object, fields, fieldName + ".");
- }
- }
- }
-
/**
* Updates the connector hierarchy and returns a list of events that
* should be fired after update of the hierarchy and the state is
@@ -2106,7 +2055,7 @@ public class ApplicationConnection {
}
if (childConnector.getParent() != parentConnector) {
childConnector.setParent(parentConnector);
- result.parentChanged.add(childConnector);
+ result.parentChangedIds.add(childConnectorId);
// Not detached even if previously removed from
// parent
maybeDetached.remove(childConnectorId);
@@ -2191,7 +2140,7 @@ public class ApplicationConnection {
}
private void recursivelyDetach(ServerConnector connector,
- List<ConnectorHierarchyChangeEvent> events) {
+ JsArrayObject<ConnectorHierarchyChangeEvent> events) {
/*
* Reset state in an attempt to keep it consistent with the
@@ -3089,9 +3038,11 @@ public class ApplicationConnection {
*
* @param component
* the Paintable whose caption has changed
+ * @deprecated As of 7.0.2, has not had any effect for a long time
*/
+ @Deprecated
public void captionSizeUpdated(Widget widget) {
- componentCaptionSizeChanges.add(widget);
+ // This doesn't do anything, it's just kept here for compatibility
}
/**
diff --git a/client/src/com/vaadin/client/communication/StateChangeEvent.java b/client/src/com/vaadin/client/communication/StateChangeEvent.java
index 35187b03d4..e17a56aa69 100644
--- a/client/src/com/vaadin/client/communication/StateChangeEvent.java
+++ b/client/src/com/vaadin/client/communication/StateChangeEvent.java
@@ -19,10 +19,17 @@ import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.json.client.JSONObject;
import com.vaadin.client.FastStringSet;
+import com.vaadin.client.JsArrayObject;
+import com.vaadin.client.Profiler;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
+import com.vaadin.client.metadata.NoDataException;
+import com.vaadin.client.metadata.Property;
+import com.vaadin.client.ui.AbstractConnector;
public class StateChangeEvent extends
AbstractServerConnectorEvent<StateChangeHandler> {
@@ -31,14 +38,24 @@ public class StateChangeEvent extends
*/
public static final Type<StateChangeHandler> TYPE = new Type<StateChangeHandler>();
- private final FastStringSet changedProperties;
+ /**
+ * Used to cache a FastStringSet representation of the properties that have
+ * changed if one is needed.
+ */
+ @Deprecated
+ private FastStringSet changedProperties;
/**
* Used to cache a Set representation of the changedProperties if one is
* needed.
*/
+ @Deprecated
private Set<String> changedPropertiesSet;
+ private boolean isNewConnector = false;
+
+ private JSONObject stateJson;
+
@Override
public Type<StateChangeHandler> getAssociatedType() {
return TYPE;
@@ -52,14 +69,16 @@ public class StateChangeEvent extends
* @param changedPropertiesSet
* a set of names of the changed properties
* @deprecated As of 7.0.1, use
- * {@link #StateChangeEvent(ServerConnector, FastStringSet)}
+ * {@link #StateChangeEvent(ServerConnector, JSONObject, boolean)}
* instead for improved performance.
*/
@Deprecated
public StateChangeEvent(ServerConnector connector,
Set<String> changedPropertiesSet) {
setConnector(connector);
+ // Keep instance around for caching
this.changedPropertiesSet = changedPropertiesSet;
+
changedProperties = FastStringSet.create();
for (String property : changedPropertiesSet) {
changedProperties.add(property);
@@ -73,13 +92,35 @@ public class StateChangeEvent extends
* the event whose state has changed
* @param changedProperties
* a set of names of the changed properties
+ * @deprecated As of 7.0.2, use
+ * {@link #StateChangeEvent(ServerConnector, JSONObject, boolean)}
+ * instead for improved performance.
*/
+ @Deprecated
public StateChangeEvent(ServerConnector connector,
FastStringSet changedProperties) {
setConnector(connector);
this.changedProperties = changedProperties;
}
+ /**
+ * /** Creates a new state change event.
+ *
+ * @param connector
+ * the event whose state has changed
+ * @param stateJson
+ * the JSON representation of the state change
+ * @param isNewConnector
+ * <code>true</code> if the state change is for a new connector,
+ * otherwise <code>false</code>
+ */
+ public StateChangeEvent(ServerConnector connector, JSONObject stateJson,
+ boolean isNewConnector) {
+ setConnector(connector);
+ this.stateJson = stateJson;
+ this.isNewConnector = isNewConnector;
+ }
+
@Override
public void dispatch(StateChangeHandler listener) {
listener.onStateChanged(this);
@@ -108,15 +149,16 @@ public class StateChangeEvent extends
*
* @return a set of names of the changed properties
*
- * @deprecated As of 7.0.1, use {@link #getChangedPropertiesFastSet()} or
- * {@link #hasPropertyChanged(String)} instead for improved
- * performance.
+ * @deprecated As of 7.0.1, use {@link #hasPropertyChanged(String)} instead
+ * for improved performance.
*/
@Deprecated
public Set<String> getChangedProperties() {
if (changedPropertiesSet == null) {
+ Profiler.enter("StateChangeEvent.getChangedProperties populate");
changedPropertiesSet = new HashSet<String>();
- changedProperties.addAllTo(changedPropertiesSet);
+ getChangedPropertiesFastSet().addAllTo(changedPropertiesSet);
+ Profiler.leave("StateChangeEvent.getChangedProperties populate");
}
return changedPropertiesSet;
}
@@ -126,8 +168,24 @@ public class StateChangeEvent extends
*
* @return a set of names of the changed properties
*
+ * @deprecated As of 7.0.1, use {@link #hasPropertyChanged(String)} instead
+ * for improved performance.
*/
+ @Deprecated
public FastStringSet getChangedPropertiesFastSet() {
+ if (changedProperties == null) {
+ Profiler.enter("StateChangeEvent.getChangedPropertiesFastSet populate");
+ changedProperties = FastStringSet.create();
+
+ addJsonFields(stateJson, changedProperties, "");
+ if (isNewConnector) {
+ addAllStateFields(
+ AbstractConnector.getStateType(getConnector()),
+ changedProperties, "");
+ }
+
+ Profiler.leave("StateChangeEvent.getChangedPropertiesFastSet populate");
+ }
return changedProperties;
}
@@ -140,6 +198,115 @@ public class StateChangeEvent extends
* <code>false></code>
*/
public boolean hasPropertyChanged(String property) {
- return changedProperties.contains(property);
+ if (isNewConnector) {
+ // Everything has changed for a new connector
+ return true;
+ } else if (stateJson != null) {
+ // Check whether it's in the json object
+ return isInJson(property, stateJson.getJavaScriptObject());
+ } else {
+ // Legacy cases
+ if (changedProperties != null) {
+ // Check legacy stuff
+ return changedProperties.contains(property);
+ } else if (changedPropertiesSet != null) {
+ // Check legacy stuff
+ return changedPropertiesSet.contains(property);
+ } else {
+ throw new IllegalStateException(
+ "StateChangeEvent should have either stateJson, changedProperties or changePropertiesSet");
+ }
+ }
+ }
+
+ /**
+ * Checks whether the given property name (which might contains dots) is
+ * defined in some JavaScript object.
+ *
+ * @param property
+ * the name of the property, might include dots to reference
+ * inner objects
+ * @param target
+ * the JavaScript object to check
+ * @return true if the property is defined
+ */
+ private static native final boolean isInJson(String property,
+ JavaScriptObject target)
+ /*-{
+ var segments = property.split('.');
+ while (typeof target == 'object') {
+ var nextSegment = segments.shift();
+ if (!(nextSegment in target)) {
+ // Abort if segment is not found
+ return false;
+ } else if (segments.length == 0) {
+ // Done if there are no more segments
+ return true;
+ } else {
+ // Else just go deeper
+ target = target[nextSegment];
+ }
+ }
+ // Not defined if we reach something that isn't an object
+ return false;
+ }-*/;
+
+ /**
+ * Recursively adds the names of all properties in the provided state type.
+ *
+ * @param type
+ * the type to process
+ * @param changedProperties
+ * a set of all currently added properties
+ * @param context
+ * the base name of the current object
+ */
+ @Deprecated
+ private static void addAllStateFields(com.vaadin.client.metadata.Type type,
+ FastStringSet changedProperties, String context) {
+ try {
+ JsArrayObject<Property> properties = type.getPropertiesAsArray();
+ int size = properties.size();
+ for (int i = 0; i < size; i++) {
+ Property property = properties.get(i);
+ String propertyName = context + property.getName();
+ changedProperties.add(propertyName);
+
+ com.vaadin.client.metadata.Type propertyType = property
+ .getType();
+ if (propertyType.hasProperties()) {
+ addAllStateFields(propertyType, changedProperties,
+ propertyName + ".");
+ }
+ }
+ } catch (NoDataException e) {
+ throw new IllegalStateException("No property info for " + type
+ + ". Did you remember to compile the right widgetset?", e);
+ }
+ }
+
+ /**
+ * Recursively adds the names of all fields in all objects in the provided
+ * json object.
+ *
+ * @param json
+ * the json object to process
+ * @param changedProperties
+ * a set of all currently added fields
+ * @param context
+ * the base name of the current object
+ */
+ @Deprecated
+ private static void addJsonFields(JSONObject json,
+ FastStringSet changedProperties, String context) {
+ for (String key : json.keySet()) {
+ String fieldName = context + key;
+ changedProperties.add(fieldName);
+
+ JSONObject object = json.get(key).isObject();
+ if (object != null) {
+ addJsonFields(object, changedProperties, fieldName + ".");
+ }
+ }
}
}
diff --git a/client/src/com/vaadin/client/metadata/Type.java b/client/src/com/vaadin/client/metadata/Type.java
index 9c8a52d8e5..c09dffa638 100644
--- a/client/src/com/vaadin/client/metadata/Type.java
+++ b/client/src/com/vaadin/client/metadata/Type.java
@@ -17,6 +17,7 @@ package com.vaadin.client.metadata;
import java.util.Collection;
+import com.google.gwt.core.client.JsArrayString;
import com.vaadin.client.JsArrayObject;
import com.vaadin.client.communication.JSONSerializer;
@@ -138,4 +139,8 @@ public class Type {
return TypeDataStore.hasProperties(this);
}
+ public JsArrayString getDelegateToWidgetProperties() {
+ return TypeDataStore.getDelegateToWidgetProperites(this);
+ }
+
}
diff --git a/client/src/com/vaadin/client/metadata/TypeDataStore.java b/client/src/com/vaadin/client/metadata/TypeDataStore.java
index c1eca0a168..dff02749f8 100644
--- a/client/src/com/vaadin/client/metadata/TypeDataStore.java
+++ b/client/src/com/vaadin/client/metadata/TypeDataStore.java
@@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.Collection;
import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArrayString;
import com.vaadin.client.FastStringMap;
import com.vaadin.client.FastStringSet;
import com.vaadin.client.JsArrayObject;
@@ -35,6 +36,8 @@ public class TypeDataStore {
.create();
private final FastStringMap<JsArrayObject<Property>> properties = FastStringMap
.create();
+ private final FastStringMap<JsArrayString> delegateToWidgetProperties = FastStringMap
+ .create();
private final FastStringSet delayedMethods = FastStringSet.create();
private final FastStringSet lastOnlyMethods = FastStringSet.create();
@@ -118,11 +121,22 @@ public class TypeDataStore {
return get().delegateToWidget.get(property.getSignature());
}
+ public static JsArrayString getDelegateToWidgetProperites(Type type) {
+ return get().delegateToWidgetProperties.get(type.getSignature());
+ }
+
public void setDelegateToWidget(Class<?> clazz, String propertyName,
String delegateValue) {
- delegateToWidget.put(
- new Property(getType(clazz), propertyName).getSignature(),
+ Type type = getType(clazz);
+ delegateToWidget.put(new Property(type, propertyName).getSignature(),
delegateValue);
+ JsArrayString typeProperties = delegateToWidgetProperties.get(type
+ .getSignature());
+ if (typeProperties == null) {
+ typeProperties = JavaScriptObject.createArray().cast();
+ delegateToWidgetProperties.put(type.getSignature(), typeProperties);
+ }
+ typeProperties.push(propertyName);
}
public void setReturnType(Class<?> type, String methodName, Type returnType) {