com.inline.feature.common
Class AbstractFeature

java.lang.Object
  |
  +--com.inline.feature.common.AbstractResourceListener
        |
        +--com.inline.feature.common.AbstractFeature
Direct Known Subclasses:
JavaClassFeature, JavaFieldFeature, JavaFileFeature, JavaMethodFeature, JavaRootFeature

public abstract class AbstractFeature
extends AbstractResourceListener
implements Feature

AbstractFeature is the recommended superclass of all feature classes. It introduces several methods that can be overridden by subclasses to add concrete functionality to the feature implementation.

Properties
Most features have properties, which reflect the state of the resources the feature represents. For example, if the feature represents a Java field, the likely properties will be "fieldName", "fieldType", etc. In implementing a property you need to follow several rules. Let's say the name of the property is "bar" and it is a String.

Managed Properties
If managing the value of the property is expensive, you may want to use the notion of a managed property. Managed properties are handled individually. They are parsed separately and the application of changes will skip the managed properties that have not changed. The implementation rules for a managed property are slightly different from a regular one.

Note that managed properties can sometimes be more expensive because they are managed individually and that takes cycles. Another drawback is that there is no way of knowing when a property has changed without looking at it its value. This is why the refresh() method of a feature that has managed properties will call firePropertyChange(null, null, null) to indicate that they may have changed. So use managed properties with caution.


Fields inherited from class com.inline.feature.common.AbstractResourceListener
active, featureModel, parent, resourceAdapters, resourceSetAdapters, revalidate
 
Constructor Summary
AbstractFeature(FeatureModel featureModel)
          This constructor should be used exclusively by root features
AbstractFeature(Feature parent, java.lang.String signature)
           
 
Method Summary
protected  void activate()
          Feature is activated when the first object registers to listen to property change events on this feature.
protected  void addManagedProperty(java.lang.String property)
          Called from the feature's constructor to register a managed property.
protected  void addMessages(java.lang.String messageType, com.sun.java.util.collections.List messages)
          Override this method to produce FeatureMessages.
 void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
          Registers the listener and calls activate() if this is the first listener.
protected  void applyChanges()
          Override to apply changes made to the feature's properties permanent.
 boolean canChange(java.lang.String property)
          By default this method returns true.
 boolean canDelete()
          Returns true if the feature can be removed.
 void commit()
          Commits all changes to the underlying resources.
protected  void delete()
          Override to remove feature from persistent resources.
protected  void firePropertyChange(java.lang.String property, boolean oldValue, boolean newValue)
          A version of firePropertyChange that takes two booleans.
protected  void firePropertyChange(java.lang.String property, java.lang.Object oldValue, java.lang.Object newValue)
          Call this method from all setBar methods on the feature.
 com.sun.java.util.collections.Set getActions()
          Combines actions returned by getPrimitiveActions, getChildSetActions and model.getAdditionalActions(this).
 FeatureSet getChildren()
          Returns a set of all direct child features of this feature.
protected  com.sun.java.util.collections.Set getChildSetActions()
          The default implementation of this method calls getChildren().getFeatureConstructors() For each constructor, it creates an AddFeatureAction and returns a list of those.
 DisplayProperties getDisplayProperties()
          DisplayProperties are used by the UI to configure how this displayable object is displayed.
 java.lang.String getDisplayType()
          Display type is used to link this feature to its display properties.
 com.sun.java.util.collections.List getMessages(java.lang.String messageType)
          The default implementation creates an empty list and calls addMessages(messageType, list).
protected  com.sun.java.util.collections.Set getPrimitiveActions()
          Override this method to define actions that are native to the feature.
 java.lang.String getSignature()
          Returns the signature given to this feature as a parameter of the constructor.
 java.net.URL getURL()
          Creates a URL following this syntax:
protected  void insert()
          Override to make the feature persistent.
 void invalidate()
          Marks the feature as invalid, which will force the property parsing the next time refresh() is called.
 boolean isMarkedForDeletion()
          Has markForDeletion() been called?
 boolean isModified()
          Has this feature been modified since the last refresh/commit?
protected  boolean isModified(java.lang.String property)
          Has this managed property been modified?
 boolean isNew()
          Is this a newly created, uncommitted feature?
 void markForDeletion()
          Marks the feature for deletion.
protected  void parseSignature(java.lang.String signature)
          Override this to extract some of the feature properties from the signature.
protected  void propertyChanged(java.lang.String property, java.lang.Object oldValue, java.lang.Object newValue)
          Override this method if you want to be notified when a property of this feature changes (that means actually changes its value).
protected  void refresh()
          Populates the feature state according to the resource state.
protected  void refresh(java.lang.String property)
          Call this method to refresh an individual managed property.
protected  void refreshProperties()
          Override to parse resources.
protected  void refreshProperty(java.lang.String property)
          The overloaded implementation of this method should refresh the value of the specified managed property.
 void release()
          Unregisters from all ResourceAdapters and ResourceSetAdapters and forwards the release() message to the child FeatureSet.
 void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
          Unregisters the listener and calls passivate() if this was the last listener.
 java.lang.String toString()
           
 java.lang.String toStringVerbose()
          You can override this method to provide a verbose description of this feature's properties for debugging purposes.
 void validateChanges()
          Calls validateChanges(List) with an empty list.
protected  boolean validateChanges(com.sun.java.util.collections.List list)
          Override to produce validations for the feature.
 
Methods inherited from class com.inline.feature.common.AbstractResourceListener
getFeatureModel, getParent, passivate, propertyChange, registerDependencies, registerResourceAdapter, registerResourceAdapter, registerResourceSetAdapter, registerResourceSetAdapter, resourceAdded, resourceChanged, resourceRemoved, unregisterResourceAdapter, unregisterResourceSetAdapter
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

AbstractFeature

public AbstractFeature(Feature parent,
                       java.lang.String signature)
Parameters:
parent - is the parent feature of this feature
signature - is the feature's signature. It cannot change. It can be null for newly created features.

AbstractFeature

public AbstractFeature(FeatureModel featureModel)
This constructor should be used exclusively by root features
Method Detail

getURL

public java.net.URL getURL()
Creates a URL following this syntax:
     feature:type:signature
  
or, if the signature is null,
     feature:type
  
The implementation of this method provided by the AbstractFeature constructs a URL by combining results of getType() and getSignature().
Specified by:
getURL in interface Feature

getDisplayType

public java.lang.String getDisplayType()
Display type is used to link this feature to its display properties. The AbstractFeature's implementation simply returns getType().

getDisplayProperties

public DisplayProperties getDisplayProperties()
DisplayProperties are used by the UI to configure how this displayable object is displayed.

AbstractFeature's implementation calls getDisplayProperties(this) on the feature model, thus making the displayable loosely bound to its display properties. The idea is to allow alternative sets of display properties for the same object. The choice between those alternatives is made by feature model and ultimately by DisplayPropertyFactories based the displayable instance and on properties of the model.

Tags copied from interface: Displayable
See Also:
DisplayPropertyFactory, FeatureModel.getDisplayProperties(Displayable)

getSignature

public java.lang.String getSignature()
Returns the signature given to this feature as a parameter of the constructor. Since signature is passed to the feature at allocation time, it is usually (but not always) convenient to make the signature bear the additional responsibility of identifying the elements of persistent resources that are represented by the feature. For example, if "com.acme.MyClass//foo" is the signature of a JavaFieldFeature, the feature could use the parts of the signature (class name and field name) to lookup the class descriptor and field descriptor on it. Note that this additional usage of signature is merely a convenience, not a requirement.
Specified by:
getSignature in interface Feature

parseSignature

protected void parseSignature(java.lang.String signature)
Override this to extract some of the feature properties from the signature. If the signature is not carrying any of those properties, there is no need to override this method.

getChildren

public FeatureSet getChildren()
Returns a set of all direct child features of this feature. The implementation of the FeatureSet used here aggregates feature sets for individual feature types. This structure is opaque to the client.
Specified by:
getChildren in interface Feature

addManagedProperty

protected void addManagedProperty(java.lang.String property)
Called from the feature's constructor to register a managed property.

isModified

public boolean isModified()
Has this feature been modified since the last refresh/commit?

isModified

protected boolean isModified(java.lang.String property)
Has this managed property been modified?

isNew

public boolean isNew()
Is this a newly created, uncommitted feature?
Specified by:
isNew in interface Feature

isMarkedForDeletion

public boolean isMarkedForDeletion()
Has markForDeletion() been called?
Specified by:
isMarkedForDeletion in interface Feature

getMessages

public com.sun.java.util.collections.List getMessages(java.lang.String messageType)
The default implementation creates an empty list and calls addMessages(messageType, list).
Specified by:
getMessages in interface Feature
Tags copied from interface: Feature
See Also:
FeatureMessage

addMessages

protected void addMessages(java.lang.String messageType,
                           com.sun.java.util.collections.List messages)
Override this method to produce FeatureMessages. Just add them to the supplied list. Do not forget to call super.addMessages() first.

canChange

public boolean canChange(java.lang.String property)
By default this method returns true. Override it to provide logic that determines whether or not a particular property is editable.
Specified by:
canChange in interface Feature

getActions

public com.sun.java.util.collections.Set getActions()
Combines actions returned by getPrimitiveActions, getChildSetActions and model.getAdditionalActions(this).
Specified by:
getActions in interface Feature
See Also:
getPrimitiveActions(), getChildSetActions(), FeatureModel.getAdditionalActions(Feature)

getPrimitiveActions

protected com.sun.java.util.collections.Set getPrimitiveActions()
Override this method to define actions that are native to the feature. The default implementation returns exactly one action: RemoveFeatureAction.

getChildSetActions

protected com.sun.java.util.collections.Set getChildSetActions()
The default implementation of this method calls getChildren().getFeatureConstructors() For each constructor, it creates an AddFeatureAction and returns a list of those. If a constructor returns false to isAddFeatureActionAllowed(), the corresponding action is not included in the set. Override this method to extend/reduce the set of actions produced for the child feature set.

refresh

protected void refresh()
Populates the feature state according to the resource state. The implementation calls registerDependencies(), then parseSignature(), then refreshProperties(). Then the feature is marked as unchanged and validated.

All these operations are only performed under the following conditions:

  • Method is called the first time or after the feature is invalidated explicitly or by a resource change event
  • The feature is not new and not marked for deletion
  • The call is not recursive

refresh

protected void refresh(java.lang.String property)
Call this method to refresh an individual managed property.

refreshProperties

protected void refreshProperties()
Override to parse resources. This method is invoked by refresh(). The registerDependencies method is called prior to refreshProperties, therefore the registered resource adapters and resource set adapters can be used by this method. parseSignature() is also called before refreshProperties.

The implementation of refreshProperties should call setBar() methods to set the feature properties. This way observers of the feature will be informed whenever conseqent executions of refresh produce different property values.

The method should re-acquire resources from resource adapters. Note that a resource adapter may return a different instance of resource when invoked from consequent refreshProperties() calls.


refreshProperty

protected void refreshProperty(java.lang.String property)
The overloaded implementation of this method should refresh the value of the specified managed property. Note that even if all properties of the feature are managed, refreshProperties() will be called anyway prior to any refreshProperty(property) calls.

canDelete

public boolean canDelete()
Returns true if the feature can be removed. The default implementation simply returns true.
Specified by:
canDelete in interface Feature

markForDeletion

public void markForDeletion()
Marks the feature for deletion. A subsequent commit will invoke delete() on this object. At that time the underlying resources will actually be modified.
Specified by:
markForDeletion in interface Feature
See Also:
delete()

commit

public void commit()
            throws InvalidFeatureException
Commits all changes to the underlying resources.
  • If the feature is new, the following sequence of operations is performed:
    • validateChanges()
    • insert()
  • If the feature is marked for deletion (and not new):
    • If the feature was modified, refresh()
    • delete()
  • If the feature's properties have been modified:
    • validateChanges()
    • applyChanges()
If insert(), delete() or applyChanges() was in fact called, commit() also calls FeatureModel.resourceModified() for all registered resource adapters.
Specified by:
commit in interface Feature
See Also:
insert(), delete(), applyChanges(), FeatureModel.resourceModified(ResourceAdapter)

validateChanges

public void validateChanges()
                     throws InvalidFeatureException
Calls validateChanges(List) with an empty list. If validateChanges(List) returns false, throws InvalidFeatureException initialized with that list.

validateChanges

protected boolean validateChanges(com.sun.java.util.collections.List list)
Override to produce validations for the feature. This method is invoked during the commit process. If it returns false, commit is canceled. If the method discovers any problem with the feature's properties that would prevent it from being successfully committed, it should put a description of the problem in the form of an object of type FeatureMessage into the supplied list and return false. Otherwise it should return true.

applyChanges

protected void applyChanges()
Override to apply changes made to the feature's properties permanent. Only called if the feature has been modified since last refresh. You can assume that refresh was in fact called before applyChanges() and all cached references to resources are safe to use.

insert

protected void insert()
               throws InvalidFeatureException
Override to make the feature persistent. You can assume that registerDependencies was called before this method is invoked, therefore it can use registered resource adapters and resource set adapters.

delete

protected void delete()
Override to remove feature from persistent resources. You should explicitly call refresh from this method if needed. The only assumption that can be made by this method is that the feature has a signature and that the feature's properties have not been modified since the last refresh() (if any).

addPropertyChangeListener

public void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
Registers the listener and calls activate() if this is the first listener.
Specified by:
addPropertyChangeListener in interface Feature
See Also:
AbstractResourceListener.activate()

removePropertyChangeListener

public void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
Unregisters the listener and calls passivate() if this was the last listener.
Specified by:
removePropertyChangeListener in interface Feature
See Also:
AbstractResourceListener.passivate()

firePropertyChange

protected void firePropertyChange(java.lang.String property,
                                  java.lang.Object oldValue,
                                  java.lang.Object newValue)
Call this method from all setBar methods on the feature. The method will perform several tasks.
  • Send an event to property change listeners
  • Call FeatureModel.featureChanged(this, property, oldValue, newValue)
  • Mark feature as modified
Note that method does not do anything in the following situations:
  • The old and the new values are the same
  • The method is called during the first invocation of refresh()
  • The feature is marked for deletion
See Also:
FeatureModel.featureChanged(Feature,String,Object,Object)

firePropertyChange

protected void firePropertyChange(java.lang.String property,
                                  boolean oldValue,
                                  boolean newValue)
A version of firePropertyChange that takes two booleans.

propertyChanged

protected void propertyChanged(java.lang.String property,
                               java.lang.Object oldValue,
                               java.lang.Object newValue)
Override this method if you want to be notified when a property of this feature changes (that means actually changes its value). This method is not called during the resource parsing.

activate

protected void activate()
Feature is activated when the first object registers to listen to property change events on this feature. While there are listeners, the feature will remain active and will automatically call this.refresh() whenever it receives a notification that a resource it depends on has changed. Refresh will call setBar() methods, which will in turn call firePropertyChange(). This way the observers of this feature will be kept updated.
Overrides:
activate in class AbstractResourceListener
Tags copied from class: AbstractResourceListener
See Also:
addPropertyChangeListener(PropertyChangeListener), AbstractFeatureSet.addFeatureSetListener(FeatureSetListener)

release

public void release()
Unregisters from all ResourceAdapters and ResourceSetAdapters and forwards the release() message to the child FeatureSet.
Specified by:
release in interface Feature
Overrides:
release in class AbstractResourceListener

invalidate

public void invalidate()
Marks the feature as invalid, which will force the property parsing the next time refresh() is called. If the feature is active, this method will also immediately call refresh() to keep the feature up-to-date.
Specified by:
invalidate in interface Feature
Overrides:
invalidate in class AbstractResourceListener

toStringVerbose

public java.lang.String toStringVerbose()
You can override this method to provide a verbose description of this feature's properties for debugging purposes.

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object