package data; import java.beans.*; /** * Convenience class implementing the Nameable interface. * * <p>You should derive all your Nameable classes from this class, as it provides a * complete implementation of the {@link Nameable} interface. However, there is no * obligation to derive from this class, as long as your class implements Nameable and * sticks to the contract defined in that interface.</p> * * @author Steffen Zschaler * @version 2.0 25/05/1999 * @since v2.0 */ public abstract class AbstractNameable extends Object implements Nameable { /** * Used to fire {@link java.beans.PropertyChangeEvent PropertyChangeEvents}. * * @serial */ protected PropertyChangeSupport m_pcsPropertyListeners = new PropertyChangeSupport (this); /** * The name of this object. * * @serial */ private String m_sName; /** * The current name context. * * @serial */ protected NameContext m_ncContext; /** * The monitor synchronizing access to the NameContext. */ private transient Object m_oNCLock; /** * Return the monitor synchronizing access to the NameContext. * * @override Never */ private final Object getNCLock() { if (m_oNCLock == null) { m_oNCLock = new Object(); } return m_oNCLock; } /** * Initialize a new AbstractNameable object with a <code>null</code> name. */ public AbstractNameable() { this (null); } /** * Initialize a new AbstractNameable object with the given name. The name context will initially be * <code>null</code>. * * @param sName the AbstractNameable's name. */ public AbstractNameable (String sName) { super(); m_sName = sName; m_ncContext = null; } /** * Attach a NameContext to this Nameable. * * <p>No naming conventions are checked neither in the old nor in the new NameContext.</p> * * <p>All access to the NameContext is synchronized for thread-safety.</p> * * @param nc the new NameContext of this Nameable object. * * @return the previous NameContext, if any. * * @override Never */ public NameContext attach (NameContext nc) { synchronized (getNCLock()) { NameContext ncOld = m_ncContext; m_ncContext = nc; return ncOld; } } /** * Detach the current NameContext from this Nameable. * * <p>All access to the NameContext is synchronized for thread-safety.</p> * * @return the previously attached NameContext, if any. * * @override Never */ public NameContext detachNC() { return attach ((NameContext) null); } /** * Set the Nameable's name, using help by the NameContext. * * <p>All access to the NameContext is synchronized for thread-safety.</p> * * @param sName the new name of the object * @param db the DataBasket relative to which the name change is to take place. * * @exception NameContextException if the name change was not approved of by the * NameContext. * * @override Never */ public void setName (String sName, DataBasket db) throws NameContextException { synchronized (getNCLock()) { String sOld = m_sName; if (m_ncContext != null) { synchronized (m_ncContext.getNCMonitor()) { m_ncContext.checkNameChange (db, sOld, sName); m_sName = sName; m_ncContext.nameHasChanged (db, sOld, sName); } } else { m_sName = sName; } m_pcsPropertyListeners.firePropertyChange (NAME_PROPERTY, sOld, sName); } } /** * Get the name of the object. * * override Never */ public String getName() { return m_sName; } /** * Add a PropertyChangeListener that will receive events whenever a bound property changes. * * @override Never */ public void addPropertyChangeListener (PropertyChangeListener pcl) { m_pcsPropertyListeners.addPropertyChangeListener (pcl); } /** * Remove a PropertyChangeListener. * * @override Never */ public void removePropertyChangeListener (PropertyChangeListener pcl) { m_pcsPropertyListeners.addPropertyChangeListener (pcl); } /** * Add a PropertyChangeListener that will receive events whenever the "name" property changes. * * @override Never */ public void addNameListener (PropertyChangeListener pcl) { m_pcsPropertyListeners.addPropertyChangeListener (NAME_PROPERTY, pcl); } /** * Remove a PropertyChangeListener for the "name" property. * * @override Never */ public void removeNameListener (PropertyChangeListener pcl) { m_pcsPropertyListeners.removePropertyChangeListener (NAME_PROPERTY, pcl); } }