writeClassLiteral(w, property.getBeanType());
w.print(", \"");
w.print(escape(property.getName()));
- w.print("\", new Invoker() {");
+ w.println("\", new Invoker() {");
w.indent();
w.println("public Object invoke(Object bean, Object[] params) {");
HashSet<Property> properties = new HashSet<Property>();
properties.addAll(MethodProperty.findProperties(type));
+ properties.addAll(FieldProperty.findProperties(type));
return properties;
}
--- /dev/null
+/*
+ * 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.widgetsetutils.metadata;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JField;
+import com.google.gwt.user.rebind.SourceWriter;
+
+public class FieldProperty extends Property {
+
+ private FieldProperty(JClassType beanType, JField field) {
+ super(field.getName(), beanType, field.getType());
+ }
+
+ @Override
+ public void writeSetterBody(TreeLogger logger, SourceWriter w,
+ String beanVariable, String valueVariable) {
+ w.print("((%s) %s).%s = (%s)%s;", getBeanType()
+ .getQualifiedSourceName(), beanVariable, getName(),
+ getUnboxedPropertyTypeName(), valueVariable);
+ }
+
+ @Override
+ public void writeGetterBody(TreeLogger logger, SourceWriter w,
+ String beanVariable) {
+ w.print("return ((%s) %s).%s;", getBeanType().getQualifiedSourceName(),
+ beanVariable, getName());
+ }
+
+ public static Collection<FieldProperty> findProperties(JClassType type) {
+ Collection<FieldProperty> properties = new ArrayList<FieldProperty>();
+
+ List<JField> fields = getPublicFields(type);
+ for (JField field : fields) {
+ properties.add(new FieldProperty(type, field));
+ }
+
+ return properties;
+ }
+
+ private static List<JField> getPublicFields(JClassType type) {
+ Set<String> names = new HashSet<String>();
+ ArrayList<JField> fields = new ArrayList<JField>();
+ for (JClassType subType : type.getFlattenedSupertypeHierarchy()) {
+ JField[] subFields = subType.getFields();
+ for (JField field : subFields) {
+ if (field.isPublic() && !field.isStatic()
+ && names.add(field.getName())) {
+ fields.add(field);
+ }
+ }
+ }
+ return fields;
+ }
+
+}
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
boolean sinkOnloads = false;
- switch (getState().getContentMode()) {
+ switch (getState().contentMode) {
case PREFORMATTED:
PreElement preElement = Document.get().createPreElement();
- preElement.setInnerText(getState().getText());
+ preElement.setInnerText(getState().text);
// clear existing content
getWidget().setHTML("");
// add preformatted text to dom
break;
case TEXT:
- getWidget().setText(getState().getText());
+ getWidget().setText(getState().text);
break;
case XHTML:
case RAW:
sinkOnloads = true;
case XML:
- getWidget().setHTML(getState().getText());
+ getWidget().setHTML(getState().text);
break;
default:
getWidget().setText("");
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
*/
public class JsonCodec implements Serializable {
+ public static interface BeanProperty {
+ public Object getValue(Object bean) throws Exception;
+
+ public void setValue(Object bean, Object value) throws Exception;
+
+ public String getName();
+
+ public Type getType();
+ }
+
+ private static class FieldProperty implements BeanProperty {
+ private final Field field;
+
+ public FieldProperty(Field field) {
+ this.field = field;
+ }
+
+ @Override
+ public Object getValue(Object bean) throws Exception {
+ return field.get(bean);
+ }
+
+ @Override
+ public void setValue(Object bean, Object value) throws Exception {
+ field.set(bean, value);
+ }
+
+ @Override
+ public String getName() {
+ return field.getName();
+ }
+
+ @Override
+ public Type getType() {
+ return field.getGenericType();
+ }
+
+ public static Collection<FieldProperty> find(Class<?> type)
+ throws IntrospectionException {
+ Collection<FieldProperty> properties = new ArrayList<FieldProperty>();
+
+ Field[] fields = type.getFields();
+ for (Field field : fields) {
+ if (!Modifier.isStatic(field.getModifiers())) {
+ properties.add(new FieldProperty(field));
+ }
+ }
+
+ return properties;
+ }
+
+ }
+
+ private static class MethodProperty implements BeanProperty {
+ private final PropertyDescriptor pd;
+
+ public MethodProperty(PropertyDescriptor pd) {
+ this.pd = pd;
+ }
+
+ @Override
+ public Object getValue(Object bean) throws Exception {
+ Method readMethod = pd.getReadMethod();
+ return readMethod.invoke(bean);
+ }
+
+ @Override
+ public void setValue(Object bean, Object value) throws Exception {
+ pd.getWriteMethod().invoke(bean, value);
+ }
+
+ @Override
+ public String getName() {
+ String fieldName = pd.getWriteMethod().getName().substring(3);
+ fieldName = Character.toLowerCase(fieldName.charAt(0))
+ + fieldName.substring(1);
+ return fieldName;
+ }
+
+ public static Collection<MethodProperty> find(Class<?> type)
+ throws IntrospectionException {
+ Collection<MethodProperty> properties = new ArrayList<MethodProperty>();
+
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(type)
+ .getPropertyDescriptors()) {
+ if (pd.getReadMethod() == null || pd.getWriteMethod() == null) {
+ continue;
+ }
+
+ properties.add(new MethodProperty(pd));
+ }
+ return properties;
+ }
+
+ @Override
+ public Type getType() {
+ return pd.getReadMethod().getGenericReturnType();
+ }
+
+ }
+
private static Map<Class<?>, String> typeToTransportType = new HashMap<Class<?>, String>();
/**
return set;
}
- /**
- * Returns the name that should be used as field name in the JSON. We strip
- * "set" from the setter, keeping the result - this is easy to do on both
- * server and client, avoiding some issues with cASE. E.g setZIndex()
- * becomes "zIndex". Also ensures that both getter and setter are present,
- * returning null otherwise.
- *
- * @param pd
- * @return the name to be used or null if both getter and setter are not
- * found.
- */
- static String getTransportFieldName(PropertyDescriptor pd) {
- if (pd.getReadMethod() == null || pd.getWriteMethod() == null) {
- return null;
- }
- String fieldName = pd.getWriteMethod().getName().substring(3);
- fieldName = Character.toLowerCase(fieldName.charAt(0))
- + fieldName.substring(1);
- return fieldName;
- }
-
private static Object decodeObject(Type targetType,
JSONObject serializedObject, ConnectorTracker connectorTracker)
throws JSONException {
try {
Object decodedObject = targetClass.newInstance();
- for (PropertyDescriptor pd : Introspector.getBeanInfo(targetClass)
- .getPropertyDescriptors()) {
+ for (BeanProperty property : getProperties(targetClass)) {
- String fieldName = getTransportFieldName(pd);
- if (fieldName == null) {
- continue;
- }
+ String fieldName = property.getName();
Object encodedFieldValue = serializedObject.get(fieldName);
- Type fieldType = pd.getReadMethod().getGenericReturnType();
+ Type fieldType = property.getType();
Object decodedFieldValue = decodeInternalOrCustomType(
fieldType, encodedFieldValue, connectorTracker);
- pd.getWriteMethod().invoke(decodedObject, decodedFieldValue);
+ property.setValue(decodedObject, decodedFieldValue);
}
return decodedObject;
- } catch (IllegalArgumentException e) {
- throw new JSONException(e);
- } catch (IllegalAccessException e) {
- throw new JSONException(e);
- } catch (InvocationTargetException e) {
- throw new JSONException(e);
- } catch (InstantiationException e) {
- throw new JSONException(e);
- } catch (IntrospectionException e) {
+ } catch (Exception e) {
throw new JSONException(e);
}
}
return JSONObject.NULL;
}
+ public static Collection<BeanProperty> getProperties(Class<?> type)
+ throws IntrospectionException {
+ Collection<BeanProperty> properties = new ArrayList<BeanProperty>();
+
+ properties.addAll(MethodProperty.find(type));
+ properties.addAll(FieldProperty.find(type));
+
+ return properties;
+ }
+
private static Object encodeObject(Object value, JSONObject diffState,
ConnectorTracker connectorTracker) throws JSONException {
JSONObject jsonMap = new JSONObject();
try {
- for (PropertyDescriptor pd : Introspector.getBeanInfo(
- value.getClass()).getPropertyDescriptors()) {
- String fieldName = getTransportFieldName(pd);
- if (fieldName == null) {
- continue;
- }
- Method getterMethod = pd.getReadMethod();
+ for (BeanProperty property : getProperties(value.getClass())) {
+ String fieldName = property.getName();
// We can't use PropertyDescriptor.getPropertyType() as it does
// not support generics
- Type fieldType = getterMethod.getGenericReturnType();
- Object fieldValue = getterMethod.invoke(value, (Object[]) null);
+ Type fieldType = property.getType();
+ Object fieldValue = property.getValue(value);
boolean equals = false;
Object diffStateValue = null;
if (diffState != null && diffState.has(fieldName)) {
public String getValue() {
if (getPropertyDataSource() == null) {
// Use internal value if we are running without a data source
- return getState().getText();
+ return getState().text;
}
return ConverterUtil.convertFromModel(getPropertyDataSource()
.getValue(), String.class, getConverter(), getLocale());
+ String.class.getName());
}
if (getPropertyDataSource() == null) {
- getState().setText((String) newStringValue);
+ getState().text = (String) newStringValue;
requestRepaint();
} else {
throw new IllegalStateException(
* @see ContentMode
*/
public ContentMode getContentMode() {
- return getState().getContentMode();
+ return getState().contentMode;
}
/**
throw new IllegalArgumentException("Content mode can not be null");
}
- getState().setContentMode(contentMode);
+ getState().contentMode = contentMode;
requestRepaint();
}
@Override
public void valueChange(Property.ValueChangeEvent event) {
// Update the internal value from the data source
- getState().setText(getValue());
+ getState().text = getValue();
requestRepaint();
fireValueChange();
import com.vaadin.shared.ComponentState;
public class LabelState extends ComponentState {
- private ContentMode contentMode = ContentMode.TEXT;
- private String text = "";
-
- public ContentMode getContentMode() {
- return contentMode;
- }
-
- public void setContentMode(ContentMode contentMode) {
- this.contentMode = contentMode;
- }
-
- public String getText() {
- return text;
- }
-
- public void setText(String text) {
- this.text = text;
- }
-
+ public ContentMode contentMode = ContentMode.TEXT;
+ public String text = "";
}
public class AbstractOrderedLayoutState extends AbstractLayoutState {
private boolean spacing = false;
- public HashMap<Connector, ChildComponentData> childData = new HashMap<Connector, ChildComponentData>();
+ private HashMap<Connector, ChildComponentData> childData = new HashMap<Connector, ChildComponentData>();
private int marginsBitmask = 0;
package com.vaadin.terminal.gwt.server;
/*
- * Copyright 2011 Vaadin Ltd.
+ * 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
* License for the specific language governing permissions and limitations under
* the License.
*/
-import java.beans.BeanInfo;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState;
import com.vaadin.terminal.gwt.client.communication.JsonDecoder;
import com.vaadin.terminal.gwt.client.communication.JsonEncoder;
+import com.vaadin.terminal.gwt.server.JsonCodec.BeanProperty;
/**
* Tests for {@link JsonCodec}, {@link JsonEncoder}, {@link JsonDecoder}
}
private boolean equalsBean(Object o1, Object o2) throws Exception {
- BeanInfo beanInfo = Introspector.getBeanInfo(o1.getClass());
- for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
- String fieldName = JsonCodec.getTransportFieldName(pd);
- if (fieldName == null) {
- continue;
- }
-
- Object c1 = pd.getReadMethod().invoke(o1);
- Object c2 = pd.getReadMethod().invoke(o2);
+ for (BeanProperty property : JsonCodec.getProperties(o1.getClass())) {
+ Object c1 = property.getValue(o1);
+ Object c2 = property.getValue(o2);
if (!equals(c1, c2)) {
return false;
}