Skip to content

Commit

Permalink
Merge pull request #73 from nykolaslima/override-nested-attribute-value
Browse files Browse the repository at this point in the history
fixing template where we want to override nested attribute value
  • Loading branch information
nykolaslima committed Jan 29, 2015
2 parents 1c6b90f + d769370 commit 68d6c3b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
39 changes: 32 additions & 7 deletions src/main/java/br/com/six2six/fixturefactory/ObjectFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
Expand Down Expand Up @@ -88,23 +90,28 @@ public <T> List<T> gimme(int quantity, String label, Rule propertiesToOverride)
}

protected Object createObject(Rule rule) {
Map<String, Object> constructorArguments = new HashMap<String, Object>();
Map<String, Property> constructorArguments = new HashMap<String, Property>();
List<Property> deferredProperties = new ArrayList<Property>();
Class<?> clazz = templateHolder.getClazz();

List<String> parameterNames = !ReflectionUtils.hasDefaultConstructor(clazz) ?
lookupConstructorParameterNames(clazz, rule.getProperties()) : new ArrayList<String>();

for (Property property : rule.getProperties()) {
if (parameterNames.contains(property.getRootAttribute())) {
constructorArguments.put(property.getName(), generateConstructorParamValue(property));
if(parameterNames.contains(property.getRootAttribute())) {
constructorArguments.put(property.getName(), property);
} else {
deferredProperties.add(property);
}
}

Object result = ReflectionUtils.newInstance(clazz, processConstructorArguments(parameterNames, constructorArguments));

Set<Property> propertiesNotUsedInConstructor = getPropertiesNotUsedInConstructor(constructorArguments, parameterNames);
if(propertiesNotUsedInConstructor.size() > 0) {
deferredProperties.addAll(propertiesNotUsedInConstructor);
}

for (Property property : deferredProperties) {
ReflectionUtils.invokeRecursiveSetter(result, property.getName(), processPropertyValue(result, property));
}
Expand All @@ -114,6 +121,14 @@ protected Object createObject(Rule rule) {
}
return result;
}

private Set<Property> getPropertiesNotUsedInConstructor(Map<String, Property> constructorArguments, List<String> parameterNames) {
Map<String, Property> propertiesNotUsedInConstructor = new HashMap<String, Property>(constructorArguments);
for(String parameterName : parameterNames) {
propertiesNotUsedInConstructor.remove(parameterName);
}
return new HashSet<Property>(propertiesNotUsedInConstructor.values());
}

@SuppressWarnings("unchecked")
protected <T> List<T> createObjects(int quantity, Rule rule) {
Expand Down Expand Up @@ -166,25 +181,35 @@ private Object generateConstructorParamValue(Property property) {
}
}

protected List<Object> processConstructorArguments(List<String> parameterNames, Map<String, Object> arguments) {
protected List<Object> processConstructorArguments(List<String> parameterNames, Map<String, Property> arguments) {
List<Object> values = new ArrayList<Object>();
Map<String, Object> processedArguments = processArguments(arguments);

if (owner != null && ReflectionUtils.isInnerClass(templateHolder.getClazz())) {
values.add(owner);
}

TransformerChain transformerChain = buildTransformerChain(new ParameterPlaceholderTransformer(arguments));
TransformerChain transformerChain = buildTransformerChain(new ParameterPlaceholderTransformer(processedArguments));

for (String parameterName : parameterNames) {
Class<?> fieldType = ReflectionUtils.invokeRecursiveType(templateHolder.getClazz(), parameterName);
Object result = arguments.get(parameterName);
Object result = processedArguments.get(parameterName);
if (result == null) {
result = processChainedProperty(parameterName, fieldType, arguments);
result = processChainedProperty(parameterName, fieldType, processedArguments);
}
values.add(transformerChain.transform(result, fieldType));
}
return values;
}

private Map<String, Object> processArguments(Map<String, Property> arguments) {
Map<String, Object> processedArguments = new HashMap<String, Object>();
for(Entry<String, Property> entry : arguments.entrySet()) {
processedArguments.put(entry.getKey(), generateConstructorParamValue(entry.getValue()));
}

return processedArguments;
}

protected Object processChainedProperty(String parameterName, Class<?> fieldType, Map<String, Object> arguments) {
Rule rule = new Rule();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,14 @@ public void shouldWorkWhenChainingInheritedProperty() {
assertThat(child.getParentAttribute().getValue().length(), is(8));
assertThat(child.getChildAttribute().length(), is(16));
}

@Test
public void shouldOverrideNestedObjectAttribute() {
Immutable result = Fixture.from(Immutable.class).gimme("fullConstructor", new Rule() {{
add("address.street", "Rua do Nykolas");
}});

assertThat(result.getAddress().getStreet(), equalTo("Rua do Nykolas"));
}

}

0 comments on commit 68d6c3b

Please sign in to comment.