diff --git a/spring-data-rest-webmvc/build.gradle b/spring-data-rest-webmvc/build.gradle index 69fc25827..684b8d416 100644 --- a/spring-data-rest-webmvc/build.gradle +++ b/spring-data-rest-webmvc/build.gradle @@ -16,7 +16,7 @@ dependencies { // Repository Exporter support compile project(":spring-data-rest-repository") - compile "org.springframework.hateoas:spring-hateoas:0.2.0.BUILD-SNAPSHOT" + compile "org.springframework.hateoas:spring-hateoas:0.3.0.BUILD-SNAPSHOT" compile "org.springframework.data:spring-data-commons-core:$sdCommonsVersion" runtime "org.hibernate:hibernate-entitymanager:$hibernateVersion" diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java index eb665fa65..b593305fb 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java @@ -16,7 +16,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl * * @author Jon Brisbin */ -public class RepositoryRestHandlerAdapter extends ResourceEnricherInvokingHandlerAdapter { +public class RepositoryRestHandlerAdapter extends ResourceProcessorInvokingHandlerAdapter { @Autowired private ResourcesReturnValueHandler resourcesReturnValueHandler; diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceEnricherHandlerMethodReturnValueHandler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandler.java similarity index 60% rename from spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceEnricherHandlerMethodReturnValueHandler.java rename to spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandler.java index 8e53b77fe..8d745fca1 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceEnricherHandlerMethodReturnValueHandler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorHandlerMethodReturnValueHandler.java @@ -17,6 +17,7 @@ package org.springframework.data.rest.webmvc; import static org.springframework.data.util.ClassTypeInformation.*; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -28,64 +29,71 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.TypeInformation; import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceEnricher; +import org.springframework.hateoas.ResourceProcessor; import org.springframework.hateoas.ResourceSupport; import org.springframework.hateoas.Resources; import org.springframework.http.HttpEntity; +import org.springframework.http.ResponseEntity; import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; /** * {@link HandlerMethodReturnValueHandler} to post-process the objects returned from controller methods using the - * configured {@link ResourceEnricher}s. + * configured {@link ResourceProcessor}s. * * @author Oliver Gierke */ -public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler { +public class ResourceProcessorHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler { private static final TypeInformation RESOURCE_TYPE = from(Resource.class); private static final TypeInformation RESOURCES_TYPE = from(Resources.class); + private static final Field CONTENT_FIELD = ReflectionUtils.findField(Resources.class, "content"); + + static { + ReflectionUtils.makeAccessible(CONTENT_FIELD); + } private final HandlerMethodReturnValueHandler delegate; - private final List enrichers; + private final List processors; /** - * Creates a new {@link ResourceEnricherHandlerMethodReturnValueHandler} using the given delegate to eventually + * Creates a new {@link ResourceProcessorHandlerMethodReturnValueHandler} using the given delegate to eventually * delegate calls to {@link #handleReturnValue(Object, MethodParameter, ModelAndViewContainer, NativeWebRequest)} to. - * Will consider the given {@link ResourceEnricher} to post-process the controller methods return value to before + * Will consider the given {@link ResourceProcessor} to post-process the controller methods return value to before * invoking the delegate. * * @param delegate the {@link HandlerMethodReturnValueHandler} to evenually delegate calls to, must not be * {@literal null}. - * @param enrichers the {@link ResourceEnricher}s to be considered, must not be {@literal null}. + * @param processors the {@link ResourceProcessor}s to be considered, must not be {@literal null}. */ - public ResourceEnricherHandlerMethodReturnValueHandler(HandlerMethodReturnValueHandler delegate, - List> enrichers) { + public ResourceProcessorHandlerMethodReturnValueHandler(HandlerMethodReturnValueHandler delegate, + List> processors) { Assert.notNull(delegate, "Delegate must not be null!"); - Assert.notNull(enrichers, "ResourceEnrichers must not be null!"); + Assert.notNull(processors, "ResourceProcessors must not be null!"); this.delegate = delegate; - this.enrichers = new ArrayList(); + this.processors = new ArrayList(); - for (ResourceEnricher enricher : enrichers) { + for (ResourceProcessor processor : processors) { - TypeInformation componentType = from(enricher.getClass()).getSuperTypeInformation(ResourceEnricher.class) + TypeInformation componentType = from(processor.getClass()).getSuperTypeInformation(ResourceProcessor.class) .getComponentType(); Class rawType = componentType.getType(); if (Resource.class.isAssignableFrom(rawType)) { - this.enrichers.add(new ResourceEnricherWrapper(enricher)); + this.processors.add(new ResourceProcessorWrapper(processor)); } else if (Resources.class.isAssignableFrom(rawType)) { - this.enrichers.add(new ResourcesEnricherWrapper(enricher)); + this.processors.add(new ResourcesProcessorWrapper(processor)); } else { - this.enrichers.add(new DefaultEnricherWrapper(enricher)); + this.processors.add(new DefaultProcessorWrapper(processor)); } } - Collections.sort(this.enrichers, AnnotationAwareOrderComparator.INSTANCE); + Collections.sort(this.processors, AnnotationAwareOrderComparator.INSTANCE); } /* @@ -117,7 +125,7 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM return; } - // We have a Resource or Resources - find suitable enrichers + // We have a Resource or Resources - find suitable processors TypeInformation targetType = ClassTypeInformation.fromReturnTypeOf(returnType.getMethod()); // Unbox HttpEntity @@ -136,6 +144,7 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM Resources resources = (Resources) value; TypeInformation elementTargetType = targetType.getSuperTypeInformation(Resources.class).getComponentType(); + List result = new ArrayList(resources.getContent().size()); for (Object element : resources) { @@ -144,22 +153,59 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM elementTargetType = elementTypeInformation; } - for (EnricherWrapper wrapper : this.enrichers) { - if (wrapper.supports(elementTargetType, element)) { - wrapper.invokeEnricher(element); - } - } + result.add(invokeProcessorsFor(element, elementTargetType)); } + + ReflectionUtils.setField(CONTENT_FIELD, resources, result); } + Object result = invokeProcessorsFor(value, targetType); + delegate.handleReturnValue(rewrapResult(result, returnValue), returnType, mavContainer, webRequest); + } + + /** + * Invokes all registered {@link ResourceProcessor}s registered for the given {@link TypeInformation}. + * + * @param value the object to process + * @param targetType + * @return + */ + private Object invokeProcessorsFor(Object value, TypeInformation targetType) { + + Object currentValue = value; + // Process actual value - for (EnricherWrapper wrapper : this.enrichers) { - if (wrapper.supports(targetType, value)) { - wrapper.invokeEnricher(value); + for (ProcessorWrapper wrapper : this.processors) { + if (wrapper.supports(targetType, currentValue)) { + currentValue = wrapper.invokeProcessor(currentValue); } } - delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest); + return currentValue; + } + + /** + * Re-wraps the result of the post-processing work into an {@link HttpEntity} or {@link ResponseEntity} if the + * original value was one of those two types. Copies headers and status code from the original value but uses the new + * body. + * + * @param newBody the post-processed value. + * @param originalValue the original input value. + * @return + */ + static Object rewrapResult(Object newBody, Object originalValue) { + + if (!(originalValue instanceof HttpEntity)) { + return newBody; + } + + if (originalValue instanceof ResponseEntity) { + ResponseEntity source = (ResponseEntity) originalValue; + return new ResponseEntity(newBody, source.getHeaders(), source.getStatusCode()); + } else { + HttpEntity source = (HttpEntity) originalValue; + return new HttpEntity(newBody, source.getHeaders()); + } } /** @@ -173,58 +219,58 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM } /** - * Interface to unify interaction with {@link ResourceEnricher}s. The {@link Ordered} rank should be determined by the - * underlying processor. + * Interface to unify interaction with {@link ResourceProcessor}s. The {@link Ordered} rank should be determined by + * the underlying processor. * * @author Oliver Gierke */ - private interface EnricherWrapper extends Ordered { + private interface ProcessorWrapper extends Ordered { /** * Returns whether the underlying processor supports the given {@link TypeInformation}. It might also aditionally - * inspect the object that would eventually be handed to the enricher. + * inspect the object that would eventually be handed to the processor. * * @param typeInformation the type of object to be post processed, will never be {@literal null}. - * @param value the object that would be passed into the enricher eventually, can be {@literal null}. + * @param value the object that would be passed into the processor eventually, can be {@literal null}. * @return */ boolean supports(TypeInformation typeInformation, Object value); /** - * Performs the actual invocation of the enricher. Implementations can be sure + * Performs the actual invocation of the processor. Implementations can be sure * {@link #supports(TypeInformation, Object)} has been called before and returned {@literal true}. * * @param object */ - void invokeEnricher(Object object); + Object invokeProcessor(Object object); } /** - * Default implementation of {@link EnricherWrapper} to generically deal with {@link ResourceSupport} types. + * Default implementation of {@link ProcessorWrapper} to generically deal with {@link ResourceSupport} types. * * @author Oliver Gierke */ - private static class DefaultEnricherWrapper implements EnricherWrapper { + private static class DefaultProcessorWrapper implements ProcessorWrapper { - private final ResourceEnricher enricher; + private final ResourceProcessor processor; private final TypeInformation targetType; /** - * Creates a ne {@link DefaultEnricherWrapper} with the given {@link ResourceEnricher}. + * Creates a ne {@link DefaultProcessorWrapper} with the given {@link ResourceProcessor}. * - * @param enricher must not be {@literal null}. + * @param processor must not be {@literal null}. */ - public DefaultEnricherWrapper(ResourceEnricher enricher) { + public DefaultProcessorWrapper(ResourceProcessor processor) { - Assert.notNull(enricher); + Assert.notNull(processor); - this.enricher = enricher; - this.targetType = from(enricher.getClass()).getSuperTypeInformation(ResourceEnricher.class).getComponentType(); + this.processor = processor; + this.targetType = from(processor.getClass()).getSuperTypeInformation(ResourceProcessor.class).getComponentType(); } /* * (non-Javadoc) - * @see org.springframework.data.rest.webmvc.ResourceEnricherHandlerMethodReturnValueHandler.PostProcessorWrapper#supports(org.springframework.data.util.TypeInformation, java.lang.Object) + * @see org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.PostProcessorWrapper#supports(org.springframework.data.util.TypeInformation, java.lang.Object) */ @Override public boolean supports(TypeInformation typeInformation, Object value) { @@ -233,12 +279,12 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM /* * (non-Javadoc) - * @see org.springframework.data.rest.webmvc.ResourceEnricherHandlerMethodReturnValueHandler.PostProcessorWrapper#invokeProcessor(java.lang.Object) + * @see org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.PostProcessorWrapper#invokeProcessor(java.lang.Object) */ @Override @SuppressWarnings("unchecked") - public void invokeEnricher(Object object) { - ((ResourceEnricher) enricher).enrich((ResourceSupport) object); + public Object invokeProcessor(Object object) { + return ((ResourceProcessor) processor).enrich((ResourceSupport) object); } /* @@ -247,11 +293,11 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM */ @Override public int getOrder() { - return CustomOrderAwareComparator.INSTANCE.getOrder(enricher); + return CustomOrderAwareComparator.INSTANCE.getOrder(processor); } /** - * Returns the target type the underlying {@link ResourceEnricher} wants to get invoked for. + * Returns the target type the underlying {@link ResourceProcessor} wants to get invoked for. * * @return the targetType */ @@ -261,25 +307,25 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM } /** - * {@link EnricherWrapper} to deal with {@link ResourceEnricher}s for {@link Resource}s. Will fall back to peeking + * {@link ProcessorWrapper} to deal with {@link ResourceProcessor}s for {@link Resource}s. Will fall back to peeking * into the {@link Resource}'s content for type resolution. * * @author Oliver Gierke */ - private static class ResourceEnricherWrapper extends DefaultEnricherWrapper { + private static class ResourceProcessorWrapper extends DefaultProcessorWrapper { /** - * Creates a new {@link ResourceEnricherWrapper} for the given {@link ResourceEnricher}. + * Creates a new {@link ResourceProcessorWrapper} for the given {@link ResourceProcessor}. * * @param processor must not be {@literal null}. */ - public ResourceEnricherWrapper(ResourceEnricher processor) { + public ResourceProcessorWrapper(ResourceProcessor processor) { super(processor); } /* * (non-Javadoc) - * @see org.springframework.data.rest.webmvc.ResourceEnricherHandlerMethodReturnValueHandler.PostProcessorWrapper#supports(org.springframework.data.util.TypeInformation, java.lang.Object) + * @see org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.PostProcessorWrapper#supports(org.springframework.data.util.TypeInformation, java.lang.Object) */ @Override public boolean supports(TypeInformation typeInformation, Object value) { @@ -317,20 +363,20 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM } /** - * {@link EnricherWrapper} for {@link ResourceEnricher}s targeting {@link Resources}. Will peek into the content of + * {@link ProcessorWrapper} for {@link ResourceProcessor}s targeting {@link Resources}. Will peek into the content of * the {@link Resources} for type matching decisions if needed. * * @author Oliver Gierke */ - private static class ResourcesEnricherWrapper extends DefaultEnricherWrapper { + private static class ResourcesProcessorWrapper extends DefaultProcessorWrapper { /** - * Creates a new {@link ResourcesEnricherWrapper} for the given {@link ResourceEnricher}. + * Creates a new {@link ResourcesProcessorWrapper} for the given {@link ResourceProcessor}. * - * @param enricher must not be {@literal null}. + * @param processor must not be {@literal null}. */ - public ResourcesEnricherWrapper(ResourceEnricher enricher) { - super(enricher); + public ResourcesProcessorWrapper(ResourceProcessor processor) { + super(processor); } /* @@ -374,7 +420,7 @@ public class ResourceEnricherHandlerMethodReturnValueHandler implements HandlerM } TypeInformation resourceTypeInformation = target.getSuperTypeInformation(Resources.class).getComponentType(); - return ResourceEnricherWrapper.isValueTypeMatch((Resource) element, resourceTypeInformation); + return ResourceProcessorWrapper.isValueTypeMatch((Resource) element, resourceTypeInformation); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceEnricherInvokingHandlerAdapter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorInvokingHandlerAdapter.java similarity index 81% rename from spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceEnricherInvokingHandlerAdapter.java rename to spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorInvokingHandlerAdapter.java index f9056f74c..f68f9b178 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceEnricherInvokingHandlerAdapter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceProcessorInvokingHandlerAdapter.java @@ -19,7 +19,7 @@ import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.ResourceEnricher; +import org.springframework.hateoas.ResourceProcessor; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.util.Assert; import org.springframework.web.bind.support.WebBindingInitializer; @@ -30,7 +30,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl /** * Special {@link RequestMappingHandlerAdapter} that tweaks the {@link HandlerMethodReturnValueHandlerComposite} to be - * proxied by a {@link ResourceEnricherHandlerMethodReturnValueHandler} which will invoke the {@link ResourceEnricher}s + * proxied by a {@link ResourceProcessorHandlerMethodReturnValueHandler} which will invoke the {@link ResourceProcessor}s * found in the application context and eventually delegate to the originally configured * {@link HandlerMethodReturnValueHandler}. *

@@ -39,15 +39,15 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl * * @author Oliver Gierke */ -public class ResourceEnricherInvokingHandlerAdapter extends RequestMappingHandlerAdapter { +public class ResourceProcessorInvokingHandlerAdapter extends RequestMappingHandlerAdapter { @Autowired(required = false) - private List> resourcesEnrichers = new ArrayList>(); + private List> resourcesProcessors = new ArrayList>(); /** - * Empty constructor to setup a {@link ResourceEnricherInvokingHandlerAdapter}. + * Empty constructor to setup a {@link ResourceProcessorInvokingHandlerAdapter}. */ - public ResourceEnricherInvokingHandlerAdapter() { + public ResourceProcessorInvokingHandlerAdapter() { } @@ -57,7 +57,7 @@ public class ResourceEnricherInvokingHandlerAdapter extends RequestMappingHandle * * @param original must not be {@literal null}. */ - public ResourceEnricherInvokingHandlerAdapter(RequestMappingHandlerAdapter original) { + public ResourceProcessorInvokingHandlerAdapter(RequestMappingHandlerAdapter original) { Assert.notNull(original); @@ -81,7 +81,7 @@ public class ResourceEnricherInvokingHandlerAdapter extends RequestMappingHandle // Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones List newHandlers = new ArrayList(); - newHandlers.add(new ResourceEnricherHandlerMethodReturnValueHandler(oldHandlers, resourcesEnrichers)); + newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, resourcesProcessors)); // Configure the new handler to be used this.setReturnValueHandlers(newHandlers); diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ResourceEnricherHandlerMethodReturnValueHandlerUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ResourceProcessorHandlerMethodReturnValueHandlerUnitTests.java similarity index 65% rename from spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ResourceEnricherHandlerMethodReturnValueHandlerUnitTests.java rename to spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ResourceProcessorHandlerMethodReturnValueHandlerUnitTests.java index d28046b4f..548ae8d34 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ResourceEnricherHandlerMethodReturnValueHandlerUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ResourceProcessorHandlerMethodReturnValueHandlerUnitTests.java @@ -33,10 +33,9 @@ import org.mockito.Mockito; import org.mockito.internal.matchers.Equals; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.core.MethodParameter; -import org.springframework.data.rest.webmvc.ResourceEnricherHandlerMethodReturnValueHandler; -import org.springframework.hateoas.Link; +import org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler; import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceEnricher; +import org.springframework.hateoas.ResourceProcessor; import org.springframework.hateoas.Resources; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; @@ -46,12 +45,12 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; /** - * Unit tests for {@link ResourceEnricherHandlerMethodReturnValueHandler}. + * Unit tests for {@link ResourceProcessorHandlerMethodReturnValueHandler}. * * @author Oliver Gierke */ @RunWith(MockitoJUnitRunner.class) -public class ResourceEnricherHandlerMethodReturnValueHandlerUnitTests { +public class ResourceProcessorHandlerMethodReturnValueHandlerUnitTests { @Mock HandlerMethodReturnValueHandler delegate; @@ -59,20 +58,14 @@ public class ResourceEnricherHandlerMethodReturnValueHandlerUnitTests { @Mock MethodParameter parameter; - List> resourceEnrichers; + List> resourceProcessors; - Resource source; - Resource result; + Resource source = new Resource("foo"); + Resource result = StringResourceProcessor.RESULT; @Before public void setUp() { - resourceEnrichers = new ArrayList>(); - resetResources(); - } - - private void resetResources() { - source = new Resource("foo"); - result = new Resource("foo", StringResourceEnricher.LINK); + resourceProcessors = new ArrayList>(); } @Test @@ -88,8 +81,8 @@ public class ResourceEnricherHandlerMethodReturnValueHandlerUnitTests { private void assertSupport(boolean value) { when(delegate.supportsReturnType(Mockito.any(MethodParameter.class))).thenReturn(value); - HandlerMethodReturnValueHandler handler = new ResourceEnricherHandlerMethodReturnValueHandler(delegate, - resourceEnrichers); + HandlerMethodReturnValueHandler handler = new ResourceProcessorHandlerMethodReturnValueHandler(delegate, + resourceProcessors); assertThat(handler.supportsReturnType(parameter), is(value)); } @@ -97,81 +90,65 @@ public class ResourceEnricherHandlerMethodReturnValueHandlerUnitTests { @Test public void invokesStringPostProcessorForSimpleStringResource() throws Exception { - resourceEnrichers.add(new StringResourceEnricher()); - resourceEnrichers.add(new LongResourceEnricher()); + resourceProcessors.add(new StringResourceProcessor()); + resourceProcessors.add(new LongResourceProcessor()); HttpEntity> input = new HttpEntity>(source); HttpEntity> output = new HttpEntity>(result); assertProcessorInvokedForMethod("stringResourceEntity", input, output); - resetResources(); - input = new HttpEntity>(source); assertProcessorInvokedForMethod("resourceEntity", input, output); } @Test public void invokesStringPostProcessorForSimpleStringResourceInResponseEntity() throws Exception { - resourceEnrichers.add(new StringResourceEnricher()); - resourceEnrichers.add(new LongResourceEnricher()); + resourceProcessors.add(new StringResourceProcessor()); + resourceProcessors.add(new LongResourceProcessor()); ResponseEntity> input = new ResponseEntity>(source, HttpStatus.OK); ResponseEntity> output = new ResponseEntity>(result, HttpStatus.OK); assertProcessorInvokedForMethod("stringResourceEntity", input, output); - - resetResources(); - input = new ResponseEntity>(source, HttpStatus.OK); assertProcessorInvokedForMethod("resourceEntity", input, output); } @Test public void invokesStringPostProcessorForSimpleStringResources() throws Exception { - resourceEnrichers.add(new StringResourceEnricher()); - resourceEnrichers.add(new LongResourceEnricher()); - resourceEnrichers.add(new StringResourcesEnricher()); + resourceProcessors.add(new StringResourceProcessor()); + resourceProcessors.add(new LongResourceProcessor()); + resourceProcessors.add(new StringResourcesProcessor()); Resources> sources = new Resources>(Collections.singleton(source)); - HttpEntity>> input = new HttpEntity>>(sources); HttpEntity>> output = new HttpEntity>>( - new Resources>(Collections.singleton(result), StringResourcesEnricher.LINK)); + StringResourcesProcessor.RESULT); assertProcessorInvokedForMethod("stringResourceEntity", input, output); - - resetResources(); - input = new HttpEntity>>(new Resources>(Collections.singleton(source))); - output = new HttpEntity>>( - new Resources>(Collections.singleton(result), StringResourcesEnricher.LINK)); assertProcessorInvokedForMethod("resourceEntity", input, output); } @Test public void invokesStringPostProcessorForSpecializedStringResource() throws Exception { - resourceEnrichers.add(new StringResourceEnricher()); - resourceEnrichers.add(new LongResourceEnricher()); + resourceProcessors.add(new StringResourceProcessor()); + resourceProcessors.add(new LongResourceProcessor()); + HttpEntity> stringOutput = new HttpEntity>(result); HttpEntity specializedInput = new HttpEntity(new StringResource("foo")); - HttpEntity stringOutput = new HttpEntity(new StringResource("foo", - StringResourceEnricher.LINK)); assertProcessorInvokedForMethod("stringResourceEntity", specializedInput, stringOutput); - - specializedInput = new HttpEntity(new StringResource("foo")); assertProcessorInvokedForMethod("resourceEntity", specializedInput, stringOutput); - - specializedInput = new HttpEntity(new StringResource("foo")); assertProcessorInvokedForMethod("specializedStringResourceEntity", specializedInput, stringOutput); } @Test public void doesNotInvokeSpecializedStringPostProcessorForSimpleStringResource() throws Exception { - resourceEnrichers.add(new SpecializedStringResourceEnricher()); - resourceEnrichers.add(new LongResourceEnricher()); + resourceProcessors.add(new SpecializedStringResourceProcessor()); + resourceProcessors.add(new LongResourceProcessor()); HttpEntity> input = new HttpEntity>(source); @@ -181,12 +158,11 @@ public class ResourceEnricherHandlerMethodReturnValueHandlerUnitTests { @Test public void invokesSpecializedStringPostProcessor() throws Exception { - resourceEnrichers.add(new SpecializedStringResourceEnricher()); - resourceEnrichers.add(new LongResourceEnricher()); + resourceProcessors.add(new SpecializedStringResourceProcessor()); + resourceProcessors.add(new LongResourceProcessor()); HttpEntity input = new HttpEntity(new StringResource("foo")); - HttpEntity output = new HttpEntity(new StringResource("foo", - SpecializedStringResourceEnricher.LINK)); + HttpEntity output = new HttpEntity(SpecializedStringResourceProcessor.RESULT); assertProcessorInvokedForMethod("specializedStringResourceEntity", input, output); } @@ -194,23 +170,22 @@ public class ResourceEnricherHandlerMethodReturnValueHandlerUnitTests { @Test public void invokesLongPostProcessorForLongResource() throws Exception { - resourceEnrichers.add(new StringResourceEnricher()); - resourceEnrichers.add(new LongResourceEnricher()); + resourceProcessors.add(new StringResourceProcessor()); + resourceProcessors.add(new LongResourceProcessor()); HttpEntity> input = new HttpEntity>(new Resource(50L)); HttpEntity specializedInput = new HttpEntity(new LongResource(50L)); + HttpEntity> output = new HttpEntity>(LongResourceProcessor.RESULT); - assertProcessorInvokedForMethod("resourceEntity", specializedInput, new HttpEntity(new LongResource( - 50L, LongResourceEnricher.LINK))); - assertProcessorInvokedForMethod("numberResourceEntity", input, new HttpEntity>(new Resource( - 50L, LongResourceEnricher.LINK))); + assertProcessorInvokedForMethod("resourceEntity", specializedInput, output); + assertProcessorInvokedForMethod("numberResourceEntity", input, output); } private void assertProcessorInvokedForMethod(String methodName, Object returnValue, Object processedValue) throws Exception { - HandlerMethodReturnValueHandler handler = new ResourceEnricherHandlerMethodReturnValueHandler(delegate, - resourceEnrichers); + HandlerMethodReturnValueHandler handler = new ResourceProcessorHandlerMethodReturnValueHandler(delegate, + resourceProcessors); Method method = Controller.class.getMethod(methodName); MethodParameter returnType = new MethodParameter(method, -1); @@ -292,58 +267,69 @@ public class ResourceEnricherHandlerMethodReturnValueHandlerUnitTests { ResponseEntity> resourcesResponseEntity(); } - + + /** + * {@link ResourceProcessor} to process {@link String}s. + * + * @author Oliver Gierke + */ + static class StringResourceProcessor implements ResourceProcessor> { + + static final Resource RESULT = new Resource("bar"); + + @Override + public Resource enrich(Resource resource) { + return RESULT; + } + } + + static class StringResourcesProcessor implements ResourceProcessor>> { + + static final Resources> RESULT = new Resources>( + Collections.singleton(StringResourceProcessor.RESULT)); + + @Override + public Resources> enrich(Resources> resources) { + return RESULT; + } + } + + /** + * {@link ResourceProcessor} to process {@link Long} values. + * + * @author Oliver Gierke + */ + static class LongResourceProcessor implements ResourceProcessor> { + + static final Resource RESULT = new Resource(10L); + + @Override + public Resource enrich(Resource resource) { + return RESULT; + } + } + static class StringResource extends Resource { - public StringResource(String value, Link... links) { - super(value, links); + public StringResource(String value) { + super(value); } } static class LongResource extends Resource { - public LongResource(Long value, Link... links) { - super(value, links); + public LongResource(Long value) { + super(value); } } - static class StringResourceEnricher implements ResourceEnricher> { + static class SpecializedStringResourceProcessor implements ResourceProcessor { - static final Link LINK = new Link("string-resource"); + static final StringResource RESULT = new StringResource("foobar"); @Override - public void enrich(Resource resource) { - resource.add(LINK); - } - } - - static class StringResourcesEnricher implements ResourceEnricher>> { - - static final Link LINK = new Link("string-resources"); - - @Override - public void enrich(Resources> resource) { - resource.add(LINK); - } - } - - static class LongResourceEnricher implements ResourceEnricher> { - - static final Link LINK = new Link("long-resource"); - - @Override - public void enrich(Resource resource) { - resource.add(LINK); - } - } - - static class SpecializedStringResourceEnricher implements ResourceEnricher { - - static final Link LINK = new Link("specialized-string"); - - @Override - public void enrich(StringResource resource) { - resource.add(LINK); + public StringResource enrich(StringResource resource) { + return RESULT; } } }