package org.oddjob.values; import java.util.LinkedHashMap; import java.util.Map; import org.apache.commons.beanutils.expression.DefaultResolver; import org.apache.commons.beanutils.expression.Resolver; import org.oddjob.arooa.ArooaException; import org.oddjob.arooa.ArooaValue; import org.oddjob.arooa.reflect.ArooaPropertyException; import org.oddjob.arooa.reflect.PropertyAccessor; import org.oddjob.framework.SimpleJob; /** * @oddjob.description A job which sets properties in other * jobs when it executes. * * @oddjob.example * * Setting lots of properties. * * {@oddjob.xml.resource org/oddjob/values/set-test.xml} * * This is the configuration for one * of the tests. */ public class SetJob extends SimpleJob { private final Map<String, ArooaValue> values = new LinkedHashMap<String, ArooaValue>(); /** * Add a name value pair. * * @oddjob.property values * @oddjob.description The thing to set on the property that is given by * the key of this mapped property. * @oddjob.required No, but pointless if not provided. * * @param name The name of the variable. * @param value The runtime configurable for the value. */ public void setValues(String name, ArooaValue value) { values.put(name, value); } /* * (non-Javadoc) * @see org.oddjob.jobs.AbstractJob#execute() */ protected int execute() throws Exception { for (Map.Entry<String, ArooaValue> entry : values.entrySet()) { String name = entry.getKey(); ArooaValue value = entry.getValue(); logger().info("Setting [" + name + "] = [" + value + "]"); setProperty(name, value); } return 0; } /** * Set a property on a Component in the registry. This method * will resolve the valueFor before setting the property. This might * not be the desired result for things like variables. The * way round this would be to create a dummy type ProxyType which * the DynaClass of VariablesJob, SetJob etc would return and which * valueFor methods would recognize and would return themselves as the * valueFor - but that's a lot of work and propbably isn't requied * much. * <p> * This method should really be a lot better at resolving the types of * nested beans for property conversion. This method only goes as far as * resolving past component id so the correct type of component is used. */ private void setProperty( String property, ArooaValue value) throws ArooaPropertyException { Resolver resolver = new DefaultResolver(); String compName = resolver.next(property); String propertyExpression = resolver.remove(property); if ( propertyExpression == null) { throw new ArooaException("No thing specified to set property on."); } Object component = getArooaSession().getBeanRegistry( ).lookup(compName); if (component == null) { throw new ArooaException("No component [" + compName + "]"); } PropertyAccessor propertyAccessor = getArooaSession().getTools().getPropertyAccessor(); propertyAccessor = propertyAccessor.accessorWithConversions( getArooaSession().getTools().getArooaConverter()); propertyAccessor.setProperty(component, propertyExpression, value); } }