diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-08-22 17:07:22 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-08-22 19:25:32 +0300 |
commit | 02878bd07a38dc69fe415c7f60238817d2a7c434 (patch) | |
tree | ebae730a5108dca70be31039ebc6b30884436fa7 /client | |
parent | e345e1820aa0e0fe551cca86d6d28b906beb8937 (diff) | |
download | vaadin-framework-02878bd07a38dc69fe415c7f60238817d2a7c434.tar.gz vaadin-framework-02878bd07a38dc69fe415c7f60238817d2a7c434.zip |
Use ConnectorBundle for JSON encoding and decoding (#9371)
Diffstat (limited to 'client')
10 files changed, 171 insertions, 135 deletions
diff --git a/client/src/com/vaadin/Vaadin.gwt.xml b/client/src/com/vaadin/Vaadin.gwt.xml index fe9643232e..44357b24a0 100644 --- a/client/src/com/vaadin/Vaadin.gwt.xml +++ b/client/src/com/vaadin/Vaadin.gwt.xml @@ -23,14 +23,6 @@ <when-type-is class="com.google.gwt.core.client.impl.SchedulerImpl" /> </replace-with> - <!-- Generators for serializators for classes used in communication between - server and client --> - <generate-with - class="com.vaadin.terminal.gwt.widgetsetutils.SerializerMapGenerator"> - <when-type-is - class="com.vaadin.terminal.gwt.client.communication.SerializerMap" /> - </generate-with> - <replace-with class="com.vaadin.terminal.gwt.client.VDebugConsole"> <when-type-is class="com.vaadin.terminal.gwt.client.Console" /> </replace-with> diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 9b58eb1295..7e1c505fe9 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -65,7 +65,6 @@ import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper import com.vaadin.terminal.gwt.client.communication.JsonDecoder; import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.communication.RpcManager; -import com.vaadin.terminal.gwt.client.communication.SerializerMap; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector; import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; @@ -106,8 +105,6 @@ public class ApplicationConnection { public static final char VAR_ESCAPE_CHARACTER = '\u001b'; - private static SerializerMap serializerMap; - /** * 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 @@ -215,7 +212,6 @@ public class ApplicationConnection { rpcManager = GWT.create(RpcManager.class); layoutManager = GWT.create(LayoutManager.class); layoutManager.setConnection(this); - serializerMap = GWT.create(SerializerMap.class); } public void init(WidgetSet widgetSet, ApplicationConfiguration cnf) { @@ -2577,8 +2573,4 @@ public class ApplicationConnection { LayoutManager getLayoutManager() { return layoutManager; } - - public SerializerMap getSerializerMap() { - return serializerMap; - } } diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/client/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index ef5090ec18..a98d08c368 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -31,6 +31,8 @@ import com.google.gwt.json.client.JSONValue; import com.vaadin.shared.Connector; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ConnectorMap; +import com.vaadin.terminal.gwt.client.metadata.NoDataException; +import com.vaadin.terminal.gwt.client.metadata.Property; import com.vaadin.terminal.gwt.client.metadata.Type; /** @@ -106,18 +108,42 @@ public class JsonDecoder { private static Object decodeObject(Type type, JSONValue jsonValue, Object target, ApplicationConnection connection) { - JSONSerializer<Object> serializer = connection.getSerializerMap() - .getSerializer(type.getBaseTypeName()); - // TODO handle case with no serializer found - // Currently getSerializer throws exception if not found - - if (target != null && serializer instanceof DiffJSONSerializer<?>) { - DiffJSONSerializer<Object> diffSerializer = (DiffJSONSerializer<Object>) serializer; - diffSerializer.update(target, type, jsonValue, connection); - return target; + JSONSerializer<Object> serializer = (JSONSerializer<Object>) type + .findSerializer(); + if (serializer != null) { + if (target != null && serializer instanceof DiffJSONSerializer<?>) { + DiffJSONSerializer<Object> diffSerializer = (DiffJSONSerializer<Object>) serializer; + diffSerializer.update(target, type, jsonValue, connection); + return target; + } else { + Object object = serializer.deserialize(type, jsonValue, + connection); + return object; + } } else { - Object object = serializer.deserialize(type, jsonValue, connection); - return object; + try { + Collection<Property> properties = type.getProperties(); + if (target == null) { + target = type.createInstance(); + } + JSONObject jsonObject = jsonValue.isObject(); + + for (Property property : properties) { + JSONValue encodedPropertyValue = jsonObject.get(property + .getName()); + if (encodedPropertyValue == null) { + continue; + } + Object propertyReference = property.getValue(target); + Object decodedValue = decodeValue(property.getType(), + encodedPropertyValue, propertyReference, connection); + property.setValue(target, decodedValue); + } + return target; + } catch (NoDataException e) { + throw new RuntimeException("Can not deserialize " + + type.getSignature(), e); + } } } diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/client/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index 3730cad4c3..9b28da8b34 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -33,6 +33,9 @@ import com.vaadin.shared.Connector; import com.vaadin.shared.JsonConstants; import com.vaadin.shared.communication.UidlValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.metadata.NoDataException; +import com.vaadin.terminal.gwt.client.metadata.Property; +import com.vaadin.terminal.gwt.client.metadata.Type; /** * Encoder for converting RPC parameters and other values to JSON for transfer @@ -99,12 +102,33 @@ public class JsonEncoder { } else { // Try to find a generated serializer object, class name is the // type - transportType = value.getClass().getName(); - JSONSerializer serializer = connection.getSerializerMap() - .getSerializer(transportType); + Type type = new Type(value.getClass()); + + JSONSerializer<Object> serializer = (JSONSerializer<Object>) type + .findSerializer(); + if (serializer != null) { + return serializer.serialize(value, connection); + } else { + try { + Collection<Property> properties = type.getProperties(); + + JSONObject jsonObject = new JSONObject(); + for (Property property : properties) { + Object propertyValue = property.getValue(value); + JSONValue encodedPropertyValue = encode( + propertyValue, restrictToInternalTypes, + connection); + jsonObject.put(property.getName(), + encodedPropertyValue); + } + return jsonObject; + + } catch (NoDataException e) { + throw new RuntimeException("Can not encode " + + type.getSignature(), e); + } + } - // TODO handle case with no serializer found - return serializer.serialize(value, connection); } } } diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/SerializerMap.java b/client/src/com/vaadin/terminal/gwt/client/communication/SerializerMap.java deleted file mode 100644 index 77df4c7b08..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/SerializerMap.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.client.communication; - -/** - * Provide a mapping from a type (communicated between the server and the - * client) and a {@link JSONSerializer} instance. - * - * An implementation of this class is created at GWT compilation time by - * SerializerMapGenerator, so this interface can be instantiated with - * GWT.create(). - * - * @since 7.0 - */ -public interface SerializerMap { - - /** - * Returns a serializer instance for a given type. - * - * @param type - * type communicated on between the server and the client - * (currently fully qualified class name) - * @return serializer instance, not null - * @throws RuntimeException - * if no serializer is found - */ - // TODO better error handling in javadoc and in generator - public JSONSerializer getSerializer(String type); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/Type.java b/client/src/com/vaadin/terminal/gwt/client/communication/Type.java deleted file mode 100644 index ff93234a1d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/Type.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.client.communication; - -public class Type { - private final String baseTypeName; - private final Type[] parameterTypes; - - public Type(String baseTypeName, Type[] parameterTypes) { - this.baseTypeName = baseTypeName; - this.parameterTypes = parameterTypes; - } - - public String getBaseTypeName() { - return baseTypeName; - } - - public Type[] getParameterTypes() { - return parameterTypes; - } - - @Override - public String toString() { - String string = baseTypeName; - if (parameterTypes != null) { - string += '<'; - for (int i = 0; i < parameterTypes.length; i++) { - if (i != 0) { - string += ','; - } - string += parameterTypes[i].toString(); - } - string += '>'; - } - - return string; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java index 5f6a839da6..33e8776429 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java @@ -5,5 +5,5 @@ package com.vaadin.terminal.gwt.client.metadata; public interface Invoker { - public Object invoke(Object target, Object[] params); + public Object invoke(Object target, Object... params); } diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java index 30d864a43f..082d032e64 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java @@ -5,16 +5,20 @@ package com.vaadin.terminal.gwt.client.metadata; public class Property { - private final Type type; + private final Type bean; private final String name; - public Property(Type type, String name) { - this.type = type; + public Property(Type bean, String name) { + this.bean = bean; this.name = name; } public Object getValue(Object bean) throws NoDataException { - return TypeDataStore.getGetter(this).invoke(bean, null); + return TypeDataStore.getGetter(this).invoke(bean); + } + + public void setValue(Object bean, Object value) throws NoDataException { + TypeDataStore.getSetter(this).invoke(bean, value); } public String getDelegateToWidgetMethod() { @@ -29,8 +33,12 @@ public class Property { } } + public Type getType() throws NoDataException { + return TypeDataStore.getType(this); + } + public String getSignature() { - return type.toString() + "." + name; + return bean.toString() + "." + name; } @Override @@ -50,4 +58,13 @@ public class Property { return getSignature().hashCode(); } + public String getName() { + return name; + } + + @Override + public String toString() { + return getSignature(); + } + } diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java index 2dc5182845..d869cc2599 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java @@ -3,6 +3,10 @@ */ package com.vaadin.terminal.gwt.client.metadata; +import java.util.Collection; + +import com.vaadin.terminal.gwt.client.communication.JSONSerializer; + public class Type { private final String name; private final Type[] parameterTypes; @@ -27,13 +31,17 @@ public class Type { public Object createInstance() throws NoDataException { Invoker invoker = TypeDataStore.getConstructor(this); - return invoker.invoke(null, null); + return invoker.invoke(null); } public Method getMethod(String name) { return new Method(this, name); } + public Collection<Property> getProperties() throws NoDataException { + return TypeDataStore.getProperties(this); + } + public Property getProperty(String propertyName) { return new Property(this, propertyName); } @@ -82,4 +90,8 @@ public class Type { .createProxy(invokationHandler); } + public JSONSerializer<?> findSerializer() { + return TypeDataStore.findSerializer(this); + } + } diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java index f056e46d2d..55740f69da 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java @@ -4,17 +4,23 @@ package com.vaadin.terminal.gwt.client.metadata; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import com.vaadin.terminal.gwt.client.communication.JSONSerializer; + public class TypeDataStore { private static final String CONSTRUCTOR_NAME = "!new"; private final Map<String, Class<?>> identifiers = new HashMap<String, Class<?>>(); + private final Map<Type, Invoker> serializerFactories = new HashMap<Type, Invoker>(); private final Map<Type, ProxyHandler> proxyHandlers = new HashMap<Type, ProxyHandler>(); + private final Map<Type, Collection<Property>> properties = new HashMap<Type, Collection<Property>>(); private final Set<Method> delayedMethods = new HashSet<Method>(); private final Set<Method> lastonlyMethods = new HashSet<Method>(); @@ -23,6 +29,8 @@ public class TypeDataStore { private final Map<Method, Invoker> invokers = new HashMap<Method, Invoker>(); private final Map<Method, Type[]> paramTypes = new HashMap<Method, Type[]>(); + private final Map<Property, Type> propertyTypes = new HashMap<Property, Type>(); + private final Map<Property, Invoker> setters = new HashMap<Property, Invoker>(); private final Map<Property, Invoker> getters = new HashMap<Property, Invoker>(); private final Map<Property, String> delegateToWidget = new HashMap<Property, String>(); @@ -85,6 +93,10 @@ public class TypeDataStore { return getter; } + public void setGetter(Class<?> clazz, String propertyName, Invoker invoker) { + getters.put(new Property(getType(clazz), propertyName), invoker); + } + public static String getDelegateToWidget(Property property) { return get().delegateToWidget.get(property); } @@ -148,4 +160,61 @@ public class TypeDataStore { public void setLastonly(Class<?> clazz, String methodName) { lastonlyMethods.add(getType(clazz).getMethod(methodName)); } + + public static Collection<Property> getProperties(Type type) + throws NoDataException { + Collection<Property> properties = get().properties.get(type); + if (properties == null) { + throw new NoDataException("No property list for " + + type.getSignature()); + } + return properties; + } + + public void setProperties(Class<?> clazz, String[] propertyNames) { + Set<Property> properties = new HashSet<Property>(); + Type type = getType(clazz); + for (String name : propertyNames) { + properties.add(new Property(type, name)); + } + this.properties.put(type, Collections.unmodifiableSet(properties)); + } + + public static Type getType(Property property) throws NoDataException { + Type type = get().propertyTypes.get(property); + if (type == null) { + throw new NoDataException("No return type for " + + property.getSignature()); + } + return type; + } + + public void setPropertyType(Class<?> clazz, String propertName, Type type) { + propertyTypes.put(new Property(getType(clazz), propertName), type); + } + + public static Invoker getSetter(Property property) throws NoDataException { + Invoker setter = get().setters.get(property); + if (setter == null) { + throw new NoDataException("No setter for " + + property.getSignature()); + } + return setter; + } + + public void setSetter(Class<?> clazz, String propertyName, Invoker setter) { + setters.put(new Property(getType(clazz), propertyName), setter); + } + + public void setSerializerFactory(Class<?> clazz, Invoker factory) { + serializerFactories.put(getType(clazz), factory); + } + + public static JSONSerializer<?> findSerializer(Type type) { + Invoker factoryCreator = get().serializerFactories.get(type); + if (factoryCreator == null) { + return null; + } + return (JSONSerializer<?>) factoryCreator.invoke(null); + } } |