View Javadoc

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