From: <wes...@us...> - 2013-02-21 08:49:27
|
Revision: 1173 http://jmoney.svn.sourceforge.net/jmoney/?rev=1173&view=rev Author: westbury Date: 2013-02-21 08:49:18 +0000 (Thu, 21 Feb 2013) Log Message: ----------- fix and clean-up the use of IValueProperty for both normal properties and properties in extension objects Modified Paths: -------------- trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtendablePropertySet.java trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtensionPropertySet.java trunk/net.sf.jmoney/src/net/sf/jmoney/model2/PropertySet.java trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ScalarPropertyAccessor.java Modified: trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtendablePropertySet.java =================================================================== --- trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtendablePropertySet.java 2013-02-21 08:48:05 UTC (rev 1172) +++ trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtendablePropertySet.java 2013-02-21 08:49:18 UTC (rev 1173) @@ -33,6 +33,8 @@ import net.sf.jmoney.isolation.IValues; import net.sf.jmoney.isolation.ListKey; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.ISharedImages; @@ -47,7 +49,7 @@ * or null if this is an abstract property set. */ IExtendableObjectConstructors<E> constructors; - + /** * true if further property sets must be derived from this property set, * false if property sets cannot be derived from this property set. @@ -61,10 +63,10 @@ */ private Map<Class<? extends E>, ExtendablePropertySet<? extends E>> derivedPropertySets = new HashMap<Class<? extends E>, ExtendablePropertySet<? extends E>>(); - private Collection<ExtendablePropertySet<? extends E>> directlyDerivedPropertySets = new Vector<ExtendablePropertySet<? extends E>>(); - - Map<String, ExtensionPropertySet<?,E>> extensionPropertySets = null; + private Collection<ExtendablePropertySet<? extends E>> directlyDerivedPropertySets = new Vector<ExtendablePropertySet<? extends E>>(); + Map<String, ExtensionPropertySet<?,E>> extensionPropertySets = null; + /** * Localized text describing the type of object represented * by this property set. This property is never null. @@ -104,7 +106,7 @@ /** * Constructs a property set object. - * + * * @param classOfObject * the class of the implementation object * @param objectDescription @@ -123,7 +125,7 @@ this.classOfObject = classOfObject; this.basePropertySet = basePropertySet; this.constructors = constructors; - + this.derivable = (constructors == null); this.objectDescription = objectDescription; this.iconImageDescriptor = null; @@ -134,7 +136,7 @@ @Override public void initProperties(String propertySetId) { super.initProperties(propertySetId); - + // Add to our map that maps ids to ExtendablePropertySet objects. allExtendablePropertySetsMap.put(propertySetId, this); @@ -172,7 +174,7 @@ * set. However, icons also apply to derived property sets for which no * icon has been set. So, if the icon is null, go up the list of base * property sets until we find a non-null icon. - * + * * This must be done here and not in the constructor because the calling * code must have a chance to set an icon before this code is executed. */ @@ -191,26 +193,26 @@ for (ExtendablePropertySet base = getBasePropertySet(); base != null; base = base.getBasePropertySet()) { scalarIndex += base.getScalarProperties2().size(); } - + for (ScalarPropertyAccessor propertyAccessor: getScalarProperties2()) { propertyAccessor.setIndexIntoScalarProperties(scalarIndex++); } - + } - + /** * Gets the set of all property sets that are directly derived from this * property set. This set does not include property sets that are derived * from property sets that are in turn derived from this property set. This * set includes both property sets that are derivable and property sets that * are final. - * + * * This method is useful when the caller needs to know the actual tree * structure of the derived property sets or needs to know about the * intermediate (non-final) property sets. Callers generally would call this * method in a recursive manner. - * + * * If a caller just needs a list of the final property sets, * getDerivedPropertySets() is simpler to use. */ @@ -219,7 +221,7 @@ } /** - * + * * @return the set of all property sets * that are derived from this property set and * that are themselves not derivable @@ -238,7 +240,7 @@ * property set that is not derived from this property set then null will be * returned. The advantage of using this method is that the returned * property set is parameterized with <? extends E>. - * @throws PropertySetNotFoundException + * @throws PropertySetNotFoundException */ public ExtendablePropertySet<? extends E> getDerivedPropertySet(String propertySetId) throws PropertySetNotFoundException { for (ExtendablePropertySet<? extends E> propertySet : derivedPropertySets.values()) { @@ -248,7 +250,7 @@ } throw new PropertySetNotFoundException(propertySetId); } - + /** * Given a class of an object, returns the property * set for that object. The class passed to this method @@ -257,10 +259,10 @@ * extended from the implementation class. The class must be * a final class (i.e. a class of an actual object instance, * not an abstract class). - * + * * If this property set is a final property set then this * method will always return this object. - * + * * @return the final property set */ @Override @@ -269,7 +271,7 @@ } /** - * + * * @return If this property set is derived from another property * set then the base property set is returned, otherwise * null is returned. @@ -302,7 +304,7 @@ * If no icon is set then the icon for the base class will be * used or, if there is no base class, no icon will be shown * for objects of this class. - * + * * @param iconImageDescriptor */ public void setIcon(ImageDescriptor iconImageDescriptor) { @@ -317,7 +319,7 @@ * must be created by UI thread. * <P> * This method is valid for extendable property sets only. - * + * * @return the icon associated with objects that implement * this property set. */ @@ -355,7 +357,7 @@ * possible. We therefore allow local names only to be specified. * Local names may not be unique when extensions are included, so we * must require fully qualified names for extensions. - * + * * @param name The local property name */ public PropertyAccessor getPropertyAccessorGivenLocalNameAndExcludingExtensions(String localPropertyName) throws PropertyNotFoundException { @@ -379,7 +381,7 @@ * <P> * Properties from base property sets and properties from derived property * sets are not returned. - * + * * @return a collection of <code>PropertyAccessor</code> objects */ private Collection<PropertyAccessor> getProperties2() { @@ -409,7 +411,7 @@ * <P> * Properties from base property sets and properties from derived property * sets are not returned. - * + * * @return a collection of <code>PropertyAccessor</code> objects */ public Collection<ScalarPropertyAccessor<?,E>> getScalarProperties2() { @@ -439,7 +441,7 @@ * <P> * Properties from base property sets and properties from derived property * sets are not returned. - * + * * @return a collection of <code>PropertyAccessor</code> objects */ public Collection<ListPropertyAccessor> getListProperties2() { @@ -551,39 +553,39 @@ * <P> * Note: * This method does not return derived property sets. - * This method does not return property sets that extend any + * This method does not return property sets that extend any * property sets from which this property set is derived. - * + * * @return the extension property sets that extend this property * set */ public Collection<ExtensionPropertySet<?,E>> getDirectExtensionPropertySets() { return extensionPropertySets.values(); } - + /** * Gets a list of all property sets that extend the given property set. * Property sets that extend any base property sets are also included. - * + * * Note: This method does not return derived property sets. - * + * * @return the extension property sets that extend this property set */ public Collection<ExtensionPropertySet<?,? super E>> getExtensionPropertySets() { Collection<ExtensionPropertySet<?,? super E>> result = new ArrayList<ExtensionPropertySet<?,? super E>>(); - + ExtendablePropertySet<? super E> propertySet = this; do { result.addAll(propertySet.extensionPropertySets.values()); propertySet = propertySet.getBasePropertySet(); } while (propertySet != null); - + return result; } - + /** * This method should be used only by plug-ins that implement a datastore. - * + * * @param objectKey * key to the object, which cannot be null * @param parentKey @@ -603,7 +605,7 @@ /** * This method should be used only by plug-ins that implement * a datastore. - * + * * @return A newly constructed object, constructed from the given * parameters. This object may be an ExtendableObject or * may be an ExtensionObject. @@ -612,17 +614,17 @@ public E constructDefaultImplementationObject(IObjectKey objectKey, ListKey<? super E,?> parentKey) { return constructors.construct(objectKey, parentKey); } - + /** * Returns the set of tabbed pages that are to be shown in the * editor associated with extendable objects of this property set. * <P> * This method is valid only for non-derivable extendable property sets. - * + * * @return a set of objects of type PageEntry */ public Vector<PageEntry> getPageFactories() { - return pageExtensions; + return pageExtensions; } @@ -644,7 +646,7 @@ /** * Utility method to find a property among all properties supported * by objects of this class. - * + * * @param scalarPropertyId * @return */ @@ -660,7 +662,7 @@ /** * Utility method to find a property among all properties supported * by objects of this class. - * + * * @param listPropertyId * @return */ @@ -679,29 +681,7 @@ } @Override - public <V> V getPropertyValue(ExtendableObject extendableObject, - ScalarPropertyAccessor<V, ?> accessor) { - - if (!classOfObject.isAssignableFrom(extendableObject.getClass())) { - // TODO: We should be able to validate this at compile time using generics. - // This would involve adding the implementation class of the containing - // property set as a type parameter to all property accessors. - throw new RuntimeException("Property " + accessor.getName() //$NON-NLS-1$ - + " is implemented by " + classOfObject.getName() //$NON-NLS-1$ - + " but is being called on an object of type " //$NON-NLS-1$ - + getClass().getName()); - } - -// return accessor.invokeGetMethod(extendableObject); -// return accessor.getValue(extendableObject); - // revert to above line when parameterized - return accessor.getClassOfValueObject().cast(accessor.getBeanValue(extendableObject)); + public IValueProperty createValueProperty(ScalarPropertyAccessor accessor) { + return BeanProperties.value(classOfObject, accessor.localName); } - - @Override - public <V> void setPropertyValue(ExtendableObject extendableObject, - ScalarPropertyAccessor<V, ?> accessor, V value) { -// accessor.invokeSetMethod(extendableObject, value); - accessor.setBeanValue(extendableObject, value); - } } Modified: trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtensionPropertySet.java =================================================================== --- trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtensionPropertySet.java 2013-02-21 08:48:05 UTC (rev 1172) +++ trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ExtensionPropertySet.java 2013-02-21 08:49:18 UTC (rev 1173) @@ -24,6 +24,7 @@ import net.sf.jmoney.isolation.IValues; +import org.eclipse.core.databinding.beans.BeanProperties; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.value.AbstractObservableValue; import org.eclipse.core.databinding.observable.value.IObservableValue; @@ -33,7 +34,7 @@ public class ExtensionPropertySet<X extends ExtensionObject,E extends ExtendableObject> extends PropertySet<X,E> { - private ExtendablePropertySet<E> extendablePropertySet; + private ExtendablePropertySet<E> extendablePropertySet; /** * An interface that can be used to construct implementation objects, @@ -44,7 +45,7 @@ IValueProperty extensionGivenExtendableObject; /** * Constructs an extension property set object. - * + * * @param classOfObject * @param constructors * a required interface containing methods for constructing @@ -60,7 +61,7 @@ if (extendablePropertySet == null) { throw new MalformedPluginException("A non-null extendable property set must be passed."); //$NON-NLS-1$ } - + extensionGivenExtendableObject = new ValueProperty() { @Override @@ -86,18 +87,18 @@ } }; } - + @Override public void initProperties(String propertySetId) { super.initProperties(propertySetId); - + // Add to our map that maps ids to ExtensionPropertySet objects. allExtensionPropertySetsMap.put(propertySetId, this); // Add to our map that maps ids to ExtensionPropertySet objects // within a particular extendable object. extendablePropertySet.extensionPropertySets.put(propertySetId, this); -/* +/* // Build the list of properties that are passed to // the 'new object' constructor and another list that // are passed to the 're-instantiating' constructor. @@ -114,7 +115,7 @@ defaultConstructorProperties.add(propertyAccessor); } } -*/ +*/ } public ExtendablePropertySet getExtendablePropertySet() { @@ -128,7 +129,7 @@ * the constructor. If an extendable object is being constructed * then the first three elements of this array must be the * object key, the extension map, and the parent object key. - * + * * @return A newly constructed object, constructed from the given * parameters. This object may be an ExtendableObject or * may be an ExtensionObject. @@ -142,7 +143,7 @@ /** * This method should be used only by plug-ins that implement * a datastore. - * + * * @return A newly constructed object, constructed from the given * parameters. This object may be an ExtendableObject or * may be an ExtensionObject. @@ -152,49 +153,99 @@ extensionObject.setPropertySet(this); return extensionObject; } - + @Override protected X getImplementationObject(ExtendableObject extendableObject) { return extendableObject.getExtension(this, true); } @Override - public <V> V getPropertyValue(ExtendableObject extendableObject, - ScalarPropertyAccessor<V, ?> accessor) { - - ExtensionObject extension = extendableObject.getExtension(this, false); - Class<?> implementationClass = extendablePropertySet.getImplementationClass(); - + public IValueProperty createValueProperty(final ScalarPropertyAccessor accessor) { /* - * If there is no extension then we return the default value. + * This is a little more complex. We need to create an IValueProperty + * implementation that takes as the source object the ExtendableObject + * but the property is actually in an extension object. + * + * By returning such an IValueProperty implementation, consumers + * can use databinding without needing to know whether the property is + * in the base object or an extension object. */ - if (extension == null) { - return accessor.getDefaultValue(); - } - if (!implementationClass.isAssignableFrom(extendableObject.getClass())) { - // TODO: We should be able to validate this at compile time using generics. - // This would involve adding the implementation class of the containing - // property set as a type parameter to all property accessors. - throw new RuntimeException("Property " + accessor.getName() //$NON-NLS-1$ - + " is implemented by " + implementationClass.getName() //$NON-NLS-1$ - + " but is being called on an object of type " //$NON-NLS-1$ - + getClass().getName()); - } + final IValueProperty beanValueProperty = BeanProperties.value(classOfObject, accessor.localName); -// return (V)extensionGivenExtendableObject.value(accessor).getValue(extendableObject); - return (V)accessor.getBeanValue(extension); - } + return new ValueProperty() { - @Override - public <V> void setPropertyValue(ExtendableObject extendableObject, - ScalarPropertyAccessor<V, ?> accessor, V value) { + @Override + public Object getValueType() { + return classOfObject; + } - // Get the extension, creating one if necessary. - Object objectWithProperties = extendableObject.getExtension(this, true); -// accessor.invokeSetMethod(objectWithProperties, value); - accessor.setBeanValue(objectWithProperties, value); + @Override + public Object doGetValue(Object source) { + ExtendableObject extendableObject = (ExtendableObject)source; -// extensionGivenExtendableObject.value(accessor).setValue(extendableObject, value); + /* + * This implementation is a little more efficient than going through + * the observable. So we overwrite the default implementation with + * this more efficient way of getting the value. + */ + + ExtensionObject extension = extendableObject.getExtension(ExtensionPropertySet.this, false); + Class<?> implementationClass = extendablePropertySet.getImplementationClass(); + + /* + * If there is no extension then we return the default value. + */ + if (extension == null) { + return accessor.getDefaultValue(); + } + + if (!implementationClass.isAssignableFrom(extendableObject.getClass())) { + // TODO: We should be able to validate this at compile time using generics. + // This would involve adding the implementation class of the containing + // property set as a type parameter to all property accessors. + throw new RuntimeException("Property " + accessor.getName() //$NON-NLS-1$ + + " is implemented by " + implementationClass.getName() //$NON-NLS-1$ + + " but is being called on an object of type " //$NON-NLS-1$ + + getClass().getName()); + } + + return beanValueProperty.getValue(extension); + } + + @Override + protected void doSetValue(Object source, Object value) { + ExtendableObject extendableObject = (ExtendableObject)source; + + /* + * This implementation is a little more efficient than going through + * the observable. So we overwrite the default implementation with + * this more efficient way of setting the value. + */ + + // Get the extension, creating one if necessary. + X extension = extendableObject.getExtension(ExtensionPropertySet.this, true); + beanValueProperty.setValue(extension, value); + } + + @Override + public IObservableValue observe(Realm realm, Object source) { + /* + * We use a bit of a trick here. If the extension does not + * exist then we create it at this time. This allows us to + * simply observe the property in the extension. This trick + * works because once an extension has been created the extension + * is never removed or replaced (only fields within the extension + * may change). + * + * We cannot be significantly adding to a scalability problem + * here because there is a fair amount of overhead in creating an + * observable and listening to it. + */ + ExtendableObject extendableObject = (ExtendableObject)source; + X extension = extendableObject.getExtension(ExtensionPropertySet.this, true); + return beanValueProperty.observe(realm, extension); + } + }; } } Modified: trunk/net.sf.jmoney/src/net/sf/jmoney/model2/PropertySet.java =================================================================== --- trunk/net.sf.jmoney/src/net/sf/jmoney/model2/PropertySet.java 2013-02-21 08:48:05 UTC (rev 1172) +++ trunk/net.sf.jmoney/src/net/sf/jmoney/model2/PropertySet.java 2013-02-21 08:49:18 UTC (rev 1173) @@ -32,6 +32,7 @@ import net.sf.jmoney.isolation.IObjectKey; import net.sf.jmoney.isolation.ObjectCollection; +import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; @@ -50,28 +51,28 @@ * </LI> * <LI>or are the properties added to a data model object by * a plug-in (such property sets are know as extension - * property sets) + * property sets) * </LI> * </UL> - * The <code>getBasePropertySet</code> and <code>isExtension</code> methods + * The <code>getBasePropertySet</code> and <code>isExtension</code> methods * can be called to determine in which of the above three categories * a property set lies. - * + * * @see <a href="propertySets.html">Property Set Documentation</a> * @see <a href="extendingDatamodel.html#propertySets">Property Set Documentation</a> * @param P the type of the implementation object, which must be * either an ExtendableObject or an ExtensionObject * @Param E the type of the extendable object, which will be the same * as P if this is an extendable object but will be different if - * P is an extension object + * P is an extension object * @author Nigel Westbury */ public abstract class PropertySet<P,S extends ExtendableObject> { - + protected String propertySetId; - + protected Class<P> classOfObject; - + protected Vector<PropertyAccessor> properties = new Vector<PropertyAccessor>(); /** @@ -81,10 +82,10 @@ private Vector<ListPropertyAccessor<?,S>> listProperties1 = null; boolean isExtension; - + static Vector<PropertySet> allPropertySets = new Vector<PropertySet>(); static Set<String> allPropertySetIds = new HashSet<String>(); - + /** * Maps property set id to the property set */ @@ -95,22 +96,22 @@ * Map extendable classes to property sets. */ protected static Map<Class<? extends ExtendableObject>, ExtendablePropertySet> classToPropertySetMap = new HashMap<Class<? extends ExtendableObject>, ExtendablePropertySet>(); - + protected PropertySet() { // Add to our list of all property sets allPropertySets.add(this); } - + /** * This method is called after all the properties in this property set have * been set. It completes the initialization of this object. - * + * * This cannot be done in the constructor because there may be circular references * between property sets, properties in those property sets, and property sets for * the objects referenced by those properties. - * - * @param propertySetId * + * @param propertySetId + * */ public void initProperties(String propertySetId) { /* @@ -122,23 +123,23 @@ this.propertySetId = propertySetId; allPropertySetIds.add(propertySetId); } - + /** * Loads the property sets. - * All property sets (both base and extensions) are added to the + * All property sets (both base and extensions) are added to the * net.sf.jmoney.fields extension point. */ public static void init() { // Load the property set extensions. IExtensionRegistry registry = Platform.getExtensionRegistry(); - + // TODO: They may be not much point in processing extendable classes before extension // classes. Eclipse, I believe, will always iterate extension info from a plug-in // before extensions from plug-ins that depend on that plug-in, so we don't have the // problem of the extendable not being processed before the extension. // We do have other problems, however, which have required a second pass thru // the property sets. - + for (IConfigurationElement element: registry.getConfigurationElementsFor("net.sf.jmoney.fields")) { //$NON-NLS-1$ if (element.getName().equals("extendable-property-set")) { //$NON-NLS-1$ try { @@ -213,14 +214,14 @@ /* * Check for property sets that have been created (because * other property sets depended on them) but that have no entry - * in a plugin.xml file. + * in a plugin.xml file. */ for (PropertySet propertySet: PropertySet.allPropertySets) { if (propertySet.getId() == null) { throw new MalformedPluginException("The property set for " + propertySet.getImplementationClass().getName() + " has not been registered in the plugin.xml file."); //$NON-NLS-1$ //$NON-NLS-2$ } } - + /* * After all property information has been registered, make a second * pass through the extendable objects. In this pass we do processing of @@ -231,34 +232,34 @@ propertySet.initPropertiesPass2(); } } - + /** - * + * * @param propertySetId * @param basePropertySetId If this property set is derived from * another property set then the id of the base property set, - * otherwise null. + * otherwise null. * @param propertySetInfo Null if property set data is found in * the datastore but no plug-in defined a property set - * with this id. - * @param class1 + * with this id. + * @param class1 * @return */ static private void registerExtendablePropertySet(final String propertySetId, final String basePropertySetId, IPropertySetInfo propertySetInfo) { - + // Set up the list of properties. // This is done by calling the registerProperties // method of the supplied interface. PropertySet propertySet = propertySetInfo.registerProperties(); propertySet.initProperties(propertySetId); } - + /** - * - * @param propertySetId + * + * @param propertySetId * @param propertySetInfo Null if property set data is found in * the datastore but no plug-in defined a property set - * with this id. + * with this id. * @return */ static private void registerExtensionPropertySet(final String propertySetId, final String extendablePropertySetId, IPropertySetInfo propertySetInfo) { @@ -268,7 +269,7 @@ PropertySet propertySet = propertySetInfo.registerProperties(); propertySet.initProperties(propertySetId); } - + /** * This method is called when a property set id in plugin.xml references * an extendable property set. The property set object is @@ -297,7 +298,7 @@ return propertySet; } - + /** * This method will find the PropertySet object, given the class of an * implementation object. The given class must be an implementation of ExtendableObject @@ -323,17 +324,17 @@ public String toString() { return propertySetId; } - + /** * @return The globally unique id of the property set. */ public String getId() { return propertySetId; } - + /** * Returns the implementation class for this property set. - * + * * The implementation class for a property set is a class that * implements getters and setters for all the properties in * the property set. Implementation classes for property sets @@ -349,11 +350,11 @@ public Class<P> getImplementationClass() { return classOfObject; } - + /** - * Get the property accessor for a property in a + * Get the property accessor for a property in a * property set. - * + * * This method looks in only in the given property set * (it will not look in base property sets or extension * property sets). @@ -369,25 +370,25 @@ } throw new PropertyNotFoundException(propertySetId, name); } - + /** * Gets a list of all extension property sets. - * + * * @return the collection of all property sets */ static public Collection<ExtensionPropertySet<?,?>> getAllExtensionPropertySets() { return allExtensionPropertySetsMap.values(); } - + /** * Gets a list of all extendable property sets. - * + * * @return the collection of all property sets */ static public Collection<ExtendablePropertySet<?>> getAllExtendablePropertySets() { return allExtendablePropertySetsMap.values(); } - + /** * @return An iterator that iterates over all properties * in this property set, returning, for each property, @@ -396,7 +397,7 @@ public Collection<PropertyAccessor> getProperties1() { return properties; } - + public Collection<ScalarPropertyAccessor<?,S>> getScalarProperties1() { if (scalarProperties1 == null) { scalarProperties1 = new Vector<ScalarPropertyAccessor<?,S>>(); @@ -406,10 +407,10 @@ } } } - + return scalarProperties1; } - + public Collection<ListPropertyAccessor<?,S>> getListProperties1() { if (listProperties1 == null) { listProperties1 = new Vector<ListPropertyAccessor<?,S>>(); @@ -419,10 +420,10 @@ } } } - + return listProperties1; } - + /** * @return */ @@ -430,10 +431,6 @@ return isExtension; } - public abstract <V> V getPropertyValue(ExtendableObject extendableObject, ScalarPropertyAccessor<V,?> accessor); - - public abstract <V> void setPropertyValue(ExtendableObject extendableObject, ScalarPropertyAccessor<V,?> accessor, V value); - public static <E2 extends ExtendableObject> ExtendablePropertySet<E2> addBaseAbstractPropertySet(Class<E2> classOfImplementationObject, String description) { return new ExtendablePropertySet<E2>(classOfImplementationObject, description, null, null); } @@ -493,7 +490,7 @@ return listGetter.getList(getImplementationObject(parentObject)); } }; - + properties.add(accessor); return accessor; } @@ -501,15 +498,25 @@ /** * Given an extendable object, return the Java object that contains the * getters and setters for this property set. - * + * * If this property set is an extendable property set then this method * should return the passed object as is. If this property set is an * extension property set then this method should get the appropriate * extension object. - * + * * @param extendableObject * @return */ protected abstract P getImplementationObject(S extendableObject); + + /** + * Given the Bean name of a property in this property set, return an + * IValueProperty implementation that uses as the source the extendable + * object (not the extension object). + * + * @param localName + * @return + */ + public abstract IValueProperty createValueProperty(ScalarPropertyAccessor accessor); } Modified: trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ScalarPropertyAccessor.java =================================================================== --- trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ScalarPropertyAccessor.java 2013-02-21 08:48:05 UTC (rev 1172) +++ trunk/net.sf.jmoney/src/net/sf/jmoney/model2/ScalarPropertyAccessor.java 2013-02-21 08:49:18 UTC (rev 1173) @@ -5,7 +5,6 @@ import net.sf.jmoney.isolation.IScalarPropertyAccessor; -import org.eclipse.core.databinding.beans.BeanProperties; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.map.IObservableMap; @@ -21,11 +20,11 @@ public class ScalarPropertyAccessor<V,E extends ExtendableObject> extends PropertyAccessor<E> implements IScalarPropertyAccessor<V,E> { private IValueProperty valueProperty; - - private int weight; - private int minimumWidth; + private int weight; + private int minimumWidth; + private boolean sortable; /** @@ -57,7 +56,7 @@ private Comparator<ExtendableObject> parentComparator; private IPropertyDependency<? super E> dependency; - + public ScalarPropertyAccessor(Class<V> classOfValueObject, PropertySet<?,E> propertySet, String localName, String displayName, int weight, int minimumWidth, final IPropertyControlFactory<V> propertyControlFactory, IPropertyDependency<? super E> propertyDependency) { super(propertySet, localName, displayName); @@ -69,12 +68,12 @@ Class implementationClass = propertySet.getImplementationClass(); - if (classOfValueObject.isPrimitive()) { + if (classOfValueObject.isPrimitive()) { throw new MalformedPluginException("Property '" + localName + "' in '" + implementationClass.getName() + "' has been parameterized by a primitive type (" + classOfValueObject.getName() + "). Although primitive types may be used by the getters and setters, the equivalent object classes must be used for parameterization."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } - - valueProperty = BeanProperties.value(localName, propertySet.getImplementationClass()); - + + valueProperty = propertySet.createValueProperty(this); + Method theGetMethod; // Use introspection on the interface to find the getter method. // Following the Java beans pattern, we allow the getter for a @@ -136,7 +135,7 @@ /* * Set the comparator, if any. - * + * * If this object has been given a comparator to compare the values of * the properties, then return a comparator that compares the parent * objects by getting the property value from each parent and comparing @@ -168,7 +167,7 @@ * This weight indicates how much the property * can benefit from being given excess width. For example * a property containing a description can benefit, whereas - * a property containing a date cannot. + * a property containing a date cannot. */ public int getWeight() { return weight; @@ -176,7 +175,7 @@ /** * The minimum width to be used when this property is displayed - * in a table or a grid. + * in a table or a grid. */ public int getMinimumWidth() { return minimumWidth; @@ -191,7 +190,7 @@ /** * Indicates whether the property may take null values. - * + * * All properties may take null values except properties whose values are * the intrinsic types (int, long, boolean, char). Properties of type Integer, * Long, Boolean, and Character may take null values. @@ -203,22 +202,22 @@ /** * The default value for a property is suitable for uses such * as: - * + * * - setting the default columnn value in a database * - providing values when the value is missing from an * XML file - * + * * It is expected that this value is constant (the same value * is always returned for a given property). The results will * be unpredicable if this is not the case. - * + * * @return the default value to use for this property, which may * be null if the property is of a nullable type */ public V getDefaultValue() { return propertyControlFactory.getDefaultValue(); } - + /** * Indicates whether the property may be edited by the user. */ @@ -231,7 +230,7 @@ * of this property. This method looks to the comparator, if any, provided by * the IPropertyControlFactory implementation. The ordering is thus defined by the * plug-in that added this property. - * + * * @return a comparator, or null if no comparator was provided * for use with this property */ @@ -243,7 +242,7 @@ String methodName = prefix + propertyName.toUpperCase().charAt(0) + propertyName.substring(1, propertyName.length()); - + try { return getDeclaredMethodRecursively(propertySet.getImplementationClass(), methodName, parameters); } catch (NoSuchMethodException e) { @@ -268,12 +267,12 @@ } /** - * Gets a method from an interface. + * Gets a method from an interface. * Whereas Class.getDeclaredMethod finds a method from an * interface, it will not find the method if the method is * defined in an interface which the given interface extends. * This method will find the method if any of the interfaces - * extended by this interface define the method. + * extended by this interface define the method. */ @SuppressWarnings("unchecked") private Method getDeclaredMethodRecursively(Class implementationClass, String methodName, Class[] arguments) @@ -286,13 +285,13 @@ classToTry = classToTry.getSuperclass(); } } while (classToTry != null); - + throw new NoSuchMethodException(); } - + /** * Create a Control object that edits the property. - * + * * @param parent * @return An interface to a wrapper class. */ @@ -326,7 +325,7 @@ // We call into that factory to obtain the property value // and format it. - // If null or the empty string is returned to us, + // If null or the empty string is returned to us, // change to "empty". String formattedValue = propertyControlFactory.formatValueForMessage(object, this); return (formattedValue == null || formattedValue.length() == 0) @@ -336,11 +335,11 @@ /** * Format the value of a property as appropriate for displaying in a * table. - * + * * The returned value is expected to be displayed in a table or some similar * view. Null and empty values are therefore returned as empty strings. * Text values are not quoted. - * + * * @return The value of the property formatted as appropriate. */ public String formatValueForTable(ExtendableObject object) { @@ -371,7 +370,7 @@ * the getter method returns int, long, boolean, or char then this * method will return Integer.class, Long.class, Boolean.class, or * Character.class. - * + * * @return the class of the property values (if the method signatures show int, * long, boolean, or char, this field will be Integer.class, Long.class, * Boolean.class, or Character.class) @@ -384,7 +383,7 @@ /** * Returns the class for the values of this property. This is the * class that is returned by the getter method. - * + * * @return the class of the property values (if the method signatures show int, * long, boolean, or char, this field will be int.class, long.class, * boolean.class, or char.class) @@ -409,18 +408,18 @@ * i.e. if this method returns n then in every case where the * collection returned by getPropertyIterator_Scalar3 contains this property, * this property will be returned as the (n+1)'th element in the collection. - * + * * @return the index of this property in the list of scalar * properties for the class. This method returns zero * for the first scalar property returned by - * PropertySet.getPropertyIterator3() and so on. + * PropertySet.getPropertyIterator3() and so on. */ @Override public int getIndexIntoScalarProperties() { return indexIntoScalarProperties; } - // TODO: This method should be accessible only from within the package. + // TODO: This method should be accessible only from within the package. public void setIndexIntoScalarProperties(int indexIntoScalarProperties) { this.indexIntoScalarProperties = indexIntoScalarProperties; } @@ -429,10 +428,10 @@ * Indicates if this property is applicable. An instance of an object * containing this property is passed. This method should look to the values * of the other properties in the object to determine if this property is applicable. - * + * * If the property is not applicable then the UI should not show a value for this * property nor allow it to be updated. - * + * * @return */ public boolean isPropertyApplicable(E containingObject) { @@ -444,11 +443,11 @@ } public V getValue(E extendableObject) { - return propertySet.getPropertyValue(extendableObject, this); + return (V)valueProperty.getValue(extendableObject); } - + public void setValue(E extendableObject, V value) { - propertySet.setPropertyValue(extendableObject, this, value); + valueProperty.setValue(extendableObject, value); } public <V2> ScalarPropertyAccessor<? super V2, E> typeIfGivenValue( @@ -468,8 +467,7 @@ // TODO remove this untyped version when generics is in IValueProperty @Override public Object getValue(Object source) { - return propertySet.getPropertyValue((ExtendableObject)source, this); -// return valueProperty.getValue(source); + return valueProperty.getValue(source); } // TODO remove this untyped version when generics is in IValueProperty @@ -479,15 +477,6 @@ @Override public void setValue(Object source, Object value) { -// This is incorrect. We must support IValueProperty implementations that -// go to an extension object. -// valueProperty.setValue(source, value); - propertySet.setPropertyValue((ExtendableObject)source, this, (V)value); - } - - public void setBeanValue(Object source, Object value) { -// This is incorrect. We must support IValueProperty implementations that -// go to an extension object. valueProperty.setValue(source, value); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |