diff --git a/src/main/java/org/springframework/hateoas/LinkBuilder.java b/src/main/java/org/springframework/hateoas/LinkBuilder.java new file mode 100644 index 00000000..d854ff9f --- /dev/null +++ b/src/main/java/org/springframework/hateoas/LinkBuilder.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas; + +import java.net.URI; + +/** + * Builder to ease building {@link Link} instances. + * + * @author Ricardo Gladwell + */ +public interface LinkBuilder { + + /** + * Adds the given object's {@link String} representation as sub-resource to the current URI. + * + * @param object + * @return + */ + LinkBuilder slash(Object object); + + /** + * Adds the given {@link Identifiable}'s id as sub-resource. Will simply return the {@link LinkBuilder} as is if the + * given entity is {@literal null}. + * + * @param identifiable + * @return + */ + LinkBuilder slash(Identifiable identifiable); + + /** + * Creates a URI of the link built by the current builder instance. + * + * @return + */ + URI toUri(); + + /** + * Creates the {@link Link} built by the current builder instance with the given rel. + * + * @param rel must not be {@literal null} or empty. + * @return + */ + Link withRel(String rel); + + /** + * Creates the {@link Link} built by the current builder instance with the default self rel. + * + * @see Link#REL_SELF + * @return + */ + Link withSelfRel(); +} diff --git a/src/main/java/org/springframework/hateoas/LinkBuilderFactory.java b/src/main/java/org/springframework/hateoas/LinkBuilderFactory.java new file mode 100644 index 00000000..536f6ab4 --- /dev/null +++ b/src/main/java/org/springframework/hateoas/LinkBuilderFactory.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas; + +/** + * Factory for {@link LinkBuilder} instances. + * + * @author Ricardo Gladwell + */ +public interface LinkBuilderFactory { + + /** + * Creates a new {@link LinkBuilder} with a base of the mapping annotated to the given target clas (controller, + * service, etc.). + * + * @param target must not be {@literal null}. + * @return + */ + LinkBuilder linkTo(Class target); + + /** + * Creates a new {@link LinkBuilder} with a base of the mapping annotated to the given target class (controller, + * service, etc.). The additional parameters are used to fill up potentially available path variables in the class + * scope request mapping. + * + * @param target must not be {@literal null}. + * @param parameters must not be {@literal null}. + * @return + */ + LinkBuilder linkTo(Class target, Object... parameters); +} diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java index 9d4a948e..4d8dd0af 100755 --- a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java @@ -20,6 +20,7 @@ import java.net.URI; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.hateoas.Identifiable; import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkBuilder; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; @@ -33,7 +34,7 @@ import org.springframework.web.util.UriTemplate; * * @author Oliver Gierke */ -public class ControllerLinkBuilder { +public class ControllerLinkBuilder implements LinkBuilder { private final UriComponents uriComponents; @@ -86,11 +87,9 @@ public class ControllerLinkBuilder { return builder.slash(template.expand(parameters)); } - /** - * Adds the given object's {@link String} representation as sub-resource to the current URI. - * - * @param object - * @return + /* + * (non-Javadoc) + * @see org.springframework.hateoas.LinkBuilder#slash(java.lang.Object) */ public ControllerLinkBuilder slash(Object object) { @@ -102,12 +101,9 @@ public class ControllerLinkBuilder { return new ControllerLinkBuilder(UriComponentsBuilder.fromUri(uriComponents.toUri()).pathSegment(segments)); } - /** - * 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 + /* + * (non-Javadoc) + * @see org.springframework.hateoas.LinkBuilder#slash(org.springframework.hateoas.Identifiable) */ public ControllerLinkBuilder slash(Identifiable identifyable) { @@ -118,30 +114,25 @@ public class ControllerLinkBuilder { return slash(identifyable.getId()); } - /** - * Returns a URI resulting from the uriComponents. - * - * @return + /* + * (non-Javadoc) + * @see org.springframework.hateoas.LinkBuilder#toUri() */ public URI toUri() { return uriComponents.encode().toUri(); } - /** - * Creates the {@link Link} built by the current builder instance with the given rel. - * - * @param rel must not be {@literal null} or empty. - * @return + /* + * (non-Javadoc) + * @see org.springframework.hateoas.LinkBuilder#withRel(java.lang.String) */ public Link withRel(String rel) { return new Link(this.toString(), rel); } - /** - * Creates the {@link Link} built by the current builder instance with the default self rel. - * - * @see Link#REL_SELF - * @return + /* + * (non-Javadoc) + * @see org.springframework.hateoas.LinkBuilder#withSelfRel() */ public Link withSelfRel() { return new Link(this.toString()); diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java new file mode 100644 index 00000000..720862a3 --- /dev/null +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.mvc; + +import org.springframework.hateoas.LinkBuilderFactory; + +/** + * Factory for {@link ControllerLinkBuilder} instances. + * + * @author Ricardo Gladwell + * @author Oliver Gierke + */ +public class ControllerLinkBuilderFactory implements LinkBuilderFactory { + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.LinkBuilderFactory#linkTo(java.lang.Class) + */ + @Override + public ControllerLinkBuilder linkTo(Class controller) { + return ControllerLinkBuilder.linkTo(controller); + } + + /* + * (non-Javadoc) + * @see org.springframework.hateoas.LinkBuilderFactory#linkTo(java.lang.Class, java.lang.Object[]) + */ + @Override + public ControllerLinkBuilder linkTo(Class controller, Object... parameters) { + return ControllerLinkBuilder.linkTo(controller, parameters); + } +} diff --git a/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactoryUnitTest.java b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactoryUnitTest.java new file mode 100644 index 00000000..4a939438 --- /dev/null +++ b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactoryUnitTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.hateoas.mvc; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; +import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkBuilderFactory; +import org.springframework.hateoas.TestUtils; +import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.PersonControllerImpl; +import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.PersonsAddressesController; + +/** + * Unit tests for {@link ControllerLinkBuilderFactory}. + * + * @author Ricardo Gladwell + * @author Oliver Gierke + */ +public class ControllerLinkBuilderFactoryUnitTest extends TestUtils { + + LinkBuilderFactory factory = new ControllerLinkBuilderFactory(); + + @Test + public void createsLinkToControllerRoot() { + + Link link = factory.linkTo(PersonControllerImpl.class).withSelfRel(); + + assertThat(link.getRel(), is(Link.REL_SELF)); + assertThat(link.getHref(), endsWith("/people")); + } + + @Test + public void createsLinkToParameterizedControllerRoot() { + + Link link = factory.linkTo(PersonsAddressesController.class, 15).withSelfRel(); + + assertThat(link.getRel(), is(Link.REL_SELF)); + assertThat(link.getHref(), endsWith("/people/15/addresses")); + } +}