Skip to content

Commit

Permalink
#60 First crack at PathHelper for java config
Browse files Browse the repository at this point in the history
  • Loading branch information
Taylor Wicksell committed May 27, 2014
1 parent ae23c88 commit 4e50648
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package org.springjutsu.validation.dsl;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import org.apache.commons.lang.StringUtils;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;

/**
* Will generate dynamic proxies along a call chain. Does not support
* abstract/final types. Does not support classes with no default constructor.
* Internally, overrides the toString method on each proxy to return the current path.
* @author twicksell
*
*/
public class PathHelper {

public static <T> T forEntity(Class<T> clazz)
{
return forEntity(clazz, "", null);
}

protected static <T> T forEntity(Class<T> clazz, String path, Class parameterizedType)
{
Enhancer enhancer = new Enhancer();
return (T) enhancer.create(clazz, new PathBuildingInvocationHandler(path, parameterizedType));
}


}

class PathBuildingInvocationHandler extends PathHelper implements InvocationHandler
{

String path;
Class parameterizedType;
public PathBuildingInvocationHandler(String path, Class parameterizedType) {
this.path=path;
this.parameterizedType=parameterizedType;
}
@Override
public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
Class returnType = (parameterizedType != null) ? parameterizedType : method.getReturnType();
Class parameterType = null;
if(method.getName().equals("toString"))
return path;
if(Collection.class.isAssignableFrom(method.getReturnType()))
{
parameterType = Class.forName(((ParameterizedType)method.getGenericReturnType()).getActualTypeArguments()[0].getTypeName());
}


if(!path.isEmpty() && parameterizedType == null)
path+=".";
path+=StringUtils.uncapitalize(method.getName().replace("get", ""));
if(method.getReturnType().equals(String.class))
return path;
if(Modifier.isFinal(method.getReturnType().getModifiers()))
throw new RuntimeException("Cannot help with final or abstract return types: "+method.getReturnType());

return PathHelper.forEntity(returnType, path, parameterType);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,22 @@ public static ValidationRuleBuilder rule(String path, String type)
.forPath(path).usingHandler(type).behaviorOnFail(RuleErrorMode.ERROR);
}

public static ValidationRuleBuilder rule(Object path, String type)
{
return rule(path.toString(), type);
}

public static <M,A> ValidationRuleBuilder rule(String path, String message, RuleExecutor<M,A> handlerImpl)
{
return ReflectionBuilder.implementationFor(ValidationRuleBuilder.class)
.usingAttributeAccessStrategy(new OverloadedPropertyAwareSetterAttributeAccessStrategy()).create()
.forPath(path).withMessage(message).usingHandler(handlerImpl).behaviorOnFail(RuleErrorMode.ERROR);
}

public static <M,A> ValidationRuleBuilder rule(Object path, String message, RuleExecutor<M,A> handlerImpl)
{
return rule(path.toString(), message, handlerImpl);
}
public static ValidationContextBuilder context(String type, String... qualifiers)
{
return ReflectionBuilder.implementationFor(ValidationContextBuilder.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.validation.Errors;
import org.springjutsu.validation.dsl.PathHelper;
import org.springjutsu.validation.dsl.Validation;
import org.springjutsu.validation.executors.impl.RequiredRuleExecutor;
import org.springjutsu.validation.rules.ValidationEntity;
Expand Down Expand Up @@ -68,7 +69,7 @@ ValidationEntity personValidation()
Validation.rule("lastName", "required").withMessage("dizzam"),
Validation.rule("address", "required").withMessage("doh")
.havingValidationContexts(Validation.group("buster")
.havingRules(Validation.rule("address.lineOne", "required").withMessage("p-p-p-pow")))
.havingRules(Validation.rule(PathHelper.forEntity(Customer.class).getAddress().getLineOne(), "required").withMessage("p-p-p-pow")))
))
.build();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.springjutsu.validation.dsl;

import org.junit.Assert;
import org.junit.Test;
import org.springjutsu.validation.test.entities.Company;
import org.springjutsu.validation.test.entities.Customer;

public class PathHelperTest {

@Test
public void test()
{
Assert.assertEquals("address", PathHelper.forEntity(Customer.class).getAddress().toString());
Assert.assertEquals("address.lineOne", PathHelper.forEntity(Customer.class).getAddress().getLineOne());
Assert.assertEquals("customers.firstName", PathHelper.forEntity(Company.class).getCustomers().get(0).getFirstName());
Assert.assertEquals("customers", PathHelper.forEntity(Company.class).getCustomers().toString());
}

}

0 comments on commit 4e50648

Please sign in to comment.