123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- /*
- * Copyright 2000-2016 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.client.communication;
-
- 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.vaadin.client.FastStringSet;
- import com.vaadin.client.JsArrayObject;
- import com.vaadin.client.Profiler;
- import com.vaadin.client.ServerConnector;
- import com.vaadin.client.Util;
- 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;
-
- import elemental.json.JsonObject;
-
- public class StateChangeEvent
- extends AbstractServerConnectorEvent<StateChangeHandler> {
- /**
- * Type of this event, used by the event bus.
- */
- public static final Type<StateChangeHandler> TYPE = new Type<>();
-
- /**
- * 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 initialStateChange = false;
-
- private JsonObject stateJson;
-
- @Override
- public Type<StateChangeHandler> getAssociatedType() {
- return TYPE;
- }
-
- /**
- * Creates a new state change event.
- *
- * @param connector
- * the event whose state has changed
- * @param changedPropertiesSet
- * a set of names of the changed properties
- * @deprecated As of 7.0.1, use
- * {@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);
- }
- }
-
- /**
- * Creates a new state change event.
- *
- * @param connector
- * 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 initialStateChange
- * <code>true</code> if the state change is for a new connector,
- * otherwise <code>false</code>
- */
- public StateChangeEvent(ServerConnector connector, JsonObject stateJson,
- boolean initialStateChange) {
- setConnector(connector);
- this.stateJson = stateJson;
- this.initialStateChange = initialStateChange;
- }
-
- @Override
- public void dispatch(StateChangeHandler listener) {
- listener.onStateChanged(this);
- }
-
- /**
- * Event handler that gets notified whenever any part of the state has been
- * updated by the server.
- *
- * @author Vaadin Ltd
- * @version @VERSION@
- * @since 7.0.0
- */
- public interface StateChangeHandler extends Serializable, EventHandler {
- /**
- * Notifies the event handler that the state has changed.
- *
- * @param stateChangeEvent
- * the state change event with details about the change
- */
- public void onStateChanged(StateChangeEvent stateChangeEvent);
- }
-
- /**
- * Gets the properties that have changed.
- *
- * @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 Set<String> getChangedProperties() {
- if (changedPropertiesSet == null) {
- Profiler.enter("StateChangeEvent.getChangedProperties populate");
- changedPropertiesSet = new HashSet<>();
- getChangedPropertiesFastSet().addAllTo(changedPropertiesSet);
- Profiler.leave("StateChangeEvent.getChangedProperties populate");
- }
- return changedPropertiesSet;
- }
-
- /**
- * Gets the properties that have changed.
- *
- * @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 (isInitialStateChange()) {
- addAllStateFields(
- AbstractConnector.getStateType(getConnector()),
- changedProperties, "");
- }
-
- Profiler.leave(
- "StateChangeEvent.getChangedPropertiesFastSet populate");
- }
- return changedProperties;
- }
-
- /**
- * Checks whether the give property has changed.
- *
- * @param property
- * the name of the property to check
- * @return <code>true</code> if the property has changed, else
- * <code>false></code>
- */
- public boolean hasPropertyChanged(String property) {
- if (isInitialStateChange()) {
- // Everything has changed for a new connector
- return true;
- } else if (stateJson != null) {
- // Check whether it's in the json object
- return isInJson(property, Util.json2jso(stateJson));
- } 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.keys()) {
- String fieldName = context + key;
- changedProperties.add(fieldName);
-
- JsonObject object = json.get(key);
- if (object != null) {
- addJsonFields(object, changedProperties, fieldName + ".");
- }
- }
- }
-
- /**
- * Checks if the state change event is the first one for the given
- * connector.
- *
- * @since 7.1
- * @return true if this is the first state change event for the connector,
- * false otherwise
- */
- public boolean isInitialStateChange() {
- return initialStateChange;
- }
-
- }
|