001: /* ========================================================================
002: * JCommon : a free general purpose class library for the Java(tm) platform
003: * ========================================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jcommon/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * --------------------------
028: * BeanObjectDescription.java
029: * --------------------------
030: * (C)opyright 2003-2005, by Thomas Morgner and Contributors.
031: *
032: * Original Author: Thomas Morgner;
033: * Contributor(s): David Gilbert (for Object Refinery Limited);
034: *
035: * $Id: BeanObjectDescription.java,v 1.6 2005/10/18 13:31:58 mungady Exp $
036: *
037: * Changes (from 19-Feb-2003)
038: * -------------------------
039: * 19-Feb-2003 : Added standard header and Javadocs (DG);
040: * 29-Apr-2003 : Distilled from the JFreeReport project and moved into
041: * JCommon (TM);
042: * 18-Aug-2005 : Added casts to suppress compiler warnings, as suggested in
043: * patch 1260622 (DG);
044: *
045: */
046:
047: package org.jfree.xml.factory.objects;
048:
049: import java.lang.reflect.Method;
050: import java.lang.reflect.Modifier;
051: import java.util.Iterator;
052: import java.util.TreeSet;
053: import java.util.HashMap;
054: import java.beans.Introspector;
055: import java.beans.IntrospectionException;
056: import java.beans.BeanInfo;
057: import java.beans.PropertyDescriptor;
058: import java.io.ObjectInputStream;
059: import java.io.IOException;
060:
061: import org.jfree.util.Log;
062:
063: /**
064: * An object-description for a bean object. This object description
065: * is very dangerous, if the bean contains properties with undefined
066: * types.
067: *
068: * @author Thomas Morgner
069: */
070: public class BeanObjectDescription extends AbstractObjectDescription {
071:
072: private TreeSet ignoredParameters;
073: private transient HashMap properties;
074:
075: /**
076: * Creates a new object description.
077: *
078: * @param className the class.
079: */
080: public BeanObjectDescription(final Class className) {
081: this (className, true);
082: }
083:
084: /**
085: * Creates a new object description.
086: *
087: * @param className the class.
088: * @param init set to true, to autmaoticly initialise the object
089: * description. If set to false, the initialisation is
090: * elsewhere.
091: */
092: public BeanObjectDescription(final Class className,
093: final boolean init) {
094: super (className);
095: // now create some method descriptions ..
096: this .ignoredParameters = new TreeSet();
097: readBeanDescription(className, init);
098: }
099:
100: private boolean isValidMethod(final Method method,
101: final int parCount) {
102: if (method == null) {
103: return false;
104: }
105: if (!Modifier.isPublic(method.getModifiers())) {
106: return false;
107: }
108: if (Modifier.isStatic(method.getModifiers())) {
109: return false;
110: }
111: if (method.getParameterTypes().length != parCount) {
112: return false;
113: }
114: return true;
115: }
116:
117: /**
118: * Creates an object based on this description.
119: *
120: * @return The object.
121: */
122: public Object createObject() {
123: try {
124: final Object o = getObjectClass().newInstance();
125: // now add the various parameters ...
126:
127: final Iterator it = getParameterNames();
128: while (it.hasNext()) {
129: final String name = (String) it.next();
130:
131: if (isParameterIgnored(name)) {
132: continue;
133: }
134:
135: final Method method = findSetMethod(name);
136: final Object parameterValue = getParameter(name);
137: if (parameterValue == null) {
138: // Log.debug ("Parameter: " + name + " is null");
139: } else {
140: method.invoke(o, new Object[] { parameterValue });
141: }
142: }
143: return o;
144: } catch (Exception e) {
145: Log.error("Unable to invoke bean method", e);
146: }
147: return null;
148: }
149:
150: /**
151: * Finds a set method in the bean.
152: *
153: * @param parameterName the parameter name.
154: *
155: * @return The method.
156: */
157: private Method findSetMethod(final String parameterName) {
158: final PropertyDescriptor descriptor = (PropertyDescriptor) this .properties
159: .get(parameterName);
160: return descriptor.getWriteMethod();
161: }
162:
163: /**
164: * Finds a get method in the bean.
165: *
166: * @param parameterName the paramater name.
167: * @return The method.
168: */
169: private Method findGetMethod(final String parameterName) {
170: final PropertyDescriptor descriptor = (PropertyDescriptor) this .properties
171: .get(parameterName);
172: return descriptor.getReadMethod();
173: }
174:
175: /**
176: * Sets the parameters in the description to match the supplied object.
177: *
178: * @param o the object (<code>null</code> not allowed).
179: *
180: * @throws ObjectFactoryException if there is a problem.
181: */
182: public void setParameterFromObject(final Object o)
183: throws ObjectFactoryException {
184: if (o == null) {
185: throw new NullPointerException("Given object is null");
186: }
187: final Class c = getObjectClass();
188: if (!c.isInstance(o)) {
189: throw new ObjectFactoryException(
190: "Object is no instance of " + c + "(is "
191: + o.getClass() + ")");
192: }
193:
194: final Iterator it = getParameterNames();
195: while (it.hasNext()) {
196: final String propertyName = (String) it.next();
197:
198: if (isParameterIgnored(propertyName)) {
199: continue;
200: }
201:
202: try {
203: final Method method = findGetMethod(propertyName);
204: final Object retval = method.invoke(o, (Object[]) null);
205: if (retval != null) {
206: setParameter(propertyName, retval);
207: }
208: } catch (Exception e) {
209: Log.info("Exception on method invokation.", e);
210: }
211:
212: }
213: }
214:
215: /**
216: * Adds a parameter to the ignored parameters.
217: *
218: * @param parameter the parameter.
219: */
220: protected void ignoreParameter(final String parameter) {
221: this .ignoredParameters.add(parameter);
222: }
223:
224: /**
225: * Returns a flag that indicates whether or not the specified parameter is
226: * ignored.
227: *
228: * @param parameter the parameter.
229: *
230: * @return The flag.
231: */
232: protected boolean isParameterIgnored(final String parameter) {
233: return this .ignoredParameters.contains(parameter);
234: }
235:
236: private void readObject(final ObjectInputStream in)
237: throws IOException, ClassNotFoundException {
238: in.defaultReadObject();
239: readBeanDescription(getObjectClass(), false);
240: }
241:
242: private void readBeanDescription(final Class className,
243: final boolean init) {
244: try {
245: this .properties = new HashMap();
246:
247: final BeanInfo bi = Introspector.getBeanInfo(className);
248: final PropertyDescriptor[] propertyDescriptors = bi
249: .getPropertyDescriptors();
250: for (int i = 0; i < propertyDescriptors.length; i++) {
251: final PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
252: final Method readMethod = propertyDescriptor
253: .getReadMethod();
254: final Method writeMethod = propertyDescriptor
255: .getWriteMethod();
256: if (isValidMethod(readMethod, 0)
257: && isValidMethod(writeMethod, 1)) {
258: final String name = propertyDescriptor.getName();
259: this .properties.put(name, propertyDescriptor);
260: if (init) {
261: super .setParameterDefinition(name,
262: propertyDescriptor.getPropertyType());
263: }
264: }
265: }
266: } catch (IntrospectionException e) {
267: Log.error("Unable to build bean description", e);
268: }
269: }
270: }
|