Incorporate feedback from @rstoyanchev.
Improve ResourceAssemblerSupport by introducing a dedicated method instead of an overload. Got rid of EntityId in the course. ControllerLinkBuilder now inspects type hierarchy for @RequestMapping annotations instead of the class only. Made links list in ResourceSupport final. Polished variable names and JavaDoc.
This commit is contained in:
@@ -31,7 +31,7 @@ import org.springframework.util.Assert;
|
||||
public class ResourceSupport implements Identifiable<Link> {
|
||||
|
||||
@XmlElement(name = "link", namespace = Link.ATOM_NAMESPACE)
|
||||
private List<Link> links;
|
||||
private final List<Link> links;
|
||||
|
||||
public ResourceSupport() {
|
||||
this.links = new ArrayList<Link>();
|
||||
|
||||
@@ -35,16 +35,16 @@ import org.springframework.web.util.UriTemplate;
|
||||
*/
|
||||
public class ControllerLinkBuilder {
|
||||
|
||||
private final UriComponents builder;
|
||||
private final UriComponents uriComponents;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ControllerLinkBuilder}.
|
||||
*
|
||||
* @param builder must not be {@literal null}.
|
||||
* @param uriComponents must not be {@literal null}.
|
||||
*/
|
||||
private ControllerLinkBuilder(UriComponentsBuilder builder) {
|
||||
Assert.notNull(builder);
|
||||
this.builder = builder.build();
|
||||
this.uriComponents = builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +59,7 @@ public class ControllerLinkBuilder {
|
||||
|
||||
public static ControllerLinkBuilder linkTo(Class<?> controller, Object... parameters) {
|
||||
|
||||
RequestMapping annotation = controller.getAnnotation(RequestMapping.class);
|
||||
RequestMapping annotation = AnnotationUtils.findAnnotation(controller, RequestMapping.class);
|
||||
String[] mapping = annotation == null ? new String[0] : (String[]) AnnotationUtils.getValue(annotation);
|
||||
|
||||
if (mapping.length > 1) {
|
||||
@@ -89,12 +89,12 @@ public class ControllerLinkBuilder {
|
||||
}
|
||||
|
||||
String[] segments = StringUtils.tokenizeToStringArray(object.toString(), "/");
|
||||
return new ControllerLinkBuilder(UriComponentsBuilder.fromUri(builder.toUri()).pathSegment(segments));
|
||||
return new ControllerLinkBuilder(UriComponentsBuilder.fromUri(uriComponents.toUri()).pathSegment(segments));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given {@link AbstractEntity}'s id as sub-resource. Will simply return the current builder if the given
|
||||
* entity is {@literal null}.
|
||||
* Adds the given {@link AbstractEntity}'s id as sub-resource. Will simply return the current uriComponents if the
|
||||
* given entity is {@literal null}.
|
||||
*
|
||||
* @param identifyable
|
||||
* @return
|
||||
@@ -109,12 +109,12 @@ public class ControllerLinkBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URI resulting from the builder.
|
||||
* Returns a URI resulting from the uriComponents.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public URI toUri() {
|
||||
return builder.encode().toUri();
|
||||
return uriComponents.encode().toUri();
|
||||
}
|
||||
|
||||
public Link withRel(String rel) {
|
||||
|
||||
@@ -36,25 +36,6 @@ import org.springframework.util.Assert;
|
||||
public abstract class ResourceAssemblerSupport<T extends Identifiable<?>, D extends ResourceSupport> implements
|
||||
ResourceAssembler<T, D> {
|
||||
|
||||
public static class EntityId {
|
||||
|
||||
private final Object id;
|
||||
|
||||
public EntityId(Object id) {
|
||||
Assert.notNull(id);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static EntityId id(Object object) {
|
||||
return new EntityId(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.id.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private final Class<?> controllerClass;
|
||||
private final Class<D> resourceType;
|
||||
|
||||
@@ -77,11 +58,12 @@ public abstract class ResourceAssemblerSupport<T extends Identifiable<?>, D exte
|
||||
* Converts all given entities into resources.
|
||||
*
|
||||
* @see #toResource(Object)
|
||||
* @param entities
|
||||
* @param entities must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public List<D> toResources(Iterable<? extends T> entities) {
|
||||
|
||||
Assert.notNull(entities);
|
||||
List<D> result = new ArrayList<D>();
|
||||
|
||||
for (T entity : entities) {
|
||||
@@ -102,21 +84,21 @@ public abstract class ResourceAssemblerSupport<T extends Identifiable<?>, D exte
|
||||
}
|
||||
|
||||
protected D createResource(T entity, Object... parameters) {
|
||||
return createResource(entity, EntityId.id(entity.getId()), parameters);
|
||||
return createResourceWithId(entity.getId(), entity, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new resource with a self link to the given id.
|
||||
*
|
||||
* @param entity
|
||||
* @param id
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param id must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected D createResource(T entity, EntityId id) {
|
||||
return createResource(entity, id, new Object[0]);
|
||||
protected D createResourceWithId(Object id, T entity) {
|
||||
return createResourceWithId(id, entity, new Object[0]);
|
||||
}
|
||||
|
||||
protected D createResource(T entity, EntityId id, Object... parameters) {
|
||||
protected D createResourceWithId(Object id, T entity, Object... parameters) {
|
||||
|
||||
Assert.notNull(entity);
|
||||
Assert.notNull(id);
|
||||
@@ -154,4 +136,4 @@ public abstract class ResourceAssemblerSupport<T extends Identifiable<?>, D exte
|
||||
protected D instantiateResource(T entity) {
|
||||
return BeanUtils.instantiateClass(resourceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.hateoas.TestUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ControllerLinkBuilderUnitTest extends TestUtils {
|
||||
@@ -36,7 +35,7 @@ public class ControllerLinkBuilderUnitTest extends TestUtils {
|
||||
@Test
|
||||
public void createsLinkToControllerRoot() {
|
||||
|
||||
Link link = linkTo(PersonController.class).withSelfRel();
|
||||
Link link = linkTo(PersonControllerImpl.class).withSelfRel();
|
||||
assertThat(link.getRel(), is(Link.REL_SELF));
|
||||
assertThat(link.getHref(), Matchers.endsWith("/people"));
|
||||
}
|
||||
@@ -52,7 +51,7 @@ public class ControllerLinkBuilderUnitTest extends TestUtils {
|
||||
@Test
|
||||
public void createsLinkToSubResource() {
|
||||
|
||||
Link link = linkTo(PersonController.class).slash("something").withSelfRel();
|
||||
Link link = linkTo(PersonControllerImpl.class).slash("something").withSelfRel();
|
||||
assertThat(link.getRel(), is(Link.REL_SELF));
|
||||
assertThat(link.getHref(), Matchers.endsWith("/people/something"));
|
||||
}
|
||||
@@ -60,7 +59,7 @@ public class ControllerLinkBuilderUnitTest extends TestUtils {
|
||||
@Test
|
||||
public void createsLinkWithCustomRel() {
|
||||
|
||||
Link link = linkTo(PersonController.class).withRel(Link.REL_NEXT);
|
||||
Link link = linkTo(PersonControllerImpl.class).withRel(Link.REL_NEXT);
|
||||
assertThat(link.getRel(), is(Link.REL_NEXT));
|
||||
assertThat(link.getHref(), Matchers.endsWith("/people"));
|
||||
}
|
||||
@@ -72,7 +71,6 @@ public class ControllerLinkBuilderUnitTest extends TestUtils {
|
||||
|
||||
@Test
|
||||
public void createsLinkToUnmappedController() {
|
||||
|
||||
linkTo(UnmappedController.class);
|
||||
}
|
||||
|
||||
@@ -83,17 +81,17 @@ public class ControllerLinkBuilderUnitTest extends TestUtils {
|
||||
Identifiable<Long> identifyable = mock(Identifiable.class);
|
||||
when(identifyable.getId()).thenReturn(10L);
|
||||
|
||||
Link link = linkTo(PersonController.class).slash(identifyable).withSelfRel();
|
||||
Link link = linkTo(PersonControllerImpl.class).slash(identifyable).withSelfRel();
|
||||
assertThat(link.getHref(), Matchers.endsWith("/people/10"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendingNullIsANoOp() {
|
||||
|
||||
Link link = linkTo(PersonController.class).slash(null).withSelfRel();
|
||||
Link link = linkTo(PersonControllerImpl.class).slash(null).withSelfRel();
|
||||
assertThat(link.getHref(), Matchers.endsWith("/people"));
|
||||
|
||||
link = linkTo(PersonController.class).slash((Object) null).withSelfRel();
|
||||
link = linkTo(PersonControllerImpl.class).slash((Object) null).withSelfRel();
|
||||
assertThat(link.getHref(), Matchers.endsWith("/people"));
|
||||
}
|
||||
|
||||
@@ -108,7 +106,11 @@ public class ControllerLinkBuilderUnitTest extends TestUtils {
|
||||
}
|
||||
|
||||
@RequestMapping("/people")
|
||||
class PersonController {
|
||||
interface PersonController {
|
||||
|
||||
}
|
||||
|
||||
class PersonControllerImpl implements PersonController {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.hateoas.mvc;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
|
||||
import static org.springframework.hateoas.mvc.ResourceAssemblerSupport.EntityId.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -32,6 +31,7 @@ import org.springframework.hateoas.TestUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ResourceAssemblerSupport}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -62,7 +62,7 @@ public class ResourceAssemblerSupportUnitTest extends TestUtils {
|
||||
@Test
|
||||
public void usesAlternateIdIfGivenExplicitly() {
|
||||
|
||||
PersonResource resource = assembler.createResource(person, id(person.alternateId));
|
||||
PersonResource resource = assembler.createResourceWithId(person.alternateId, person);
|
||||
Link selfLink = resource.getId();
|
||||
assertThat(selfLink.getHref(), endsWith("/people/id"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user