diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-08-17 18:11:54 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-08-22 19:25:30 +0300 |
commit | 1a7d126e358d92850a41060b06d53309f2ac58f0 (patch) | |
tree | 3ceca4be0eeeffcc59a0f19dd28d298f9238c9d2 /client/src/com/vaadin | |
parent | 88776600733901f3f9891aa90a11a5aeb2b97ef4 (diff) | |
download | vaadin-framework-1a7d126e358d92850a41060b06d53309f2ac58f0.tar.gz vaadin-framework-1a7d126e358d92850a41060b06d53309f2ac58f0.zip |
Initial ConnectorBundle implementation (#9371)
Diffstat (limited to 'client/src/com/vaadin')
20 files changed, 582 insertions, 121 deletions
diff --git a/client/src/com/vaadin/Vaadin.gwt.xml b/client/src/com/vaadin/Vaadin.gwt.xml index 07d7c941e6..5a9909a29c 100644 --- a/client/src/com/vaadin/Vaadin.gwt.xml +++ b/client/src/com/vaadin/Vaadin.gwt.xml @@ -36,11 +36,6 @@ </replace-with> <generate-with - class="com.vaadin.terminal.gwt.widgetsetutils.EagerWidgetMapGenerator"> - <when-type-is class="com.vaadin.terminal.gwt.client.WidgetMap" /> - </generate-with> - - <generate-with class="com.vaadin.terminal.gwt.widgetsetutils.AcceptCriteriaFactoryGenerator"> <when-type-is class="com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterionFactory" /> @@ -78,6 +73,10 @@ <when-type-assignable class="com.vaadin.terminal.gwt.client.ui.ConnectorStateFactory" /> </generate-with> + + <generate-with class="com.vaadin.terminal.gwt.widgetsetutils.ConnectorBundleLoaderFactory"> + <when-type-assignable class="com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader" /> + </generate-with> <!-- Use the new cross site linker to get a nocache.js without document.write --> <add-linker name="xsiframe" /> diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java index eea60b04ea..8f6697288c 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java @@ -29,9 +29,11 @@ import com.google.gwt.core.client.JsArrayString; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.vaadin.shared.ApplicationConstants; +import com.vaadin.terminal.gwt.client.metadata.BundleLoadCallback; +import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; +import com.vaadin.terminal.gwt.client.metadata.TypeData; import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector; public class ApplicationConfiguration implements EntryPoint { @@ -207,7 +209,7 @@ public class ApplicationConfiguration implements EntryPoint { private HashMap<Integer, String> unknownComponents; - private Class<? extends ServerConnector>[] classes = new Class[1024]; + private Map<Integer, Class<? extends ServerConnector>> classes = new HashMap<Integer, Class<? extends ServerConnector>>(); private boolean browserDetailsSent = false; private boolean widgetsetVersionSent = false; @@ -390,12 +392,26 @@ public class ApplicationConfiguration implements EntryPoint { public Class<? extends ServerConnector> getConnectorClassByEncodedTag( int tag) { - try { - return classes[tag]; - } catch (Exception e) { - // component was not present in mappings - return UnknownComponentConnector.class; + Class<? extends ServerConnector> type = classes.get(tag); + if (type == null && !classes.containsKey(tag)) { + // Initialize if not already loaded + Integer currentTag = Integer.valueOf(tag); + while (type == null && currentTag != null) { + String serverSideClassNameForTag = getServerSideClassNameForTag(currentTag); + type = (Class<? extends ServerConnector>) TypeData + .getClass(serverSideClassNameForTag); + currentTag = getParentTag(currentTag.intValue()); + } + if (type == null) { + type = UnknownComponentConnector.class; + if (unknownComponents == null) { + unknownComponents = new HashMap<Integer, String>(); + } + unknownComponents.put(tag, getServerSideClassNameForTag(tag)); + } + classes.put(tag, type); } + return type; } public void addComponentInheritanceInfo(ValueMap valueMap) { @@ -418,13 +434,7 @@ public class ApplicationConfiguration implements EntryPoint { for (int i = 0; i < keyArray.length(); i++) { String key = keyArray.get(i).intern(); int value = valueMap.getInt(key); - classes[value] = widgetSet.getConnectorClassByTag(value, this); - if (classes[value] == UnknownComponentConnector.class) { - if (unknownComponents == null) { - unknownComponents = new HashMap<Integer, String>(); - } - unknownComponents.put(value, key); - } + widgetSet.ensureConnectorLoaded(value, this); } } @@ -466,86 +476,25 @@ public class ApplicationConfiguration implements EntryPoint { cmd.execute(); } callbacks.clear(); - } else if (dependenciesLoading == 0 && deferredWidgetLoader != null) { - deferredWidgetLoader.trigger(); + } else if (dependenciesLoading == 0 + && !ConnectorBundleLoader.get().isBundleLoaded( + ConnectorBundleLoader.DEFERRED_BUNDLE_NAME)) { + ConnectorBundleLoader.get().loadBundle( + ConnectorBundleLoader.DEFERRED_BUNDLE_NAME, + new BundleLoadCallback() { + @Override + public void loaded() { + // Nothing to do + } + + @Override + public void failed(Throwable reason) { + VConsole.error(reason); + } + }); } - } - /* - * This loop loads widget implementation that should be loaded deferred. - */ - static class DeferredWidgetLoader extends Timer { - private static final int FREE_LIMIT = 4; - private static final int FREE_CHECK_TIMEOUT = 100; - - int communicationFree = 0; - int nextWidgetIndex = 0; - private boolean pending; - - public DeferredWidgetLoader() { - schedule(5000); - } - - public void trigger() { - if (!pending) { - schedule(FREE_CHECK_TIMEOUT); - } - } - - @Override - public void schedule(int delayMillis) { - super.schedule(delayMillis); - pending = true; - } - - @Override - public void run() { - pending = false; - if (!isBusy()) { - Class<? extends ServerConnector> nextType = getNextType(); - if (nextType == null) { - // ensured that all widgets are loaded - deferredWidgetLoader = null; - } else { - communicationFree = 0; - widgetSet.loadImplementation(nextType); - } - } else { - schedule(FREE_CHECK_TIMEOUT); - } - } - - private Class<? extends ServerConnector> getNextType() { - Class<? extends ServerConnector>[] deferredLoadedConnectors = widgetSet - .getDeferredLoadedConnectors(); - if (deferredLoadedConnectors.length <= nextWidgetIndex) { - return null; - } else { - return deferredLoadedConnectors[nextWidgetIndex++]; - } - } - - private boolean isBusy() { - if (dependenciesLoading > 0) { - communicationFree = 0; - return true; - } - for (ApplicationConnection app : runningApplications) { - if (app.hasActiveRequest()) { - // if an UIDL request or widget loading is active, mark as - // busy - communicationFree = 0; - return true; - } - } - communicationFree++; - return communicationFree < FREE_LIMIT; - } - } - - private static DeferredWidgetLoader deferredWidgetLoader; - @Override public void onModuleLoad() { @@ -582,7 +531,6 @@ public class ApplicationConfiguration implements EntryPoint { return; } registerCallback(GWT.getModuleName()); - deferredWidgetLoader = new DeferredWidgetLoader(); } /** diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 32b15d6d87..9a14e5434e 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -67,8 +67,8 @@ 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.communication.Type; import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector; +import com.vaadin.terminal.gwt.client.metadata.Type; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.terminal.gwt.client.ui.VContextMenu; import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; diff --git a/client/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/client/src/com/vaadin/terminal/gwt/client/WidgetSet.java index fbcfbb68d9..776436f5f0 100644 --- a/client/src/com/vaadin/terminal/gwt/client/WidgetSet.java +++ b/client/src/com/vaadin/terminal/gwt/client/WidgetSet.java @@ -18,17 +18,12 @@ package com.vaadin.terminal.gwt.client; import com.google.gwt.core.client.GWT; import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper; +import com.vaadin.terminal.gwt.client.metadata.BundleLoadCallback; +import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; +import com.vaadin.terminal.gwt.client.metadata.TypeData; import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector; public class WidgetSet { - - /** - * WidgetSet (and its extensions) delegate instantiation of widgets and - * client-server matching to WidgetMap. The actual implementations are - * generated with gwts generators/deferred binding. - */ - private WidgetMap widgetMap = GWT.create(WidgetMap.class); - /** * Create an uninitialized connector that best matches given UIDL. The * connector must implement {@link ServerConnector}. @@ -65,7 +60,8 @@ public class WidgetSet { /* * let the auto generated code instantiate this type */ - ServerConnector connector = widgetMap.instantiate(classType); + ServerConnector connector = (ServerConnector) TypeData.getType( + classType).createInstance(); if (connector instanceof HasJavaScriptConnectorHelper) { ((HasJavaScriptConnectorHelper) connector) .getJavascriptConnectorHelper().setTag(tag); @@ -102,26 +98,32 @@ public class WidgetSet { * @param applicationConfiguration * @return */ - public Class<? extends ServerConnector> getConnectorClassByTag(int tag, - ApplicationConfiguration conf) { - Class<? extends ServerConnector> connectorClass = null; + public void ensureConnectorLoaded(int tag, ApplicationConfiguration conf) { + ConnectorBundleLoader loader = ConnectorBundleLoader.get(); + String bundleName = null; Integer t = tag; do { String serverSideClassName = conf.getServerSideClassNameForTag(t); - connectorClass = widgetMap - .getConnectorClassForServerSideClassName(serverSideClassName); - t = conf.getParentTag(t); - } while (connectorClass == UnknownComponentConnector.class && t != null); + bundleName = loader.getBundleForIdentifier(serverSideClassName); - return connectorClass; - } + t = conf.getParentTag(t); + } while (bundleName == null && t != null); - public Class<? extends ServerConnector>[] getDeferredLoadedConnectors() { - return widgetMap.getDeferredLoadedConnectors(); - } + if (bundleName != null && !loader.isBundleLoaded(bundleName)) { + ApplicationConfiguration.startDependencyLoading(); + loader.loadBundle(bundleName, new BundleLoadCallback() { + @Override + public void loaded() { + ApplicationConfiguration.endDependencyLoading(); + } - public void loadImplementation(Class<? extends ServerConnector> nextType) { - widgetMap.ensureInstantiator(nextType); + @Override + public void failed(Throwable reason) { + VConsole.error(reason); + ApplicationConfiguration.endDependencyLoading(); + } + }); + } } } diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java b/client/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java index a3b96a6cb2..1d5415263f 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java @@ -17,6 +17,7 @@ package com.vaadin.terminal.gwt.client.communication; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.metadata.Type; public interface DiffJSONSerializer<T> extends JSONSerializer<T> { /** diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java b/client/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java index a8fe2c7ccc..c6b814a5c1 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java @@ -20,6 +20,7 @@ import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ConnectorMap; +import com.vaadin.terminal.gwt.client.metadata.Type; /** * Implementors of this interface knows how to serialize an Object of a given 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 7d2046982c..ef5090ec18 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,7 @@ 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.Type; /** * Client side decoder for decodeing shared state and other values from JSON diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java b/client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java index 04d0e3f56f..537cc34185 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java @@ -29,6 +29,7 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.VConsole; +import com.vaadin.terminal.gwt.client.metadata.Type; /** * Client side RPC manager that can invoke methods based on RPC calls received diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java b/client/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java index a47fa5eab2..1759fbb97f 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java @@ -16,6 +16,7 @@ package com.vaadin.terminal.gwt.client.communication; import com.vaadin.shared.communication.ClientRpc; +import com.vaadin.terminal.gwt.client.metadata.Type; public abstract class RpcMethod { private String interfaceName; diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/client/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java index f77553d3c0..3d2e4f3804 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -20,6 +20,7 @@ import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; import com.vaadin.shared.communication.URLReference; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.metadata.Type; public class URLReference_Serializer implements JSONSerializer<URLReference> { diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/AsyncBundleLoader.java b/client/src/com/vaadin/terminal/gwt/client/metadata/AsyncBundleLoader.java new file mode 100644 index 0000000000..e92e51b40d --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/AsyncBundleLoader.java @@ -0,0 +1,86 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public abstract class AsyncBundleLoader { + public enum State { + NOT_STARTED, LOADING, LOADED, ERROR; + } + + private State state = State.NOT_STARTED; + + private Throwable error = null; + + private List<BundleLoadCallback> callbacks = new ArrayList<BundleLoadCallback>(); + + private final String packageName; + + private final String[] indentifiers; + + public AsyncBundleLoader(String packageName, String[] indentifiers) { + this.packageName = packageName; + this.indentifiers = indentifiers; + } + + protected abstract void load(TypeDataStore store); + + public List<BundleLoadCallback> setError(Throwable error) { + assert state == State.LOADING; + state = State.ERROR; + this.error = error; + + return clearCallbacks(); + } + + public Throwable getError() { + return error; + } + + public State getState() { + return state; + } + + public List<BundleLoadCallback> getCallback() { + return Collections.unmodifiableList(callbacks); + } + + public void load(BundleLoadCallback callback, TypeDataStore store) { + assert state == State.NOT_STARTED; + state = State.LOADING; + callbacks.add(callback); + load(store); + } + + public void addCallback(BundleLoadCallback callback) { + assert state == State.LOADING; + callbacks.add(callback); + } + + public List<BundleLoadCallback> setLoaded() { + assert state == State.LOADING; + state = State.LOADED; + + return clearCallbacks(); + } + + private List<BundleLoadCallback> clearCallbacks() { + List<BundleLoadCallback> callbacks = this.callbacks; + this.callbacks = null; + return callbacks; + } + + public String getName() { + return packageName; + } + + public String[] getIndentifiers() { + return indentifiers; + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/BundleLoadCallback.java b/client/src/com/vaadin/terminal/gwt/client/metadata/BundleLoadCallback.java new file mode 100644 index 0000000000..c7fc735829 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/BundleLoadCallback.java @@ -0,0 +1,11 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +public interface BundleLoadCallback { + public void loaded(); + + public void failed(Throwable reason); +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/ConnectorBundleLoader.java b/client/src/com/vaadin/terminal/gwt/client/metadata/ConnectorBundleLoader.java new file mode 100644 index 0000000000..48a8430312 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/ConnectorBundleLoader.java @@ -0,0 +1,97 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gwt.core.shared.GWT; +import com.vaadin.terminal.gwt.client.metadata.AsyncBundleLoader.State; + +public abstract class ConnectorBundleLoader { + public static final String EAGER_BUNDLE_NAME = "__eager"; + public static final String DEFERRED_BUNDLE_NAME = "__deferred"; + + private static ConnectorBundleLoader impl; + + private Map<String, AsyncBundleLoader> asyncBlockLoaders = new HashMap<String, AsyncBundleLoader>(); + private Map<String, String> identifierToBundle = new HashMap<String, String>(); + + private final TypeDataStore datStore = new TypeDataStore(); + + public ConnectorBundleLoader() { + init(); + } + + public TypeDataStore getTypeDataStore() { + return datStore; + } + + public static ConnectorBundleLoader get() { + if (impl == null) { + impl = GWT.create(ConnectorBundleLoader.class); + } + return impl; + } + + public void loadBundle(String packageName, BundleLoadCallback callback) { + AsyncBundleLoader loader = asyncBlockLoaders.get(packageName); + switch (loader.getState()) { + case NOT_STARTED: + loader.load(callback, getTypeDataStore()); + break; + case LOADING: + loader.addCallback(callback); + break; + case LOADED: + callback.loaded(); + break; + case ERROR: + callback.failed(loader.getError()); + } + } + + public boolean isBundleLoaded(String bundleName) { + AsyncBundleLoader loader = asyncBlockLoaders.get(bundleName); + if (loader == null) { + throw new IllegalArgumentException("Bundle " + bundleName + + " not recognized"); + } + return loader.getState() == State.LOADED; + } + + public void setLoaded(String packageName) { + List<BundleLoadCallback> callbacks = asyncBlockLoaders.get(packageName) + .setLoaded(); + for (BundleLoadCallback callback : callbacks) { + callback.loaded(); + } + } + + public void setLoadFailure(String bundleName, Throwable reason) { + List<BundleLoadCallback> callbacks = asyncBlockLoaders.get(bundleName) + .setError(reason); + for (BundleLoadCallback callback : callbacks) { + callback.failed(reason); + } + } + + public String getBundleForIdentifier(String identifier) { + return identifierToBundle.get(identifier); + } + + protected void addAsyncBlockLoader(AsyncBundleLoader loader) { + String name = loader.getName(); + asyncBlockLoaders.put(name, loader); + String[] indentifiers = loader.getIndentifiers(); + for (String identifier : indentifiers) { + identifierToBundle.put(identifier, name); + } + } + + public abstract void init(); + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java new file mode 100644 index 0000000000..5f6a839da6 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java @@ -0,0 +1,9 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +public interface Invoker { + public Object invoke(Object target, Object[] params); +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Method.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Method.java new file mode 100644 index 0000000000..f164bc4bcf --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Method.java @@ -0,0 +1,54 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +public class Method { + + private final Type type; + private final String name; + + public Method(Type type, String name) { + this.type = type; + this.name = name; + } + + public Type getType() { + return type; + } + + public String getName() { + return name; + } + + public Type getReturnType() { + return TypeDataStore.getReturnType(this); + } + + public void invoke(Object target, Object... params) { + TypeDataStore.getInvoker(this).invoke(target, params); + } + + public String getSignature() { + return type.toString() + "." + name; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof Method) { + Method other = (Method) obj; + return other.getSignature().equals(getSignature()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return getSignature().hashCode(); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java new file mode 100644 index 0000000000..5f2b1ffb41 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java @@ -0,0 +1,53 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +public class Property { + private final Type type; + private final String name; + + public Property(Type type, String name) { + this.type = type; + this.name = name; + } + + public Object getValue(Object bean) { + return TypeDataStore.getGetter(this).invoke(bean, null); + } + + public String getDelegateToWidgetMethod() { + String value = TypeDataStore.getDelegateToWidget(this); + if (value == null) { + return null; + } else if (value.isEmpty()) { + return "set" + Character.toUpperCase(value.charAt(0)) + + value.substring(1); + } else { + return value; + } + } + + public String getSignature() { + return type.toString() + "." + name; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj instanceof Property) { + Property other = (Property) obj; + return getSignature().equals(other.getSignature()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return getSignature().hashCode(); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java new file mode 100644 index 0000000000..4fab296441 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java @@ -0,0 +1,79 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.metadata; + +public class Type { + private final String name; + private final Type[] parameterTypes; + + public Type(Class<?> clazz) { + name = clazz.getName(); + parameterTypes = null; + } + + public Type(String baseTypeName, Type[] parameterTypes) { + name = baseTypeName; + this.parameterTypes = parameterTypes; + } + + public String getBaseTypeName() { + return name; + } + + public Type[] getParameterTypes() { + return parameterTypes; + } + + public Object createInstance() { + Invoker invoker = TypeDataStore.getConstructor(this); + return invoker.invoke(null, null); + } + + public Method getMethod(String name) { + return new Method(this, name); + } + + public Property getProperty(String propertyName) { + return new Property(this, propertyName); + } + + public String getSignature() { + String string = name; + if (parameterTypes != null) { + string += '<'; + for (int i = 0; i < parameterTypes.length; i++) { + if (i != 0) { + string += ','; + } + string += parameterTypes[i].toString(); + } + string += '>'; + } + + return string; + } + + @Override + public String toString() { + return getSignature(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof Type) { + Type other = (Type) obj; + return other.getSignature().equals(getSignature()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return getSignature().hashCode(); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeData.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeData.java new file mode 100644 index 0000000000..6ee0b4ede0 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeData.java @@ -0,0 +1,20 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +public class TypeData { + + public static Type getType(Class<?> type) { + return TypeDataStore.getType(type); + } + + public static Type getType(String identifier) { + return TypeDataStore.getType(getClass(identifier)); + } + + public static Class<?> getClass(String identifier) { + return TypeDataStore.getClass(identifier); + } +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataBundle.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataBundle.java new file mode 100644 index 0000000000..cbde338ff2 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataBundle.java @@ -0,0 +1,33 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +import com.google.gwt.core.client.RunAsyncCallback; + +public abstract class TypeDataBundle implements RunAsyncCallback { + private final String name; + + public TypeDataBundle(String name) { + this.name = name; + } + + @Override + public void onSuccess() { + ConnectorBundleLoader loader = ConnectorBundleLoader.get(); + load(); + loader.setLoaded(getName()); + } + + @Override + public void onFailure(Throwable reason) { + ConnectorBundleLoader.get().setLoadFailure(getName(), reason); + } + + public abstract void load(); + + public String getName() { + return name; + } +} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java new file mode 100644 index 0000000000..4b224721e6 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java @@ -0,0 +1,64 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.metadata; + +import java.util.HashMap; +import java.util.Map; + +public class TypeDataStore { + private static final String CONSTRUCTOR_NAME = "!new"; + + private final Map<String, Class<?>> identifiers = new HashMap<String, Class<?>>(); + + private final Map<Method, Type> returnTypes = new HashMap<Method, Type>(); + private final Map<Method, Invoker> invokers = new HashMap<Method, Invoker>(); + + private final Map<Property, Invoker> getters = new HashMap<Property, Invoker>(); + private final Map<Property, String> delegateToWidget = new HashMap<Property, String>(); + + public static TypeDataStore get() { + return ConnectorBundleLoader.get().getTypeDataStore(); + } + + public void setClass(String identifier, Class<?> type) { + identifiers.put(identifier, type); + } + + public static Class<?> getClass(String identifier) { + return get().identifiers.get(identifier); + } + + public static Type getType(Class<?> clazz) { + return new Type(clazz); + } + + public static Type getReturnType(Method method) { + return get().returnTypes.get(method); + } + + public static Invoker getInvoker(Method method) { + return get().invokers.get(method); + } + + public static Invoker getConstructor(Type type) { + return get().invokers.get(new Method(type, CONSTRUCTOR_NAME)); + } + + public static Invoker getGetter(Property property) { + return get().getters.get(property); + } + + public static String getDelegateToWidget(Property property) { + return get().delegateToWidget.get(property); + } + + public void setReturnType(Class<?> type, String methodName, Type returnType) { + returnTypes.put(new Method(getType(type), methodName), returnType); + } + + public void setConstructor(Class<?> type, Invoker constructor) { + invokers.put(new Method(getType(type), CONSTRUCTOR_NAME), constructor); + } +} |