Conflicts: src/com/vaadin/Application.java src/com/vaadin/ui/AbstractField.java tests/testbench/com/vaadin/tests/integration/LiferayThemeDemo.java tests/testbench/com/vaadin/tests/tickets/Ticket1673.javatags/7.0.0.alpha1
@@ -34,6 +34,9 @@ import java.util.regex.Pattern; | |||
import com.vaadin.annotations.RootInitRequiresBrowserDetals; | |||
import com.vaadin.annotations.RootTheme; | |||
import com.vaadin.annotations.RootWidgetset; | |||
import com.vaadin.data.util.converter.Converter; | |||
import com.vaadin.data.util.converter.ConverterFactory; | |||
import com.vaadin.data.util.converter.DefaultConverterFactory; | |||
import com.vaadin.service.ApplicationContext; | |||
import com.vaadin.terminal.ApplicationResource; | |||
import com.vaadin.terminal.CombinedRequest; | |||
@@ -50,6 +53,7 @@ import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; | |||
import com.vaadin.terminal.gwt.server.ChangeVariablesErrorEvent; | |||
import com.vaadin.terminal.gwt.server.WebApplicationContext; | |||
import com.vaadin.ui.AbstractComponent; | |||
import com.vaadin.ui.AbstractField; | |||
import com.vaadin.ui.Root; | |||
import com.vaadin.ui.Window; | |||
@@ -512,6 +516,13 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
*/ | |||
private Terminal.ErrorListener errorHandler = this; | |||
/** | |||
* The converter factory that is used for all fields in the application. | |||
*/ | |||
// private ConverterFactory converterFactory = new | |||
// DefaultConverterFactory(); | |||
private static ConverterFactory converterFactory = new DefaultConverterFactory(); | |||
private LinkedList<RequestHandler> requestHandlers = new LinkedList<RequestHandler>(); | |||
private int nextRootId = 0; | |||
@@ -1198,6 +1209,42 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
this.errorHandler = errorHandler; | |||
} | |||
/** | |||
* Gets the {@link ConverterFactory} used to locate a suitable | |||
* {@link Converter} for fields in the application. | |||
* | |||
* See {@link #setConverterFactory(ConverterFactory)} for more details | |||
* | |||
* @return The converter factory used in the application | |||
*/ | |||
// public ConverterFactory getConverterFactory() { | |||
// return converterFactory; | |||
// } | |||
// FIXME: Should not be static | |||
public static ConverterFactory getConverterFactory() { | |||
return converterFactory; | |||
} | |||
/** | |||
* Sets the {@link ConverterFactory} used to locate a suitable | |||
* {@link Converter} for fields in the application. | |||
* | |||
* The {@link ConverterFactory} is used to find a suitable converter when | |||
* binding data to a UI component and the data type does not match the UI | |||
* component type, e.g. binding a Double to a TextField (which is based on a | |||
* String). | |||
* | |||
* The {@link Converter} for an individual field can be overridden using | |||
* {@link AbstractField#setValueConverter(Converter)}. | |||
* | |||
* @param converterFactory | |||
* The converter factory used in the application | |||
*/ | |||
// FIXME: Should not be static | |||
public static void setConverterFactory(ConverterFactory converterFactory) { | |||
Application.converterFactory = converterFactory; | |||
} | |||
/** | |||
* Contains the system messages used to notify the user about various | |||
* critical situations that can occur. |
@@ -121,7 +121,7 @@ public interface Container extends Serializable { | |||
* ID of the Property to retrieve | |||
* @return Property with the given ID or <code>null</code> | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId); | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId); | |||
/** | |||
* Gets the data type of all Properties identified by the given Property ID. |
@@ -30,7 +30,7 @@ public interface Item extends Serializable { | |||
* identifier of the Property to get | |||
* @return the Property with the given ID or <code>null</code> | |||
*/ | |||
public Property getItemProperty(Object id); | |||
public Property<?> getItemProperty(Object id); | |||
/** | |||
* Gets the collection of IDs of all Properties stored in the Item. |
@@ -30,12 +30,15 @@ import java.io.Serializable; | |||
* needs to be changed through the implementing class. | |||
* </p> | |||
* | |||
* @param T | |||
* type of values of the property | |||
* | |||
* @author IT Mill Ltd | |||
* @version | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
public interface Property extends Serializable { | |||
public interface Property<T> extends Serializable { | |||
/** | |||
* Gets the value stored in the Property. The returned object is compatible | |||
@@ -43,7 +46,7 @@ public interface Property extends Serializable { | |||
* | |||
* @return the value stored in the Property | |||
*/ | |||
public Object getValue(); | |||
public T getValue(); | |||
/** | |||
* Sets the value of the Property. | |||
@@ -52,38 +55,23 @@ public interface Property extends Serializable { | |||
* missing, one should declare the Property to be in read-only mode and | |||
* throw <code>Property.ReadOnlyException</code> in this function. | |||
* </p> | |||
* Note : It is not required, but highly recommended to support setting the | |||
* value also as a <code>String</code> in addition to the native type of the | |||
* Property (as given by the <code>getType</code> method). If the | |||
* <code>String</code> conversion fails or is unsupported, the method should | |||
* throw <code>Property.ConversionException</code>. The string conversion | |||
* should at least understand the format returned by the | |||
* <code>toString</code> method of the Property. | |||
* | |||
* Note : Since Vaadin 7.0, setting the value of a non-String property as a | |||
* String is no longer supported. | |||
* | |||
* @param newValue | |||
* New value of the Property. This should be assignable to the | |||
* type returned by getType, but also String type should be | |||
* supported | |||
* type returned by getType | |||
* | |||
* @throws Property.ReadOnlyException | |||
* if the object is in read-only mode | |||
* @throws Property.ConversionException | |||
* if newValue can't be converted into the Property's native | |||
* type directly or through String | |||
* type directly or using a converter | |||
*/ | |||
public void setValue(Object newValue) throws Property.ReadOnlyException, | |||
Property.ConversionException; | |||
/** | |||
* Returns the value of the Property in human readable textual format. The | |||
* return value should be assignable to the <code>setValue</code> method if | |||
* the Property is not in read-only mode. | |||
* | |||
* @return <code>String</code> representation of the value stored in the | |||
* Property | |||
*/ | |||
public String toString(); | |||
/** | |||
* Returns the type of the Property. The methods <code>getValue</code> and | |||
* <code>setValue</code> must be compatible with this type: one must be able | |||
@@ -93,7 +81,7 @@ public interface Property extends Serializable { | |||
* | |||
* @return type of the Property | |||
*/ | |||
public Class<?> getType(); | |||
public Class<? extends T> getType(); | |||
/** | |||
* Tests if the Property is in read-only mode. In read-only mode calls to |
@@ -29,6 +29,13 @@ import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; | |||
* <p> | |||
* Validators must not have any side effects. | |||
* </p> | |||
* <p> | |||
* Since Vaadin 7, the method isValid(Object) does not exist in the interface - | |||
* {@link #validate(Object)} should be used instead, and the exception caught | |||
* where applicable. Concrete classes implementing {@link Validator} can still | |||
* internally implement and use isValid(Object) for convenience or to ease | |||
* migration from earlier Vaadin versions. | |||
* </p> | |||
* | |||
* @author IT Mill Ltd. | |||
* @version | |||
@@ -49,18 +56,6 @@ public interface Validator extends Serializable { | |||
*/ | |||
public void validate(Object value) throws Validator.InvalidValueException; | |||
/** | |||
* Tests if the given value is valid. This method must be symmetric with | |||
* {@link #validate(Object)} so that {@link #validate(Object)} throws an | |||
* error iff this method returns false. | |||
* | |||
* @param value | |||
* the value to check | |||
* @return <code>true</code> if the value is valid, <code>false</code> | |||
* otherwise. | |||
*/ | |||
public boolean isValid(Object value); | |||
/** | |||
* Exception that is thrown by a {@link Validator} when a value is invalid. | |||
* |
@@ -104,8 +104,9 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends | |||
+ " not found"); | |||
} | |||
try { | |||
Property property = pd.createProperty(bean); | |||
return (IDTYPE) property.getValue(); | |||
Property<IDTYPE> property = (Property<IDTYPE>) pd | |||
.createProperty(bean); | |||
return property.getValue(); | |||
} catch (MethodException e) { | |||
throw new IllegalArgumentException(e); | |||
} | |||
@@ -256,7 +257,7 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends | |||
* @see com.vaadin.data.Container#getContainerProperty(java.lang.Object, | |||
* java.lang.Object) | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId) { | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId) { | |||
Item item = getItem(itemId); | |||
if (item == null) { | |||
return null; | |||
@@ -371,7 +372,7 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends | |||
* The id of the property | |||
*/ | |||
private void addValueChangeListener(Item item, Object propertyId) { | |||
Property property = item.getItemProperty(propertyId); | |||
Property<?> property = item.getItemProperty(propertyId); | |||
if (property instanceof ValueChangeNotifier) { | |||
// avoid multiple notifications for the same property if | |||
// multiple filters are in use | |||
@@ -390,7 +391,7 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends | |||
* The id of the property | |||
*/ | |||
private void removeValueChangeListener(Item item, Object propertyId) { | |||
Property property = item.getItemProperty(propertyId); | |||
Property<?> property = item.getItemProperty(propertyId); | |||
if (property instanceof ValueChangeNotifier) { | |||
((ValueChangeNotifier) property).removeListener(this); | |||
} | |||
@@ -746,9 +747,9 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends | |||
} | |||
model.put(propertyId, propertyDescriptor); | |||
for (BeanItem item : itemIdToItem.values()) { | |||
item.addItemProperty(propertyId, propertyDescriptor | |||
.createProperty((BEANTYPE) item.getBean())); | |||
for (BeanItem<BEANTYPE> item : itemIdToItem.values()) { | |||
item.addItemProperty(propertyId, | |||
propertyDescriptor.createProperty(item.getBean())); | |||
} | |||
// Sends a change event | |||
@@ -767,7 +768,6 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends | |||
* @see NestedMethodProperty | |||
* | |||
* @param propertyId | |||
* @param propertyType | |||
* @return true if the property was added | |||
*/ | |||
public boolean addNestedContainerProperty(String propertyId) { | |||
@@ -775,6 +775,41 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends | |||
propertyId, type)); | |||
} | |||
/** | |||
* Adds a nested container properties for all sub-properties of a named | |||
* property to the container. The named property itself is removed from the | |||
* model as its subproperties are added. | |||
* | |||
* All intermediate getters must exist and must return non-null values when | |||
* the property value is accessed. | |||
* | |||
* @see NestedMethodProperty | |||
* @see #addNestedContainerProperty(String) | |||
* | |||
* @param propertyId | |||
*/ | |||
@SuppressWarnings("unchecked") | |||
public void addNestedContainerBean(String propertyId) { | |||
Class<?> propertyType = getType(propertyId); | |||
LinkedHashMap<String, VaadinPropertyDescriptor<Object>> pds = BeanItem | |||
.getPropertyDescriptors((Class<Object>) propertyType); | |||
for (String subPropertyId : pds.keySet()) { | |||
String qualifiedPropertyId = propertyId + "." + subPropertyId; | |||
NestedPropertyDescriptor<BEANTYPE> pd = new NestedPropertyDescriptor<BEANTYPE>( | |||
qualifiedPropertyId, (Class<BEANTYPE>) type); | |||
model.put(qualifiedPropertyId, pd); | |||
model.remove(propertyId); | |||
for (BeanItem<BEANTYPE> item : itemIdToItem.values()) { | |||
item.addItemProperty(propertyId, | |||
pd.createProperty(item.getBean())); | |||
item.removeItemProperty(propertyId); | |||
} | |||
} | |||
// Sends a change event | |||
fireContainerPropertySetChange(); | |||
} | |||
@Override | |||
public boolean removeContainerProperty(Object propertyId) | |||
throws UnsupportedOperationException { |
@@ -17,7 +17,7 @@ import com.vaadin.data.Property; | |||
* | |||
* @since 6.6 | |||
*/ | |||
public abstract class AbstractProperty implements Property, | |||
public abstract class AbstractProperty<T> implements Property<T>, | |||
Property.ValueChangeNotifier, Property.ReadOnlyStatusChangeNotifier { | |||
/** | |||
@@ -56,13 +56,28 @@ public abstract class AbstractProperty implements Property, | |||
/** | |||
* Returns the value of the <code>Property</code> in human readable textual | |||
* format. The return value should be assignable to the | |||
* <code>setValue</code> method if the Property is not in read-only mode. | |||
* format. | |||
* | |||
* @return String representation of the value stored in the Property | |||
* @deprecated use the property value directly, or {@link #getStringValue()} | |||
* during migration period | |||
*/ | |||
@Deprecated | |||
@Override | |||
public String toString() { | |||
throw new UnsupportedOperationException( | |||
"Use Property.getValue() instead of " + getClass() | |||
+ ".toString()"); | |||
} | |||
/** | |||
* Returns the value of the <code>Property</code> in human readable textual | |||
* format. | |||
* | |||
* @return String representation of the value stored in the Property | |||
* @since 7.0 | |||
*/ | |||
public String getStringValue() { | |||
final Object value = getValue(); | |||
if (value == null) { | |||
return null; | |||
@@ -76,8 +91,8 @@ public abstract class AbstractProperty implements Property, | |||
* An <code>Event</code> object specifying the Property whose read-only | |||
* status has been changed. | |||
*/ | |||
protected class ReadOnlyStatusChangeEvent extends java.util.EventObject | |||
implements Property.ReadOnlyStatusChangeEvent { | |||
protected static class ReadOnlyStatusChangeEvent extends | |||
java.util.EventObject implements Property.ReadOnlyStatusChangeEvent { | |||
/** | |||
* Constructs a new read-only status change event for this object. | |||
@@ -144,8 +159,8 @@ public abstract class AbstractProperty implements Property, | |||
* An <code>Event</code> object specifying the Property whose value has been | |||
* changed. | |||
*/ | |||
private class ValueChangeEvent extends java.util.EventObject implements | |||
Property.ValueChangeEvent { | |||
private static class ValueChangeEvent extends java.util.EventObject | |||
implements Property.ValueChangeEvent { | |||
/** | |||
* Constructs a new value change event for this object. |
@@ -12,9 +12,11 @@ import java.lang.reflect.Method; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
/** | |||
* A wrapper class for adding the Item interface to any Java Bean. | |||
@@ -162,7 +164,7 @@ public class BeanItem<BT> extends PropertysetItem { | |||
final Method getMethod = pd.getReadMethod(); | |||
if ((getMethod != null) | |||
&& getMethod.getDeclaringClass() != Object.class) { | |||
VaadinPropertyDescriptor<BT> vaadinPropertyDescriptor = new MethodPropertyDescriptor( | |||
VaadinPropertyDescriptor<BT> vaadinPropertyDescriptor = new MethodPropertyDescriptor<BT>( | |||
pd.getName(), pd.getPropertyType(), | |||
pd.getReadMethod(), pd.getWriteMethod()); | |||
pdMap.put(pd.getName(), vaadinPropertyDescriptor); | |||
@@ -212,6 +214,38 @@ public class BeanItem<BT> extends PropertysetItem { | |||
} | |||
} | |||
/** | |||
* Expands nested bean properties by replacing a top-level property with | |||
* some or all of its sub-properties. The expansion is not recursive. | |||
* | |||
* @param propertyId | |||
* property id for the property whose sub-properties are to be | |||
* expanded, | |||
* @param subPropertyIds | |||
* sub-properties to expand, all sub-properties are expanded if | |||
* not specified | |||
*/ | |||
public void expandProperty(String propertyId, String... subPropertyIds) { | |||
Set<String> subPropertySet = new HashSet<String>( | |||
Arrays.asList(subPropertyIds)); | |||
if (0 == subPropertyIds.length) { | |||
// Enumerate all sub-properties | |||
Class<?> propertyType = getItemProperty(propertyId).getType(); | |||
Map<String, ?> pds = getPropertyDescriptors(propertyType); | |||
subPropertySet.addAll(pds.keySet()); | |||
} | |||
for (String subproperty : subPropertySet) { | |||
String qualifiedPropertyId = propertyId + "." + subproperty; | |||
addItemProperty(qualifiedPropertyId, | |||
new NestedMethodProperty<Object>(getBean(), | |||
qualifiedPropertyId)); | |||
} | |||
removeItemProperty(propertyId); | |||
} | |||
/** | |||
* Gets the underlying JavaBean object. | |||
* |
@@ -641,7 +641,7 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical, | |||
* Container Don't add a JavaDoc comment here, we use the default | |||
* documentation from implemented interface. | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId) { | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId) { | |||
return container.getContainerProperty(itemId, propertyId); | |||
} | |||
@@ -437,7 +437,7 @@ public class ContainerOrderedWrapper implements Container.Ordered, | |||
* Container Don't add a JavaDoc comment here, we use the default | |||
* documentation from implemented interface. | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId) { | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId) { | |||
return container.getContainerProperty(itemId, propertyId); | |||
} | |||
@@ -122,8 +122,8 @@ public class DefaultItemSorter implements ItemSorter { | |||
Item item1, Item item2) { | |||
// Get the properties to compare | |||
final Property property1 = item1.getItemProperty(propertyId); | |||
final Property property2 = item2.getItemProperty(propertyId); | |||
final Property<?> property1 = item1.getItemProperty(propertyId); | |||
final Property<?> property2 = item2.getItemProperty(propertyId); | |||
// Get the values to compare | |||
final Object value1 = (property1 == null) ? null : property1.getValue(); |
@@ -459,7 +459,7 @@ public class FilesystemContainer implements Container.Hierarchical { | |||
* the property's ID. | |||
* @return the requested property's value, or <code>null</code> | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId) { | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId) { | |||
if (!(itemId instanceof File)) { | |||
return null; | |||
@@ -609,7 +609,7 @@ public class FilesystemContainer implements Container.Hierarchical { | |||
* Gets the specified property of this file. Don't add a JavaDoc comment | |||
* here, we use the default documentation from implemented interface. | |||
*/ | |||
public Property getItemProperty(Object id) { | |||
public Property<?> getItemProperty(Object id) { | |||
return getContainerProperty(file, id); | |||
} | |||
@@ -76,7 +76,7 @@ public class IndexedContainer extends | |||
/** | |||
* Set of properties that are read-only. | |||
*/ | |||
private HashSet<Property> readOnlyProperties = new HashSet<Property>(); | |||
private HashSet<Property<?>> readOnlyProperties = new HashSet<Property<?>>(); | |||
/** | |||
* List of all Property value change event listeners listening all the | |||
@@ -150,7 +150,7 @@ public class IndexedContainer extends | |||
* @see com.vaadin.data.Container#getContainerProperty(java.lang.Object, | |||
* java.lang.Object) | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId) { | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId) { | |||
if (!containsId(itemId)) { | |||
return null; | |||
} | |||
@@ -425,7 +425,7 @@ public class IndexedContainer extends | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
public class ItemSetChangeEvent extends BaseItemSetChangeEvent { | |||
public static class ItemSetChangeEvent extends BaseItemSetChangeEvent { | |||
private final int addedItemIndex; | |||
@@ -455,7 +455,7 @@ public class IndexedContainer extends | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
private class PropertyValueChangeEvent extends EventObject implements | |||
private static class PropertyValueChangeEvent extends EventObject implements | |||
Property.ValueChangeEvent, Serializable { | |||
private PropertyValueChangeEvent(Property source) { | |||
@@ -680,7 +680,7 @@ public class IndexedContainer extends | |||
* | |||
* @see com.vaadin.data.Item#getItemProperty(java.lang.Object) | |||
*/ | |||
public Property getItemProperty(Object id) { | |||
public Property<?> getItemProperty(Object id) { | |||
return new IndexedContainerProperty(itemId, id); | |||
} | |||
@@ -691,8 +691,8 @@ public class IndexedContainer extends | |||
/** | |||
* Gets the <code>String</code> representation of the contents of the | |||
* Item. The format of the string is a space separated catenation of the | |||
* <code>String</code> representations of the Properties contained by | |||
* the Item. | |||
* <code>String</code> representations of the values of the Properties | |||
* contained by the Item. | |||
* | |||
* @return <code>String</code> representation of the Item contents | |||
*/ | |||
@@ -702,7 +702,7 @@ public class IndexedContainer extends | |||
for (final Iterator<?> i = propertyIds.iterator(); i.hasNext();) { | |||
final Object propertyId = i.next(); | |||
retValue += getItemProperty(propertyId).toString(); | |||
retValue += getItemProperty(propertyId).getValue(); | |||
if (i.hasNext()) { | |||
retValue += " "; | |||
} | |||
@@ -786,7 +786,7 @@ public class IndexedContainer extends | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
private class IndexedContainerProperty implements Property, | |||
private class IndexedContainerProperty implements Property<Object>, | |||
Property.ValueChangeNotifier { | |||
/** | |||
@@ -910,9 +910,24 @@ public class IndexedContainer extends | |||
* | |||
* @return <code>String</code> representation of the value stored in the | |||
* Property | |||
* @deprecated use the property value directly, or | |||
* {@link #getStringValue()} during migration period | |||
*/ | |||
@Deprecated | |||
@Override | |||
public String toString() { | |||
throw new UnsupportedOperationException( | |||
"Use Property.getValue() instead of IndexedContainerProperty.toString()"); | |||
} | |||
/** | |||
* Returns the value of the <code>Property</code> in human readable | |||
* textual format. | |||
* | |||
* @return String representation of the value stored in the Property | |||
* @since 7.0 | |||
*/ | |||
public String getStringValue() { | |||
final Object value = getValue(); | |||
if (value == null) { | |||
return null; | |||
@@ -1038,7 +1053,7 @@ public class IndexedContainer extends | |||
getPropertySetChangeListeners()) : null); | |||
nc.propertyValueChangeListeners = propertyValueChangeListeners != null ? (LinkedList<Property.ValueChangeListener>) propertyValueChangeListeners | |||
.clone() : null; | |||
nc.readOnlyProperties = readOnlyProperties != null ? (HashSet<Property>) readOnlyProperties | |||
nc.readOnlyProperties = readOnlyProperties != null ? (HashSet<Property<?>>) readOnlyProperties | |||
.clone() : null; | |||
nc.singlePropertyValueChangeListeners = singlePropertyValueChangeListeners != null ? (Hashtable<Object, Map<Object, List<Property.ValueChangeListener>>>) singlePropertyValueChangeListeners | |||
.clone() : null; |
@@ -47,7 +47,7 @@ import com.vaadin.util.SerializerHelper; | |||
* @since 3.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class MethodProperty<T> extends AbstractProperty { | |||
public class MethodProperty<T> extends AbstractProperty<T> { | |||
private static final Logger logger = Logger.getLogger(MethodProperty.class | |||
.getName()); | |||
@@ -170,7 +170,7 @@ public class MethodProperty<T> extends AbstractProperty { | |||
@SuppressWarnings("unchecked") | |||
public MethodProperty(Object instance, String beanPropertyName) { | |||
final Class beanClass = instance.getClass(); | |||
final Class<?> beanClass = instance.getClass(); | |||
// Assure that the first letter is upper cased (it is a common | |||
// mistake to write firstName, not FirstName). | |||
@@ -349,7 +349,7 @@ public class MethodProperty<T> extends AbstractProperty { | |||
} | |||
// Tests the parameter types | |||
final Class[] c = m[i].getParameterTypes(); | |||
final Class<?>[] c = m[i].getParameterTypes(); | |||
if (c.length != getArgs.length) { | |||
// not the right amount of parameters, try next method | |||
@@ -398,7 +398,7 @@ public class MethodProperty<T> extends AbstractProperty { | |||
} | |||
// Checks parameter compatibility | |||
final Class[] c = m[i].getParameterTypes(); | |||
final Class<?>[] c = m[i].getParameterTypes(); | |||
if (c.length != setArgs.length) { | |||
// not the right amount of parameters, try next method | |||
@@ -474,7 +474,9 @@ public class MethodProperty<T> extends AbstractProperty { | |||
* {@link #setValue(Object newValue)} is called. | |||
*/ | |||
@SuppressWarnings("unchecked") | |||
public MethodProperty(Class type, Object instance, Method getMethod, | |||
// cannot use "Class<? extends T>" because of automatic primitive type | |||
// conversions | |||
public MethodProperty(Class<?> type, Object instance, Method getMethod, | |||
Method setMethod, Object[] getArgs, Object[] setArgs, | |||
int setArgumentIndex) { | |||
@@ -495,13 +497,13 @@ public class MethodProperty<T> extends AbstractProperty { | |||
} | |||
// Gets the return type from get method | |||
type = convertPrimitiveType(type); | |||
Class<? extends T> convertedType = (Class<? extends T>) convertPrimitiveType(type); | |||
this.getMethod = getMethod; | |||
this.setMethod = setMethod; | |||
setArguments(getArgs, setArgs, setArgumentIndex); | |||
this.instance = instance; | |||
this.type = type; | |||
this.type = convertedType; | |||
} | |||
/** | |||
@@ -569,8 +571,7 @@ public class MethodProperty<T> extends AbstractProperty { | |||
* | |||
* @return type of the Property | |||
*/ | |||
@SuppressWarnings("unchecked") | |||
public final Class getType() { | |||
public final Class<? extends T> getType() { | |||
return type; | |||
} | |||
@@ -593,9 +594,9 @@ public class MethodProperty<T> extends AbstractProperty { | |||
* | |||
* @return the value of the Property | |||
*/ | |||
public Object getValue() { | |||
public T getValue() { | |||
try { | |||
return getMethod.invoke(instance, getArgs); | |||
return (T) getMethod.invoke(instance, getArgs); | |||
} catch (final Throwable e) { | |||
throw new MethodException(this, e); | |||
} | |||
@@ -642,7 +643,6 @@ public class MethodProperty<T> extends AbstractProperty { | |||
* native type directly or through <code>String</code>. | |||
* @see #invokeSetMethod(Object) | |||
*/ | |||
@SuppressWarnings("unchecked") | |||
public void setValue(Object newValue) throws Property.ReadOnlyException, | |||
Property.ConversionException { | |||
@@ -675,6 +675,7 @@ public class MethodProperty<T> extends AbstractProperty { | |||
// convert using a string constructor | |||
try { | |||
// Gets the string constructor | |||
@SuppressWarnings("rawtypes") | |||
final Constructor constr = type | |||
.getConstructor(new Class[] { String.class }); | |||
@@ -123,7 +123,7 @@ public class MethodPropertyDescriptor<BT> implements | |||
return propertyType; | |||
} | |||
public Property createProperty(Object bean) { | |||
public Property<?> createProperty(Object bean) { | |||
return new MethodProperty<Object>(propertyType, bean, readMethod, | |||
writeMethod); | |||
} |
@@ -26,7 +26,7 @@ import com.vaadin.data.util.MethodProperty.MethodException; | |||
* | |||
* @since 6.6 | |||
*/ | |||
public class NestedMethodProperty extends AbstractProperty { | |||
public class NestedMethodProperty<T> extends AbstractProperty<T> { | |||
// needed for de-serialization | |||
private String propertyName; | |||
@@ -43,7 +43,7 @@ public class NestedMethodProperty extends AbstractProperty { | |||
*/ | |||
private Object instance; | |||
private Class<?> type; | |||
private Class<? extends T> type; | |||
/* Special serialization to handle method references */ | |||
private void writeObject(java.io.ObjectOutputStream out) throws IOException { | |||
@@ -158,13 +158,14 @@ public class NestedMethodProperty extends AbstractProperty { | |||
} catch (final NoSuchMethodException skipped) { | |||
} | |||
this.type = MethodProperty.convertPrimitiveType(type); | |||
this.type = (Class<? extends T>) MethodProperty | |||
.convertPrimitiveType(type); | |||
this.propertyName = propertyName; | |||
this.getMethods = getMethods; | |||
this.setMethod = setMethod; | |||
} | |||
public Class<?> getType() { | |||
public Class<? extends T> getType() { | |||
return type; | |||
} | |||
@@ -179,13 +180,13 @@ public class NestedMethodProperty extends AbstractProperty { | |||
* | |||
* @return the value of the Property | |||
*/ | |||
public Object getValue() { | |||
public T getValue() { | |||
try { | |||
Object object = instance; | |||
for (Method m : getMethods) { | |||
object = m.invoke(object); | |||
} | |||
return object; | |||
return (T) object; | |||
} catch (final Throwable e) { | |||
throw new MethodException(this, e); | |||
} |
@@ -37,7 +37,8 @@ public class NestedPropertyDescriptor<BT> implements | |||
public NestedPropertyDescriptor(String name, Class<BT> beanType) | |||
throws IllegalArgumentException { | |||
this.name = name; | |||
NestedMethodProperty property = new NestedMethodProperty(beanType, name); | |||
NestedMethodProperty<?> property = new NestedMethodProperty<Object>( | |||
beanType, name); | |||
this.propertyType = property.getType(); | |||
} | |||
@@ -49,8 +50,8 @@ public class NestedPropertyDescriptor<BT> implements | |||
return propertyType; | |||
} | |||
public Property createProperty(BT bean) { | |||
return new NestedMethodProperty(bean, name); | |||
public Property<?> createProperty(BT bean) { | |||
return new NestedMethodProperty<Object>(bean, name); | |||
} | |||
} |
@@ -19,7 +19,7 @@ import com.vaadin.data.Property; | |||
* @since 3.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class ObjectProperty<T> extends AbstractProperty { | |||
public class ObjectProperty<T> extends AbstractProperty<T> { | |||
/** | |||
* The value contained by the Property. | |||
@@ -48,9 +48,8 @@ public class ObjectProperty<T> extends AbstractProperty { | |||
/** | |||
* Creates a new instance of ObjectProperty with the given value and type. | |||
* | |||
* Any value of type Object is accepted because, if the type class contains | |||
* a string constructor, the toString of the value is used to create the new | |||
* value. See {@link #setValue(Object)}. | |||
* Since Vaadin 7, only values of the correct type are accepted, and no | |||
* automatic conversions are performed. | |||
* | |||
* @param value | |||
* the Initial value of the Property. | |||
@@ -58,7 +57,7 @@ public class ObjectProperty<T> extends AbstractProperty { | |||
* the type of the value. The value must be assignable to given | |||
* type. | |||
*/ | |||
public ObjectProperty(Object value, Class<T> type) { | |||
public ObjectProperty(T value, Class<T> type) { | |||
// Set the values | |||
this.type = type; | |||
@@ -69,7 +68,7 @@ public class ObjectProperty<T> extends AbstractProperty { | |||
* Creates a new instance of ObjectProperty with the given value, type and | |||
* read-only mode status. | |||
* | |||
* Any value of type Object is accepted, see | |||
* Since Vaadin 7, only the correct type of values is accepted, see | |||
* {@link #ObjectProperty(Object, Class)}. | |||
* | |||
* @param value | |||
@@ -80,7 +79,7 @@ public class ObjectProperty<T> extends AbstractProperty { | |||
* @param readOnly | |||
* Sets the read-only mode. | |||
*/ | |||
public ObjectProperty(Object value, Class<T> type, boolean readOnly) { | |||
public ObjectProperty(T value, Class<T> type, boolean readOnly) { | |||
this(value, type); | |||
setReadOnly(readOnly); | |||
} |
@@ -29,16 +29,20 @@ import com.vaadin.data.Property; | |||
* standard "1.0" notation with more zeroes. | |||
* </p> | |||
* | |||
* @param T | |||
* type of the underlying property (a PropertyFormatter is always a | |||
* Property<String>) | |||
* | |||
* @author IT Mill Ltd. | |||
* @since 5.3.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public abstract class PropertyFormatter extends AbstractProperty implements | |||
Property.Viewer, Property.ValueChangeListener, | |||
public abstract class PropertyFormatter<T> extends AbstractProperty<String> | |||
implements Property.Viewer, Property.ValueChangeListener, | |||
Property.ReadOnlyStatusChangeListener { | |||
/** Datasource that stores the actual value. */ | |||
Property dataSource; | |||
Property<T> dataSource; | |||
/** | |||
* Construct a new {@code PropertyFormatter} that is not connected to any | |||
@@ -57,7 +61,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
* @param propertyDataSource | |||
* to connect this property to. | |||
*/ | |||
public PropertyFormatter(Property propertyDataSource) { | |||
public PropertyFormatter(Property<T> propertyDataSource) { | |||
setPropertyDataSource(propertyDataSource); | |||
} | |||
@@ -68,7 +72,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
* @return the current data source as a Property, or <code>null</code> if | |||
* none defined. | |||
*/ | |||
public Property getPropertyDataSource() { | |||
public Property<T> getPropertyDataSource() { | |||
return dataSource; | |||
} | |||
@@ -99,7 +103,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
.removeListener(this); | |||
} | |||
readOnly = isReadOnly(); | |||
prevValue = toString(); | |||
prevValue = getStringValue(); | |||
} | |||
dataSource = newDataSource; | |||
@@ -117,7 +121,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
if (isReadOnly() != readOnly) { | |||
fireReadOnlyStatusChange(); | |||
} | |||
String newVal = toString(); | |||
String newVal = getStringValue(); | |||
if ((prevValue == null && newVal != null) | |||
|| (prevValue != null && !prevValue.equals(newVal))) { | |||
fireValueChange(); | |||
@@ -125,7 +129,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
} | |||
/* Documented in the interface */ | |||
public Class getType() { | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
@@ -135,22 +139,20 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
* @return If the datasource returns null, this is null. Otherwise this is | |||
* String given by format(). | |||
*/ | |||
public Object getValue() { | |||
return toString(); | |||
public String getValue() { | |||
return getStringValue(); | |||
} | |||
/** | |||
* Get the formatted value. | |||
* Get the formatted value. For PropertyFormatter, this is identical with | |||
* {@link #getValue()}. | |||
* | |||
* @return If the datasource returns null, this is null. Otherwise this is | |||
* String given by format(). | |||
*/ | |||
@Override | |||
public String toString() { | |||
if (dataSource == null) { | |||
return null; | |||
} | |||
Object value = dataSource.getValue(); | |||
public String getStringValue() { | |||
T value = dataSource == null ? null : dataSource.getValue(); | |||
if (value == null) { | |||
return null; | |||
} | |||
@@ -173,7 +175,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
* datasource. | |||
* @return | |||
*/ | |||
abstract public String format(Object value); | |||
abstract public String format(T value); | |||
/** | |||
* Parse string and convert it to format compatible with datasource. | |||
@@ -187,7 +189,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
* Any type of exception can be thrown to indicate that the | |||
* conversion was not succesful. | |||
*/ | |||
abstract public Object parse(String formattedValue) throws Exception; | |||
abstract public T parse(String formattedValue) throws Exception; | |||
/** | |||
* Sets the Property's read-only mode to the specified status. | |||
@@ -215,7 +217,7 @@ public abstract class PropertyFormatter extends AbstractProperty implements | |||
} else { | |||
try { | |||
dataSource.setValue(parse(newValue.toString())); | |||
if (!newValue.equals(toString())) { | |||
if (!newValue.equals(getStringValue())) { | |||
fireValueChange(); | |||
} | |||
} catch (ConversionException e) { |
@@ -34,7 +34,7 @@ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, | |||
/** | |||
* Mapping from property id to property. | |||
*/ | |||
private HashMap<Object, Property> map = new HashMap<Object, Property>(); | |||
private HashMap<Object, Property<?>> map = new HashMap<Object, Property<?>>(); | |||
/** | |||
* List of all property ids to maintain the order. | |||
@@ -57,7 +57,7 @@ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, | |||
* the identifier of the Property to get. | |||
* @return the Property with the given ID or <code>null</code> | |||
*/ | |||
public Property getItemProperty(Object id) { | |||
public Property<?> getItemProperty(Object id) { | |||
return map.get(id); | |||
} | |||
@@ -143,7 +143,7 @@ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, | |||
for (final Iterator<?> i = getItemPropertyIds().iterator(); i.hasNext();) { | |||
final Object propertyId = i.next(); | |||
retValue += getItemProperty(propertyId).toString(); | |||
retValue += getItemProperty(propertyId).getValue(); | |||
if (i.hasNext()) { | |||
retValue += " "; | |||
} | |||
@@ -163,7 +163,7 @@ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
private class PropertySetChangeEvent extends EventObject implements | |||
private static class PropertySetChangeEvent extends EventObject implements | |||
Item.PropertySetChangeEvent { | |||
private PropertySetChangeEvent(Item source) { | |||
@@ -262,7 +262,7 @@ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, | |||
npsi.list = list != null ? (LinkedList<Object>) list.clone() : null; | |||
npsi.propertySetChangeListeners = propertySetChangeListeners != null ? (LinkedList<PropertySetChangeListener>) propertySetChangeListeners | |||
.clone() : null; | |||
npsi.map = (HashMap<Object, Property>) map.clone(); | |||
npsi.map = (HashMap<Object, Property<?>>) map.clone(); | |||
return npsi; | |||
} |
@@ -136,7 +136,8 @@ public class QueryContainer implements Container, Container.Ordered, | |||
for (int i = 1; i <= count; i++) { | |||
final String columnName = metadata.getColumnName(i); | |||
list.add(columnName); | |||
final Property p = getContainerProperty(new Integer(1), columnName); | |||
final Property<?> p = getContainerProperty(new Integer(1), | |||
columnName); | |||
propertyTypes.put(columnName, | |||
p == null ? Object.class : p.getType()); | |||
} | |||
@@ -228,7 +229,7 @@ public class QueryContainer implements Container, Container.Ordered, | |||
* otherwise. | |||
*/ | |||
public synchronized Property getContainerProperty(Object itemId, | |||
public synchronized Property<?> getContainerProperty(Object itemId, | |||
Object propertyId) { | |||
if (!(itemId instanceof Integer && propertyId instanceof String)) { | |||
return null; | |||
@@ -531,7 +532,7 @@ public class QueryContainer implements Container, Container.Ordered, | |||
* identifier of the Property to get | |||
* @return the Property with the given ID or <code>null</code> | |||
*/ | |||
public Property getItemProperty(Object propertyId) { | |||
public Property<?> getItemProperty(Object propertyId) { | |||
return getContainerProperty(id, propertyId); | |||
} | |||
@@ -26,7 +26,7 @@ import java.nio.charset.Charset; | |||
* | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class TextFileProperty extends AbstractProperty { | |||
public class TextFileProperty extends AbstractProperty<String> { | |||
private File file; | |||
private Charset charset = null; | |||
@@ -64,7 +64,7 @@ public class TextFileProperty extends AbstractProperty { | |||
* | |||
* @see com.vaadin.data.Property#getType() | |||
*/ | |||
public Class<?> getType() { | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
@@ -73,7 +73,7 @@ public class TextFileProperty extends AbstractProperty { | |||
* | |||
* @see com.vaadin.data.Property#getValue() | |||
*/ | |||
public Object getValue() { | |||
public String getValue() { | |||
if (file == null) { | |||
return null; | |||
} |
@@ -39,5 +39,5 @@ public interface VaadinPropertyDescriptor<BT> extends Serializable { | |||
* @param bean | |||
* @return | |||
*/ | |||
public Property createProperty(BT bean); | |||
public Property<?> createProperty(BT bean); | |||
} |
@@ -0,0 +1,32 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.util.Locale; | |||
public class BooleanToStringConverter implements Converter<Boolean, String> { | |||
public Boolean convertFromTargetToSource(String value, Locale locale) { | |||
try { | |||
return Boolean.valueOf(value); | |||
} catch (Exception e) { | |||
throw new ConversionException("Cannot convert " + value | |||
+ " to Boolean"); | |||
} | |||
} | |||
public String convertFromSourceToTarget(Boolean value, Locale locale) { | |||
if (value == null) { | |||
return ""; | |||
} | |||
return value.toString(); | |||
} | |||
public Class<Boolean> getSourceType() { | |||
return Boolean.class; | |||
} | |||
public Class<String> getTargetType() { | |||
return String.class; | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.io.Serializable; | |||
import java.util.Locale; | |||
public interface Converter<SOURCE, TARGET> extends Serializable { | |||
public SOURCE convertFromTargetToSource(TARGET value, Locale locale) | |||
throws ConversionException; | |||
public TARGET convertFromSourceToTarget(SOURCE value, Locale locale) | |||
throws ConversionException; | |||
public Class<SOURCE> getSourceType(); | |||
public Class<TARGET> getTargetType(); | |||
/** | |||
* An exception that signals that the value passed to #convert or | |||
* Converter.convertFromTargetToSource could not be converted. | |||
* | |||
* @author Vaadin Ltd | |||
* @version | |||
* @VERSION@ | |||
* @since 7.0 | |||
*/ | |||
public class ConversionException extends RuntimeException { | |||
/** | |||
* Constructs a new <code>ConversionException</code> without a detail | |||
* message. | |||
*/ | |||
public ConversionException() { | |||
} | |||
/** | |||
* Constructs a new <code>ConversionException</code> with the specified | |||
* detail message. | |||
* | |||
* @param msg | |||
* the detail message | |||
*/ | |||
public ConversionException(String msg) { | |||
super(msg); | |||
} | |||
/** | |||
* Constructs a new {@code ConversionException} with the specified | |||
* cause. | |||
* | |||
* @param cause | |||
* The cause of the the exception | |||
*/ | |||
public ConversionException(Throwable cause) { | |||
super(cause); | |||
} | |||
/** | |||
* Constructs a new <code>ConversionException</code> with the specified | |||
* detail message and cause. | |||
* | |||
* @param message | |||
* the detail message | |||
* @param cause | |||
* The cause of the the exception | |||
*/ | |||
public ConversionException(String message, Throwable cause) { | |||
super(message, cause); | |||
} | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
package com.vaadin.data.util.converter; | |||
public interface ConverterFactory { | |||
<SOURCE, TARGET> Converter<SOURCE, TARGET> createConverter( | |||
Class<SOURCE> sourceType, Class<TARGET> targetType); | |||
} |
@@ -0,0 +1,50 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.text.DateFormat; | |||
import java.text.ParsePosition; | |||
import java.util.Date; | |||
import java.util.Locale; | |||
public class DateToStringConverter implements Converter<Date, String> { | |||
public Date convertFromTargetToSource(String value, Locale locale) | |||
throws com.vaadin.data.util.converter.Converter.ConversionException { | |||
if (value == null) { | |||
return null; | |||
} | |||
ParsePosition parsePosition = new ParsePosition(0); | |||
Date parsedValue = getFormat(locale).parse(value, parsePosition); | |||
if (parsePosition.getIndex() != value.length()) { | |||
throw new ConversionException("Could not convert '" + value | |||
+ "' to " + getTargetType().getName()); | |||
} | |||
return parsedValue; | |||
} | |||
public String convertFromSourceToTarget(Date value, Locale locale) | |||
throws com.vaadin.data.util.converter.Converter.ConversionException { | |||
if (value == null) { | |||
return null; | |||
} | |||
return getFormat(locale).format(value); | |||
} | |||
protected DateFormat getFormat(Locale locale) { | |||
DateFormat f = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, | |||
DateFormat.MEDIUM, locale); | |||
f.setLenient(false); | |||
return f; | |||
} | |||
public Class<Date> getSourceType() { | |||
return Date.class; | |||
} | |||
public Class<String> getTargetType() { | |||
return String.class; | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.util.Date; | |||
public class DefaultConverterFactory implements ConverterFactory { | |||
public <SOURCE, TARGET> Converter<SOURCE, TARGET> createConverter( | |||
Class<SOURCE> sourceType, Class<TARGET> targetType) { | |||
Converter<SOURCE, TARGET> converter = findConverter(sourceType, | |||
targetType); | |||
if (converter != null) { | |||
System.out.println(getClass().getName() + " created a " | |||
+ converter.getClass()); | |||
return converter; | |||
} | |||
// Try to find a reverse converter | |||
Converter<TARGET, SOURCE> reverseConverter = findConverter(targetType, | |||
sourceType); | |||
if (reverseConverter != null) { | |||
System.out.println(getClass().getName() + " created a reverse " | |||
+ reverseConverter.getClass()); | |||
return new ReverseConverter<SOURCE, TARGET>(reverseConverter); | |||
} | |||
System.out.println(getClass().getName() | |||
+ " could not find a converter for " + sourceType.getName() | |||
+ " to " + targetType.getName() + " conversion"); | |||
return null; | |||
} | |||
protected <SOURCE, TARGET> Converter<SOURCE, TARGET> findConverter( | |||
Class<SOURCE> sourceType, Class<TARGET> targetType) { | |||
if (targetType == String.class) { | |||
// TextField converters and more | |||
Converter<SOURCE, TARGET> converter = (Converter<SOURCE, TARGET>) createStringConverter(sourceType); | |||
if (converter != null) { | |||
return converter; | |||
} | |||
} else if (targetType == Date.class) { | |||
// DateField converters and more | |||
Converter<SOURCE, TARGET> converter = (Converter<SOURCE, TARGET>) createDateConverter(sourceType); | |||
if (converter != null) { | |||
return converter; | |||
} | |||
} | |||
return null; | |||
} | |||
protected Converter<?, Date> createDateConverter(Class<?> sourceType) { | |||
if (Long.class.isAssignableFrom(sourceType)) { | |||
return new LongToDateConverter(); | |||
} else { | |||
return null; | |||
} | |||
} | |||
protected Converter<?, String> createStringConverter(Class<?> sourceType) { | |||
if (Double.class.isAssignableFrom(sourceType)) { | |||
return new DoubleToStringConverter(); | |||
} else if (Integer.class.isAssignableFrom(sourceType)) { | |||
return new IntegerToStringConverter(); | |||
} else if (Boolean.class.isAssignableFrom(sourceType)) { | |||
return new BooleanToStringConverter(); | |||
} else if (Number.class.isAssignableFrom(sourceType)) { | |||
return new NumberToStringConverter(); | |||
} else if (Date.class.isAssignableFrom(sourceType)) { | |||
return new DateToStringConverter(); | |||
} else { | |||
return null; | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.text.NumberFormat; | |||
import java.text.ParsePosition; | |||
import java.util.Locale; | |||
public class DoubleToStringConverter implements Converter<Double, String> { | |||
protected NumberFormat getFormatter(Locale locale) { | |||
return NumberFormat.getNumberInstance(locale); | |||
} | |||
public Double convertFromTargetToSource(String value, Locale locale) { | |||
ParsePosition parsePosition = new ParsePosition(0); | |||
Number parsedValue = getFormatter(locale).parse(value, parsePosition); | |||
if (parsePosition.getIndex() != value.length()) { | |||
throw new ConversionException("Could not convert '" + value | |||
+ "' to " + getTargetType().getName()); | |||
} | |||
return parsedValue.doubleValue(); | |||
} | |||
public String convertFromSourceToTarget(Double value, Locale locale) { | |||
if (value == null) { | |||
return null; | |||
} | |||
return getFormatter(locale).format(value); | |||
} | |||
public Class<Double> getSourceType() { | |||
return Double.class; | |||
} | |||
public Class<String> getTargetType() { | |||
return String.class; | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
package com.vaadin.data.util.converter; | |||
//package com.vaadin.data; | |||
// | |||
//import java.io.Serializable; | |||
// | |||
//import com.vaadin.ui.Field; | |||
// | |||
//public interface FieldValueConverterFactory extends Serializable { | |||
// | |||
// <SOURCE, TARGET> Converter<SOURCE, TARGET> createConverter( | |||
// Field<SOURCE> field, Item item, Object propertyId, | |||
// Class<TARGET> targetType); | |||
// | |||
// } |
@@ -0,0 +1,57 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.text.NumberFormat; | |||
import java.text.ParsePosition; | |||
import java.util.Locale; | |||
public class IntegerToStringConverter implements Converter<Integer, String> { | |||
protected NumberFormat getFormatter(Locale locale) { | |||
if (locale == null) { | |||
return NumberFormat.getIntegerInstance(); | |||
} else { | |||
return NumberFormat.getIntegerInstance(locale); | |||
} | |||
} | |||
public Integer convertFromTargetToSource(String value, Locale locale) { | |||
if (value == null) { | |||
return null; | |||
} | |||
// Remove extra spaces | |||
value = value.trim(); | |||
// Parse and detect errors. If the full string was not used, it is | |||
// an error. | |||
ParsePosition parsePosition = new ParsePosition(0); | |||
Number parsedValue = getFormatter(locale).parse(value, parsePosition); | |||
if (parsePosition.getIndex() != value.length()) { | |||
throw new ConversionException("Could not convert '" + value | |||
+ "' to " + getTargetType().getName()); | |||
} | |||
if (parsedValue == null) { | |||
// Convert "" to null | |||
return null; | |||
} | |||
return parsedValue.intValue(); | |||
} | |||
public String convertFromSourceToTarget(Integer value, Locale locale) { | |||
if (value == null) { | |||
return null; | |||
} | |||
return getFormatter(locale).format(value); | |||
} | |||
public Class<Integer> getSourceType() { | |||
return Integer.class; | |||
} | |||
public Class<String> getTargetType() { | |||
return String.class; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.util.Date; | |||
import java.util.Locale; | |||
public class LongToDateConverter implements Converter<Long, Date> { | |||
public Long convertFromTargetToSource(Date value, Locale locale) { | |||
if (value == null) { | |||
return null; | |||
} | |||
return value.getTime(); | |||
} | |||
public Date convertFromSourceToTarget(Long value, Locale locale) { | |||
if (value == null) { | |||
return null; | |||
} | |||
return new Date(value); | |||
} | |||
public Class<Long> getSourceType() { | |||
return Long.class; | |||
} | |||
public Class<Date> getTargetType() { | |||
return Date.class; | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.text.NumberFormat; | |||
import java.text.ParsePosition; | |||
import java.util.Locale; | |||
public class NumberToStringConverter implements Converter<Number, String> { | |||
protected NumberFormat getFormatter(Locale locale) { | |||
if (locale == null) { | |||
return NumberFormat.getNumberInstance(); | |||
} else { | |||
return NumberFormat.getNumberInstance(locale); | |||
} | |||
} | |||
public Number convertFromTargetToSource(String value, Locale locale) { | |||
if (value == null) { | |||
return null; | |||
} | |||
// Remove extra spaces | |||
value = value.trim(); | |||
// Parse and detect errors. If the full string was not used, it is | |||
// an error. | |||
ParsePosition parsePosition = new ParsePosition(0); | |||
Number parsedValue = getFormatter(locale).parse(value, parsePosition); | |||
if (parsePosition.getIndex() != value.length()) { | |||
throw new ConversionException("Could not convert '" + value | |||
+ "' to " + getTargetType().getName()); | |||
} | |||
if (parsedValue == null) { | |||
// Convert "" to null | |||
return null; | |||
} | |||
return parsedValue; | |||
} | |||
public String convertFromSourceToTarget(Number value, Locale locale) { | |||
if (value == null) { | |||
return null; | |||
} | |||
return getFormatter(locale).format(value); | |||
} | |||
public Class<Number> getSourceType() { | |||
return Number.class; | |||
} | |||
public Class<String> getTargetType() { | |||
return String.class; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
package com.vaadin.data.util.converter; | |||
import java.util.Locale; | |||
public class ReverseConverter<SOURCE, TARGET> implements | |||
Converter<SOURCE, TARGET> { | |||
private Converter<TARGET, SOURCE> realConverter; | |||
public ReverseConverter(Converter<TARGET, SOURCE> realConverter) { | |||
this.realConverter = realConverter; | |||
} | |||
public SOURCE convertFromTargetToSource(TARGET value, Locale locale) | |||
throws com.vaadin.data.util.converter.Converter.ConversionException { | |||
return realConverter.convertFromSourceToTarget(value, locale); | |||
} | |||
public TARGET convertFromSourceToTarget(SOURCE value, Locale locale) | |||
throws com.vaadin.data.util.converter.Converter.ConversionException { | |||
return realConverter.convertFromTargetToSource(value, locale); | |||
} | |||
public Class<SOURCE> getSourceType() { | |||
return realConverter.getTargetType(); | |||
} | |||
public Class<TARGET> getTargetType() { | |||
return realConverter.getSourceType(); | |||
} | |||
} |
@@ -228,7 +228,7 @@ public abstract class Compare implements Filter { | |||
} | |||
public boolean passesFilter(Object itemId, Item item) { | |||
final Property p = item.getItemProperty(getPropertyId()); | |||
final Property<?> p = item.getItemProperty(getPropertyId()); | |||
if (null == p) { | |||
return false; | |||
} |
@@ -35,7 +35,7 @@ public final class IsNull implements Filter { | |||
public boolean passesFilter(Object itemId, Item item) | |||
throws UnsupportedOperationException { | |||
final Property p = item.getItemProperty(getPropertyId()); | |||
final Property<?> p = item.getItemProperty(getPropertyId()); | |||
if (null == p) { | |||
return false; | |||
} |
@@ -40,12 +40,16 @@ public final class SimpleStringFilter implements Filter { | |||
} | |||
public boolean passesFilter(Object itemId, Item item) { | |||
final Property p = item.getItemProperty(propertyId); | |||
if (p == null || p.toString() == null) { | |||
final Property<?> p = item.getItemProperty(propertyId); | |||
if (p == null) { | |||
return false; | |||
} | |||
final String value = ignoreCase ? p.toString().toLowerCase() : p | |||
.toString(); | |||
Object propertyValue = p.getValue(); | |||
if (propertyValue == null) { | |||
return false; | |||
} | |||
final String value = ignoreCase ? propertyValue.toString() | |||
.toLowerCase() : propertyValue.toString(); | |||
if (onlyMatchPrefix) { | |||
if (!value.startsWith(filterString)) { | |||
return false; |
@@ -168,13 +168,38 @@ final public class ColumnProperty implements Property { | |||
return propertyId; | |||
} | |||
/** | |||
* Returns the value of the Property in human readable textual format. | |||
* | |||
* @see java.lang.Object#toString() | |||
* @deprecated get the string representation from the value, or use | |||
* getStringValue() during migration | |||
*/ | |||
@Deprecated | |||
@Override | |||
public String toString() { | |||
Object val = getValue(); | |||
if (val == null) { | |||
throw new UnsupportedOperationException( | |||
"Use ColumnProperty.getValue() instead of ColumnProperty.toString()"); | |||
} | |||
/** | |||
* Returns the (UI type) value of the field converted to a String using | |||
* toString(). | |||
* | |||
* This method exists to help migration from the use of Property.toString() | |||
* to get the field value - for new applications, access getValue() | |||
* directly. This method may disappear in future Vaadin versions. | |||
* | |||
* @return string representation of the field value or null if the value is | |||
* null | |||
* @since 7.0 | |||
*/ | |||
public String getStringValue() { | |||
final Object value = getValue(); | |||
if (value == null) { | |||
return null; | |||
} | |||
return val.toString(); | |||
return value.toString(); | |||
} | |||
public void setOwner(RowItem owner) { |
@@ -48,7 +48,7 @@ public final class RowItem implements Item { | |||
this.id = id; | |||
} | |||
public Property getItemProperty(Object id) { | |||
public Property<?> getItemProperty(Object id) { | |||
if (id instanceof String && id != null) { | |||
for (ColumnProperty cp : properties) { | |||
if (id.equals(cp.getPropertyId())) { | |||
@@ -113,7 +113,8 @@ public final class RowItem implements Item { | |||
s.append("|"); | |||
s.append(propId.toString()); | |||
s.append(":"); | |||
s.append(getItemProperty(propId).toString()); | |||
Object value = getItemProperty(propId).getValue(); | |||
s.append((null != value) ? value.toString() : null); | |||
} | |||
return s.toString(); | |||
} |
@@ -227,7 +227,7 @@ public class SQLContainer implements Container, Container.Filterable, | |||
* @see com.vaadin.data.Container#getContainerProperty(java.lang.Object, | |||
* java.lang.Object) | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId) { | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId) { | |||
Item item = getItem(itemId); | |||
if (item == null) { | |||
return null; | |||
@@ -1435,7 +1435,7 @@ public class SQLContainer implements Container, Container.Filterable, | |||
* Simple ItemSetChangeEvent implementation. | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class ItemSetChangeEvent extends EventObject implements | |||
public static class ItemSetChangeEvent extends EventObject implements | |||
Container.ItemSetChangeEvent { | |||
private ItemSetChangeEvent(SQLContainer source) { |
@@ -51,7 +51,8 @@ public abstract class AbstractStringValidator extends AbstractValidator { | |||
* @return true if the value (or its toString()) is a valid string, false | |||
* otherwise | |||
*/ | |||
public boolean isValid(Object value) { | |||
@Override | |||
protected boolean internalIsValid(Object value) { | |||
if (value == null) { | |||
return true; | |||
} |
@@ -21,6 +21,11 @@ import com.vaadin.data.Validator; | |||
* {@link InvalidValueException#getHtmlMessage()} and throw such exceptions from | |||
* {@link #validate(Object)}. | |||
* </p> | |||
* <p> | |||
* Since Vaadin 7, subclasses can either implement {@link #validate(Object)} | |||
* directly or implement {@link #internalIsValid(Object)} when migrating legacy | |||
* applications. To check validity, {@link #validate(Object)} should be used. | |||
* </p> | |||
* | |||
* @author IT Mill Ltd. | |||
* @version | |||
@@ -47,8 +52,46 @@ public abstract class AbstractValidator implements Validator { | |||
this.errorMessage = errorMessage; | |||
} | |||
/** | |||
* Since Vaadin 7, subclasses of AbstractValidator should override | |||
* {@link #internalIsValid(Object)} or {@link #validate(Object)} instead of | |||
* {@link #isValid(Object)}. {@link #validate(Object)} should be used to | |||
* check values. | |||
* | |||
* This method may disappear in future Vaadin versions. | |||
* | |||
* @param value | |||
* @return true if the value is valid | |||
* @deprecated override {@link #internalIsValid(Object)} or | |||
* {@link #validate(Object)} instead of {@link #isValid(Object)} | |||
* and use {@link #validate(Object)} to check value validity | |||
*/ | |||
@Deprecated | |||
protected final boolean isValid(Object value) { | |||
try { | |||
validate(value); | |||
return true; | |||
} catch (InvalidValueException e) { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Internally check the validity of a value. This method can be overridden | |||
* in subclasses if customization of the error message is not needed - | |||
* otherwise, subclasses should override {@link #validate(Object)} instead. | |||
* | |||
* This method should not be called from outside the validator class itself. | |||
* | |||
* @param value | |||
* @return | |||
*/ | |||
protected boolean internalIsValid(Object value) { | |||
return false; | |||
} | |||
public void validate(Object value) throws InvalidValueException { | |||
if (!isValid(value)) { | |||
if (!internalIsValid(value)) { | |||
String message = errorMessage.replace("{0}", String.valueOf(value)); | |||
throw new InvalidValueException(message); | |||
} |
@@ -10,6 +10,7 @@ import java.util.LinkedList; | |||
import java.util.List; | |||
import com.vaadin.data.Validator; | |||
import com.vaadin.data.validator.CompositeValidator.CombinationMode; | |||
/** | |||
* The <code>CompositeValidator</code> allows you to chain (compose) many | |||
@@ -130,38 +131,6 @@ public class CompositeValidator extends AbstractValidator { | |||
} | |||
} | |||
/** | |||
* Checks the validity of the the given value. The value is valid, if: | |||
* <ul> | |||
* <li>{@link CombinationMode.AND}: All of the sub-validators are valid | |||
* <li>{@link CombinationMode.OR}: Any of the sub-validators are valid | |||
* </ul> | |||
* | |||
* @param value | |||
* the value to check. | |||
*/ | |||
public boolean isValid(Object value) { | |||
switch (mode) { | |||
case AND: | |||
for (Validator v : validators) { | |||
if (!v.isValid(value)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
case OR: | |||
for (Validator v : validators) { | |||
if (v.isValid(value)) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
throw new IllegalStateException( | |||
"The validator is in unsupported operation mode"); | |||
} | |||
/** | |||
* Gets the mode of the validator. | |||
* |
@@ -50,17 +50,6 @@ public class NullValidator implements Validator { | |||
} | |||
} | |||
/** | |||
* Tests if the given value is valid. | |||
* | |||
* @param value | |||
* the value to validate. | |||
* @returns <code>true</code> for valid value, otherwise <code>false</code>. | |||
*/ | |||
public boolean isValid(Object value) { | |||
return onlyNullAllowed ? value == null : value != null; | |||
} | |||
/** | |||
* Returns <code>true</code> if nulls are allowed otherwise | |||
* <code>false</code>. |
@@ -61,7 +61,8 @@ public class StringLengthValidator extends AbstractValidator { | |||
* the value to validate. | |||
* @return <code>true</code> for valid value, otherwise <code>false</code>. | |||
*/ | |||
public boolean isValid(Object value) { | |||
@Override | |||
protected boolean internalIsValid(Object value) { | |||
if (value == null) { | |||
return allowNull; | |||
} |
@@ -1337,7 +1337,7 @@ public abstract class AbstractCommunicationManager implements | |||
if (owner instanceof AbstractField) { | |||
try { | |||
handled = ((AbstractField) owner).handleError(errorEvent); | |||
handled = ((AbstractField<?>) owner).handleError(errorEvent); | |||
} catch (Exception handlerException) { | |||
/* | |||
* If there is an error in the component error handler we pass |
@@ -327,6 +327,8 @@ public abstract class AbstractComponent implements Component, MethodEventSource | |||
*/ | |||
public void setLocale(Locale locale) { | |||
this.locale = locale; | |||
// FIXME: Reload value if there is a converter | |||
requestRepaint(); | |||
} | |||
@@ -12,11 +12,14 @@ import java.util.Iterator; | |||
import java.util.LinkedList; | |||
import java.util.Map; | |||
import com.vaadin.Application; | |||
import com.vaadin.data.Buffered; | |||
import com.vaadin.data.Property; | |||
import com.vaadin.data.Validatable; | |||
import com.vaadin.data.Validator; | |||
import com.vaadin.data.Validator.InvalidValueException; | |||
import com.vaadin.data.util.converter.Converter; | |||
import com.vaadin.data.util.converter.ConverterFactory; | |||
import com.vaadin.event.Action; | |||
import com.vaadin.event.ShortcutAction; | |||
import com.vaadin.event.ShortcutListener; | |||
@@ -52,8 +55,8 @@ import com.vaadin.terminal.PaintTarget; | |||
* @since 3.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public abstract class AbstractField extends AbstractComponent implements Field, | |||
Property.ReadOnlyStatusChangeListener, | |||
public abstract class AbstractField<T> extends AbstractComponent implements | |||
Field<T>, Property.ReadOnlyStatusChangeListener, | |||
Property.ReadOnlyStatusChangeNotifier, Action.ShortcutNotifier { | |||
/* Private members */ | |||
@@ -61,12 +64,17 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
/** | |||
* Value of the abstract field. | |||
*/ | |||
private Object value; | |||
private T value; | |||
/** | |||
* A converter used to convert from the data model type to the field type | |||
* and vice versa. | |||
*/ | |||
private Converter<Object, T> valueConverter = null; | |||
/** | |||
* Connected data-source. | |||
*/ | |||
private Property dataSource = null; | |||
private Property<?> dataSource = null; | |||
/** | |||
* The list of validators. | |||
@@ -178,11 +186,16 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
&& getErrorMessage() != null; | |||
} | |||
/* | |||
* Gets the field type Don't add a JavaDoc comment here, we use the default | |||
* documentation from the implemented interface. | |||
/** | |||
* Returns the type of the Field. The methods <code>getValue</code> and | |||
* <code>setValue</code> must be compatible with this type: one must be able | |||
* to safely cast the value returned from <code>getValue</code> to the given | |||
* type and pass any variable assignable to this type as an argument to | |||
* <code>setValue</code>. | |||
* | |||
* @return the type of the Field | |||
*/ | |||
public abstract Class<?> getType(); | |||
public abstract Class<? extends T> getType(); | |||
/** | |||
* The abstract field is read only also if the data source is in read only | |||
@@ -230,13 +243,14 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
public void commit() throws Buffered.SourceException, InvalidValueException { | |||
if (dataSource != null && !dataSource.isReadOnly()) { | |||
if ((isInvalidCommitted() || isValid())) { | |||
final Object newValue = getValue(); | |||
final T fieldValue = getFieldValue(); | |||
try { | |||
// Commits the value to datasource. | |||
valueWasModifiedByDataSourceDuringCommit = false; | |||
committingValueToDataSource = true; | |||
dataSource.setValue(newValue); | |||
getPropertyDataSource().setValue( | |||
convertToDataSource(fieldValue)); | |||
} catch (final Throwable e) { | |||
@@ -259,8 +273,8 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
boolean repaintNeeded = false; | |||
// The abstract field is not modified anymore | |||
if (modified) { | |||
modified = false; | |||
if (isModified()) { | |||
setModified(false); | |||
repaintNeeded = true; | |||
} | |||
@@ -287,12 +301,11 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
if (dataSource != null) { | |||
// Gets the correct value from datasource | |||
Object newValue; | |||
T newFieldValue; | |||
try { | |||
// Discards buffer by overwriting from datasource | |||
newValue = String.class == getType() ? dataSource.toString() | |||
: dataSource.getValue(); | |||
newFieldValue = convertFromDataSource(getDataSourceValue()); | |||
// If successful, remove set the buffering state to be ok | |||
if (currentBufferedSourceException != null) { | |||
@@ -300,6 +313,7 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
requestRepaint(); | |||
} | |||
} catch (final Throwable e) { | |||
// FIXME: What should really be done here if conversion fails? | |||
// Sets the buffering state | |||
currentBufferedSourceException = new Buffered.SourceException( | |||
@@ -311,22 +325,43 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
} | |||
final boolean wasModified = isModified(); | |||
modified = false; | |||
setModified(false); | |||
// If the new value differs from the previous one | |||
if ((newValue == null && value != null) | |||
|| (newValue != null && !newValue.equals(value))) { | |||
setInternalValue(newValue); | |||
if (!equals(newFieldValue, getInternalValue())) { | |||
setInternalValue(newFieldValue); | |||
fireValueChange(false); | |||
} | |||
// If the value did not change, but the modification status did | |||
else if (wasModified) { | |||
} else if (wasModified) { | |||
// If the value did not change, but the modification status did | |||
requestRepaint(); | |||
} | |||
} | |||
} | |||
private Object getDataSourceValue() { | |||
return dataSource.getValue(); | |||
} | |||
/** | |||
* Returns the value that is or should be displayed in the field. This is | |||
* always of type T. | |||
* | |||
* This method should return the same as | |||
* convertFromDataSource(getDataSourceValue()) if there are no buffered | |||
* changes in the field. | |||
* | |||
* @return The value of the field | |||
*/ | |||
private T getFieldValue() { | |||
// Give the value from abstract buffers if the field if possible | |||
if (dataSource == null || !isReadThrough() || isModified()) { | |||
return getInternalValue(); | |||
} | |||
// There is no buffered value so use whatever the data model provides | |||
return convertFromDataSource(getDataSourceValue()); | |||
} | |||
/* | |||
* Has the field been modified since the last commit()? Don't add a JavaDoc | |||
* comment here, we use the default documentation from the implemented | |||
@@ -336,6 +371,10 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
return modified; | |||
} | |||
private void setModified(boolean modified) { | |||
this.modified = modified; | |||
} | |||
/* | |||
* Tests if the field is in write-through mode. Don't add a JavaDoc comment | |||
* here, we use the default documentation from the implemented interface. | |||
@@ -379,9 +418,8 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
return; | |||
} | |||
readThroughMode = readThrough; | |||
if (!isModified() && readThroughMode && dataSource != null) { | |||
setInternalValue(String.class == getType() ? dataSource.toString() | |||
: dataSource.getValue()); | |||
if (!isModified() && readThroughMode && getPropertyDataSource() != null) { | |||
setInternalValue(convertFromDataSource(getDataSourceValue())); | |||
fireValueChange(false); | |||
} | |||
} | |||
@@ -392,14 +430,34 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
* Returns the value of the Property in human readable textual format. | |||
* | |||
* @see java.lang.Object#toString() | |||
* @deprecated get the string representation from the data source, or use | |||
* getStringValue() during migration | |||
*/ | |||
@Deprecated | |||
@Override | |||
public String toString() { | |||
final Object value = getValue(); | |||
throw new UnsupportedOperationException( | |||
"Use Property.getValue() instead of " + getClass() | |||
+ ".toString()"); | |||
} | |||
/** | |||
* Returns the (UI type) value of the field converted to a String. | |||
* | |||
* This method exists to help migration from the use of Property.toString() | |||
* to get the field value. For new applications, it is often better to | |||
* access getValue() directly. | |||
* | |||
* @return string representation of the field value or null if the value is | |||
* null | |||
* @since 7.0 | |||
*/ | |||
public String getStringValue() { | |||
final Object value = getFieldValue(); | |||
if (value == null) { | |||
return null; | |||
} | |||
return getValue().toString(); | |||
return value.toString(); | |||
} | |||
/** | |||
@@ -407,67 +465,63 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
* | |||
* <p> | |||
* This is the visible, modified and possible invalid value the user have | |||
* entered to the field. In the read-through mode, the abstract buffer is | |||
* also updated and validation is performed. | |||
* entered to the field. | |||
* </p> | |||
* | |||
* <p> | |||
* Note that the object returned is compatible with getType(). For example, | |||
* if the type is String, this returns Strings even when the underlying | |||
* datasource is of some other type. In order to access the datasources | |||
* native type, use getPropertyDatasource().getValue() instead. | |||
* datasource is of some other type. In order to access the native value of | |||
* the datasource, use getDataSourceValue() instead. | |||
* </p> | |||
* | |||
* <p> | |||
* Note that when you extend AbstractField, you must reimplement this method | |||
* if datasource.getValue() is not assignable to class returned by getType() | |||
* AND getType() is not String. In case of Strings, getValue() calls | |||
* datasource.toString() instead of datasource.getValue(). | |||
* Since Vaadin 7.0, no implicit conversions between other data types and | |||
* String are performed, but a value converter is used if set. | |||
* </p> | |||
* | |||
* @return the current value of the field. | |||
* @throws Property.ConversionException | |||
*/ | |||
public Object getValue() { | |||
// Give the value from abstract buffers if the field if possible | |||
if (dataSource == null || !isReadThrough() || isModified()) { | |||
return value; | |||
} | |||
Object newValue = String.class == getType() ? dataSource.toString() | |||
: dataSource.getValue(); | |||
return newValue; | |||
public T getValue() { | |||
return getFieldValue(); | |||
} | |||
/** | |||
* Sets the value of the field. | |||
* | |||
* @param newValue | |||
* @param newFieldValue | |||
* the New value of the field. | |||
* @throws Property.ReadOnlyException | |||
* @throws Property.ConversionException | |||
*/ | |||
public void setValue(Object newValue) throws Property.ReadOnlyException, | |||
Property.ConversionException { | |||
setValue(newValue, false); | |||
public void setValue(Object newFieldValue) | |||
throws Property.ReadOnlyException, Property.ConversionException { | |||
// This check is needed as long as setValue accepts Object instead of T | |||
if (newFieldValue != null) { | |||
if (!getType().isAssignableFrom(newFieldValue.getClass())) { | |||
throw new ConversionException("Value of type " | |||
+ newFieldValue.getClass() + " cannot be assigned to " | |||
+ getClass().getName()); | |||
} | |||
} | |||
setValue((T) newFieldValue, false); | |||
} | |||
/** | |||
* Sets the value of the field. | |||
* | |||
* @param newValue | |||
* @param newFieldValue | |||
* the New value of the field. | |||
* @param repaintIsNotNeeded | |||
* True iff caller is sure that repaint is not needed. | |||
* @throws Property.ReadOnlyException | |||
* @throws Property.ConversionException | |||
*/ | |||
protected void setValue(Object newValue, boolean repaintIsNotNeeded) | |||
protected void setValue(T newFieldValue, boolean repaintIsNotNeeded) | |||
throws Property.ReadOnlyException, Property.ConversionException { | |||
if ((newValue == null && value != null) | |||
|| (newValue != null && !newValue.equals(value))) { | |||
if (!equals(newFieldValue, getInternalValue())) { | |||
// Read only fields can not be changed | |||
if (isReadOnly()) { | |||
@@ -486,14 +540,14 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
if (v != null) { | |||
for (final Iterator<Validator> i = v.iterator(); i | |||
.hasNext();) { | |||
(i.next()).validate(newValue); | |||
(i.next()).validate(newFieldValue); | |||
} | |||
} | |||
} | |||
// Changes the value | |||
setInternalValue(newValue); | |||
modified = dataSource != null; | |||
setInternalValue(newFieldValue); | |||
setModified(dataSource != null); | |||
valueWasModifiedByDataSourceDuringCommit = false; | |||
// In write through mode , try to commit | |||
@@ -503,10 +557,11 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
// Commits the value to datasource | |||
committingValueToDataSource = true; | |||
dataSource.setValue(newValue); | |||
getPropertyDataSource().setValue( | |||
convertToDataSource(newFieldValue)); | |||
// The buffer is now unmodified | |||
modified = false; | |||
setModified(false); | |||
} catch (final Throwable e) { | |||
@@ -542,6 +597,13 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
} | |||
} | |||
private static boolean equals(Object value1, Object value2) { | |||
if (value1 == null) { | |||
return value2 == null; | |||
} | |||
return value1.equals(value2); | |||
} | |||
/* External data source */ | |||
/** | |||
@@ -584,7 +646,7 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
public void setPropertyDataSource(Property newDataSource) { | |||
// Saves the old value | |||
final Object oldValue = value; | |||
final Object oldValue = getInternalValue(); | |||
// Stops listening the old data source changes | |||
if (dataSource != null | |||
@@ -602,17 +664,23 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
// Sets the new data source | |||
dataSource = newDataSource; | |||
// Check if the current converter is compatible. If not, get a new one | |||
if (newDataSource == null) { | |||
setValueConverter(null); | |||
} else if (!isValueConverterType(newDataSource.getType())) { | |||
setValueConverterFromFactory(newDataSource.getType()); | |||
} | |||
// Gets the value from source | |||
try { | |||
if (dataSource != null) { | |||
setInternalValue(String.class == getType() ? dataSource | |||
.toString() : dataSource.getValue()); | |||
T fieldValue = convertFromDataSource(getDataSourceValue()); | |||
setInternalValue(fieldValue); | |||
} | |||
modified = false; | |||
setModified(false); | |||
} catch (final Throwable e) { | |||
currentBufferedSourceException = new Buffered.SourceException(this, | |||
e); | |||
modified = true; | |||
setModified(true); | |||
} | |||
// Listens the new data source if possible | |||
@@ -637,12 +705,91 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
} | |||
// Fires value change if the value has changed | |||
T value = getInternalValue(); | |||
if ((value != oldValue) | |||
&& ((value != null && !value.equals(oldValue)) || value == null)) { | |||
fireValueChange(false); | |||
} | |||
} | |||
private void setValueConverterFromFactory(Class<?> datamodelType) { | |||
// FIXME Use thread local to get application | |||
ConverterFactory factory = Application.getConverterFactory(); | |||
Converter<?, T> converter = (Converter<?, T>) factory.createConverter( | |||
datamodelType, getType()); | |||
setValueConverter(converter); | |||
} | |||
private boolean isValueConverterType(Class<?> type) { | |||
if (getValueConverter() == null) { | |||
return false; | |||
} | |||
return getValueConverter().getSourceType().isAssignableFrom(type); | |||
} | |||
@SuppressWarnings("unchecked") | |||
private T convertFromDataSource(Object newValue) { | |||
if (valueConverter != null) { | |||
return valueConverter.convertFromSourceToTarget(newValue, | |||
getLocale()); | |||
} | |||
if (newValue == null) { | |||
return null; | |||
} | |||
if (getType().isAssignableFrom(newValue.getClass())) { | |||
return (T) newValue; | |||
} else { | |||
throw new ConversionException( | |||
"Unable to convert value of type " | |||
+ newValue.getClass().getName() | |||
+ " to " | |||
+ getType() | |||
+ ". No value converter is set and the types are not compatible."); | |||
} | |||
} | |||
private Object convertToDataSource(T fieldValue) | |||
throws Converter.ConversionException { | |||
if (valueConverter != null) { | |||
/* | |||
* If there is a value converter, always use it. It must convert or | |||
* throw an exception. | |||
*/ | |||
return valueConverter.convertFromTargetToSource(fieldValue, | |||
getLocale()); | |||
} | |||
if (fieldValue == null) { | |||
// Null should always be passed through the converter but if there | |||
// is no converter we can safely return null | |||
return null; | |||
} | |||
// check that the value class is compatible with the data source type | |||
// (if data source set) or field type | |||
Class<?> type; | |||
if (getPropertyDataSource() != null) { | |||
type = getPropertyDataSource().getType(); | |||
} else { | |||
type = getType(); | |||
} | |||
if (type.isAssignableFrom(fieldValue.getClass())) { | |||
return fieldValue; | |||
} else { | |||
throw new Converter.ConversionException( | |||
"Unable to convert value of type " | |||
+ fieldValue.getClass().getName() | |||
+ " to " | |||
+ type.getName() | |||
+ ". No value converter is set and the types are not compatible."); | |||
} | |||
} | |||
/* Validation */ | |||
/** | |||
@@ -691,32 +838,21 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
* empty. If the field is empty it is considered valid if it is not required | |||
* and invalid otherwise. Validators are never checked for empty fields. | |||
* | |||
* In most cases, {@link #validate()} should be used instead of | |||
* {@link #isValid()} to also get the error message. | |||
* | |||
* @return <code>true</code> if all registered validators claim that the | |||
* current value is valid or if the field is empty and not required, | |||
* <code>false</code> otherwise. | |||
*/ | |||
public boolean isValid() { | |||
if (isEmpty()) { | |||
if (isRequired()) { | |||
return false; | |||
} else { | |||
return true; | |||
} | |||
} | |||
if (validators == null) { | |||
try { | |||
validate(); | |||
return true; | |||
} catch (InvalidValueException e) { | |||
return false; | |||
} | |||
final Object value = getValue(); | |||
for (final Iterator<Validator> i = validators.iterator(); i.hasNext();) { | |||
if (!(i.next()).isValid(value)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
/** | |||
@@ -748,12 +884,12 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
// Initialize temps | |||
Validator.InvalidValueException firstError = null; | |||
LinkedList<InvalidValueException> errors = null; | |||
final Object value = getValue(); | |||
final Object fieldValue = getFieldValue(); | |||
// Gets all the validation errors | |||
for (final Iterator<Validator> i = validators.iterator(); i.hasNext();) { | |||
try { | |||
(i.next()).validate(value); | |||
(i.next()).validate(fieldValue); | |||
} catch (final Validator.InvalidValueException e) { | |||
if (firstError == null) { | |||
firstError = e; | |||
@@ -942,8 +1078,8 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
public class ReadOnlyStatusChangeEvent extends Component.Event implements | |||
Property.ReadOnlyStatusChangeEvent, Serializable { | |||
public static class ReadOnlyStatusChangeEvent extends Component.Event | |||
implements Property.ReadOnlyStatusChangeEvent, Serializable { | |||
/** | |||
* New instance of text change event. | |||
@@ -1007,10 +1143,8 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
public void valueChange(Property.ValueChangeEvent event) { | |||
if (isReadThrough()) { | |||
if (committingValueToDataSource) { | |||
boolean propertyNotifiesOfTheBufferedValue = event | |||
.getProperty().getValue() == value | |||
|| (value != null && value.equals(event.getProperty() | |||
.getValue())); | |||
boolean propertyNotifiesOfTheBufferedValue = equals(event | |||
.getProperty().getValue(), getInternalValue()); | |||
if (!propertyNotifiesOfTheBufferedValue) { | |||
/* | |||
* Property (or chained property like PropertyFormatter) now | |||
@@ -1033,7 +1167,7 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
} | |||
private void readValueFromProperty(Property.ValueChangeEvent event) { | |||
setInternalValue(event.getProperty().getValue()); | |||
setInternalValue(convertFromDataSource(event.getProperty().getValue())); | |||
} | |||
@Override | |||
@@ -1049,25 +1183,6 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
super.focus(); | |||
} | |||
/** | |||
* Creates abstract field by the type of the property. | |||
* | |||
* <p> | |||
* This returns most suitable field type for editing property of given type. | |||
* </p> | |||
* | |||
* @param propertyType | |||
* the Type of the property, that needs to be edited. | |||
* @deprecated use e.g. | |||
* {@link DefaultFieldFactory#createFieldByPropertyType(Class)} | |||
* instead | |||
*/ | |||
@Deprecated | |||
public static AbstractField constructField(Class<?> propertyType) { | |||
return (AbstractField) DefaultFieldFactory | |||
.createFieldByPropertyType(propertyType); | |||
} | |||
/* | |||
* (non-Javadoc) | |||
* | |||
@@ -1087,6 +1202,14 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
requestRepaint(); | |||
} | |||
/** | |||
* | |||
* @return | |||
*/ | |||
protected T getInternalValue() { | |||
return value; | |||
} | |||
/** | |||
* Sets the internal field value. This is purely used by AbstractField to | |||
* change the internal Field value. It does not trigger valuechange events. | |||
@@ -1096,7 +1219,7 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
* @param newValue | |||
* the new value to be set. | |||
*/ | |||
protected void setInternalValue(Object newValue) { | |||
protected void setInternalValue(T newValue) { | |||
value = newValue; | |||
if (validators != null && !validators.isEmpty()) { | |||
requestRepaint(); | |||
@@ -1168,7 +1291,7 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
* also treats empty string as "empty". | |||
*/ | |||
protected boolean isEmpty() { | |||
return (getValue() == null); | |||
return (getFieldValue() == null); | |||
} | |||
/** | |||
@@ -1271,4 +1394,32 @@ public abstract class AbstractField extends AbstractComponent implements Field, | |||
focusable.focus(); | |||
} | |||
} | |||
/** | |||
* Gets the converter used to convert the property data source value to the | |||
* field value. | |||
* | |||
* @return The converter or null if none is set. | |||
*/ | |||
public Converter<Object, T> getValueConverter() { | |||
return valueConverter; | |||
} | |||
/** | |||
* Sets the converter used to convert the property data source value to the | |||
* field value. The converter must have a target type that matches the field | |||
* type. | |||
* | |||
* The source for the converter is the data model and the target is the | |||
* field. | |||
* | |||
* @param valueConverter | |||
* The new value converter to use. | |||
*/ | |||
public void setValueConverter(Converter<?, T> valueConverter) { | |||
// | |||
this.valueConverter = (Converter<Object, T>) valueConverter; | |||
requestRepaint(); | |||
} | |||
} |
@@ -55,7 +55,8 @@ import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; | |||
* @since 5.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public abstract class AbstractSelect extends AbstractField implements | |||
// TODO currently cannot specify type more precisely in case of multi-select | |||
public abstract class AbstractSelect extends AbstractField<Object> implements | |||
Container, Container.Viewer, Container.PropertySetChangeListener, | |||
Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier, | |||
Container.ItemSetChangeListener { | |||
@@ -729,7 +730,7 @@ public abstract class AbstractSelect extends AbstractField implements | |||
* | |||
* @see com.vaadin.data.Container#getContainerProperty(Object, Object) | |||
*/ | |||
public Property getContainerProperty(Object itemId, Object propertyId) { | |||
public Property<?> getContainerProperty(Object itemId, Object propertyId) { | |||
return items.getContainerProperty(itemId, propertyId); | |||
} | |||
@@ -1077,10 +1078,13 @@ public abstract class AbstractSelect extends AbstractField implements | |||
break; | |||
case ITEM_CAPTION_MODE_PROPERTY: | |||
final Property p = getContainerProperty(itemId, | |||
final Property<?> p = getContainerProperty(itemId, | |||
getItemCaptionPropertyId()); | |||
if (p != null) { | |||
caption = p.toString(); | |||
Object value = p.getValue(); | |||
if (value != null) { | |||
caption = value.toString(); | |||
} | |||
} | |||
break; | |||
} | |||
@@ -1125,7 +1129,7 @@ public abstract class AbstractSelect extends AbstractField implements | |||
return null; | |||
} | |||
final Property ip = getContainerProperty(itemId, | |||
final Property<?> ip = getContainerProperty(itemId, | |||
getItemIconPropertyId()); | |||
if (ip == null) { | |||
return null; | |||
@@ -1704,7 +1708,7 @@ public abstract class AbstractSelect extends AbstractField implements | |||
Collection<?> pids = i.getItemPropertyIds(); | |||
if (pids != null) { | |||
for (Iterator<?> it = pids.iterator(); it.hasNext();) { | |||
Property p = i.getItemProperty(it.next()); | |||
Property<?> p = i.getItemProperty(it.next()); | |||
if (p != null | |||
&& p instanceof Property.ValueChangeNotifier) { | |||
((Property.ValueChangeNotifier) p) | |||
@@ -1716,7 +1720,7 @@ public abstract class AbstractSelect extends AbstractField implements | |||
} | |||
break; | |||
case ITEM_CAPTION_MODE_PROPERTY: | |||
final Property p = getContainerProperty(itemId, | |||
final Property<?> p = getContainerProperty(itemId, | |||
getItemCaptionPropertyId()); | |||
if (p != null && p instanceof Property.ValueChangeNotifier) { | |||
((Property.ValueChangeNotifier) p) |
@@ -20,7 +20,7 @@ import com.vaadin.terminal.PaintException; | |||
import com.vaadin.terminal.PaintTarget; | |||
import com.vaadin.terminal.gwt.client.ui.VTextField; | |||
public abstract class AbstractTextField extends AbstractField implements | |||
public abstract class AbstractTextField extends AbstractField<String> implements | |||
BlurNotifier, FocusNotifier, TextChangeNotifier { | |||
/** | |||
@@ -171,8 +171,8 @@ public abstract class AbstractTextField extends AbstractField implements | |||
} | |||
@Override | |||
public Object getValue() { | |||
Object v = super.getValue(); | |||
public String getValue() { | |||
String v = super.getValue(); | |||
if (format == null || v == null) { | |||
return v; | |||
} | |||
@@ -250,7 +250,7 @@ public abstract class AbstractTextField extends AbstractField implements | |||
} | |||
@Override | |||
public Class getType() { | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
@@ -373,7 +373,7 @@ public abstract class AbstractTextField extends AbstractField implements | |||
@Override | |||
protected boolean isEmpty() { | |||
return super.isEmpty() || toString().length() == 0; | |||
return super.isEmpty() || getStringValue().length() == 0; | |||
} | |||
/** | |||
@@ -456,7 +456,7 @@ public abstract class AbstractTextField extends AbstractField implements | |||
} | |||
@Override | |||
protected void setInternalValue(Object newValue) { | |||
protected void setInternalValue(String newValue) { | |||
if (changingVariables && !textChangeEventPending) { | |||
/* | |||
@@ -513,7 +513,7 @@ public abstract class AbstractTextField extends AbstractField implements | |||
* case. AbstractField optimizes value change if the existing value is | |||
* reset. Also we need to force repaint if the flag is on. | |||
*/ | |||
if(lastKnownTextContent != null) { | |||
if (lastKnownTextContent != null) { | |||
lastKnownTextContent = null; | |||
requestRepaint(); | |||
} | |||
@@ -751,4 +751,4 @@ public abstract class AbstractTextField extends AbstractField implements | |||
removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); | |||
} | |||
} | |||
} |
@@ -40,7 +40,7 @@ public class BaseFieldFactory implements FieldFactory { | |||
* | |||
* @see com.vaadin.ui.FieldFactory#createField(Class, Component) | |||
*/ | |||
public Field createField(Class<?> type, Component uiContext) { | |||
public Field<?> createField(Class<?> type, Component uiContext) { | |||
return DefaultFieldFactory.createFieldByPropertyType(type); | |||
} | |||
@@ -49,7 +49,7 @@ public class BaseFieldFactory implements FieldFactory { | |||
* | |||
* @see com.vaadin.ui.FieldFactory#createField(Property, Component) | |||
*/ | |||
public Field createField(Property property, Component uiContext) { | |||
public Field<?> createField(Property property, Component uiContext) { | |||
if (property != null) { | |||
return createField(property.getType(), uiContext); | |||
} else { | |||
@@ -62,9 +62,10 @@ public class BaseFieldFactory implements FieldFactory { | |||
* | |||
* @see com.vaadin.ui.FieldFactory#createField(Item, Object, Component) | |||
*/ | |||
public Field createField(Item item, Object propertyId, Component uiContext) { | |||
public Field<?> createField(Item item, Object propertyId, | |||
Component uiContext) { | |||
if (item != null && propertyId != null) { | |||
final Field f = createField(item.getItemProperty(propertyId), | |||
final Field<?> f = createField(item.getItemProperty(propertyId), | |||
uiContext); | |||
if (f instanceof AbstractComponent) { | |||
String name = DefaultFieldFactory | |||
@@ -81,7 +82,7 @@ public class BaseFieldFactory implements FieldFactory { | |||
* @see com.vaadin.ui.FieldFactory#createField(com.vaadin.data.Container, | |||
* java.lang.Object, java.lang.Object, com.vaadin.ui.Component) | |||
*/ | |||
public Field createField(Container container, Object itemId, | |||
public Field<?> createField(Container container, Object itemId, | |||
Object propertyId, Component uiContext) { | |||
return createField(container.getContainerProperty(itemId, propertyId), | |||
uiContext); |
@@ -75,27 +75,6 @@ public class Button extends AbstractComponent implements | |||
addListener(listener); | |||
} | |||
/** | |||
* Creates a new push button with a method listening button clicks. Using | |||
* this method is discouraged because it cannot be checked during | |||
* compilation. Use | |||
* {@link #Button(String, com.vaadin.ui.Button.ClickListener)} instead. The | |||
* method must have either no parameters, or only one parameter of | |||
* Button.ClickEvent type. | |||
* | |||
* @param caption | |||
* the Button caption. | |||
* @param target | |||
* the Object having the method for listening button clicks. | |||
* @param methodName | |||
* the name of the method in target object, that receives button | |||
* click events. | |||
*/ | |||
public Button(String caption, Object target, String methodName) { | |||
this(caption); | |||
addListener(ClickEvent.class, target, methodName); | |||
} | |||
/** | |||
* Paints the content of this component. | |||
* |
@@ -16,11 +16,12 @@ import com.vaadin.terminal.PaintTarget; | |||
import com.vaadin.terminal.gwt.client.ui.VCheckBox; | |||
@ClientWidget(com.vaadin.terminal.gwt.client.ui.VCheckBox.class) | |||
public class CheckBox extends AbstractField { | |||
public class CheckBox extends AbstractField<Boolean> { | |||
/** | |||
* Creates a new checkbox. | |||
*/ | |||
public CheckBox() { | |||
setValue(Boolean.FALSE); | |||
} | |||
/** | |||
@@ -54,13 +55,13 @@ public class CheckBox extends AbstractField { | |||
* the Initial state of the switch-button. | |||
* @param dataSource | |||
*/ | |||
public CheckBox(String caption, Property dataSource) { | |||
public CheckBox(String caption, Property<?> dataSource) { | |||
this(caption); | |||
setPropertyDataSource(dataSource); | |||
} | |||
@Override | |||
public Class<?> getType() { | |||
public Class<Boolean> getType() { | |||
return Boolean.class; | |||
} | |||
@@ -68,7 +69,7 @@ public class CheckBox extends AbstractField { | |||
public void paintContent(PaintTarget target) throws PaintException { | |||
super.paintContent(target); | |||
target.addVariable(this, VCheckBox.VARIABLE_STATE, booleanValue()); | |||
target.addVariable(this, VCheckBox.VARIABLE_STATE, getValue()); | |||
} | |||
@Override | |||
@@ -79,7 +80,7 @@ public class CheckBox extends AbstractField { | |||
// Gets the new and old states | |||
final Boolean newValue = (Boolean) variables | |||
.get(VCheckBox.VARIABLE_STATE); | |||
final Boolean oldValue = (Boolean) getValue(); | |||
final Boolean oldValue = getValue(); | |||
// The event is only sent if the switch state is changed | |||
if (newValue != null && !newValue.equals(oldValue)) { | |||
@@ -114,19 +115,4 @@ public class CheckBox extends AbstractField { | |||
} | |||
/** | |||
* Get the boolean value of the checkbox state. | |||
* | |||
* @return True iff the checkbox is checked. | |||
* @deprecated in Vaadin 7.0.0. Retained to ease migration from Vaadin 6 | |||
*/ | |||
@Deprecated | |||
public boolean booleanValue() { | |||
// FIXME: How should null really be handled? A default converter that | |||
// converts it to false? The only UI values supported are true and | |||
// false. | |||
Boolean value = (Boolean) getValue(); | |||
return (null == value) ? false : value.booleanValue(); | |||
} | |||
} |
@@ -35,11 +35,6 @@ public class CustomComponent extends AbstractComponentContainer { | |||
*/ | |||
private Component root = null; | |||
/** | |||
* Type of the component. | |||
*/ | |||
private String componentType = null; | |||
/** | |||
* Constructs a new custom component. | |||
* | |||
@@ -115,43 +110,9 @@ public class CustomComponent extends AbstractComponentContainer { | |||
+ " can be painted"); | |||
} | |||
if (getComponentType() != null) { | |||
target.addAttribute("type", getComponentType()); | |||
} | |||
root.paint(target); | |||
} | |||
/** | |||
* Gets the component type. | |||
* | |||
* The component type is textual type of the component. This is included in | |||
* the UIDL as component tag attribute. | |||
* | |||
* @deprecated not more useful as the whole tag system has been removed | |||
* | |||
* @return the component type. | |||
*/ | |||
@Deprecated | |||
public String getComponentType() { | |||
return componentType; | |||
} | |||
/** | |||
* Sets the component type. | |||
* | |||
* The component type is textual type of the component. This is included in | |||
* the UIDL as component tag attribute. | |||
* | |||
* @deprecated not more useful as the whole tag system has been removed | |||
* | |||
* @param componentType | |||
* the componentType to set. | |||
*/ | |||
@Deprecated | |||
public void setComponentType(String componentType) { | |||
this.componentType = componentType; | |||
} | |||
private class ComponentIterator implements Iterator<Component>, | |||
Serializable { | |||
boolean first = getCompositionRoot() != null; |
@@ -0,0 +1,242 @@ | |||
package com.vaadin.ui; | |||
import java.io.Serializable; | |||
import java.lang.reflect.Method; | |||
import java.util.Iterator; | |||
import com.vaadin.data.Property; | |||
import com.vaadin.terminal.PaintException; | |||
import com.vaadin.terminal.PaintTarget; | |||
import com.vaadin.terminal.gwt.client.ui.VCustomComponent; | |||
/** | |||
* A {@link Field} whose UI content can be constructed by the user, enabling the | |||
* creation of e.g. form fields by composing Vaadin components. Customization of | |||
* both the visual presentation and the logic of the field is possible. | |||
* | |||
* Subclasses must implement {@link #getType()} and {@link #createContent()}. | |||
* | |||
* Most custom fields can simply compose a user interface that calls the methods | |||
* {@link #setInternalValue(Object)} and {@link #getInternalValue()} when | |||
* necessary. | |||
* | |||
* It is also possible to override {@link #commit()}, | |||
* {@link #setPropertyDataSource(Property)} and other logic of the field. | |||
* | |||
* @since 7.0 | |||
*/ | |||
@ClientWidget(VCustomComponent.class) | |||
public abstract class CustomField<T> extends AbstractField<T> implements | |||
ComponentContainer { | |||
/** | |||
* The root component implementing the custom component. | |||
*/ | |||
private Component root = null; | |||
/** | |||
* Constructs a new custom field. | |||
* | |||
* <p> | |||
* The component is implemented by wrapping the methods of the composition | |||
* root component given as parameter. The composition root must be set | |||
* before the component can be used. | |||
* </p> | |||
*/ | |||
public CustomField() { | |||
// expand horizontally by default | |||
setWidth(100, UNITS_PERCENTAGE); | |||
} | |||
/** | |||
* Constructs the content and notifies it that the {@link CustomField} is | |||
* attached to a window. | |||
* | |||
* @see com.vaadin.ui.Component#attach() | |||
*/ | |||
@Override | |||
public void attach() { | |||
root = getContent(); | |||
super.attach(); | |||
getContent().setParent(this); | |||
getContent().attach(); | |||
fireComponentAttachEvent(getContent()); | |||
} | |||
/** | |||
* Notifies the content that the {@link CustomField} is detached from a | |||
* window. | |||
* | |||
* @see com.vaadin.ui.Component#detach() | |||
*/ | |||
@Override | |||
public void detach() { | |||
super.detach(); | |||
getContent().detach(); | |||
} | |||
@Override | |||
public void paintContent(PaintTarget target) throws PaintException { | |||
if (getContent() == null) { | |||
throw new IllegalStateException( | |||
"Content component or layout of the field must be set before the " | |||
+ getClass().getName() + " can be painted"); | |||
} | |||
getContent().paint(target); | |||
} | |||
/** | |||
* Returns the content of the | |||
* | |||
* @return | |||
*/ | |||
protected Component getContent() { | |||
if (null == root) { | |||
root = createContent(); | |||
} | |||
return root; | |||
} | |||
/** | |||
* Create the content component or layout for the field. Subclasses of | |||
* {@link CustomField} should implement this method. | |||
* | |||
* Note that this method is called when the CustomField is attached to a | |||
* layout or when {@link #getContent()} is called explicitly for the first | |||
* time. It is only called once for a {@link CustomField}. | |||
* | |||
* @return | |||
*/ | |||
protected abstract Component createContent(); | |||
private void requestContentRepaint() { | |||
if (getParent() == null) { | |||
// skip repaint - not yet attached | |||
return; | |||
} | |||
if (getContent() instanceof ComponentContainer) { | |||
((ComponentContainer) getContent()).requestRepaintAll(); | |||
} else { | |||
getContent().requestRepaint(); | |||
} | |||
} | |||
// Size related methods | |||
// TODO might not be necessary to override but following the pattern from | |||
// AbstractComponentContainer | |||
@Override | |||
public void setHeight(float height, int unit) { | |||
super.setHeight(height, unit); | |||
requestContentRepaint(); | |||
} | |||
@Override | |||
public void setWidth(float height, int unit) { | |||
super.setWidth(height, unit); | |||
requestContentRepaint(); | |||
} | |||
// ComponentContainer methods | |||
private class ComponentIterator implements Iterator<Component>, | |||
Serializable { | |||
boolean first = getContent() != null; | |||
public boolean hasNext() { | |||
return first; | |||
} | |||
public Component next() { | |||
first = false; | |||
return getContent(); | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
} | |||
public Iterator<Component> getComponentIterator() { | |||
return new ComponentIterator(); | |||
} | |||
public int getComponentCount() { | |||
return (null != getContent()) ? 1 : 0; | |||
} | |||
public void requestRepaintAll() { | |||
requestRepaint(); | |||
requestContentRepaint(); | |||
} | |||
/** | |||
* Fires the component attached event. This should be called by the | |||
* addComponent methods after the component have been added to this | |||
* container. | |||
* | |||
* @param component | |||
* the component that has been added to this container. | |||
*/ | |||
protected void fireComponentAttachEvent(Component component) { | |||
fireEvent(new ComponentAttachEvent(this, component)); | |||
} | |||
// TODO remove these methods when ComponentContainer interface is cleaned up | |||
public void addComponent(Component c) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
public void removeComponent(Component c) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
public void removeAllComponents() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
public void replaceComponent(Component oldComponent, Component newComponent) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
public void moveComponentsFrom(ComponentContainer source) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
private static final Method COMPONENT_ATTACHED_METHOD; | |||
static { | |||
try { | |||
COMPONENT_ATTACHED_METHOD = ComponentAttachListener.class | |||
.getDeclaredMethod("componentAttachedToContainer", | |||
new Class[] { ComponentAttachEvent.class }); | |||
} catch (final java.lang.NoSuchMethodException e) { | |||
// This should never happen | |||
throw new java.lang.RuntimeException( | |||
"Internal error finding methods in CustomField"); | |||
} | |||
} | |||
public void addListener(ComponentAttachListener listener) { | |||
addListener(ComponentContainer.ComponentAttachEvent.class, listener, | |||
COMPONENT_ATTACHED_METHOD); | |||
} | |||
public void removeListener(ComponentAttachListener listener) { | |||
removeListener(ComponentContainer.ComponentAttachEvent.class, listener, | |||
COMPONENT_ATTACHED_METHOD); | |||
} | |||
public void addListener(ComponentDetachListener listener) { | |||
// content never detached | |||
} | |||
public void removeListener(ComponentDetachListener listener) { | |||
// content never detached | |||
} | |||
} |
@@ -48,7 +48,7 @@ import com.vaadin.terminal.gwt.client.ui.VPopupCalendar; | |||
*/ | |||
@SuppressWarnings("serial") | |||
@ClientWidget(VPopupCalendar.class) | |||
public class DateField extends AbstractField implements | |||
public class DateField extends AbstractField<Date> implements | |||
FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { | |||
/* Private members */ | |||
@@ -228,7 +228,7 @@ public class DateField extends AbstractField implements | |||
// Gets the calendar | |||
final Calendar calendar = getCalendar(); | |||
final Date currentDate = (Date) getValue(); | |||
final Date currentDate = getValue(); | |||
for (int r = resolution; r <= largestModifiable; r++) { | |||
switch (r) { | |||
@@ -298,10 +298,10 @@ public class DateField extends AbstractField implements | |||
|| variables.containsKey("min") | |||
|| variables.containsKey("sec") | |||
|| variables.containsKey("msec") || variables | |||
.containsKey("dateString"))) { | |||
.containsKey("dateString"))) { | |||
// Old and new dates | |||
final Date oldDate = (Date) getValue(); | |||
final Date oldDate = getValue(); | |||
Date newDate = null; | |||
// this enables analyzing invalid input on the server | |||
@@ -469,7 +469,7 @@ public class DateField extends AbstractField implements | |||
* the default documentation from implemented interface. | |||
*/ | |||
@Override | |||
public Class<?> getType() { | |||
public Class<Date> getType() { | |||
return Date.class; | |||
} | |||
@@ -479,7 +479,7 @@ public class DateField extends AbstractField implements | |||
* @see com.vaadin.ui.AbstractField#setValue(java.lang.Object, boolean) | |||
*/ | |||
@Override | |||
protected void setValue(Object newValue, boolean repaintIsNotNeeded) | |||
protected void setValue(Date newValue, boolean repaintIsNotNeeded) | |||
throws Property.ReadOnlyException, Property.ConversionException { | |||
/* | |||
@@ -544,7 +544,7 @@ public class DateField extends AbstractField implements | |||
Form f = (Form) parenOfDateField; | |||
Collection<?> visibleItemProperties = f.getItemPropertyIds(); | |||
for (Object fieldId : visibleItemProperties) { | |||
Field field = f.getField(fieldId); | |||
Field<?> field = f.getField(fieldId); | |||
if (field == this) { | |||
/* | |||
* this datefield is logically in a form. Do the same | |||
@@ -564,24 +564,8 @@ public class DateField extends AbstractField implements | |||
} | |||
} | |||
/** | |||
* Sets the DateField datasource. Datasource type must assignable to Date. | |||
* | |||
* @see com.vaadin.data.Property.Viewer#setPropertyDataSource(Property) | |||
*/ | |||
@Override | |||
public void setPropertyDataSource(Property newDataSource) { | |||
if (newDataSource == null | |||
|| Date.class.isAssignableFrom(newDataSource.getType())) { | |||
super.setPropertyDataSource(newDataSource); | |||
} else { | |||
throw new IllegalArgumentException( | |||
"DateField only supports Date properties"); | |||
} | |||
} | |||
@Override | |||
protected void setInternalValue(Object newValue) { | |||
protected void setInternalValue(Date newValue) { | |||
// Also set the internal dateString | |||
if (newValue != null) { | |||
dateString = newValue.toString(); | |||
@@ -642,7 +626,7 @@ public class DateField extends AbstractField implements | |||
final Calendar newCal = (Calendar) calendar.clone(); | |||
// Assigns the current time tom calendar. | |||
final Date currentDate = (Date) getValue(); | |||
final Date currentDate = getValue(); | |||
if (currentDate != null) { | |||
newCal.setTime(currentDate); | |||
} | |||
@@ -752,18 +736,13 @@ public class DateField extends AbstractField implements | |||
} | |||
/** | |||
* Tests the current value against registered validators if the field is not | |||
* empty. Note that DateField is considered empty (value == null) and | |||
* Validates the current value against registered validators if the field is | |||
* not empty. Note that DateField is considered empty (value == null) and | |||
* invalid if it contains text typed in by the user that couldn't be parsed | |||
* into a Date value. | |||
* | |||
* @see com.vaadin.ui.AbstractField#isValid() | |||
* @see com.vaadin.ui.AbstractField#validate() | |||
*/ | |||
@Override | |||
public boolean isValid() { | |||
return uiHasValidDateString && super.isValid(); | |||
} | |||
@Override | |||
public void validate() throws InvalidValueException { | |||
/* |
@@ -35,19 +35,20 @@ public class DefaultFieldFactory implements FormFieldFactory, TableFieldFactory | |||
protected DefaultFieldFactory() { | |||
} | |||
public Field createField(Item item, Object propertyId, Component uiContext) { | |||
public Field<?> createField(Item item, Object propertyId, | |||
Component uiContext) { | |||
Class<?> type = item.getItemProperty(propertyId).getType(); | |||
Field field = createFieldByPropertyType(type); | |||
Field<?> field = createFieldByPropertyType(type); | |||
field.setCaption(createCaptionByPropertyId(propertyId)); | |||
return field; | |||
} | |||
public Field createField(Container container, Object itemId, | |||
public Field<?> createField(Container container, Object itemId, | |||
Object propertyId, Component uiContext) { | |||
Property containerProperty = container.getContainerProperty(itemId, | |||
Property<?> containerProperty = container.getContainerProperty(itemId, | |||
propertyId); | |||
Class<?> type = containerProperty.getType(); | |||
Field field = createFieldByPropertyType(type); | |||
Field<?> field = createFieldByPropertyType(type); | |||
field.setCaption(createCaptionByPropertyId(propertyId)); | |||
return field; | |||
} | |||
@@ -110,7 +111,7 @@ public class DefaultFieldFactory implements FormFieldFactory, TableFieldFactory | |||
* the type of the property | |||
* @return the most suitable generic {@link Field} for given type | |||
*/ | |||
public static Field createFieldByPropertyType(Class<?> type) { | |||
public static Field<?> createFieldByPropertyType(Class<?> type) { | |||
// Null typed properties can not be edited | |||
if (type == null) { | |||
return null; |
@@ -9,29 +9,18 @@ import com.vaadin.data.Property; | |||
import com.vaadin.ui.Component.Focusable; | |||
/** | |||
* @author IT Mill Ltd. | |||
* TODO document | |||
* | |||
* @param T | |||
* the type of values in the field, which might not be the same type | |||
* as that of the data source if converters are used | |||
* | |||
* @author IT Mill Ltd. | |||
*/ | |||
public interface Field extends Component, BufferedValidatable, Property, | |||
public interface Field<T> extends Component, BufferedValidatable, Property<T>, | |||
Property.ValueChangeNotifier, Property.ValueChangeListener, | |||
Property.Editor, Focusable { | |||
/** | |||
* Sets the Caption. | |||
* | |||
* @param caption | |||
*/ | |||
void setCaption(String caption); | |||
String getDescription(); | |||
/** | |||
* Sets the Description. | |||
* | |||
* @param caption | |||
*/ | |||
void setDescription(String caption); | |||
/** | |||
* Is this field required. | |||
* | |||
@@ -80,7 +69,7 @@ public interface Field extends Component, BufferedValidatable, Property, | |||
* @since 3.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class ValueChangeEvent extends Component.Event implements | |||
public static class ValueChangeEvent extends Component.Event implements | |||
Property.ValueChangeEvent { | |||
/** |
@@ -30,7 +30,7 @@ public interface FieldFactory extends FormFieldFactory, TableFieldFactory { | |||
* @return Field the field suitable for editing the specified data. | |||
* | |||
*/ | |||
Field createField(Class<?> type, Component uiContext); | |||
Field<?> createField(Class<?> type, Component uiContext); | |||
/** | |||
* Creates a field based on the property datasource. | |||
@@ -41,6 +41,6 @@ public interface FieldFactory extends FormFieldFactory, TableFieldFactory { | |||
* the component where the field is presented. | |||
* @return Field the field suitable for editing the specified data. | |||
*/ | |||
Field createField(Property property, Component uiContext); | |||
Field<?> createField(Property property, Component uiContext); | |||
} |
@@ -61,8 +61,8 @@ import com.vaadin.terminal.gwt.client.ui.VForm; | |||
*/ | |||
@SuppressWarnings("serial") | |||
@ClientWidget(VForm.class) | |||
public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
Validatable, Action.Notifier { | |||
public class Form extends AbstractField<Object> implements Item.Editor, | |||
Buffered, Item, Validatable, Action.Notifier { | |||
private Object propertyValue; | |||
@@ -99,12 +99,12 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
/** | |||
* Mapping from propertyName to corresponding field. | |||
*/ | |||
private final HashMap<Object, Field> fields = new HashMap<Object, Field>(); | |||
private final HashMap<Object, Field<?>> fields = new HashMap<Object, Field<?>>(); | |||
/** | |||
* Form may act as an Item, its own properties are stored here. | |||
*/ | |||
private final HashMap<Object, Property> ownProperties = new HashMap<Object, Property>(); | |||
private final HashMap<Object, Property<?>> ownProperties = new HashMap<Object, Property<?>>(); | |||
/** | |||
* Field factory for this form. | |||
@@ -242,7 +242,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
field.getCaption()); | |||
} | |||
break; | |||
} else if (f instanceof Field && !((Field) f).isValid()) { | |||
} else if (f instanceof Field && !((Field<?>) f).isValid()) { | |||
// Something is wrong with the field, but no proper | |||
// error is given. Generate one. | |||
validationError = new Validator.InvalidValueException( | |||
@@ -321,7 +321,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
// Try to commit all | |||
for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { | |||
try { | |||
final Field f = (fields.get(i.next())); | |||
final Field<?> f = (fields.get(i.next())); | |||
// Commit only non-readonly fields. | |||
if (!f.isReadOnly()) { | |||
f.commit(); | |||
@@ -408,7 +408,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
@Override | |||
public boolean isModified() { | |||
for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { | |||
final Field f = fields.get(i.next()); | |||
final Field<?> f = fields.get(i.next()); | |||
if (f != null && f.isModified()) { | |||
return true; | |||
} | |||
@@ -485,7 +485,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
ownProperties.put(id, property); | |||
// Gets suitable field | |||
final Field field = fieldFactory.createField(this, id, this); | |||
final Field<?> field = fieldFactory.createField(this, id, this); | |||
if (field == null) { | |||
return false; | |||
} | |||
@@ -516,7 +516,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
* @param field | |||
* the field which should be added to the form. | |||
*/ | |||
public void addField(Object propertyId, Field field) { | |||
public void addField(Object propertyId, Field<?> field) { | |||
registerField(propertyId, field); | |||
attachField(propertyId, field); | |||
requestRepaint(); | |||
@@ -536,7 +536,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
* @param field | |||
* the Field that should be registered | |||
*/ | |||
private void registerField(Object propertyId, Field field) { | |||
private void registerField(Object propertyId, Field<?> field) { | |||
if (propertyId == null || field == null) { | |||
return; | |||
} | |||
@@ -599,13 +599,13 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
* | |||
* @see com.vaadin.data.Item#getItemProperty(Object) | |||
*/ | |||
public Property getItemProperty(Object id) { | |||
final Field field = fields.get(id); | |||
public Property<?> getItemProperty(Object id) { | |||
final Field<?> field = fields.get(id); | |||
if (field == null) { | |||
// field does not exist or it is not (yet) created for this property | |||
return ownProperties.get(id); | |||
} | |||
final Property property = field.getPropertyDataSource(); | |||
final Property<?> property = field.getPropertyDataSource(); | |||
if (property != null) { | |||
return property; | |||
@@ -620,7 +620,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
* @param propertyId | |||
* the id of the property. | |||
*/ | |||
public Field getField(Object propertyId) { | |||
public Field<?> getField(Object propertyId) { | |||
return fields.get(propertyId); | |||
} | |||
@@ -637,7 +637,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
public boolean removeItemProperty(Object id) { | |||
ownProperties.remove(id); | |||
final Field field = fields.get(id); | |||
final Field<?> field = fields.get(id); | |||
if (field != null) { | |||
propertyIds.remove(id); | |||
@@ -750,9 +750,9 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
// Adds all the properties to this form | |||
for (final Iterator<?> i = propertyIds.iterator(); i.hasNext();) { | |||
final Object id = i.next(); | |||
final Property property = itemDatasource.getItemProperty(id); | |||
final Property<?> property = itemDatasource.getItemProperty(id); | |||
if (id != null && property != null) { | |||
final Field f = fieldFactory.createField(itemDatasource, id, | |||
final Field<?> f = fieldFactory.createField(itemDatasource, id, | |||
this); | |||
if (f != null) { | |||
bindPropertyToField(id, property, f); | |||
@@ -828,7 +828,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
if (layout != null) { | |||
final Object[] properties = propertyIds.toArray(); | |||
for (int i = 0; i < properties.length; i++) { | |||
Field f = getField(properties[i]); | |||
Field<?> f = getField(properties[i]); | |||
detachField(f); | |||
if (newLayout instanceof CustomLayout) { | |||
((CustomLayout) newLayout).addComponent(f, | |||
@@ -875,7 +875,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
} | |||
// Gets the old field | |||
final Field oldField = fields.get(propertyId); | |||
final Field<?> oldField = fields.get(propertyId); | |||
if (oldField == null) { | |||
throw new IllegalArgumentException("Field with given propertyid '" | |||
+ propertyId.toString() + "' can not be found."); | |||
@@ -952,7 +952,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
} | |||
// Sets the property data source | |||
final Property property = oldField.getPropertyDataSource(); | |||
final Property<?> property = oldField.getPropertyDataSource(); | |||
oldField.setPropertyDataSource(null); | |||
newField.setPropertyDataSource(property); | |||
@@ -994,21 +994,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
} | |||
/** | |||
* Tests the current value of the object against all registered validators | |||
* | |||
* @see com.vaadin.data.Validatable#isValid() | |||
*/ | |||
@Override | |||
public boolean isValid() { | |||
boolean valid = true; | |||
for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { | |||
valid &= (fields.get(i.next())).isValid(); | |||
} | |||
return valid && super.isValid(); | |||
} | |||
/** | |||
* Checks the validity of the validatable. | |||
* Checks the validity of the Form and all of its fields. | |||
* | |||
* @see com.vaadin.data.Validatable#validate() | |||
*/ | |||
@@ -1155,11 +1141,11 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
* | |||
* @return the Field. | |||
*/ | |||
private Field getFirstFocusableField() { | |||
private Field<?> getFirstFocusableField() { | |||
if (getItemPropertyIds() != null) { | |||
for (Object id : getItemPropertyIds()) { | |||
if (id != null) { | |||
Field field = getField(id); | |||
Field<?> field = getField(id); | |||
if (field.isEnabled() && !field.isReadOnly()) { | |||
return field; | |||
} | |||
@@ -1248,7 +1234,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
*/ | |||
@Override | |||
public void focus() { | |||
final Field f = getFirstFocusableField(); | |||
final Field<?> f = getFirstFocusableField(); | |||
if (f != null) { | |||
f.focus(); | |||
} | |||
@@ -1274,8 +1260,8 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
@Override | |||
public void setImmediate(boolean immediate) { | |||
super.setImmediate(immediate); | |||
for (Iterator<Field> i = fields.values().iterator(); i.hasNext();) { | |||
Field f = i.next(); | |||
for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) { | |||
Field<?> f = i.next(); | |||
if (f instanceof AbstractComponent) { | |||
((AbstractComponent) f).setImmediate(immediate); | |||
} | |||
@@ -1286,10 +1272,10 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item, | |||
@Override | |||
protected boolean isEmpty() { | |||
for (Iterator<Field> i = fields.values().iterator(); i.hasNext();) { | |||
Field f = i.next(); | |||
for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) { | |||
Field<?> f = i.next(); | |||
if (f instanceof AbstractField) { | |||
if (!((AbstractField) f).isEmpty()) { | |||
if (!((AbstractField<?>) f).isEmpty()) { | |||
return false; | |||
} | |||
} |
@@ -37,5 +37,5 @@ public interface FormFieldFactory extends Serializable { | |||
* creating it. | |||
* @return Field the field suitable for editing the specified data. | |||
*/ | |||
Field createField(Item item, Object propertyId, Component uiContext); | |||
Field<?> createField(Item item, Object propertyId, Component uiContext); | |||
} |
@@ -40,6 +40,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; | |||
*/ | |||
@SuppressWarnings("serial") | |||
@ClientWidget(value = VLabel.class, loadStyle = LoadStyle.EAGER) | |||
// TODO generics for interface Property | |||
public class Label extends AbstractComponent implements Property, | |||
Property.Viewer, Property.ValueChangeListener, | |||
Property.ValueChangeNotifier, Comparable<Object> { | |||
@@ -194,24 +195,24 @@ public class Label extends AbstractComponent implements Property, | |||
target.addAttribute("mode", CONTENT_MODE_NAME[contentMode]); | |||
} | |||
if (contentMode == CONTENT_TEXT) { | |||
target.addText(toString()); | |||
target.addText(getStringValue()); | |||
} else if (contentMode == CONTENT_UIDL) { | |||
target.addUIDL(toString()); | |||
target.addUIDL(getStringValue()); | |||
} else if (contentMode == CONTENT_XHTML) { | |||
target.startTag("data"); | |||
target.addXMLSection("div", toString(), | |||
target.addXMLSection("div", getStringValue(), | |||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); | |||
target.endTag("data"); | |||
} else if (contentMode == CONTENT_PREFORMATTED) { | |||
target.startTag("pre"); | |||
target.addText(toString()); | |||
target.addText(getStringValue()); | |||
target.endTag("pre"); | |||
} else if (contentMode == CONTENT_XML) { | |||
target.addXMLSection("data", toString(), null); | |||
target.addXMLSection("data", getStringValue(), null); | |||
} else if (contentMode == CONTENT_RAW) { | |||
target.startTag("data"); | |||
target.addAttribute("escape", false); | |||
target.addText(toString()); | |||
target.addText(getStringValue()); | |||
target.endTag("data"); | |||
} | |||
@@ -246,13 +247,33 @@ public class Label extends AbstractComponent implements Property, | |||
/** | |||
* @see java.lang.Object#toString() | |||
* @deprecated use the data source value or {@link #getStringValue()} | |||
* instead | |||
*/ | |||
@Deprecated | |||
@Override | |||
public String toString() { | |||
throw new UnsupportedOperationException( | |||
"Use Property.getValue() instead of Label.toString()"); | |||
} | |||
/** | |||
* Returns the value of the <code>Property</code> in human readable textual | |||
* format. | |||
* | |||
* This method exists to help migration from previous Vaadin versions by | |||
* providing a simple replacement for {@link #toString()}. However, it is | |||
* normally better to use the value of the label directly. | |||
* | |||
* @return String representation of the value stored in the Property | |||
* @since 7.0 | |||
*/ | |||
public String getStringValue() { | |||
if (dataSource == null) { | |||
throw new IllegalStateException(DATASOURCE_MUST_BE_SET); | |||
} | |||
return dataSource.toString(); | |||
Object value = dataSource.getValue(); | |||
return (null != value) ? value.toString() : null; | |||
} | |||
/** | |||
@@ -397,7 +418,7 @@ public class Label extends AbstractComponent implements Property, | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
public class ValueChangeEvent extends Component.Event implements | |||
public static class ValueChangeEvent extends Component.Event implements | |||
Property.ValueChangeEvent { | |||
/** | |||
@@ -489,17 +510,19 @@ public class Label extends AbstractComponent implements Property, | |||
if (contentMode == CONTENT_XML || contentMode == CONTENT_UIDL | |||
|| contentMode == CONTENT_XHTML) { | |||
thisValue = stripTags(toString()); | |||
thisValue = stripTags(getStringValue()); | |||
} else { | |||
thisValue = toString(); | |||
thisValue = getStringValue(); | |||
} | |||
if (other instanceof Label | |||
&& (((Label) other).getContentMode() == CONTENT_XML | |||
|| ((Label) other).getContentMode() == CONTENT_UIDL || ((Label) other) | |||
.getContentMode() == CONTENT_XHTML)) { | |||
otherValue = stripTags(other.toString()); | |||
otherValue = stripTags(((Label) other).getStringValue()); | |||
} else { | |||
// TODO not a good idea - and might assume that Field.toString() | |||
// returns a string representation of the value | |||
otherValue = other.toString(); | |||
} | |||
@@ -21,8 +21,4 @@ public class NativeButton extends Button { | |||
super(caption, listener); | |||
} | |||
public NativeButton(String caption, Object target, String methodName) { | |||
super(caption, target, methodName); | |||
} | |||
} |
@@ -26,7 +26,7 @@ import com.vaadin.terminal.gwt.client.ui.VProgressIndicator; | |||
*/ | |||
@SuppressWarnings("serial") | |||
@ClientWidget(VProgressIndicator.class) | |||
public class ProgressIndicator extends AbstractField implements Property, | |||
public class ProgressIndicator extends AbstractField<Number> implements | |||
Property.Viewer, Property.ValueChangeListener { | |||
/** | |||
@@ -125,11 +125,12 @@ public class ProgressIndicator extends AbstractField implements Property, | |||
* @see com.vaadin.ui.AbstractField#getValue() | |||
*/ | |||
@Override | |||
public Object getValue() { | |||
public Number getValue() { | |||
if (dataSource == null) { | |||
throw new IllegalStateException("Datasource must be set"); | |||
} | |||
return dataSource.getValue(); | |||
// TODO conversions to eliminate cast | |||
return (Number) dataSource.getValue(); | |||
} | |||
/** | |||
@@ -138,7 +139,7 @@ public class ProgressIndicator extends AbstractField implements Property, | |||
* | |||
* @param newValue | |||
* the New value of the ProgressIndicator. | |||
* @see com.vaadin.ui.AbstractField#setValue(java.lang.Object) | |||
* @see com.vaadin.ui.AbstractField#setValue() | |||
*/ | |||
@Override | |||
public void setValue(Object newValue) { | |||
@@ -150,20 +151,20 @@ public class ProgressIndicator extends AbstractField implements Property, | |||
/** | |||
* @see com.vaadin.ui.AbstractField#toString() | |||
* @deprecated use the data source value instead of toString() | |||
*/ | |||
@Deprecated | |||
@Override | |||
public String toString() { | |||
if (dataSource == null) { | |||
throw new IllegalStateException("Datasource must be set"); | |||
} | |||
return dataSource.toString(); | |||
throw new UnsupportedOperationException( | |||
"Use Property.getValue() instead of ProgressIndicator.toString()"); | |||
} | |||
/** | |||
* @see com.vaadin.ui.AbstractField#getType() | |||
*/ | |||
@Override | |||
public Class<?> getType() { | |||
public Class<? extends Number> getType() { | |||
if (dataSource == null) { | |||
throw new IllegalStateException("Datasource must be set"); | |||
} |
@@ -21,7 +21,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; | |||
* into length of field. | |||
*/ | |||
@ClientWidget(value = VRichTextArea.class, loadStyle = LoadStyle.LAZY) | |||
public class RichTextArea extends AbstractField { | |||
public class RichTextArea extends AbstractField<String> { | |||
/** | |||
* Value formatter used to format the string contents. | |||
@@ -176,8 +176,8 @@ public class RichTextArea extends AbstractField { | |||
} | |||
@Override | |||
public Object getValue() { | |||
Object v = super.getValue(); | |||
public String getValue() { | |||
String v = super.getValue(); | |||
if (format == null || v == null) { | |||
return v; | |||
} | |||
@@ -222,7 +222,7 @@ public class RichTextArea extends AbstractField { | |||
} | |||
@Override | |||
public Class getType() { | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
@@ -343,7 +343,7 @@ public class RichTextArea extends AbstractField { | |||
@Override | |||
protected boolean isEmpty() { | |||
return super.isEmpty() || toString().length() == 0; | |||
return super.isEmpty() || getStringValue().length() == 0; | |||
} | |||
} |
@@ -48,7 +48,7 @@ import com.vaadin.terminal.gwt.client.ui.VSlider; | |||
*/ | |||
@SuppressWarnings("serial") | |||
@ClientWidget(VSlider.class) | |||
public class Slider extends AbstractField { | |||
public class Slider extends AbstractField<Number> { | |||
public static final int ORIENTATION_HORIZONTAL = 0; | |||
@@ -408,10 +408,9 @@ public class Slider extends AbstractField { | |||
target.addAttribute("resolution", resolution); | |||
if (resolution > 0) { | |||
target.addVariable(this, "value", | |||
((Double) getValue()).doubleValue()); | |||
target.addVariable(this, "value", getValue().doubleValue()); | |||
} else { | |||
target.addVariable(this, "value", ((Double) getValue()).intValue()); | |||
target.addVariable(this, "value", getValue().intValue()); | |||
} | |||
if (orientation == ORIENTATION_VERTICAL) { | |||
@@ -493,7 +492,7 @@ public class Slider extends AbstractField { | |||
} | |||
@Override | |||
public Class getType() { | |||
public Class<Double> getType() { | |||
return Double.class; | |||
} | |||
@@ -20,11 +20,13 @@ import java.util.StringTokenizer; | |||
import java.util.logging.Level; | |||
import java.util.logging.Logger; | |||
import com.vaadin.Application; | |||
import com.vaadin.data.Container; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.Property; | |||
import com.vaadin.data.util.ContainerOrderedWrapper; | |||
import com.vaadin.data.util.IndexedContainer; | |||
import com.vaadin.data.util.converter.Converter; | |||
import com.vaadin.event.Action; | |||
import com.vaadin.event.Action.Handler; | |||
import com.vaadin.event.DataBoundTransferable; | |||
@@ -70,7 +72,7 @@ import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers; | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
@SuppressWarnings({ "serial", "deprecation" }) | |||
@SuppressWarnings({ "deprecation" }) | |||
@ClientWidget(VScrollTable.class) | |||
public class Table extends AbstractSelect implements Action.Container, | |||
Container.Ordered, Container.Sortable, ItemClickSource, | |||
@@ -309,7 +311,7 @@ public class Table extends AbstractSelect implements Action.Container, | |||
* Set of properties listened - the list is kept to release the listeners | |||
* later. | |||
*/ | |||
private HashSet<Property> listenedProperties = null; | |||
private HashSet<Property<?>> listenedProperties = null; | |||
/** | |||
* Set of visible components - the is used for needsRepaint calculation. | |||
@@ -404,10 +406,12 @@ public class Table extends AbstractSelect implements Action.Container, | |||
private RowGenerator rowGenerator = null; | |||
private final Map<Field, Property> associatedProperties = new HashMap<Field, Property>(); | |||
private final Map<Field<?>, Property<?>> associatedProperties = new HashMap<Field<?>, Property<?>>(); | |||
private boolean painted = false; | |||
private HashMap<Object, Converter> propertyValueConverters = new HashMap<Object, Converter>(); | |||
/* Table constructors */ | |||
/** | |||
@@ -1718,13 +1722,13 @@ public class Table extends AbstractSelect implements Action.Container, | |||
final Object[] colids = getVisibleColumns(); | |||
final int cols = colids.length; | |||
HashSet<Property> oldListenedProperties = listenedProperties; | |||
HashSet<Property<?>> oldListenedProperties = listenedProperties; | |||
HashSet<Component> oldVisibleComponents = visibleComponents; | |||
if (replaceListeners) { | |||
// initialize the listener collections, this should only be done if | |||
// the entire cache is refreshed (through refreshRenderedCells) | |||
listenedProperties = new HashSet<Property>(); | |||
listenedProperties = new HashSet<Property<?>>(); | |||
visibleComponents = new HashSet<Component>(); | |||
} | |||
@@ -1784,7 +1788,7 @@ public class Table extends AbstractSelect implements Action.Container, | |||
if (isColumnCollapsed(colids[j])) { | |||
continue; | |||
} | |||
Property p = null; | |||
Property<?> p = null; | |||
Object value = ""; | |||
boolean isGeneratedRow = generatedRow != null; | |||
boolean isGeneratedColumn = columnGenerators | |||
@@ -1904,8 +1908,8 @@ public class Table extends AbstractSelect implements Action.Container, | |||
visibleComponents.add(component); | |||
} | |||
private void listenProperty(Property p, | |||
HashSet<Property> oldListenedProperties) { | |||
private void listenProperty(Property<?> p, | |||
HashSet<Property<?>> oldListenedProperties) { | |||
if (p instanceof Property.ValueChangeNotifier) { | |||
if (oldListenedProperties == null | |||
|| !oldListenedProperties.contains(p)) { | |||
@@ -1945,7 +1949,7 @@ public class Table extends AbstractSelect implements Action.Container, | |||
visibleComponents.remove(cellVal); | |||
unregisterComponent((Component) cellVal); | |||
} else { | |||
Property p = getContainerProperty( | |||
Property<?> p = getContainerProperty( | |||
pageBuffer[CELL_ITEMID][i + ix], colids[c]); | |||
if (p instanceof ValueChangeNotifier | |||
&& listenedProperties.contains(p)) { | |||
@@ -1970,7 +1974,7 @@ public class Table extends AbstractSelect implements Action.Container, | |||
* set of components that where attached in last render | |||
*/ | |||
private void unregisterPropertiesAndComponents( | |||
HashSet<Property> oldListenedProperties, | |||
HashSet<Property<?>> oldListenedProperties, | |||
HashSet<Component> oldVisibleComponents) { | |||
if (oldVisibleComponents != null) { | |||
for (final Iterator<Component> i = oldVisibleComponents.iterator(); i | |||
@@ -1983,8 +1987,8 @@ public class Table extends AbstractSelect implements Action.Container, | |||
} | |||
if (oldListenedProperties != null) { | |||
for (final Iterator<Property> i = oldListenedProperties.iterator(); i | |||
.hasNext();) { | |||
for (final Iterator<Property<?>> i = oldListenedProperties | |||
.iterator(); i.hasNext();) { | |||
Property.ValueChangeNotifier o = (ValueChangeNotifier) i.next(); | |||
if (!listenedProperties.contains(o)) { | |||
o.removeListener(this); | |||
@@ -2017,8 +2021,8 @@ public class Table extends AbstractSelect implements Action.Container, | |||
* fields in memory. | |||
*/ | |||
if (component instanceof Field) { | |||
Field field = (Field) component; | |||
Property associatedProperty = associatedProperties | |||
Field<?> field = (Field<?>) component; | |||
Property<?> associatedProperty = associatedProperties | |||
.remove(component); | |||
if (associatedProperty != null | |||
&& field.getPropertyDataSource() == associatedProperty) { | |||
@@ -3399,8 +3403,8 @@ public class Table extends AbstractSelect implements Action.Container, | |||
protected Object getPropertyValue(Object rowId, Object colId, | |||
Property property) { | |||
if (isEditable() && fieldFactory != null) { | |||
final Field f = fieldFactory.createField(getContainerDataSource(), | |||
rowId, colId, this); | |||
final Field<?> f = fieldFactory.createField( | |||
getContainerDataSource(), rowId, colId, this); | |||
if (f != null) { | |||
// Remember that we have made this association so we can remove | |||
// it when the component is removed | |||
@@ -3454,11 +3458,25 @@ public class Table extends AbstractSelect implements Action.Container, | |||
* @since 3.1 | |||
*/ | |||
protected String formatPropertyValue(Object rowId, Object colId, | |||
Property property) { | |||
Property<?> property) { | |||
if (property == null) { | |||
return ""; | |||
} | |||
return property.toString(); | |||
Converter<Object, String> converter = null; | |||
if (hasConverter(colId)) { | |||
converter = getConverter(colId); | |||
} else { | |||
// FIXME: Use thread local | |||
converter = (Converter<Object, String>) Application | |||
.getConverterFactory().createConverter(property.getType(), | |||
String.class); | |||
} | |||
Object value = property.getValue(); | |||
if (converter != null) { | |||
return converter.convertFromSourceToTarget(value, getLocale()); | |||
} | |||
return (null != value) ? value.toString() : ""; | |||
} | |||
/* Action container */ | |||
@@ -5141,4 +5159,35 @@ public class Table extends AbstractSelect implements Action.Container, | |||
public RowGenerator getRowGenerator() { | |||
return rowGenerator; | |||
} | |||
// FIXME: Javadoc | |||
public void setConverter(Object propertyId, Converter<?, String> converter) { | |||
if (!getContainerPropertyIds().contains(propertyId)) { | |||
throw new IllegalArgumentException("PropertyId " + propertyId | |||
+ " must be in the container"); | |||
} | |||
// FIXME: This check should be here but primitive types like Boolean | |||
// formatter for boolean property must be handled | |||
// if (!converter.getSourceType().isAssignableFrom(getType(propertyId))) | |||
// { | |||
// throw new IllegalArgumentException("Property type (" | |||
// + getType(propertyId) | |||
// + ") must match converter source type (" | |||
// + converter.getSourceType() + ")"); | |||
// } | |||
propertyValueConverters.put(propertyId, converter); | |||
refreshRowCache(); | |||
} | |||
// FIXME: Javadoc | |||
protected boolean hasConverter(Object propertyId) { | |||
return propertyValueConverters.containsKey(propertyId); | |||
} | |||
// FIXME: Javadoc | |||
public Converter<Object, String> getConverter(Object propertyId) { | |||
return propertyValueConverters.get(propertyId); | |||
} | |||
} |
@@ -39,7 +39,7 @@ public interface TableFieldFactory extends Serializable { | |||
* @return A field suitable for editing the specified data or null if the | |||
* property should not be editable. | |||
*/ | |||
Field createField(Container container, Object itemId, Object propertyId, | |||
Field<?> createField(Container container, Object itemId, Object propertyId, | |||
Component uiContext); | |||
} |
@@ -12,11 +12,6 @@ import java.util.Map; | |||
import junit.framework.Assert; | |||
import junit.framework.TestCase; | |||
import com.vaadin.data.util.BeanItem; | |||
import com.vaadin.data.util.MethodProperty; | |||
import com.vaadin.data.util.MethodPropertyDescriptor; | |||
import com.vaadin.data.util.VaadinPropertyDescriptor; | |||
/** | |||
* Test BeanItem specific features. | |||
* | |||
@@ -322,7 +317,7 @@ public class BeanItemTest extends TestCase { | |||
MyClass.class.getDeclaredMethod("getName"), | |||
MyClass.class.getDeclaredMethod("setName", String.class)); | |||
BeanItem<MyClass> item = new BeanItem(new MyClass("bean1")); | |||
BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); | |||
Assert.assertEquals(6, item.getItemPropertyIds().size()); | |||
Assert.assertEquals(null, item.getItemProperty("myname")); |
@@ -10,8 +10,6 @@ import java.io.Serializable; | |||
import junit.framework.Assert; | |||
import junit.framework.TestCase; | |||
import com.vaadin.data.util.NestedMethodProperty; | |||
public class NestedMethodPropertyTest extends TestCase { | |||
public static class Address implements Serializable { | |||
@@ -126,34 +124,34 @@ public class NestedMethodPropertyTest extends TestCase { | |||
} | |||
public void testSingleLevelNestedSimpleProperty() { | |||
NestedMethodProperty nameProperty = new NestedMethodProperty(vaadin, | |||
"name"); | |||
NestedMethodProperty<String> nameProperty = new NestedMethodProperty<String>( | |||
vaadin, "name"); | |||
Assert.assertEquals(String.class, nameProperty.getType()); | |||
Assert.assertEquals("Vaadin", nameProperty.getValue()); | |||
} | |||
public void testSingleLevelNestedObjectProperty() { | |||
NestedMethodProperty managerProperty = new NestedMethodProperty(vaadin, | |||
"manager"); | |||
NestedMethodProperty<Person> managerProperty = new NestedMethodProperty<Person>( | |||
vaadin, "manager"); | |||
Assert.assertEquals(Person.class, managerProperty.getType()); | |||
Assert.assertEquals(joonas, managerProperty.getValue()); | |||
} | |||
public void testMultiLevelNestedProperty() { | |||
NestedMethodProperty managerNameProperty = new NestedMethodProperty( | |||
NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.name"); | |||
NestedMethodProperty addressProperty = new NestedMethodProperty(vaadin, | |||
"manager.address"); | |||
NestedMethodProperty streetProperty = new NestedMethodProperty(vaadin, | |||
"manager.address.street"); | |||
NestedMethodProperty postalCodePrimitiveProperty = new NestedMethodProperty( | |||
NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( | |||
vaadin, "manager.address"); | |||
NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.address.street"); | |||
NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( | |||
vaadin, "manager.address.postalCodePrimitive"); | |||
NestedMethodProperty postalCodeObjectProperty = new NestedMethodProperty( | |||
NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( | |||
vaadin, "manager.address.postalCodeObject"); | |||
NestedMethodProperty booleanProperty = new NestedMethodProperty(vaadin, | |||
"manager.address.boolean"); | |||
NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( | |||
vaadin, "manager.address.boolean"); | |||
Assert.assertEquals(String.class, managerNameProperty.getType()); | |||
Assert.assertEquals("Joonas", managerNameProperty.getValue()); | |||
@@ -166,25 +164,27 @@ public class NestedMethodPropertyTest extends TestCase { | |||
Assert.assertEquals(Integer.class, | |||
postalCodePrimitiveProperty.getType()); | |||
Assert.assertEquals(20540, postalCodePrimitiveProperty.getValue()); | |||
Assert.assertEquals(Integer.valueOf(20540), | |||
postalCodePrimitiveProperty.getValue()); | |||
Assert.assertEquals(Integer.class, postalCodeObjectProperty.getType()); | |||
Assert.assertEquals(20540, postalCodeObjectProperty.getValue()); | |||
Assert.assertEquals(Integer.valueOf(20540), | |||
postalCodeObjectProperty.getValue()); | |||
Assert.assertEquals(Boolean.class, booleanProperty.getType()); | |||
Assert.assertEquals(true, booleanProperty.getValue()); | |||
Assert.assertEquals(Boolean.TRUE, booleanProperty.getValue()); | |||
} | |||
public void testEmptyPropertyName() { | |||
try { | |||
new NestedMethodProperty(vaadin, ""); | |||
new NestedMethodProperty<Object>(vaadin, ""); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
} | |||
try { | |||
new NestedMethodProperty(vaadin, " "); | |||
new NestedMethodProperty<Object>(vaadin, " "); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
@@ -193,25 +193,25 @@ public class NestedMethodPropertyTest extends TestCase { | |||
public void testInvalidPropertyName() { | |||
try { | |||
new NestedMethodProperty(vaadin, "."); | |||
new NestedMethodProperty<Object>(vaadin, "."); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
} | |||
try { | |||
new NestedMethodProperty(vaadin, ".manager"); | |||
new NestedMethodProperty<Object>(vaadin, ".manager"); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
} | |||
try { | |||
new NestedMethodProperty(vaadin, "manager."); | |||
new NestedMethodProperty<Object>(vaadin, "manager."); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
} | |||
try { | |||
new NestedMethodProperty(vaadin, "manager..name"); | |||
new NestedMethodProperty<Object>(vaadin, "manager..name"); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
@@ -220,21 +220,21 @@ public class NestedMethodPropertyTest extends TestCase { | |||
public void testInvalidNestedPropertyName() { | |||
try { | |||
new NestedMethodProperty(vaadin, "member"); | |||
new NestedMethodProperty<Object>(vaadin, "member"); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
} | |||
try { | |||
new NestedMethodProperty(vaadin, "manager.pet"); | |||
new NestedMethodProperty<Object>(vaadin, "manager.pet"); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
} | |||
try { | |||
new NestedMethodProperty(vaadin, "manager.address.city"); | |||
new NestedMethodProperty<Object>(vaadin, "manager.address.city"); | |||
fail(); | |||
} catch (IllegalArgumentException e) { | |||
// should get exception | |||
@@ -242,10 +242,10 @@ public class NestedMethodPropertyTest extends TestCase { | |||
} | |||
public void testNullNestedProperty() { | |||
NestedMethodProperty managerNameProperty = new NestedMethodProperty( | |||
NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.name"); | |||
NestedMethodProperty streetProperty = new NestedMethodProperty(vaadin, | |||
"manager.address.street"); | |||
NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.address.street"); | |||
joonas.setAddress(null); | |||
try { | |||
@@ -274,15 +274,15 @@ public class NestedMethodPropertyTest extends TestCase { | |||
} | |||
public void testMultiLevelNestedPropertySetValue() { | |||
NestedMethodProperty managerNameProperty = new NestedMethodProperty( | |||
NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.name"); | |||
NestedMethodProperty addressProperty = new NestedMethodProperty(vaadin, | |||
"manager.address"); | |||
NestedMethodProperty streetProperty = new NestedMethodProperty(vaadin, | |||
"manager.address.street"); | |||
NestedMethodProperty postalCodePrimitiveProperty = new NestedMethodProperty( | |||
NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( | |||
vaadin, "manager.address"); | |||
NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.address.street"); | |||
NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( | |||
vaadin, "manager.address.postalCodePrimitive"); | |||
NestedMethodProperty postalCodeObjectProperty = new NestedMethodProperty( | |||
NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( | |||
vaadin, "manager.address.postalCodeObject"); | |||
managerNameProperty.setValue("Joonas L"); | |||
@@ -303,21 +303,22 @@ public class NestedMethodPropertyTest extends TestCase { | |||
} | |||
public void testSerialization() throws IOException, ClassNotFoundException { | |||
NestedMethodProperty streetProperty = new NestedMethodProperty(vaadin, | |||
"manager.address.street"); | |||
NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.address.street"); | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
new ObjectOutputStream(baos).writeObject(streetProperty); | |||
NestedMethodProperty property2 = (NestedMethodProperty) new ObjectInputStream( | |||
@SuppressWarnings("unchecked") | |||
NestedMethodProperty<String> property2 = (NestedMethodProperty<String>) new ObjectInputStream( | |||
new ByteArrayInputStream(baos.toByteArray())).readObject(); | |||
Assert.assertEquals("Ruukinkatu 2-4", property2.getValue()); | |||
} | |||
public void testIsReadOnly() { | |||
NestedMethodProperty streetProperty = new NestedMethodProperty(vaadin, | |||
"manager.address.street"); | |||
NestedMethodProperty booleanProperty = new NestedMethodProperty(vaadin, | |||
"manager.address.boolean"); | |||
NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( | |||
vaadin, "manager.address.street"); | |||
NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( | |||
vaadin, "manager.address.boolean"); | |||
Assert.assertFalse(streetProperty.isReadOnly()); | |||
Assert.assertTrue(booleanProperty.isReadOnly()); |
@@ -4,8 +4,6 @@ import junit.framework.TestCase; | |||
import org.junit.Assert; | |||
import com.vaadin.data.util.ObjectProperty; | |||
public class ObjectPropertyTest extends TestCase { | |||
public static class TestSuperClass { | |||
@@ -70,7 +68,7 @@ public class ObjectPropertyTest extends TestCase { | |||
ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( | |||
super1, TestSuperClass.class); | |||
Assert.assertEquals("super1", prop.getValue().getName()); | |||
prop.setValue("super2"); | |||
prop.setValue(new TestSuperClass("super2")); | |||
Assert.assertEquals("super1", super1.getName()); | |||
Assert.assertEquals("super2", prop.getValue().getName()); | |||
} | |||
@@ -79,7 +77,7 @@ public class ObjectPropertyTest extends TestCase { | |||
ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>( | |||
sub1, TestSubClass.class); | |||
Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); | |||
prop.setValue("sub2"); | |||
prop.setValue(new TestSubClass("sub2")); | |||
Assert.assertEquals("Subclass: sub1", sub1.getName()); | |||
Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); | |||
} | |||
@@ -92,7 +90,7 @@ public class ObjectPropertyTest extends TestCase { | |||
// create correct subclass based on the runtime type of the instance | |||
// given to ObjectProperty constructor, which is a subclass of the type | |||
// parameter | |||
prop.setValue("sub2"); | |||
prop.setValue(new TestSubClass("sub2")); | |||
Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); | |||
} | |||
@@ -11,9 +11,6 @@ import junit.framework.Assert; | |||
import junit.framework.TestCase; | |||
import com.vaadin.data.Property; | |||
import com.vaadin.data.util.MethodPropertyDescriptor; | |||
import com.vaadin.data.util.NestedPropertyDescriptor; | |||
import com.vaadin.data.util.VaadinPropertyDescriptor; | |||
import com.vaadin.data.util.NestedMethodPropertyTest.Person; | |||
public class PropertyDescriptorTest extends TestCase { | |||
@@ -33,11 +30,12 @@ public class PropertyDescriptorTest extends TestCase { | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
new ObjectOutputStream(baos).writeObject(descriptor); | |||
@SuppressWarnings("unchecked") | |||
VaadinPropertyDescriptor<Person> descriptor2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( | |||
new ByteArrayInputStream(baos.toByteArray())).readObject(); | |||
Property property = descriptor2 | |||
.createProperty(new Person("John", null)); | |||
Property<?> property = descriptor2.createProperty(new Person("John", | |||
null)); | |||
Assert.assertEquals("John", property.getValue()); | |||
} | |||
@@ -47,10 +45,11 @@ public class PropertyDescriptorTest extends TestCase { | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
new ObjectOutputStream(baos).writeObject(pd); | |||
@SuppressWarnings("unchecked") | |||
VaadinPropertyDescriptor<Person> pd2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( | |||
new ByteArrayInputStream(baos.toByteArray())).readObject(); | |||
Property property = pd2.createProperty(new Person("John", null)); | |||
Property<?> property = pd2.createProperty(new Person("John", null)); | |||
Assert.assertEquals("John", property.getValue()); | |||
} | |||
} |
@@ -9,8 +9,6 @@ import org.easymock.EasyMock; | |||
import com.vaadin.data.Item.PropertySetChangeEvent; | |||
import com.vaadin.data.Item.PropertySetChangeListener; | |||
import com.vaadin.data.util.ObjectProperty; | |||
import com.vaadin.data.util.PropertysetItem; | |||
public class PropertySetItemTest extends TestCase { | |||
@@ -395,13 +393,13 @@ public class PropertySetItemTest extends TestCase { | |||
item.addItemProperty(ID1, prop1); | |||
Assert.assertEquals(String.valueOf(prop1), item.toString()); | |||
Assert.assertEquals(String.valueOf(prop1.getValue()), item.toString()); | |||
item.addItemProperty(ID2, prop2); | |||
Assert.assertEquals( | |||
String.valueOf(prop1) + " " + String.valueOf(prop2), | |||
item.toString()); | |||
String.valueOf(prop1.getValue()) + " " | |||
+ String.valueOf(prop2.getValue()), item.toString()); | |||
} | |||
} |
@@ -22,9 +22,9 @@ public abstract class AbstractFilterTest<FILTERTYPE extends Filter> extends | |||
} | |||
} | |||
protected static class NullProperty implements Property { | |||
protected static class NullProperty implements Property<String> { | |||
public Object getValue() { | |||
public String getValue() { | |||
return null; | |||
} | |||
@@ -33,7 +33,7 @@ public abstract class AbstractFilterTest<FILTERTYPE extends Filter> extends | |||
throw new ReadOnlyException(); | |||
} | |||
public Class<?> getType() { | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
@@ -5,10 +5,8 @@ import junit.framework.Assert; | |||
import com.vaadin.data.Container.Filter; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.util.BeanItem; | |||
import com.vaadin.data.util.filter.And; | |||
import com.vaadin.data.util.filter.Or; | |||
public class AndOrFilterTest extends AbstractFilterTest { | |||
public class AndOrFilterTest extends AbstractFilterTest<AbstractJunctionFilter> { | |||
protected Item item1 = new BeanItem<Integer>(1); | |||
protected Item item2 = new BeanItem<Integer>(2); |
@@ -14,7 +14,7 @@ import com.vaadin.data.util.filter.Compare.GreaterOrEqual; | |||
import com.vaadin.data.util.filter.Compare.Less; | |||
import com.vaadin.data.util.filter.Compare.LessOrEqual; | |||
public class CompareFilterTest extends AbstractFilterTest { | |||
public class CompareFilterTest extends AbstractFilterTest<Compare> { | |||
protected Item itemNull; | |||
protected Item itemEmpty; |
@@ -6,10 +6,8 @@ import com.vaadin.data.Container.Filter; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.util.ObjectProperty; | |||
import com.vaadin.data.util.PropertysetItem; | |||
import com.vaadin.data.util.filter.And; | |||
import com.vaadin.data.util.filter.IsNull; | |||
public class IsNullFilterTest extends AbstractFilterTest { | |||
public class IsNullFilterTest extends AbstractFilterTest<IsNull> { | |||
public void testIsNull() { | |||
Item item1 = new PropertysetItem(); |
@@ -5,10 +5,8 @@ import junit.framework.Assert; | |||
import com.vaadin.data.Container.Filter; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.util.BeanItem; | |||
import com.vaadin.data.util.filter.And; | |||
import com.vaadin.data.util.filter.Not; | |||
public class NotFilterTest extends AbstractFilterTest { | |||
public class NotFilterTest extends AbstractFilterTest<Not> { | |||
protected Item item1 = new BeanItem<Integer>(1); | |||
protected Item item2 = new BeanItem<Integer>(2); |
@@ -2,9 +2,8 @@ package com.vaadin.data.util.filter; | |||
import junit.framework.Assert; | |||
import com.vaadin.data.util.filter.SimpleStringFilter; | |||
public class SimpleStringFilterTest extends AbstractFilterTest { | |||
public class SimpleStringFilterTest extends | |||
AbstractFilterTest<SimpleStringFilter> { | |||
protected static TestItem<String, String> createTestItem() { | |||
return new TestItem<String, String>("abcde", "TeSt"); |
@@ -1344,7 +1344,7 @@ public class SQLContainerTest { | |||
Statement statement = conn.createStatement(); | |||
statement | |||
.executeUpdate("DELETE FROM people WHERE \"ID\"=" | |||
+ item.getItemProperty("ID")); | |||
+ item.getItemProperty("ID").getValue()); | |||
statement.close(); | |||
return true; | |||
} |
@@ -12,7 +12,7 @@ import com.vaadin.data.util.filter.Between; | |||
public class BetweenTest { | |||
private Item itemWithPropertyValue(Object propertyId, Object value) { | |||
Property property = EasyMock.createMock(Property.class); | |||
Property<?> property = EasyMock.createMock(Property.class); | |||
property.getValue(); | |||
EasyMock.expectLastCall().andReturn(value).anyTimes(); | |||
EasyMock.replay(property); |
@@ -0,0 +1,63 @@ | |||
package com.vaadin.tests.data.bean; | |||
import java.io.Serializable; | |||
@SuppressWarnings("serial") | |||
public class Address implements Serializable { | |||
private String streetAddress = ""; | |||
private Integer postalCode = null; | |||
private String city = ""; | |||
private Country country = null; | |||
public Address() { | |||
} | |||
public Address(String streetAddress, int postalCode, String city, | |||
Country country) { | |||
setStreetAddress(streetAddress); | |||
setPostalCode(postalCode); | |||
setCity(city); | |||
setCountry(country); | |||
} | |||
@Override | |||
public String toString() { | |||
return "Address [streetAddress=" + streetAddress + ", postalCode=" | |||
+ postalCode + ", city=" + city + ", country=" + country + "]"; | |||
} | |||
public String getStreetAddress() { | |||
return streetAddress; | |||
} | |||
public void setStreetAddress(String streetAddress) { | |||
this.streetAddress = streetAddress; | |||
} | |||
public Integer getPostalCode() { | |||
return postalCode; | |||
} | |||
public void setPostalCode(Integer postalCode) { | |||
this.postalCode = postalCode; | |||
} | |||
public String getCity() { | |||
return city; | |||
} | |||
public void setCity(String city) { | |||
this.city = city; | |||
} | |||
public Country getCountry() { | |||
return country; | |||
} | |||
public void setCountry(Country country) { | |||
this.country = country; | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.vaadin.tests.data.bean; | |||
public enum Country { | |||
FINLAND("Finland"), SWEDEN("Sweden"), USA("USA"), RUSSIA("Russia"), NETHERLANDS( | |||
"Netherlands"), SOUTH_AFRICA("South Africa"); | |||
private String name; | |||
private Country(String name) { | |||
this.name = name; | |||
} | |||
@Override | |||
public String toString() { | |||
return name; | |||
} | |||
} |
@@ -0,0 +1,133 @@ | |||
package com.vaadin.tests.data.bean; | |||
import java.math.BigDecimal; | |||
import java.util.Date; | |||
public class Person { | |||
private String firstName; | |||
private String lastName; | |||
private String email; | |||
private int age; | |||
private Sex sex; | |||
private Address address; | |||
private boolean deceased; | |||
private Date birthDate; | |||
private Integer salary; // null if unknown | |||
private Double salaryDouble; // null if unknown | |||
private BigDecimal rent; | |||
public Person() { | |||
} | |||
@Override | |||
public String toString() { | |||
return "Person [firstName=" + firstName + ", lastName=" + lastName | |||
+ ", email=" + email + ", age=" + age + ", sex=" + sex | |||
+ ", address=" + address + ", deceased=" + deceased | |||
+ ", salary=" + salary + ", salaryDouble=" + salaryDouble | |||
+ ", rent=" + rent + "]"; | |||
} | |||
public Person(String firstName, String lastName, String email, int age, | |||
Sex sex, Address address) { | |||
super(); | |||
this.firstName = firstName; | |||
this.lastName = lastName; | |||
this.email = email; | |||
this.age = age; | |||
this.sex = sex; | |||
this.address = address; | |||
} | |||
public String getFirstName() { | |||
return firstName; | |||
} | |||
public void setFirstName(String firstName) { | |||
this.firstName = firstName; | |||
} | |||
public String getLastName() { | |||
return lastName; | |||
} | |||
public void setLastName(String lastName) { | |||
this.lastName = lastName; | |||
} | |||
public int getAge() { | |||
return age; | |||
} | |||
public void setAge(int age) { | |||
this.age = age; | |||
} | |||
public Address getAddress() { | |||
return address; | |||
} | |||
public void setAddress(Address address) { | |||
this.address = address; | |||
} | |||
public Sex getSex() { | |||
return sex; | |||
} | |||
public void setSex(Sex sex) { | |||
this.sex = sex; | |||
} | |||
public String getEmail() { | |||
return email; | |||
} | |||
public void setEmail(String email) { | |||
this.email = email; | |||
} | |||
public boolean getDeceased() { | |||
return deceased; | |||
} | |||
public void setDeceased(boolean deceased) { | |||
this.deceased = deceased; | |||
} | |||
public Integer getSalary() { | |||
return salary; | |||
} | |||
public void setSalary(Integer salary) { | |||
this.salary = salary; | |||
} | |||
public BigDecimal getRent() { | |||
return rent; | |||
} | |||
public void setRent(BigDecimal rent) { | |||
this.rent = rent; | |||
} | |||
public Double getSalaryDouble() { | |||
return salaryDouble; | |||
} | |||
public void setSalaryDouble(Double salaryDouble) { | |||
this.salaryDouble = salaryDouble; | |||
} | |||
public Date getBirthDate() { | |||
return birthDate; | |||
} | |||
public void setBirthDate(Date birthDate) { | |||
this.birthDate = birthDate; | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
package com.vaadin.tests.data.bean; | |||
public enum Sex { | |||
MALE("Male"), FEMALE("Female"), UNKNOWN("Unknown"); | |||
private String stringRepresentation; | |||
private Sex(String stringRepresentation) { | |||
this.stringRepresentation = stringRepresentation; | |||
} | |||
public String getStringRepresentation() { | |||
return stringRepresentation; | |||
} | |||
} |
@@ -10,6 +10,7 @@ import java.io.Serializable; | |||
import junit.framework.TestCase; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.Property; | |||
import com.vaadin.data.util.IndexedContainer; | |||
import com.vaadin.data.util.MethodProperty; | |||
import com.vaadin.data.validator.RegexpValidator; | |||
@@ -19,9 +20,9 @@ public class TestSerialization extends TestCase { | |||
public void testValidators() throws Exception { | |||
RegexpValidator validator = new RegexpValidator(".*", "Error"); | |||
validator.isValid("aaa"); | |||
validator.validate("aaa"); | |||
RegexpValidator validator2 = (RegexpValidator) serializeAndDeserialize(validator); | |||
validator2.isValid("aaa"); | |||
validator2.validate("aaa"); | |||
} | |||
public void testForm() throws Exception { | |||
@@ -78,15 +79,25 @@ public class TestSerialization extends TestCase { | |||
data)); | |||
Serializable s2 = (Serializable) in.readObject(); | |||
// using special toString(Object) method to avoid calling | |||
// Property.toString(), which will be temporarily disabled | |||
if (s.equals(s2)) { | |||
System.out.println(s + " equals " + s2); | |||
System.out.println(toString(s) + " equals " + toString(s2)); | |||
} else { | |||
System.out.println(s + " does NOT equal " + s2); | |||
System.out.println(toString(s) + " does NOT equal " + toString(s2)); | |||
} | |||
return s2; | |||
} | |||
private static String toString(Object o) { | |||
if (o instanceof Property) { | |||
return String.valueOf(((Property<?>) o).getValue()); | |||
} else { | |||
return String.valueOf(o); | |||
} | |||
} | |||
public static class Data implements Serializable { | |||
private String dummyGetter; | |||
private String dummyGetterAndSetter; |
@@ -0,0 +1,164 @@ | |||
package com.vaadin.tests.server.component.abstractfield; | |||
import java.util.Locale; | |||
import junit.framework.TestCase; | |||
import com.vaadin.data.util.MethodProperty; | |||
import com.vaadin.data.util.converter.Converter; | |||
import com.vaadin.data.util.converter.NumberToStringConverter; | |||
import com.vaadin.tests.data.bean.Address; | |||
import com.vaadin.tests.data.bean.Country; | |||
import com.vaadin.tests.data.bean.Person; | |||
import com.vaadin.tests.data.bean.Sex; | |||
import com.vaadin.ui.CheckBox; | |||
import com.vaadin.ui.TextField; | |||
public class AbstractFieldValueConversions extends TestCase { | |||
Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com", | |||
34, Sex.FEMALE, new Address("Paula street 1", 12345, "P-town", | |||
Country.FINLAND)); | |||
public void testWithoutConversion() { | |||
TextField tf = new TextField(); | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, | |||
"firstName")); | |||
assertEquals("Paula", tf.getValue()); | |||
assertEquals("Paula", tf.getPropertyDataSource().getValue()); | |||
tf.setValue("abc"); | |||
assertEquals("abc", tf.getValue()); | |||
assertEquals("abc", tf.getPropertyDataSource().getValue()); | |||
assertEquals("abc", paulaBean.getFirstName()); | |||
} | |||
public void testStringIdentityConversion() { | |||
TextField tf = new TextField(); | |||
tf.setValueConverter(new Converter<String, String>() { | |||
public String convertFromTargetToSource(String value, Locale locale) { | |||
return value; | |||
} | |||
public String convertFromSourceToTarget(String value, Locale locale) { | |||
return value; | |||
} | |||
public Class<String> getSourceType() { | |||
return String.class; | |||
} | |||
public Class<String> getTargetType() { | |||
return String.class; | |||
} | |||
}); | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, | |||
"firstName")); | |||
assertEquals("Paula", tf.getValue()); | |||
assertEquals("Paula", tf.getPropertyDataSource().getValue()); | |||
tf.setValue("abc"); | |||
assertEquals("abc", tf.getValue()); | |||
assertEquals("abc", tf.getPropertyDataSource().getValue()); | |||
assertEquals("abc", paulaBean.getFirstName()); | |||
} | |||
public void testFailingConversion() { | |||
TextField tf = new TextField(); | |||
tf.setValueConverter(new Converter<Integer, String>() { | |||
public Integer convertFromTargetToSource(String value, Locale locale) { | |||
throw new ConversionException("Failed"); | |||
} | |||
public String convertFromSourceToTarget(Integer value, Locale locale) { | |||
throw new ConversionException("Failed"); | |||
} | |||
public Class<Integer> getSourceType() { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
public Class<String> getTargetType() { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
}); | |||
try { | |||
tf.setValue(1); | |||
fail("setValue(Integer) should throw an exception"); | |||
} catch (com.vaadin.data.Property.ConversionException e) { | |||
// OK, expected | |||
} | |||
} | |||
public void testIntegerStringConversion() { | |||
TextField tf = new TextField(); | |||
tf.setValueConverter(new NumberToStringConverter()); | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, "age")); | |||
assertEquals(34, tf.getPropertyDataSource().getValue()); | |||
assertEquals("34", tf.getValue()); | |||
tf.setValue("12"); | |||
assertEquals(12, tf.getPropertyDataSource().getValue()); | |||
assertEquals("12", tf.getValue()); | |||
tf.getPropertyDataSource().setValue(42); | |||
assertEquals(42, tf.getPropertyDataSource().getValue()); | |||
assertEquals("42", tf.getValue()); | |||
} | |||
public void testBooleanNullConversion() { | |||
CheckBox cb = new CheckBox(); | |||
cb.setValueConverter(new Converter<Boolean, Boolean>() { | |||
public Boolean convertFromTargetToSource(Boolean value, | |||
Locale locale) { | |||
// value from a CheckBox should never be null as long as it is | |||
// not set to null (handled by conversion below). | |||
assertNotNull(value); | |||
return value; | |||
} | |||
public Boolean convertFromSourceToTarget(Boolean value, | |||
Locale locale) { | |||
// Datamodel -> field | |||
if (value == null) { | |||
return false; | |||
} | |||
return value; | |||
} | |||
public Class<Boolean> getSourceType() { | |||
return Boolean.class; | |||
} | |||
public Class<Boolean> getTargetType() { | |||
return Boolean.class; | |||
} | |||
}); | |||
MethodProperty<Person> property = new MethodProperty<Person>(paulaBean, | |||
"deceased"); | |||
cb.setPropertyDataSource(property); | |||
assertNull(property.getValue()); | |||
assertEquals(Boolean.FALSE, cb.getValue()); | |||
Boolean newDmValue = cb.getValueConverter().convertFromSourceToTarget( | |||
cb.getValue(), new Locale("fi", "FI")); | |||
assertEquals(Boolean.FALSE, newDmValue); | |||
// FIXME: Should be able to set to false here to cause datamodel to be | |||
// set to false but the change will not be propagated to the Property | |||
// (field value is already false) | |||
cb.setValue(true); | |||
assertEquals(Boolean.TRUE, cb.getValue()); | |||
assertEquals(Boolean.TRUE, property.getValue()); | |||
cb.setValue(false); | |||
assertEquals(Boolean.FALSE, cb.getValue()); | |||
assertEquals(Boolean.FALSE, property.getValue()); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
package com.vaadin.tests.server.component.abstractfield; | |||
import java.math.BigDecimal; | |||
import java.util.Locale; | |||
import junit.framework.TestCase; | |||
import com.vaadin.Application; | |||
import com.vaadin.data.util.MethodProperty; | |||
import com.vaadin.tests.data.bean.Address; | |||
import com.vaadin.tests.data.bean.Country; | |||
import com.vaadin.tests.data.bean.Person; | |||
import com.vaadin.tests.data.bean.Sex; | |||
import com.vaadin.ui.TextField; | |||
import com.vaadin.ui.Window; | |||
public class DefaultConverterFactory extends TestCase { | |||
Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com", | |||
34, Sex.FEMALE, new Address("Paula street 1", 12345, "P-town", | |||
Country.FINLAND)); | |||
{ | |||
paulaBean.setSalary(49000); | |||
BigDecimal rent = new BigDecimal(57223); | |||
rent = rent.scaleByPowerOfTen(-2); | |||
paulaBean.setRent(rent); | |||
} | |||
public void testDefaultNumberConversion() { | |||
Application app = new Application() { | |||
@Override | |||
public void init() { | |||
} | |||
}; | |||
app.setMainWindow(new Window()); | |||
TextField tf = new TextField(); | |||
app.getMainWindow().addComponent(tf); | |||
tf.setLocale(new Locale("en", "US")); | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, "salary")); | |||
assertEquals("49,000", tf.getValue()); | |||
tf.setLocale(new Locale("fi", "FI")); | |||
// FIXME: The following line should not be necessary and should be | |||
// removed | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, "salary")); | |||
String value = tf.getValue(); | |||
// Java uses a non-breaking space (ascii 160) instead of space when | |||
// formatting | |||
String expected = "49" + (char) 160 + "000"; | |||
assertEquals(expected, value); | |||
} | |||
} |
@@ -2,6 +2,8 @@ package com.vaadin.tests.server.component.textfield; | |||
import java.util.Collections; | |||
import junit.framework.TestCase; | |||
import com.vaadin.data.Property; | |||
import com.vaadin.data.Property.ValueChangeEvent; | |||
import com.vaadin.data.Property.ValueChangeListener; | |||
@@ -11,8 +13,6 @@ import com.vaadin.terminal.Paintable; | |||
import com.vaadin.terminal.Paintable.RepaintRequestEvent; | |||
import com.vaadin.ui.TextField; | |||
import junit.framework.TestCase; | |||
public class TextFieldWithPropertyFormatter extends TestCase { | |||
private static final String INPUT_VALUE = "foo"; | |||
@@ -20,7 +20,7 @@ public class TextFieldWithPropertyFormatter extends TestCase { | |||
private static final String FORMATTED_VALUE = "FOOBAR"; | |||
private static final String ORIGINAL_VALUE = "Original"; | |||
private TextField field; | |||
private PropertyFormatter formatter; | |||
private PropertyFormatter<String> formatter; | |||
private ObjectProperty<String> property; | |||
private ValueChangeListener listener; | |||
private int listenerCalled; | |||
@@ -32,16 +32,16 @@ public class TextFieldWithPropertyFormatter extends TestCase { | |||
field = new TextField(); | |||
formatter = new PropertyFormatter() { | |||
formatter = new PropertyFormatter<String>() { | |||
@Override | |||
public Object parse(String formattedValue) throws Exception { | |||
public String parse(String formattedValue) throws Exception { | |||
assertEquals(INPUT_VALUE, formattedValue); | |||
return PARSED_VALUE; | |||
} | |||
@Override | |||
public String format(Object value) { | |||
public String format(String value) { | |||
return FORMATTED_VALUE; | |||
} | |||
}; | |||
@@ -59,7 +59,7 @@ public class TextFieldWithPropertyFormatter extends TestCase { | |||
assertEquals(FORMATTED_VALUE, event.getProperty().getValue()); | |||
} | |||
}; | |||
field.addListener(listener); | |||
field.addListener(new Paintable.RepaintRequestListener() { | |||
public void repaintRequested(RepaintRequestEvent event) { |
@@ -22,12 +22,12 @@ import com.vaadin.ui.AbstractField; | |||
* override {@link #setValue(AbstractField)} to set the field value via | |||
* <code>changeVariables()</code>. | |||
*/ | |||
public abstract class AbstractTestFieldValueChange extends TestCase { | |||
public abstract class AbstractTestFieldValueChange<T> extends TestCase { | |||
private AbstractField field; | |||
private AbstractField<T> field; | |||
private ValueChangeListener listener; | |||
protected void setUp(AbstractField field) throws Exception { | |||
protected void setUp(AbstractField<T> field) throws Exception { | |||
this.field = field; | |||
listener = EasyMock.createStrictMock(ValueChangeListener.class); | |||
@@ -155,14 +155,14 @@ public abstract class AbstractTestFieldValueChange extends TestCase { | |||
EasyMock.verify(listener); | |||
} | |||
protected AbstractField getField() { | |||
protected AbstractField<T> getField() { | |||
return field; | |||
} | |||
/** | |||
* Override in subclasses to set value with changeVariables(). | |||
*/ | |||
protected void setValue(AbstractField field) { | |||
protected void setValue(AbstractField<T> field) { | |||
field.setValue("newValue"); | |||
} | |||
@@ -12,7 +12,8 @@ import com.vaadin.ui.ComboBox; | |||
* | |||
* See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>. | |||
*/ | |||
public class TestComboBoxValueChange extends AbstractTestFieldValueChange { | |||
public class TestComboBoxValueChange extends | |||
AbstractTestFieldValueChange<Object> { | |||
@Override | |||
protected void setUp() throws Exception { | |||
ComboBox combo = new ComboBox(); | |||
@@ -21,7 +22,7 @@ public class TestComboBoxValueChange extends AbstractTestFieldValueChange { | |||
} | |||
@Override | |||
protected void setValue(AbstractField field) { | |||
protected void setValue(AbstractField<Object> field) { | |||
Map<String, Object> variables = new HashMap<String, Object>(); | |||
variables.put("selected", new String[] { "myvalue" }); | |||
field.changeVariables(field, variables); |
@@ -18,7 +18,8 @@ import com.vaadin.ui.TextField; | |||
* | |||
* See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>. | |||
*/ | |||
public class TestTextFieldValueChange extends AbstractTestFieldValueChange { | |||
public class TestTextFieldValueChange extends | |||
AbstractTestFieldValueChange<String> { | |||
@Override | |||
protected void setUp() throws Exception { | |||
@@ -36,7 +37,7 @@ public class TestTextFieldValueChange extends AbstractTestFieldValueChange { | |||
} | |||
@Override | |||
protected void setValue(AbstractField field) { | |||
protected void setValue(AbstractField<String> field) { | |||
Map<String, Object> variables = new HashMap<String, Object>(); | |||
variables.put("text", "newValue"); | |||
field.changeVariables(field, variables); |
@@ -11,7 +11,7 @@ public class TestReadOnlyValidation { | |||
public void testIntegerValidation() { | |||
TextField field = new TextField(); | |||
field.addValidator(new IntegerValidator("Enter a Valid Number")); | |||
field.setValue(Integer.valueOf(10)); | |||
field.setValue(String.valueOf(10)); | |||
field.validate(); | |||
} | |||
} |
@@ -5,6 +5,7 @@ | |||
package com.vaadin.tests; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; | |||
import com.vaadin.ui.Component.Event; | |||
import com.vaadin.ui.Component.Listener; | |||
import com.vaadin.ui.CustomLayout; | |||
@@ -40,7 +41,13 @@ public class CustomLayoutDemo extends com.vaadin.Application.LegacyApplication | |||
private final PasswordField loginPwd = new PasswordField("Password"); | |||
private final Button loginButton = new Button("Login", this, "loginClicked"); | |||
private final Button loginButton = new Button("Login", | |||
new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
loginClicked(); | |||
} | |||
}); | |||
private final Tree menu = new Tree(); | |||
@@ -7,6 +7,7 @@ package com.vaadin.tests; | |||
import java.util.Date; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; | |||
import com.vaadin.ui.CustomComponent; | |||
import com.vaadin.ui.Label; | |||
import com.vaadin.ui.Table; | |||
@@ -36,10 +37,18 @@ public class PerformanceTestSubTreeCaching extends CustomComponent { | |||
setCompositionRoot(main); | |||
addInfo(); | |||
Button b = new Button("start test", this, "startTest"); | |||
Button b = new Button("start test", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
startTest(); | |||
} | |||
}); | |||
b.setDescription("Push this button to start test. A test label will be rendered above existing components."); | |||
main.addComponent(b); | |||
b = new Button("end test", this, "endTest"); | |||
b = new Button("end test", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
endTest(); | |||
} | |||
}); | |||
b.setDescription("Push this button as soon as test componenet is rendered."); | |||
main.addComponent(b); | |||
@@ -9,6 +9,7 @@ import java.util.Iterator; | |||
import com.vaadin.terminal.ExternalResource; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; | |||
import com.vaadin.ui.Component; | |||
import com.vaadin.ui.CustomComponent; | |||
import com.vaadin.ui.Label; | |||
@@ -51,14 +52,21 @@ public class TestForChildComponentRendering extends CustomComponent { | |||
se.addItem("valinta1"); | |||
se.addItem("Valinta 2"); | |||
Button b = new Button("refresh view", this, "createNewView"); | |||
Button b = new Button("refresh view", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
createNewView(); | |||
} | |||
}); | |||
main.addComponent(b); | |||
b = new Button("reorder view", this, "randomReorder"); | |||
b = new Button("reorder view", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
randomReorder(); | |||
} | |||
}); | |||
main.addComponent(b); | |||
b = new Button("remove randomly one component", this, | |||
"removeRandomComponent"); | |||
b = new Button("remove randomly one component", new Button.ClickListener() { public void buttonClick(ClickEvent event) { removeRandomComponent();}}); | |||
main.addComponent(b); | |||
} |
@@ -62,12 +62,12 @@ public class TestForContainerFilterable extends CustomComponent { | |||
filterButton.addListener(new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
ic.removeAllContainerFilters(); | |||
if (fooFilter.toString().length() > 0) { | |||
ic.addContainerFilter("foo", fooFilter.toString(), false, | |||
if (fooFilter.getStringValue().length() > 0) { | |||
ic.addContainerFilter("foo", fooFilter.getStringValue(), false, | |||
false); | |||
} | |||
if (barFilter.toString().length() > 0) { | |||
ic.addContainerFilter("bar", barFilter.toString(), true, | |||
if (barFilter.getStringValue().length() > 0) { | |||
ic.addContainerFilter("bar", barFilter.getStringValue(), true, | |||
true); | |||
} | |||
count.setValue("Rows in table: " + ic.size()); |
@@ -9,6 +9,7 @@ import java.util.Iterator; | |||
import com.vaadin.terminal.ExternalResource; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; | |||
import com.vaadin.ui.Component; | |||
import com.vaadin.ui.CustomComponent; | |||
import com.vaadin.ui.GridLayout; | |||
@@ -52,14 +53,26 @@ public class TestForGridLayoutChildComponentRendering extends CustomComponent { | |||
main.addComponent(se, 0, 1, 1, 1); | |||
Button b = new Button("refresh view", this, "createNewView"); | |||
Button b = new Button("refresh view", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
createNewView(); | |||
} | |||
}); | |||
main.addComponent(b); | |||
b = new Button("reorder view", this, "randomReorder"); | |||
b = new Button("reorder view", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
randomReorder(); | |||
} | |||
}); | |||
main.addComponent(b); | |||
b = new Button("remove randomly one component", this, | |||
"removeRandomComponent"); | |||
b = new Button("remove randomly one component", | |||
new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
removeRandomComponent(); | |||
} | |||
}); | |||
main.addComponent(b); | |||
} |
@@ -90,7 +90,11 @@ public class TestForPreconfiguredComponents extends CustomComponent implements | |||
test.setCaption("OptionGroup + multiselect manually (configured from select)"); | |||
main.addComponent(test); | |||
final Button b = new Button("refresh view", this, "createNewView"); | |||
final Button b = new Button("refresh view", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
createNewView(); | |||
} | |||
}); | |||
main.addComponent(b); | |||
} | |||
@@ -160,6 +164,7 @@ public class TestForPreconfiguredComponents extends CustomComponent implements | |||
t.addListener(new Listener() { | |||
public void componentEvent(Event event) { | |||
status.addComponent(new Label(event.getClass().getName())); | |||
// TODO should not use Field.toString() | |||
status.addComponent(new Label("selected: " | |||
+ event.getSource().toString())); | |||
} |