001 package data; 002 003 import java.beans.PropertyChangeListener; 004 import java.beans.PropertyChangeSupport; 005 006 /** 007 * Convenience class implementing the Nameable interface. 008 * 009 * <p>You should derive all your Nameable classes from this class, as it provides a 010 * complete implementation of the {@link Nameable} interface. However, there is no 011 * obligation to derive from this class, as long as your class implements Nameable and 012 * sticks to the contract defined in that interface.</p> 013 * 014 * @author Steffen Zschaler 015 * @version 2.0 25/05/1999 016 * @since v2.0 017 */ 018 public abstract class AbstractNameable extends Object implements Nameable { 019 020 /** 021 * Used to fire {@link java.beans.PropertyChangeEvent PropertyChangeEvents}. 022 * 023 * @serial 024 */ 025 protected PropertyChangeSupport m_pcsPropertyListeners = new PropertyChangeSupport(this); 026 027 /** 028 * The name of this object. 029 * 030 * @serial 031 */ 032 private String m_sName; 033 034 /** 035 * The current name context. 036 * 037 * @serial 038 */ 039 protected NameContext m_ncContext; 040 041 /** 042 * The monitor synchronizing access to the NameContext. 043 */ 044 private transient Object m_oNCLock; 045 046 /** 047 * Return the monitor synchronizing access to the NameContext. 048 * 049 * @override Never 050 */ 051 private final Object getNCLock() { 052 if (m_oNCLock == null) { 053 m_oNCLock = new Object(); 054 } 055 056 return m_oNCLock; 057 } 058 059 /** 060 * Initialize a new AbstractNameable object with a <code>null</code> name. 061 */ 062 public AbstractNameable() { 063 this(null); 064 } 065 066 /** 067 * Initialize a new AbstractNameable object with the given name. The name context will initially be 068 * <code>null</code>. 069 * 070 * @param sName the AbstractNameable's name. 071 */ 072 public AbstractNameable(String sName) { 073 super(); 074 075 m_sName = sName; 076 m_ncContext = null; 077 } 078 079 /** 080 * Attach a NameContext to this Nameable. 081 * 082 * <p>No naming conventions are checked neither in the old nor in the new NameContext.</p> 083 * 084 * <p>All access to the NameContext is synchronized for thread-safety.</p> 085 * 086 * @param nc the new NameContext of this Nameable object. 087 * 088 * @return the previous NameContext, if any. 089 * 090 * @override Never 091 */ 092 public NameContext attach(NameContext nc) { 093 synchronized (getNCLock()) { 094 NameContext ncOld = m_ncContext; 095 096 m_ncContext = nc; 097 098 return ncOld; 099 } 100 } 101 102 /** 103 * Detach the current NameContext from this Nameable. 104 * 105 * <p>All access to the NameContext is synchronized for thread-safety.</p> 106 * 107 * @return the previously attached NameContext, if any. 108 * 109 * @override Never 110 */ 111 public NameContext detachNC() { 112 return attach((NameContext)null); 113 } 114 115 /** 116 * Set the Nameable's name, using help by the NameContext. 117 * 118 * <p>All access to the NameContext is synchronized for thread-safety.</p> 119 * 120 * @param sName the new name of the object 121 * @param db the DataBasket relative to which the name change is to take place. 122 * 123 * @exception NameContextException if the name change was not approved of by the 124 * NameContext. 125 * 126 * @override Never 127 */ 128 public void setName(String sName, DataBasket db) throws NameContextException { 129 synchronized (getNCLock()) { 130 String sOld = m_sName; 131 132 if (m_ncContext != null) { 133 synchronized (m_ncContext.getNCMonitor()) { 134 135 m_ncContext.checkNameChange(db, sOld, sName); 136 137 m_sName = sName; 138 139 m_ncContext.nameHasChanged(db, sOld, sName); 140 } 141 } else { 142 m_sName = sName; 143 } 144 145 m_pcsPropertyListeners.firePropertyChange(NAME_PROPERTY, sOld, sName); 146 } 147 } 148 149 /** 150 * Get the name of the object. 151 * 152 * override Never 153 */ 154 public String getName() { 155 return m_sName; 156 } 157 158 /** 159 * Add a PropertyChangeListener that will receive events whenever a bound property changes. 160 * 161 * @override Never 162 */ 163 public void addPropertyChangeListener(PropertyChangeListener pcl) { 164 m_pcsPropertyListeners.addPropertyChangeListener(pcl); 165 } 166 167 /** 168 * Remove a PropertyChangeListener. 169 * 170 * @override Never 171 */ 172 public void removePropertyChangeListener(PropertyChangeListener pcl) { 173 m_pcsPropertyListeners.addPropertyChangeListener(pcl); 174 } 175 176 /** 177 * Add a PropertyChangeListener that will receive events whenever the "name" property changes. 178 * 179 * @override Never 180 */ 181 public void addNameListener(PropertyChangeListener pcl) { 182 m_pcsPropertyListeners.addPropertyChangeListener(NAME_PROPERTY, pcl); 183 } 184 185 /** 186 * Remove a PropertyChangeListener for the "name" property. 187 * 188 * @override Never 189 */ 190 public void removeNameListener(PropertyChangeListener pcl) { 191 m_pcsPropertyListeners.removePropertyChangeListener(NAME_PROPERTY, pcl); 192 } 193 }