diff options
Diffstat (limited to 'src/com/itmill/toolkit/data/util/ObjectProperty.java')
-rw-r--r-- | src/com/itmill/toolkit/data/util/ObjectProperty.java | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/src/com/itmill/toolkit/data/util/ObjectProperty.java b/src/com/itmill/toolkit/data/util/ObjectProperty.java new file mode 100644 index 0000000000..47490011cf --- /dev/null +++ b/src/com/itmill/toolkit/data/util/ObjectProperty.java @@ -0,0 +1,322 @@ +/* ************************************************************************* + + IT Mill Toolkit + + Development of Browser User Intarfaces Made Easy + + Copyright (C) 2000-2006 IT Mill Ltd + + ************************************************************************* + + This product is distributed under commercial license that can be found + from the product package on license/license.txt. Use of this product might + require purchasing a commercial license from IT Mill Ltd. For guidelines + on usage, see license/licensing-guidelines.html + + ************************************************************************* + + For more information, contact: + + IT Mill Ltd phone: +358 2 4802 7180 + Ruukinkatu 2-4 fax: +358 2 4802 7181 + 20540, Turku email: info@itmill.com + Finland company www: www.itmill.com + + Primary source for information and releases: www.itmill.com + + ********************************************************************** */ + +package com.itmill.toolkit.data.util; + +import com.itmill.toolkit.data.Property; + +import java.lang.reflect.Constructor; +import java.util.LinkedList; + +/** A simple data object containing one typed value. This class is a + * straightforward implementation of the the + * {@link com.itmill.toolkit.data.Property} interface. + * + * @author IT Mill Ltd. + * @version @VERSION@ + * @since 3.0 + */ +public class ObjectProperty implements Property, Property.ValueChangeNotifier, +Property.ReadOnlyStatusChangeNotifier { + + /** A boolean value storing the Property's read-only status + * information. + */ + private boolean readOnly = false; + + /** The value contained by the Property. */ + private Object value; + + /** Data type of the Property's value */ + private Class type; + + /** Internal list of registered value change listeners. */ + private LinkedList valueChangeListeners = null; + + /** Internal list of registered read-only status change listeners. */ + private LinkedList readOnlyStatusChangeListeners = null; + + /** Creates a new instance of ObjectProperty with the given value. + * The type of the property is automatically initialized to be + * the type of the given value. + * + * @param value Initial value of the Property + */ + public ObjectProperty(Object value) { + this(value,value.getClass()); + } + + /** Creates a new instance of ObjectProperty with the given value and + * type. + * + * @param value Initial value of the Property + * @param type The type of the value. The value must be assignable to + * given type + */ + public ObjectProperty(Object value, Class type) { + + // Set the values + this.type = type; + setValue(value); + } + + /** Creates a new instance of ObjectProperty with the given value, type + * and read-only mode status. + * + * @param value Initial value of the property. + * @param type The type of the value. <code>value</code> must be + * assignable to this type. + * @param readOnly Sets the read-only mode. + */ + public ObjectProperty(Object value, Class type, boolean readOnly) { + this(value,type); + setReadOnly(readOnly); + } + + /** Returns the type of the ObjectProperty. 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 type of the Property + */ + public final Class getType() { + return type; + } + + /** Gets the value stored in the Property. + * + * @return the value stored in the Property + */ + public Object getValue() { + return value; + } + + /** Returns the value of the ObjectProperty 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 + * ObjectProperty + */ + public String toString() { + Object value = getValue(); + if (value != null) + return value.toString(); + else + return null; + } + + /** Tests if the Property is in read-only mode. In read-only mode calls + * to the method <code>setValue</code> will throw + * <code>ReadOnlyException</code>s and will not modify the value of the + * Property. + * + * @return <code>true</code> if the Property is in read-only mode, + * <code>false</code> if it's not + */ + public boolean isReadOnly() { + return readOnly; + } + + /** Sets the Property's read-only mode to the specified status. + * + * @param newStatus new read-only status of the Property + */ + public void setReadOnly(boolean newStatus) { + readOnly = newStatus; + } + + /** Set the value of the property. This method supports setting from + * <code>String</code>s if either <code>String</code> is directly + * assignable to property type, or the type class contains a string + * constructor. + * + * @param newValue New value of the property. + * @throws <code>Property.ReadOnlyException</code> if the object is in + * read-only mode + * @throws <code>Property.ConversionException</code> if + * <code>newValue</code> can't be converted into the Property's native + * type directly or through <code>String</code> + */ + public void setValue(Object newValue) + throws Property.ReadOnlyException, Property.ConversionException { + + // Check the mode + if (isReadOnly()) throw new Property.ReadOnlyException(); + + // Try to assign the compatible value directly + if (newValue == null || type.isAssignableFrom(newValue.getClass())) + value = newValue; + + // Otherwise try to convert the value trough string constructor + else try { + + // Get the string constructor + Constructor constr = + getType().getConstructor(new Class[] { String.class }); + + // Create new object from the string + value = constr.newInstance(new Object[] {newValue.toString()}); + + } catch (java.lang.Exception e) { + throw new Property.ConversionException(e); + } + + fireValueChange(); + } + + /* Events *************************************************************** */ + + /** An <code>Event</code> object specifying the ObjectProperty whose value + * has changed. + * @author IT Mill Ltd. + * @version @VERSION@ + * @since 3.0 + */ + private class ValueChangeEvent extends java.util.EventObject + implements Property.ValueChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3256718468479725873L; + + /** Constructs a new value change event for this object. + * + * @param source source object of the event + */ + protected ValueChangeEvent(ObjectProperty source) { + super(source); + } + + /** Gets the Property whose read-only state has changed. + * + * @return source Property of the event. + */ + public Property getProperty() { + return (Property) getSource(); + } + } + + /** An <code>Event</code> object specifying the Property whose read-only + * status has been changed. + * @author IT Mill Ltd. + * @version @VERSION@ + * @since 3.0 + */ + private class ReadOnlyStatusChangeEvent extends java.util.EventObject + implements Property.ReadOnlyStatusChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3907208273529616696L; + + /** Constructs a new read-only status change event for this object. + * + * @param source source object of the event + */ + protected ReadOnlyStatusChangeEvent(ObjectProperty source) { + super(source); + } + + /** Gets the Property whose read-only state has changed. + * + * @return source Property of the event. + */ + public Property getProperty() { + return (Property) getSource(); + } + } + + /** Remove a previously registered value change listener. + * + * @param listener listener to be removed + */ + public void removeListener(Property.ValueChangeListener listener) { + if (valueChangeListeners != null) + valueChangeListeners.remove(listener); + } + + /** Registers a new value change listener for this ObjectProperty. + * + * @param listener the new Listener to be registered + */ + public void addListener(Property.ValueChangeListener listener) { + if (valueChangeListeners == null) + valueChangeListeners = new LinkedList(); + valueChangeListeners.add(listener); + } + + /** Registers a new read-only status change listener for this Property. + * + * @param listener the new Listener to be registered + */ + public void addListener(Property.ReadOnlyStatusChangeListener listener) { + if (readOnlyStatusChangeListeners == null) + readOnlyStatusChangeListeners = new LinkedList(); + readOnlyStatusChangeListeners.add(listener); + } + + /** Remove a previously registered read-only status change listener. + * + * @param listener listener to be removed + */ + public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + if (readOnlyStatusChangeListeners != null) + readOnlyStatusChangeListeners.remove(listener); + } + + /** Send a value change event to all registered listeners. + */ + private void fireValueChange() { + if (valueChangeListeners != null) { + Object[] l = valueChangeListeners.toArray(); + Property.ValueChangeEvent event = + new ObjectProperty.ValueChangeEvent(this); + for (int i=0; i<l.length; i++) + ((Property.ValueChangeListener)l[i]).valueChange(event); + } + } + + /** Send a read only status change event to all registered listeners. + */ + private void fireReadOnlyStatusChange() { + if (readOnlyStatusChangeListeners != null) { + Object[] l = readOnlyStatusChangeListeners.toArray(); + Property.ReadOnlyStatusChangeEvent event = + new ObjectProperty.ReadOnlyStatusChangeEvent(this); + for (int i=0; i<l.length; i++) + ((Property.ReadOnlyStatusChangeListener)l[i]). + readOnlyStatusChange(event); + } + } +} |