home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 July / Chip_1998-07_cd.bin / zkuste / JBuilder / BDK / Win / bdk_sep97.exe / _SETUP.1 / PropertyHookup.java < prev    next >
Encoding:
Java Source  |  1997-09-10  |  4.6 KB  |  163 lines

  1.  
  2. package sunw.beanbox;
  3.  
  4. /**
  5.  * This class manages hookups between properties, so that a
  6.  * bound property change on object X turns into a property
  7.  * set on a related property on object Y.
  8.  * <P>
  9.  * We do this by associating a PropertyHookup adaptor with each
  10.  * source object that we are interested in.  As part of the adaptor
  11.  * we keep track of which target setter methods to call when a given
  12.  * property changes.
  13.  */
  14.  
  15. import java.lang.reflect.*;
  16. import java.beans.*;
  17. import java.io.*;
  18. import java.util.Hashtable;
  19. import java.util.Vector;
  20.  
  21. public class PropertyHookup implements PropertyChangeListener, Serializable {
  22.  
  23.     static final long serialVersionUID = 4502052857914084293L;
  24.  
  25.     /**
  26.      * Create a property hookup, so that a change to the named bound
  27.      * property on the source object turns into a call on the "setter"
  28.      * method of the given target object.
  29.      */
  30.  
  31.     public void attach(Object source,
  32.                String propertyName, Method getter,
  33.                Object targetObject, Method setter) {
  34.  
  35.     Vector targets = (Vector) targetsByPropertyName.get(propertyName);
  36.     if (targets == null) {
  37.         targets = new Vector();
  38.         targetsByPropertyName.put(propertyName, targets);
  39.     }
  40.     PropertyHookupTarget target;
  41.     for (int i = 0; i < targets.size(); i++) {
  42.         target = (PropertyHookupTarget) targets.elementAt(i);
  43.         if (target.setter == setter && target.object == targetObject) {
  44.         // We've already got this hookup.  Just return.
  45.         return;
  46.         }
  47.     }
  48.     targets.addElement(new PropertyHookupTarget(targetObject,setter));
  49.  
  50.     // propagate the initial value.
  51.     try {
  52.         Object args1[] = { };
  53.         Object value = getter.invoke(source, args1);
  54.         Object args2[] = { value };
  55.         setter.invoke(targetObject, args2);
  56.     } catch (InvocationTargetException ex) {
  57.         System.err.println("Property propagation failed");
  58.         ex.getTargetException().printStackTrace();
  59.         } catch (Exception ex) {
  60.         System.err.println("Property propagation failed");
  61.         ex.printStackTrace();
  62.     }
  63.     }
  64.  
  65.     /**
  66.      * Constructor for a new property hookup adaptor.
  67.      */
  68.  
  69.     public PropertyHookup(Object source) {
  70.     this.source = source;    
  71.     targetsByPropertyName = new Hashtable();
  72.     }
  73.  
  74.     /**
  75.      * This is the method that gets called when a bound property
  76.      * changes on the source object.
  77.      * We map the property name to a list of targets and then
  78.      * call each of the target "setter" methods.
  79.      */
  80.  
  81.     synchronized public void propertyChange(PropertyChangeEvent evt) {
  82.     String propertyName = evt.getPropertyName();
  83.     Vector targets = (Vector) targetsByPropertyName.get(propertyName);
  84.     if (targets == null) {
  85.         return;
  86.     }
  87.     Object args[] = { evt.getNewValue() };
  88.     for (int i = 0; i < targets.size(); i++) {
  89.         PropertyHookupTarget target
  90.         = (PropertyHookupTarget)targets.elementAt(i);
  91.         try {
  92.             target.setter.invoke(target.object, args);
  93.         } catch (InvocationTargetException ex) {
  94.          System.err.println("Property set failed");
  95.         ex.getTargetException().printStackTrace();
  96.         } catch (Exception ex) {
  97.          System.err.println("Unexpected Property set exception");
  98.         ex.printStackTrace();
  99.         }
  100.     }
  101.     }
  102.  
  103.     public void vetoablePropertyChange(PropertyChangeEvent evt)
  104.                     throws PropertyVetoException {
  105.     propertyChange(evt);
  106.     }
  107.  
  108.     // Event source
  109.     Object source;
  110.  
  111.     // Table that maps from property names to a vector of PropertyHookupTargets
  112.     Hashtable targetsByPropertyName;
  113. }
  114.  
  115.  
  116. // Information for an event delivery target.
  117. class PropertyHookupTarget implements Serializable {
  118.  
  119.     static final long serialVersionUID = -8352305996623495352L;
  120.  
  121.     private static int ourVersion = 1;
  122.     Object object;
  123.     Method setter;
  124.  
  125.     PropertyHookupTarget(Object object, Method setter) {
  126.     this.object = object;
  127.     this.setter = setter;
  128.     }
  129.  
  130.     private void writeObject(ObjectOutputStream s)
  131.                     throws IOException {
  132.     // Because Method objects aren't serializable, we 
  133.         // serialize the name of the setter method.
  134.     s.writeInt(ourVersion);
  135.     s.writeObject(setter.toString());
  136.     s.writeObject(object);
  137.     }
  138.  
  139.     private void readObject(ObjectInputStream s)
  140.             throws ClassNotFoundException, IOException {
  141.     int version = s.readInt();
  142.     String setterName = (String)s.readObject();
  143.     object = s.readObject();
  144.  
  145.     // We do a rather expensive search for a setter method
  146.     // matching the given setterName.
  147.     setter = null;
  148.     Method methods[] = object.getClass().getMethods();
  149.     for (int i = 0; i < methods.length; i++) {
  150.         if (methods[i].toString().equals(setterName)) {
  151.         setter = methods[i];
  152.         break;
  153.         }
  154.     }
  155.     if (setter == null) {
  156.         throw new IOException("PropertyHookupTarget : no suitable setter" +
  157.             "\n    " + setterName + 
  158.             "\n    in class " + object.getClass());
  159.     }
  160.     }
  161. }
  162.  
  163.