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