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  */