View Javadoc

    1   /*
    2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
    3    *
    4    * This software is open source.
    5    * See the bottom of this file for the licence.
    6    */
    7
    8   package org.dom4j.bean;
    9
    10  import java.beans.BeanInfo;
    11  import java.beans.IntrospectionException;
    12  import java.beans.Introspector;
    13  import java.beans.PropertyDescriptor;
    14  import java.lang.reflect.Method;
    15  import java.util.HashMap;
    16  import java.util.Map;
    17
    18  import org.dom4j.DocumentFactory;
    19  import org.dom4j.QName;
    20
    21  /***
    22   * <p>
    23   * <code>BeanMetaData</code> contains metadata about a bean class.
    24   * </p>
    25   *
    26   * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
    27   * @version $Revision: 1.10 $
    28   */
    29  public class BeanMetaData {
    30      /*** Empty arguments for reflection calls */
    31      protected static final Object[] NULL_ARGS = {};
    32
    33      /*** Singleton cache */
    34      private static Map singletonCache = new HashMap();
    35
    36      private static final DocumentFactory DOCUMENT_FACTORY = BeanDocumentFactory
    37              .getInstance();
    38
    39      /*** The class of the bean */
    40      private Class beanClass;
    41
    42      /*** Property descriptors for the bean */
    43      private PropertyDescriptor[] propertyDescriptors;
    44
    45      /*** QNames for the attributes */
    46      private QName[] qNames;
    47
    48      /*** Read methods used for getting properties */
    49      private Method[] readMethods;
    50
    51      /*** Write methods used for setting properties */
    52      private Method[] writeMethods;
    53
    54      /*** Index of names and QNames to indices */
    55      private Map nameMap = new HashMap();
    56
    57      public BeanMetaData(Class beanClass) {
    58          this.beanClass = beanClass;
    59
    60          if (beanClass != null) {
    61              try {
    62                  BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);
    63                  propertyDescriptors = beanInfo.getPropertyDescriptors();
    64              } catch (IntrospectionException e) {
    65                  handleException(e);
    66              }
    67          }
    68
    69          if (propertyDescriptors == null) {
    70              propertyDescriptors = new PropertyDescriptor[0];
    71          }
    72
    73          int size = propertyDescriptors.length;
    74          qNames = new QName[size];
    75          readMethods = new Method[size];
    76          writeMethods = new Method[size];
    77
    78          for (int i = 0; i < size; i++) {
    79              PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
    80              String name = propertyDescriptor.getName();
    81              QName qName = DOCUMENT_FACTORY.createQName(name);
    82              qNames[i] = qName;
    83              readMethods[i] = propertyDescriptor.getReadMethod();
    84              writeMethods[i] = propertyDescriptor.getWriteMethod();
    85
    86              Integer index = new Integer(i);
    87              nameMap.put(name, index);
    88              nameMap.put(qName, index);
    89          }
    90      }
    91
    92      /***
    93       * Static helper method to find and cache meta data objects for bean types
    94       *
    95       * @param beanClass
    96       *            DOCUMENT ME!
    97       *
    98       * @return DOCUMENT ME!
    99       */
    100     public static BeanMetaData get(Class beanClass) {
    101         BeanMetaData answer = (BeanMetaData) singletonCache.get(beanClass);
    102
    103         if (answer == null) {
    104             answer = new BeanMetaData(beanClass);
    105             singletonCache.put(beanClass, answer);
    106         }
    107
    108         return answer;
    109     }
    110
    111     /***
    112      * DOCUMENT ME!
    113      *
    114      * @return the number of attribtutes for this bean type
    115      */
    116     public int attributeCount() {
    117         return propertyDescriptors.length;
    118     }
    119
    120     public BeanAttributeList createAttributeList(BeanElement parent) {
    121         return new BeanAttributeList(parent, this);
    122     }
    123
    124     public QName getQName(int index) {
    125         return qNames[index];
    126     }
    127
    128     public int getIndex(String name) {
    129         Integer index = (Integer) nameMap.get(name);
    130
    131         return (index != null) ? index.intValue() : (-1);
    132     }
    133
    134     public int getIndex(QName qName) {
    135         Integer index = (Integer) nameMap.get(qName);
    136
    137         return (index != null) ? index.intValue() : (-1);
    138     }
    139
    140     public Object getData(int index, Object bean) {
    141         try {
    142             Method method = readMethods[index];
    143
    144             return method.invoke(bean, NULL_ARGS);
    145         } catch (Exception e) {
    146             handleException(e);
    147
    148             return null;
    149         }
    150     }
    151
    152     public void setData(int index, Object bean, Object data) {
    153         try {
    154             Method method = writeMethods[index];
    155             Object[] args = {data};
    156             method.invoke(bean, args);
    157         } catch (Exception e) {
    158             handleException(e);
    159         }
    160     }
    161
    162     // Implementation methods
    163     // -------------------------------------------------------------------------
    164     protected void handleException(Exception e) {
    165         // ignore introspection exceptions
    166     }
    167 }
    168
    169 /*
    170  * Redistribution and use of this software and associated documentation
    171  * ("Software"), with or without modification, are permitted provided that the
    172  * following conditions are met:
    173  *
    174  * 1. Redistributions of source code must retain copyright statements and
    175  * notices. Redistributions must also contain a copy of this document.
    176  *
    177  * 2. Redistributions in binary form must reproduce the above copyright notice,
    178  * this list of conditions and the following disclaimer in the documentation
    179  * and/or other materials provided with the distribution.
    180  *
    181  * 3. The name "DOM4J" must not be used to endorse or promote products derived
    182  * from this Software without prior written permission of MetaStuff, Ltd. For
    183  * written permission, please contact dom4j-info@metastuff.com.
    184  *
    185  * 4. Products derived from this Software may not be called "DOM4J" nor may
    186  * "DOM4J" appear in their names without prior written permission of MetaStuff,
    187  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
    188  *
    189  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
    190  *
    191  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
    192  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    193  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    194  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
    195  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    196  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    197  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    198  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    199  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    200  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    201  * POSSIBILITY OF SUCH DAMAGE.
    202  *
    203  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
    204  */