All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jbpm.instantiation.FieldInstantiator Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jbpm.instantiation;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jbpm.JbpmException;
import org.jbpm.util.ClassLoaderUtil;

public class FieldInstantiator implements Instantiator {

  public Object instantiate(Class clazz, String configuration) {
    // create a new instance with the default constructor
    Object newInstance = newInstance(clazz);

    if (configuration != null && configuration.length() > 0) {
      // parse the bean configuration
      Element configurationElement = parseConfiguration(configuration);

      // loop over the configured properties
      for (Iterator iter = configurationElement.elementIterator(); iter.hasNext();) {
        Element propertyElement = (Element) iter.next();
        String propertyName = propertyElement.getName();
        setPropertyValue(clazz, newInstance, propertyName, propertyElement);
      }
    }
    return newInstance;
  }

  protected void setPropertyValue(Class clazz, Object instance, String propertyName,
    Element propertyElement) {
    Field field = findField(clazz, propertyName);
    if (field != null) {
      field.setAccessible(true);
      Object value = getValue(field.getType(), propertyElement);
      try {
        field.set(instance, value);
      }
      catch (IllegalArgumentException e) {
        log.error("could not set '" + propertyName + "' to: " + value, e);
      }
      catch (IllegalAccessException e) {
        log.error(getClass() + " has no access to " + field, e);
      }
    }
    else {
      log.error("field not found: " + propertyName);
    }
  }

  private Field findField(Class clazz, String propertyName) {
    do {
      try {
        return clazz.getDeclaredField(propertyName);
      }
      catch (NoSuchFieldException e) {
        clazz = clazz.getSuperclass();
      }
    } while (clazz != null);

    return null;
  }

  protected Element parseConfiguration(String configuration) {
    try {
      return DocumentHelper.parseText("" + configuration + "")
        .getRootElement();
    }
    catch (DocumentException e) {
      throw new JbpmException("failed to parse configuration", e);
    }
  }

  protected Object newInstance(Class clazz) {
    try {
      return clazz.newInstance();
    }
    catch (InstantiationException e) {
      throw new JbpmException("failed to instantiate " + clazz, e);
    }
    catch (IllegalAccessException e) {
      throw new JbpmException(getClass() + " has no access to " + clazz, e);
    }
  }

  public static Object getValue(Class type, Element propertyElement) {
    // parse the value
    Object value = null;
    if (type == String.class) {
      value = propertyElement.getText();
    }
    else if (type == Integer.class || type == int.class) {
      value = new Integer(propertyElement.getTextTrim());
    }
    else if (type == Long.class || type == long.class) {
      value = new Long(propertyElement.getTextTrim());
    }
    else if (type == Float.class || type == float.class) {
      value = new Float(propertyElement.getTextTrim());
    }
    else if (type == Double.class || type == double.class) {
      value = new Double(propertyElement.getTextTrim());
    }
    else if (type == Boolean.class || type == boolean.class) {
      value = Boolean.valueOf(propertyElement.getTextTrim());
    }
    else if (type == Character.class || type == char.class) {
      value = new Character(propertyElement.getTextTrim().charAt(0));
    }
    else if (type == Short.class || type == short.class) {
      value = new Short(propertyElement.getTextTrim());
    }
    else if (type == Byte.class || type == byte.class) {
      value = new Byte(propertyElement.getTextTrim());
    }
    else if (type == List.class || type == Collection.class) {
      value = getCollection(propertyElement, new ArrayList());
    }
    else if (type == Set.class) {
      value = getCollection(propertyElement, new HashSet());
    }
    else if (type == SortedSet.class) {
      value = getCollection(propertyElement, new TreeSet());
    }
    else if (type == Map.class) {
      value = getMap(propertyElement, new HashMap());
    }
    else if (type == SortedMap.class) {
      value = getMap(propertyElement, new TreeMap());
    }
    else if (Element.class.isAssignableFrom(type)) {
      value = propertyElement;
    }
    else {
      try {
        if (Collection.class.isAssignableFrom(type)) {
          value = getCollection(propertyElement, (Collection) type.newInstance());
        }
        else if (Map.class.isAssignableFrom(type)) {
          value = getMap(propertyElement, (Map) type.newInstance());
        }
        else if (propertyElement.isTextOnly()) {
          Constructor constructor = type.getConstructor(new Class[] {
            String.class
          });
          try {
            value = constructor.newInstance(new Object[] {
              propertyElement.getTextTrim()
            });
          }
          catch (IllegalAccessException e) {
            log.error(FieldInstantiator.class + " has no access to " + constructor);
          }
          catch (InvocationTargetException e) {
            log.error(constructor + " threw exception", e.getCause());
          }
        }
        else {
          log.error("element '" + propertyElement.getName() + "' has non-text content");
        }
      }
      catch (InstantiationException e) {
        log.error("failed to instantiate " + type, e);
      }
      catch (IllegalAccessException e) {
        log.error(FieldInstantiator.class + " has no access to " + type, e);
      }
      catch (NoSuchMethodException e) {
        log.error("constructor not found: " + type.getName() + "(String)", e);
      }
    }
    return value;
  }

  private static Map getMap(Element mapElement, Map map) {
    Class keyClass = classForAttributeValue(mapElement, "key-type");
    Class valueClass = classForAttributeValue(mapElement, "value-type");

    for (Iterator iter = mapElement.elementIterator(); iter.hasNext();) {
      Element element = (Element) iter.next();
      Element keyElement = element.element("key");
      Element valueElement = element.element("value");

      map.put(getValue(keyClass, keyElement), getValue(valueClass, valueElement));
    }
    return map;
  }

  private static Object getCollection(Element collectionElement, Collection collection) {
    Class elementClass = classForAttributeValue(collectionElement, "element-type");

    for (Iterator iter = collectionElement.elementIterator(); iter.hasNext();) {
      Element element = (Element) iter.next();
      collection.add(getValue(elementClass, element));
    }
    return collection;
  }

  /**
   * Returns the Class associated with the value for the attribute with the given
   * name.
   */
  private static Class classForAttributeValue(Element element, String attributeName) {
    String className = element.attributeValue(attributeName);
    if (className != null) {
      try {
        return ClassLoaderUtil.classForName(className);
      }
      catch (ClassNotFoundException e) {
        throw new JbpmException("no such class " + className, e);
      }
    }
    return String.class;
  }

  private static final Log log = LogFactory.getLog(FieldInstantiator.class);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy