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

  1. /*
  2.  * @(#)PropertyChangeSupport.java    1.24 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 bound
  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 PropertyChangeSupport implements java.io.Serializable {
  30.  
  31.     /**
  32.      * @param sourceBean  The bean to be given as the source for any events.
  33.      */
  34.  
  35.     public PropertyChangeSupport(Object sourceBean) {
  36.     if (sourceBean == null) {
  37.         throw new NullPointerException();
  38.     }
  39.     source = sourceBean;
  40.     }
  41.  
  42.     /**
  43.      * Add a PropertyChangeListener to the listener list.
  44.      * The listener is registered for all properties.
  45.      *
  46.      * @param listener  The PropertyChangeListener to be added
  47.      */
  48.  
  49.     public synchronized void addPropertyChangeListener(
  50.                 PropertyChangeListener listener) {
  51.     if (listeners == null) {
  52.         listeners = new java.util.Vector();
  53.     }
  54.     listeners.addElement(listener);
  55.     }
  56.  
  57.     /**
  58.      * Remove a PropertyChangeListener from the listener list.
  59.      * This removes a PropertyChangeListener that was registered
  60.      * for all properties.
  61.      *
  62.      * @param listener  The PropertyChangeListener to be removed
  63.      */
  64.  
  65.     public synchronized void removePropertyChangeListener(
  66.                 PropertyChangeListener listener) {
  67.     if (listeners == null) {
  68.         return;
  69.     }
  70.     listeners.removeElement(listener);
  71.     }
  72.  
  73.     /**
  74.      * Add a PropertyChangeListener for a specific property.  The listener
  75.      * will be invoked only when a call on firePropertyChange names that
  76.      * specific property.
  77.      *
  78.      * @param propertyName  The name of the property to listen on.
  79.      * @param listener  The PropertyChangeListener to be added
  80.      */
  81.  
  82.     public synchronized void addPropertyChangeListener(
  83.                 String propertyName,
  84.                 PropertyChangeListener listener) {
  85.     if (children == null) {
  86.         children = new java.util.Hashtable();
  87.     }
  88.     PropertyChangeSupport child = (PropertyChangeSupport)children.get(propertyName);
  89.     if (child == null) {
  90.         child = new PropertyChangeSupport(source);
  91.         children.put(propertyName, child);
  92.     }
  93.     child.addPropertyChangeListener(listener);
  94.     }
  95.  
  96.     /**
  97.      * Remove a PropertyChangeListener for a specific property.
  98.      *
  99.      * @param propertyName  The name of the property that was listened on.
  100.      * @param listener  The PropertyChangeListener to be removed
  101.      */
  102.  
  103.     public synchronized void removePropertyChangeListener(
  104.                 String propertyName,
  105.                 PropertyChangeListener listener) {
  106.     if (children == null) {
  107.         return;
  108.     }
  109.     PropertyChangeSupport child = (PropertyChangeSupport)children.get(propertyName);
  110.     if (child == null) {
  111.         return;
  112.     }
  113.     child.removePropertyChangeListener(listener);
  114.     }
  115.  
  116.     /**
  117.      * Report a bound property update to any registered listeners.
  118.      * No event is fired if old and new are equal and non-null.
  119.      *
  120.      * @param propertyName  The programmatic name of the property
  121.      *        that was changed.
  122.      * @param oldValue  The old value of the property.
  123.      * @param newValue  The new value of the property.
  124.      */
  125.     public void firePropertyChange(String propertyName, 
  126.                     Object oldValue, Object newValue) {
  127.  
  128.     if (oldValue != null && newValue != null && oldValue.equals(newValue)) {
  129.         return;
  130.     }
  131.  
  132.     java.util.Vector targets = null;
  133.     PropertyChangeSupport child = null;
  134.     synchronized (this) {
  135.         if (listeners != null) {
  136.             targets = (java.util.Vector) listeners.clone();
  137.         }
  138.         if (children != null && propertyName != null) {
  139.         child = (PropertyChangeSupport)children.get(propertyName);
  140.         }
  141.     }
  142.  
  143.         PropertyChangeEvent evt = new PropertyChangeEvent(source,
  144.                         propertyName, oldValue, newValue);
  145.  
  146.     if (targets != null) {
  147.         for (int i = 0; i < targets.size(); i++) {
  148.             PropertyChangeListener target = (PropertyChangeListener)targets.elementAt(i);
  149.             target.propertyChange(evt);
  150.         }
  151.     }
  152.  
  153.     if (child != null) {
  154.         child.firePropertyChange(evt);
  155.     }    
  156.     }
  157.  
  158.     /**
  159.      * Report an int bound property update to any registered listeners.
  160.      * No event is fired if old and new are equal and non-null.
  161.      * <p>
  162.      * This is merely a convenience wrapper around the more general
  163.      * firePropertyChange method that takes Object values.
  164.      *
  165.      * @param propertyName  The programmatic name of the property
  166.      *        that was changed.
  167.      * @param oldValue  The old value of the property.
  168.      * @param newValue  The new value of the property.
  169.      */
  170.     public void firePropertyChange(String propertyName, 
  171.                     int oldValue, int newValue) {
  172.     if (oldValue == newValue) {
  173.         return;
  174.     }
  175.     firePropertyChange(propertyName, new Integer(oldValue), new Integer(newValue));
  176.     }
  177.  
  178.  
  179.     /**
  180.      * Report a boolean bound property update to any registered listeners.
  181.      * No event is fired if old and new are equal and non-null.
  182.      * <p>
  183.      * This is merely a convenience wrapper around the more general
  184.      * firePropertyChange method that takes Object values.
  185.      *
  186.      * @param propertyName  The programmatic name of the property
  187.      *        that was changed.
  188.      * @param oldValue  The old value of the property.
  189.      * @param newValue  The new value of the property.
  190.      */
  191.     public void firePropertyChange(String propertyName, 
  192.                     boolean oldValue, boolean newValue) {
  193.     if (oldValue == newValue) {
  194.         return;
  195.     }
  196.     firePropertyChange(propertyName, new Boolean(oldValue), new Boolean(newValue));
  197.     }
  198.  
  199.     /**
  200.      * Fire an existing PropertyChangeEvent to any registered listeners.
  201.      * No event is fired if the given event's old and new values are
  202.      * equal and non-null.
  203.      * @param evt  The PropertyChangeEvent object.
  204.      */
  205.     public void firePropertyChange(PropertyChangeEvent evt) {
  206.     Object oldValue = evt.getOldValue();
  207.     Object newValue = evt.getNewValue();
  208.         String propertyName = evt.getPropertyName();
  209.     if (oldValue != null && newValue != null && oldValue.equals(newValue)) {
  210.         return;
  211.     }
  212.  
  213.     java.util.Vector targets = null;
  214.     PropertyChangeSupport child = null;
  215.     synchronized (this) {
  216.         if (listeners != null) {
  217.             targets = (java.util.Vector) listeners.clone();
  218.         }
  219.         if (children != null && propertyName != null) {
  220.         child = (PropertyChangeSupport)children.get(propertyName);
  221.         }
  222.     }
  223.  
  224.     if (targets != null) {
  225.         for (int i = 0; i < targets.size(); i++) {
  226.             PropertyChangeListener target = (PropertyChangeListener)targets.elementAt(i);
  227.             target.propertyChange(evt);
  228.         }
  229.     }
  230.     if (child != null) {
  231.         child.firePropertyChange(evt);
  232.     }
  233.     }
  234.  
  235.     /**
  236.      * Check if there are any listeners for a specific property.
  237.      *
  238.      * @param propertyName  the property name.
  239.      * @return true if there are ore or more listeners for the given property
  240.      */
  241.     public synchronized boolean hasListeners(String propertyName) {
  242.     if (listeners != null && !listeners.isEmpty()) {
  243.         // there is a generic listener
  244.         return true;
  245.     }
  246.     if (children != null) {
  247.         PropertyChangeSupport child = (PropertyChangeSupport)children.get(propertyName);
  248.         if (child != null) {
  249.         // The child will always have a listeners Vector.            
  250.         return !child.listeners.isEmpty();
  251.         }
  252.     }
  253.     return false;
  254.     }
  255.  
  256.     private void writeObject(ObjectOutputStream s) throws IOException {
  257.         s.defaultWriteObject();
  258.  
  259.     java.util.Vector v = null;
  260.     synchronized (this) {
  261.         if (listeners != null) {
  262.             v = (java.util.Vector) listeners.clone();
  263.             }
  264.     }
  265.  
  266.     if (v != null) {
  267.         for (int i = 0; i < v.size(); i++) {
  268.             PropertyChangeListener l = (PropertyChangeListener)v.elementAt(i);
  269.             if (l instanceof Serializable) {
  270.                 s.writeObject(l);
  271.             }
  272.             }
  273.         }
  274.         s.writeObject(null);
  275.     }
  276.  
  277.  
  278.     private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
  279.         s.defaultReadObject();
  280.       
  281.         Object listenerOrNull;
  282.         while (null != (listenerOrNull = s.readObject())) {
  283.       addPropertyChangeListener((PropertyChangeListener)listenerOrNull);
  284.         }
  285.     }
  286.  
  287.     // "listeners" lists all the generic listeners.
  288.     transient private java.util.Vector listeners;
  289.     // "children" contains PropertyChangeSupports for individual properties
  290.     private java.util.Hashtable children;
  291.     private Object source;
  292.     private int propertyChangeSupportSerializedDataVersion = 2;
  293.  
  294.     // Serialization version ID, so we're compatible with JDK 1.1
  295.     static final long serialVersionUID = 6401253773779951803L;
  296. }
  297.