Skip to content

Commit

Permalink
supporting ids of any type
Browse files Browse the repository at this point in the history
  • Loading branch information
lucascs committed Mar 22, 2011
1 parent d47fedd commit adde295
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public interface Converters {
* @param container
* @return
*/
Converter<?> to(Class<?> type);
<T> Converter<T> to(Class<T> type);

void register(Class<? extends Converter<?>> converterClass);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ public void register(Class<? extends Converter<?>> converterClass) {
classes.addFirst(converterClass);
}

public Converter<?> to(Class<?> clazz) {
public <T> Converter<T> to(Class<T> clazz) {
if (!existsFor(clazz)) {
throw new VRaptorException("Unable to find converter for " + clazz.getName());
}
return container.instanceFor(findConverterType(clazz));
return (Converter<T>) container.instanceFor(findConverterType(clazz));
}

private Class<? extends Converter<?>> findConverterType(Class<?> clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,37 @@
import static com.google.common.collect.Iterables.isEmpty;
import static java.util.Arrays.asList;

import java.io.Serializable;
import java.lang.annotation.Annotation;

import javax.servlet.http.HttpServletRequest;

import net.vidageek.mirror.dsl.Mirror;

import org.hibernate.Session;

import br.com.caelum.vraptor.Converter;
import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.Lazy;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.Converters;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.core.Localization;
import br.com.caelum.vraptor.http.ParameterNameProvider;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;

/**
*
* Interceptor that loads given entity from the database.
*
* @author Lucas Cavalcanti
* @since
* @author Cecilia Fernandes
* @since 3.3.2
*
*/
@Intercepts(before=ParametersInstantiatorInterceptor.class)
Expand All @@ -38,21 +46,21 @@ public class ParameterLoaderInterceptor implements Interceptor {
private final HttpServletRequest request;
private final ParameterNameProvider provider;
private final Result result;
private final Converters converters;
private final Localization localization;

public ParameterLoaderInterceptor(Session session, HttpServletRequest request, ParameterNameProvider provider, Result result) {
public ParameterLoaderInterceptor(Session session, HttpServletRequest request, ParameterNameProvider provider,
Result result, Converters converters, Localization localization) {
this.session = session;
this.request = request;
this.provider = provider;
this.result = result;
this.converters = converters;
this.localization = localization;
}

public boolean accepts(ResourceMethod method) {
for (Annotation[] param : method.getMethod().getParameterAnnotations()) {
if (any(asList(param), instanceOf(Load.class))) {
return true;
}
}
return false;
return any(asList(method.getMethod().getParameterAnnotations()), hasLoadAnnotation());
}

public void intercept(InterceptorStack stack, ResourceMethod method, Object resourceInstance)
Expand Down Expand Up @@ -80,13 +88,25 @@ public void intercept(InterceptorStack stack, ResourceMethod method, Object reso
stack.next(method, resourceInstance);
}

private Object load(String name, Class<?> types) {
private Object load(String name, Class type) {
String parameter = request.getParameter(name + ".id");
if (parameter == null) {
return null;
}
Long id = Long.valueOf(parameter);
return session.get(types, id);
Class<?> idType = new Mirror().on(type).reflect().field("id").getType();
Converter<?> converter = converters.to(idType);

Serializable id = (Serializable) converter.convert(parameter, type, localization.getBundle());
return session.get(type, id);
}

private Predicate<Annotation[]> hasLoadAnnotation() {
return new Predicate<Annotation[]>() {
public boolean apply(Annotation[] param) {
return any(asList(param), instanceOf(Load.class));
}
};
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ void setDelegateConverters(Converters delegateConverters) {
this.delegateConverters = delegateConverters;
}

public Converter<?> to(Class<?> type) {
public <T> Converter<T> to(Class<T> type) {
Converter<?> vraptor2Convterter = findVRaptor2Converter(type);
return vraptor2Convterter == null ? delegateConverters.to(type) : vraptor2Convterter;
return (Converter<T>) (vraptor2Convterter == null ? delegateConverters.to(type) : vraptor2Convterter);
}

private Converter<?> findVRaptor2Converter(Class<?> type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
import org.mockito.MockitoAnnotations;

import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.converter.LongConverter;
import br.com.caelum.vraptor.converter.StringConverter;
import br.com.caelum.vraptor.core.Converters;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.http.ParameterNameProvider;
import br.com.caelum.vraptor.resource.DefaultResourceMethod;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.util.test.MockLocalization;

public class ParameterLoaderInterceptorTest {

Expand All @@ -27,18 +31,25 @@ public class ParameterLoaderInterceptorTest {
private @Mock HttpServletRequest request;
private @Mock ParameterNameProvider provider;
private @Mock Result result;
private @Mock Converters converters;

private ParameterLoaderInterceptor interceptor;
private ResourceMethod method;
private @Mock InterceptorStack stack;
private Object instance;
private ResourceMethod managed;
private ResourceMethod other;

@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
interceptor = new ParameterLoaderInterceptor(session, request, provider, result);
interceptor = new ParameterLoaderInterceptor(session, request, provider, result, converters, new MockLocalization());
method = DefaultResourceMethod.instanceFor(Resource.class, Resource.class.getMethod("method", Entity.class));
managed = DefaultResourceMethod.instanceFor(Resource.class, Resource.class.getMethod("managed", Entity.class));
other = DefaultResourceMethod.instanceFor(Resource.class, Resource.class.getMethod("other", OtherEntity.class));

when(converters.to(Long.class)).thenReturn(new LongConverter());
when(converters.to(String.class)).thenReturn(new StringConverter());
}

@Test
Expand All @@ -55,6 +66,20 @@ public void shouldLoadEntityUsingId() throws Exception {
verify(stack).next(method, instance);
}

@Test
public void shouldLoadEntityUsingIdOfAnyType() throws Exception {
when(provider.parameterNamesFor(other.getMethod())).thenReturn(new String[] {"entity"});
when(request.getParameter("entity.id")).thenReturn("123");
OtherEntity expectedEntity = new OtherEntity();
when(session.get(OtherEntity.class, "123")).thenReturn(expectedEntity);

interceptor.intercept(stack, other, instance);

verify(request).setAttribute("entity", expectedEntity);
verify(session).evict(expectedEntity);
verify(stack).next(other, instance);
}

@Test
public void shouldNotEvictIfIsManaged() throws Exception {
when(provider.parameterNamesFor(managed.getMethod())).thenReturn(new String[] {"entity"});
Expand Down Expand Up @@ -97,10 +122,15 @@ public void shouldSend404WhenIdDoesntExist() throws Exception {
static class Entity {
private Long id;
}
static class OtherEntity {
private String id;
}

static class Resource {
public void method(@Load Entity entity) {
}
public void other(@Load OtherEntity entity) {
}
public void managed(@Load(managed=true) Entity entity) {
}
}
Expand Down

0 comments on commit adde295

Please sign in to comment.