@(#)Property.txt 1.11
Proposal: Improved Property Management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Brian Burkhalter
Created: 13 July 2000
Revised: 12/18/00
CHANGES DURING COMMUNITY REVIEW
-------------------------------
. Added specification of PropertyChangeSupportJAI class.
PROPOSAL
--------
1. Motivation
This proposal arises in response to sundry requests for various changes to
the property management API provided in the first version of the JAI API
specification. In particular the following areas are of concern:
Retention of Property Name Case
The case of property names is not maintained by the API which
may lead to some confusion and loss of clarity and aesthetics.
Property Synchronization
Unlike image data the property data attached to an image rendered
from a node in an operation chain may change spontaneously after
the rendering has been generated.
Multiple Property Name Spaces
Only a single name space is provided for property names.
This is perceived as a limitation due to problems which could
could arise from property name collisions.
Property Specification Clarification
Some aspects of the API specification for property management are
unclear.
Following the next section each of these topics is addressed in the order
listed.
The use of the term "properties" in JAI could cause easily be confused with
properties as used with Java Beans. Properties of Java Beans are configurable
attributes of objects which are made available to adaptive code via
introspection. Properties in JAI usually represent meta-data of an image
such as regions of interest, coordinate systems, etc. In this proposal the
use of Java Bean type properties is added to JAI image classes and JAI
properties are linked into the Java Beans property model.
2. Fundamental Modifications
2.1 Java Bean-style Events
2.1.1 Define a Bean Event Base Class
Define to be used as the base class for all bean-style events generated by
JAI image objects.
package javax.media.jai;
import java.beans.PropertyChangeEvent;
/**
* A class instances of which represent Java Bean-style events emitted by
* JAI objects. This class definition adds no functionality to that provided
* by the superclass. The significance of the derivation is that bean events
* will be easily identifiable as having been generated by JAI classes by
* virtue of their being instances of this event class. Note that this does
* not prevent JAI properties from colliding with other Java Bean properties
* in the Bean property name space.
*
* @since Java Advanced Imaging 1.1
*/
public class PropertyChangeEventJAI extends PropertyChangeEvent {
/**
* Constructs a PropertyChangeEventJAI
.
* propertyName
is forced to lower case; all other
* parameters are passed unmodified to the superclass constructor.
* The original property name may be obtained by invoking
* getOriginalPropertyName()
.
*
* @exception NullPointerException if propertyName
is
* null
.
* @exception IllegalArgumentException if source
is
* null
or if oldValue
and
* newValue
are both null
.
*/
public PropertyChangeEventJAI(Object source,
String propertyName,
Object oldValue,
Object newValue) {}
/**
* Returns the value of propertyName
originally passed to
* the class constructor. This name has its case retained.
*/
public String getOriginalPropertyName() {}
}
Also define a utility class which forces property names to lower case and
allows retrieval of the property change event source:
/**
* Extension of the beans utility class PropertyChangeSupport
* which adds an accessor for the parameter passed to the constructor. All
* events fired by the firePropertyChange()
methods of this
* class are instances of PropertyChangeEventJAI
; consequently
* all property names are forced to lower case for recognition purposes.
* The property name-specific PropertyChangeListener
registration
* and unregistration methods defined in this class also force the supplied
* property name to lower case.
*
* @see PropertyChangeSupport
*
* @since 1.1
*/
public final class PropertyChangeSupportJAI extends PropertyChangeSupport {
/**
* The PropertyChangeEvent
source.
*/
protected Object propertyChangeEventSource;
/**
* Constructs a PropertyChangeSupportJAI
object. The
* parameter is cached for later use and retrieval.
*
* @param propertyChangeEventSource The property change event source.
* @throws If propertyChangeEventSource
is null
* then a NullPointerException
will be thrown
* in the superclass.
*/
public PropertyChangeSupportJAI(Object propertyChangeEventSource) {}
/**
* Retrieve the parameter passed to the constructor.
*
* @return The property change event source.
*/
public Object getPropertyChangeEventSource() {}
/**
* Add a PropertyChangeListener
for a specific property.
* The propertyName
is forced to lower case.
*
* @exception IllegalArgumentException if propertyName
is
* null
.
*/
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {}
/**
* Remove a PropertyChangeListener
for a specific property.
* The propertyName
is forced to lower case.
*
* @exception IllegalArgumentException if propertyName
is
* null
.
*/
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {}
/**
* Report a bound property update to any registered listeners.
* If the supplied object is not a PropertyChangeEventJAI
* then a PropertyChangeEventJAI
is constructed from the
* event object's accessors and fired instead.
*
* @param evt The PropertyChangeEvent
object.
*/
public void firePropertyChange(PropertyChangeEvent evt) {}
/**
* Report a bound property update to any registered listeners.
* A PropertyChangeEventJAI
is created from the cached
* property event source and the supplied parameters and fired using
* the superclass firePropertyChange(PropertyChangeEvent)
* method.
*
* @param propertyName The name of the changed property.
* @param oldValue The old value of the property.
* @param newValue The new value of the property.
*/
public void firePropertyChange(String propertyName,
Object oldValue, Object newValue) {}
/**
* Check whether there are any listeners for a specific property.
* The propertyName
is forced to lower case.
*
* @param propertyName The name of the property.
* @return true
if there are one or more listeners for
* the given property
*/
public synchronized boolean hasListeners(String propertyName) {}
}
2.1.2 Define a Class Linking JAI Properties and Java Beans Properties
Properties as defined in the context of Java Beans and as defined in JAI
are two entirely different entities. This class provides a construct linking
the two concepts.
package javax.media.jai;
/**
* A class instances of which represent JAI properties as emitted for
* example by a PropertySource
but in the guise of an event
* as defined for Java Beans. This class definition adds no functionality
* to that provided by the superclass per se. The significance of the
* derivation is that instances of this event by definition refer to properties
* in the JAI sense of the term. Otherwise put, this class provides an extra
* level of indirection.
*
* @see PropertyChangeEventJAI
* @see PropertySource
*
* @since Java Advanced Imaging 1.1
*/
public class PropertySourceChangeEvent extends PropertyChangeEventJAI {
/**
* Constructs a PropertySourceChangeEvent
.
* propertyName
is forced to lower case; all other
* parameters are passed unmodified to the superclass constructor.
* If oldValue
or newValue
is to indicate
* a property for which no value is defined, then the object
* java.awt.Image.UndefinedProperty
should be passed.
*
* @exception NullPointerException if propertyName
is
* null
.
* @exception IllegalArgumentException if source
,
* oldValue
or newValue
is
* null
.
*/
public PropertySourceChangeEvent(Object source,
String propertyName,
Object oldValue,
Object newValue) {}
}
2.2 Define an Interface for PropertyChangeListener Registration
/**
* A class which emits PropertyChangeEvent
s.
* This abstraction permits objects of disparate types to be recognized
* as sources of PropertyChangeEvent
s.
* PropertyChangeEvent
s emitted by JAI objects will be
* PropertyChangeEventJAI
instances.
*
*
Note that the case of property names used in this context is * significant. * * @see PropertyChangeEventJAI * * @since Java Advanced Imaging 1.1 */ public interface PropertyChangeEmitter { /** * Add a PropertyChangeListener to the listener list. The * listener is registered for all properties. */ void addPropertyChangeListener(PropertyChangeListener listener); /** * Add a PropertyChangeListener for a specific property. The * listener will be invoked only when a call on * firePropertyChange names that specific property. */ void addPropertyChangeListener(String propertyName, PropertyChangeListener listener); /** * Remove a PropertyChangeListener from the listener list. This * removes a PropertyChangeListener that was registered for all * properties. */ void removePropertyChangeListener(PropertyChangeListener listener); /** * Remove a PropertyChangeListener for a specific property. */ void removePropertyChangeListener(String propertyName, PropertyChangeListener listener); } 2.3 Modify PropertySource Interface Specification 2.3.1 Add comments to the class specification: *
If a PropertySource
is also a
* PropertyChangeEmitter
* then it should fire PropertySourceChangeEvent
s to all
* registered listeners whenever this is reasonable to do so in the context
* of the PropertySource
in question.
2.3.2 Add a method specification:
/**
* Returns the class expected to be returned by a request for
* the property with the specified name. If this information
* is unavailable, null
will be returned indicating
* that getProperty(propertyName).getClass()
should
* be executed instead. A null
value might
* be returned for example to prevent generating the value of
* a deferred property solely to obtain its class. null
* will also be returned if the requested property is not emitted
* by this property source.
*
* @param propertyName the name of the property, as a String
.
*
* @return The Class
expected to be return by a
* request for the value of this property or null
.
*
* @exception IllegalArgumentException if propertyName
* is null
.
*/
Class getPropertyClass(String propertyName);
This method may help in identifying the names of properties which return
values which are instances of a specific class.
All classes which implement PropertySource or ImageJAI will be modified to
implement this method.
2.4 Modify PropertyGenerator Interface Specification
Addition of the following methods enables the generic interface to accomodate
as yet unidentified operation node types or other objects for which properties
may be generated. All classes which implement or which use classes which
implement this interace will need to be modified accordingly.
2.4.1 Add Verifier
/**
* Determines whether the specified Object
will
* be recognized by getProperty(String,Object)
.
*
* @exception IllegalArgumentException if opNode
* is null
.
*/
boolean canGenerateProperties(Object opNode);
2.4.2 Add Property Class Accessor
/**
* Returns the class expected to be returned by a request for
* the property with the specified name. If this information
* is unavailable, null
will be returned indicating
* that getProperty(propertyName).getClass()
should
* be executed instead. A null
value might
* be returned for example to prevent generating the value of
* a deferred property solely to obtain its class.
*
* @return The Class
expected to be return by a
* request for the value of this property or null
.
* @exception IllegalArgumentException if propertyName
* is null
.
*/
Class getClass(String propertyName);
2.4.3 Add a Generic Property Accessor
/**
* Computes the value of a property relative to an environment
* of pre-existing properties. The case of the supplied
* String
is ignored.
*
*
In the case of an OperationNode
in a chain of
* operations these properties may be emitted by the sources of the
* node in a chain or the parameters of that operation. The information
* requisite to compute the requested property must be available via the
* supplied OperationNode
. It is legal to call
* getProperty()
on the operation's sources.
*
* @param name the name of the property, as a String
.
* @param op the Object
from which properties will
* be generated.
* @return the value of the property, as an Object
or the
* value java.awt.Image.UndefinedProperty
.
* @exception IllegalArgumentException if name
or
* opNode
is null
.
* @exception IllegalArgumentException if opNode
is
* not an instance of a supported class for this method, i.e.,
* canGenerateProperties(opNode)
returns
* false
.
*/
Object getProperty(String name, Object opNode);
The getProperty() methods which accept a RenderedOp or a RenderableOp as the
second parameter are deprecated as they will be redundant with the above.
2.5 Create WritablePropertySource Sub-Interface
Create a sub-interface of PropertySource in javax.media.jai:
/**
* Sub-interface of PropertySource
which permits setting
* the values of JAI properties in addition to obtaining their names
* and values. As the values of properties managed by classes which
* implement this interface may change, this is also a sub-interface
* of PropertyChangeEmitter
. This permits other objects
* to register as listeners of particular JAI properties.
*
*
The case of the names of properties added via this interface
* should be retained although the case will be ignored in queries via
* Implementing classes which should
* fire a If the property event utility object was not set at construction,
* then it will be initialized to a If the property event utility object was not set at construction,
* then it will be initialized to a If the property event utility object was not set at construction,
* then it will be initialized to a If the property event utility object was not set at construction,
* then it will be initialized to a Accessors and mutators of the critical attributes of the node
* are provided:
*
* Methods are also provided to modify the local property environment
* of the node. The global property environment is maintained by the
* associated A A This method does not validate the content of the supplied
* A A If the operation name changes as a result of calling this
* method, a If the registry changes as a result of calling this
* method, a This method does not validate the content of the supplied
* If the If the The interface includes the Property name space collisions may be prevented by adhering to
* an hierarchical naming convention. This could for example be based
* on the name of the package in question, e.g.,
* com.sun.media.jai.MyProperty.
* The names of properties generated by JAI itself will not adhere to the
* aforementioned naming convention, but this should not pose a problem if
* users adopt this convention for their own property names.
* Another approach to handling multiple property name spaces would
* be to define a separate PropertySource for each name space of properties.
* These PropertySources could themselves be attached to images as properties.
* Inheritance of these properties would occur by the default mechanism.
* Modification of these properties within an operation chain could be
* managed by PropertyGenerators which are capable of recognizing these
* properties. Note that a potential problem with this approach exists
* when a The operation name, sources, and The property environment of a The When a property value is requested an attempt will be made to derive
* it from the several entities in the following order of precedence:
* All dynamically computed properties of a The property environment of the When a property value is requested an attempt will be made to derive
* it from the several entities in the following order of precedence:
* The properties of a The property environment of a When a property value is requested an attempt will be made to derive
* it from the several entities in the following order of precedence:
* All dynamically computed properties of a getProperty()
and will be forced to lower case in
* emitted PropertySourceChangeEvent
.
*
* @see PropertySource
* @see PropertyChangeEmitter
*
* @since Java Advanced Imaging 1.1
*/
public interface WritablePropertySource
extends PropertySource, PropertyChangeEmitter {}
This sub-interface would add the following methods:
/**
* Adds the property value associated with the supplied name to
* the
WritablePropertySource
. Properties set by
* this means will supersede any properties of the same name
* which might otherwise be derived dynamically.
*
* PropertySourceChangeEvent
with a name set to
* that of the set property (retaining case), source set to the
*
WritablePropertySource
, and old and new values set to
* the previous and current values of the property, respectively.
* Neither the old nor the new value may null
: undefined
* properties must as usual be indicated by an the constant value
* java.awt.Image.UndefinedProperty
. It is however
* legal for either but not both of the old and new property values
* to equal java.awt.Image.UndefinedProperty
.
*
* @param propertyName the name of the property, as a String
.
* @param propertyValue the property, as a general Object
.
*
* @exception IllegalArgumentException if propertyName
* or propertyValue
* is null
.
*/
void setProperty(String propertyName, Object propertyValue);
/**
* Removes the named property from the WritablePropertySource
.
* This method will clear any locally cached (static) properties
* but may have no effect on properties which would be derived
* dynamically.
*
* @param propertyName the name of the property, as a String
.
* @param propertyValue the property, as a general Object
.
*
* @exception IllegalArgumentException if propertyName
* is null
.
*/
void removeProperty(String propertyName);
2.6 Implement PropertySource
Create a utility implementation of PropertySource. Note that the extant
package scope class of the same name will have to be renamed, e.g., to
"PropertyEnvironment".
2.6.1 Create a Utility Class for Property Name Handling
package javax.media.jai.util;
/**
* Class to use as the key in a java.util.Map
.
* The case of the name is maintained but the equals()
* method performs case-insensitive comparison.
*
* @see PropertySource
* @see java.util.Map
*
* @since Java Advanced Imaging 1.1
*/
public final class CaselessStringKey implements Cloneable, Serializable {
/**
* Creates a CaselessStringKey
for the given name.
* The parameter name
is stored by reference.
*
* @throws IllegalArgumentException if name
is
* null
.
*/
public CaselessStringKey(String name) {}
/**
* Returns a hash code value for the CaselessStringKey
.
*/
public int hashCode() {}
/**
* Returns the internal name by reference.
*/
public String getName() {}
/**
* Stores the parameter by reference in the internal name.
*
* @throws IllegalArgumentException if name
is
* null
.
*/
public void setName(String name) {}
/**
* Returns a clone of the CaselessStringKey
as an
* Object
.
*/
public Object clone() {}
/**
* Whether another Object
equals this one. This will obtain
* if and only if the parameter is non-null
and is a
* CaselessStringKey
whose lower case name equals the
* lower case name of this CaselessStringKey
.
*/
public boolean equals(Object o) {}
/**
* Returns the value returned by getName()
.
*/
public String toString() {}
}
2.6.2 Class Definition
package javax.media.jai;
import java.util.Map;
/**
* A utility implementation of the PropertySource
interface.
* Properties are managed by three internal structures: one which maps
* property names to values, a second which maps property names to
* PropertySource
s, and a third which tracks which entries
* in the name-value mapping derived their respective values from a
* PropertySource
in the name-PropertySource
* mapping. The case of property names is retained for subsequent
* retrieval but is ignored when the names are used as keys.
*
* @see CaselessStringKey
* @see PropertySource
* @see PropertySourceImpl
* @see WritablePropertySource
* @see WritablePropertySourceImpl
*
* @since Java Advanced Imaging 1.1
*/
public class PropertySourceImpl implements PropertySource, Serializable {
/**
* Mapping of CaselessStringKey
s to values.
* If this object is serialized, only those entries of which
* the value is serializable will be retained.
*/
protected transient Map properties;
/**
* Mapping of CaselessStringKey
s to
* PropertySource
s.
* If this object is serialized, only those entries of which
* the value is serializable will be retained.
*/
protected transient Map propertySources;
/**
* CaselessStringKey
s corresponding to the keys of entries
* in properties
which derived their respective
* values from a PropertySource
in
* propertySources
.
*/
protected Set cachedPropertyNames;
/**
* Constructs a PropertySourceImpl
instance with
* no properties set.
*/
protected PropertySourceImpl() {}
/**
* Constructs a PropertySourceImpl
instance which
* will derive properties from one or both of the supplied parameters.
* The propertyMap
and propertySource
parameters
* will be used to initialize the name-value and
* name-PropertySource
mappings, respectively.
* Entries in the propertyMap
object will be assumed
* to be properties if the key is a String
or a
* CaselessStringKey
. The propertySource
* object will be queried for the names of properties that it emits
* but requests for associated values will not be made at this time
* so as to to defer any calculation that such requests might provoke.
* The case of property names will be retained but will be ignored
* insofar as the name is used as a key to the property value.
*
* @param propertyMap A Map
from which to copy properties
* which have keys which are either String
s or
* CaselessStringKey
s.
* @param propertySource A PropertySource
from which to
* derive properties.
*
* @exception IllegalArgumentException if propertyMap
* and propertySource
are both null
* and this constructor is not being invoked from within a
* subclass constructor. When invoked from a subclass
* constructor both parameters may be null
.
*/
public PropertySourceImpl(Map propertyMap, PropertySource propertySource) {}
2.6.3 Add Convenience Method
/**
* Copies into a Map
all properties currently available
* via this PropertySource
. All property values are
* copied by reference rather than by being cloned. The keys in the
* Map
will be String
s with the original
* property name case intact. Property values derived from the
* name-value mapping will take precedence. The names of properties
* whose values are derived via the name-PropertySource
* mapping will be recorded as "cached properties".
*
* @return A Map
of all properties or null
if
* none are defined.
*/
public Map getProperties() {}
2.7 Implement WritablePropertySource
Create a utility implementation of WritablePropertySource. This
implementation will be synchronized and retain the case of all property names.
2.7.1 Class Definition
/**
* A utility implementation of the WritablePropertySource
* interface. The same internal superclass data structures are used and
* are supplemented by a PropertyChangeSupportJAI
to handle
* property event firing. All events fired by an instance of this class
* will be PropertySourceChangeEvent
s with an event source
* equal to the object used to create the PropertyChangeSupportJAI
* helper object. This object is user-specifiable at construction time or
* automatically created when a PropertyChangeListener
is
* added or removed and the PropertyChangeSupportJAI
specified
* at construction was null
.
*
* @see CaselessStringKey
* @see PropertySource
* @see PropertySourceChangeEvent
* @see PropertySourceImpl
* @see WritablePropertySource
* @see PropertyChangeEmitter
* @see PropertyChangeSupportJAI
*
* @since Java Advanced Imaging 1.1
*/
public class WritablePropertySourceImpl extends PropertySourceImpl
implements WritablePropertySource {
/**
* Helper object for bean-style property events. Its default
* value is null
which indicates that no events
* are to be fired.
*/
protected PropertyChangeSupportJAI manager = null;
/**
* Constructs a WritablePropertySourceImpl
instance with
* no properties set.
*/
public WritablePropertySourceImpl() {
super();
}
/**
* Constructs a WritablePropertySourceImpl
instance which
* will derive properties from one or both of the supplied parameters.
* The propertyMap
and propertySource
parameters
* will be used to initialize the name-value and
* name-PropertySource
mappings, respectively.
* Entries in the propertyMap
object will be assumed
* to be properties if the key is a String
or a
* CaselessStringKey
. The propertySource
* object will be queried for the names of properties that it emits
* but requests for associated values will not be made at this time
* so as to to defer any calculation that such requests might provoke.
* The case of property names will be retained but will be ignored
* insofar as the name is used as a key to the property value.
*
* @param propertyMap A Map
from which to copy properties
* which have keys which are either String
s or
* CaselessStringKey
s.
* @param propertySource A PropertySource
from which to
* derive properties.
* @param manager The object which will actually fire the events.
* May be null
in which case a default
* event manager will be created as needed with this
* object as its event source.
*/
public WritablePropertySourceImpl(Map propertyMap,
PropertySource source,
PropertyChangeSupportJAI manager) {}
2.7.2 Add Convenience Methods
Add these methods which are not defined in the interface:
/**
* Copies from the supplied Map
to the property set all
* entries wherein the key is an instance of String
* or CaselessStringKey
. Values set by this means will
* supersede any previously defined values of the respective properties.
* All property values are copied by reference.
* PropertySourceChangeEvent
s may be fired for each
* property added. If the property was not previously defined the
* old value of the property event will be
*
java.awt.Image.UndefinedProperty
.
*
* @param propertyMap A Map
from which to copy properties
* which have keys which are either String
s or
* CaselessStringKey
s. If null
no
* properties will be added.
*/
public void addProperties(Map propertyMap) {}
/**
* Adds a PropertySource
to the
* name-PropertySource
mapping. The
* actual property values are not requested at this time but instead
* an entry for the name of each property emitted by the
* PropertySource
is added to the
* name-PropertySource
mapping. Properties defined by
* this PropertySource
supersede those of all other
* previously added PropertySource
s including that
* specified at construction, if any. Note that this method will not
* provoke any events as no properties will actually have changed.
*
* @param propertySource A PropertySource
from which to
* derive properties. If null
nothing is done.
*/
public void addProperties(PropertySource propertySource) {}
/**
* Clears all properties from the PropertySource
by
* invoking removeProperty()
with all known names.
* PropertySourceChangeEvent
s may be fired
* for each stored property removed. In this case the new value
* of the property event will be
*
java.awt.Image.UndefinedProperty
.
*/
public void clearProperties() {}
/**
* Clears the name-value mapping of all properties.
* PropertySourceChangeEvent
s may be fired
* for each stored property removed. In this case the new value
* of the property event will be
*
java.awt.Image.UndefinedProperty
.
*/
public void clearPropertyMap() {}
/**
* Clears the name-PropertySource
mapping.
* No events will be fired.
*/
public void clearPropertySourceMap() {}
/**
* Clears from the name-value mapping all properties which were
* derived from a source in the name-PropertySource
mapping.
* PropertySourceChangeEvent
s may be fired
* for each stored property removed. In this case the new value
* of the property event will be
*
java.awt.Image.UndefinedProperty
.
*/
public void clearCachedProperties() {}
/**
* Removes from the name-PropertySource
mapping all entries
* which refer to the supplied PropertySource
.
*/
public void removePropertySource(PropertySource propertySource) {}
2.7.3 Add PropertyChangeEmitter Methods
/**
* Add a PropertyChangeListener
to the listener list. The
* listener is registered for all properties.
*
* PropertyChangeSupportJAI
* whose property event source is this object.
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {}
/**
* Add a PropertyChangeListener
for a specific property. The
* listener will be invoked only when a call on
* firePropertyChange names that specific property.
*
* PropertyChangeSupportJAI
* whose property event source is this object.
*/
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {}
/**
* Remove a PropertyChangeListener
from the listener list.
* This removes a PropertyChangeListener
that was registered
* for all properties.
*
* PropertyChangeSupportJAI
* whose property event source is this object.
*/
public void removePropertyChangeListener(PropertyChangeListener listener)
{}
/**
* Remove a PropertyChangeListener
for a specific property.
*
* PropertyChangeSupportJAI
* whose property event source is this object.
*/
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener)
{}
2.8 Define an Interface Representing Generic Operation Nodes
While this modification is more of a generic change to the core architecture
it is presented in the context of this proposal nonetheless.
2.8.1 OperationNode Interface Specification
/**
* A class which is a node in a chain of operations. This interface
* aggregates the minimal set of methods which would be expected to be
* implemented by such a class.
*
*
*
*
* Whether an implementing class maintains these critical attributes by
* reference or by copying or cloning is left to the discretion of the
* implementation.
*
* String
;
* OperationRegistry
to be used to resolve the
* operation name into an image factory which renders the node;
* ParameterBlock
; and
* OperationNode
s should fire a
* PropertyChangeEventJAI
when any of the critical attributes of
* the node is modified. These events should be named "OperationName",
* "OperationRegistry", "ParameterBlock", and "RenderingHints" corresponding
* to the respective critical attributes. Events named "Sources" and
* "Parameters" may instead be fired if it can be determined that a
*
ParameterBlock
modification has affected only the sources
* or parameters of the node, respectively. Nodes which implement convenience
* methods to edit individual node sources, parameters, or hints should
* still fire an event for the attribute as a whole. Note that this might
* require cloning the respective object. OperationNode
s are
* also required to fire PropertySourceChangeEvent
s by virtue
* of their being a PropertySource
as well as a
* PropertyChangeEmitter
.
*
* OperationRegistry
and used to initialize the
* local property environment. Methods are provided to:
*
*
*
*
* Invocation of these methods would not affect the global property
* environment of the operation as maintained by the
* PropertyGenerator
;
* OperationRegistry
.
*/
public interface OperationNode extends PropertySource, PropertyChangeEmitter {
/**
* Returns the name of the RegistryMode
corresponding to
* this OperationNode
. This value should be immutable
* for a given node.
*/
String getRegistryModeName();
/**
* Returns the name of the operation this node represents as
* a String
.
*/
String getOperationName();
/**
* Sets the name of the operation this node represents.
*
* PropertyChangeEventJAI
named "OperationName"
* should be fired with
* source equal to this node and old and new values set to the old
* and new values of the operation name, respectively.
*
* @param opName The new operation name to be set.
*
* @throws NullPointerException if
opName
is
* null
.
*/
void setOperationName(String opName);
/**
* Returns the OperationRegistry
that is used
* by this node. If the registry is not set, the default
* registry is returned.
*/
OperationRegistry getRegistry();
/**
* Sets the OperationRegistry
that is used by
* this node. If the specified registry is null
, the
* default registry is used.
*
* PropertyChangeEventJAI
named "OperationRegistry"
* should be fired with
* source equal to this node and old and new values set to the old
* and new values of the registry, respectively.
*
* @param registry The new
OperationRegistry
to be set;
* it may be null
.
*/
void setRegistry(OperationRegistry registry);
/**
* Returns the ParameterBlock
of this node.
*/
ParameterBlock getParameterBlock();
/**
* Sets the ParameterBlock
of this node. If the specified
* new ParameterBlock
is null
, it is assumed
* that this node has no input sources and parameters.
*
* ParameterBlock
. The caller should ensure that
* the sources and parameters in the ParameterBlock
* are suitable for the operation this node represents; otherwise
* some form of error or exception may occur at the time of rendering.
*
* PropertyChangeEventJAI
named "ParameterBlock"
* should be fired with
* source equal to this node and old and new values set to the old
* and new values of the
ParameterBlock
, respectively.
* A PropertyChangeEventJAI
named "Sources" or
* "Parameters" may instead be fired if it can be determined that the
*
ParameterBlock
modification has affected only the sources
* or parameters of the node, respectively.
*
* @param pb The new ParameterBlock
to be set;
* it may be null
.
*/
void setParameterBlock(ParameterBlock pb);
/**
* Returns the RenderingHints
of this node.
* It may be null
.
*/
RenderingHints getRenderingHints();
/**
* Sets the RenderingHints
of this node. It is legal
* for nodes to ignore RenderingHints
set on them by
* this mechanism.
*
* PropertyChangeEventJAI
named "RenderingHints"
* should be fired with
* source equal to this node and old and new values set to the old
* and new values of the hints, respectively.
*
* @param hints The new
RenderingHints
to be set;
* it may be null
.
*/
void setRenderingHints(RenderingHints hints);
/**
* Returns the property associated with the specified property name,
* or java.awt.Image.UndefinedProperty
if the specified
* property is not set on the image. This method is dynamic in the
* sense that subsequent invocations of this method on the same object
* may return different values as a function of changes in the property
* environment of the node, e.g., a change in which
* PropertyGenerator
s are registered or in the values
* associated with properties of node sources. The case of the property
* name passed to this method is ignored.
*
* @param name A String
naming the property.
*
* @throws IllegalArgumentException if
* name
is null
.
*/
Object getDynamicProperty(String name);
/**
* Adds a PropertyGenerator
to the node. The property values
* emitted by this property generator override any previous
* definitions.
*
* @param pg A PropertyGenerator
to be added to this node's
* property environment.
*
* @throws IllegalArgumentException if
* pg
is null
.
*/
void addPropertyGenerator(PropertyGenerator pg);
/**
* Forces a property to be copied from the specified source node.
* By default, a property is copied from the first source node
* that emits it. The result of specifying an invalid source is
* undefined.
*
* @param propertyName the name of the property to be copied.
* @param sourceIndex the index of the from which to copy the property.
* @throws IllegalArgumentException if propertyName
is
* null
.
*/
void copyPropertyFromSource(String propertyName,
int sourceIndex);
/**
* Removes a named property from the property environment of this
* node. Unless the property is stored locally either due
* to having been set explicitly or to having been cached for property
* synchronization purposes, subsequent calls to
* getProperty(name)
will return
* java.awt.Image.UndefinedProperty
, and name
* will not appear on the list of properties emitted by
* getPropertyNames()
.
*
* @param name A String
naming the property to be suppressed.
*
* @throws IllegalArgumentException if
* name
is null
.
*/
void suppressProperty(String name);
}
2.8.2 OperationNode Utility Class Specification
/**
* This is a utility class that can be used by OperationNode
s
* to consolidate common functionality. An instance of this class may be
* used as a member field of the OperationNode
and some of the
* OperationNode
's work delegated to it.
*/
public class OperationNodeSupport implements Serializable {
/**
* Constructs an OperationNodeSupport
instance.
* All parameters except opName
may be null
.
* If non-null
the PropertyChangeSupportJAI
* should have been created with the node as its event source (note
* that this cannot be verified).
*
* @param registryModeName The name of the registry mode concerned.
* @param opName The operation name to set.
* @param registry The OperationRegistry
to set;
* it may be null
in which case the registry will
* will be set to the default JAI registry.
* @param pb The ParameterBlock
to set;
* it may be null
.
* @param hints The new RenderingHints
to be set;
* it may be null
.
* @param eventManager The event helper object. The property change
* event source of this object should be the
* OperationNode
which is using the constructed
* OperationNodeSupport
instance. If null
* no events will be fired.
*
* @throws IllegalArgumentException if opName
is
* null
.
*/
public OperationNodeSupport(String registryModeName,
String opName,
OperationRegistry registry,
ParameterBlock pb,
RenderingHints hints,
PropertyChangeSupportJAI eventManager) {}
/**
* Returns the name of RegistryMode
corresponding to
* this OperationNode
. This value shoud be immutable
* for a given node. The value is returned by reference.
*/
public String getRegistryModeName() {}
/**
* Returns the name of the operation the associated node represents.
* The value is returned by reference.
*/
public String getOperationName() {}
/**
* Sets the name of the operation the associated node represents.
* The value is set by reference.
*
* PropertyChangeEventJAI
named "OperationName"
* will be fired by the event helper object with old and new values
* set to the old and new values of the operation name, respectively.
*
* @param opName The new operation name to be set.
*
* @throws IllegalArgumentException if
opName
is
* null
.
*/
public void setOperationName(String opName) {}
/**
* Returns the OperationRegistry
used by the associated
* node. The value is returned by reference.
*/
public OperationRegistry getRegistry() {}
/**
* Sets the OperationRegistry
that is used by the associated
* node. If the specified registry is null
, the
* registry will be set to the default JAI registry. The value is
* set by reference.
*
* PropertyChangeEventJAI
named "OperationRegistry"
* will be fired by the event helper object with old and new values
* set to the old and new values of the registry, respectively.
*
* @param registry The new
OperationRegistry
to be set;
* it may be null
.
*/
public void setRegistry(OperationRegistry registry) {}
/**
* Returns the ParameterBlock
of the associated node
* by reference. Nodes desirous of maintaining a consistent state
* for their ParameterBlock
may prefer to clone the
* value returned by this method.
*/
public ParameterBlock getParameterBlock() {}
/**
* Sets the ParameterBlock
of the associated node by
* reference. If the specified ParameterBlock
is
* null
, it is assumed that the associated node has
* neither input sources nor parameters. Nodes desirous of maintaining
* a consistent state for their ParameterBlock
may prefer
* to clone any user-supplied ParameterBlock
before passing
* it to this method.
*
* ParameterBlock
. The caller should ensure that
* the sources and parameters in the ParameterBlock
* are suitable for the operation the associated node represents; otherwise
* some form of error or exception may occur at the time of rendering.
*
* ParameterBlock
changes as a result of calling
* this method, a PropertyChangeEventJAI
named "ParameterBlock"
* will be fired by the event helper object with old and new values
* set to the old and new values of the
ParameterBlock
,
* respectively. A PropertyChangeEventJAI
named "Sources" or
* "Parameters" will instead be fired if it can be determined that the
*
ParameterBlock
modification has affected only the sources
* or parameters of the node, respectively.
*
* @param pb The new ParameterBlock
to be set;
* it may be null
.
*/
public void setParameterBlock(ParameterBlock pb) {}
/**
* Returns the RenderingHints
of the associated node
* by reference. Nodes desirous of maintaining a consistent state
* for their RenderingHints
may prefer to clone the
* value returned by this method.
*/
public RenderingHints getRenderingHints() {}
/**
* Sets the RenderingHints
of the associated node. It is
* legal for nodes to ignore RenderingHints
set on them by
* this mechanism. Nodes desirous of maintaining
* a consistent state for their RenderingHints
may prefer
* to clone any user-supplied RenderingHints
before passing
* it to this method.
*
* RenderingHints
changes as a result of calling
* this method, a PropertyChangeEventJAI
named "RenderingHints"
* will be fired by the event helper object with old and new values
* set to the old and new values of the
RenderingHints
,
* respectively.
*
* @param hints The new RenderingHints
to be set;
* it may be null
.
*/
public void setRenderingHints(RenderingHints hints) {}
/**
* Adds a PropertyGenerator
to the node. The property values
* emitted by this property generator override any previous definitions.
*
* @param pg A PropertyGenerator
to be added to the
* associated node's property environment.
*
* @throws IllegalArgumentException if
* pg
is null
.
*/
public void addPropertyGenerator(PropertyGenerator pg) {}
if(equals(this.hints, hints)) {
return;
}
fireEvent("RenderingHints", this.hints, hints);
this.hints = hints;
resetPropertyEnvironment(false);
}
/**
* Forces a property to be copied from the specified source node.
* By default, a property is copied from the first source node that
* that emits it. The result of specifying an invalid source is
* undefined.
*
* @param propertyName the name of the property to be copied.
* @param sourceIndex the index of the source to copy the property from.
* @throws IllegalArgumentException if propertyName is null.
*/
public void copyPropertyFromSource(String propertyName,
int sourceIndex) {}
if(equals(this.hints, hints)) {
return;
}
fireEvent("RenderingHints", this.hints, hints);
this.hints = hints;
resetPropertyEnvironment(false);
}
/**
* Removes a named property from the property environment of the
* associated node. Unless the property is stored locally either due
* to having been set explicitly or to having been cached for property
* synchronization purposes, subsequent calls to
* getProperty(name)
will return
* java.awt.Image.UndefinedProperty
, and name
* will not appear on the list of properties emitted by
* getPropertyNames()
.
*
* @param name A String
naming the property to be suppressed.
*
* @throws IllegalArgumentException if
* name
is null
.
*/
public void suppressProperty(String name) {}
if(equals(this.hints, hints)) {
return;
}
fireEvent("RenderingHints", this.hints, hints);
this.hints = hints;
resetPropertyEnvironment(false);
}
/**
* Constructs and returns a PropertySource
suitable for
* use by the specified OperationNode
. The
* PropertySource
includes the global property environment
* as managed by the OperationRegistry
for the
* corresponding operation. Prior and subsequent modifications to the
* local property environment made via this object will be reflected
* in the returned PropertySource
.
*
* @param op the OperationNode
requesting its
* PropertySource
.
* @param defaultPS a PropertySource
to be used to derive
* property values if and only if they would otherwise be
* derived by inheritance from a source rather than from a
* a PropertyGenerator
or a copy-from-source
* directive.
* @throws NullPointerException if op is null.
*/
public PropertySource getPropertySource(OperationNode opNode,
PropertySource defaultPS) {}
/**
* Resets the property environment. The list of local property
* environment modifications made directly on this object is reset
* if and only if the parameter is true
.
*
* @param resetLocalEnvironment Whether to clear the list of property
* environment changes made directly on this object.
*/
public void resetPropertyEnvironment(boolean resetLocalEnvironment) {}
}
2.9 ImageJAI
Modify the definition of ImageJAI to extend WritablePropertySource instead
of PropertySource. All classes which implement ImageJAI will have to add
the new methods defined for WritablePropertySource. These will be discussed
later but include PlanarImage, CollectionImage, and ImageMIPMap. (The classes
RenderableOp, MultiResolutionRenderableImage, and RenderableImageAdapter
should also be made to implement WritablePropertySource.)
2.9 Rendered Class Modifications
2.9.1 PlanarImage
2.9.1.1 Change Class Defnition
Implement WritablePropertySource in addition to the other interfaces.
2.9.1.2 Conform to WritablePropertySource Specification
* Implement getClass(name).
* Change setProperty() to return a boolean value.
(This should have no effect on API users as it previously returned
nothing, i.e., was void.)
* Implement removeProperty().
* Modify internals of getProperties() and setProperties().
2.9.1.3 Improve Property Encapsulation
The instance variable
protected Hashtable properties;
will be replaced with a protected instance variable to handle properties:
/** A helper object to manage the image properties. */
protected WritablePropertySourceImpl properties = null;
Subclasses might have to override the PlanarImage implementation of
WritablePropertySource methods to obtain desired property behavior.
2.9.1.4 Implement PropertyChangeEmitter
Enable a java.beans.PropertyChangeListener to monitor image properties in
the JAI sense of the term. If any PropertyChangeListeners are registered with
the PlanarImage when one of its properties changes, a PropertyChangeEventJAI
will be fired which will have as its source the PlanarImage object, a
propertyName set to the name of the image property in question, and old and
new values equal to the previous and current values of the image property.
Either the old or the new values may be null.
The PropertyChangeEmitter interface methods will likely be implemented using
a protected variable which is an instance of the utility class
java.beans.PropertyChangeSupport.
2.9.2 RenderedOp
2.9.2.1 Improve Property Encapsulation
Internal modification: change RenderedOp to use the property accessors and
mutators instead of dereferencing the inherited properties Hashtable.
2.9.2.2 Implement OperationNode
The internal implementation will be revised to utilize an instance of the
utility class OperationNodeSupport in conjunction with the inherited
PropertyChangeSupport variable.
2.10 Renderable Class Modifications
2.10.1 RenderableOp
2.10.1.1 Change Class Definition
Make RenderableOp implement ImageJAI instead of PropertySource:
* Implement getClass(name).
* Change setProperty() to return a boolean value.
(This should have no effect on API users as it previously returned
nothing, i.e., was void.)
* Implement removeProperty().
2.10.1.2 Implement PropertyChangeEmitter
Make modifications like those made for PlanarImage.
2.10.1.3 Implement OperationNode
Make modifications like those made for RenderedOp.
Note that currently no RenderingHints are stored in a node. If a cache of
hints were added to the node it could be used in the manner of the hints
stored in each instance of the JAI class: hints stored in the node would
be "merged" with any passed in when one of the createRendering() methods
was invoked. Hints passed in to the method would, as with JAI.create(),
take precedence.
2.10.2 MultiResolutionRenderableImage
Implement ImageJAI. Will require implementing WritablePropertySource.
2.10.3 RenderableImageAdapter
Implement ImageJAI instead of PropertySource. Will require implementing
methods in WritablePropertySource and not in PropertySource.
2.11 Miscellaneous Class Modifications
2.11.1 Collection Class Modifications
The JAI Collection architecture specifies very limited property management
capabilities. This topic will be addressed in greater detail in a separate
proposal dealing with the JAI CollectionImage architecture in general.
The following changes should be made:
* CollectionImage should implement WritablePropertySource methods not in
PropertySource.
* CollectionImage should implement PropertyChangeEmitter like PlanarImage.
* CollectionOp should implement OperationNode like RenderedOp.
2.11.2 Other Modifications
ImageMIPMap should implement ImageJAI.
3. Retention of Property Name Case
Property names are currently case-insensitive in terms of property queries
via the getProperty() method of the PropertyGenerator() and PropertySource()
interfaces. All properties stored via setProperty() have their names forced
to lower case. As a result invoking getPropertyNames() will return different
names from those passed to setProperty() if any upper case characters were
used.
The property mechanism will be modified so that the storage of property names
is case-retentive instead of case-insensitive. This means that when property
values are stored or retrieved the case of the property names will be ignored
insofar as the name is used as a key for the property value but that
getPropertyNames() will return the property name strings as they were
originally specified either by a call to setProperty() or by the
PropertyGenerator (or by whatever originally set the name, e.g., on an
externally generated RenderedImage).
The required modifications will be to all implementations of PropertySource
as well as to the OperationRegistry.
4. Property Synchronization
In the current implementation of JAI if the value of a property at a given
node depends on the value of one or more properties of the sources of the
node then the value of the destination property may change if the value of
any of the source properties on which it depends changes. For example, if
the source node of a unary geometric operation has an ROI property set on
it then the default behavior is to warp the ROI using the geometric mapping
applied to transform the image. If the source ROI changes between distinct
invocations of getProperty("ROI") on the destination node then different
destination ROIs will be returned. This behavior is inconsistent with the
synchronous behavior of image data computation.
One method of synchronizing the property value would be to cache it locally
once it is computed. When a property value is requested from a node of
whatever type, the locally cached properties always take precedence over
those which are calculated dynamically or inherited from source images.
4.1 RenderedOp
4.1.1 Locally Cache Dynamic Properties
The property value on a RenderedOp would be synchronized by caching all
dynamically generated properties via the superclass setProperty() method.
This would involve a trivial modification of the source code of the
getProperty() method.
4.1.2 Response to RenderingChangeEvents
When a rendering needs to be cleared in response to a RenderingChangeEvent
as described in "Support for Editing Rendered Op Chains", all properties
which were not "manually" set on the node by user invocation of setProperty()
should be cleared. To enable RenderedOp to respond to events in this fashion,
setProperty() will be modified to store the names of all properties which
were set by invoking setProperty() on the RenderedOp. Any locally cached
properties the (lower case) names of which are not in this set will be cleared
in response to a RenderingChangeEvent which completely clears the rendering
of the node.
4.2 RenderableOp
Property values would be cached as in RenderedOp.
4.3 CollectionOp
Collection operator nodes currently do not support any type of dynamic
property management. This capability will be added. As previously noted,
this topic will be addressed in greater detail in a separate proposal.
4.4 Dynamic Properties
To enable retrieval of properties the values of which change in response to
changes in their property environment OperationNode defines the method
getDynamicProperty().
This method will not return any property which is stored in the local cache
of properties unless the property was set by an invocation of setProperty()
on the node. Locally cached properties not stored due a setProperty() call
would have been generated dynamically in a property environment which may
be different from that at the time of invocation of this method.
5. Multiple Property Name Spaces
No specific modifications will be made directly to handle multiple name
spaces for image properties. This problem should however be able to be
addressed indirectly using existing and proposed capabilities of JAI.
5.1 Hierarchical Name Space Convention
Property name space collisions could be prevented if all property names
were generated in adherence to an hierarchical naming convention. This
could for example be based on the package name of the core package which
generates the properties.
The names generated by JAI itself will not adhere to the aforementioned
naming convention, but this should not pose a problem if users adopt this
convention for their own property names.
5.2 PropertySources as Properties
Another method of handling multiple property name spaces would be to define a
separate PropertySource for each name space of properties. These
PropertySources could themselves be attached to images as properties.
Inheritance of these properties would occur by the default mechanism.
Modification of these properties within an operation chain could be
managed by PropertyGenerators which are capable of recognizing these
properties. The proposed convenience classes PropertySourceImpl and
WritablePropertySourceImpl should aid in the implementation of objects
to represent alternate name spaces.
6. Property Specification Clarification
The documentation changes described in this section will be added in an
attempt to clarify the specification.
6.1 PropertySource
Replace related sections of class description with the following:
* getProperty()
and
* getPropertyNames()
methods familiar from the
* RenderedImage
and RenderableImage
interfaces.
* Classes which implement this interface should do so in a manner which
* treats the property names as case-retentive. That is to say that as
* concerns operations effected using the property name as a key, the
* operation should ignore the case of the property name while on the
* other hand the property name retrieval methods should return the names
* with their case preserved.
*
* PropertySource
is implemented by the ImageJAI
* interface and, among other classes, by PlanarImage
,
* RenderableOp
and CollectionImage
.
* Since all RenderedImage
s used with JAI are "wrapped"
* by a RenderedImageAdapter
, all JAI RenderedImage
s
* may be assumed to implement PropertySource
.
Add comments related to multiple name spaces:
* PropertySourceChangeEvent
is fired: it might be
* necessary to clone the entire tree of properties in order to obtain
* the old value of event object.
6.2 PropertyGenerator
Comments for getPropertyNames():
* Returns an array of String
s naming properties emitted
* by this property generator. The String
s may contain
* characters of any case.
Comments for getProperty(String,RenderedOp):
* Computes the value of a property relative to an environment
* of pre-existing properties emitted by the sources of
* a RenderedOp
, and the parameters of that operation.
Comments for getProperty(String,RenderableOp):
* Computes the value of a property relative to an environment
* of pre-existing properties emitted by the sources of
* a RenderableOp
, and the parameters of that operation.
*
* ParameterBlock
* of the RenderableOp
being processed may be obtained by
* means of the op.getOperationName
,
* op.getSources()
, and op.getParameterBlock()
* methods. It is legal to call getProperty()
on the
* operation's sources.
6.3 OperationRegistry
This section has been superseded by the OperationRegistry proposal.
6.4 RenderedOp
Class comments:
* RenderedOp
is initially
* derived from that of the corresponding OperationDescriptor
* as maintained by the OperationRegistry
. It may be modified
* locally by adding PropertyGenerator
s, directives to copy
* certain properties from specific sources, or requests to suppress certain
* properties. These modifications per se cannot be undone directly but
* may be eliminated as a side effect of other changes to the node as
* described below.
*
* RenderedOp
itself synthesizes several property values,
* which may neither be set nor removed. These are: image_width
,
* image_height
, image_min_x_coord
, and
* image_min_y_coord
. These properties are referred to as
* synthetic properties.
*
*
*
* Local properties are those which have been cached locally either by virtue
* of direct invocation of PropertyGenerator
s, or
*
a source specified via a copy-from-source directive;setProperty()
or due to caching of a
* property derived from the property environment.
*
* RenderedOp
which
* have been cached locally, i.e., those cached properties which were not set
* by an explicit call to setProperty()
, will be cleared when any
* of the critical attributes of the node is edited. By implication these
* properties will also be cleared when a RenderingChangeEvent
* is received from any node source.
6.5 RenderableOp
Class comments:
* RenderableOp
is initially
* derived from that of the corresponding OperationDescriptor
* as maintained by the OperationRegistry
. It may be modified
* locally by adding a PropertyGenerator
or by suppressing a
* specific property. These modifications cannot be undone.
*
*
*
* Local properties are those which have been cached locally either by virtue
* of direct invocation of PropertyGenerator
s, or
*
a source specified via a copy-from-source directive;setProperty()
or due to caching of a
* property derived from the property environment.
*
* RenderableOp
node are copied to each
* rendering generated by any of the createRendering()
methods.
* Properties already set on the rendering are not copied, i.e., those of the
* rendering take precedence.
6.6 CollectionOp
The following comments would be equally a propos in the proposal "Image
Collection API Modifications" but are included here in the context of the
previous similar comment modifications.
Class comments:
* CollectionOp
is initially
* derived from that of the corresponding OperationDescriptor
* as maintained by the OperationRegistry
. It may be modified
* locally by adding PropertyGenerator
s, directives to copy
* certain properties from specific sources, or requests to suppress certain
* properties. These modifications per se cannot be undone directly but
* may be eliminated as a side effect of other changes to the node as
* described below.
*
*
*
* Local properties are those which have been cached locally either by virtue
* of direct invocation of PropertyGenerator
s, or
*
a source specified via a copy-from-source directive;setProperty()
or due to caching of a
* property derived from the property environment.
*
* CollectionOp
which
* have been cached locally, i.e., those cached properties which were not set
* by an explicit call to setProperty()
, will be cleared when any
* of the critical attributes of the node is edited. By implication these
* properties will also be cleared when a CollectionChangeEvent
* is received from any node source.