diff options
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/model/ChangeSupport.java')
-rw-r--r-- | jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/model/ChangeSupport.java | 2363 |
1 files changed, 0 insertions, 2363 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/model/ChangeSupport.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/model/ChangeSupport.java deleted file mode 100644 index 3150f612bc..0000000000 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/model/ChangeSupport.java +++ /dev/null @@ -1,2363 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2008 Oracle. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0, which accompanies this distribution - * and is available at http://www.eclipse.org/legal/epl-v10.html. - * - * Contributors: - * Oracle - initial API and implementation - ******************************************************************************/ -package org.eclipse.jpt.utility.internal.model; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.lang.reflect.Array; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.eclipse.jpt.utility.internal.ClassTools; -import org.eclipse.jpt.utility.internal.CollectionTools; -import org.eclipse.jpt.utility.internal.StringTools; -import org.eclipse.jpt.utility.model.Model; -import org.eclipse.jpt.utility.model.event.CollectionChangeEvent; -import org.eclipse.jpt.utility.model.event.ListChangeEvent; -import org.eclipse.jpt.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.utility.model.event.StateChangeEvent; -import org.eclipse.jpt.utility.model.event.TreeChangeEvent; -import org.eclipse.jpt.utility.model.listener.ChangeListener; -import org.eclipse.jpt.utility.model.listener.CollectionChangeListener; -import org.eclipse.jpt.utility.model.listener.ListChangeListener; -import org.eclipse.jpt.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.utility.model.listener.StateChangeListener; -import org.eclipse.jpt.utility.model.listener.TreeChangeListener; - -/** - * Support object that can be used by implementors of the Model interface. - * It provides for state, property, collection, list, and tree change notifications to - * listeners. - * - * NB: There is lots of copy-n-paste code in this class. Nearly all of this duplication - * is an effort to prevent the unnecessary creation of new objects (typically event - * objects). Since many events are fired when there are no listeners, we postpone - * the creation of event objects until we know we have interested listeners. - * Most methods have the "non-duplicated" version of the method body commented - * out at the top of the current method body. - * The hope was that this class would prove to be fairly static and the duplicated - * code would not prove onerous; but that has not proven to be - * the case, as we have added support for "state" changes, "dirty" notification, - * and custom "notifiers", with more to come, I'm sure.... ~bjv - * - * NB2: This class will check to see if, during the firing of events, a listener - * on the original, cloned, list of listeners has been removed from the master - * list of listeners *before* it is notified. If the listener has been removed - * "concurrently" it will *not* be notified. (See the code that uses the - * 'stillListening' local boolean flag.) - * - * NB3: Any listener that is added during the firing of events will *not* be - * also notified. - * - * NB4: This class is serializable, but it will only write out listeners that - * are also serializable while silently leaving behind listeners that are not. - * - * TODO fire a state change event with *every* change? - * TODO use objects (IDs?) instead of strings to identify aspects? - */ -public class ChangeSupport - implements Serializable -{ - - /** The object to be provided as the "source" for any generated events. */ - protected final Model source; - - /** Associate a listener class to a collection of "generic" listeners for that class. */ - private transient GenericListenerList[] genericListeners = EMPTY_GENERIC_LISTENERS; - private static final GenericListenerList[] EMPTY_GENERIC_LISTENERS = new GenericListenerList[0]; - - /** Associate aspect names to child change support objects. */ - private AspectChild[] aspectChildren = EMPTY_ASPECT_CHILDREN; - private static final AspectChild[] EMPTY_ASPECT_CHILDREN = new AspectChild[0]; - - private static final long serialVersionUID = 1L; - - - // ********** constructor ********** - - /** - * Construct support for the specified source of change events. - * The source cannot be null. - */ - public ChangeSupport(Model source) { - super(); - if (source == null) { - throw new NullPointerException(); - } - this.source = source; - } - - - // ********** internal behavior ********** - - /** - * Add a "generic" listener that listens to all events appropriate to that - * listener, regardless of the aspect name associated with that event. - * The listener cannot be null. - */ - protected <T extends ChangeListener> void addListener(Class<T> listenerClass, T listener) { - if (listener == null) { - throw new NullPointerException(); // better sooner than later - } - synchronized (this) { - GenericListenerList gll = this.genericListenerList(listenerClass); - if (gll == null) { - this.addGenericListenerList(listenerClass, listener); - } else { - gll.addListener(listener); - } - } - } - - /** - * Return the "generic" listener list for the specified listener class. - * Return null if the list is not present. - */ - protected GenericListenerList genericListenerList(Class<? extends ChangeListener> listenerClass) { - for (GenericListenerList gll : this.genericListeners) { - if (gll.listenerClass == listenerClass) { - return gll; - } - } - return null; - } - - /** - * Add the "generic" listener list for the specified listener class. - * Return the newly-built generic listener list. - */ - protected <T extends ChangeListener> GenericListenerList addGenericListenerList(Class<T> listenerClass, T listener) { - GenericListenerList gll = new GenericListenerList(listenerClass, listener); - this.genericListeners = CollectionTools.add(this.genericListeners, gll); - return gll; - } - - /** - * Adds a listener that listens to all events appropriate to that listener, - * and only to those events carrying the aspect name specified. - * The aspect name cannot be null and the listener cannot be null. - */ - protected <T extends ChangeListener> void addListener(String aspectName, Class<T> listenerClass, T listener) { - if ((aspectName == null) || (listener == null)) { - throw new NullPointerException(); // better sooner than later - } - synchronized (this) { - ChangeSupport child = this.child(aspectName); - if (child == null) { - child = this.addChild(aspectName); - } - child.addListener(listenerClass, listener); - } - } - - /** - * Return the child change support for the specified aspect name. - * Return null if the aspect name is null or the child is not present. - */ - protected ChangeSupport child(String aspectName) { - // put in a null check to simplify calling code - if (aspectName == null) { - return null; - } - for (AspectChild aspectChild : this.aspectChildren) { - if (aspectChild.aspectName == aspectName) { - return aspectChild.child; - } - } - return null; - } - - /** - * Add the child change support for the specified aspect name. - * Return the newly-built child change support. - */ - protected ChangeSupport addChild(String aspectName) { - ChangeSupport child = this.buildChildChangeSupport(); - this.aspectChildren = CollectionTools.add(this.aspectChildren, new AspectChild(aspectName, child)); - return child; - } - - /** - * Build and return a child change support to hold aspect-specific listeners. - */ - protected ChangeSupport buildChildChangeSupport() { - return new ChangeSupport(this.source); - } - - /** - * Removes a "generic" listener that has been registered for all events - * appropriate to that listener. - */ - protected <T extends ChangeListener> void removeListener(Class<T> listenerClass, T listener) { - synchronized (this) { - GenericListenerList gll = this.genericListenerList(listenerClass); - if (gll == null) { - throw new IllegalArgumentException("listener not registered"); //$NON-NLS-1$ - } - if ( ! gll.removeListener(listener)) { // leave the GLL, even if it is empty? - throw new IllegalArgumentException("listener not registered: " + listener); //$NON-NLS-1$ - } - } - } - - /** - * Removes a listener that has been registered for appropriate - * events carrying the specified aspect name. - */ - protected <T extends ChangeListener> void removeListener(String aspectName, Class<T> listenerClass, T listener) { - synchronized (this) { - ChangeSupport child = this.child(aspectName); - if (child == null) { - throw new IllegalArgumentException("listener not registered"); //$NON-NLS-1$ - } - child.removeListener(listenerClass, listener); // leave the child, even if it is empty? - } - } - - - // ********** internal queries ********** - - /** - * Return the "generic" listeners for the specified listener class. - * Return null if there are no listeners. - */ - protected ChangeListener[] listeners(Class<? extends ChangeListener> listenerClass) { - GenericListenerList gll = this.genericListenerList(listenerClass); - return (gll == null) ? null : gll.listeners; - } - - /** - * Return whether there are any "generic" listeners for the specified - * listener class. - */ - protected synchronized <T extends ChangeListener> boolean hasAnyListeners(Class<T> listenerClass) { - GenericListenerList gll = this.genericListenerList(listenerClass); - return (gll != null) && gll.hasListeners(); - } - - /** - * Return whether there are no "generic" listeners for the specified - * listener class. - */ - protected <T extends ChangeListener> boolean hasNoListeners(Class<T> listenerClass) { - return ! this.hasAnyListeners(listenerClass); - } - - /** - * Return whether there are any listeners for the specified - * listener class and aspect name. - */ - protected synchronized boolean hasAnyListeners(Class<? extends ChangeListener> listenerClass, String aspectName) { - if (this.hasAnyListeners(listenerClass)) { - return true; // there's a "generic" listener - } - ChangeSupport child = this.child(aspectName); - return (child != null) && - child.hasAnyListeners(listenerClass); - } - - /** - * Return whether there are no "generic" listeners for the specified - * listener class and aspect name. - */ - protected <T extends ChangeListener> boolean hasNoListeners(Class<T> listenerClass, String aspectName) { - return ! this.hasAnyListeners(listenerClass, aspectName); - } - - - // ********** behavior ********** - - /** - * The specified aspect of the source has changed; - * override this method to perform things like setting a - * dirty flag or validating the source's state. - * The aspect ID will be null if a "state change" occurred. - */ - protected void sourceChanged(@SuppressWarnings("unused") String aspectName) { - // the default is to do nothing - } - - - // ********** state change support ********** - - protected static final Class<StateChangeListener> STATE_CHANGE_LISTENER_CLASS = StateChangeListener.class; - - /** - * Add a state change listener. - */ - public void addStateChangeListener(StateChangeListener listener) { - this.addListener(STATE_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a state change listener. - */ - public void removeStateChangeListener(StateChangeListener listener) { - this.removeListener(STATE_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Return whether there are any state change listeners. - */ - public boolean hasAnyStateChangeListeners() { - return this.hasAnyListeners(STATE_CHANGE_LISTENER_CLASS); - } - - private StateChangeListener[] stateChangeListeners() { - return (StateChangeListener[]) this.listeners(STATE_CHANGE_LISTENER_CLASS); - } - - /** - * Fire the specified state change event to any registered listeners. - */ - public void fireStateChanged(StateChangeEvent event) { - - StateChangeListener[] targets = null; - - synchronized (this) { - StateChangeListener[] stateChangeListeners = this.stateChangeListeners(); - if (stateChangeListeners != null) { - targets = stateChangeListeners.clone(); - } - } - - if (targets != null) { - for (StateChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.stateChangeListeners(), target); - } - if (stillListening) { - target.stateChanged(event); - } - } - } - - this.sourceChanged(null); - } - - /** - * Report a generic state change event to any registered state change - * listeners. - */ - public void fireStateChanged() { -// this.fireStateChange(new StateChangeEvent(this.source)); - - StateChangeListener[] targets = null; - - synchronized (this) { - StateChangeListener[] stateChangeListeners = this.stateChangeListeners(); - if (stateChangeListeners != null) { - targets = stateChangeListeners.clone(); - } - } - - if (targets != null) { - StateChangeEvent event = null; - for (StateChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.stateChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new StateChangeEvent(this.source); - } - target.stateChanged(event); - } - } - } - - this.sourceChanged(null); - } - - - // ********** property change support ********** - - protected static final Class<PropertyChangeListener> PROPERTY_CHANGE_LISTENER_CLASS = PropertyChangeListener.class; - - /** - * Return whether the values are equal, with the appropriate null checks. - * Convenience method for checking whether an attribute value has changed. - */ - public boolean valuesAreEqual(Object value1, Object value2) { - if ((value1 == null) && (value2 == null)) { - return true; // both are null - } - if ((value1 == null) || (value2 == null)) { - return false; // one is null but the other is not - } - return value1.equals(value2); - } - - /** - * Return whether the values are different, with the appropriate null checks. - * Convenience method for checking whether an attribute value has changed. - */ - public boolean valuesAreDifferent(Object value1, Object value2) { - return ! this.valuesAreEqual(value1, value2); - } - - /** - * Add a property change listener that is registered for all properties. - */ - public void addPropertyChangeListener(PropertyChangeListener listener) { - this.addListener(PROPERTY_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Add a property change listener for the specified property. The listener - * will be notified only for changes to the specified property. - */ - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - this.addListener(propertyName, PROPERTY_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a property change listener that was registered for all properties. - */ - public void removePropertyChangeListener(PropertyChangeListener listener) { - this.removeListener(PROPERTY_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a property change listener that was registered for a specific property. - */ - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - this.removeListener(propertyName, PROPERTY_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Return whether there are any property change listeners that will - * be notified when the specified property has changed. - */ - public boolean hasAnyPropertyChangeListeners(String propertyName) { - return this.hasAnyListeners(PROPERTY_CHANGE_LISTENER_CLASS, propertyName); - } - - /** - * Return whether there are any property change listeners that will - * be notified when any property has changed. - */ - public boolean hasAnyPropertyChangeListeners() { - return this.hasAnyListeners(PROPERTY_CHANGE_LISTENER_CLASS); - } - - private PropertyChangeListener[] propertyChangeListeners() { - return (PropertyChangeListener[]) this.listeners(PROPERTY_CHANGE_LISTENER_CLASS); - } - - /** - * Fire the specified property change event to any registered listeners. - * No event is fired if the given event's old and new values are the same; - * this includes when both values are null. Use a state change event - * for general purpose notification of changes. - */ - public void firePropertyChanged(PropertyChangeEvent event) { - if (this.valuesAreEqual(event.getOldValue(), event.getNewValue())) { - return; - } - - String propertyName = event.getPropertyName(); - - PropertyChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - PropertyChangeListener[] propertyChangeListeners = this.propertyChangeListeners(); - if (propertyChangeListeners != null) { - targets = propertyChangeListeners.clone(); - } - child = this.child(propertyName); - } - - if (targets != null) { - for (PropertyChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.propertyChangeListeners(), target); - } - if (stillListening) { - target.propertyChanged(event); - } - } - } - if (child != null) { - child.firePropertyChanged(event); - } - - this.sourceChanged(propertyName); - } - - /** - * Report a bound property update to any registered property change listeners. - * No event is fired if the given old and new values are the same; - * this includes when both values are null. Use a state change event - * for general purpose notification of changes. - */ - public void firePropertyChanged(String propertyName, Object oldValue, Object newValue) { -// this.firePropertyChanged(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue)); - if (this.valuesAreEqual(oldValue, newValue)) { - return; - } - - PropertyChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - PropertyChangeListener[] propertyChangeListeners = this.propertyChangeListeners(); - if (propertyChangeListeners != null) { - targets = propertyChangeListeners.clone(); - } - child = this.child(propertyName); - } - - PropertyChangeEvent event = null; - - if (targets != null) { - for (PropertyChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.propertyChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new PropertyChangeEvent(this.source, propertyName, oldValue, newValue); - } - target.propertyChanged(event); - } - } - } - if (child != null) { - if (event == null) { - child.firePropertyChanged(propertyName, oldValue, newValue); - } else { - child.firePropertyChanged(event); - } - } - - this.sourceChanged(propertyName); - } - - /** - * Report an int bound property update to any registered listeners. - * No event is fired if old and new are equal. - * <p> - * This is merely a convenience wrapper around the more general - * firePropertyChange method that takes Object values. - */ - public void firePropertyChanged(String propertyName, int oldValue, int newValue) { -// this.firePropertyChanged(propertyName, new Integer(oldValue), new Integer(newValue)); - if (oldValue == newValue) { - return; - } - - PropertyChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - PropertyChangeListener[] propertyChangeListeners = this.propertyChangeListeners(); - if (propertyChangeListeners != null) { - targets = propertyChangeListeners.clone(); - } - child = this.child(propertyName); - } - - PropertyChangeEvent event = null; - - if (targets != null) { - for (PropertyChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.propertyChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new PropertyChangeEvent(this.source, propertyName, new Integer(oldValue), new Integer(newValue)); - } - target.propertyChanged(event); - } - } - } - if (child != null) { - if (event == null) { - child.firePropertyChanged(propertyName, oldValue, newValue); - } else { - child.firePropertyChanged(event); - } - } - - this.sourceChanged(propertyName); - } - - /** - * Report a boolean bound property update to any registered listeners. - * No event is fired if old and new are equal. - * <p> - * This is merely a convenience wrapper around the more general - * firePropertyChange method that takes Object values. - */ - public void firePropertyChanged(String propertyName, boolean oldValue, boolean newValue) { -// this.firePropertyChanged(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); - if (oldValue == newValue) { - return; - } - - PropertyChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - PropertyChangeListener[] propertyChangeListeners = this.propertyChangeListeners(); - if (propertyChangeListeners != null) { - targets = propertyChangeListeners.clone(); - } - child = this.child(propertyName); - } - - PropertyChangeEvent event = null; - - if (targets != null) { - for (PropertyChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.propertyChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new PropertyChangeEvent(this.source, propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); - } - target.propertyChanged(event); - } - } - } - if (child != null) { - if (event == null) { - child.firePropertyChanged(propertyName, oldValue, newValue); - } else { - child.firePropertyChanged(event); - } - } - - this.sourceChanged(propertyName); - } - - - // ********** collection change support ********** - - protected static final Class<CollectionChangeListener> COLLECTION_CHANGE_LISTENER_CLASS = CollectionChangeListener.class; - - /** - * Add a collection change listener that is registered for all collections. - */ - public void addCollectionChangeListener(CollectionChangeListener listener) { - this.addListener(COLLECTION_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Add a collection change listener for the specified collection. The listener - * will be notified only for changes to the specified collection. - */ - public void addCollectionChangeListener(String collectionName, CollectionChangeListener listener) { - this.addListener(collectionName, COLLECTION_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a collection change listener that was registered for all collections. - */ - public void removeCollectionChangeListener(CollectionChangeListener listener) { - this.removeListener(COLLECTION_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a collection change listener that was registered for a specific collection. - */ - public void removeCollectionChangeListener(String collectionName, CollectionChangeListener listener) { - this.removeListener(collectionName, COLLECTION_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Return whether there are any collection change listeners that will - * be notified when the specified collection has changed. - */ - public boolean hasAnyCollectionChangeListeners(String collectionName) { - return this.hasAnyListeners(COLLECTION_CHANGE_LISTENER_CLASS, collectionName); - } - - /** - * Return whether there are any collection change listeners that will - * be notified when any collection has changed. - */ - public boolean hasAnyCollectionChangeListeners() { - return this.hasAnyListeners(COLLECTION_CHANGE_LISTENER_CLASS); - } - - private CollectionChangeListener[] collectionChangeListeners() { - return (CollectionChangeListener[]) this.listeners(COLLECTION_CHANGE_LISTENER_CLASS); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireItemsAdded(CollectionChangeEvent event) { - if (event.itemsSize() == 0) { - return; - } - - String collectionName = event.getCollectionName(); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - target.itemsAdded(event); - } - } - } - if (child != null) { - child.fireItemsAdded(event); - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireItemsAdded(String collectionName, Collection<?> addedItems) { -// this.fireItemsAdded(new CollectionChangeEvent(this.source, collectionName, addedItems)); - if (addedItems.size() == 0) { - return; - } - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - CollectionChangeEvent event = null; - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new CollectionChangeEvent(this.source, collectionName, addedItems); - } - target.itemsAdded(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemsAdded(collectionName, addedItems); - } else { - child.fireItemsAdded(event); - } - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireItemAdded(String collectionName, Object addedItem) { -// this.fireItemsAdded(collectionName, Collections.singleton(addedItem)); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - CollectionChangeEvent event = null; - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new CollectionChangeEvent(this.source, collectionName, Collections.singleton(addedItem)); - } - target.itemsAdded(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemAdded(collectionName, addedItem); - } else { - child.fireItemsAdded(event); - } - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireItemsRemoved(CollectionChangeEvent event) { - if (event.itemsSize() == 0) { - return; - } - - String collectionName = event.getCollectionName(); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - target.itemsRemoved(event); - } - } - } - if (child != null) { - child.fireItemsRemoved(event); - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireItemsRemoved(String collectionName, Collection<?> removedItems) { -// this.fireItemsRemoved(new CollectionChangeEvent(this.source, collectionName, removedItems)); - if (removedItems.size() == 0) { - return; - } - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - CollectionChangeEvent event = null; - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new CollectionChangeEvent(this.source, collectionName, removedItems); - } - target.itemsRemoved(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemsRemoved(collectionName, removedItems); - } else { - child.fireItemsRemoved(event); - } - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireItemRemoved(String collectionName, Object removedItem) { -// this.fireItemsRemoved(collectionName, Collections.singleton(removedItem)); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - CollectionChangeEvent event = null; - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new CollectionChangeEvent(this.source, collectionName, Collections.singleton(removedItem)); - } - target.itemsRemoved(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemRemoved(collectionName, removedItem); - } else { - child.fireItemsRemoved(event); - } - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireCollectionCleared(CollectionChangeEvent event) { - String collectionName = event.getCollectionName(); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - target.collectionCleared(event); - } - } - } - if (child != null) { - child.fireCollectionCleared(event); - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireCollectionCleared(String collectionName) { -// this.fireCollectionCleared(new CollectionChangeEvent(this.source, collectionName)); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - CollectionChangeEvent event = null; - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new CollectionChangeEvent(this.source, collectionName); - } - target.collectionCleared(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireCollectionCleared(collectionName); - } else { - child.fireCollectionCleared(event); - } - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireCollectionChanged(CollectionChangeEvent event) { - String collectionName = event.getCollectionName(); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - target.collectionChanged(event); - } - } - } - if (child != null) { - child.fireCollectionChanged(event); - } - - this.sourceChanged(collectionName); - } - - /** - * Report a bound collection update to any registered listeners. - */ - public void fireCollectionChanged(String collectionName) { -// this.fireCollectionChanged(new CollectionChangeEvent(this.source, collectionName)); - - CollectionChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - CollectionChangeListener[] collectionChangeListeners = this.collectionChangeListeners(); - if (collectionChangeListeners != null) { - targets = collectionChangeListeners.clone(); - } - child = this.child(collectionName); - } - - CollectionChangeEvent event = null; - - if (targets != null) { - for (CollectionChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.collectionChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new CollectionChangeEvent(this.source, collectionName); - } - target.collectionChanged(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireCollectionChanged(collectionName); - } else { - child.fireCollectionChanged(event); - } - } - - this.sourceChanged(collectionName); - } - - - // ********** list change support ********** - - protected static final Class<ListChangeListener> LIST_CHANGE_LISTENER_CLASS = ListChangeListener.class; - - /** - * Add a list change listener that is registered for all lists. - */ - public void addListChangeListener(ListChangeListener listener) { - this.addListener(LIST_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Add a list change listener for the specified list. The listener - * will be notified only for changes to the specified list. - */ - public void addListChangeListener(String listName, ListChangeListener listener) { - this.addListener(listName, LIST_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a list change listener that was registered for all lists. - */ - public void removeListChangeListener(ListChangeListener listener) { - this.removeListener(LIST_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a list change listener that was registered for a specific list. - */ - public void removeListChangeListener(String listName, ListChangeListener listener) { - this.removeListener(listName, LIST_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Return whether there are any list change listeners that will - * be notified when the specified list has changed. - */ - public boolean hasAnyListChangeListeners(String listName) { - return this.hasAnyListeners(LIST_CHANGE_LISTENER_CLASS, listName); - } - - /** - * Return whether there are any list change listeners that will - * be notified when any list has changed. - */ - public boolean hasAnyListChangeListeners() { - return this.hasAnyListeners(LIST_CHANGE_LISTENER_CLASS); - } - - private ListChangeListener[] listChangeListeners() { - return (ListChangeListener[]) this.listeners(LIST_CHANGE_LISTENER_CLASS); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsAdded(ListChangeEvent event) { - if (event.itemsSize() == 0) { - return; - } - - String listName = event.getListName(); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - target.itemsAdded(event); - } - } - } - if (child != null) { - child.fireItemsAdded(event); - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsAdded(String listName, int index, List<?> addedItems) { -// this.fireItemsAdded(new ListChangeEvent(this.source, listName, index, addedItems)); - if (addedItems.size() == 0) { - return; - } - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName, index, addedItems); - } - target.itemsAdded(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemsAdded(listName, index, addedItems); - } else { - child.fireItemsAdded(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemAdded(String listName, int index, Object addedItem) { -// this.fireItemsAdded(listName, index, Collections.singletonList(addedItem)); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName, index, Collections.singletonList(addedItem)); - } - target.itemsAdded(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemAdded(listName, index, addedItem); - } else { - child.fireItemsAdded(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsRemoved(ListChangeEvent event) { - if (event.itemsSize() == 0) { - return; - } - - String listName = event.getListName(); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - target.itemsRemoved(event); - } - } - } - if (child != null) { - child.fireItemsRemoved(event); - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsRemoved(String listName, int index, List<?> removedItems) { -// this.fireItemsRemoved(new ListChangeEvent(this.source, listName, index, removedItems)); - if (removedItems.size() == 0) { - return; - } - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName, index, removedItems); - } - target.itemsRemoved(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemsRemoved(listName, index, removedItems); - } else { - child.fireItemsRemoved(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemRemoved(String listName, int index, Object removedItem) { -// this.fireItemsRemoved(listName, index, Collections.singletonList(removedItem)); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName, index, Collections.singletonList(removedItem)); - } - target.itemsRemoved(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemRemoved(listName, index, removedItem); - } else { - child.fireItemsRemoved(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsReplaced(ListChangeEvent event) { - if (event.itemsSize() == 0) { - return; - } - - String listName = event.getListName(); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - target.itemsReplaced(event); - } - } - } - if (child != null) { - child.fireItemsReplaced(event); - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsReplaced(String listName, int index, List<?> newItems, List<?> replacedItems) { -// this.fireItemsReplaced(new ListChangeEvent(this.source, listName, index, newItems, replacedItems)); - if (newItems.size() == 0) { - return; - } - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName, index, newItems, replacedItems); - } - target.itemsReplaced(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemsReplaced(listName, index, newItems, replacedItems); - } else { - child.fireItemsReplaced(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemReplaced(String listName, int index, Object newItem, Object replacedItem) { -// this.fireItemsReplaced(listName, index, Collections.singletonList(newItem), Collections.singletonList(replacedItem)); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName, index, Collections.singletonList(newItem), Collections.singletonList(replacedItem)); - } - target.itemsReplaced(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemReplaced(listName, index, newItem, replacedItem); - } else { - child.fireItemsReplaced(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsMoved(ListChangeEvent event) { - if (event.getTargetIndex() == event.getSourceIndex()) { - return; - } - - String listName = event.getListName(); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - target.itemsMoved(event); - } - } - } - if (child != null) { - child.fireItemsMoved(event); - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemsMoved(String listName, int targetIndex, int sourceIndex, int length) { -// this.fireItemsMoved(new ListChangeEvent(this.source, listName, targetIndex, sourceIndex, length)); - if (targetIndex == sourceIndex) { - return; - } - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName, targetIndex, sourceIndex, length); - } - target.itemsMoved(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireItemsMoved(listName, targetIndex, sourceIndex, length); - } else { - child.fireItemsMoved(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireItemMoved(String listName, int targetIndex, int sourceIndex) { - this.fireItemsMoved(listName, targetIndex, sourceIndex, 1); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireListCleared(ListChangeEvent event) { - String listName = event.getListName(); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - target.listCleared(event); - } - } - } - if (child != null) { - child.fireListCleared(event); - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireListCleared(String listName) { -// this.fireListCleared(new ListChangeEvent(this.source, listName)); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName); - } - target.listCleared(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireListCleared(listName); - } else { - child.fireListCleared(event); - } - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireListChanged(ListChangeEvent event) { - String listName = event.getListName(); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - target.listChanged(event); - } - } - } - if (child != null) { - child.fireListChanged(event); - } - - this.sourceChanged(listName); - } - - /** - * Report a bound list update to any registered listeners. - */ - public void fireListChanged(String listName) { -// this.fireListChanged(new ListChangeEvent(this.source, listName)); - - ListChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - ListChangeListener[] listChangeListeners = this.listChangeListeners(); - if (listChangeListeners != null) { - targets = listChangeListeners.clone(); - } - child = this.child(listName); - } - - ListChangeEvent event = null; - - if (targets != null) { - for (ListChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.listChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new ListChangeEvent(this.source, listName); - } - target.listChanged(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireListChanged(listName); - } else { - child.fireListChanged(event); - } - } - - this.sourceChanged(listName); - } - - - // ********** tree change support ********** - - protected static final Class<TreeChangeListener> TREE_CHANGE_LISTENER_CLASS = TreeChangeListener.class; - private static final Object[] EMPTY_TREE_PATH = new Object[0]; - - /** - * Add a tree change listener that is registered for all trees. - */ - public void addTreeChangeListener(TreeChangeListener listener) { - this.addListener(TREE_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Add a tree change listener for the specified tree. The listener - * will be notified only for changes to the specified tree. - */ - public void addTreeChangeListener(String treeName, TreeChangeListener listener) { - this.addListener(treeName, TREE_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a tree change listener that was registered for all tree. - */ - public void removeTreeChangeListener(TreeChangeListener listener) { - this.removeListener(TREE_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Remove a tree change listener that was registered for a specific tree. - */ - public void removeTreeChangeListener(String treeName, TreeChangeListener listener) { - this.removeListener(treeName, TREE_CHANGE_LISTENER_CLASS, listener); - } - - /** - * Return whether there are any tree change listeners that will - * be notified when the specified tree has changed. - */ - public boolean hasAnyTreeChangeListeners(String treeName) { - return this.hasAnyListeners(TREE_CHANGE_LISTENER_CLASS, treeName); - } - - /** - * Return whether there are any tree change listeners that will - * be notified when any tree has changed. - */ - public boolean hasAnyTreeChangeListeners() { - return this.hasAnyListeners(TREE_CHANGE_LISTENER_CLASS); - } - - private TreeChangeListener[] treeChangeListeners() { - return (TreeChangeListener[]) this.listeners(TREE_CHANGE_LISTENER_CLASS); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireNodeAdded(TreeChangeEvent event) { - String treeName = event.getTreeName(); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - target.nodeAdded(event); - } - } - } - if (child != null) { - child.fireNodeAdded(event); - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireNodeAdded(String treeName, Object[] path) { -// this.fireNodeAdded(new TreeChangeEvent(this.source, treeName, path)); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - TreeChangeEvent event = null; - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new TreeChangeEvent(this.source, treeName, path); - } - target.nodeAdded(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireNodeAdded(treeName, path); - } else { - child.fireNodeAdded(event); - } - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireNodeRemoved(TreeChangeEvent event) { - String treeName = event.getTreeName(); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - target.nodeRemoved(event); - } - } - } - if (child != null) { - child.fireNodeRemoved(event); - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireNodeRemoved(String treeName, Object[] path) { -// this.fireNodeRemoved(new TreeChangeEvent(this.source, treeName, path)); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - TreeChangeEvent event = null; - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new TreeChangeEvent(this.source, treeName, path); - } - target.nodeRemoved(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireNodeRemoved(treeName, path); - } else { - child.fireNodeRemoved(event); - } - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireTreeCleared(TreeChangeEvent event) { - String treeName = event.getTreeName(); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - target.treeCleared(event); - } - } - } - if (child != null) { - child.fireTreeCleared(event); - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireTreeCleared(String treeName, Object[] path) { -// this.fireTreeCleared(new TreeChangeEvent(this.source, treeName, path)); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - TreeChangeEvent event = null; - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new TreeChangeEvent(this.source, treeName, path); - } - target.treeCleared(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireTreeCleared(treeName, path); - } else { - child.fireTreeCleared(event); - } - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireTreeCleared(String treeName) { - this.fireTreeCleared(treeName, EMPTY_TREE_PATH); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireTreeChanged(TreeChangeEvent event) { - String treeName = event.getTreeName(); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - target.treeChanged(event); - } - } - } - if (child != null) { - child.fireTreeChanged(event); - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireTreeChanged(String treeName, Object[] path) { -// this.fireTreeChanged(new TreeChangeEvent(this.source, treeName, path)); - - TreeChangeListener[] targets = null; - ChangeSupport child = null; - - synchronized (this) { - TreeChangeListener[] treeChangeListeners = this.treeChangeListeners(); - if (treeChangeListeners != null) { - targets = treeChangeListeners.clone(); - } - child = this.child(treeName); - } - - TreeChangeEvent event = null; - - if (targets != null) { - for (TreeChangeListener target : targets) { - boolean stillListening; - synchronized (this) { - stillListening = CollectionTools.contains(this.treeChangeListeners(), target); - } - if (stillListening) { - if (event == null) { - // here's the reason for the duplicate code... - event = new TreeChangeEvent(this.source, treeName, path); - } - target.treeChanged(event); - } - } - } - if (child != null) { - if (event == null) { - child.fireTreeChanged(treeName, path); - } else { - child.fireTreeChanged(event); - } - } - - this.sourceChanged(treeName); - } - - /** - * Report a bound tree update to any registered listeners. - */ - public void fireTreeChanged(String treeName) { - this.fireTreeChanged(treeName, EMPTY_TREE_PATH); - } - - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.source); - } - - - // ********** serialization ********** - - private synchronized void writeObject(ObjectOutputStream s) throws IOException { - // write out the source, children, and any hidden stuff - s.defaultWriteObject(); - - // only write out Serializable listeners - int len = this.genericListeners.length; - for (int i = 0; i < len; i++) { - this.writeObject(s, this.genericListeners[i]); - } - s.writeObject(null); - } - - private void writeObject(ObjectOutputStream s, GenericListenerList gll) throws IOException { - boolean first = true; - int len = gll.listeners.length; - for (int i = 0; i < len; i++) { - ChangeListener listener = gll.listeners[i]; - if (listener instanceof Serializable) { - if (first) { - first = false; - s.writeObject(gll.listenerClass); - } - s.writeObject(listener); - } - } - if ( ! first) { - s.writeObject(null); - } - } - - private synchronized void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { - // read in the source, children, and any hidden stuff - s.defaultReadObject(); - - // read in generic listener lists - this.genericListeners = EMPTY_GENERIC_LISTENERS; - Object o; - while (null != (o = s.readObject())) { - @SuppressWarnings("unchecked") - Class<? extends ChangeListener> listenerClass = (Class<? extends ChangeListener>) o; - GenericListenerList gll = null; - while (null != (o = s.readObject())) { - if (gll == null) { - gll = this.addGenericListenerList_(listenerClass, (ChangeListener) o); - } else { - gll.addListener((ChangeListener) o); - } - } - } - } - - @SuppressWarnings("unchecked") - private <T extends ChangeListener> GenericListenerList addGenericListenerList_(Class<T> listenerClass, ChangeListener listener) { - return this.addGenericListenerList(listenerClass, (T) listener); - } - - - // ********** member classes ********** - - /** - * Pair a listener class with its "generic" listeners. - */ - private static class GenericListenerList { - final Class<? extends ChangeListener> listenerClass; - ChangeListener[] listeners; - - <T extends ChangeListener> GenericListenerList(Class<T> listenerClass, T listener) { - super(); - this.listenerClass = listenerClass; - this.listeners = (ChangeListener[]) Array.newInstance(listenerClass, 1); - this.listeners[0] = listener; - } - - void addListener(ChangeListener listener) { - this.listeners = CollectionTools.add(this.listeners, listener); - } - - boolean removeListener(ChangeListener listener) { - int len = this.listeners.length; - if (len == 0) { - return false; - } - try { - this.listeners = CollectionTools.remove(this.listeners, listener); - } catch (ArrayIndexOutOfBoundsException ex) { - return false; // listener not in the list - } - return (this.listeners.length + 1) == len; - } - - boolean hasListeners() { - return this.listeners.length > 0; - } - - @Override - public String toString() { - return StringTools.buildToStringFor(this, ClassTools.shortNameFor(this.listenerClass)); - } - - } - - /** - * Pair an aspect name with the change support holding its associated - * listeners. - */ - private static class AspectChild implements Serializable { - final String aspectName; - final ChangeSupport child; - private static final long serialVersionUID = 1L; - - AspectChild(String aspectName, ChangeSupport child) { - super(); - this.aspectName = aspectName; - this.child = child; - } - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.aspectName); - } - - } - -} |