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
import com.vaadin.server.widgetsetutils.metadata.GeneratedSerializer; | import com.vaadin.server.widgetsetutils.metadata.GeneratedSerializer; | ||||
import com.vaadin.server.widgetsetutils.metadata.OnStateChangeVisitor; | import com.vaadin.server.widgetsetutils.metadata.OnStateChangeVisitor; | ||||
import com.vaadin.server.widgetsetutils.metadata.Property; | 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.ServerRpcVisitor; | ||||
import com.vaadin.server.widgetsetutils.metadata.StateInitVisitor; | import com.vaadin.server.widgetsetutils.metadata.StateInitVisitor; | ||||
import com.vaadin.server.widgetsetutils.metadata.TypeVisitor; | import com.vaadin.server.widgetsetutils.metadata.TypeVisitor; | ||||
// this after the JS property data has been initialized | // this after the JS property data has been initialized | ||||
writePropertyTypes(logger, w, bundle); | writePropertyTypes(logger, w, bundle); | ||||
writeSerializers(logger, w, bundle); | writeSerializers(logger, w, bundle); | ||||
writePresentationTypes(w, bundle); | |||||
writeDelegateToWidget(logger, w, bundle); | writeDelegateToWidget(logger, w, bundle); | ||||
writeOnStateChangeHandlers(logger, w, bundle); | writeOnStateChangeHandlers(logger, w, bundle); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
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, | private void writePropertyTypes(TreeLogger logger, SplittingSourceWriter w, | ||||
ConnectorBundle bundle) { | ConnectorBundle bundle) { | ||||
Set<Property> properties = bundle.getNeedsProperty(); | Set<Property> properties = bundle.getNeedsProperty(); | ||||
throws NotFoundException { | throws NotFoundException { | ||||
List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList( | List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList( | ||||
new ConnectorInitVisitor(), new StateInitVisitor(), | new ConnectorInitVisitor(), new StateInitVisitor(), | ||||
new WidgetInitVisitor(), new RendererInitVisitor(), | |||||
new WidgetInitVisitor(), new RendererVisitor(), | |||||
new ClientRpcVisitor(), new ServerRpcVisitor(), | new ClientRpcVisitor(), new ServerRpcVisitor(), | ||||
new OnStateChangeVisitor()); | new OnStateChangeVisitor()); | ||||
for (TypeVisitor typeVisitor : visitors) { | for (TypeVisitor typeVisitor : visitors) { |
private final Set<JType> hasSerializeSupport = new HashSet<JType>(); | private final Set<JType> hasSerializeSupport = new HashSet<JType>(); | ||||
private final Set<JType> needsSerializeSupport = new HashSet<JType>(); | private final Set<JType> needsSerializeSupport = new HashSet<JType>(); | ||||
private final Map<JType, GeneratedSerializer> serializers = new HashMap<JType, GeneratedSerializer>(); | 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> needsSuperClass = new HashSet<JClassType>(); | ||||
private final Set<JClassType> needsGwtConstructor = new HashSet<JClassType>(); | private final Set<JClassType> needsGwtConstructor = new HashSet<JClassType>(); | ||||
return Collections.unmodifiableMap(serializers); | 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) { | private void setNeedsSuperclass(JClassType typeAsClass) { | ||||
if (!isNeedsSuperClass(typeAsClass)) { | if (!isNeedsSuperClass(typeAsClass)) { | ||||
needsSuperClass.add(typeAsClass); | needsSuperClass.add(typeAsClass); |
/* | |||||
* 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); | |||||
} | |||||
} | |||||
} | |||||
} |
/* | |||||
* 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()); | |||||
} | |||||
} |
.create(); | .create(); | ||||
private final FastStringMap<JsArrayString> delegateToWidgetProperties = FastStringMap | private final FastStringMap<JsArrayString> delegateToWidgetProperties = FastStringMap | ||||
.create(); | .create(); | ||||
private final FastStringMap<Type> presentationTypes = FastStringMap | |||||
.create(); | |||||
/** | /** | ||||
* Maps connector class -> state property name -> hander method data | * Maps connector class -> state property name -> hander method data | ||||
return get().delegateToWidgetProperties.get(type.getBaseTypeName()); | 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, | public void setDelegateToWidget(Class<?> clazz, String propertyName, | ||||
String delegateValue) { | String delegateValue) { | ||||
Type type = getType(clazz); | Type type = getType(clazz); | ||||
typeProperties.push(propertyName); | 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) { | public void setReturnType(Class<?> type, String methodName, Type returnType) { | ||||
returnTypes.put(new Method(getType(type), methodName).getLookupKey(), | returnTypes.put(new Method(getType(type), methodName).getLookupKey(), | ||||
returnType); | returnType); |
import com.vaadin.client.metadata.NoDataException; | import com.vaadin.client.metadata.NoDataException; | ||||
import com.vaadin.client.metadata.Type; | import com.vaadin.client.metadata.Type; | ||||
import com.vaadin.client.metadata.TypeData; | 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.GridConnector; | ||||
import com.vaadin.client.ui.grid.Renderer; | import com.vaadin.client.ui.grid.Renderer; | ||||
private Renderer<T> renderer = null; | 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. | * Returns the renderer associated with this renderer connector. | ||||
* <p> | * <p> | ||||
*/ | */ | ||||
public T decode(JSONValue value) { | public T decode(JSONValue value) { | ||||
@SuppressWarnings("unchecked") | @SuppressWarnings("unchecked") | ||||
T decodedValue = (T) JsonDecoder.decodeValue(new Type(getType()), | |||||
value, null, getConnection()); | |||||
T decodedValue = (T) JsonDecoder.decodeValue(presentationType, value, | |||||
null, getConnection()); | |||||
return decodedValue; | return decodedValue; | ||||
} | } | ||||
// TODO generate data type | |||||
protected abstract Class<T> getType(); | |||||
@Override | @Override | ||||
@Deprecated | @Deprecated | ||||
protected void extend(ServerConnector target) { | protected void extend(ServerConnector target) { |
public TextRenderer getRenderer() { | public TextRenderer getRenderer() { | ||||
return (TextRenderer) super.getRenderer(); | return (TextRenderer) super.getRenderer(); | ||||
} | } | ||||
@Override | |||||
public Class<String> getType() { | |||||
return String.class; | |||||
} | |||||
} | } |
public UnsafeHtmlRenderer getRenderer() { | public UnsafeHtmlRenderer getRenderer() { | ||||
return (UnsafeHtmlRenderer) super.getRenderer(); | return (UnsafeHtmlRenderer) super.getRenderer(); | ||||
} | } | ||||
@Override | |||||
public Class<String> getType() { | |||||
return String.class; | |||||
} | |||||
} | } |
public IntArrayRenderer getRenderer() { | public IntArrayRenderer getRenderer() { | ||||
return (IntArrayRenderer) super.getRenderer(); | return (IntArrayRenderer) super.getRenderer(); | ||||
} | } | ||||
@Override | |||||
public Class<int[]> getType() { | |||||
return int[].class; | |||||
} | |||||
} | } |
} | } | ||||
} | } | ||||
@Override | |||||
protected Class<Void> getType() { | |||||
return Void.class; | |||||
} | |||||
@Override | @Override | ||||
protected Renderer<Void> createRenderer() { | protected Renderer<Void> createRenderer() { | ||||
// cannot use the default createRenderer as RowAwareRenderer needs a | // cannot use the default createRenderer as RowAwareRenderer needs a |