Index: org/netbeans/mdr/util/EventNotifier.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/util/EventNotifier.java,v retrieving revision 1.5 diff -u -r1.5 EventNotifier.java --- org/netbeans/mdr/util/EventNotifier.java 22 May 2002 15:22:08 -0000 1.5 +++ org/netbeans/mdr/util/EventNotifier.java 28 Jun 2002 10:37:39 -0000 @@ -22,6 +22,7 @@ * after transactions. * * @author mmatula + * @author Holger Krug * @version */ public final class EventNotifier { @@ -144,7 +145,7 @@ * Catches all exceptions and logs the stack trace. * *
Returns if a queued change event was not planned before (i.e. does - * not correspond to an entry in {@link #changeListeners}. + * not correspond to an entry in {@link #changeListeners}).
*/ private class EventsDelivery implements Runnable { /** @@ -191,13 +192,25 @@ * the local queue and to fire the pre-change events. */ public abstract class Abstract { + /** + * Maps source objects to pre-change listeners. + */ private final HashMap preChange = new HashMap(); + /** + * Maps source objects to pre-change hierarchy listeners. + */ + private final HashMap preChangeHierarchy = new HashMap(); + /** + * Maps source objects to change listeners. + */ private final HashMap change = new HashMap(); + /** + * Maps source objects to change hierarchy listeners. + */ + private final HashMap changeHierarchy = new HashMap(); /** Registers a new listener in the maplisteners
.
*
- * [PENDING]: make this method static
- *
* @param listeners a map from source objects to sets of listeners
* @param listener the listener to be added to listeners
* @param the source object the listener shall be added for
@@ -217,8 +230,6 @@
/** Removes a listener from the map listeners
.
*
- *
[PENDING]: make this method static
- *
* @param listeners a map from source objects to sets of listeners
* @param listener the listener to be removed from listeners
* @param the source object the listener shall be removed for
@@ -241,6 +252,9 @@
* Adds listener
for object source
.
*/
public void addListener(MDRChangeListener listener, Object source) {
+ /* We do not check if the listener was already added as hierarchy listener.
+ * If a listener is added as well as simple as also as hierarchy listener,
+ * the correctness of the implementation will not be affected. */
if (listener instanceof MDRPreChangeListener) {
register(preChange, listener, source);
} else {
@@ -249,13 +263,29 @@
}
/**
+ * Adds hierarchy listener
for object source
.
+ */
+ public void addHierarchyListener(MDRChangeListener listener, Object source) {
+ /* We do not check if the listener was already added as simple listener.
+ * If a listener is added as well as simple as also as hierarchy listener,
+ * the correctness of the implementation will not be affected. */
+ if (listener instanceof MDRPreChangeListener) {
+ register(preChangeHierarchy, listener, source);
+ } else {
+ register(changeHierarchy, listener, source);
+ }
+ }
+
+ /**
* Removes listener
for object source
.
*/
public void removeListener(MDRChangeListener listener, Object source) {
if (listener instanceof MDRPreChangeListener) {
unregister(preChange, listener, source);
+ unregister(preChangeHierarchy, listener, source);
} else {
unregister(change, listener, source);
+ unregister(changeHierarchy, listener, source);
}
}
@@ -271,7 +301,8 @@
public void firePlannedChange(Object current, MDRChangeEvent event) {
localQueue.addLast(event);
HashSet collected = new HashSet();
- collectListeners(current, event, false, collected);
+ collectSimpleListeners(current, false, collected);
+ collectHierarchyListeners(current, event, false, collected);
for (Iterator it = collected.iterator(); it.hasNext();) {
try {
((MDRPreChangeListener) it.next()).plannedChange(event);
@@ -283,31 +314,20 @@
if (preChangeListeners.put(event, collected.clone()) != null) {
throw new DebugException("Same event fired twice.");
}
- collectListeners(current, event, true, collected);
+ collectSimpleListeners(current, true, collected);
+ collectHierarchyListeners(current, event, true, collected);
if (changeListeners.put(event, collected) != null) {
throw new DebugException("Same event fired twice.");
}
}
/**
- * Collect the listeners for the given event
on object
- * current
. This method has to be overwritten by derived
- * classes to inform listeners on owner objects. Overwriting methods
- * shall call this method on then add any further listeners.
- *
- * @param current the object on which the event was fired
- * @param event the event
- * @param post if false
, listeners implementing
- * {@link org.netbeans.api.mdr.events.MDRPreChangeListener} are
- * collected, otherwise listeners implementing only
- * {@link org.netbeans.api.mdr.events.MDRChangeListener}
- * @param collected the set to which the collected listeners have to be
- * added
+ * Collect listeners from map listeners
for object current
+ * into set collected
.
*/
- protected void collectListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
+ private void collectListenersImpl(Map listeners, Object current, Set collected) {
Set value;
- Map listeners = post ? change : preChange;
-
+
// fire event on all listeners registered on this object
synchronized (listeners) {
value = (Set) listeners.get(current);
@@ -316,6 +336,41 @@
}
}
}
+
+ /**
+ * Collect the simple listeners for the given event
on object
+ * current
.
+ * @param current the object on which the event was fired
+ * @param post if false
, simple listeners implementing
+ * {@link org.netbeans.api.mdr.events.MDRPreChangeListener} are
+ * collected, otherwise simple listeners implementing only
+ * {@link org.netbeans.api.mdr.events.MDRChangeListener}
+ * @param collected the set to which the collected simple listeners have to be
+ * added
+ */
+ private void collectSimpleListeners(Object current, boolean post, Set collected) {
+ collectListenersImpl(post ? change : preChange, current, collected);
+ }
+
+ /**
+ * Collect the hierarchy listeners for the given event
on object
+ * current
. This method has to be overridden by derived
+ * classes to inform hierarchy listeners on owner objects. Overwriting methods
+ * shall call this method and then add any further hierarchy listeners.
+ *
+ * @param current the object on which the event was fired
+ * @param event the event, super-classes will use this parameter to decide
+ * how to forward the event
+ * @param post if false
, hierarchy listeners implementing
+ * {@link org.netbeans.api.mdr.events.MDRPreChangeListener} are
+ * collected, otherwise hierarchy listeners implementing only
+ * {@link org.netbeans.api.mdr.events.MDRChangeListener}
+ * @param collected the set to which the collected hierarchy listeners have to be
+ * added
+ */
+ protected void collectHierarchyListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
+ collectListenersImpl(post ? changeHierarchy : preChangeHierarchy, current, collected);
+ }
}
/* -------------------------------------------------------------------- */
@@ -331,22 +386,22 @@
}
/**
- * Adds listeners on the instances participating in the association link
+ * Adds hierarchy listeners on the instances participating in the association link
* added resp. removed and on the owning package.
*/
- protected void collectListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
- super.collectListeners(current, event, post, collected);
+ protected void collectHierarchyListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
+ super.collectHierarchyListeners(current, event, post, collected);
// fire event on all listeners registered on instances that were affected
if (event instanceof AssociationEvent) {
AssociationEvent assocEvent = (AssociationEvent) event;
- if (assocEvent.getFixedElement() != null) INSTANCE.collectListeners(assocEvent.getFixedElement(), event, post, collected);
- if (assocEvent.getOldElement() != null) INSTANCE.collectListeners(assocEvent.getOldElement(), event, post, collected);
- if (assocEvent.getNewElement() != null) INSTANCE.collectListeners(assocEvent.getNewElement(), event, post, collected);
+ if (assocEvent.getFixedElement() != null) INSTANCE.collectHierarchyListeners(assocEvent.getFixedElement(), event, post, collected);
+ if (assocEvent.getOldElement() != null) INSTANCE.collectHierarchyListeners(assocEvent.getOldElement(), event, post, collected);
+ if (assocEvent.getNewElement() != null) INSTANCE.collectHierarchyListeners(assocEvent.getNewElement(), event, post, collected);
}
// fire event on the immediate package extent
- PACKAGE.collectListeners(((RefAssociation) current).refImmediatePackage(), event, post, collected);
+ PACKAGE.collectHierarchyListeners(((RefAssociation) current).refImmediatePackage(), event, post, collected);
}
}
@@ -365,9 +420,9 @@
/**
* Adds listeners on the owning package.
*/
- protected void collectListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
- super.collectListeners(current, event, post, collected);
- PACKAGE.collectListeners(((RefClass) current).refImmediatePackage(), event, post, collected);
+ protected void collectHierarchyListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
+ super.collectHierarchyListeners(current, event, post, collected);
+ PACKAGE.collectHierarchyListeners(((RefClass) current).refImmediatePackage(), event, post, collected);
}
}
@@ -384,11 +439,11 @@
}
/**
- * Adds listeners on the owning class proxy.
+ * Adds hierarchy listeners on the owning class proxy.
*/
- protected void collectListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
- super.collectListeners(current, event, post, collected);
- CLASS.collectListeners(((RefObject) current).refClass(), event, post, collected);
+ protected void collectHierarchyListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
+ super.collectHierarchyListeners(current, event, post, collected);
+ CLASS.collectHierarchyListeners(((RefObject) current).refClass(), event, post, collected);
}
}
@@ -405,16 +460,16 @@
}
/**
- * Adds listeners on the owning package resp., if this package is
+ * Adds hierarchy listeners on the owning package resp., if this package is
* outermost, on the repository.
*/
- protected void collectListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
- super.collectListeners(current, event, post, collected);
+ protected void collectHierarchyListeners(Object current, MDRChangeEvent event, boolean post, Set collected) {
+ super.collectHierarchyListeners(current, event, post, collected);
RefPackage immediate = ((RefPackage) current).refImmediatePackage();
if (immediate != null) {
- collectListeners(immediate, event, post, collected);
+ collectHierarchyListeners(immediate, event, post, collected);
} else {
- REPOSITORY.collectListeners(((BaseObjectHandler) current)._getDelegate().getMdrStorage(), event, post, collected);
+ REPOSITORY.collectHierarchyListeners(((BaseObjectHandler) current)._getDelegate().getMdrStorage(), event, post, collected);
}
}
}
Index: org/netbeans/mdr/handlers/InstanceHandler.java
===================================================================
RCS file: /cvs/mdr/src/org/netbeans/mdr/handlers/InstanceHandler.java,v
retrieving revision 1.16
diff -u -r1.16 InstanceHandler.java
--- org/netbeans/mdr/handlers/InstanceHandler.java 25 Jun 2002 15:48:01 -0000 1.16
+++ org/netbeans/mdr/handlers/InstanceHandler.java 28 Jun 2002 10:37:39 -0000
@@ -355,6 +355,13 @@
_getMdrStorage().getEventNotifier().INSTANCE.addListener(listener, this);
}
+ /** Registers a hierarchy listener for receiving event notifications.
+ * @param listener Object that implements {@link Listener} interface.
+ */
+ public void addHierarchyListener(MDRChangeListener listener) {
+ _getMdrStorage().getEventNotifier().INSTANCE.addHierarchyListener(listener, this);
+ }
+
/** Removes listener from the list of objects registered for events notifications.
* @param listener Object that implements {@link Listener} interface.
*/
Index: org/netbeans/mdr/handlers/ClassProxyHandler.java
===================================================================
RCS file: /cvs/mdr/src/org/netbeans/mdr/handlers/ClassProxyHandler.java,v
retrieving revision 1.18
diff -u -r1.18 ClassProxyHandler.java
--- org/netbeans/mdr/handlers/ClassProxyHandler.java 26 Jun 2002 12:41:02 -0000 1.18
+++ org/netbeans/mdr/handlers/ClassProxyHandler.java 28 Jun 2002 10:37:39 -0000
@@ -241,6 +241,13 @@
public void addListener(MDRChangeListener listener) {
_getMdrStorage().getEventNotifier().CLASS.addListener(listener, this);
}
+
+ /** Registers a hierarchy listener for receiving event notifications.
+ * @param listener Object that implements {@link Listener} interface.
+ */
+ public void addHierarchyListener(MDRChangeListener listener) {
+ _getMdrStorage().getEventNotifier().CLASS.addHierarchyListener(listener, this);
+ }
/** Removes listener from the list of objects registered for events notifications.
* @param listener Object that implements {@link Listener} interface.
Index: org/netbeans/mdr/handlers/PackageProxyHandler.java
===================================================================
RCS file: /cvs/mdr/src/org/netbeans/mdr/handlers/PackageProxyHandler.java,v
retrieving revision 1.12
diff -u -r1.12 PackageProxyHandler.java
--- org/netbeans/mdr/handlers/PackageProxyHandler.java 17 Jun 2002 09:47:22 -0000 1.12
+++ org/netbeans/mdr/handlers/PackageProxyHandler.java 28 Jun 2002 10:37:39 -0000
@@ -333,6 +333,13 @@
public void addListener(MDRChangeListener listener) {
_getMdrStorage().getEventNotifier().PACKAGE.addListener(listener, this);
}
+
+ /** Registers a hierarchy listener for receiving event notifications.
+ * @param listener Object that implements {@link Listener} interface.
+ */
+ public void addHierarchyListener(MDRChangeListener listener) {
+ _getMdrStorage().getEventNotifier().PACKAGE.addHierarchyListener(listener, this);
+ }
/** Removes listener from the list of objects registered for events notifications.
* @param listener Object that implements {@link Listener} interface.
Index: org/netbeans/mdr/handlers/AssociationHandler.java
===================================================================
RCS file: /cvs/mdr/src/org/netbeans/mdr/handlers/AssociationHandler.java,v
retrieving revision 1.21
diff -u -r1.21 AssociationHandler.java
--- org/netbeans/mdr/handlers/AssociationHandler.java 26 Jun 2002 12:41:02 -0000 1.21
+++ org/netbeans/mdr/handlers/AssociationHandler.java 28 Jun 2002 10:37:40 -0000
@@ -310,6 +310,13 @@
_getMdrStorage().getEventNotifier().ASSOCIATION.addListener(listener, this);
}
+ /** Registers a hierarchy listener for receiving event notifications.
+ * @param listener Object that implements {@link Listener} interface.
+ */
+ public void addHierarchyListener(MDRChangeListener listener) {
+ _getMdrStorage().getEventNotifier().ASSOCIATION.addHierarchyListener(listener, this);
+ }
+
/** Removes listener from the list of objects registered for events notifications.
* @param listener Object that implements {@link Listener} interface.
*/
Index: org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java
===================================================================
RCS file: /cvs/mdr/src/org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java,v
retrieving revision 1.1
diff -u -r1.1 MDREventHandler.java
--- org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java 22 Apr 2002 10:35:41 -0000 1.1
+++ org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java 28 Jun 2002 10:37:39 -0000
@@ -26,24 +26,55 @@
import org.netbeans.api.looks.Look;
/**
+ * Instances of MDREventHandler
are event handlers which listen
+ * on repository changes on behalf of {@link org.netbeans.api.looks.LookNodeSubstitutes
+ * node substitutes}. They manage a map from repository objects to node substitutes
+ * to be able to access the node substitute for a given repository object. Looks
+ * have to register their node subsitutes by calling {@link #addNodeSubstitute(Look.NodeSubstitute)}
+ * or {@link #addNodeSubstitute(Object, Look.NodeSubstitute)} from within
+ * {@link org.netbeans.api.looks.Look#attachTo(ook.NodeSubstitute)}.
*
+ * @deprecated register NodeSubstitutes directly on repository objects instead, see
+ * issue 25186
* @author Tomas Zezula
*/
public class MDREventHandler implements MDRPreChangeListener {
+ /* --------------------------------------------------------------------- */
+ /* -- Attributes ------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ /**
+ * Maps repository content to node substitutes.
+ */
private HashMap registeredNodeSubstitutes;
+
+ /**
+ * Map storing the parents of objects to be deleted. After an object has
+ * been deleted, its parent node is not accessible any more. Nevertheless it
+ * must be refreshed to reflect the deletion of the node representing the object.
+ * Hence the parents of the objects to be deleted are stored in the map.
+ */
private HashMap pendingEvents;
private ReferenceQueue queue;
private MDRepository repository;
+ /* --------------------------------------------------------------------- */
+ /* -- Constructor ------------------------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
public MDREventHandler (MDRepository repository) {
this.queue = new ReferenceQueue();
this.registeredNodeSubstitutes = new HashMap();
this.pendingEvents = new HashMap();
this.repository = repository;
- this.repository.addListener(this);
+ this.repository.addHierarchyListener(this);
}
+ /* --------------------------------------------------------------------- */
+ /* -- Management of NodeSubstitutes ------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
public synchronized void addNodeSubstitute(Look.NodeSubstitute substitute) {
if (substitute == null)
return;
@@ -56,32 +87,25 @@
this.registeredNodeSubstitutes.put(key, new WeakReference(substitute,this.queue));
}
- /** This method is called when the node was garbage collected. You shoud
- * unregister from all objects where this object was registered as a
- * listener.
- */
-
- /** This method gets called if a planned change (which was already announced
- * by calling {@link #plannedChange} was cancelled (e.g. the operation that was
- * going to perform the change failed). This method is called synchronously by
- * the operation that tried to perform the change.
- * Any run-time exception thrown by the implementation of this method should - * not affect the events dispatching (i.e. it should be ignored by the event source). - * @param e Object describing the cancelled change (has to be the same instance - * as passed to the {@link #plannedChange} method). - */ - public void changeCancelled(MDRChangeEvent e) { - if ((e.getType() & 2) == 2) { - this.pendingEvents.remove(e.getSource()); + private synchronized Look.NodeSubstitute getNodeSubstituteForObject(Object object) { + if (object ==null) + return null; + Reference ref = (Reference) this.registeredNodeSubstitutes.get(object); + if (ref == null) { + return null; // Not registered object } + Look.NodeSubstitute substitute = (Look.NodeSubstitute) ref.get(); + return substitute; } - /** This method gets called when a repository change is planned to occur. - * Any operation that performs a change in MDR has to fire this notification - * synchronously on each registered pre-change listener before the change is performed.
- * Any run-time exception thrown by the implementation of this method should - * not affect the events dispatching (i.e. it should be ignored by the event source). - * @param e Object describing the planned change. + /* --------------------------------------------------------------------- */ + /* -- Implements org.netbeans.api.mdr.MDRPreChangeListener ------------- */ + /* --------------------------------------------------------------------- */ + + /** + * Handles deletion events only. Stores the parents of objects to be deleted. + * This is necessary to refresh parent nodes when the object to be deleted + * has been deleted. */ public void plannedChange(MDRChangeEvent e) { if ((e.getType() & ExtentEvent.EVENT_EXTENT_DELETE) == ExtentEvent.EVENT_EXTENT_DELETE) { @@ -107,16 +131,18 @@ } } - /** This method gets called after a repository change is performed. This method - * is called asynchronously. - * If a listener implements {@link MDRPreChangeListener} which is a descedant - * of this interface, the event object passed to this method must be the same - * instance as the event object previously passed to the corresponding - * {@link MDRPreChangeListener#plannedChange} method call of the listener.
- * Any run-time exception thrown by the implementation of this method should
- * not affect the events dispatching (i.e. it should be ignored by the event source).
- *
- * @param e Object describing the performed change.
+ /**
+ * Removes the information stored for the pending event e
.
+ * @see #plannedChange(MDRChangeEvent)
+ */
+ public void changeCancelled(MDRChangeEvent e) {
+ if ((e.getType() & 2) == 2) {
+ this.pendingEvents.remove(e.getSource());
+ }
+ }
+
+ /**
+ * Refreshes the nodes affected by e
.
*/
public void change(MDRChangeEvent e) {
if ((e.getType() & ExtentEvent.EVENT_EXTENT_CREATE) == ExtentEvent.EVENT_EXTENT_CREATE) {
@@ -171,6 +197,14 @@
}
}
+ /* --------------------------------------------------------------------- */
+ /* -- Clean-up dangling map entries ------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
+ /**
+ * Removes entries with garbage collected values from the map associating
+ * repository objects with node substitutes.
+ */
synchronized void flushReferenceQueue() {
if (this.queue.poll()!=null) {
Iterator values = this.registeredNodeSubstitutes.values().iterator();
@@ -184,17 +218,6 @@
}
}
-
- private synchronized Look.NodeSubstitute getNodeSubstituteForObject(Object object) {
- if (object ==null)
- return null;
- Reference ref = (Reference) this.registeredNodeSubstitutes.get(object);
- if (ref == null) {
- return null; // Not registered object
- }
- Look.NodeSubstitute substitute = (Look.NodeSubstitute) ref.get();
- return substitute;
- }
}
Index: org/netbeans/api/mdr/events/MDRChangeSource.java
===================================================================
RCS file: /cvs/mdr/src/org/netbeans/api/mdr/events/MDRChangeSource.java,v
retrieving revision 1.1
diff -u -r1.1 MDRChangeSource.java
--- org/netbeans/api/mdr/events/MDRChangeSource.java 16 Feb 2002 01:30:39 -0000 1.1
+++ org/netbeans/api/mdr/events/MDRChangeSource.java 28 Jun 2002 10:37:39 -0000
@@ -18,21 +18,32 @@
* The objects that have to be registered for event
* notifications need to implement {@link MDRChangeListener}
* or {@link MDRPreChangeListener} interface.
- * The repository should distribute all the events in the following way: + * + *
Listeners can be registered for events originating on the object the + * listener is registered for by calling {@link #addListener(MDRChangeListener)}. + * Listeners can also be registered for events originating on a hierarchy of + * objects by calling {@link #addHierarchyListener(MDRChangeListener)}.
+ * + * The repository should distribute all the events to hierarchy listeners in the following way: *MDRChangeSource
.
* @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void addListener(MDRChangeListener listener);
+ /** Registers a listener for receiving event notifications for this
+ * MDRChangeSource
and its children.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ */
+ public void addHierarchyListener(MDRChangeListener listener);
/** Removes listener from the list of objects registered for events notifications.
* @param listener Object that implements {@link MDRChangeListener} interface.
*/
Index: org/netbeans/mdr/NBMDRepositoryImpl.java
===================================================================
RCS file: /cvs/mdr/src/org/netbeans/mdr/NBMDRepositoryImpl.java,v
retrieving revision 1.36
diff -u -r1.36 NBMDRepositoryImpl.java
--- org/netbeans/mdr/NBMDRepositoryImpl.java 26 Jun 2002 12:41:01 -0000 1.36
+++ org/netbeans/mdr/NBMDRepositoryImpl.java 28 Jun 2002 10:37:40 -0000
@@ -110,14 +110,16 @@
}
/** Creates new {@link org.netbeans.api.mdr.MDRepository} with given parameters.
- * The following parameters are processed:
+ * The following parameter is processed:
*
* storage
: name of a class implementing {@link
* org.netbeans.mdr.persistence.StorageFactory}fileName
: storage locationAll other parameters depend on the StorageFactory
and are
+ * forwarded to
+ * {@link rg.netbeans.mdr.persistence.StorageFactory#createStorage(java.util.Map)}.