package br.com.six2six.fixturefactory.function.impl; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.StringUtils; import br.com.six2six.fixturefactory.function.AssociationFunction; import br.com.six2six.fixturefactory.function.FixtureFunction; import br.com.six2six.fixturefactory.function.Function; import br.com.six2six.fixturefactory.processor.Processor; import br.com.six2six.fixturefactory.util.ReflectionUtils; public class AssociationFunctionImpl implements AssociationFunction { private String targetAttribute; private Class<?> clazz; private List<String> labels; private Integer quantity; public AssociationFunctionImpl(Integer quantity) { this.quantity = quantity; } public AssociationFunctionImpl(Class<?> clazz, String label) { this.clazz = clazz; this.labels = Arrays.asList(label); } public AssociationFunctionImpl(String targetAttribute) { this.targetAttribute = targetAttribute; } @Override public <T> T generateValue() { return new FixtureFunction(clazz, labels, quantity).generateValue(); } @Override public <T> T generateValue(Processor processor) { return new FixtureFunction(clazz, labels, quantity).generateValue(processor); } @Override public <T> T generateValue(Object owner) { T target = new FixtureFunction(clazz, labels, quantity).generateValue(owner); if (target instanceof Collection<?>) { for (Object item : (Collection<?>) target) { this.setField(item, owner); } } else { this.setField(target, owner); } return target; } @Override public <T> T generateValue(Object owner, Processor processor) { T target = new FixtureFunction(clazz, labels, quantity).generateValue(owner, processor); if (target instanceof Collection<?>) { for (Object item : (Collection<?>) target) { this.setField(item, owner); } } else { this.setField(target, owner); } return target; } @Override public AssociationFunction of(Class<?> clazz, String label) { this.clazz = clazz; this.labels = Arrays.asList(label); return this; } @Override public AssociationFunction of(Class<?> clazz, String... labels) { this.clazz = clazz; this.labels = Arrays.asList(labels); return this; } @Override public Function of(Class<? extends Enum<?>> clazz) { return new EnumFunction(clazz, quantity); } @Override public Function targetAttribute(String targetAttribute) { this.targetAttribute = targetAttribute; return this; } private void setField(Object target, Object value) { String fieldName = targetAttribute; if (StringUtils.isBlank(targetAttribute)) { Field field = this.getAssignableField(target.getClass(), value.getClass()); if (field != null) { fieldName = field.getName(); } } if (!StringUtils.isBlank(fieldName)) { ReflectionUtils.invokeRecursiveSetter(target, fieldName, value); } } private Field getAssignableField(Class<?> clazz, Class<?> fieldType) { Field searchdField = null; for (Field field : clazz.getDeclaredFields()) { if (ClassUtils.isAssignable(field.getType(), fieldType) && !field.isSynthetic()) { searchdField = field; break; } } return searchdField; } }