JavaBeanDataModel.java
上传用户:zhengdagz
上传日期:2014-03-06
资源大小:1956k
文件大小:10k
源码类别:

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: JavaBeanDataModel.java,v 1.2 2005/10/10 17:01:05 rbair Exp $
  3.  *
  4.  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
  5.  * Santa Clara, California 95054, U.S.A. All rights reserved.
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  * 
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.  */
  21. package org.jdesktop.binding;
  22. import java.beans.BeanInfo;
  23. import java.beans.IntrospectionException;
  24. import java.beans.Introspector;
  25. import java.beans.PropertyChangeEvent;
  26. import java.beans.PropertyChangeListener;
  27. import java.beans.PropertyDescriptor;
  28. import java.lang.reflect.Method;
  29. import java.util.HashMap;
  30. import java.util.Map;
  31. import org.jdesktop.binding.metadata.MetaData;
  32. import org.jdesktop.binding.metadata.NumberMetaData;
  33. /**
  34.  * A class that creates a collection of MetaData based BeanInfo
  35.  * PropertyDescriptors. To use this class:
  36.  * <ol>
  37.  *   <li>Construct the model using the Bean class you wish to model
  38.  *   <li>use <code>setJavaBean</code> to set the current object of this class.
  39.  *   <li>Updates made to the form will update the property values of the bean.
  40.  * </ol>
  41.  * <p>
  42.  * TODO: Using JavaBeans as a data source should be generalized and not
  43.  * constrained to FormModels.
  44.  *
  45.  * @author Mark Davidson
  46.  */
  47. public class JavaBeanDataModel extends DefaultDataModel {
  48.     private BeanInfo info;
  49.     // needed for error checking in setJavaBean
  50.     private Class beanClass;
  51.     private Object bean; // current bean instance
  52.     private static final Map<Class, Class> primitivesToBoxed = new HashMap<Class,Class>();
  53.     
  54.     // temporarily public for testing!
  55.     public PropertyChangeListener propertyChangeListener;
  56.     static {
  57.         primitivesToBoxed.put(Integer.TYPE, Integer.class);
  58.         primitivesToBoxed.put(Long.TYPE, Long.class);
  59.         primitivesToBoxed.put(Short.TYPE, Short.class);
  60.         primitivesToBoxed.put(Byte.TYPE, Byte.class);
  61.         primitivesToBoxed.put(Float.TYPE, Float.class);
  62.         primitivesToBoxed.put(Double.TYPE, Double.class);
  63.         primitivesToBoxed.put(Boolean.TYPE, Boolean.class);
  64.     }
  65.     
  66.     public JavaBeanDataModel(Class beanClass) throws IntrospectionException {
  67.         this(beanClass, null);
  68.     }
  69.     public JavaBeanDataModel(Object bean) throws IntrospectionException {
  70.         this(bean.getClass(), bean);
  71.     }
  72.     /**
  73.      * Constructs a JavaBeanDataModel by introspecting on the class and using the data from
  74.      * the object as the current bean
  75.      *
  76.      * @param beanClass the class to use to introspect properties
  77.      * @param bean the object where the current values will be retrieved and stored.
  78.      */
  79.     public JavaBeanDataModel(Class beanClass, Object bean) throws IntrospectionException {
  80.         this(beanClass, bean, null);
  81.     }
  82.     public JavaBeanDataModel(Class beanClass, Object bean, MetaData[] metaData) throws IntrospectionException {
  83.         this.beanClass = beanClass;
  84.         createDefaultMetaData(beanClass, metaData);
  85.         setJavaBean(bean);
  86.         
  87.     }
  88.     private void createDefaultMetaData(Class beanClass, MetaData[] metaData) throws IntrospectionException {
  89.         info = Introspector.getBeanInfo(beanClass);
  90.         boolean bound = false;
  91.         if (metaData == null) {
  92.             PropertyDescriptor[] props = info.getPropertyDescriptors();
  93.             for (int i = 0; i < props.length; i++) {
  94.              PropertyDescriptor prop = props[i];
  95.                 bound = bound || prop.isBound();
  96.                 addField(createMetaData(prop));
  97.             }
  98.         } else {
  99.             for (int i = 0; i < metaData.length; i++) {
  100.                 PropertyDescriptor prop = getPropertyDescriptor(metaData[i].getName());
  101.                 if (prop != null) {
  102.                     bound = bound || prop.isBound();
  103.                     addField(metaData[i]);
  104.                 }
  105.             }
  106.         }
  107.         if (bound) {
  108.             initPropertyChangeListener();
  109.         }
  110.     }
  111.     private MetaData createMetaData(PropertyDescriptor prop) {
  112.         
  113.         MetaData metaData = null;
  114.         // JW: cannot cope with indexedPropertyTypes (?)
  115.         // they seem to return null for getPropertyType
  116.         if (Number.class.isAssignableFrom(prop.getPropertyType())) {
  117.             metaData = new NumberMetaData(
  118.                     prop.getName(),
  119.                     prop.getPropertyType(),
  120.                     prop.getDisplayName());
  121.         } else if (isNumberType(prop))
  122.         {
  123.             // convert the primitive types to their boxed types
  124.             // this makes the binding code happier in
  125.             // AbstractBinding#convertToModelType
  126.              metaData = new NumberMetaData(
  127.                             prop.getName(),
  128.                             primitivesToBoxed.get(prop.getPropertyType()),
  129.                             prop.getDisplayName());
  130.             // JW: really??
  131.             metaData.setRequired(true);
  132.         } else {
  133.             Class type = prop.getPropertyType();
  134.             if (primitivesToBoxed.get(type) != null) {
  135.                 type = primitivesToBoxed.get(type);
  136.             }
  137.             metaData = new MetaData(prop.getName(), type, prop
  138.                                 .getDisplayName());
  139.                 
  140.         }
  141.         return metaData;
  142.     }
  143.     private void initPropertyChangeListener() {
  144.         if (propertyChangeListener != null) return;
  145.         try {
  146.             beanClass.getMethod("addPropertyChangeListener", 
  147.                     new Class[] { PropertyChangeListener.class });
  148.             beanClass.getMethod("removePropertyChangeListener", 
  149.                     new Class[] { PropertyChangeListener.class });
  150.         } catch (Exception e) {
  151.             // TODO Auto-generated catch block
  152.             e.printStackTrace();
  153.             return;
  154.         } 
  155.         propertyChangeListener = new PropertyChangeListener() {
  156.             public void propertyChange(PropertyChangeEvent evt) {
  157.                 fireValueChanged(evt.getPropertyName());
  158.                 
  159.             }
  160.             
  161.         };
  162.         
  163.     }
  164.     private boolean isNumberType(PropertyDescriptor prop) {
  165.         if (prop.getPropertyType() == Boolean.TYPE) return false;
  166.         return prop.getPropertyType()==Integer.TYPE
  167.              || prop.getPropertyType()==Long.TYPE
  168.              || prop.getPropertyType()==Short.TYPE
  169.              || prop.getPropertyType()==Byte.TYPE
  170.              || prop.getPropertyType()==Float.TYPE
  171.              || prop.getPropertyType()==Double.TYPE;
  172.     }
  173.     /**
  174.      * Set the JavaBean instance that this model will use.
  175.      */
  176.     public void setJavaBean(Object bean) {
  177.         if (bean != null && bean.getClass() != beanClass) {
  178.             throw new RuntimeException("ERROR: argument is not a " +
  179.                                        beanClass.toString());
  180.         }
  181.         Object oldBean = this.bean;
  182.         removePropertyChangeListener(oldBean);
  183.         this.bean = bean;
  184.         if (bean != oldBean) {
  185.             // Should update all the values
  186.             String[] fieldNames = getFieldNames();
  187.             for (int i = 0; i < fieldNames.length; i++) {
  188.                 fireValueChanged(fieldNames[i]);
  189.             }
  190.         }
  191.         addPropertyChangeListener(bean);
  192.     }
  193.     private void addPropertyChangeListener(Object bean) {
  194.         if ((propertyChangeListener == null) || (bean == null)) return;
  195.         try {
  196.             Method adder = beanClass.getMethod("addPropertyChangeListener", 
  197.                     new Class[] { PropertyChangeListener.class });
  198.             adder.invoke(bean, new Object[] { propertyChangeListener });
  199.        } catch (Exception e) {
  200.             // TODO Auto-generated catch block
  201.             e.printStackTrace();
  202.         } 
  203.         
  204.     }
  205.     private void removePropertyChangeListener(Object bean) {
  206.         if ((propertyChangeListener == null) || (bean == null)) return;
  207.         try {
  208.             Method adder = beanClass.getMethod("removePropertyChangeListener", 
  209.                     new Class[] { PropertyChangeListener.class });
  210.             adder.invoke(bean, new Object[] { propertyChangeListener });
  211.        } catch (Exception e) {
  212.             // TODO Auto-generated catch block
  213.             e.printStackTrace();
  214.         } 
  215.     }
  216.     /**
  217.      * Get the JavaBean instance that this model uses.
  218.      */
  219.     public Object getJavaBean() {
  220.         return bean;
  221.     }
  222.     public Object getValue(String fieldName) {
  223.         if (getJavaBean() == null) {
  224.             return null;
  225.         }
  226.         PropertyDescriptor prop = getPropertyDescriptor(fieldName);
  227.         Method readMethod = prop.getReadMethod();
  228.         if (readMethod != null) {
  229.             try {
  230.                 return readMethod.invoke(getJavaBean(), new Object[0]);
  231.             }
  232.             catch (Exception ex) {
  233.                 // XXX excecption for illegal access, etc..
  234.                 ex.printStackTrace();
  235.             }
  236.         }
  237.         return null;
  238.     }
  239.     // XXX should be protected.
  240.     protected void setValueImpl(String fieldName, Object value) {
  241.         if (getJavaBean() == null) {
  242.             return;
  243.         }
  244.         PropertyDescriptor prop = getPropertyDescriptor(fieldName);
  245.         Method writeMethod = prop.getWriteMethod();
  246.         if (writeMethod != null) {
  247.             try {
  248.                 writeMethod.invoke(getJavaBean(), new Object[] {value});
  249.             }
  250.             catch (Exception ex) {
  251.                 // XXX exception for illegal access, etc..
  252.                 ex.printStackTrace();
  253.             }
  254.         }
  255.     }
  256.     private PropertyDescriptor getPropertyDescriptor(String name) {
  257.         PropertyDescriptor pd = null;
  258.         PropertyDescriptor[] desc = info.getPropertyDescriptors();
  259.         for (int i = 0; i < desc.length; i++) {
  260.             if (name.equals(desc[i].getName())) {
  261.                 pd = desc[i];
  262.                 break;
  263.             }
  264.         }
  265.         return pd;
  266.     }
  267. }