src/share/classes/java/beans/VetoableChangeSupport.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) throws PropertyVetoException {
  64  *         String oldValue = this.value;
  65  *         this.vcs.fireVetoableChange("value", oldValue, newValue);
  66  *         this.value = newValue;
  67  *     }
  68  *
  69  *     [...]
  70  * }
  71  * }</pre>
  72  * <p>
  73  * A {@code VetoableChangeSupport} 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 PropertyChangeSupport

  80  */
  81 public class VetoableChangeSupport implements Serializable {
  82     private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
  83 
  84     /**
  85      * Constructs a <code>VetoableChangeSupport</code> object.
  86      *
  87      * @param sourceBean  The bean to be given as the source for any events.
  88      */
  89     public VetoableChangeSupport(Object sourceBean) {
  90         if (sourceBean == null) {
  91             throw new NullPointerException();
  92         }
  93         source = sourceBean;
  94     }
  95 
  96     /**
  97      * Add a VetoableChangeListener 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>VetoableChangeListeners</code> added or an
 175      *         empty array if no listeners have been added
 176      * @since 1.4
 177      */
 178     public VetoableChangeListener[] getVetoableChangeListeners(){
 179         return this.map.getListeners();
 180     }
 181 
 182     /**
 183      * Add a VetoableChangeListener for a specific property.  The listener
 184      * will be invoked only when a call on fireVetoableChange 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 VetoableChangeListener to be added

 194      */
 195     public void addVetoableChangeListener(
 196                                 String propertyName,
 197                 VetoableChangeListener 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 VetoableChangeListener 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 VetoableChangeListener to be removed

 219      */
 220     public void removeVetoableChangeListener(
 221                                 String propertyName,
 222                 VetoableChangeListener 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 the <code>VetoableChangeListeners</code> associated with
 238      *         the named property.  If no such listeners have been added,


 275     /**
 276      * Reports an integer constrained property update to listeners
 277      * that have been registered to track updates of
 278      * all properties or a property with the specified name.
 279      * <p>
 280      * Any listener can throw a {@code PropertyVetoException} to veto the update.
 281      * If one of the listeners vetoes the update, this method passes
 282      * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
 283      * to all listeners that already confirmed this update
 284      * and throws the {@code PropertyVetoException} again.
 285      * <p>
 286      * No event is fired if old and new values are equal.
 287      * <p>
 288      * This is merely a convenience wrapper around the more general
 289      * {@link #fireVetoableChange(String, Object, Object)} method.
 290      *
 291      * @param propertyName  the programmatic name of the property that is about to change
 292      * @param oldValue      the old value of the property
 293      * @param newValue      the new value of the property
 294      * @throws PropertyVetoException if one of listeners vetoes the property update

 295      */
 296     public void fireVetoableChange(String propertyName, int oldValue, int newValue)
 297             throws PropertyVetoException {
 298         if (oldValue != newValue) {
 299             fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
 300         }
 301     }
 302 
 303     /**
 304      * Reports a boolean constrained property update to listeners
 305      * that have been registered to track updates of
 306      * all properties or a property with the specified name.
 307      * <p>
 308      * Any listener can throw a {@code PropertyVetoException} to veto the update.
 309      * If one of the listeners vetoes the update, this method passes
 310      * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
 311      * to all listeners that already confirmed this update
 312      * and throws the {@code PropertyVetoException} again.
 313      * <p>
 314      * No event is fired if old and new values are equal.
 315      * <p>
 316      * This is merely a convenience wrapper around the more general
 317      * {@link #fireVetoableChange(String, Object, Object)} method.
 318      *
 319      * @param propertyName  the programmatic name of the property that is about to change
 320      * @param oldValue      the old value of the property
 321      * @param newValue      the new value of the property
 322      * @throws PropertyVetoException if one of listeners vetoes the property update

 323      */
 324     public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
 325             throws PropertyVetoException {
 326         if (oldValue != newValue) {
 327             fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
 328         }
 329     }
 330 
 331     /**
 332      * Fires a property change event to listeners
 333      * that have been registered to track updates of
 334      * all properties or a property with the specified name.
 335      * <p>
 336      * Any listener can throw a {@code PropertyVetoException} to veto the update.
 337      * If one of the listeners vetoes the update, this method passes
 338      * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
 339      * to all listeners that already confirmed this update
 340      * and throws the {@code PropertyVetoException} again.
 341      * <p>
 342      * No event is fired if the given event's old and new values are equal and non-null.
 343      *
 344      * @param event  the {@code PropertyChangeEvent} to be fired
 345      * @throws PropertyVetoException if one of listeners vetoes the property update

 346      */
 347     public void fireVetoableChange(PropertyChangeEvent event)
 348             throws PropertyVetoException {
 349         Object oldValue = event.getOldValue();
 350         Object newValue = event.getNewValue();
 351         if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
 352             String name = event.getPropertyName();
 353 
 354             VetoableChangeListener[] common = this.map.get(null);
 355             VetoableChangeListener[] named = (name != null)
 356                         ? this.map.get(name)
 357                         : null;
 358 
 359             VetoableChangeListener[] listeners;
 360             if (common == null) {
 361                 listeners = named;
 362             }
 363             else if (named == null) {
 364                 listeners = common;
 365             }


 382                         try {
 383                             listeners[i].vetoableChange(event);
 384                         }
 385                         catch (PropertyVetoException exception) {
 386                             // ignore exceptions that occur during rolling back
 387                         }
 388                     }
 389                     throw veto; // rethrow the veto exception
 390                 }
 391             }
 392         }
 393     }
 394 
 395     /**
 396      * Check if there are any listeners for a specific property, including
 397      * those registered on all properties.  If <code>propertyName</code>
 398      * is null, only check for listeners registered on all properties.
 399      *
 400      * @param propertyName  the property name.
 401      * @return true if there are one or more listeners for the given property

 402      */
 403     public boolean hasListeners(String propertyName) {
 404         return this.map.hasListeners(propertyName);
 405     }
 406 
 407     /**
 408      * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
 409      * <p>
 410      * At serialization time we skip non-serializable listeners and
 411      * only serialize the serializable listeners.
 412      */
 413     private void writeObject(ObjectOutputStream s) throws IOException {
 414         Hashtable<String, VetoableChangeSupport> children = null;
 415         VetoableChangeListener[] listeners = null;
 416         synchronized (this.map) {
 417             for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
 418                 String property = entry.getKey();
 419                 if (property == null) {
 420                     listeners = entry.getValue();
 421                 } else {




  60  *         return this.value;
  61  *     }
  62  *
  63  *     public void setValue(String newValue) throws PropertyVetoException {
  64  *         String oldValue = this.value;
  65  *         this.vcs.fireVetoableChange("value", oldValue, newValue);
  66  *         this.value = newValue;
  67  *     }
  68  *
  69  *     [...]
  70  * }
  71  * }</pre>
  72  * <p>
  73  * A {@code VetoableChangeSupport} 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 PropertyChangeSupport
  80  * @since 1.1
  81  */
  82 public class VetoableChangeSupport implements Serializable {
  83     private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
  84 
  85     /**
  86      * Constructs a <code>VetoableChangeSupport</code> object.
  87      *
  88      * @param sourceBean  The bean to be given as the source for any events.
  89      */
  90     public VetoableChangeSupport(Object sourceBean) {
  91         if (sourceBean == null) {
  92             throw new NullPointerException();
  93         }
  94         source = sourceBean;
  95     }
  96 
  97     /**
  98      * Add a VetoableChangeListener 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>VetoableChangeListeners</code> added or an
 176      *         empty array if no listeners have been added
 177      * @since 1.4
 178      */
 179     public VetoableChangeListener[] getVetoableChangeListeners(){
 180         return this.map.getListeners();
 181     }
 182 
 183     /**
 184      * Add a VetoableChangeListener for a specific property.  The listener
 185      * will be invoked only when a call on fireVetoableChange 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 VetoableChangeListener to be added
 195      * @since 1.2
 196      */
 197     public void addVetoableChangeListener(
 198                                 String propertyName,
 199                 VetoableChangeListener 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 VetoableChangeListener 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 VetoableChangeListener to be removed
 221      * @since 1.2
 222      */
 223     public void removeVetoableChangeListener(
 224                                 String propertyName,
 225                 VetoableChangeListener 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 the <code>VetoableChangeListeners</code> associated with
 241      *         the named property.  If no such listeners have been added,


 278     /**
 279      * Reports an integer constrained property update to listeners
 280      * that have been registered to track updates of
 281      * all properties or a property with the specified name.
 282      * <p>
 283      * Any listener can throw a {@code PropertyVetoException} to veto the update.
 284      * If one of the listeners vetoes the update, this method passes
 285      * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
 286      * to all listeners that already confirmed this update
 287      * and throws the {@code PropertyVetoException} again.
 288      * <p>
 289      * No event is fired if old and new values are equal.
 290      * <p>
 291      * This is merely a convenience wrapper around the more general
 292      * {@link #fireVetoableChange(String, Object, Object)} method.
 293      *
 294      * @param propertyName  the programmatic name of the property that is about to change
 295      * @param oldValue      the old value of the property
 296      * @param newValue      the new value of the property
 297      * @throws PropertyVetoException if one of listeners vetoes the property update
 298      * @since 1.2
 299      */
 300     public void fireVetoableChange(String propertyName, int oldValue, int newValue)
 301             throws PropertyVetoException {
 302         if (oldValue != newValue) {
 303             fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
 304         }
 305     }
 306 
 307     /**
 308      * Reports a boolean constrained property update to listeners
 309      * that have been registered to track updates of
 310      * all properties or a property with the specified name.
 311      * <p>
 312      * Any listener can throw a {@code PropertyVetoException} to veto the update.
 313      * If one of the listeners vetoes the update, this method passes
 314      * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
 315      * to all listeners that already confirmed this update
 316      * and throws the {@code PropertyVetoException} again.
 317      * <p>
 318      * No event is fired if old and new values are equal.
 319      * <p>
 320      * This is merely a convenience wrapper around the more general
 321      * {@link #fireVetoableChange(String, Object, Object)} method.
 322      *
 323      * @param propertyName  the programmatic name of the property that is about to change
 324      * @param oldValue      the old value of the property
 325      * @param newValue      the new value of the property
 326      * @throws PropertyVetoException if one of listeners vetoes the property update
 327      * @since 1.2
 328      */
 329     public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
 330             throws PropertyVetoException {
 331         if (oldValue != newValue) {
 332             fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
 333         }
 334     }
 335 
 336     /**
 337      * Fires a property change event to listeners
 338      * that have been registered to track updates of
 339      * all properties or a property with the specified name.
 340      * <p>
 341      * Any listener can throw a {@code PropertyVetoException} to veto the update.
 342      * If one of the listeners vetoes the update, this method passes
 343      * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
 344      * to all listeners that already confirmed this update
 345      * and throws the {@code PropertyVetoException} again.
 346      * <p>
 347      * No event is fired if the given event's old and new values are equal and non-null.
 348      *
 349      * @param event  the {@code PropertyChangeEvent} to be fired
 350      * @throws PropertyVetoException if one of listeners vetoes the property update
 351      * @since 1.2
 352      */
 353     public void fireVetoableChange(PropertyChangeEvent event)
 354             throws PropertyVetoException {
 355         Object oldValue = event.getOldValue();
 356         Object newValue = event.getNewValue();
 357         if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
 358             String name = event.getPropertyName();
 359 
 360             VetoableChangeListener[] common = this.map.get(null);
 361             VetoableChangeListener[] named = (name != null)
 362                         ? this.map.get(name)
 363                         : null;
 364 
 365             VetoableChangeListener[] listeners;
 366             if (common == null) {
 367                 listeners = named;
 368             }
 369             else if (named == null) {
 370                 listeners = common;
 371             }


 388                         try {
 389                             listeners[i].vetoableChange(event);
 390                         }
 391                         catch (PropertyVetoException exception) {
 392                             // ignore exceptions that occur during rolling back
 393                         }
 394                     }
 395                     throw veto; // rethrow the veto exception
 396                 }
 397             }
 398         }
 399     }
 400 
 401     /**
 402      * Check if there are any listeners for a specific property, including
 403      * those registered on all properties.  If <code>propertyName</code>
 404      * is null, only check for listeners registered on all properties.
 405      *
 406      * @param propertyName  the property name.
 407      * @return true if there are one or more listeners for the given property
 408      * @since 1.2
 409      */
 410     public boolean hasListeners(String propertyName) {
 411         return this.map.hasListeners(propertyName);
 412     }
 413 
 414     /**
 415      * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
 416      * <p>
 417      * At serialization time we skip non-serializable listeners and
 418      * only serialize the serializable listeners.
 419      */
 420     private void writeObject(ObjectOutputStream s) throws IOException {
 421         Hashtable<String, VetoableChangeSupport> children = null;
 422         VetoableChangeListener[] listeners = null;
 423         synchronized (this.map) {
 424             for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
 425                 String property = entry.getKey();
 426                 if (property == null) {
 427                     listeners = entry.getValue();
 428                 } else {