The presentation type parameter is stored so that decode works without implementers having to implement a getType method. Change-Id: Ia2b9f977f2bf6ed006379cda5eeb61674dd92ee0tags/7.4.0.beta1
@@ -61,7 +61,7 @@ import com.vaadin.server.widgetsetutils.metadata.ConnectorInitVisitor; | |||
import com.vaadin.server.widgetsetutils.metadata.GeneratedSerializer; | |||
import com.vaadin.server.widgetsetutils.metadata.OnStateChangeVisitor; | |||
import com.vaadin.server.widgetsetutils.metadata.Property; | |||
import com.vaadin.server.widgetsetutils.metadata.RendererInitVisitor; | |||
import com.vaadin.server.widgetsetutils.metadata.RendererVisitor; | |||
import com.vaadin.server.widgetsetutils.metadata.ServerRpcVisitor; | |||
import com.vaadin.server.widgetsetutils.metadata.StateInitVisitor; | |||
import com.vaadin.server.widgetsetutils.metadata.TypeVisitor; | |||
@@ -504,6 +504,7 @@ public class ConnectorBundleLoaderFactory extends Generator { | |||
// this after the JS property data has been initialized | |||
writePropertyTypes(logger, w, bundle); | |||
writeSerializers(logger, w, bundle); | |||
writePresentationTypes(w, bundle); | |||
writeDelegateToWidget(logger, w, bundle); | |||
writeOnStateChangeHandlers(logger, w, bundle); | |||
} | |||
@@ -680,6 +681,21 @@ public class ConnectorBundleLoaderFactory extends Generator { | |||
} | |||
} | |||
private void writePresentationTypes(SplittingSourceWriter w, | |||
ConnectorBundle bundle) { | |||
Map<JClassType, JType> presentationTypes = bundle | |||
.getPresentationTypes(); | |||
for (Entry<JClassType, JType> entry : presentationTypes.entrySet()) { | |||
w.print("store.setPresentationType("); | |||
writeClassLiteral(w, entry.getKey()); | |||
w.print(", "); | |||
writeClassLiteral(w, entry.getValue()); | |||
w.println(");"); | |||
w.splitIfNeeded(); | |||
} | |||
} | |||
private void writePropertyTypes(TreeLogger logger, SplittingSourceWriter w, | |||
ConnectorBundle bundle) { | |||
Set<Property> properties = bundle.getNeedsProperty(); | |||
@@ -1236,7 +1252,7 @@ public class ConnectorBundleLoaderFactory extends Generator { | |||
throws NotFoundException { | |||
List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList( | |||
new ConnectorInitVisitor(), new StateInitVisitor(), | |||
new WidgetInitVisitor(), new RendererInitVisitor(), | |||
new WidgetInitVisitor(), new RendererVisitor(), | |||
new ClientRpcVisitor(), new ServerRpcVisitor(), | |||
new OnStateChangeVisitor()); | |||
for (TypeVisitor typeVisitor : visitors) { |
@@ -59,6 +59,7 @@ public class ConnectorBundle { | |||
private final Set<JType> hasSerializeSupport = new HashSet<JType>(); | |||
private final Set<JType> needsSerializeSupport = new HashSet<JType>(); | |||
private final Map<JType, GeneratedSerializer> serializers = new HashMap<JType, GeneratedSerializer>(); | |||
private final Map<JClassType, JType> presentationTypes = new HashMap<JClassType, JType>(); | |||
private final Set<JClassType> needsSuperClass = new HashSet<JClassType>(); | |||
private final Set<JClassType> needsGwtConstructor = new HashSet<JClassType>(); | |||
@@ -306,6 +307,25 @@ public class ConnectorBundle { | |||
return Collections.unmodifiableMap(serializers); | |||
} | |||
public void setPresentationType(JClassType type, JType presentationType) { | |||
if (!hasPresentationType(type)) { | |||
presentationTypes.put(type, presentationType); | |||
} | |||
} | |||
private boolean hasPresentationType(JClassType type) { | |||
if (presentationTypes.containsKey(type)) { | |||
return true; | |||
} else { | |||
return previousBundle != null | |||
&& previousBundle.hasPresentationType(type); | |||
} | |||
} | |||
public Map<JClassType, JType> getPresentationTypes() { | |||
return Collections.unmodifiableMap(presentationTypes); | |||
} | |||
private void setNeedsSuperclass(JClassType typeAsClass) { | |||
if (!isNeedsSuperClass(typeAsClass)) { | |||
needsSuperClass.add(typeAsClass); |
@@ -1,63 +0,0 @@ | |||
/* | |||
* Copyright 2000-2014 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.server.widgetsetutils.metadata; | |||
import com.google.gwt.core.ext.TreeLogger; | |||
import com.google.gwt.core.ext.UnableToCompleteException; | |||
import com.google.gwt.core.ext.typeinfo.JClassType; | |||
import com.google.gwt.core.ext.typeinfo.JMethod; | |||
import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector; | |||
/** | |||
* Generates type data for renderer connectors. Specifically, stores the return | |||
* type of the overridden {@link AbstractRendererConnector#getRenderer() | |||
* getRenderer} method to enable automatic creation of an instance of the proper | |||
* renderer type. | |||
* | |||
* @see WidgetInitVisitor | |||
* | |||
* @since | |||
* @author Vaadin Ltd | |||
*/ | |||
public class RendererInitVisitor extends TypeVisitor { | |||
@Override | |||
public void visitConnector(TreeLogger logger, JClassType type, | |||
ConnectorBundle bundle) throws UnableToCompleteException { | |||
if (ConnectorBundle.isConnectedRendererConnector(type)) { | |||
// The class in which createRenderer is implemented | |||
JClassType createRendererClass = ConnectorBundle | |||
.findInheritedMethod(type, "createRenderer") | |||
.getEnclosingType(); | |||
JMethod getRenderer = ConnectorBundle.findInheritedMethod(type, | |||
"getRenderer"); | |||
JClassType rendererType = getRenderer.getReturnType().isClass(); | |||
// Needs GWT constructor if createRenderer is not overridden | |||
if (createRendererClass.getQualifiedSourceName().equals( | |||
AbstractRendererConnector.class.getCanonicalName())) { | |||
bundle.setNeedsGwtConstructor(rendererType); | |||
// Also needs renderer type to find the right GWT constructor | |||
bundle.setNeedsReturnType(type, getRenderer); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
/* | |||
* Copyright 2000-2014 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.server.widgetsetutils.metadata; | |||
import com.google.gwt.core.ext.TreeLogger; | |||
import com.google.gwt.core.ext.TreeLogger.Type; | |||
import com.google.gwt.core.ext.typeinfo.JClassType; | |||
import com.google.gwt.core.ext.typeinfo.JMethod; | |||
import com.google.gwt.core.ext.typeinfo.JType; | |||
import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector; | |||
/** | |||
* Generates type data for renderer connectors. | |||
* <ul> | |||
* <li>Stores the return type of the overridden | |||
* {@link AbstractRendererConnector#getRenderer() getRenderer} method to enable | |||
* automatic creation of an instance of the proper renderer type. | |||
* <li>Stores the presentation type of the connector to enable the | |||
* {@link AbstractRendererConnector#decode(com.google.gwt.json.client.JSONValue) | |||
* decode} method to work without having to implement a "getPresentationType" | |||
* method. | |||
* </ul> | |||
* | |||
* @see WidgetInitVisitor | |||
* | |||
* @since | |||
* @author Vaadin Ltd | |||
*/ | |||
public class RendererVisitor extends TypeVisitor { | |||
@Override | |||
public void visitConnector(TreeLogger logger, JClassType type, | |||
ConnectorBundle bundle) { | |||
if (ConnectorBundle.isConnectedRendererConnector(type)) { | |||
doRendererType(logger, type, bundle); | |||
doPresentationType(logger, type, bundle); | |||
} | |||
} | |||
private static void doRendererType(TreeLogger logger, JClassType type, | |||
ConnectorBundle bundle) { | |||
// The class in which createRenderer is implemented | |||
JClassType createRendererClass = ConnectorBundle.findInheritedMethod( | |||
type, "createRenderer").getEnclosingType(); | |||
// Needs GWT constructor if createRenderer is not overridden | |||
if (createRendererClass.getQualifiedSourceName().equals( | |||
AbstractRendererConnector.class.getCanonicalName())) { | |||
JMethod getRenderer = ConnectorBundle.findInheritedMethod(type, | |||
"getRenderer"); | |||
JClassType rendererType = getRenderer.getReturnType().isClass(); | |||
bundle.setNeedsGwtConstructor(rendererType); | |||
// Also needs renderer type to find the right GWT constructor | |||
bundle.setNeedsReturnType(type, getRenderer); | |||
logger.log(Type.DEBUG, "Renderer type of " + type + " is " | |||
+ rendererType); | |||
} | |||
} | |||
private void doPresentationType(TreeLogger logger, JClassType type, | |||
ConnectorBundle bundle) { | |||
JType presentationType = getPresentationType(type); | |||
bundle.setPresentationType(type, presentationType); | |||
logger.log(Type.DEBUG, "Presentation type of " + type + " is " | |||
+ presentationType); | |||
} | |||
private static JType getPresentationType(JClassType type) { | |||
JClassType originalType = type; | |||
while (type != null) { | |||
if (type.getQualifiedBinaryName().equals( | |||
AbstractRendererConnector.class.getName())) { | |||
return type.isParameterized().getTypeArgs()[0]; | |||
} | |||
type = type.getSuperclass(); | |||
} | |||
throw new IllegalArgumentException("The type " | |||
+ originalType.getQualifiedSourceName() + " does not extend " | |||
+ AbstractRendererConnector.class.getName()); | |||
} | |||
} |
@@ -37,6 +37,8 @@ public class TypeDataStore { | |||
.create(); | |||
private final FastStringMap<JsArrayString> delegateToWidgetProperties = FastStringMap | |||
.create(); | |||
private final FastStringMap<Type> presentationTypes = FastStringMap | |||
.create(); | |||
/** | |||
* Maps connector class -> state property name -> hander method data | |||
@@ -135,6 +137,10 @@ public class TypeDataStore { | |||
return get().delegateToWidgetProperties.get(type.getBaseTypeName()); | |||
} | |||
public static Type getPresentationType(Class<?> type) { | |||
return get().presentationTypes.get(getType(type).getBaseTypeName()); | |||
} | |||
public void setDelegateToWidget(Class<?> clazz, String propertyName, | |||
String delegateValue) { | |||
Type type = getType(clazz); | |||
@@ -150,6 +156,11 @@ public class TypeDataStore { | |||
typeProperties.push(propertyName); | |||
} | |||
public void setPresentationType(Class<?> type, Class<?> presentationType) { | |||
presentationTypes.put(getType(type).getBaseTypeName(), | |||
getType(presentationType)); | |||
} | |||
public void setReturnType(Class<?> type, String methodName, Type returnType) { | |||
returnTypes.put(new Method(getType(type), methodName).getLookupKey(), | |||
returnType); |
@@ -23,6 +23,7 @@ import com.vaadin.client.extensions.AbstractExtensionConnector; | |||
import com.vaadin.client.metadata.NoDataException; | |||
import com.vaadin.client.metadata.Type; | |||
import com.vaadin.client.metadata.TypeData; | |||
import com.vaadin.client.metadata.TypeDataStore; | |||
import com.vaadin.client.ui.grid.GridConnector; | |||
import com.vaadin.client.ui.grid.Renderer; | |||
@@ -44,6 +45,18 @@ public abstract class AbstractRendererConnector<T> extends | |||
private Renderer<T> renderer = null; | |||
private final Type presentationType = TypeDataStore | |||
.getPresentationType(this.getClass()); | |||
protected AbstractRendererConnector() { | |||
if (presentationType == null) { | |||
throw new IllegalStateException( | |||
"No presentation type found for " | |||
+ Util.getSimpleName(this) | |||
+ ". This may be caused by some unspecified problem in widgetset compilation."); | |||
} | |||
} | |||
/** | |||
* Returns the renderer associated with this renderer connector. | |||
* <p> | |||
@@ -109,14 +122,11 @@ public abstract class AbstractRendererConnector<T> extends | |||
*/ | |||
public T decode(JSONValue value) { | |||
@SuppressWarnings("unchecked") | |||
T decodedValue = (T) JsonDecoder.decodeValue(new Type(getType()), | |||
value, null, getConnection()); | |||
T decodedValue = (T) JsonDecoder.decodeValue(presentationType, value, | |||
null, getConnection()); | |||
return decodedValue; | |||
} | |||
// TODO generate data type | |||
protected abstract Class<T> getType(); | |||
@Override | |||
@Deprecated | |||
protected void extend(ServerConnector target) { |
@@ -30,9 +30,4 @@ public class TextRendererConnector extends AbstractRendererConnector<String> { | |||
public TextRenderer getRenderer() { | |||
return (TextRenderer) super.getRenderer(); | |||
} | |||
@Override | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
} |
@@ -40,9 +40,4 @@ public class UnsafeHtmlRendererConnector extends | |||
public UnsafeHtmlRenderer getRenderer() { | |||
return (UnsafeHtmlRenderer) super.getRenderer(); | |||
} | |||
@Override | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
} |
@@ -43,9 +43,4 @@ public class IntArrayRendererConnector extends AbstractRendererConnector<int[]> | |||
public IntArrayRenderer getRenderer() { | |||
return (IntArrayRenderer) super.getRenderer(); | |||
} | |||
@Override | |||
public Class<int[]> getType() { | |||
return int[].class; | |||
} | |||
} |
@@ -67,11 +67,6 @@ public class RowAwareRendererConnector extends AbstractRendererConnector<Void> { | |||
} | |||
} | |||
@Override | |||
protected Class<Void> getType() { | |||
return Void.class; | |||
} | |||
@Override | |||
protected Renderer<Void> createRenderer() { | |||
// cannot use the default createRenderer as RowAwareRenderer needs a |