#833 - Changed ResourceSupport class name hierarchy.
This commit is contained in:
@@ -60,17 +60,17 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
* {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
LinkBuilder linkForSingleResource(Class<?> type, Object id);
|
||||
LinkBuilder linkForItemResource(Class<?> type, Object id);
|
||||
|
||||
/**
|
||||
* Returns a {@link LinkBuilder} able to create links to the controller managing the given entity.
|
||||
*
|
||||
* @see #linkForSingleResource(Class, Object)
|
||||
* @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}.
|
||||
* @throws IllegalArgumentException in case the type of the given entity is unknown the entity links infrastructure.
|
||||
*/
|
||||
LinkBuilder linkForSingleResource(Identifiable<?> entity);
|
||||
LinkBuilder linkForItemResource(Identifiable<?> entity);
|
||||
|
||||
/**
|
||||
* Creates a {@link Link} pointing to the collection resource of the given type. The relation type of the link will be
|
||||
@@ -93,7 +93,7 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
* {@literal null}.
|
||||
* @throws IllegalArgumentException in case the given type is unknown the entity links infrastructure.
|
||||
*/
|
||||
Link linkToSingleResource(Class<?> type, Object id);
|
||||
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
|
||||
@@ -103,5 +103,5 @@ public interface EntityLinks extends Plugin<Class<?>> {
|
||||
* @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 linkToSingleResource(Identifiable<?> entity);
|
||||
Link linkToItemResource(Identifiable<?> entity);
|
||||
}
|
||||
|
||||
@@ -15,41 +15,39 @@
|
||||
*/
|
||||
package org.springframework.hateoas.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
|
||||
/**
|
||||
* Interface for components that convert a domain type into a {@link ResourceSupport}.
|
||||
* Interface for components that convert a domain type into a {@link RepresentationModel}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
public interface ResourceAssembler<T, D extends ResourceSupport> {
|
||||
public interface RepresentationModelAssembler<T, D extends RepresentationModel<?>> {
|
||||
|
||||
/**
|
||||
* Converts the given entity into a {@code D}, which extends {@link ResourceSupport}.
|
||||
* Converts the given entity into a {@code D}, which extends {@link RepresentationModel}.
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
D toResource(T entity);
|
||||
D toModel(T entity);
|
||||
|
||||
/**
|
||||
* Converts an {@link Iterable} or {@code T}s into an {@link Iterable} of {@link ResourceSupport} and wraps them in a
|
||||
* {@link Resources} instance.
|
||||
* Converts an {@link Iterable} or {@code T}s into an {@link Iterable} of {@link RepresentationModel} and wraps them
|
||||
* in a {@link CollectionModel} instance.
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
* @return {@link Resources} containing {@code D}.
|
||||
* @return {@link CollectionModel} containing {@code D}.
|
||||
*/
|
||||
default Resources<D> toResources(Iterable<? extends T> entities) {
|
||||
default CollectionModel<D> toCollectionModel(Iterable<? extends T> entities) {
|
||||
|
||||
List<D> resources = new ArrayList<>();
|
||||
for (T entity : entities) {
|
||||
resources.add(toResource(entity));
|
||||
}
|
||||
return new Resources<>(resources);
|
||||
return StreamSupport.stream(entities.spliterator(), false) //
|
||||
.map(this::toModel) //
|
||||
.collect(Collectors.collectingAndThen(Collectors.toList(), CollectionModel::new));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -15,23 +15,23 @@
|
||||
*/
|
||||
package org.springframework.hateoas.server;
|
||||
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
|
||||
/**
|
||||
* SPI interface to allow components to process the {@link ResourceSupport} instances returned from Spring MVC
|
||||
* SPI interface to allow components to process the {@link RepresentationModel} instances returned from Spring MVC
|
||||
* controllers.
|
||||
*
|
||||
* @see Resource
|
||||
* @see Resources
|
||||
*
|
||||
* @see EntityModel
|
||||
* @see CollectionModel
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface ResourceProcessor<T extends ResourceSupport> {
|
||||
public interface RepresentationModelProcessor<T extends RepresentationModel<?>> {
|
||||
|
||||
/**
|
||||
* Processes the given resource, add links, alter the domain data etc.
|
||||
*
|
||||
* Processes the given representation model, add links, alter the domain data etc.
|
||||
*
|
||||
* @param resource
|
||||
* @return the processed resource
|
||||
*/
|
||||
@@ -18,65 +18,68 @@ package org.springframework.hateoas.server;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link ResourceAssembler} based purely on the domain type, using {@code Resource<T>} as the enclosing
|
||||
* "resource" type.
|
||||
* A {@link RepresentationModelAssembler} based purely on the domain type, using {@code EntityRepresentationModel<T>} as
|
||||
* the enclosing representation model type.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface SimpleResourceAssembler<T> extends ResourceAssembler<T, Resource<T>> {
|
||||
public interface SimpleRepresentationModelAssembler<T>
|
||||
extends RepresentationModelAssembler<T, EntityModel<T>> {
|
||||
|
||||
/**
|
||||
* Converts the given entity into a {@link Resource}.
|
||||
* Converts the given entity into a {@link EntityModel}.
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
default Resource<T> toResource(T entity) {
|
||||
|
||||
Resource<T> resource = new Resource<>(entity);
|
||||
default EntityModel<T> toModel(T entity) {
|
||||
|
||||
EntityModel<T> resource = new EntityModel<>(entity);
|
||||
addLinks(resource);
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define links to add to every individual {@link Resource}.
|
||||
* Define links to add to every individual {@link EntityModel}.
|
||||
*
|
||||
* @param resource
|
||||
*/
|
||||
void addLinks(Resource<T> resource);
|
||||
void addLinks(EntityModel<T> resource);
|
||||
|
||||
/**
|
||||
* Converts all given entities into resources and wraps the collection as a resource as well.
|
||||
*
|
||||
* @see #toResource(Object)
|
||||
* @see #toModel(Object)
|
||||
* @param entities must not be {@literal null}.
|
||||
* @return {@link Resources} containing {@link Resource} of {@code T}.
|
||||
* @return {@link CollectionModel} containing {@link EntityModel} of {@code T}.
|
||||
*/
|
||||
@Override
|
||||
default Resources<Resource<T>> toResources(Iterable<? extends T> entities) {
|
||||
default CollectionModel<EntityModel<T>> toCollectionModel(
|
||||
Iterable<? extends T> entities) {
|
||||
|
||||
Assert.notNull(entities, "entities must not be null!");
|
||||
List<Resource<T>> resourceList = new ArrayList<>();
|
||||
List<EntityModel<T>> resourceList = new ArrayList<>();
|
||||
|
||||
for (T entity : entities) {
|
||||
resourceList.add(toResource(entity));
|
||||
resourceList.add(toModel(entity));
|
||||
}
|
||||
|
||||
Resources<Resource<T>> resources = new Resources<>(resourceList);
|
||||
CollectionModel<EntityModel<T>> resources = new CollectionModel<>(
|
||||
resourceList);
|
||||
addLinks(resources);
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define links to add to the {@link Resources} collection.
|
||||
* Define links to add to the {@link CollectionModel} collection.
|
||||
*
|
||||
* @param resources
|
||||
*/
|
||||
void addLinks(Resources<Resource<T>> resources);
|
||||
void addLinks(CollectionModel<EntityModel<T>> resources);
|
||||
}
|
||||
@@ -34,9 +34,9 @@ public abstract class AbstractEntityLinks implements EntityLinks {
|
||||
* @see org.springframework.hateoas.EntityLinks#getLinkToSingleResource(org.springframework.hateoas.Identifiable)
|
||||
*/
|
||||
@Override
|
||||
public Link linkToSingleResource(Identifiable<?> entity) {
|
||||
public Link linkToItemResource(Identifiable<?> entity) {
|
||||
Assert.notNull(entity, "Entity must not be null!");
|
||||
return linkToSingleResource(entity.getClass(), entity.getId());
|
||||
return linkToItemResource(entity.getClass(), entity.getId());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -44,7 +44,7 @@ public abstract class AbstractEntityLinks implements EntityLinks {
|
||||
* @see org.springframework.hateoas.EntityLinks#linkForSingleResource(java.lang.Class, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public LinkBuilder linkForSingleResource(Class<?> type, Object id) {
|
||||
public LinkBuilder linkForItemResource(Class<?> type, Object id) {
|
||||
return linkFor(type).slash(id);
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ public abstract class AbstractEntityLinks implements EntityLinks {
|
||||
* @see org.springframework.hateoas.EntityLinks#linkForSingleResource(org.springframework.hateoas.Identifiable)
|
||||
*/
|
||||
@Override
|
||||
public LinkBuilder linkForSingleResource(Identifiable<?> entity) {
|
||||
public LinkBuilder linkForItemResource(Identifiable<?> entity) {
|
||||
Assert.notNull(entity, "Entity must not be null!");
|
||||
return linkForSingleResource(entity.getClass(), entity.getId());
|
||||
return linkForItemResource(entity.getClass(), entity.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public class ControllerEntityLinks extends AbstractEntityLinks {
|
||||
* @see org.springframework.hateoas.EntityLinks#getLinkToSingleResource(java.lang.Class, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Link linkToSingleResource(Class<?> entity, Object id) {
|
||||
public Link linkToItemResource(Class<?> entity, Object id) {
|
||||
return linkFor(entity).slash(id).withSelfRel();
|
||||
}
|
||||
|
||||
|
||||
@@ -74,8 +74,8 @@ public class DelegatingEntityLinks extends AbstractEntityLinks {
|
||||
* @see org.springframework.hateoas.EntityLinks#getLinkToSingleResource(java.lang.Class, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Link linkToSingleResource(Class<?> type, Object id) {
|
||||
return getPluginFor(type).linkToSingleResource(type, id);
|
||||
public Link linkToItemResource(Class<?> type, Object id) {
|
||||
return getPluginFor(type).linkToItemResource(type, id);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,10 +18,10 @@ package org.springframework.hateoas.server.core;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.hateoas.LinkRelation;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
|
||||
/**
|
||||
* A wrapper to handle values to be embedded into a {@link Resource}.
|
||||
* A wrapper to handle values to be embedded into a {@link EntityModel}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.Optional;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.hateoas.LinkRelation;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -142,7 +142,7 @@ public class EmbeddedWrappers {
|
||||
return null;
|
||||
}
|
||||
|
||||
peek = peek instanceof Resource ? ((Resource<Object>) peek).getContent() : peek;
|
||||
peek = peek instanceof EntityModel ? ((EntityModel<Object>) peek).getContent() : peek;
|
||||
|
||||
return AopUtils.getTargetClass(peek);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ package org.springframework.hateoas.server.core;
|
||||
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Links;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.server.ResourceProcessor;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.server.RepresentationModelProcessor;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -26,15 +26,15 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Special {@link ResponseEntity} that exposes {@link Link} instances in the contained {@link ResourceSupport} as link
|
||||
* headers instead of in the body. Note, that this class is not intended to be used directly from user code but by
|
||||
* Special {@link ResponseEntity} that exposes {@link Link} instances in the contained {@link RepresentationModel} as
|
||||
* link headers instead of in the body. Note, that this class is not intended to be used directly from user code but by
|
||||
* support code that will transparently invoke the header exposure. If you use this class from a controller directly,
|
||||
* the {@link Link}s will not be present in the {@link ResourceSupport} instance anymore when {@link ResourceProcessor}s
|
||||
* kick in.
|
||||
* the {@link Link}s will not be present in the {@link RepresentationModel} instance anymore when
|
||||
* {@link RepresentationModelProcessor}s kick in.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class HeaderLinksResponseEntity<T extends ResourceSupport> extends ResponseEntity<T> {
|
||||
public class HeaderLinksResponseEntity<T extends RepresentationModel<?>> extends ResponseEntity<T> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link HeaderLinksResponseEntity} from the given {@link ResponseEntity}.
|
||||
@@ -64,7 +64,7 @@ public class HeaderLinksResponseEntity<T extends ResourceSupport> extends Respon
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static <S extends ResourceSupport> HeaderLinksResponseEntity<S> wrap(HttpEntity<S> entity) {
|
||||
public static <S extends RepresentationModel<?>> HeaderLinksResponseEntity<S> wrap(HttpEntity<S> entity) {
|
||||
|
||||
Assert.notNull(entity, "Given HttpEntity must not be null!");
|
||||
|
||||
@@ -76,13 +76,13 @@ public class HeaderLinksResponseEntity<T extends ResourceSupport> extends Respon
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given {@link ResourceSupport} into a {@link HeaderLinksResponseEntity}. Will default the status code to
|
||||
* {@link HttpStatus#OK}.
|
||||
* Wraps the given {@link RepresentationModel} into a {@link HeaderLinksResponseEntity}. Will default the status code
|
||||
* to {@link HttpStatus#OK}.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static <S extends ResourceSupport> HeaderLinksResponseEntity<S> wrap(S entity) {
|
||||
public static <S extends RepresentationModel<?>> HeaderLinksResponseEntity<S> wrap(S entity) {
|
||||
|
||||
Assert.notNull(entity, "ResourceSupport must not be null!");
|
||||
|
||||
@@ -90,13 +90,13 @@ public class HeaderLinksResponseEntity<T extends ResourceSupport> extends Respon
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Link}s contained in the {@link ResourceSupport} of the given {@link ResponseEntity} as
|
||||
* Returns the {@link Link}s contained in the {@link RepresentationModel} of the given {@link ResponseEntity} as
|
||||
* {@link HttpHeaders}.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static <T extends ResourceSupport> HttpHeaders getHeadersWithLinks(ResponseEntity<T> entity) {
|
||||
private static <T extends RepresentationModel<?>> HttpHeaders getHeadersWithLinks(ResponseEntity<T> entity) {
|
||||
|
||||
Links links = entity.getBody().getLinks();
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
|
||||
/**
|
||||
* Annotation to configure the relation to be used when embedding objects in HAL representations of {@link Resource}s
|
||||
* and {@link Resources}.
|
||||
* Annotation to configure the relation to be used when embedding objects in HAL representations of {@link EntityModel}s
|
||||
* and {@link CollectionModel}.
|
||||
*
|
||||
* @author Alexander Baetz
|
||||
* @author Oliver Gierke
|
||||
|
||||
@@ -20,28 +20,28 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.hateoas.Identifiable;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.server.ResourceAssembler;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.server.RepresentationModelAssembler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class to implement {@link ResourceAssembler}s. Will automate {@link ResourceSupport} instance creation and make
|
||||
* sure a self-link is always added.
|
||||
* Base class to implement {@link RepresentationModelAssembler}s. Will automate {@link RepresentationModel} instance
|
||||
* creation and make sure a self-link is always added.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class IdentifiableResourceAssemblerSupport<T extends Identifiable<?>, D extends ResourceSupport>
|
||||
extends ResourceAssemblerSupport<T, D> {
|
||||
public abstract class IdentifiableRepresentationModelAssemblerSupport<T extends Identifiable<?>, D extends RepresentationModel<D>>
|
||||
extends RepresentationModelAssemblerSupport<T, D> {
|
||||
|
||||
private final Class<?> controllerClass;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ResourceAssemblerSupport} using the given controller class and resource type.
|
||||
* Creates a new {@link RepresentationModelAssemblerSupport} using the given controller class and resource type.
|
||||
*
|
||||
* @param controllerClass must not be {@literal null}.
|
||||
* @param resourceType must not be {@literal null}.
|
||||
*/
|
||||
public IdentifiableResourceAssemblerSupport(Class<?> controllerClass, Class<D> resourceType) {
|
||||
public IdentifiableRepresentationModelAssemblerSupport(Class<?> controllerClass, Class<D> resourceType) {
|
||||
|
||||
super(controllerClass, resourceType);
|
||||
this.controllerClass = controllerClass;
|
||||
@@ -53,21 +53,21 @@ public abstract class IdentifiableResourceAssemblerSupport<T extends Identifiabl
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected D createResource(T entity) {
|
||||
return createResource(entity, new Object[0]);
|
||||
protected D createModel(T entity) {
|
||||
return createModel(entity, new Object[0]);
|
||||
}
|
||||
|
||||
protected D createResource(T entity, Object... parameters) {
|
||||
return createResourceWithId(entity.getId(), entity, parameters);
|
||||
protected D createModel(T entity, Object... parameters) {
|
||||
return createModelWithId(entity.getId(), entity, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected D createResourceWithId(Object id, T entity, Object... parameters) {
|
||||
protected D createModelWithId(Object id, T entity, Object... parameters) {
|
||||
|
||||
Assert.notNull(entity, "Entity must not be null!");
|
||||
Assert.notNull(id, "Id must not be null!");
|
||||
|
||||
D instance = instantiateResource(entity);
|
||||
D instance = instantiateModel(entity);
|
||||
instance.add(linkTo(controllerClass, unwrapIdentifyables(parameters)).slash(id).withSelfRel());
|
||||
return instance;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
@@ -22,30 +22,31 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.server.ResourceAssembler;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.server.RepresentationModelAssembler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class to implement {@link ResourceAssembler}s. Will automate {@link ResourceSupport} instance creation and make
|
||||
* sure a self-link is always added.
|
||||
* Base class to implement {@link RepresentationModelAssembler}s. Will automate {@link RepresentationModel} instance
|
||||
* creation and make sure a self-link is always added.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
public abstract class ResourceAssemblerSupport<T, D extends ResourceSupport> implements ResourceAssembler<T, D> {
|
||||
public abstract class RepresentationModelAssemblerSupport<T, D extends RepresentationModel<D>>
|
||||
implements RepresentationModelAssembler<T, D> {
|
||||
|
||||
private final Class<?> controllerClass;
|
||||
private final Class<D> resourceType;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ResourceAssemblerSupport} using the given controller class and resource type.
|
||||
* Creates a new {@link RepresentationModelAssemblerSupport} using the given controller class and resource type.
|
||||
*
|
||||
* @param controllerClass must not be {@literal null}.
|
||||
* @param resourceType must not be {@literal null}.
|
||||
*/
|
||||
public ResourceAssemblerSupport(Class<?> controllerClass, Class<D> resourceType) {
|
||||
public RepresentationModelAssemblerSupport(Class<?> controllerClass, Class<D> resourceType) {
|
||||
|
||||
Assert.notNull(controllerClass, "ControllerClass must not be null!");
|
||||
Assert.notNull(resourceType, "ResourceType must not be null!");
|
||||
@@ -56,10 +57,10 @@ public abstract class ResourceAssemblerSupport<T, D extends ResourceSupport> imp
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.ResourceAssembler#toResources(java.lang.Iterable)
|
||||
* @see org.springframework.hateoas.server.RepresentationModelAssembler#toCollectionModel(java.lang.Iterable)
|
||||
*/
|
||||
@Override
|
||||
public Resources<D> toResources(Iterable<? extends T> entities) {
|
||||
public CollectionModel<D> toCollectionModel(Iterable<? extends T> entities) {
|
||||
return this.map(entities).toResources();
|
||||
}
|
||||
|
||||
@@ -74,16 +75,16 @@ public abstract class ResourceAssemblerSupport<T, D extends ResourceSupport> imp
|
||||
* @param id must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected D createResourceWithId(Object id, T entity) {
|
||||
return createResourceWithId(id, entity, new Object[0]);
|
||||
protected D createModelWithId(Object id, T entity) {
|
||||
return createModelWithId(id, entity, new Object[0]);
|
||||
}
|
||||
|
||||
protected D createResourceWithId(Object id, T entity, Object... parameters) {
|
||||
protected D createModelWithId(Object id, T entity, Object... parameters) {
|
||||
|
||||
Assert.notNull(entity, "Entity must not be null!");
|
||||
Assert.notNull(id, "Id must not be null!");
|
||||
|
||||
D instance = instantiateResource(entity);
|
||||
D instance = instantiateModel(entity);
|
||||
instance.add(linkTo(this.controllerClass, parameters).slash(id).withSelfRel());
|
||||
return instance;
|
||||
}
|
||||
@@ -96,23 +97,23 @@ public abstract class ResourceAssemblerSupport<T, D extends ResourceSupport> imp
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
protected D instantiateResource(T entity) {
|
||||
protected D instantiateModel(T entity) {
|
||||
return BeanUtils.instantiateClass(this.resourceType);
|
||||
}
|
||||
|
||||
static class Builder<T, D extends ResourceSupport> {
|
||||
static class Builder<T, D extends RepresentationModel<D>> {
|
||||
|
||||
private final Iterable<? extends T> entities;
|
||||
private final ResourceAssemblerSupport<T, D> resourceAssembler;
|
||||
private final RepresentationModelAssemblerSupport<T, D> resourceAssembler;
|
||||
|
||||
Builder(Iterable<? extends T> entities, ResourceAssemblerSupport<T, D> resourceAssembler) {
|
||||
Builder(Iterable<? extends T> entities, RepresentationModelAssemblerSupport<T, D> resourceAssembler) {
|
||||
|
||||
this.entities = Objects.requireNonNull(entities, "entities must not null!");
|
||||
this.resourceAssembler = resourceAssembler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a list of {@code T}s into a list of {@link ResourceSupport}s.
|
||||
* Transform a list of {@code T}s into a list of {@link RepresentationModel}s.
|
||||
*
|
||||
* @see #toListOfResources() if you need this transformed list rendered as hypermedia
|
||||
* @return
|
||||
@@ -122,20 +123,21 @@ public abstract class ResourceAssemblerSupport<T, D extends ResourceSupport> imp
|
||||
List<D> result = new ArrayList<>();
|
||||
|
||||
for (T entity : this.entities) {
|
||||
result.add(this.resourceAssembler.toResource(entity));
|
||||
result.add(this.resourceAssembler.toModel(entity));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all given entities into resources and wraps the result in a {@link Resources} instance.
|
||||
* Converts all given entities into resources and wraps the result in a {@link CollectionModel}
|
||||
* instance.
|
||||
*
|
||||
* @see #toListOfResources() and {@link ResourceAssembler#toResource(Object)}
|
||||
* @see #toListOfResources() and {@link RepresentationModelAssembler#toModel(Object)}
|
||||
* @return
|
||||
*/
|
||||
public Resources<D> toResources() {
|
||||
return new Resources<>(toListOfResources());
|
||||
public CollectionModel<D> toResources() {
|
||||
return new CollectionModel<>(toListOfResources());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,10 @@ import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.server.ResourceProcessor;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.server.RepresentationModelProcessor;
|
||||
import org.springframework.hateoas.server.core.HeaderLinksResponseEntity;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -36,27 +36,27 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* {@link HandlerMethodReturnValueHandler} to post-process the objects returned from controller methods using the
|
||||
* configured {@link ResourceProcessor}s.
|
||||
*
|
||||
* configured {@link RepresentationModelProcessor}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 0.20
|
||||
* @soundtrack Doppelkopf - Balance (Von Abseits)
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ResourceProcessorHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
public class RepresentationModelProcessorHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
|
||||
static final ResolvableType RESOURCE_TYPE = ResolvableType.forRawClass(Resource.class);
|
||||
static final ResolvableType RESOURCES_TYPE = ResolvableType.forRawClass(Resources.class);
|
||||
static final ResolvableType RESOURCE_TYPE = ResolvableType.forRawClass(EntityModel.class);
|
||||
static final ResolvableType RESOURCES_TYPE = ResolvableType.forRawClass(CollectionModel.class);
|
||||
private static final ResolvableType HTTP_ENTITY_TYPE = ResolvableType.forRawClass(HttpEntity.class);
|
||||
|
||||
static final Field CONTENT_FIELD = ReflectionUtils.findField(Resources.class, "content");
|
||||
static final Field CONTENT_FIELD = ReflectionUtils.findField(CollectionModel.class, "content");
|
||||
|
||||
static {
|
||||
ReflectionUtils.makeAccessible(CONTENT_FIELD);
|
||||
}
|
||||
|
||||
private final @NonNull HandlerMethodReturnValueHandler delegate;
|
||||
private final @NonNull ResourceProcessorInvoker invoker;
|
||||
private final @NonNull RepresentationModelProcessorInvoker invoker;
|
||||
|
||||
private boolean rootLinksAsHeaders = false;
|
||||
|
||||
@@ -81,6 +81,7 @@ public class ResourceProcessorHandlerMethodReturnValueHandler implements Handler
|
||||
* @see org.springframework.web.method.support.HandlerMethodReturnValueHandler#handleReturnValue(java.lang.Object, org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest) throws Exception {
|
||||
|
||||
@@ -91,7 +92,7 @@ public class ResourceProcessorHandlerMethodReturnValueHandler implements Handler
|
||||
}
|
||||
|
||||
// No post-processable type found - proceed with delegate
|
||||
if (!(value instanceof ResourceSupport)) {
|
||||
if (!(value instanceof RepresentationModel)) {
|
||||
delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
|
||||
return;
|
||||
}
|
||||
@@ -111,7 +112,7 @@ public class ResourceProcessorHandlerMethodReturnValueHandler implements Handler
|
||||
targetType = returnValueType;
|
||||
}
|
||||
|
||||
ResourceSupport result = invoker.invokeProcessorsFor((ResourceSupport) value, targetType);
|
||||
RepresentationModel<?> result = invoker.invokeProcessorsFor((RepresentationModel) value, targetType);
|
||||
delegate.handleReturnValue(rewrapResult(result, returnValue), returnType, mavContainer, webRequest);
|
||||
}
|
||||
|
||||
@@ -119,18 +120,18 @@ public class ResourceProcessorHandlerMethodReturnValueHandler implements Handler
|
||||
* 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
|
||||
*/
|
||||
Object rewrapResult(ResourceSupport newBody, Object originalValue) {
|
||||
Object rewrapResult(RepresentationModel<?> newBody, Object originalValue) {
|
||||
|
||||
if (!(originalValue instanceof HttpEntity)) {
|
||||
return rootLinksAsHeaders ? HeaderLinksResponseEntity.wrap(newBody) : newBody;
|
||||
}
|
||||
|
||||
HttpEntity<ResourceSupport> entity = null;
|
||||
HttpEntity<RepresentationModel<?>> entity = null;
|
||||
|
||||
if (originalValue instanceof ResponseEntity) {
|
||||
ResponseEntity<?> source = (ResponseEntity<?>) originalValue;
|
||||
@@ -23,46 +23,47 @@ import java.util.List;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.server.ResourceProcessor;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.server.RepresentationModelProcessor;
|
||||
import org.springframework.hateoas.server.core.EmbeddedWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Component to easily invoke all {@link ResourceProcessor} instances registered for values of type
|
||||
* {@link ResourceSupport}.
|
||||
* Component to easily invoke all {@link RepresentationModelProcessor} instances registered for values of type
|
||||
* {@link RepresentationModel}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 0.20
|
||||
* @soundtrack Doppelkopf - Die fabelhaften Vier (Von Abseits)
|
||||
*/
|
||||
public class ResourceProcessorInvoker {
|
||||
public class RepresentationModelProcessorInvoker {
|
||||
|
||||
private final List<ProcessorWrapper> processors;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ResourceProcessorInvoker} to consider the given {@link ResourceProcessor} to post-process the
|
||||
* controller methods return value to before invoking the delegate.
|
||||
*
|
||||
* @param processors the {@link ResourceProcessor}s to be considered, must not be {@literal null}.
|
||||
* Creates a new {@link RepresentationModelProcessorInvoker} to consider the given
|
||||
* {@link RepresentationModelProcessor} to post-process the controller methods return value to before invoking the
|
||||
* delegate.
|
||||
*
|
||||
* @param processors the {@link RepresentationModelProcessor}s to be considered, must not be {@literal null}.
|
||||
*/
|
||||
public ResourceProcessorInvoker(Collection<ResourceProcessor<?>> processors) {
|
||||
public RepresentationModelProcessorInvoker(Collection<RepresentationModelProcessor<?>> processors) {
|
||||
|
||||
Assert.notNull(processors, "ResourceProcessors must not be null!");
|
||||
|
||||
this.processors = new ArrayList<>();
|
||||
|
||||
for (ResourceProcessor<?> processor : processors) {
|
||||
for (RepresentationModelProcessor<?> processor : processors) {
|
||||
|
||||
ResolvableType processorType = ResolvableType.forClass(ResourceProcessor.class, processor.getClass());
|
||||
ResolvableType processorType = ResolvableType.forClass(RepresentationModelProcessor.class, processor.getClass());
|
||||
Class<?> rawType = processorType.getGeneric(0).resolve();
|
||||
|
||||
if (Resource.class.isAssignableFrom(rawType)) {
|
||||
if (EntityModel.class.isAssignableFrom(rawType)) {
|
||||
this.processors.add(new ResourceProcessorWrapper(processor));
|
||||
} else if (Resources.class.isAssignableFrom(rawType)) {
|
||||
} else if (CollectionModel.class.isAssignableFrom(rawType)) {
|
||||
this.processors.add(new ResourcesProcessorWrapper(processor));
|
||||
} else {
|
||||
this.processors.add(new DefaultProcessorWrapper(processor));
|
||||
@@ -73,12 +74,12 @@ public class ResourceProcessorInvoker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes all {@link ResourceProcessor} instances registered for the type of the given value.
|
||||
*
|
||||
* Invokes all {@link RepresentationModelProcessor} instances registered for the type of the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public <T extends ResourceSupport> T invokeProcessorsFor(T value) {
|
||||
public <T extends RepresentationModel<T>> T invokeProcessorsFor(T value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
@@ -86,24 +87,25 @@ public class ResourceProcessorInvoker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes all {@link ResourceProcessor} instances registered for the type of the given value and reference type.
|
||||
*
|
||||
* Invokes all {@link RepresentationModelProcessor} instances registered for the type of the given value and reference
|
||||
* type.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @param referenceType must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ResourceSupport> T invokeProcessorsFor(T value, ResolvableType referenceType) {
|
||||
public <T extends RepresentationModel<T>> T invokeProcessorsFor(T value, ResolvableType referenceType) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
Assert.notNull(referenceType, "Reference type must not be null!");
|
||||
|
||||
// For Resources implementations, process elements first
|
||||
if (ResourceProcessorHandlerMethodReturnValueHandler.RESOURCES_TYPE.isAssignableFrom(referenceType)) {
|
||||
if (RepresentationModelProcessorHandlerMethodReturnValueHandler.RESOURCES_TYPE.isAssignableFrom(referenceType)) {
|
||||
|
||||
Resources<?> resources = (Resources<?>) value;
|
||||
ResolvableType elementTargetType = ResolvableType.forClass(Resources.class, referenceType.getRawClass())
|
||||
.getGeneric(0);
|
||||
CollectionModel<?> resources = (CollectionModel<?>) value;
|
||||
ResolvableType elementTargetType = ResolvableType
|
||||
.forClass(CollectionModel.class, referenceType.getRawClass()).getGeneric(0);
|
||||
List<Object> result = new ArrayList<>(resources.getContent().size());
|
||||
|
||||
for (Object element : resources) {
|
||||
@@ -117,15 +119,16 @@ public class ResourceProcessorInvoker {
|
||||
result.add(invokeProcessorsFor(element, elementTargetType));
|
||||
}
|
||||
|
||||
ReflectionUtils.setField(ResourceProcessorHandlerMethodReturnValueHandler.CONTENT_FIELD, resources, result);
|
||||
ReflectionUtils.setField(RepresentationModelProcessorHandlerMethodReturnValueHandler.CONTENT_FIELD, resources,
|
||||
result);
|
||||
}
|
||||
|
||||
return (T) invokeProcessorsFor((Object) value, referenceType);
|
||||
return (T) invokeProcessorsFor(Object.class.cast(value), referenceType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes all registered {@link ResourceProcessor}s registered for the given {@link ResolvableType}.
|
||||
*
|
||||
* Invokes all registered {@link RepresentationModelProcessor}s registered for the given {@link ResolvableType}.
|
||||
*
|
||||
* @param value the object to process
|
||||
* @param type
|
||||
* @return
|
||||
@@ -135,7 +138,7 @@ public class ResourceProcessorInvoker {
|
||||
Object currentValue = value;
|
||||
|
||||
// Process actual value
|
||||
for (ResourceProcessorInvoker.ProcessorWrapper wrapper : this.processors) {
|
||||
for (RepresentationModelProcessorInvoker.ProcessorWrapper wrapper : this.processors) {
|
||||
if (wrapper.supports(type, currentValue)) {
|
||||
currentValue = wrapper.invokeProcessor(currentValue);
|
||||
}
|
||||
@@ -155,9 +158,9 @@ public class ResourceProcessorInvoker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to unify interaction with {@link ResourceProcessor}s. The {@link Ordered} rank should be determined by
|
||||
* the underlying processor.
|
||||
*
|
||||
* Interface to unify interaction with {@link RepresentationModelProcessor}s. The {@link Ordered} rank should be
|
||||
* determined by the underlying processor.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private interface ProcessorWrapper extends Ordered {
|
||||
@@ -165,7 +168,7 @@ public class ResourceProcessorInvoker {
|
||||
/**
|
||||
* Returns whether the underlying processor supports the given {@link ResolvableType}. It might also additionally
|
||||
* inspect the object that would eventually be handed to the processor.
|
||||
*
|
||||
*
|
||||
* @param type the type of object to be post processed, will never be {@literal null}.
|
||||
* @param value the object that would be passed into the processor eventually, can be {@literal null}.
|
||||
* @return
|
||||
@@ -175,33 +178,33 @@ public class ResourceProcessorInvoker {
|
||||
/**
|
||||
* Performs the actual invocation of the processor. Implementations can be sure
|
||||
* {@link #supports(ResolvableType, Object)} has been called before and returned {@literal true}.
|
||||
*
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
Object invokeProcessor(Object object);
|
||||
<S> S invokeProcessor(S object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ProcessorWrapper} to generically deal with {@link ResourceSupport} types.
|
||||
*
|
||||
* Default implementation of {@link ProcessorWrapper} to generically deal with {@link RepresentationModel} types.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class DefaultProcessorWrapper implements ResourceProcessorInvoker.ProcessorWrapper {
|
||||
private static class DefaultProcessorWrapper implements RepresentationModelProcessorInvoker.ProcessorWrapper {
|
||||
|
||||
private final ResourceProcessor<?> processor;
|
||||
private final RepresentationModelProcessor<?> processor;
|
||||
private final ResolvableType targetType;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultProcessorWrapper} with the given {@link ResourceProcessor}.
|
||||
*
|
||||
* Creates a new {@link DefaultProcessorWrapper} with the given {@link RepresentationModelProcessor}.
|
||||
*
|
||||
* @param processor must not be {@literal null}.
|
||||
*/
|
||||
DefaultProcessorWrapper(ResourceProcessor<?> processor) {
|
||||
DefaultProcessorWrapper(RepresentationModelProcessor<?> processor) {
|
||||
|
||||
Assert.notNull(processor, "Processor must not be null!");
|
||||
|
||||
this.processor = processor;
|
||||
this.targetType = ResolvableType.forClass(ResourceProcessor.class, processor.getClass()).getGeneric(0);
|
||||
this.targetType = ResolvableType.forClass(RepresentationModelProcessor.class, processor.getClass()).getGeneric(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -213,14 +216,15 @@ public class ResourceProcessorInvoker {
|
||||
return isRawTypeAssignable(targetType, getRawType(type));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.PostProcessorWrapper#invokeProcessor(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object invokeProcessor(Object object) {
|
||||
return ((ResourceProcessor<ResourceSupport>) processor).process((ResourceSupport) object);
|
||||
return ((RepresentationModelProcessor<RepresentationModel<?>>) processor)
|
||||
.process((RepresentationModel<?>) object);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -233,8 +237,8 @@ public class ResourceProcessorInvoker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target type the underlying {@link ResourceProcessor} wants to get invoked for.
|
||||
*
|
||||
* Returns the target type the underlying {@link RepresentationModelProcessor} wants to get invoked for.
|
||||
*
|
||||
* @return the targetType
|
||||
*/
|
||||
public ResolvableType getTargetType() {
|
||||
@@ -243,19 +247,19 @@ public class ResourceProcessorInvoker {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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.
|
||||
*
|
||||
* {@link ProcessorWrapper} to deal with {@link RepresentationModelProcessor}s for {@link EntityModel}s.
|
||||
* Will fall back to peeking into the {@link EntityModel}'s content for type resolution.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ResourceProcessorWrapper extends ResourceProcessorInvoker.DefaultProcessorWrapper {
|
||||
private static class ResourceProcessorWrapper extends RepresentationModelProcessorInvoker.DefaultProcessorWrapper {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ResourceProcessorWrapper} for the given {@link ResourceProcessor}.
|
||||
*
|
||||
* Creates a new {@link ResourceProcessorWrapper} for the given {@link RepresentationModelProcessor}.
|
||||
*
|
||||
* @param processor must not be {@literal null}.
|
||||
*/
|
||||
public ResourceProcessorWrapper(ResourceProcessor<?> processor) {
|
||||
public ResourceProcessorWrapper(RepresentationModelProcessor<?> processor) {
|
||||
super(processor);
|
||||
}
|
||||
|
||||
@@ -266,22 +270,23 @@ public class ResourceProcessorInvoker {
|
||||
@Override
|
||||
public boolean supports(ResolvableType type, Object value) {
|
||||
|
||||
if (!ResourceProcessorHandlerMethodReturnValueHandler.RESOURCE_TYPE.isAssignableFrom(type)) {
|
||||
if (!RepresentationModelProcessorHandlerMethodReturnValueHandler.RESOURCE_TYPE.isAssignableFrom(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.supports(type, value) && isValueTypeMatch((Resource<?>) value, getTargetType());
|
||||
return super.supports(type, value) && isValueTypeMatch((EntityModel<?>) value, getTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link Resource} matches the given target {@link ResolvableType}. We inspect the
|
||||
* {@link Resource}'s value to determine the match.
|
||||
*
|
||||
* Returns whether the given {@link EntityModel} matches the given target {@link ResolvableType}. We
|
||||
* inspect the {@link EntityModel}'s value to determine the match.
|
||||
*
|
||||
* @param resource
|
||||
* @param target must not be {@literal null}.
|
||||
* @return whether the given {@link Resource} can be assigned to the given target {@link ResolvableType}
|
||||
* @return whether the given {@link EntityModel} can be assigned to the given target
|
||||
* {@link ResolvableType}
|
||||
*/
|
||||
private static boolean isValueTypeMatch(Resource<?> resource, ResolvableType target) {
|
||||
private static boolean isValueTypeMatch(EntityModel<?> resource, ResolvableType target) {
|
||||
|
||||
if (resource == null || !isRawTypeAssignable(target, resource.getClass())) {
|
||||
return false;
|
||||
@@ -293,7 +298,7 @@ public class ResourceProcessorInvoker {
|
||||
return false;
|
||||
}
|
||||
|
||||
ResolvableType type = findGenericType(target, Resource.class);
|
||||
ResolvableType type = findGenericType(target, EntityModel.class);
|
||||
return type != null && type.getGeneric(0).isAssignableFrom(ResolvableType.forClass(content.getClass()));
|
||||
}
|
||||
|
||||
@@ -314,19 +319,19 @@ public class ResourceProcessorInvoker {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ProcessorWrapper} for {@link ResourceProcessor}s targeting {@link Resources}. Will peek into the content of
|
||||
* the {@link Resources} for type matching decisions if needed.
|
||||
*
|
||||
* {@link ProcessorWrapper} for {@link RepresentationModelProcessor}s targeting {@link CollectionModel}.
|
||||
* Will peek into the content of the {@link CollectionModel} for type matching decisions if needed.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static class ResourcesProcessorWrapper extends ResourceProcessorInvoker.DefaultProcessorWrapper {
|
||||
public static class ResourcesProcessorWrapper extends RepresentationModelProcessorInvoker.DefaultProcessorWrapper {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ResourcesProcessorWrapper} for the given {@link ResourceProcessor}.
|
||||
*
|
||||
* Creates a new {@link ResourcesProcessorWrapper} for the given {@link RepresentationModelProcessor}.
|
||||
*
|
||||
* @param processor must not be {@literal null}.
|
||||
*/
|
||||
public ResourcesProcessorWrapper(ResourceProcessor<?> processor) {
|
||||
public ResourcesProcessorWrapper(RepresentationModelProcessor<?> processor) {
|
||||
super(processor);
|
||||
}
|
||||
|
||||
@@ -337,22 +342,23 @@ public class ResourceProcessorInvoker {
|
||||
@Override
|
||||
public boolean supports(ResolvableType type, Object value) {
|
||||
|
||||
if (!ResourceProcessorHandlerMethodReturnValueHandler.RESOURCES_TYPE.isAssignableFrom(type)) {
|
||||
if (!RepresentationModelProcessorHandlerMethodReturnValueHandler.RESOURCES_TYPE.isAssignableFrom(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.supports(type, value) && isValueTypeMatch((Resources<?>) value, getTargetType());
|
||||
return super.supports(type, value) && isValueTypeMatch((CollectionModel<?>) value, getTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link Resources} instance matches the given {@link ResolvableType}. We predict this by
|
||||
* inspecting the first element of the content of the {@link Resources}.
|
||||
*
|
||||
* @param resources the {@link Resources} to inspect.
|
||||
* Returns whether the given {@link CollectionModel} instance matches the given
|
||||
* {@link ResolvableType}. We predict this by inspecting the first element of the content of the
|
||||
* {@link CollectionModel}.
|
||||
*
|
||||
* @param resources the {@link CollectionModel} to inspect.
|
||||
* @param target that target {@link ResolvableType}.
|
||||
* @return
|
||||
*/
|
||||
static boolean isValueTypeMatch(Resources<?> resources, ResolvableType target) {
|
||||
static boolean isValueTypeMatch(CollectionModel<?> resources, ResolvableType target) {
|
||||
|
||||
if (resources == null) {
|
||||
return false;
|
||||
@@ -366,7 +372,8 @@ public class ResourceProcessorInvoker {
|
||||
|
||||
ResolvableType superType = null;
|
||||
|
||||
for (Class<?> resourcesType : Arrays.<Class<?>>asList(resources.getClass(), Resources.class)) {
|
||||
for (Class<?> resourcesType : Arrays.<Class<?>> asList(resources.getClass(),
|
||||
CollectionModel.class)) {
|
||||
|
||||
superType = getSuperType(target, resourcesType);
|
||||
|
||||
@@ -382,8 +389,8 @@ public class ResourceProcessorInvoker {
|
||||
Object element = content.iterator().next();
|
||||
ResolvableType resourceType = superType.getGeneric(0);
|
||||
|
||||
if (element instanceof Resource) {
|
||||
return ResourceProcessorWrapper.isValueTypeMatch((Resource<?>) element, resourceType);
|
||||
if (element instanceof EntityModel) {
|
||||
return ResourceProcessorWrapper.isValueTypeMatch((EntityModel<?>) element, resourceType);
|
||||
} else if (element instanceof EmbeddedWrapper) {
|
||||
return isRawTypeAssignable(resourceType, ((EmbeddedWrapper) element).getRelTargetType());
|
||||
}
|
||||
@@ -393,7 +400,7 @@ public class ResourceProcessorInvoker {
|
||||
|
||||
/**
|
||||
* Returns the {@link ResolvableType} for the given raw super class.
|
||||
*
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param superType must not be {@literal null}.
|
||||
* @return
|
||||
@@ -423,12 +430,12 @@ public class ResourceProcessorInvoker {
|
||||
/**
|
||||
* Helper extension of {@link AnnotationAwareOrderComparator} to make {@link #getOrder(Object)} public to allow it
|
||||
* being used in a standalone fashion.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class CustomOrderAwareComparator extends AnnotationAwareOrderComparator {
|
||||
|
||||
public static ResourceProcessorInvoker.CustomOrderAwareComparator INSTANCE = new CustomOrderAwareComparator();
|
||||
public static RepresentationModelProcessorInvoker.CustomOrderAwareComparator INSTANCE = new CustomOrderAwareComparator();
|
||||
|
||||
@Override
|
||||
protected int getOrder(Object obj) {
|
||||
@@ -22,7 +22,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.hateoas.server.ResourceProcessor;
|
||||
import org.springframework.hateoas.server.RepresentationModelProcessor;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
|
||||
@@ -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 ResourceProcessorHandlerMethodReturnValueHandler} which will invoke the {@link ResourceProcessor}
|
||||
* proxied by a {@link RepresentationModelProcessorHandlerMethodReturnValueHandler} which will invoke the {@link RepresentationModelProcessor}
|
||||
* s found in the application context and eventually delegate to the originally configured
|
||||
* {@link HandlerMethodReturnValueHandler}.
|
||||
* <p/>
|
||||
@@ -43,12 +43,12 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
||||
* @soundtrack Dopplekopf - Regen für immer (Von Abseits)
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ResourceProcessorInvokingHandlerAdapter extends RequestMappingHandlerAdapter {
|
||||
public class RepresentationModelProcessorInvokingHandlerAdapter extends RequestMappingHandlerAdapter {
|
||||
|
||||
private static final Method RETURN_VALUE_HANDLER_METHOD = ReflectionUtils
|
||||
.findMethod(ResourceProcessorInvokingHandlerAdapter.class, "getReturnValueHandlers");
|
||||
.findMethod(RepresentationModelProcessorInvokingHandlerAdapter.class, "getReturnValueHandlers");
|
||||
|
||||
private @NonNull final ResourceProcessorInvoker invoker;
|
||||
private @NonNull final RepresentationModelProcessorInvoker invoker;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -64,7 +64,7 @@ public class ResourceProcessorInvokingHandlerAdapter extends RequestMappingHandl
|
||||
|
||||
// Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
|
||||
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<>();
|
||||
newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, invoker));
|
||||
newHandlers.add(new RepresentationModelProcessorHandlerMethodReturnValueHandler(oldHandlers, invoker));
|
||||
|
||||
// Configure the new handler to be used
|
||||
this.setReturnValueHandlers(newHandlers);
|
||||
@@ -26,7 +26,8 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper to easily create {@link ParameterizedTypeReference} instances to Spring HATEOAS resource types. They're
|
||||
* basically a shortcut over using a verbose {@code new ParameterizedTypeReference<Resources<DomainType>>()}.
|
||||
* basically a shortcut over using a verbose
|
||||
* {@code new ParameterizedTypeReference<CollectionRepresentationModel<DomainType>>()}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 0.17
|
||||
@@ -34,31 +35,31 @@ import org.springframework.util.Assert;
|
||||
public class TypeReferences {
|
||||
|
||||
/**
|
||||
* A {@link ParameterizedTypeReference} to return a {@link org.springframework.hateoas.Resource} of some type.
|
||||
* A {@link ParameterizedTypeReference} to return a {@link org.springframework.hateoas.EntityModel} of some type.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 0.17
|
||||
*/
|
||||
public static class ResourceType<T>
|
||||
extends SyntheticParameterizedTypeReference<org.springframework.hateoas.Resource<T>> {}
|
||||
public static class EntityModelType<T>
|
||||
extends SyntheticParameterizedTypeReference<org.springframework.hateoas.EntityModel<T>> {}
|
||||
|
||||
/**
|
||||
* A {@link ParameterizedTypeReference} to return a {@link org.springframework.hateoas.Resources} of some type.
|
||||
* A {@link ParameterizedTypeReference} to return a {@link org.springframework.hateoas.CollectionModel} of some type.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 0.17
|
||||
*/
|
||||
public static class ResourcesType<T>
|
||||
extends SyntheticParameterizedTypeReference<org.springframework.hateoas.Resources<T>> {}
|
||||
public static class CollectionModelType<T>
|
||||
extends SyntheticParameterizedTypeReference<org.springframework.hateoas.CollectionModel<T>> {}
|
||||
|
||||
/**
|
||||
* A {@link ParameterizedTypeReference} to return a {@link org.springframework.hateoas.PagedResources} of some type.
|
||||
* A {@link ParameterizedTypeReference} to return a {@link org.springframework.hateoas.PagedModel} of some type.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 0.17
|
||||
*/
|
||||
public static class PagedResourcesType<T>
|
||||
extends SyntheticParameterizedTypeReference<org.springframework.hateoas.PagedResources<T>> {}
|
||||
public static class PagedModelType<T>
|
||||
extends SyntheticParameterizedTypeReference<org.springframework.hateoas.PagedModel<T>> {}
|
||||
|
||||
/**
|
||||
* Special {@link ParameterizedTypeReference} to customize the generic type detection and eventually return a
|
||||
@@ -144,7 +145,7 @@ public class TypeReferences {
|
||||
}
|
||||
|
||||
/**
|
||||
* A sythetic {@link ParameterizedType}.
|
||||
* A synthetic {@link ParameterizedType}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 0.17
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
class UriComponentsBuilderFactory {
|
||||
|
||||
static final String REQUEST_ATTRIBUTES_MISSING = "Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler?";
|
||||
private static final String CACHE_KEY = ControllerLinkBuilder.class.getName() + "#BUILDER_CACHE";
|
||||
private static final String CACHE_KEY = UriComponentsBuilderFactory.class.getName() + "#BUILDER_CACHE";
|
||||
|
||||
/**
|
||||
* Returns a {@link UriComponentsBuilder} obtained from the current servlet mapping with scheme tweaked in case the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Spring MVC helper classes to build {@link org.springframework.hateoas.Link}s and assemble
|
||||
* {@link org.springframework.hateoas.ResourceSupport} types.
|
||||
* {@link org.springframework.hateoas.RepresentationModel} types.
|
||||
*/
|
||||
package org.springframework.hateoas.server.mvc;
|
||||
|
||||
|
||||
@@ -18,41 +18,40 @@ package org.springframework.hateoas.server.reactive;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.server.ResourceAssembler;
|
||||
import org.springframework.hateoas.server.SimpleResourceAssembler;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.server.RepresentationModelAssembler;
|
||||
import org.springframework.hateoas.server.SimpleRepresentationModelAssembler;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Reactive variant of {@link ResourceAssembler} combined with {@link SimpleResourceAssembler}.
|
||||
* Reactive variant of {@link RepresentationModelAssembler} combined with {@link SimpleRepresentationModelAssembler}.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 1.0
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
public interface ReactiveResourceAssembler<T, D extends ResourceSupport> {
|
||||
public interface ReactiveRepresentationModelAssembler<T, D extends RepresentationModel<D>> {
|
||||
|
||||
/**
|
||||
* Converts the given entity into a {@code D}, which extends {@link ResourceSupport}.
|
||||
* Converts the given entity into a {@code D}, which extends {@link RepresentationModel}.
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
Mono<D> toResource(T entity, ServerWebExchange exchange);
|
||||
Mono<D> toModel(T entity, ServerWebExchange exchange);
|
||||
|
||||
/**
|
||||
* Converts an {@link Iterable} or {@code T}s into an {@link Iterable} of {@link ResourceSupport} and wraps
|
||||
* them in a {@link Resources} instance.
|
||||
* Converts an {@link Iterable} or {@code T}s into an {@link Iterable} of {@link RepresentationModel} and wraps them
|
||||
* in a {@link CollectionModel} instance.
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
* @return {@link Resources} containing {@code D}.
|
||||
* @return {@link CollectionModel} containing {@code D}.
|
||||
*/
|
||||
default Mono<Resources<D>> toResources(Flux<? extends T> entities, ServerWebExchange exchange) {
|
||||
default Mono<CollectionModel<D>> toCollectionModel(Flux<? extends T> entities,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
return entities
|
||||
.flatMap(entity -> toResource(entity, exchange))
|
||||
.collectList()
|
||||
.map(listOfResources -> new Resources<>(listOfResources));
|
||||
return entities.flatMap(entity -> toModel(entity, exchange)) //
|
||||
.collectList() //
|
||||
.map(CollectionModel::new);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.reactive;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.server.RepresentationModelAssembler;
|
||||
import org.springframework.hateoas.server.SimpleRepresentationModelAssembler;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Reactive variant of {@link RepresentationModelAssembler} combined with {@link SimpleRepresentationModelAssembler}.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
public interface SimpleReactiveRepresentationModelAssembler<T>
|
||||
extends ReactiveRepresentationModelAssembler<T, EntityModel<T>> {
|
||||
|
||||
/**
|
||||
* Converts the given entity into a {@link EntityModel} wrapped in a {@link Mono}.
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
default Mono<EntityModel<T>> toModel(T entity, ServerWebExchange exchange) {
|
||||
|
||||
EntityModel<T> resource = new EntityModel<>(entity);
|
||||
return Mono.just(addLinks(resource, exchange));
|
||||
}
|
||||
|
||||
/**
|
||||
* Define links to add to every individual {@link EntityModel}.
|
||||
*
|
||||
* @param resource
|
||||
*/
|
||||
default EntityModel<T> addLinks(EntityModel<T> resource, ServerWebExchange exchange) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all given entities into resources and wraps the collection as a resource as well.
|
||||
*
|
||||
* @see #toResource(Object, ServerWebExchange)
|
||||
* @param entities must not be {@literal null}.
|
||||
* @return {@link CollectionModel} containing {@link EntityModel} of {@code T}.
|
||||
*/
|
||||
default Mono<CollectionModel<EntityModel<T>>> toCollectionModel(
|
||||
Flux<? extends T> entities, ServerWebExchange exchange) {
|
||||
|
||||
return entities //
|
||||
.flatMap(entity -> toModel(entity, exchange)) //
|
||||
.collectList() //
|
||||
.map(CollectionModel::new) //
|
||||
.map(it -> addLinks(it, exchange));
|
||||
}
|
||||
|
||||
/**
|
||||
* Define links to add to the {@link CollectionModel} collection.
|
||||
*
|
||||
* @param resources
|
||||
*/
|
||||
default CollectionModel<EntityModel<T>> addLinks(
|
||||
CollectionModel<EntityModel<T>> resources, ServerWebExchange exchange) {
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* 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.reactive;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.server.ResourceAssembler;
|
||||
import org.springframework.hateoas.server.SimpleResourceAssembler;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Reactive variant of {@link ResourceAssembler} combined with {@link SimpleResourceAssembler}.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface SimpleReactiveResourceAssembler<T> extends ReactiveResourceAssembler<T, Resource<T>> {
|
||||
|
||||
/**
|
||||
* Converts the given entity into a {@link Resource} wrapped in a {@link Mono}.
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
default Mono<Resource<T>> toResource(T entity, ServerWebExchange exchange) {
|
||||
|
||||
Resource<T> resource = new Resource<>(entity);
|
||||
addLinks(resource, exchange);
|
||||
return Mono.just(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define links to add to every individual {@link Resource}.
|
||||
*
|
||||
* @param resource
|
||||
*/
|
||||
void addLinks(Resource<T> resource, ServerWebExchange exchange);
|
||||
|
||||
/**
|
||||
* Converts all given entities into resources and wraps the collection as a resource as well.
|
||||
*
|
||||
* @see #toResource(Object, ServerWebExchange)
|
||||
* @param entities must not be {@literal null}.
|
||||
* @return {@link Resources} containing {@link Resource} of {@code T}.
|
||||
*/
|
||||
default Mono<Resources<Resource<T>>> toResources(Flux<? extends T> entities, ServerWebExchange exchange) {
|
||||
|
||||
return entities //
|
||||
.flatMap(entity -> toResource(entity, exchange)) //
|
||||
.collectList() //
|
||||
.map(listOfResources -> {
|
||||
Resources<Resource<T>> resources = new Resources<>(listOfResources);
|
||||
addLinks(resources, exchange);
|
||||
return resources;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Define links to add to the {@link Resources} collection.
|
||||
*
|
||||
* @param resources
|
||||
*/
|
||||
void addLinks(Resources<Resource<T>> resources, ServerWebExchange exchange);
|
||||
}
|
||||
Reference in New Issue
Block a user