001/* 002 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved. 003 * 004 * This software is open source. 005 * See the bottom of this file for the licence. 006 * 007 * $Id: BeanMetaData.java,v 1.4 2001/05/15 18:17:38 jstrachan Exp $ 008 */ 009 010package org.dom4j.bean; 011 012import java.beans.BeanInfo; 013import java.beans.Introspector; 014import java.beans.IntrospectionException; 015import java.beans.PropertyDescriptor; 016import java.lang.reflect.Method; 017import java.util.HashMap; 018import java.util.Map; 019 020import org.dom4j.DocumentFactory; 021import org.dom4j.QName; 022 023/** <p><code>BeanMetaData</code> contains metadata about a bean class.</p> 024 * 025 * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a> 026 * @version $Revision: 1.4 $ 027 */ 028public class BeanMetaData { 029 030 /** Empty arguments for reflection calls */ 031 protected static final Object[] NULL_ARGS = {}; 032 033 /** Singleton cache */ 034 private static Map singletonCache = new HashMap(); 035 036 private static final DocumentFactory DOCUMENT_FACTORY = BeanDocumentFactory.getInstance(); 037 038 /** The class of the bean */ 039 private Class beanClass; 040 041 /** Property descriptors for the bean */ 042 private PropertyDescriptor[] propertyDescriptors; 043 044 /** QNames for the attributes */ 045 private QName[] qNames; 046 047 /** Read methods used for getting properties */ 048 private Method[] readMethods; 049 050 /** Write methods used for setting properties */ 051 private Method[] writeMethods; 052 053 /** Index of names and QNames to indices */ 054 private Map nameMap = new HashMap(); 055 056 057 /** Static helper method to find and cache meta data objects for bean types 058 */ 059 public static BeanMetaData get(Class beanClass) { 060 BeanMetaData answer = (BeanMetaData) singletonCache.get( beanClass ); 061 if ( answer == null ) { 062 answer = new BeanMetaData( beanClass ); 063 singletonCache.put( beanClass, answer ); 064 } 065 return answer; 066 } 067 068 public BeanMetaData(Class beanClass) { 069 this.beanClass = beanClass; 070 if ( beanClass != null ) { 071 try { 072 BeanInfo beanInfo = Introspector.getBeanInfo( beanClass ); 073 propertyDescriptors = beanInfo.getPropertyDescriptors(); 074 } 075 catch (IntrospectionException e) { 076 handleException(e); 077 } 078 } 079 if ( propertyDescriptors == null ) { 080 propertyDescriptors = new PropertyDescriptor[0]; 081 } 082 int size = propertyDescriptors.length; 083 qNames = new QName[size]; 084 readMethods = new Method[size]; 085 writeMethods = new Method[size]; 086 for ( int i = 0; i < size; i++ ) { 087 PropertyDescriptor propertyDescriptor = propertyDescriptors[i]; 088 String name = propertyDescriptor.getName(); 089 QName qName = DOCUMENT_FACTORY.createQName( name ); 090 qNames[i] = qName; 091 readMethods[i] = propertyDescriptor.getReadMethod(); 092 writeMethods[i] = propertyDescriptor.getWriteMethod(); 093 094 Integer index = new Integer(i); 095 nameMap.put( name, index ); 096 nameMap.put( qName, index ); 097 } 098 } 099 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://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 (C) MetaStuff, Ltd. All Rights Reserved. 197 * 198 * $Id: BeanMetaData.java,v 1.4 2001/05/15 18:17:38 jstrachan Exp $ 199 */