#843 - Introduced EntityLinks.link(To|For)ItemResource(Object, Function).
The introduced methods allow clients to pass an identifier extractor function. Also introduced a new (Extended)TypedEntityLinks that exposes the same functionality as EntityLinks but with a shared identifier extractor function so that clients don't have to provide it for each method invocation. Prepares the fix for #842.
This commit is contained in:
@@ -15,17 +15,21 @@
|
||||
*/
|
||||
package org.springframework.hateoas.server;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.hateoas.IanaLinkRelations;
|
||||
import org.springframework.hateoas.Identifiable;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.server.TypedEntityLinks.ExtendedTypedEntityLinks;
|
||||
import org.springframework.plugin.core.Plugin;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Accessor to links pointing to controllers backing an entity type. The {@link IllegalArgumentException} potentially
|
||||
* thrown by the declared methods will only appear if the {@link #supports(Class)} method has returned {@literal false}
|
||||
* and the method has been invoked anyway, i.e. if {@link #supports(Class)} returns {@literal true} it's safe to invoke
|
||||
* the interface methods an the exception will never be thrown.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface EntityLinks extends Plugin<Class<?>> {
|
||||
@@ -33,7 +37,7 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
/**
|
||||
* Returns a {@link LinkBuilder} able to create links to the controller managing the given entity type. Expects a
|
||||
* controller being mapped to a fully expanded URI template (i.e. not path variables being used).
|
||||
*
|
||||
*
|
||||
* @param type the entity type to point to, must not be {@literal null}.
|
||||
* @return the {@link LinkBuilder} pointing to the collection resource. Will never be {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
@@ -43,7 +47,7 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
/**
|
||||
* Returns a {@link LinkBuilder} able to create links to the controller managing the given entity type, unfolding the
|
||||
* given parameters into the URI template the backing controller is mapped to.
|
||||
*
|
||||
*
|
||||
* @param type the entity type to point to, must not be {@literal null}.
|
||||
* @return the {@link LinkBuilder} pointing to the collection resource.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
@@ -52,19 +56,37 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
|
||||
/**
|
||||
* Returns a {@link LinkBuilder} able to create links to the controller managing the given entity type and id.
|
||||
* Implementations will know about the URI structure being used to expose single-resource URIs.
|
||||
*
|
||||
* Implementations will know about the URI structure being used to expose item-resource URIs.
|
||||
*
|
||||
* @param type the entity type to point to, must not be {@literal null}.
|
||||
* @param id the id of the object of the handed type, {@link Identifiable}s will be unwrapped.
|
||||
* @return the {@link LinkBuilder} pointing to the single resource identified by the given type and id. Will never be
|
||||
* @return the {@link LinkBuilder} pointing to the item resource identified by the given type and id. Will never be
|
||||
* {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
LinkBuilder linkForItemResource(Class<?> type, Object id);
|
||||
|
||||
/**
|
||||
* Returns a {@link LinkBuilder} able to create links to the controller managing the given entity type and identifier
|
||||
* extractor. Implementations will know about the URI structure being used to expose item-resource URIs.
|
||||
*
|
||||
* @param type the entity to point to, must not be {@literal null}.
|
||||
* @param identifierExtractor an extractor function to determine the id of the given entity, must not be
|
||||
* {@literal null}.
|
||||
* @return the {@link LinkBuilder} pointing to the item resource identified by the given entity. Will never be
|
||||
* {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
default <T> LinkBuilder linkForItemResource(T entity, Function<T, Object> identifierExtractor) {
|
||||
|
||||
Assert.notNull(identifierExtractor, "Identifier extractor must not be null!");
|
||||
|
||||
return linkForItemResource(entity.getClass(), identifierExtractor.apply(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link LinkBuilder} able to create links to the controller managing the given entity.
|
||||
*
|
||||
*
|
||||
* @see #linkForItemResource(Class, Object)
|
||||
* @param entity the entity type to point to, must not be {@literal null}.
|
||||
* @return the {@link LinkBuilder} pointing the given entity. Will never be {@literal null}.
|
||||
@@ -75,7 +97,7 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
/**
|
||||
* Creates a {@link Link} pointing to the collection resource of the given type. The relation type of the link will be
|
||||
* determined by the implementation class and should be defaulted to {@link IanaLinkRelations#SELF}.
|
||||
*
|
||||
*
|
||||
* @param type the entity type to point to, must not be {@literal null}.
|
||||
* @return the {@link Link} pointing to the collection resource exposed for the given entity. Will never be
|
||||
* {@literal null}.
|
||||
@@ -84,9 +106,9 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
Link linkToCollectionResource(Class<?> type);
|
||||
|
||||
/**
|
||||
* Creates a {@link Link} pointing to single resource backing the given entity type and id. The relation type of the
|
||||
* Creates a {@link Link} pointing to item resource backing the given entity type and id. The relation type of the
|
||||
* link will be determined by the implementation class and should be defaulted to {@link IanaLinkRelations#SELF}.
|
||||
*
|
||||
*
|
||||
* @param type the entity type to point to, must not be {@literal null}.
|
||||
* @param id the identifier of the entity of the given type
|
||||
* @return the {@link Link} pointing to the resource exposed for the entity with the given type and id. Will never be
|
||||
@@ -96,12 +118,49 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
Link linkToItemResource(Class<?> type, Object id);
|
||||
|
||||
/**
|
||||
* Creates a {@link Link} pointing to single resource backing the given entity. The relation type of the link will be
|
||||
* Creates a {@link Link} pointing to item resource backing the given entity and identifier extractor. The relation
|
||||
* type of the link will be determined by the implementation class and should be defaulted to
|
||||
* {@link IanaLinkRelations#SELF}.
|
||||
*
|
||||
* @param type the entity to point to, must not be {@literal null}.
|
||||
* @param identifierExtractor an extractor function to determine the id of the given entity.
|
||||
* @return the {@link Link} pointing to the resource exposed for the given entity. Will never be {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
default <T> Link linkToItemResource(T entity, Function<T, Object> identifierExtractor) {
|
||||
return linkToItemResource(entity.getClass(), identifierExtractor.apply(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Link} pointing to item resource backing the given entity. The relation type of the link will be
|
||||
* determined by the implementation class and should be defaulted to {@link IanaLinkRelations#SELF}.
|
||||
*
|
||||
*
|
||||
* @param entity the entity type to point to, must not be {@literal null}.
|
||||
* @return the {@link Link} pointing to the resource exposed for the given entity. Will never be {@literal null}.
|
||||
* @throws IllegalArgumentException in case the type of the given entity is unknown the entity links infrastructure.
|
||||
*/
|
||||
Link linkToItemResource(Identifiable<?> entity);
|
||||
|
||||
/**
|
||||
* Creates a {@link TypedEntityLinks} instance using the given identifier extractor function.
|
||||
*
|
||||
* @param <T> the type of entity to be handled.
|
||||
* @param extractor the extractor to use to derive an identifier from the given entity.
|
||||
* @return
|
||||
*/
|
||||
default <T> TypedEntityLinks<T> forType(Function<T, ? extends Object> extractor) {
|
||||
return new TypedEntityLinks<>(extractor, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link TypedEntityLinks} instance using the given type and identifier extractor function.
|
||||
*
|
||||
* @param <T> the type of entity to be handled.
|
||||
* @param type the type of entity.
|
||||
* @param extractor the extractor to use to derive an identifier from the given entity.
|
||||
* @return
|
||||
*/
|
||||
default <T> ExtendedTypedEntityLinks<T> forType(Class<T> type, Function<T, Object> extractor) {
|
||||
return new ExtendedTypedEntityLinks<>(extractor, this, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2019 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.server;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.hateoas.IanaLinkRelations;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Entity links API to create {@link Link}s and {@link LinkBuilder} instances based on an identifier function.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @see EntityLinks#forType(Function)
|
||||
* @see EntityLinks#forType(Class, Function)
|
||||
*/
|
||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
public class TypedEntityLinks<T> {
|
||||
|
||||
private final @NonNull Function<T, ? extends Object> identifierExtractor;
|
||||
private final @NonNull EntityLinks entityLinks;
|
||||
|
||||
/**
|
||||
* Returns a {@link LinkBuilder} able to create links to the controller managing the given entity. Implementations
|
||||
* will know about the URI structure being used to expose item-resource URIs.
|
||||
*
|
||||
* @param type the entity to point to, must not be {@literal null}.
|
||||
* @return the {@link LinkBuilder} pointing to the item resource identified by the given entity. Will never be
|
||||
* {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
public LinkBuilder linkForItemResource(T entity) {
|
||||
return entityLinks.linkForItemResource(entity.getClass(), identifierExtractor.apply(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Link} pointing to item resource backing the given entity. The relation type of the link will be
|
||||
* determined by the implementation class and should be defaulted to {@link IanaLinkRelations#SELF}.
|
||||
*
|
||||
* @param type the entity to point to, must not be {@literal null}.
|
||||
* @return the {@link Link} pointing to the resource exposed for the given entity. Will never be {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
public Link linkToItemResource(T entity) {
|
||||
return entityLinks.linkToItemResource(entity.getClass(), identifierExtractor.apply(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension of {@link TypedEntityLinks} that exposes the ability to create links to collection resources as well.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
public static class ExtendedTypedEntityLinks<T> extends TypedEntityLinks<T> {
|
||||
|
||||
private final Class<T> type;
|
||||
private final EntityLinks delegate;
|
||||
|
||||
ExtendedTypedEntityLinks(Function<T, ? extends Object> identifierExtractor, EntityLinks delegate, Class<T> type) {
|
||||
|
||||
super(identifierExtractor, delegate);
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
|
||||
this.type = type;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Link} pointing to the collection resource of the configured type. The relation type of the link
|
||||
* will be determined by the implementation class and should be defaulted to {@link IanaLinkRelations#SELF}.
|
||||
*
|
||||
* @param type the entity type to point to, must not be {@literal null}.
|
||||
* @return the {@link Link} pointing to the collection resource exposed for the configured entity type. Will never
|
||||
* be {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
public Link linkToCollectionResource() {
|
||||
return delegate.linkToCollectionResource(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user