home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / beans / VetoableChangeSupport.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  9.6 KB  |  311 lines

  1. /*
  2.  * @(#)VetoableChangeSupport.java    1.26 98/03/18
  3.  *
  4.  * Copyright 1996, 1997 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.beans;
  16.  
  17. import java.io.Serializable;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21.  
  22.  
  23. /**
  24.  * This is a utility class that can be used by beans that support constrained
  25.  * properties.  You can use an instance of this class as a member field
  26.  * of your bean and delegate various work to it.
  27.  */
  28.  
  29. public class VetoableChangeSupport implements java.io.Serializable {
  30.  
  31.     /**
  32.      * @param sourceBean  The bean to be given as the source for any events.
  33.      */
  34.  
  35.     public VetoableChangeSupport(Object sourceBean) {
  36.     if (sourceBean == null) {
  37.         throw new NullPointerException();
  38.     }
  39.     source = sourceBean;
  40.     }
  41.  
  42.     /**
  43.      * Add a VetoableListener to the listener list.
  44.      * The listener is registered for all properties.
  45.      *
  46.      * @param listener  The VetoableChangeListener to be added
  47.      */
  48.  
  49.     public synchronized void addVetoableChangeListener(
  50.                     VetoableChangeListener listener) {
  51.     if (listeners == null) {
  52.         listeners = new java.util.Vector();
  53.     }
  54.     listeners.addElement(listener);
  55.     }
  56.  
  57.     /**
  58.      * Remove a VetoableChangeListener from the listener list.
  59.      * This removes a PropertyChangeListener that was registered
  60.      * for all properties.
  61.      *
  62.      * @param listener  The VetoableChangeListener to be removed
  63.      */
  64.     public synchronized void removeVetoableChangeListener(
  65.                     VetoableChangeListener listener) {
  66.     if (listeners == null) {
  67.         return;
  68.     }
  69.     listeners.removeElement(listener);
  70.     }
  71.  
  72.  
  73.     /**
  74.      * Add a VetoableChangeListener for a specific property.  The listener
  75.      * will be invoked only when a call on fireVetoableChange names that
  76.      * specific property.
  77.      *
  78.      * @param propertyName  The name of the property to listen on.
  79.      * @param listener  The VetoableChangeListener to be added
  80.      */
  81.  
  82.     public synchronized void addVetoableChangeListener(
  83.                 String propertyName,
  84.                 VetoableChangeListener listener) {
  85.     if (children == null) {
  86.         children = new java.util.Hashtable();
  87.     }
  88.     VetoableChangeSupport child = (VetoableChangeSupport)children.get(propertyName);
  89.     if (child == null) {
  90.         child = new VetoableChangeSupport(source);
  91.         children.put(propertyName, child);
  92.     }
  93.     child.addVetoableChangeListener(listener);
  94.     }
  95.  
  96.     /**
  97.      * Remove a VetoableChangeListener for a specific property.
  98.      *
  99.      * @param propertyName  The name of the property that was listened on.
  100.      * @param listener  The VetoableChangeListener to be removed
  101.      */
  102.  
  103.     public synchronized void removeVetoableChangeListener(
  104.                 String propertyName,
  105.                 VetoableChangeListener listener) {
  106.     if (children == null) {
  107.         return;
  108.     }
  109.     VetoableChangeSupport child = (VetoableChangeSupport)children.get(propertyName);
  110.     if (child == null) {
  111.         return;
  112.     }
  113.     child.removeVetoableChangeListener(listener);
  114.     }
  115.  
  116.  
  117.     /**
  118.      * Report a vetoable property update to any registered listeners.  If
  119.      * anyone vetos the change, then fire a new event reverting everyone to 
  120.      * the old value and then rethrow the PropertyVetoException.
  121.      * <p>
  122.      * No event is fired if old and new are equal and non-null.
  123.      *
  124.      * @param propertyName  The programmatic name of the property
  125.      *        that is about to change..
  126.      * @param oldValue  The old value of the property.
  127.      * @param newValue  The new value of the property.
  128.      * @exception PropertyVetoException if the recipient wishes the property
  129.      *              change to be rolled back.
  130.      */
  131.     public void fireVetoableChange(String propertyName, 
  132.                     Object oldValue, Object newValue)
  133.                     throws PropertyVetoException {
  134.     if (listeners == null && children == null) {
  135.         return;
  136.     }
  137.  
  138.            PropertyChangeEvent evt = new PropertyChangeEvent(source, propertyName,
  139.                                 oldValue, newValue);
  140.     fireVetoableChange(evt);
  141.     }
  142.  
  143.     /**
  144.      * Report a int vetoable property update to any registered listeners.
  145.      * No event is fired if old and new are equal and non-null.
  146.      * <p>
  147.      * This is merely a convenience wrapper around the more general
  148.      * fireVetoableChange method that takes Object values.
  149.      *
  150.      * @param propertyName  The programmatic name of the property
  151.      *        that is about to change.
  152.      * @param oldValue  The old value of the property.
  153.      * @param newValue  The new value of the property.
  154.      */
  155.     public void fireVetoableChange(String propertyName, 
  156.                     int oldValue, int newValue)
  157.                     throws PropertyVetoException {
  158.     if (oldValue == newValue) {
  159.         return;
  160.     }
  161.     fireVetoableChange(propertyName, new Integer(oldValue), new Integer(newValue));
  162.     }
  163.  
  164.     /**
  165.      * Report a boolean vetoable property update to any registered listeners.
  166.      * No event is fired if old and new are equal and non-null.
  167.      * <p>
  168.      * This is merely a convenience wrapper around the more general
  169.      * fireVetoableChange method that takes Object values.
  170.      *
  171.      * @param propertyName  The programmatic name of the property
  172.      *        that is about to change.
  173.      * @param oldValue  The old value of the property.
  174.      * @param newValue  The new value of the property.
  175.      */
  176.     public void fireVetoableChange(String propertyName, 
  177.                     boolean oldValue, boolean newValue) 
  178.                     throws PropertyVetoException {
  179.     if (oldValue == newValue) {
  180.         return;
  181.     }
  182.     fireVetoableChange(propertyName, new Boolean(oldValue), new Boolean(newValue));
  183.     }
  184.  
  185.  
  186.     /**
  187.      * Fire a vetoable property update to any registered listeners.  If
  188.      * anyone vetos the change, then fire a new event reverting everyone to 
  189.      * the old value and then rethrow the PropertyVetoException.
  190.      * <p>
  191.      * No event is fired if old and new are equal and non-null.
  192.      *
  193.      * @param evt  The PropertyChangeEvent to be fired.
  194.      * @exception PropertyVetoException if the recipient wishes the property
  195.      *              change to be rolled back.
  196.      */
  197.     public void fireVetoableChange(PropertyChangeEvent evt)
  198.                     throws PropertyVetoException {
  199.  
  200.     Object oldValue = evt.getOldValue();
  201.     Object newValue = evt.getNewValue();
  202.     String propertyName = evt.getPropertyName();
  203.     if (oldValue != null && newValue != null && oldValue.equals(newValue)) {
  204.         return;
  205.     }
  206.  
  207.     java.util.Vector targets = null;
  208.     VetoableChangeSupport child = null;
  209.     synchronized (this) {
  210.         if (listeners != null) {
  211.             targets = (java.util.Vector) listeners.clone();
  212.         }
  213.         if (children != null && propertyName != null) {
  214.         child = (VetoableChangeSupport)children.get(propertyName);
  215.         }
  216.     }
  217.  
  218.     if (listeners != null) {
  219.         try {
  220.             for (int i = 0; i < targets.size(); i++) {
  221.                 VetoableChangeListener target = 
  222.                 (VetoableChangeListener)targets.elementAt(i);
  223.                 target.vetoableChange(evt);
  224.             }
  225.         } catch (PropertyVetoException veto) {
  226.             // Create an event to revert everyone to the old value.
  227.                    evt = new PropertyChangeEvent(source, propertyName, newValue, oldValue);
  228.             for (int i = 0; i < targets.size(); i++) {
  229.             try {
  230.                     VetoableChangeListener target =
  231.                 (VetoableChangeListener)targets.elementAt(i);
  232.                     target.vetoableChange(evt);
  233.             } catch (PropertyVetoException ex) {
  234.                  // We just ignore exceptions that occur during reversions.
  235.             }
  236.             }
  237.             // And now rethrow the PropertyVetoException.
  238.             throw veto;
  239.         }
  240.     }
  241.  
  242.     if (child != null) {
  243.         child.fireVetoableChange(evt);
  244.     }
  245.     }
  246.  
  247.  
  248.     /**
  249.      * Check if there are any listeners for a specific property.
  250.      *
  251.      * @param propertyName  the property name.
  252.      * @return true if there are one or more listeners for the given property
  253.      */
  254.     public synchronized boolean hasListeners(String propertyName) {
  255.     if (listeners != null && !listeners.isEmpty()) {
  256.         // there is a generic listener
  257.         return true;
  258.     }
  259.     if (children != null) {
  260.         VetoableChangeSupport child = (VetoableChangeSupport)children.get(propertyName);
  261.         if (child != null) {
  262.         // The child will always have a listeners Vector.            
  263.         return !child.listeners.isEmpty();
  264.         }
  265.     }
  266.     return false;
  267.     }
  268.  
  269.  
  270.     private void writeObject(ObjectOutputStream s) throws IOException {
  271.         s.defaultWriteObject();
  272.  
  273.     java.util.Vector v = null;
  274.     synchronized (this) {
  275.         if (listeners != null) {
  276.             v = (java.util.Vector) listeners.clone();
  277.             }
  278.     }
  279.  
  280.     if (v != null) {
  281.         for(int i = 0; i < v.size(); i++) {
  282.             VetoableChangeListener l = (VetoableChangeListener)v.elementAt(i);
  283.             if (l instanceof Serializable) {
  284.                 s.writeObject(l);
  285.             }
  286.             }
  287.         }
  288.         s.writeObject(null);
  289.     }
  290.  
  291.  
  292.     private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
  293.         s.defaultReadObject();
  294.       
  295.         Object listenerOrNull;
  296.         while(null != (listenerOrNull = s.readObject())) {
  297.         addVetoableChangeListener((VetoableChangeListener)listenerOrNull);
  298.         }
  299.     }
  300.  
  301.     // "listeners" lists all the generic listeners.
  302.     transient private java.util.Vector listeners;
  303.     // "children" contains VetoableChangeSupports for individual properties
  304.     private java.util.Hashtable children;
  305.     private Object source;
  306.     private int vetoableChangeSupportSerializedDataVersion = 2;
  307.  
  308.     // Serialization version ID, so we're compatible with JDK 1.1
  309.     static final long serialVersionUID = -5090210921595982017L;
  310. }
  311.