/*******************************************************************************
 * Copyright (c) 2007 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.internal.model.event.CollectionChangeEvent;
import org.eclipse.jpt.utility.internal.model.event.ListChangeEvent;
import org.eclipse.jpt.utility.internal.model.event.PropertyChangeEvent;
import org.eclipse.jpt.utility.internal.model.event.StateChangeEvent;
import org.eclipse.jpt.utility.internal.model.event.TreeChangeEvent;
import org.eclipse.jpt.utility.internal.model.listener.ChangeListener;
import org.eclipse.jpt.utility.internal.model.listener.CollectionChangeListener;
import org.eclipse.jpt.utility.internal.model.listener.ListChangeListener;
import org.eclipse.jpt.utility.internal.model.listener.PropertyChangeListener;
import org.eclipse.jpt.utility.internal.model.listener.StateChangeListener;
import org.eclipse.jpt.utility.internal.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: This class is serializable, but it will only write out listeners that
 * are also serializable while silently leaving behind listeners that are not.
 * 
 * TODO support a dispatcher per listener?
 * 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. */
	transient private 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");
			}
			if ( ! gll.removeListener(listener)) {  // leave the GLL, even if it is empty?
				throw new IllegalArgumentException("listener not registered");
			}
		}
	}

	/**
	 * 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");
			}
			child.removeListener(listenerClass, listener);  // leave the child, even if it is empty?
		}
	}


	// ********** internal queries **********

	/**
	 * Return a dispatcher that will forward change notifications to the listeners.
	 */
	protected ChangeEventDispatcher dispatcher() {
		return SimpleChangeEventDispatcher.instance();
	}

	/**
	 * 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(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) {
					this.dispatcher().stateChanged(target, 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);
					}
					this.dispatcher().stateChanged(target, 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.oldValue(), event.newValue())) {
			return; 
		}

		String propertyName = event.propertyName();

		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) {
					this.dispatcher().propertyChanged(target, 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);
					}
					this.dispatcher().propertyChanged(target, 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));
					}
					this.dispatcher().propertyChanged(target, 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));
					}
					this.dispatcher().propertyChanged(target, 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.collectionName();

		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) {
					this.dispatcher().itemsAdded(target, 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);
					}
					this.dispatcher().itemsAdded(target, 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));
					}
					this.dispatcher().itemsAdded(target, 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.collectionName();

		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) {
					this.dispatcher().itemsRemoved(target, 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);
					}
					this.dispatcher().itemsRemoved(target, 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));
					}
					this.dispatcher().itemsRemoved(target, 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.collectionName();

		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) {
					this.dispatcher().collectionCleared(target, 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);
					}
					this.dispatcher().collectionCleared(target, 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.collectionName();

		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) {
					this.dispatcher().collectionChanged(target, 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);
					}
					this.dispatcher().collectionChanged(target, 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.listName();

		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) {
					this.dispatcher().itemsAdded(target, 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);
					}
					this.dispatcher().itemsAdded(target, 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));
					}
					this.dispatcher().itemsAdded(target, 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.listName();

		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) {
					this.dispatcher().itemsRemoved(target, 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);
					}
					this.dispatcher().itemsRemoved(target, 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));
					}
					this.dispatcher().itemsRemoved(target, 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.listName();

		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) {
					this.dispatcher().itemsReplaced(target, 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);
					}
					this.dispatcher().itemsReplaced(target, 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));
					}
					this.dispatcher().itemsReplaced(target, 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.targetIndex() == event.sourceIndex()) {
			return;
		}

		String listName = event.listName();

		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) {
					this.dispatcher().itemsMoved(target, 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);
					}
					this.dispatcher().itemsMoved(target, 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.listName();

		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) {
					this.dispatcher().listCleared(target, 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);
					}
					this.dispatcher().listCleared(target, 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.listName();

		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) {
					this.dispatcher().listChanged(target, 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);
					}
					this.dispatcher().listChanged(target, 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.treeName();

		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) {
					this.dispatcher().nodeAdded(target, 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);
					}
					this.dispatcher().nodeAdded(target, 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.treeName();

		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) {
					this.dispatcher().nodeRemoved(target, 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);
					}
					this.dispatcher().nodeRemoved(target, 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.treeName();

		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) {
					this.dispatcher().treeCleared(target, 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);
					}
					this.dispatcher().treeCleared(target, 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.treeName();

		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) {
					this.dispatcher().treeChanged(target, 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);
					}
					this.dispatcher().treeChanged(target, 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 len1 = this.genericListeners.length;
		for (int i = 0; i < len1; 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.addGenericListenerListInternal(listenerClass, (ChangeListener) o);
				} else {
					gll.addListener((ChangeListener) o);
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	private <T extends ChangeListener> GenericListenerList addGenericListenerListInternal(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);
		}

	}

}
