From 673f82d38878fab295431ef51903ccee5c6986d4 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 5 Jun 2014 16:19:10 +0200 Subject: [PATCH] #192 - Added linkTo(Class, Method, Object...) to MethodLinkBuilderFactory. The newly introduced method is needed to make sure the correct mappings are looked up if the method given is actually not declared on the class the method shall eventually be invoked on. This is basically allowing to try to build links, similar to the dummy invocation mechanism but effectively avoiding the overhead of creating such invocation manually (as it would usually require reflection to be used). --- .../hateoas/MethodLinkBuilderFactory.java | 17 ++++++++++++++--- .../hateoas/mvc/ControllerLinkBuilder.java | 16 +++++++++++++++- .../mvc/ControllerLinkBuilderFactory.java | 9 +++++++++ .../mvc/ControllerLinkBuilderUnitTest.java | 13 +++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/springframework/hateoas/MethodLinkBuilderFactory.java b/src/main/java/org/springframework/hateoas/MethodLinkBuilderFactory.java index bb6a689d..1f990b98 100644 --- a/src/main/java/org/springframework/hateoas/MethodLinkBuilderFactory.java +++ b/src/main/java/org/springframework/hateoas/MethodLinkBuilderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,10 +38,21 @@ public interface MethodLinkBuilderFactory extends LinkBui */ T linkTo(Method method, Object... parameters); + /** + * Returns a {@link LinkBuilder} pointing to the URI mapped to the given {@link Method} assuming it was invoked on an + * object of the given type. + * + * @param type must not be {@literal null}. + * @param method must not be {@literal null}. + * @param parameters + * @return + */ + T linkTo(Class type, Method method, Object... parameters); + /** * Returns a {@link LinkBuilder} pointing to the URI mapped to the method the result is handed into this method. Use - * {@link DummyInvocationUtils#methodOn(Class, Object...)} to obtain a dummy instance of a controller to record a dummy - * method invocation on. See {@link ControllerLinkBuilder#linkTo(Object)} for an example. + * {@link DummyInvocationUtils#methodOn(Class, Object...)} to obtain a dummy instance of a controller to record a + * dummy method invocation on. See {@link ControllerLinkBuilder#linkTo(Object)} for an example. * * @see ControllerLinkBuilder#linkTo(Object) * @param methodInvocationResult must not be {@literal null}. diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java index d36f3f4d..51688956 100755 --- a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java @@ -88,10 +88,24 @@ public class ControllerLinkBuilder extends LinkBuilderSupport, Method, Object...) + */ + public static ControllerLinkBuilder linkTo(Class controller, Method method, Object... parameters) { + + Assert.notNull(controller, "Controller type must not be null!"); + Assert.notNull(method, "Method must not be null!"); + + UriTemplate template = new UriTemplate(DISCOVERER.getMapping(controller, method)); URI uri = template.expand(parameters); + return new ControllerLinkBuilder(getBuilder()).slash(uri); } diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java index 2759df6e..be13d85f 100644 --- a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java @@ -90,6 +90,15 @@ public class ControllerLinkBuilderFactory implements MethodLinkBuilderFactory controller, Method method, Object... parameters) { + return ControllerLinkBuilder.linkTo(controller, method, parameters); + } + /* * (non-Javadoc) * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(java.lang.Object) diff --git a/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java index db525d42..0e180a6e 100644 --- a/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java @@ -19,6 +19,7 @@ import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; @@ -365,6 +366,18 @@ public class ControllerLinkBuilderUnitTest extends TestUtils { assertThat(link.getHref(), endsWith("/root")); } + /** + * @see #192 + */ + @Test + public void usesRootMappingOfTargetClassForMethodsOfParen() throws Exception { + + Method method = ParentControllerWithoutRootMapping.class.getMethod("someEmptyMappedMethod"); + + Link link = linkTo(ChildControllerWithRootMapping.class, method).withSelfRel(); + assertThat(link.getHref(), endsWith("/root")); + } + private static UriComponents toComponents(Link link) { return UriComponentsBuilder.fromUriString(link.getHref()).build(); }