package org.oddjob.beanbus.destinations;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;
import org.oddjob.arooa.ArooaSession;
import org.oddjob.arooa.ArooaTools;
import org.oddjob.arooa.beanutils.MagicBeanClassCreator;
import org.oddjob.arooa.deploy.annotations.ArooaHidden;
import org.oddjob.arooa.life.ArooaSessionAware;
import org.oddjob.arooa.reflect.ArooaClass;
import org.oddjob.arooa.reflect.BeanOverview;
import org.oddjob.arooa.reflect.PropertyAccessor;
import org.oddjob.beanbus.AbstractDestination;
import org.oddjob.beanbus.BusFilter;
/**
* @oddjob.description Copy the properties of a bean to another bean.
*
* @oddjob.example
*
* Copy beans into bean properties given by the class.
*
* {@oddjob.xml.resource org/oddjob/beanbus/destinations/BeanCopyJavaClass.xml}
*
* @oddjob.example
*
* Copy beans into a dynamically created bean.
*
* {@oddjob.xml.resource org/oddjob/beanbus/destinations/BeanCopyMagicClass.xml}
*
* @oddjob.example
*
* Copy beans into a dynamically created bean the properties of which match
* the source bean.
*
* {@oddjob.xml.resource org/oddjob/beanbus/destinations/BeanCopyNoClass.xml}
*
* @author rob
*
* @param <F> From
* @param <T> To
*/
public class BeanCopy<F, T> extends AbstractDestination<F>
implements BusFilter<F, T>, ArooaSessionAware {
private static final Logger logger = Logger.getLogger(BeanCopy.class);
private static AtomicInteger instance = new AtomicInteger();
private String name;
private ArooaClass arooaClass;
private Collection<? super T> to;
private PropertyAccessor accessor;
private Map<String, String> mappings =
new LinkedHashMap<String, String>();
@ArooaHidden
@Override
public void setArooaSession(ArooaSession session) {
ArooaTools tools = session.getTools();
this.accessor = tools.getPropertyAccessor().accessorWithConversions(
tools.getArooaConverter());
}
@SuppressWarnings("unchecked")
@Override
public boolean add(F bean) {
if (arooaClass == null) {
arooaClass = createClassFromBean(bean);
}
Object toBean = arooaClass.newInstance();
for (Map.Entry<String, String> mapping : mappings.entrySet()) {
String from = mapping.getKey();
String to = mapping.getValue();
accessor.setProperty(toBean, to,
accessor.getProperty(bean, from));
}
to.add((T) toBean);
return true;
}
protected ArooaClass createClassFromBean(F bean) {
String magicClassName = "BeanCopy-" + instance.incrementAndGet();
logger.debug("Creating Magic Bean Class [" + magicClassName + "]");
MagicBeanClassCreator creator = new MagicBeanClassCreator(
magicClassName);
ArooaClass sourceClass = accessor.getClassName(bean);
BeanOverview overview = sourceClass.getBeanOverview(accessor);
for (Map.Entry<String, String> mapping : mappings.entrySet()) {
String from = mapping.getKey();
String to = mapping.getValue();
Class<?> propertyType = overview.getPropertyType(from);
logger.debug("Adding property to copy [" + to +
"] of type [" + propertyType + "]");
creator.addProperty(to, propertyType);
}
return creator.create();
}
public void setArooaClass(ArooaClass arooaClass) {
this.arooaClass = arooaClass;
}
@Override
public void setTo(Collection<? super T> to) {
this.to = to;
}
public Collection<? super T> getTo() {
return to;
}
public void setMappings(String from, String to) {
mappings.put(from, to);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
if (name == null) {
return getClass().getSimpleName();
}
else {
return name;
}
}
}