/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package Sirius.navigator.tools;
import Sirius.server.middleware.types.MetaObject;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* DOCUMENT ME!
*
* @author martin.scholl@cismet.de
* @version $Revision$, $Date$
*/
public final class MetaObjectChangeSupport {
//~ Enums ------------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private enum Change {
//~ Enum constants -----------------------------------------------------
ADDED, CHANGED, REMOVED
}
//~ Instance fields --------------------------------------------------------
private final transient Set<MetaObjectChangeListener> listeners;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new MetaObjectChangeSupport object.
*/
public MetaObjectChangeSupport() {
listeners = new HashSet<MetaObjectChangeListener>();
}
//~ Methods ----------------------------------------------------------------
/**
* Adds the given {@link MetaObjectChangeListener} to the set of listeners.
*
* @param mocL the listener to add
*/
public void addMetaObjectChangeListener(final MetaObjectChangeListener mocL) {
synchronized (listeners) {
listeners.add(mocL);
}
}
/**
* Removes the given {@link MetaObjectChangeListener} from the set of listeners.
*
* @param mocL the listener to remove
*/
public void removeMetaObjectChangeListener(final MetaObjectChangeListener mocL) {
synchronized (listeners) {
listeners.remove(mocL);
}
}
/**
* Fires the given {@link MetaObjectChangeEvent} to all registered listeners. This operation assures that the <code>
* MetaObjectChangeEvent</code> is properly initialised. In case of removed there has to be the source object and
* the old and the new {@link MetaObject}.
*
* @param moce the <code>MetaObjectChangeEvent</code> to be fired
*
* @throws IllegalArgumentException if the given event does not have a source object or an old or a new <code>
* MetaObject</code>
*/
public void fireMetaObjectChanged(final MetaObjectChangeEvent moce) {
if (moce.getOldMetaObject() == null) {
throw new IllegalArgumentException(
"fireMetaObjectChanged invocation with MetaObjectChangeEvent object without old metaobject illegal: " // NOI18N
+ moce);
} else if (moce.getNewMetaObject() == null) {
throw new IllegalArgumentException(
"fireMetaObjectChanged invocation with MetaObjectChangeEvent object without new metaobject illegal: " // NOI18N
+ moce);
}
doFireMetaObjectChanged(moce, Change.ADDED);
}
/**
* Fires the given {@link MetaObjectChangeEvent} to all registered listeners. This operation assures that the <code>
* MetaObjectChangeEvent</code> is properly initialised. In case of added there has to be the source object and the
* new {@link MetaObject}.
*
* @param moce the <code>MetaObjectChangeEvent</code> to be fired
*
* @throws IllegalArgumentException if the given event does not have a source object or a new <code>
* MetaObject</code>
*/
public void fireMetaObjectAdded(final MetaObjectChangeEvent moce) {
if (moce.getNewMetaObject() == null) {
throw new IllegalArgumentException(
"fireMetaObjectAdded invocation with MetaObjectChangeEvent object without new metaobject illegal: " // NOI18N
+ moce);
}
doFireMetaObjectChanged(moce, Change.CHANGED);
}
/**
* Fires the given {@link MetaObjectChangeEvent} to all registered listeners. This operation assures that the <code>
* MetaObjectChangeEvent</code> is properly initialised. In case of removed there has to be the source object and
* the old {@link MetaObject}.
*
* @param moce the <code>MetaObjectChangeEvent</code> to be fired
*
* @throws IllegalArgumentException if the given event does not have a source object or an old <code>
* MetaObject</code>
*/
public void fireMetaObjectRemoved(final MetaObjectChangeEvent moce) {
if (moce.getOldMetaObject() == null) {
throw new IllegalArgumentException(
"fireMetaObjectRemoved invocation with MetaObjectChangeEvent object without old metaobject illegal: " // NOI18N
+ moce);
}
doFireMetaObjectChanged(moce, Change.REMOVED);
}
/**
* Assures that the source of the {@link MetaObjectChangeEvent} has been set and fires an appropriate change to all
* listeners.
*
* @param moce DOCUMENT ME!
* @param change DOCUMENT ME!
*
* @throws IllegalArgumentException if the <code>MetaObjectChangeEvent</code> does not have a source object or the
* give change object is unknown (which only happens if somebody alters the enum
* and does not add another case here).
*/
private void doFireMetaObjectChanged(final MetaObjectChangeEvent moce, final Change change) {
if (moce.getSource() == null) {
throw new IllegalArgumentException("MetaObjectChangeEvent objects without source are illegal"); // NOI18N
}
final Iterator<MetaObjectChangeListener> it;
synchronized (listeners) {
it = new HashSet<MetaObjectChangeListener>(listeners).iterator();
}
while (it.hasNext()) {
// no switch, if is faster
if (Change.ADDED == change) {
it.next().metaObjectAdded(moce);
} else if (Change.CHANGED == change) {
it.next().metaObjectChanged(moce);
} else if (Change.REMOVED == change) {
it.next().metaObjectRemoved(moce);
} else {
throw new IllegalArgumentException("unknown change: " + change); // NOI18N
}
}
}
/**
* Returns the default instance of the <code>MetaObjectChangeSupport</code> which should be used by default
* components to register their interest in meta object changes.
*
* @return the default instance of <code>MetaObjectChangeSupport</code>
*/
public static MetaObjectChangeSupport getDefault() {
return LazyInitialiser.INSTANCE;
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private static final class LazyInitialiser {
//~ Static fields/initializers -----------------------------------------
private static final MetaObjectChangeSupport INSTANCE = new MetaObjectChangeSupport();
//~ Constructors -------------------------------------------------------
/**
* Creates a new LazyInitialiser object.
*/
private LazyInitialiser() {
}
}
}