src/share/classes/java/beans/PropertyChangeSupport.java

Print this page
rev 10053 : 8044855: Add missing @since tag under java.beans.*
Reviewed-by:


  60  *         return this.value;
  61  *     }
  62  *
  63  *     public void setValue(String newValue) {
  64  *         String oldValue = this.value;
  65  *         this.value = newValue;
  66  *         this.pcs.firePropertyChange("value", oldValue, newValue);
  67  *     }
  68  *
  69  *     [...]
  70  * }
  71  * </pre>
  72  * <p>
  73  * A {@code PropertyChangeSupport} instance is thread-safe.
  74  * <p>
  75  * This class is serializable.  When it is serialized it will save
  76  * (and restore) any listeners that are themselves serializable.  Any
  77  * non-serializable listeners will be skipped during serialization.
  78  *
  79  * @see VetoableChangeSupport

  80  */
  81 public class PropertyChangeSupport implements Serializable {
  82     private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
  83 
  84     /**
  85      * Constructs a <code>PropertyChangeSupport</code> object.
  86      *
  87      * @param sourceBean  The bean to be given as the source for any events.
  88      */
  89     public PropertyChangeSupport(Object sourceBean) {
  90         if (sourceBean == null) {
  91             throw new NullPointerException();
  92         }
  93         source = sourceBean;
  94     }
  95 
  96     /**
  97      * Add a PropertyChangeListener to the listener list.
  98      * The listener is registered for all properties.
  99      * The same listener object may be added more than once, and will be called


 174      * @return all of the <code>PropertyChangeListeners</code> added or an
 175      *         empty array if no listeners have been added
 176      * @since 1.4
 177      */
 178     public PropertyChangeListener[] getPropertyChangeListeners() {
 179         return this.map.getListeners();
 180     }
 181 
 182     /**
 183      * Add a PropertyChangeListener for a specific property.  The listener
 184      * will be invoked only when a call on firePropertyChange names that
 185      * specific property.
 186      * The same listener object may be added more than once.  For each
 187      * property,  the listener will be invoked the number of times it was added
 188      * for that property.
 189      * If <code>propertyName</code> or <code>listener</code> is null, no
 190      * exception is thrown and no action is taken.
 191      *
 192      * @param propertyName  The name of the property to listen on.
 193      * @param listener  The PropertyChangeListener to be added

 194      */
 195     public void addPropertyChangeListener(
 196                 String propertyName,
 197                 PropertyChangeListener listener) {
 198         if (listener == null || propertyName == null) {
 199             return;
 200         }
 201         listener = this.map.extract(listener);
 202         if (listener != null) {
 203             this.map.add(propertyName, listener);
 204         }
 205     }
 206 
 207     /**
 208      * Remove a PropertyChangeListener for a specific property.
 209      * If <code>listener</code> was added more than once to the same event
 210      * source for the specified property, it will be notified one less time
 211      * after being removed.
 212      * If <code>propertyName</code> is null,  no exception is thrown and no
 213      * action is taken.
 214      * If <code>listener</code> is null, or was never added for the specified
 215      * property, no exception is thrown and no action is taken.
 216      *
 217      * @param propertyName  The name of the property that was listened on.
 218      * @param listener  The PropertyChangeListener to be removed

 219      */
 220     public void removePropertyChangeListener(
 221                 String propertyName,
 222                 PropertyChangeListener listener) {
 223         if (listener == null || propertyName == null) {
 224             return;
 225         }
 226         listener = this.map.extract(listener);
 227         if (listener != null) {
 228             this.map.remove(propertyName, listener);
 229         }
 230     }
 231 
 232     /**
 233      * Returns an array of all the listeners which have been associated
 234      * with the named property.
 235      *
 236      * @param propertyName  The name of the property being listened to
 237      * @return all of the <code>PropertyChangeListeners</code> associated with
 238      *         the named property.  If no such listeners have been added,


 260      */
 261     public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
 262         if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
 263             firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
 264         }
 265     }
 266 
 267     /**
 268      * Reports an integer bound property update to listeners
 269      * that have been registered to track updates of
 270      * all properties or a property with the specified name.
 271      * <p>
 272      * No event is fired if old and new values are equal.
 273      * <p>
 274      * This is merely a convenience wrapper around the more general
 275      * {@link #firePropertyChange(String, Object, Object)}  method.
 276      *
 277      * @param propertyName  the programmatic name of the property that was changed
 278      * @param oldValue      the old value of the property
 279      * @param newValue      the new value of the property

 280      */
 281     public void firePropertyChange(String propertyName, int oldValue, int newValue) {
 282         if (oldValue != newValue) {
 283             firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
 284         }
 285     }
 286 
 287     /**
 288      * Reports a boolean bound property update to listeners
 289      * that have been registered to track updates of
 290      * all properties or a property with the specified name.
 291      * <p>
 292      * No event is fired if old and new values are equal.
 293      * <p>
 294      * This is merely a convenience wrapper around the more general
 295      * {@link #firePropertyChange(String, Object, Object)}  method.
 296      *
 297      * @param propertyName  the programmatic name of the property that was changed
 298      * @param oldValue      the old value of the property
 299      * @param newValue      the new value of the property

 300      */
 301     public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
 302         if (oldValue != newValue) {
 303             firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
 304         }
 305     }
 306 
 307     /**
 308      * Fires a property change event to listeners
 309      * that have been registered to track updates of
 310      * all properties or a property with the specified name.
 311      * <p>
 312      * No event is fired if the given event's old and new values are equal and non-null.
 313      *
 314      * @param event  the {@code PropertyChangeEvent} to be fired

 315      */
 316     public void firePropertyChange(PropertyChangeEvent event) {
 317         Object oldValue = event.getOldValue();
 318         Object newValue = event.getNewValue();
 319         if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
 320             String name = event.getPropertyName();
 321 
 322             PropertyChangeListener[] common = this.map.get(null);
 323             PropertyChangeListener[] named = (name != null)
 324                         ? this.map.get(name)
 325                         : null;
 326 
 327             fire(common, event);
 328             fire(named, event);
 329         }
 330     }
 331 
 332     private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
 333         if (listeners != null) {
 334             for (PropertyChangeListener listener : listeners) {


 393      *
 394      * @param propertyName  the programmatic name of the property that was changed
 395      * @param index         the index of the property element that was changed
 396      * @param oldValue      the old value of the property
 397      * @param newValue      the new value of the property
 398      * @since 1.5
 399      */
 400     public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
 401         if (oldValue != newValue) {
 402             fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
 403         }
 404     }
 405 
 406     /**
 407      * Check if there are any listeners for a specific property, including
 408      * those registered on all properties.  If <code>propertyName</code>
 409      * is null, only check for listeners registered on all properties.
 410      *
 411      * @param propertyName  the property name.
 412      * @return true if there are one or more listeners for the given property

 413      */
 414     public boolean hasListeners(String propertyName) {
 415         return this.map.hasListeners(propertyName);
 416     }
 417 
 418     /**
 419      * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
 420      * <p>
 421      * At serialization time we skip non-serializable listeners and
 422      * only serialize the serializable listeners.
 423      */
 424     private void writeObject(ObjectOutputStream s) throws IOException {
 425         Hashtable<String, PropertyChangeSupport> children = null;
 426         PropertyChangeListener[] listeners = null;
 427         synchronized (this.map) {
 428             for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
 429                 String property = entry.getKey();
 430                 if (property == null) {
 431                     listeners = entry.getValue();
 432                 } else {




  60  *         return this.value;
  61  *     }
  62  *
  63  *     public void setValue(String newValue) {
  64  *         String oldValue = this.value;
  65  *         this.value = newValue;
  66  *         this.pcs.firePropertyChange("value", oldValue, newValue);
  67  *     }
  68  *
  69  *     [...]
  70  * }
  71  * </pre>
  72  * <p>
  73  * A {@code PropertyChangeSupport} instance is thread-safe.
  74  * <p>
  75  * This class is serializable.  When it is serialized it will save
  76  * (and restore) any listeners that are themselves serializable.  Any
  77  * non-serializable listeners will be skipped during serialization.
  78  *
  79  * @see VetoableChangeSupport
  80  * @since 1.1
  81  */
  82 public class PropertyChangeSupport implements Serializable {
  83     private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
  84 
  85     /**
  86      * Constructs a <code>PropertyChangeSupport</code> object.
  87      *
  88      * @param sourceBean  The bean to be given as the source for any events.
  89      */
  90     public PropertyChangeSupport(Object sourceBean) {
  91         if (sourceBean == null) {
  92             throw new NullPointerException();
  93         }
  94         source = sourceBean;
  95     }
  96 
  97     /**
  98      * Add a PropertyChangeListener to the listener list.
  99      * The listener is registered for all properties.
 100      * The same listener object may be added more than once, and will be called


 175      * @return all of the <code>PropertyChangeListeners</code> added or an
 176      *         empty array if no listeners have been added
 177      * @since 1.4
 178      */
 179     public PropertyChangeListener[] getPropertyChangeListeners() {
 180         return this.map.getListeners();
 181     }
 182 
 183     /**
 184      * Add a PropertyChangeListener for a specific property.  The listener
 185      * will be invoked only when a call on firePropertyChange names that
 186      * specific property.
 187      * The same listener object may be added more than once.  For each
 188      * property,  the listener will be invoked the number of times it was added
 189      * for that property.
 190      * If <code>propertyName</code> or <code>listener</code> is null, no
 191      * exception is thrown and no action is taken.
 192      *
 193      * @param propertyName  The name of the property to listen on.
 194      * @param listener  The PropertyChangeListener to be added
 195      * @since 1.2
 196      */
 197     public void addPropertyChangeListener(
 198                 String propertyName,
 199                 PropertyChangeListener listener) {
 200         if (listener == null || propertyName == null) {
 201             return;
 202         }
 203         listener = this.map.extract(listener);
 204         if (listener != null) {
 205             this.map.add(propertyName, listener);
 206         }
 207     }
 208 
 209     /**
 210      * Remove a PropertyChangeListener for a specific property.
 211      * If <code>listener</code> was added more than once to the same event
 212      * source for the specified property, it will be notified one less time
 213      * after being removed.
 214      * If <code>propertyName</code> is null,  no exception is thrown and no
 215      * action is taken.
 216      * If <code>listener</code> is null, or was never added for the specified
 217      * property, no exception is thrown and no action is taken.
 218      *
 219      * @param propertyName  The name of the property that was listened on.
 220      * @param listener  The PropertyChangeListener to be removed
 221      * @since 1.2
 222      */
 223     public void removePropertyChangeListener(
 224                 String propertyName,
 225                 PropertyChangeListener listener) {
 226         if (listener == null || propertyName == null) {
 227             return;
 228         }
 229         listener = this.map.extract(listener);
 230         if (listener != null) {
 231             this.map.remove(propertyName, listener);
 232         }
 233     }
 234 
 235     /**
 236      * Returns an array of all the listeners which have been associated
 237      * with the named property.
 238      *
 239      * @param propertyName  The name of the property being listened to
 240      * @return all of the <code>PropertyChangeListeners</code> associated with
 241      *         the named property.  If no such listeners have been added,


 263      */
 264     public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
 265         if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
 266             firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
 267         }
 268     }
 269 
 270     /**
 271      * Reports an integer bound property update to listeners
 272      * that have been registered to track updates of
 273      * all properties or a property with the specified name.
 274      * <p>
 275      * No event is fired if old and new values are equal.
 276      * <p>
 277      * This is merely a convenience wrapper around the more general
 278      * {@link #firePropertyChange(String, Object, Object)}  method.
 279      *
 280      * @param propertyName  the programmatic name of the property that was changed
 281      * @param oldValue      the old value of the property
 282      * @param newValue      the new value of the property
 283      * @since 1.2
 284      */
 285     public void firePropertyChange(String propertyName, int oldValue, int newValue) {
 286         if (oldValue != newValue) {
 287             firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
 288         }
 289     }
 290 
 291     /**
 292      * Reports a boolean bound property update to listeners
 293      * that have been registered to track updates of
 294      * all properties or a property with the specified name.
 295      * <p>
 296      * No event is fired if old and new values are equal.
 297      * <p>
 298      * This is merely a convenience wrapper around the more general
 299      * {@link #firePropertyChange(String, Object, Object)}  method.
 300      *
 301      * @param propertyName  the programmatic name of the property that was changed
 302      * @param oldValue      the old value of the property
 303      * @param newValue      the new value of the property
 304      * @since 1.2
 305      */
 306     public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
 307         if (oldValue != newValue) {
 308             firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
 309         }
 310     }
 311 
 312     /**
 313      * Fires a property change event to listeners
 314      * that have been registered to track updates of
 315      * all properties or a property with the specified name.
 316      * <p>
 317      * No event is fired if the given event's old and new values are equal and non-null.
 318      *
 319      * @param event  the {@code PropertyChangeEvent} to be fired
 320      * @since 1.2
 321      */
 322     public void firePropertyChange(PropertyChangeEvent event) {
 323         Object oldValue = event.getOldValue();
 324         Object newValue = event.getNewValue();
 325         if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
 326             String name = event.getPropertyName();
 327 
 328             PropertyChangeListener[] common = this.map.get(null);
 329             PropertyChangeListener[] named = (name != null)
 330                         ? this.map.get(name)
 331                         : null;
 332 
 333             fire(common, event);
 334             fire(named, event);
 335         }
 336     }
 337 
 338     private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
 339         if (listeners != null) {
 340             for (PropertyChangeListener listener : listeners) {


 399      *
 400      * @param propertyName  the programmatic name of the property that was changed
 401      * @param index         the index of the property element that was changed
 402      * @param oldValue      the old value of the property
 403      * @param newValue      the new value of the property
 404      * @since 1.5
 405      */
 406     public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
 407         if (oldValue != newValue) {
 408             fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
 409         }
 410     }
 411 
 412     /**
 413      * Check if there are any listeners for a specific property, including
 414      * those registered on all properties.  If <code>propertyName</code>
 415      * is null, only check for listeners registered on all properties.
 416      *
 417      * @param propertyName  the property name.
 418      * @return true if there are one or more listeners for the given property
 419      * @since 1.2
 420      */
 421     public boolean hasListeners(String propertyName) {
 422         return this.map.hasListeners(propertyName);
 423     }
 424 
 425     /**
 426      * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
 427      * <p>
 428      * At serialization time we skip non-serializable listeners and
 429      * only serialize the serializable listeners.
 430      */
 431     private void writeObject(ObjectOutputStream s) throws IOException {
 432         Hashtable<String, PropertyChangeSupport> children = null;
 433         PropertyChangeListener[] listeners = null;
 434         synchronized (this.map) {
 435             for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
 436                 String property = entry.getKey();
 437                 if (property == null) {
 438                     listeners = entry.getValue();
 439                 } else {