coar-notify-7 merge conflicts fixes, ldn configuration fixes

This commit is contained in:
frabacche
2024-02-21 16:38:34 +01:00
18 changed files with 892 additions and 47 deletions

View File

@@ -70,11 +70,17 @@ public class WebApplication {
@Scheduled(cron = "${ldn.queue.extractor.cron:-}")
public void ldnExtractFromQueue() throws IOException, SQLException {
if (!configuration.getLdnEnabled()) {
return;
}
LDNQueueExtractor.extractMessageFromQueue();
}
@Scheduled(cron = "${ldn.queue.timeout.checker.cron:-}")
public void ldnQueueTimeoutCheck() throws IOException, SQLException {
if (!configuration.getLdnEnabled()) {
return;
}
LDNQueueTimeoutChecker.checkQueueMessageTimeout();
}

View File

@@ -9,6 +9,7 @@ package org.dspace.app.rest.model.step;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
@@ -19,6 +20,11 @@ import com.fasterxml.jackson.annotation.JsonUnwrapped;
*/
public class DataUpload implements SectionData {
/*
* primary bitstream uuid
*/
private UUID primary;
@JsonUnwrapped
private List<UploadBitstreamRest> files;
@@ -32,4 +38,13 @@ public class DataUpload implements SectionData {
public void setFiles(List<UploadBitstreamRest> files) {
this.files = files;
}
public UUID getPrimary() {
return primary;
}
public void setPrimary(UUID primary) {
this.primary = primary;
}
}

View File

@@ -39,6 +39,7 @@ public interface DataProcessingStep extends RestProcessingStep {
public static final String ACCESS_CONDITION_STEP_OPERATION_ENTRY = "discoverable";
public static final String ACCESS_CONDITION_POLICY_STEP_OPERATION_ENTRY = "accessConditions";
public static final String SHOW_IDENTIFIERS_ENTRY = "identifiers";
public static final String PRIMARY_FLAG_ENTRY = "primary";
public static final String UPLOAD_STEP_METADATA_PATH = "metadata";
public static final String COARNOTIFY_STEP_PATH = "coarnotify";

View File

@@ -53,7 +53,7 @@ public class BitstreamMetadataValueAddPatchOperation extends MetadataValueAddPat
bitstreamMetadataValuePathUtils.validate(absolutePath);
Item item = source.getItem();
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
;
for (Bundle bb : bundle) {
int idx = 0;
for (Bitstream b : bb.getBitstreams()) {

View File

@@ -0,0 +1,87 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.submit.factory.impl;
import static org.dspace.core.Constants.CONTENT_BUNDLE_NAME;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Submission "add" operation to set primary bitstream.
*
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
*/
public class PrimaryBitstreamAddPatchOperation extends AddPatchOperation<String> {
@Autowired
private ItemService itemService;
@Override
void add(Context context, HttpServletRequest currentRequest, InProgressSubmission source, String path, Object value)
throws Exception {
Item item = source.getItem();
UUID primaryUUID = parseValue(value);
List<Bundle> bundles = itemService.getBundles(item, CONTENT_BUNDLE_NAME);
Optional<Bundle> currentPrimaryBundle = bundles.stream()
.filter(bundle -> Objects.nonNull(bundle.getPrimaryBitstream()))
.findFirst();
Optional<Bitstream> primaryBitstreamToAdd = null;
for (Bundle bundle : bundles) {
primaryBitstreamToAdd = bundle.getBitstreams().stream()
.filter(b -> b.getID().equals(primaryUUID))
.findFirst();
if (primaryBitstreamToAdd.isPresent()) {
if (currentPrimaryBundle.isPresent()) {
currentPrimaryBundle.get().setPrimaryBitstreamID(null);
}
bundle.setPrimaryBitstreamID(primaryBitstreamToAdd.get());
break;
}
}
if (primaryBitstreamToAdd.isEmpty()) {
throw new UnprocessableEntityException("The provided uuid: " + primaryUUID +
" of bitstream to set as primary doesn't match any bitstream!");
}
}
private UUID parseValue(Object value) {
UUID primaryBitstreamUUID;
try {
primaryBitstreamUUID = UUID.fromString((String) value);
} catch (Exception e) {
throw new UnprocessableEntityException("The provided value is invalid!", e);
}
return primaryBitstreamUUID;
}
@Override
protected Class<String[]> getArrayClassForEvaluation() {
return null;
}
@Override
protected Class<String> getClassForEvaluation() {
return null;
}
}

View File

@@ -0,0 +1,50 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.submit.factory.impl;
import static org.dspace.core.Constants.CONTENT_BUNDLE_NAME;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.dspace.content.Bundle;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Submission "remove" operation to remove primary bitstream.
*
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
*/
public class PrimaryBitstreamRemovePatchOperation extends RemovePatchOperation<String> {
@Autowired
private ItemService itemService;
@Override
void remove(Context context, HttpServletRequest request, InProgressSubmission source, String path, Object value)
throws Exception {
Item item = source.getItem();
List<Bundle> bundles = itemService.getBundles(item, CONTENT_BUNDLE_NAME);
bundles.forEach(b -> b.setPrimaryBitstreamID(null));
}
@Override
protected Class<String[]> getArrayClassForEvaluation() {
return null;
}
@Override
protected Class<String> getClassForEvaluation() {
return null;
}
}

View File

@@ -0,0 +1,88 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.submit.factory.impl;
import static org.dspace.core.Constants.CONTENT_BUNDLE_NAME;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Submission "replace" operation to replace primary bitstream.
*
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
*/
public class PrimaryBitstreamReplacePatchOperation extends ReplacePatchOperation<String> {
private final String EX_MESSAGE = "It is impossible to replace primary bitstrem if it wasn't set!";
@Autowired
private ItemService itemService;
@Override
void replace(Context context, HttpServletRequest request, InProgressSubmission source, String path, Object value)
throws Exception {
Item item = source.getItem();
UUID primaryUUID = parseValue(value);
List<Bundle> bundles = itemService.getBundles(item, CONTENT_BUNDLE_NAME);
Bundle currentPrimaryBundle = bundles.stream()
.filter(bundle -> Objects.nonNull(bundle.getPrimaryBitstream()))
.findFirst()
.orElseThrow(() -> new UnprocessableEntityException(EX_MESSAGE));
Optional<Bitstream> primaryBitstream = null;
for (Bundle bundle : bundles) {
primaryBitstream = bundle.getBitstreams().stream()
.filter(b -> b.getID().equals(primaryUUID))
.findFirst();
if (primaryBitstream.isPresent()) {
currentPrimaryBundle.setPrimaryBitstreamID(null);
bundle.setPrimaryBitstreamID(primaryBitstream.get());
break;
}
}
if (primaryBitstream.isEmpty()) {
throw new UnprocessableEntityException("The provided uuid: " + primaryUUID +
" of bitstream to set as primary doesn't match any bitstream!");
}
}
private UUID parseValue(Object value) {
UUID primaryBitstreamUUID;
try {
primaryBitstreamUUID = UUID.fromString((String) value);
} catch (Exception e) {
throw new UnprocessableEntityException("The provided value is invalid!", e);
}
return primaryBitstreamUUID;
}
@Override
protected Class<String[]> getArrayClassForEvaluation() {
return null;
}
@Override
protected Class<String> getClassForEvaluation() {
return null;
}
}

View File

@@ -10,8 +10,10 @@ package org.dspace.app.rest.submit.step;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.ErrorRest;
@@ -56,8 +58,12 @@ public class UploadStep extends AbstractProcessingStep
List<Bundle> bundles = itemService.getBundles(obj.getItem(), Constants.CONTENT_BUNDLE_NAME);
for (Bundle bundle : bundles) {
for (Bitstream source : bundle.getBitstreams()) {
Bitstream primaryBitstream = bundle.getPrimaryBitstream();
UploadBitstreamRest b = submissionService.buildUploadBitstream(configurationService, source);
result.getFiles().add(b);
if (Objects.nonNull(primaryBitstream)) {
result.setPrimary(primaryBitstream.getID());
}
}
}
return result;
@@ -73,6 +79,8 @@ public class UploadStep extends AbstractProcessingStep
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
} else if (op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) {
instance = stepConf.getType() + "." + UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY;
} else if (op.getPath().contains(PRIMARY_FLAG_ENTRY)) {
instance = PRIMARY_FLAG_ENTRY;
} else {
instance = UPLOAD_STEP_REMOVE_OPERATION_ENTRY;
}
@@ -87,9 +95,11 @@ public class UploadStep extends AbstractProcessingStep
instance = stepConf.getType() + "." + UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY;
} else if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) {
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
} else if (op.getPath().contains(PRIMARY_FLAG_ENTRY)) {
instance = PRIMARY_FLAG_ENTRY;
}
}
if (instance == null) {
if (StringUtils.isBlank(instance)) {
throw new UnprocessableEntityException("The path " + op.getPath() + " is not supported by the operation "
+ op.getOp());
}

View File

@@ -72,6 +72,10 @@ public class ApplicationConfig {
@Value("${dspace.ui.url:http://localhost:4000}")
private String uiURL;
// LDN enable status
@Value("ldn.enabled")
private boolean ldnEnabled;
/**
* Return the array of allowed origins (client URLs) for the CORS "Access-Control-Allow-Origin" header
* Used by Application class
@@ -130,6 +134,14 @@ public class ApplicationConfig {
return corsAllowCredentials;
}
/**
* Return the ldn.enabled value
* @return true or false
*/
public boolean getLdnEnabled() {
return this.ldnEnabled;
}
/**
* Return whether to allow credentials (cookies) on IIIF requests. This is used to set the
* CORS "Access-Control-Allow-Credentials" header in Application class. Defaults to false.

View File

@@ -20,18 +20,15 @@
<map>
<!-- WARNING do not change "key" it match with Java code (TODO dynamic discover from PATCH operation); -->
<entry key="itemmetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueMovePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueMovePatchOperation"/>
</entry>
<entry key="bitstreammetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueMovePatchOperation">
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueMovePatchOperation">
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
</bean>
</entry>
<entry key="bitstreammove">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamMovePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamMovePatchOperation"/>
</entry>
</map>
</entry>
@@ -39,26 +36,21 @@
<map>
<!-- WARNING do not change "key" it match with Java code (TODO dynamic discover from PATCH operation); -->
<entry key="itemmetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueAddPatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueAddPatchOperation"/>
</entry>
<entry key="bitstreammetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueAddPatchOperation">
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueAddPatchOperation">
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
</bean>
</entry>
<entry key="granted">
<bean
class="org.dspace.app.rest.submit.factory.impl.LicenseAddPatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.LicenseAddPatchOperation"/>
</entry>
<entry key="upload.accessConditions">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyAddPatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyAddPatchOperation"/>
</entry>
<entry key="cclicense/uri">
<bean
class="org.dspace.app.rest.submit.factory.impl.CCLicenseAddPatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.CCLicenseAddPatchOperation"/>
</entry>
<entry key="accessConditions">
<bean class="org.dspace.app.rest.submit.factory.impl.AccessConditionAddPatchOperation"/>
@@ -66,36 +58,33 @@
<entry key="coarnotify">
<bean class="org.dspace.app.rest.submit.factory.impl.NotifyServiceAddPatchOperation"/>
</entry>
<entry key="primary">
<bean class="org.dspace.app.rest.submit.factory.impl.PrimaryBitstreamAddPatchOperation"/>
</entry>
</map>
</entry>
<entry key="remove">
<map>
<!-- WARNING do not change "key" it match with Java code (TODO dynamic discover from PATCH operation); -->
<entry key="itemmetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueRemovePatchOperation" />
<bean class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueRemovePatchOperation" />
</entry>
<entry key="bitstreammetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueRemovePatchOperation">
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueRemovePatchOperation">
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
</bean>
</entry>
<entry key="granted">
<bean
class="org.dspace.app.rest.submit.factory.impl.LicenseRemovePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.LicenseRemovePatchOperation"/>
</entry>
<entry key="bitstreamremove">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamRemovePatchOperation" />
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamRemovePatchOperation" />
</entry>
<entry key="upload.accessConditions">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyRemovePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyRemovePatchOperation"/>
</entry>
<entry key="cclicense/uri">
<bean
class="org.dspace.app.rest.submit.factory.impl.CCLicenseRemovePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.CCLicenseRemovePatchOperation"/>
</entry>
<entry key="accessConditions">
<bean class="org.dspace.app.rest.submit.factory.impl.AccessConditionRemovePatchOperation"/>
@@ -103,32 +92,30 @@
<entry key="coarnotify">
<bean class="org.dspace.app.rest.submit.factory.impl.NotifyServiceRemovePatchOperation"/>
</entry>
<entry key="primary">
<bean class="org.dspace.app.rest.submit.factory.impl.PrimaryBitstreamRemovePatchOperation"/>
</entry>
</map>
</entry>
<entry key="replace">
<map>
<!-- WARNING do not change "key" it match with Java code (TODO dynamic discover from PATCH operation); -->
<entry key="itemmetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueReplacePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueReplacePatchOperation"/>
</entry>
<entry key="bitstreammetadata">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueReplacePatchOperation">
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueReplacePatchOperation">
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
</bean>
</entry>
<entry key="granted">
<bean
class="org.dspace.app.rest.submit.factory.impl.LicenseReplacePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.LicenseReplacePatchOperation"/>
</entry>
<entry key="upload.accessConditions">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyReplacePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyReplacePatchOperation"/>
</entry>
<entry key="collection">
<bean
class="org.dspace.app.rest.submit.factory.impl.CollectionReplacePatchOperation"/>
<bean class="org.dspace.app.rest.submit.factory.impl.CollectionReplacePatchOperation"/>
</entry>
<entry key="discoverable">
<bean class="org.dspace.app.rest.submit.factory.impl.AccessConditionDiscoverableReplacePatchOperation"/>
@@ -139,6 +126,9 @@
<entry key="coarnotify">
<bean class="org.dspace.app.rest.submit.factory.impl.NotifyServiceReplacePatchOperation"/>
</entry>
<entry key="primary">
<bean class="org.dspace.app.rest.submit.factory.impl.PrimaryBitstreamReplacePatchOperation"/>
</entry>
</map>
</entry>
</map>

View File

@@ -59,13 +59,15 @@ public class RorImportMetadataSourceServiceIT extends AbstractLiveImportIntegrat
ImportRecord record = recordsImported.iterator().next();
assertThat(record.getValueList(), hasSize(9));
assertThat(record.getValueList(), hasSize(11));
assertThat(
record.getSingleValue("organization.legalName"),
is("The University of Texas")
);
assertThat(record.getSingleValue("organization.identifier.ror"), is("https://ror.org/02f6dcw23"));
assertThat(record.getSingleValue("organization.alternateName"), is("UTHSCSA"));
assertThat(record.getSingleValue("organization.url"), is("http://www.uthscsa.edu/"));
assertThat(record.getSingleValue("dc.type"), is("Education"));
assertThat(record.getSingleValue("organization.address.addressCountry"), is("US"));
assertThat(record.getSingleValue("organization.foundingDate"), is("1959"));
@@ -116,12 +118,15 @@ public class RorImportMetadataSourceServiceIT extends AbstractLiveImportIntegrat
context.restoreAuthSystemState();
ImportRecord record = rorServiceImpl.getRecord("https://ror.org/01sps7q28");
assertThat(record.getValueList(), hasSize(7));
assertThat(record.getValueList(), hasSize(9));
assertThat(
record.getSingleValue("organization.legalName"),
is("The University of Texas Health Science Center at Tyler")
);
assertThat(record.getSingleValue("organization.identifier.ror"), is("https://ror.org/01sps7q28"));
assertThat(record.getSingleValue("organization.alternateName"), is("UTHSCT"));
assertThat(record.getSingleValue("organization.url"),
is("https://www.utsystem.edu/institutions/university-texas-health-science-center-tyler"));
assertThat(record.getSingleValue("dc.type"), is("Healthcare"));
assertThat(record.getSingleValue("organization.address.addressCountry"), is("US"));
assertThat(record.getSingleValue("organization.foundingDate"), is("1947"));

View File

@@ -8604,9 +8604,9 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
.content("/api/submission/workspaceitems/" + workspaceItem.getID())
.contentType(textUriContentType))
.andExpect(status().isCreated());
}
@Test
public void testSubmissionWithCOARNotifyServicesSection() throws Exception {
@@ -9238,7 +9238,535 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
.andExpect(jsonPath(
"$.errors[?(@.message=='error.validation.coarnotify.invalidfilter')]")
.doesNotExist());
}
@Test
public void patchAddPrimaryTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
AtomicReference<String> idRef = new AtomicReference<String>();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")));
List<Operation> addPrimaryOps = new ArrayList<Operation>();
addPrimaryOps.add(new AddOperation("/sections/upload/primary", idRef.get()));
String patchBody = getPatchContent(addPrimaryOps);
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idRef.get())));
}
@Test
public void patchAddPrimaryBitstreamWithOwnerTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
context.setCurrentUser(eperson);
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
AtomicReference<String> idRef = new AtomicReference<String>();
String tokenSubmitter = getAuthToken(eperson.getEmail(), password);
getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")));
List<Operation> addPrimaryOps = new ArrayList<Operation>();
addPrimaryOps.add(new AddOperation("/sections/upload/primary", idRef.get()));
String patchBody = getPatchContent(addPrimaryOps);
getClient(tokenSubmitter).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idRef.get())));
}
@Test
public void patchAddPrimaryBitstreamWithNotOwnerTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson submitter = EPersonBuilder.createEPerson(context)
.withEmail("test-email@mail.com")
.withPassword(password)
.build();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
context.setCurrentUser(submitter);
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
AtomicReference<String> idRef = new AtomicReference<String>();
String tokenSubmitter = getAuthToken(submitter.getEmail(), password);
getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")));
List<Operation> addPrimaryOps = new ArrayList<Operation>();
addPrimaryOps.add(new AddOperation("/sections/upload/primary", idRef.get()));
String tokenNotSubmitter = getAuthToken(eperson.getEmail(), password);
// non submitter cannot add primary bitstream
getClient(tokenNotSubmitter).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(addPrimaryOps))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isForbidden());
// even anonymous users cannot add primary bitstream
getClient().perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(addPrimaryOps))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isUnauthorized());
getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()));
}
@Test
public void patchAddPrimaryBitstreamUpdateAlredySettedOneTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
InputStream pdf2 = getClass().getResourceAsStream("bibtex-test.bib");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withFulltext("bibtex-test.bib",
"/local/path/bibtex-test.bib", pdf2)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
AtomicReference<String> idFirstPdf = new AtomicReference<String>();
AtomicReference<String> idSecondPdf = new AtomicReference<String>();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idFirstPdf.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")))
.andDo(result -> idSecondPdf.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[1].uuid")));
List<Operation> addPrimaryOps = new ArrayList<Operation>();
addPrimaryOps.add(new AddOperation("/sections/upload/primary", idFirstPdf.get()));
String patchBody = getPatchContent(addPrimaryOps);
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idFirstPdf.get())));
List<Operation> addPrimaryOps2 = new ArrayList<Operation>();
addPrimaryOps2.add(new AddOperation("/sections/upload/primary", idSecondPdf.get()));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(addPrimaryOps2))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idSecondPdf.get())));
}
@Test
public void patchAddPrimaryUUIDofNotExistingBitstreamTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()));
List<Operation> addOperations = new ArrayList<Operation>();
addOperations.add(new AddOperation("/sections/upload/primary", UUID.randomUUID()));
String patchBody = getPatchContent(addOperations);
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isUnprocessableEntity());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()));
}
@Test
public void patchAddPrimaryWrongUUIDTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()));
List<Operation> addOperations = new ArrayList<Operation>();
addOperations.add(new AddOperation("/sections/upload/primary", "wrong-uuid"));
String patchBody = getPatchContent(addOperations);
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isUnprocessableEntity());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()));
}
@Test
public void patchRemovePrimaryTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
AtomicReference<String> idRef = new AtomicReference<String>();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")));
List<Operation> addOperations = new ArrayList<Operation>();
addOperations.add(new AddOperation("/sections/upload/primary", idRef.get()));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(addOperations))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idRef.get())));
List<Operation> removeOps = new ArrayList<Operation>();
removeOps.add(new RemoveOperation("/sections/upload/primary"));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(removeOps))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()));
}
@Test
public void patchReplacePrimaryTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
InputStream pdf2 = getClass().getResourceAsStream("bibtex-test.bib");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withFulltext("bibtex-test.bib",
"/local/path/bibtex-test.bib", pdf2)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
AtomicReference<String> idFirstPdf = new AtomicReference<String>();
AtomicReference<String> idSecondPdf = new AtomicReference<String>();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idFirstPdf.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")))
.andDo(result -> idSecondPdf.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[1].uuid")));
List<Operation> addOperations = new ArrayList<Operation>();
addOperations.add(new AddOperation("/sections/upload/primary", idFirstPdf.get()));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(addOperations))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idFirstPdf.get())));
List<Operation> replaceOperations = new ArrayList<Operation>();
replaceOperations.add(new ReplaceOperation("/sections/upload/primary", idSecondPdf.get()));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(replaceOperations))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idSecondPdf.get())));
}
@Test
public void patchReplacePrimaryWhenPrimariIsUnsetTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
InputStream pdf2 = getClass().getResourceAsStream("bibtex-test.bib");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.withSubject("testEntry")
.build();
context.restoreAuthSystemState();
AtomicReference<String> idPdf = new AtomicReference<String>();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idPdf.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")));
List<Operation> replaceOperations = new ArrayList<Operation>();
replaceOperations.add(new ReplaceOperation("/sections/upload/primary", idPdf.get()));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(replaceOperations))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isUnprocessableEntity());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()));
}
@Test
public void patchReplaceProvidingWrongPrimaryTest() throws Exception {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1")
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.withTitle("TITLE test")
.withIssueDate("2023-10-18")
.withFulltext("simple-article.pdf",
"/local/path/simple-article.pdf", pdf)
.build();
context.restoreAuthSystemState();
AtomicReference<String> idFirstPdf = new AtomicReference<String>();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", nullValue()))
.andDo(result -> idFirstPdf.set(read(result.getResponse().getContentAsString(),
"$.sections.upload.files[0].uuid")));
List<Operation> addOperations = new ArrayList<Operation>();
addOperations.add(new AddOperation("/sections/upload/primary", idFirstPdf.get()));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(addOperations))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idFirstPdf.get())));
List<Operation> replaceOperations = new ArrayList<Operation>();
replaceOperations.add(new ReplaceOperation("/sections/upload/primary", UUID.randomUUID()));
getClient(tokenAdmin).perform(patch("/api/submission/workspaceitems/" + witem.getID())
.content(getPatchContent(replaceOperations))
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isUnprocessableEntity());
getClient(tokenAdmin).perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.primary", is(idFirstPdf.get())));
}
}

View File

@@ -457,6 +457,13 @@
</oaire:funderIdentifier>
</xsl:template>
<!-- This template creates the sub-element <oaire:funderIdentifier> from a Funded Project built entity -->
<xsl:template match="doc:field[starts-with(@name,'project.funder.rorIdentifier')]" mode="entity_funding">
<oaire:funderIdentifier funderIdentifierType="ROR" schemeURI="http://ror.org/">
<xsl:value-of select="./text()"/>
</oaire:funderIdentifier>
</xsl:template>
<!-- This template creates the sub-element <oaire:fundingStream> from a Funded Project built entity -->
<xsl:template match="doc:field[starts-with(@name,'oaire.fundingStream')]" mode="entity_funding">
<oaire:fundingStream>

View File

@@ -15,7 +15,7 @@ iiif.image.server = http://localhost:8182/iiif/2/
# The search plugin used to support (experimental) IIIF Search.
# This is the class used with https://dbmdz.github.io/solr-ocrhighlighting/
# It is currently the only supported option.
# iiif.search.plugin = org.dspace.app.rest.iiif.service.WordHighlightSolrSearch
# iiif.search.plugin = org.dspace.app.iiif.service.WordHighlightSolrSearch
# Sets the viewing hint. Possible values: "paged" or "individuals".
# Typically "paged" is preferred for multi-age documents. Use "individuals"

View File

@@ -111,6 +111,7 @@ orcid.mapping.organization.city = organization.address.addressLocality
orcid.mapping.organization.identifiers = organization.identifier.crossrefid::FUNDREF
orcid.mapping.organization.identifiers = organization.identifier.rin::RINGGOLD
orcid.mapping.organization.identifiers = organization.identifier.lei::LEI
orcid.mapping.organization.identifiers = organization.identifier.ror::ROR
### Contributor mapping ###
orcid.mapping.contributor.email = person.email
@@ -128,6 +129,7 @@ orcid.validation.organization.identifier-sources = RINGGOLD
orcid.validation.organization.identifier-sources = GRID
orcid.validation.organization.identifier-sources = FUNDREF
orcid.validation.organization.identifier-sources = LEI
orcid.validation.organization.identifier-sources = ROR
#------------------------------------------------------------------#
#---------------------ORCID BULK SYNCHRONIZATION-------------------#

View File

@@ -86,6 +86,18 @@
<element>parentOrganization</element>
<scope_note>The larger organization that this organization is a subOrganization of, if any.</scope_note>
</dc-type>
<dc-type>
<schema>organization</schema>
<element>alternateName</element>
<scope_note>An alias for the organization.</scope_note>
</dc-type>
<dc-type>
<schema>organization</schema>
<element>url</element>
<scope_note>Url of the organization.</scope_note>
</dc-type>
</dspace-dc-types>

View File

@@ -14,7 +14,9 @@
<util:map id="rorMetadataFieldMap" key-type="org.dspace.importer.external.metadatamapping.MetadataFieldConfig" value-type="org.dspace.importer.external.metadatamapping.contributor.MetadataContributor">
<entry key-ref="ror.title" value-ref="rorTitleContrib"/>
<entry key-ref="ror.identifier" value-ref="rorIdentifierContrib"/>
<entry key-ref="ror.links" value-ref="rorLinksContrib"/>
<entry key-ref="ror.types" value-ref="rorTypesContrib"/>
<entry key-ref="ror.acronym" value-ref="rorAcronymContrib"/>
<entry key-ref="ror.country" value-ref="rorCountryContrib"/>
<entry key-ref="ror.established" value-ref="rorEstablishedContrib"/>
<entry key-ref="ror.fundref" value-ref="rorFundRefContrib"/>
@@ -38,6 +40,22 @@
<constructor-arg value="organization.identifier.ror"/>
</bean>
<bean id="rorAcronymContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="ror.acronym"/>
<property name="query" value="/acronyms"/>
</bean>
<bean id="ror.acronym" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="organization.alternateName"/>
</bean>
<bean id="rorLinksContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="ror.links"/>
<property name="query" value="/links"/>
</bean>
<bean id="ror.links" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="organization.url"/>
</bean>
<bean id="rorTypesContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="ror.types"/>
<property name="query" value="/types"/>

View File

@@ -167,6 +167,7 @@
<entry key="oaire.awardTitle" value-ref="publicationProject_name"/>
<entry key="project.funder.name" value-ref="publicationProject_projectFunderName_related"/>
<entry key="project.funder.identifier" value-ref="publicationProject_projectFunderId_related"/>
<entry key="project.funder.rorIdentifier" value-ref="publicationProject_projectRorId_related"/>
</util:map>
<bean class="org.dspace.content.virtual.Collected" id="publicationProject_name">
<property name="fields">
@@ -208,7 +209,13 @@
<property name="relationshipTypeString" value="isFundingAgencyOfProject"/>
<property name="virtualMetadataConfiguration" ref="projectOrgUnit_orgId"/>
</bean>
<bean class="org.dspace.content.virtual.Related" id="publicationProject_projectRorId_related">
<property name="relationshipTypeString" value="isProjectOfFundingAgency"/>
<property name="place" value="0"/>
<property name="virtualMetadataConfiguration" ref="projectOrgUnit_rorId"/>
</bean>
<!-- Config like this will tell our VirtualMetadataPopulator to include the virtual metadata field
'project.funder.*' on the appropriate item with the values defined in the value-ref.
This value-ref should be a bean of type VirtualMetadataConfiguration -->
@@ -231,4 +238,11 @@
</util:list>
</property>
</bean>
<bean class="org.dspace.content.virtual.Collected" id="projectOrgUnit_rorId">
<property name="fields">
<util:list>
<value>organization.identifier.ror</value>
</util:list>
</property>
</bean>
</beans>