001: /*
002: * JBoss, Home of Professional Open Source
003: * Copyright 2005, JBoss Inc., and individual contributors as indicated
004: * by the @authors tag. See the copyright.txt in the distribution for a
005: * full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jbpm.instantiation;
023:
024: import java.lang.reflect.Constructor;
025: import java.lang.reflect.Field;
026: import java.util.ArrayList;
027: import java.util.Collection;
028: import java.util.HashMap;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.List;
032: import java.util.Map;
033: import java.util.Set;
034:
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.dom4j.DocumentException;
038: import org.dom4j.DocumentHelper;
039: import org.dom4j.Element;
040: import org.jbpm.JbpmException;
041: import org.jbpm.util.ClassLoaderUtil;
042:
043: public class FieldInstantiator implements Instantiator {
044:
045: public Object instantiate(Class clazz, String configuration) {
046:
047: // create a new instance with the default constructor
048: Object newInstance = newInstance(clazz);
049:
050: if ((configuration != null) && (!"".equals(configuration))) {
051: // parse the bean configuration
052: Element configurationElement = parseConfiguration(configuration);
053:
054: // loop over the configured properties
055: Iterator iter = configurationElement.elements().iterator();
056: while (iter.hasNext()) {
057: Element propertyElement = (Element) iter.next();
058: String propertyName = propertyElement.getName();
059: setPropertyValue(clazz, newInstance, propertyName,
060: propertyElement);
061: }
062: }
063: return newInstance;
064: }
065:
066: protected void setPropertyValue(Class clazz, Object newInstance,
067: String propertyName, Element propertyElement) {
068: try {
069: Field f = findField(clazz, propertyName);
070: f.setAccessible(true);
071: f.set(newInstance, getValue(f.getType(), propertyElement));
072: } catch (Exception e) {
073: log
074: .error("couldn't parse set field '" + propertyName
075: + "' to value '" + propertyElement.asXML()
076: + "'", e);
077: }
078: }
079:
080: private Field findField(Class clazz, String propertyName)
081: throws NoSuchFieldException {
082: Field f = null;
083: if (clazz != null) {
084: try {
085: f = clazz.getDeclaredField(propertyName);
086: } catch (NoSuchFieldException e) {
087: f = findField(clazz.getSuperclass(), propertyName);
088: }
089: }
090: return f;
091: }
092:
093: protected Element parseConfiguration(String configuration) {
094: Element element = null;
095: try {
096: element = DocumentHelper.parseText(
097: "<action>" + configuration + "</action>")
098: .getRootElement();
099: } catch (DocumentException e) {
100: log.error("couldn't parse bean configuration : "
101: + configuration, e);
102: throw new JbpmException(e);
103: }
104: return element;
105: }
106:
107: protected Object newInstance(Class clazz) {
108: Object newInstance = null;
109: try {
110: newInstance = clazz.newInstance();
111: } catch (Exception e) {
112: log.error("couldn't instantiate type '" + clazz.getName()
113: + "' with the default constructor");
114: throw new JbpmException(e);
115: }
116: return newInstance;
117: }
118:
119: public static Object getValue(Class type, Element propertyElement) {
120: // parse the value
121: Object value = null;
122: try {
123:
124: if (type == String.class) {
125: value = propertyElement.getText();
126: } else if ((type == Integer.class) || (type == int.class)) {
127: value = new Integer(propertyElement.getTextTrim());
128: } else if ((type == Long.class) || (type == long.class)) {
129: value = new Long(propertyElement.getTextTrim());
130: } else if ((type == Float.class) || (type == float.class)) {
131: value = new Float(propertyElement.getTextTrim());
132: } else if ((type == Double.class) || (type == double.class)) {
133: value = new Double(propertyElement.getTextTrim());
134: } else if ((type == Boolean.class)
135: || (type == boolean.class)) {
136: value = Boolean.valueOf(propertyElement.getTextTrim());
137: } else if ((type == Character.class)
138: || (type == char.class)) {
139: value = new Character(propertyElement.getTextTrim()
140: .charAt(0));
141: } else if ((type == Short.class) || (type == short.class)) {
142: value = new Short(propertyElement.getTextTrim());
143: } else if ((type == Byte.class) || (type == byte.class)) {
144: value = new Byte(propertyElement.getTextTrim());
145: } else if (List.class.isAssignableFrom(type)) {
146: value = getCollection(propertyElement, new ArrayList());
147: } else if (Set.class.isAssignableFrom(type)) {
148: value = getCollection(propertyElement, new HashSet());
149: } else if (Collection.class.isAssignableFrom(type)) {
150: value = getCollection(propertyElement, new ArrayList());
151: } else if (Map.class.isAssignableFrom(type)) {
152: value = getMap(propertyElement, new HashMap());
153: } else if (Element.class.isAssignableFrom(type)) {
154: value = propertyElement;
155: } else {
156: Constructor constructor = type
157: .getConstructor(new Class[] { String.class });
158: if ((propertyElement.isTextOnly())
159: && (constructor != null)) {
160: value = constructor
161: .newInstance(new Object[] { propertyElement
162: .getTextTrim() });
163: }
164: }
165: } catch (Exception e) {
166: log.error("couldn't parse the bean property value '"
167: + propertyElement.asXML() + "' to a '"
168: + type.getName() + "'");
169: throw new JbpmException(e);
170: }
171: return value;
172: }
173:
174: static Object getMap(Element mapElement, Map map) {
175: Class keyClass = String.class;
176: String keyType = mapElement.attributeValue("key-type");
177: if (keyType != null) {
178: keyClass = ClassLoaderUtil.loadClass(keyType);
179: }
180:
181: Class valueClass = String.class;
182: String valueType = mapElement.attributeValue("value-type");
183: if (valueType != null) {
184: valueClass = ClassLoaderUtil.loadClass(valueType);
185: }
186:
187: Iterator iter = mapElement.elementIterator();
188: while (iter.hasNext()) {
189: Element element = (Element) iter.next();
190: Element keyElement = element.element("key");
191: Element valueElement = element.element("value");
192:
193: map.put(getValue(keyClass, keyElement), getValue(
194: valueClass, valueElement));
195: }
196: return map;
197: }
198:
199: static Object getCollection(Element collectionElement,
200: Collection collection) {
201: Class elementClass = String.class;
202: String elementType = collectionElement
203: .attributeValue("element-type");
204: if (elementType != null) {
205: elementClass = ClassLoaderUtil.loadClass(elementType);
206: }
207: Iterator iter = collectionElement.elementIterator();
208: while (iter.hasNext()) {
209: Element element = (Element) iter.next();
210: collection.add(getValue(elementClass, element));
211: }
212: return collection;
213: }
214:
215: private static final Log log = LogFactory
216: .getLog(FieldInstantiator.class);
217: }
|