You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ky...@apache.org on 2004/12/03 03:54:10 UTC
svn commit: r109621 - in incubator/beehive/trunk/controls: src/api/org/apache/beehive/controls/api/bean src/runtime/org/apache/beehive/controls/runtime/bean src/runtime/org/apache/beehive/controls/runtime/generator test/src/controls/org/apache/beehive/controls/test/controls/property test/src/units/org/apache/beehive/controls/test/java/property
Author: kylem
Date: Thu Dec 2 18:54:09 2004
New Revision: 109621
URL: http://svn.apache.org/viewcvs?view=rev&rev=109621
Log:
Added support for bound and constrained properties in controls. You can now annotate any
propert declaration method within an @PropertySet with @PropertyInfo(bound=true,constrained=true)
to signal that PropertyChangeListener and/or VetoableChangeListener registration methods should
be exposed. PropertyChangeEvents will be delivered for these bound and/or constrained properties
as described in section 7.4 of the JavaBeans spec when property setters are called. Still
remaining to be done is a way to expose bound/constrained property change events to an
associated ControlImplementation class, but this checkin fully enables external listeners for
PropertyChangeEvents. Included is a new checkin test case that validates the new functionality.
Added:
incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEvents.java
incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEventsImpl.jcs
incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/property/PropEvents.java
Modified:
incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/ControlBean.java
incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java
incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptControlInterface.java
incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptProperty.java
incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBean.vm
incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm
Modified: incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/ControlBean.java
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/ControlBean.java?view=diff&rev=109621&p1=incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/ControlBean.java&r1=109620&p2=incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/ControlBean.java&r2=109621
==============================================================================
--- incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/ControlBean.java (original)
+++ incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/ControlBean.java Thu Dec 2 18:54:09 2004
@@ -29,6 +29,8 @@
* interface to provide a way to get the <code>BeanContext</code> directly associated
* with the Java Control. The <code>getBeanContext()</code> API on the interface will
* return the parent (containing) context.
+ *
+ * @see java.beans.beancontext.BeanContextProxy
*/
public interface ControlBean extends BeanContextProxy, java.io.Serializable
{
Modified: incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java?view=diff&rev=109621&p1=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java&r1=109620&p2=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java&r2=109621
==============================================================================
--- incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java (original)
+++ incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java Thu Dec 2 18:54:09 2004
@@ -19,6 +19,10 @@
import java.beans.beancontext.BeanContext;
import java.beans.beancontext.BeanContextServices;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyChangeListener;
+import java.beans.VetoableChangeSupport;
+import java.beans.VetoableChangeListener;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.AnnotatedElement;
@@ -527,9 +531,6 @@
*/
protected void setControlProperty(PropertyKey key, Object o)
{
- //
- // TODO: Property change notification and veto handling go here
- //
_properties.setProperty(key, o);
}
@@ -561,32 +562,15 @@
return method.invoke(eventNotifier, args);
}
- //
- // These can all be removed once auto-boxing can be assumed
- //
- protected void setControlProperty(PropertyKey key, int i)
- { setControlProperty(key, new Integer(i)); }
-
- protected void setControlProperty(PropertyKey key, short s)
- { setControlProperty(key, new Short(s)); }
-
- protected void setControlProperty(PropertyKey key, long l)
- { setControlProperty(key, new Long(l)); }
-
- protected void setControlProperty(PropertyKey key, byte b)
- { setControlProperty(key, new Byte(b)); }
-
- protected void setControlProperty(PropertyKey key, char c)
- { setControlProperty(key, new Character(c)); }
-
- protected void setControlProperty(PropertyKey key, float f)
- { setControlProperty(key, new Float(f)); }
-
- protected void setControlProperty(PropertyKey key, double d)
- { setControlProperty(key, new Double(d)); }
-
- protected void setControlProperty(PropertyKey key, boolean b)
- { setControlProperty(key, new Boolean(b)); }
+ /**
+ * Returns a property on the ControlBean instance. This version does not coerce
+ * an annotation type property from a PropertyMap to a proxy instance of the
+ * type.
+ */
+ protected Object getRawControlProperty(PropertyKey key)
+ {
+ return _properties.getProperty(key);
+ }
/**
* Returns a property on the ControlBean instance. All generated property getter methods
@@ -594,7 +578,7 @@
*/
protected Object getControlProperty(PropertyKey key)
{
- Object value = _properties.getProperty(key);
+ Object value = getRawControlProperty(key);
// If the held value is a PropertyMap, then wrap it in an annotation proxy of
// the expected type.
@@ -643,6 +627,67 @@
}
/**
+ * This protected version is only available to concrete subclasses that expose bound
+ * property support. This method is synchronized to enable lazy instantiation, in
+ * the belief that is a bigger win to avoid allocating when there are no listeners
+ * than it is to introduce synchronization overhead on access.
+ */
+ synchronized protected PropertyChangeSupport getPropertyChangeSupport()
+ {
+ if (_changeSupport == null)
+ _changeSupport = new PropertyChangeSupport(this);
+
+ return _changeSupport;
+ }
+
+ /**
+ * Delivers a PropertyChangeEvent to any registered PropertyChangeListeners associated
+ * with the property referenced by the specified key.
+ *
+ * This method *should not* be synchronized, as the PropertyChangeSupport has its own
+ * built in synchronization mechanisms.
+ */
+ protected void firePropertyChange(PropertyKey propertyKey, Object oldValue, Object newValue)
+ {
+ // No change support instance means no listeners
+ if (_changeSupport == null)
+ return;
+
+ _changeSupport.firePropertyChange(propertyKey.getPropertyName(), oldValue, newValue);
+ }
+
+ /**
+ * This protected version is only available to concrete subclasses that expose bound
+ * property support. This method is synchronized to enable lazy instantiation, in
+ * the belief that is a bigger win to avoid allocating when there are no listeners
+ * than it is to introduce synchronization overhead on access.
+ */
+ synchronized protected VetoableChangeSupport getVetoableChangeSupport()
+ {
+ if (_vetoSupport == null)
+ _vetoSupport = new VetoableChangeSupport(this);
+
+ return _vetoSupport;
+ }
+
+ /**
+ * Delivers a PropertyChangeEvent to any registered VetoableChangeListeners associated
+ * with the property referenced by the specified key.
+ *
+ * This method *should not* be synchronized, as the VetoableChangeSupport has its own
+ * built in synchronization mechanisms.
+ */
+ protected void fireVetoableChange(PropertyKey propertyKey, Object oldValue, Object newValue)
+ throws java.beans.PropertyVetoException
+ {
+ // No veto support instance means no listeners
+ if (_vetoSupport == null)
+ return;
+
+ _vetoSupport.fireVetoableChange(propertyKey.getPropertyName(), oldValue, newValue);
+ }
+
+ /**
* Returns the parameter names for a method on the ControlBean. Actual mapping is done
* by generated subclasses, so if we reach the base ControlBean implementation, then
* no parameter names are available for the target method.
@@ -719,6 +764,16 @@
* is threadsafe, then the value will be null.
*/
transient private Semaphore _invokeLock;
+
+ /**
+ * This field manages PropertyChangeListeners (if supporting bound properties).
+ */
+ private PropertyChangeSupport _changeSupport;
+
+ /**
+ * This field manages VetoabbleChangeListeners (if supporting constrained properties)
+ */
+ private VetoableChangeSupport _vetoSupport;
/** END synchronized fields */
Modified: incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptControlInterface.java
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptControlInterface.java?view=diff&rev=109621&p1=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptControlInterface.java&r1=109620&p2=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptControlInterface.java&r2=109621
==============================================================================
--- incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptControlInterface.java (original)
+++ incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptControlInterface.java Thu Dec 2 18:54:09 2004
@@ -246,13 +246,29 @@
new AptPropertySet(this, (AnnotationTypeDeclaration)innerDecl, _env));
}
}
+
+ //
+ // Detect the presence of locally declared bound or constrained properties
+ //
+ for (AptPropertySet propSet : propSets)
+ {
+ for (AptProperty prop : propSet.getProperties())
+ {
+ if (prop.isBound())
+ _hasBoundProperties = true;
+
+ if (prop.isConstrained())
+ _hasConstrainedProperties = true;
+ }
+ }
+
return propSets;
}
/**
* Returns the list of PropertySets declared directly by this AptControlInterface
*/
- public ArrayList<AptPropertySet> getPropertySets() { return _propertySets; }
+ public Collection<AptPropertySet> getPropertySets() { return _propertySets; }
/**
* Returns the total number of properties for this control interface
@@ -267,25 +283,59 @@
}
/**
- * Returns true if the control BeanInfo needs a customized set of PropertyDescriptors
- * code generated or false if standard introspection via reflection is ok.
+ * Returns true if the interface has any bound properties associated with it.
*/
- public boolean needsCustomPropertyDescriptors()
+ public boolean hasBoundProperties()
+ {
+ if (_superClass != null && _superClass.hasBoundProperties())
+ return true;
+
+ return _hasBoundProperties;
+ }
+
+ /**
+ * Returns true if this interface is the first interface in the inheritance hierarchy
+ * to declare support for bound properties. This is used to declared PropertyChangeListener
+ * registration methods for the bean once (and only once).
+ */
+ public boolean addsBoundPropertySupport()
{
//
- // The algorithm here is pretty simple.. if any individual property needs a customized
- // descriptor, then you have to generate them all. Reflection-driven introspection is
- // an all-or-nothing deal as implemented by java.beans.Introspector.
+ // If a super interface has already added support, then not added here
//
- for (AptPropertySet propertySet : _propertySets)
- {
- for (AptProperty property : propertySet.getProperties())
- {
- if (property.needsCustomPropertyDescriptor())
- return true;
- }
- }
- return false;
+ if (_superClass != null && _superClass.addsBoundPropertySupport())
+ return false;
+
+ return hasBoundProperties();
+ }
+
+ /**
+ * Returns true if any properties declared directly by this control interface are constrained
+ * properties. This <b>will not</b> reflect the attributes of properties declared on
+ * an interface from which this interface derives.
+ */
+ public boolean hasConstrainedProperties()
+ {
+ if (_superClass != null && _superClass.hasConstrainedProperties())
+ return true;
+
+ return _hasConstrainedProperties;
+ }
+
+ /**
+ * Returns true if this interface is the first interface in the inheritance hierarchy
+ * to declare support for constrained properties. This is used to declared
+ * VetoableChangeListener registration methods for the bean once (and only once).
+ */
+ public boolean addsConstrainedPropertySupport()
+ {
+ //
+ // If a super interface has already added support, then not added here
+ //
+ if (_superClass != null && _superClass.addsConstrainedPropertySupport())
+ return false;
+
+ return hasConstrainedProperties();
}
/**
@@ -609,6 +659,8 @@
private AptControlInterface _superClass;
AptMethodSet<AptOperation> _operations;
ArrayList<AptPropertySet> _propertySets;
+ boolean _hasBoundProperties;
+ boolean _hasConstrainedProperties;;
ArrayList<AptEventSet> _eventSets;
ControlBean _bean;
FeatureInfo _featureInfo;
Modified: incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptProperty.java
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptProperty.java?view=diff&rev=109621&p1=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptProperty.java&r1=109620&p2=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptProperty.java&r2=109621
==============================================================================
--- incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptProperty.java (original)
+++ incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/AptProperty.java Thu Dec 2 18:54:09 2004
@@ -71,26 +71,29 @@
* Returns the base property name. The associated accessor methods will have the
* form set{name} and get{name}
*/
- public String getName()
+ public String getAccessorName()
{
StringBuffer sb = new StringBuffer();
sb.append(_propertySet.getPrefix());
- String memberName = getMemberName();
- sb.append(Character.toUpperCase(memberName.charAt(0)));
- if (memberName.length() > 0)
- sb.append(memberName.substring(1));
+ String name = getName();
+ sb.append(Character.toUpperCase(name.charAt(0)));
+ if (name.length() > 0)
+ sb.append(name.substring(1));
return sb.toString();
}
/**
- * Returns the member name associated with this Property in the PropertySet
+ * Returns the name associated with this Property in the PropertySet
*/
- public String getMemberName()
+ public String getName()
{
if ( _propDecl == null )
return "";
+ //
+ // Use the member name of the property method in the property set
+ //
return _propDecl.getSimpleName();
}
@@ -99,15 +102,7 @@
*/
public String getKeyName()
{
- return getName() + "Key";
- }
-
- /**
- * Returns true if the property needs a custom-generated PropertyDescriptor, false otherwise
- */
- public boolean needsCustomPropertyDescriptor()
- {
- return getPropertyInfo() != null || getFeatureInfo() != null;
+ return getAccessorName() + "Key";
}
/**
@@ -144,6 +139,41 @@
}
/**
+ * Returns any FeatureInfo associated with the property (or null if none)
+ */
+ public FeatureInfo getFeatureInfo()
+ {
+ if ( _propDecl == null )
+ return null;
+
+ return _propDecl.getAnnotation(FeatureInfo.class);
+ }
+
+ /**
+ * Returns 'true' is the property is a bound property that will support registration of
+ * a PropertyChangeListener for change notifications.
+ */
+ public boolean isBound()
+ {
+ //
+ // Constrained properties are implicitly bound. Refer to section 7.4.3 of the JavaBeans
+ // spec for the rationale.
+ //
+ PropertyInfo propInfo = getPropertyInfo();
+ return propInfo != null && (propInfo.bound() || propInfo.constrained());
+ }
+
+ /**
+ * Returns 'true' is the property is a constrained property that will support registration of
+ * a VetoableChangeListener for vetoable change notifications.
+ */
+ public boolean isConstrained()
+ {
+ PropertyInfo propInfo = getPropertyInfo();
+ return propInfo != null && propInfo.constrained();
+ }
+
+ /**
* Returns the class name of the property editor class, or null
*/
public String getEditorClass()
@@ -183,17 +213,6 @@
}
}
return null;
- }
-
- /**
- * Returns any FeatureInfo associated with the property (or null if none)
- */
- public FeatureInfo getFeatureInfo()
- {
- if ( _propDecl == null )
- return null;
-
- return _propDecl.getAnnotation(FeatureInfo.class);
}
AnnotationTypeElementDeclaration _propDecl;
Modified: incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBean.vm
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBean.vm?view=diff&rev=109621&p1=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBean.vm&r1=109620&p2=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBean.vm&r2=109621
==============================================================================
--- incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBean.vm (original)
+++ incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBean.vm Thu Dec 2 18:54:09 2004
@@ -167,24 +167,35 @@
## This macro defines the property accessor methods for a bean property
##
#macro (declarePropertyAccessors $property)
- public static PropertyKey $property.keyName = new PropertyKey(${property.propertySet.className}.class, "$property.memberName");
+ public static PropertyKey $property.keyName = new PropertyKey(${property.propertySet.className}.class, "$property.name");
#if ($property.isAnnotation())
- public void set${property.name}(PropertyMap map)
- {
- setControlProperty($property.keyName, map);
- }
+ public void set${property.accessorName}(PropertyMap value)
#else
- public void set${property.name}($property.type prop)
+ public void set${property.accessorName}($property.type value)
+ #end
+ #if ($property.constrained)
+ throws java.beans.PropertyVetoException
+ #end
{
- setControlProperty($property.keyName, prop);
+
+ #if ($property.bound || $property.constrained)
+ Object oldValue = getRawControlProperty($property.keyName);
+ #end
+
+ #if ($property.constrained)
+ fireVetoableChange($property.keyName, oldValue, value);
+ #end
+ setControlProperty($property.keyName, value);
+ #if ($property.bound)
+ firePropertyChange($property.keyName, oldValue, value);
+ #end
}
- #end
#if ($property.getType().equals("boolean"))
- public $property.type is${property.name}()
+ public $property.type is${property.accessorName}()
#else
- public $property.type get${property.name}()
+ public $property.type get${property.accessorName}()
#end
{
return (#toObject($property.type))getControlProperty($property.keyName);
@@ -192,6 +203,86 @@
#end
##
+## This macro declares the registration methods supporting a PropertyChangeListener
+##
+#macro (declareBoundPropertySupport)
+ /**
+ * Adds a new PropertyChangeListener for listening to changes on bound properties of this
+ * control.
+ */
+ public void addPropertyChangeListener(PropertyChangeListener pcl)
+ {
+ getPropertyChangeSupport().addPropertyChangeListener(pcl);
+ }
+
+ /**
+ * Adds a new PropertyChangeListener for listening to changes to a specific bound
+ * property of this control.
+ */
+ public void addPropertyChangeListener(String propertyName, PropertyChangeListener pcl)
+ {
+ getPropertyChangeSupport().addPropertyChangeListener(propertyName, pcl);
+ }
+
+ /**
+ * Removes a registered PropertyChangeListener listening to changes on bound properties of
+ * this control.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener pcl)
+ {
+ getPropertyChangeSupport().removePropertyChangeListener(pcl);
+ }
+
+ /**
+ * Removes a registered PropertyChangeListener listening to changes on a specific bound
+ * property of this control.
+ */
+ public void removePropertyChangeListener(String propertyName, PropertyChangeListener pcl)
+ {
+ getPropertyChangeSupport().removePropertyChangeListener(propertyName, pcl);
+ }
+#end
+##
+## This macro declares the registration methods supporting a VetoableChangeListener
+##
+#macro (declareConstrainedPropertySupport)
+ /**
+ * Adds a new PropertyChangeListener for listening to changes on bound properties of this
+ * control.
+ */
+ public void addVetoableChangeListener(VetoableChangeListener vcl)
+ {
+ getVetoableChangeSupport().addVetoableChangeListener(vcl);
+ }
+
+ /**
+ * Adds a new PropertyChangeListener for listening to changes to a specific constrained
+ * property of this control.
+ */
+ public void addVetoableChangeListener(String propertyName, VetoableChangeListener vcl)
+ {
+ getVetoableChangeSupport().addVetoableChangeListener(propertyName, vcl);
+ }
+
+ /**
+ * Removes a registered PropertyChangeListener listening to changes on constrained properties
+ * of this control.
+ */
+ public void removeVetoableChangeListener(VetoableChangeListener vcl)
+ {
+ getVetoableChangeSupport().removeVetoableChangeListener(vcl);
+ }
+
+ /**
+ * Removes a registered PropertyChangeListener listening to changes to a specific constrained
+ * property of this control.
+ */
+ public void removeVetoableChangeListener(String propertyName, VetoableChangeListener vcl)
+ {
+ getVetoableChangeSupport().removeVetoableChangeListener(propertyName, vcl);
+ }
+#end
+##
## This macro defines the implementation of an event routing method
##
#macro (declareEventImpl $event)
@@ -276,10 +367,13 @@
##
package $bean.package;
+import java.beans.*;
+
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashMap;
import java.util.Map;
+
import org.apache.beehive.controls.api.bean.Extensible;
import org.apache.beehive.controls.api.context.ControlBeanContext;
import org.apache.beehive.controls.api.properties.PropertyKey;
@@ -310,6 +404,14 @@
#foreach ($property in $propertySet.properties)
#declarePropertyAccessors ($property)
#end
+ #end
+
+ #if ($intf.addsBoundPropertySupport())
+ #declareBoundPropertySupport()
+ #end
+
+ #if ($intf.addsConstrainedPropertySupport())
+ #declareConstrainedPropertySupport()
#end
#foreach ($eventSet in $intf.eventSets)
Modified: incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm?view=diff&rev=109621&p1=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm&r1=109620&p2=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm&r2=109621
==============================================================================
--- incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm (original)
+++ incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm Thu Dec 2 18:54:09 2004
@@ -88,7 +88,7 @@
return bd;
}
- #if ($intf.needsCustomPropertyDescriptors())
+ #if ($intf.propertyCount != 0)
public PropertyDescriptor [] getPropertyDescriptors()
{
PropertyDescriptor [] propDescriptors = new PropertyDescriptor[$intf.propertyCount];
@@ -98,7 +98,7 @@
PropertyDescriptor pd;
#foreach ($propertySet in $intf.propertySets)
#foreach ($property in $propertySet.properties)
- pd = new PropertyDescriptor("$property.memberName", ${bean.className}.class);
+ pd = new PropertyDescriptor("$property.name", ${bean.className}.class);
#if ($property.propertyInfo)
pd.setBound($property.propertyInfo.bound());
pd.setConstrained($property.propertyInfo.constrained());
@@ -107,7 +107,7 @@
#end
#end
#if ($property.featureInfo)
- #initFeatureDescriptor("pd" $property.featureInfo $property.memberName)
+ #initFeatureDescriptor("pd" $property.featureInfo $property.name)
#end
propDescriptors[i++] = pd;
#end
Added: incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEvents.java
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEvents.java?view=auto&rev=109621
==============================================================================
--- (empty file)
+++ incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEvents.java Thu Dec 2 18:54:09 2004
@@ -0,0 +1,71 @@
+package org.apache.beehive.controls.test.controls.property;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.beans.PropertyChangeListener;
+import java.beans.VetoableChangeListener;
+
+import org.apache.beehive.controls.api.bean.ControlInterface;
+import org.apache.beehive.controls.api.packaging.PropertyInfo;
+import org.apache.beehive.controls.api.properties.PropertySet;
+import org.apache.beehive.controls.api.events.EventSet;
+
+/**
+ * A simple control that can be used for property testing of bound and constrained
+ * property event behavior.
+ */
+@ControlInterface
+public interface PropEvents
+{
+ //
+ // Declare a set of bound properties. These should deliver PropertyChange events
+ // if modified.
+ //
+ @PropertySet
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target( {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD} )
+ public @interface BoundProps
+ {
+ @PropertyInfo(bound=true)
+ public int boundInt() default 0;
+ }
+
+ //
+ // Declare a set of bound properties. These should deliver PropertyChange and
+ // VetoableChange events if modified.
+ //
+ @PropertySet
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target( {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD} )
+ public @interface ConstrainedProps
+ {
+ @PropertyInfo(constrained=true)
+ public int constrainedInt() default 0;
+
+ }
+
+ //
+ // Declared unbound and unconstrained events. These should deliver no events if
+ // modified.
+ //
+ @PropertySet
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target( {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD} )
+ public @interface BasicProps
+ {
+ public int basicInt() default 0;
+ }
+
+ //
+ // These EventSets are used as an external test point for events received by the
+ // implementation class
+ //
+ //@EventSet
+ //public interface PropertyChangeOnImpl extends PropertyChangeListener {}
+
+ //@EventSet
+ //public interface VetoableChangeOnImpl extends VetoableChangeListener {}
+}
Added: incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEventsImpl.jcs
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEventsImpl.jcs?view=auto&rev=109621
==============================================================================
--- (empty file)
+++ incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/property/PropEventsImpl.jcs Thu Dec 2 18:54:09 2004
@@ -0,0 +1,16 @@
+package org.apache.beehive.controls.test.controls.property;
+
+import org.apache.beehive.controls.api.bean.ControlImplementation;
+import org.apache.beehive.controls.api.context.Context;
+import org.apache.beehive.controls.api.context.ControlBeanContext;
+
+@ControlImplementation
+public class PropEventsImpl implements PropEvents
+{
+ static final long serialVersionUID = 1L;
+
+ @Context
+ ControlBeanContext context;
+
+ // Does nothing (for now)
+}
Added: incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/property/PropEvents.java
Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/property/PropEvents.java?view=auto&rev=109621
==============================================================================
--- (empty file)
+++ incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/property/PropEvents.java Thu Dec 2 18:54:09 2004
@@ -0,0 +1,293 @@
+package org.apache.beehive.controls.test.java.property;
+
+import java.beans.Beans;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.beehive.test.tools.mantis.annotations.tch.Freq;
+
+import org.apache.beehive.controls.api.bean.ControlBean;
+import org.apache.beehive.controls.test.controls.property.PropEventsBean;
+
+/**
+ * This test case validates bound and constrained property behaviors, w.r.t. to the delivery
+ * of PropertyChange events for bound and constrained events
+ */
+@Freq("checkin")
+public class PropEvents extends TestCase
+{
+ PropEventsBean eventBean;
+
+ public PropEvents( String s ) { super( s ); }
+
+ /**
+ * This base class hold a queue of property change events and makes them accessible
+ * for event validation.
+ */
+ abstract static class QueueListener
+ {
+ QueueListener()
+ {
+ initEvents();
+ }
+
+ /**
+ * Resets/initializes the internal event queue
+ */
+ public void initEvents()
+ {
+ eventQueue = new ArrayList<PropertyChangeEvent>();
+ }
+
+ /**
+ * Returns the collection of events
+ */
+ public Collection<PropertyChangeEvent> getEvents() { return eventQueue; }
+
+ ArrayList<PropertyChangeEvent> eventQueue;
+ }
+
+ static class ChangeTestListener extends QueueListener
+ implements java.beans.PropertyChangeListener
+ {
+ /**
+ * Implementation of PropertyChangeListener.propertyChange(). Will enqueue
+ * the received event.
+ */
+ public void propertyChange(PropertyChangeEvent pce)
+ {
+ eventQueue.add(pce);
+ }
+ }
+
+ static class VetoableTestListener extends QueueListener
+ implements java.beans.VetoableChangeListener
+ {
+ /**
+ * Implementation of PropertyChangeListener.propertyChange(). Will enqueue
+ * the received event.
+ */
+ public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException
+ {
+ eventQueue.add(pce);
+
+ // Veto attempts to set even values
+ if ((((Integer)pce.getNewValue()).intValue() & 1) == 0)
+ throw new PropertyVetoException("Sorry", pce);
+ }
+ }
+
+
+ public void setUp() throws Exception
+ {
+ eventBean = (PropEventsBean)
+ Beans.instantiate(Thread.currentThread().getContextClassLoader(),
+ "org.apache.beehive.controls.test.controls.property.PropEventsBean");
+ }
+
+ /**
+ * Basic test: setting/reading property values by a control client
+ */
+ public void testPropertyChange() throws Exception
+ {
+ // Set the test property to a well-defined initial value
+ eventBean.setBoundInt(0);
+
+ // Create a new test listener and register it on the test bean
+ ChangeTestListener ctl = new ChangeTestListener();
+ eventBean.addPropertyChangeListener(ctl);
+
+ // Call the bound property setter on the bean 100 times
+ for (int i = 1; i < 100; i++)
+ eventBean.setBoundInt(i);
+
+ // Now validate the received properties
+ int i = 0;
+ for (PropertyChangeEvent pce : ctl.getEvents())
+ {
+ if (pce.getSource() != eventBean)
+ fail("Invalid source value in PropertyChangeEvent");
+
+ if (!pce.getPropertyName().equals("boundInt"))
+ fail("Invalid property name: " + pce.getPropertyName());
+
+ if (!pce.getOldValue().equals(new Integer(i)))
+ fail("Unexpected old value: " + pce.getOldValue() + ", expected: " + i);
+
+ if (!pce.getNewValue().equals(new Integer(i+1)))
+ fail("Unexpected new value: " + pce.getNewValue() + ", expected: " + (i+1));
+
+ i++;
+ }
+ if (i != 99)
+ fail("Received less events than expected: " + i);
+
+ // Reset the event queue
+ ctl.initEvents();
+
+ // Change an unbound property and verify that no property change event was delivered
+ eventBean.setBasicInt(0);
+ if (ctl.getEvents().size() != 0)
+ fail("Unexpected event delivered on unbound property change");
+
+ // Remove the event listener, change a bound property, and verify no event is delivered
+ eventBean.removePropertyChangeListener(ctl);
+ eventBean.setBoundInt(0);
+ if (ctl.getEvents().size() != 0)
+ fail("Unexpected event delivered after listener removed");
+ }
+
+ /**
+ * Basic test: setting/reading property values by a control client
+ */
+ public void testVetoChange() throws Exception
+ {
+ // Set the test property to a well-defined initial value
+ eventBean.setConstrainedInt(0);
+
+ // Create a new test listener and register it on the test bean
+ VetoableTestListener vtl = new VetoableTestListener();
+ eventBean.addVetoableChangeListener(vtl);
+
+ // Create a change listener and register it... this will be used to validate the
+ // property changes that were not vetoed
+ ChangeTestListener ctl = new ChangeTestListener();
+ eventBean.addPropertyChangeListener(ctl);
+
+ // Call the bound property setter on the bean 100 times
+ int expected = 0;
+ for (int i = 1; i < 100; i++)
+ {
+ boolean vetoed = false;
+ boolean expectVeto = (i & 1) == 0;
+ try
+ {
+ eventBean.setConstrainedInt(i);
+ }
+ catch (PropertyVetoException pve)
+ {
+ vetoed = true;
+ }
+
+ if (vetoed)
+ {
+ if (!expectVeto)
+ fail("Unexpected PropertyVetoException: " + i);
+ }
+ else
+ {
+ if (expectVeto)
+ fail("Did not receive expected PropertVetoException: " + i);
+
+ expected = i;
+ }
+
+ //
+ // Read back the property and see if it was successfully changed or vetoed
+ if (eventBean.getConstrainedInt() != expected)
+ fail("Did not get expected value: " + expected + " for " + i);
+ }
+
+ // Now validate the received properties, there should be one per vetoed property,
+ // two per allowed change
+ int i = 1;
+ expected = 0;
+ boolean expectVeto = false;
+ Iterator<PropertyChangeEvent> changeIter = ctl.getEvents().iterator();
+ Iterator<PropertyChangeEvent> vetoIter = vtl.getEvents().iterator();
+ while(vetoIter.hasNext())
+ {
+ PropertyChangeEvent vce = vetoIter.next();
+
+ expectVeto = (i & 1) == 0;
+
+ if (vce.getSource() != eventBean)
+ fail("Invalid source value in PropertyChangeEvent");
+
+ if (!vce.getPropertyName().equals("constrainedInt"))
+ fail("Invalid property name: " + vce.getPropertyName());
+
+ if (!vce.getOldValue().equals(new Integer(expected)))
+ fail("Unexpected old value: " + vce.getOldValue() + ", expected: " + expected);
+
+ if (!vce.getNewValue().equals(new Integer(i)))
+ fail("Unexpected new value: " + vce.getNewValue() + ", expected: " + i);
+
+ if (expectVeto)
+ {
+ // If a veto occurred, then there should be a 2nd vetoable change event that
+ // goes from the vetoed value back to the last valid value
+ if (!vetoIter.hasNext())
+ fail("Did not find expected veto revert event");
+
+ //
+ // Pull the next event, which should revert from the attempted change back
+ // to the last accepted value
+ //
+ vce = vetoIter.next();
+ if (vce.getSource() != eventBean)
+ fail("Invalid source value in PropertyChangeEvent");
+
+ if (!vce.getPropertyName().equals("constrainedInt"))
+ fail("Invalid property name: " + vce.getPropertyName());
+
+ if (!vce.getOldValue().equals(new Integer(i)))
+ fail("Unexpected old value: " + vce.getOldValue() + ", expected: " + i);
+
+ if (!vce.getNewValue().equals(new Integer(expected)))
+ fail("Unexpected new value: " + vce.getNewValue() + ", expected: " + expected);
+ }
+ else
+ {
+ // Expected to succeed so look for the corresponding PropertyChange
+ if (!changeIter.hasNext())
+ fail("Missing PropertyChange event");
+
+ PropertyChangeEvent pce = changeIter.next();
+ if (pce.getSource() != eventBean)
+ fail("Invalid source value in PropertyChangeEvent");
+
+ if (!pce.getPropertyName().equals("constrainedInt"))
+ fail("Invalid property name: " + pce.getPropertyName());
+
+ if (!pce.getOldValue().equals(new Integer(expected)))
+ fail("Unexpected old value: " + pce.getOldValue() + ", expected: " + expected);
+
+ if (!pce.getNewValue().equals(new Integer(i)))
+ fail("Unexpected new value: " + pce.getNewValue() + ", expected: " + i);
+
+ expected = i;
+ }
+
+ i++;
+ }
+ if (expected != 99)
+ fail("Received less events than expected: " + expected);
+
+ // Reset the event queue
+ vtl.initEvents();
+ ctl.initEvents();
+
+ // Change an unbound property and verify that no property change event was delivered
+ eventBean.setBasicInt(0);
+ if (vtl.getEvents().size() != 0 || ctl.getEvents().size() != 0)
+ fail("Unexpected event delivered on unbound property change");
+
+ // Remove the veto event listener but not the change listener, change a constrained
+ // property, and verify no veto event is delivered but a change event is delivered
+ eventBean.removeVetoableChangeListener(vtl);
+ eventBean.setConstrainedInt(1);
+ if (vtl.getEvents().size() != 0)
+ fail("Unexpected event delivered after listener removed");
+ if (ctl.getEvents().size() != 1)
+ fail("Change event not delivered after listener removed");
+ }
+}