mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Add previously processed links
This commit is contained in:
@@ -32,6 +32,7 @@ import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -155,9 +156,12 @@ public class ConverterService {
|
||||
* @throws ClassCastException if the resource type is not compatible with the inferred return type.
|
||||
*/
|
||||
public <T extends HALResource> T toResource(RestModel restObject) {
|
||||
return toResource(restObject, new Link[] {});
|
||||
}
|
||||
public <T extends HALResource> T toResource(RestModel restObject, Link... oldLinks) {
|
||||
T halResource = getResource(restObject);
|
||||
if (restObject instanceof RestAddressableModel) {
|
||||
utils.embedOrLinkClassLevelRels(halResource);
|
||||
utils.embedOrLinkClassLevelRels(halResource, oldLinks);
|
||||
halLinkService.addLinks(halResource);
|
||||
Projection projection = ((RestAddressableModel) restObject).getProjection();
|
||||
return projection.transformResource(halResource);
|
||||
|
@@ -11,6 +11,7 @@ import org.dspace.app.rest.model.LinkRest;
|
||||
import org.dspace.app.rest.model.RestAddressableModel;
|
||||
import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.model.hateoas.HALResource;
|
||||
import org.springframework.hateoas.Link;
|
||||
|
||||
/**
|
||||
* Abstract base class for projections.
|
||||
@@ -35,7 +36,7 @@ public abstract class AbstractProjection implements Projection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest) {
|
||||
public boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest, Link... oldLinks) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,7 @@ import org.dspace.app.rest.model.LinkRest;
|
||||
import org.dspace.app.rest.model.RestAddressableModel;
|
||||
import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.model.hateoas.HALResource;
|
||||
import org.springframework.hateoas.Link;
|
||||
|
||||
/**
|
||||
* A projection that combines the behavior of multiple projections.
|
||||
@@ -61,9 +62,9 @@ public class CompositeProjection implements Projection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest) {
|
||||
public boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest, Link... oldLinks) {
|
||||
for (Projection projection : projections) {
|
||||
if (projection.allowEmbedding(halResource, linkRest)) {
|
||||
if (projection.allowEmbedding(halResource, linkRest, oldLinks)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ import java.util.Set;
|
||||
import org.dspace.app.rest.model.LinkRest;
|
||||
import org.dspace.app.rest.model.RestAddressableModel;
|
||||
import org.dspace.app.rest.model.hateoas.HALResource;
|
||||
import org.springframework.hateoas.Link;
|
||||
|
||||
/**
|
||||
* Projection that allows a given set of rels to be embedded.
|
||||
@@ -32,9 +33,22 @@ public class EmbedRelsProjection extends AbstractProjection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest) {
|
||||
if (halResource.getContent().getEmbedLevel() == 0)
|
||||
return embedRels.contains(linkRest.name());
|
||||
public boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest, Link... oldLinks) {
|
||||
if (halResource.getContent().getEmbedLevel() == 0 && embedRels.contains(linkRest.name()))
|
||||
return true;
|
||||
StringBuilder fullName = new StringBuilder();
|
||||
for (Link oldLink : oldLinks) {
|
||||
fullName.append(oldLink.getRel()).append("/");
|
||||
}
|
||||
fullName.append(linkRest.name());
|
||||
if (embedRels.contains(fullName.toString())) {
|
||||
return true;
|
||||
}
|
||||
fullName.append("/");
|
||||
for (String embedRel : embedRels) {
|
||||
if (embedRel.startsWith(fullName.toString()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ package org.dspace.app.rest.projection;
|
||||
|
||||
import org.dspace.app.rest.model.LinkRest;
|
||||
import org.dspace.app.rest.model.hateoas.HALResource;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -24,7 +25,7 @@ public class FullProjection extends AbstractProjection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowEmbedding(HALResource halResource, LinkRest linkRest) {
|
||||
public boolean allowEmbedding(HALResource halResource, LinkRest linkRest, Link... oldLinks) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@ import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.model.hateoas.HALResource;
|
||||
import org.dspace.app.rest.repository.DSpaceRestRepository;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -118,7 +119,7 @@ public interface Projection {
|
||||
* @param linkRest the LinkRest annotation through which the related resource was discovered on the rest object.
|
||||
* @return true if allowed, false otherwise.
|
||||
*/
|
||||
boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest);
|
||||
boolean allowEmbedding(HALResource<? extends RestAddressableModel> halResource, LinkRest linkRest, Link... oldLinks);
|
||||
|
||||
/**
|
||||
* Tells whether this projection permits the linking of a particular linkable subresource.
|
||||
|
@@ -516,13 +516,14 @@ public class Utils {
|
||||
* Adds embeds or links for all class-level LinkRel annotations for which embeds or links are allowed.
|
||||
*
|
||||
* @param halResource the resource.
|
||||
* @param oldLinks previously traversed links
|
||||
*/
|
||||
public void embedOrLinkClassLevelRels(HALResource<RestAddressableModel> halResource) {
|
||||
public void embedOrLinkClassLevelRels(HALResource<RestAddressableModel> halResource, Link... oldLinks) {
|
||||
Projection projection = halResource.getContent().getProjection();
|
||||
getLinkRests(halResource.getContent().getClass()).stream().forEach((linkRest) -> {
|
||||
Link link = linkToSubResource(halResource.getContent(), linkRest.name());
|
||||
if (projection.allowEmbedding(halResource, linkRest)) {
|
||||
embedRelFromRepository(halResource, linkRest.name(), link, linkRest);
|
||||
if (projection.allowEmbedding(halResource, linkRest, oldLinks)) {
|
||||
embedRelFromRepository(halResource, linkRest.name(), link, linkRest, oldLinks);
|
||||
halResource.add(link); // unconditionally link if embedding was allowed
|
||||
} else if (projection.allowLinking(halResource, linkRest)) {
|
||||
halResource.add(link);
|
||||
@@ -561,6 +562,10 @@ public class Utils {
|
||||
*/
|
||||
void embedRelFromRepository(HALResource<? extends RestAddressableModel> resource,
|
||||
String rel, Link link, LinkRest linkRest) {
|
||||
embedRelFromRepository(resource, rel, link, linkRest, new Link[] {});
|
||||
}
|
||||
void embedRelFromRepository(HALResource<? extends RestAddressableModel> resource,
|
||||
String rel, Link link, LinkRest linkRest, Link... oldLinks) {
|
||||
if (resource.getContent().getEmbedLevel() == EMBED_MAX_LEVELS) {
|
||||
return;
|
||||
}
|
||||
@@ -572,7 +577,7 @@ public class Utils {
|
||||
Object contentId = getContentIdForLinkMethod(resource.getContent(), method);
|
||||
try {
|
||||
Object linkedObject = method.invoke(linkRepository, null, contentId, null, projection);
|
||||
resource.embedResource(rel, wrapForEmbedding(resource, linkedObject, link));
|
||||
resource.embedResource(rel, wrapForEmbedding(resource, linkedObject, link, oldLinks));
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getTargetException() instanceof RuntimeException) {
|
||||
throw (RuntimeException) e.getTargetException();
|
||||
@@ -677,17 +682,23 @@ public class Utils {
|
||||
*/
|
||||
private Object wrapForEmbedding(HALResource<? extends RestAddressableModel> resource,
|
||||
Object linkedObject, Link link) {
|
||||
return wrapForEmbedding(resource, linkedObject, link, new Link[] {});
|
||||
}
|
||||
private Object wrapForEmbedding(HALResource<? extends RestAddressableModel> resource,
|
||||
Object linkedObject, Link link, Link... oldLinks) {
|
||||
int childEmbedLevel = resource.getContent().getEmbedLevel() + 1;
|
||||
Link[] newList = Arrays.copyOf(oldLinks, oldLinks.length+1);
|
||||
newList[oldLinks.length] = link;
|
||||
if (linkedObject instanceof RestAddressableModel) {
|
||||
RestAddressableModel restObject = (RestAddressableModel) linkedObject;
|
||||
restObject.setEmbedLevel(childEmbedLevel);
|
||||
return converter.toResource(restObject);
|
||||
return converter.toResource(restObject, newList);
|
||||
} else if (linkedObject instanceof Page) {
|
||||
// The first page has already been constructed by a link repository and we only need to wrap it
|
||||
Page<RestAddressableModel> page = (Page<RestAddressableModel>) linkedObject;
|
||||
return new EmbeddedPage(link.getHref(), page.map((restObject) -> {
|
||||
restObject.setEmbedLevel(childEmbedLevel);
|
||||
return converter.toResource(restObject);
|
||||
return converter.toResource(restObject, newList);
|
||||
}), null, link.getRel());
|
||||
} else if (linkedObject instanceof List) {
|
||||
// The full list has been retrieved and we need to provide the first page for embedding
|
||||
@@ -699,7 +710,7 @@ public class Utils {
|
||||
return new EmbeddedPage(link.getHref(),
|
||||
page.map((restObject) -> {
|
||||
restObject.setEmbedLevel(childEmbedLevel);
|
||||
return converter.toResource(restObject);
|
||||
return converter.toResource(restObject, newList);
|
||||
}),
|
||||
list, link.getRel());
|
||||
} else {
|
||||
|
@@ -87,7 +87,7 @@ public class MockProjection implements Projection {
|
||||
return halResource;
|
||||
}
|
||||
|
||||
public boolean allowEmbedding(HALResource halResource, LinkRest linkRest) {
|
||||
public boolean allowEmbedding(HALResource halResource, LinkRest linkRest, Link... oldLinks) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user