diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImport.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImport.java index 6b1e6d42a095..ba348be0fe4b 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImport.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImport.java @@ -258,7 +258,7 @@ public void setup() throws ParseException { collectionId = commandLine.getOptionValue('c'); filename = commandLine.getOptionValue('f'); - if (commandLine.hasOption('e')) { + if (commandLine.hasOption("er")) { abortOnError = true; } } @@ -266,11 +266,9 @@ public void setup() throws ParseException { @Override public void internalRun() throws Exception { context = new Context(Context.Mode.BATCH_EDIT); - assignCurrentUserInContext(); + assignCurrentUserInContext(context); assignSpecialGroupsInContext(); - context.turnOffAuthorisationSystem(); - InputStream inputStream = handler.getFileStream(context, filename) .orElseThrow(() -> new IllegalArgumentException("Error reading file, the file couldn't be " + "found for filename: " + filename)); @@ -285,6 +283,7 @@ public void internalRun() throws Exception { } try { + context.turnOffAuthorisationSystem(); performImport(inputStream); context.complete(); context.restoreAuthSystemState(); @@ -1604,7 +1603,7 @@ private void rollback() { } } - private void assignCurrentUserInContext() throws SQLException { + protected void assignCurrentUserInContext(Context context) throws SQLException, ParseException { UUID uuid = getEpersonIdentifier(); if (uuid != null) { EPerson ePerson = EPersonServiceFactory.getInstance().getEPersonService().find(context, uuid); diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCli.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCli.java index 36da59c7a252..c1399c61413b 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCli.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCli.java @@ -7,6 +7,13 @@ */ package org.dspace.app.bulkedit; +import java.sql.SQLException; + +import org.apache.commons.cli.ParseException; +import org.dspace.core.Context; +import org.dspace.eperson.EPerson; +import org.dspace.eperson.factory.EPersonServiceFactory; + /** * Extension of {@link BulkImport} for CLI. * @@ -15,4 +22,24 @@ */ public class BulkImportCli extends BulkImport { + @Override + protected void assignCurrentUserInContext(Context context) throws ParseException { + if (commandLine.hasOption('e')) { + String ePersonEmail = commandLine.getOptionValue('e'); + try { + EPerson ePerson = + EPersonServiceFactory.getInstance().getEPersonService().findByEmail(context, ePersonEmail); + if (ePerson == null) { + super.handler.logError("EPerson not found: " + ePersonEmail); + throw new IllegalArgumentException("Unable to find a user with email: " + ePersonEmail); + } + context.setCurrentUser(ePerson); + } catch (SQLException e) { + throw new IllegalArgumentException("SQLException trying to find user with email: " + ePersonEmail); + } + } else { + throw new ParseException("Required parameter -e missing!"); + } + } + } diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCliScriptConfiguration.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCliScriptConfiguration.java index f79c03e041e2..5e34f6a58464 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCliScriptConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportCliScriptConfiguration.java @@ -7,6 +7,8 @@ */ package org.dspace.app.bulkedit; +import org.apache.commons.cli.Options; + /** * Extension of {@link BulkImportScriptConfiguration} for CLI. * @@ -15,5 +17,13 @@ */ public class BulkImportCliScriptConfiguration extends BulkImportScriptConfiguration { + @Override + public Options getOptions() { + Options options = super.getOptions(); + options.addOption("e", "email", true, "email address of user"); + options.getOption("e").setRequired(true); + super.options = options; + return options; + } } diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportScriptConfiguration.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportScriptConfiguration.java index e2fd7bacd0e1..3530687bf36f 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportScriptConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkImportScriptConfiguration.java @@ -52,9 +52,9 @@ public Options getOptions() { options.getOption("f").setType(InputStream.class); options.getOption("f").setRequired(true); - options.addOption("e", "concludeOnError", false, "conclude the import at the first error"); - options.getOption("e").setType(boolean.class); - options.getOption("e").setRequired(false); + options.addOption("er", "concludeOnError", false, "conclude the import at the first error"); + options.getOption("er").setType(boolean.class); + options.getOption("er").setRequired(false); super.options = options; } diff --git a/dspace-api/src/main/java/org/dspace/app/deduplication/service/impl/SolrDedupServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/deduplication/service/impl/SolrDedupServiceImpl.java index 6f719ff85f2c..cc5c0f2bc861 100644 --- a/dspace-api/src/main/java/org/dspace/app/deduplication/service/impl/SolrDedupServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/deduplication/service/impl/SolrDedupServiceImpl.java @@ -314,6 +314,22 @@ private void fillSignature(Context ctx, DSpaceObject iu, Map plainSignatures = algo.getPlainSignature(iu, ctx); + for (String signature : plainSignatures) { + if (StringUtils.isNotEmpty(signature)) { + String key = "plain_" + algo.getSignatureType() + "_signature"; + if (tmpMapFilter.containsKey(key)) { + List obj = tmpMapFilter.get(key); + obj.add(signature); + tmpMapFilter.put(key, obj); + } else { + List obj = new ArrayList(); + obj.add(signature); + tmpMapFilter.put(key, obj); + } + } + } } } diff --git a/dspace-api/src/main/java/org/dspace/app/deduplication/utils/MD5ValueSignature.java b/dspace-api/src/main/java/org/dspace/app/deduplication/utils/MD5ValueSignature.java index 8b047584bc1b..aacc7aa9ae0e 100644 --- a/dspace-api/src/main/java/org/dspace/app/deduplication/utils/MD5ValueSignature.java +++ b/dspace-api/src/main/java/org/dspace/app/deduplication/utils/MD5ValueSignature.java @@ -6,6 +6,7 @@ * http://www.dspace.org/license/ */ package org.dspace.app.deduplication.utils; + import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -13,6 +14,7 @@ import java.util.List; import java.util.Locale; import java.util.Objects; +import java.util.stream.Collectors; import com.ibm.icu.text.CharsetDetector; import com.ibm.icu.text.CharsetMatch; @@ -22,12 +24,15 @@ import org.apache.logging.log4j.Logger; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataFieldName; import org.dspace.content.MetadataValue; import org.dspace.content.WorkspaceItem; +import org.dspace.content.dto.MetadataValueDTO; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; import org.dspace.content.service.WorkspaceItemService; import org.dspace.core.Context; +import org.dspace.external.model.ExternalDataObject; import org.dspace.workflow.WorkflowItem; import org.dspace.workflow.WorkflowItemService; import org.dspace.workflow.factory.WorkflowServiceFactory; @@ -95,6 +100,37 @@ public List getSignature(DSpaceObject item, Context context) { } } + public List getPlainSignature(DSpaceObject item, Context context) { + List result = new ArrayList(); + try { + MessageDigest digester = MessageDigest.getInstance("MD5"); + List values = getMultiValue(item, metadata); + if (values != null) { + for (String value : values) { + if (StringUtils.isNotEmpty(value)) { + String valueNorm = normalize(item, value); + digester.update(valueNorm.getBytes("UTF-8")); + byte[] signature = digester.digest(); + char[] arr = new char[signature.length << 1]; + for (int i = 0; i < signature.length; i++) { + int b = signature[i]; + int idx = i << 1; + arr[idx] = HEX_DIGITS[(b >> 4) & 0xf]; + arr[idx + 1] = HEX_DIGITS[b & 0xf]; + } + String sigString = new String(arr); + result.add(sigString); + } + } + } + return result; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + protected String normalize(DSpaceObject item, Context context, String value) { if (value != null) { String temp = StringUtils.EMPTY; @@ -210,6 +246,70 @@ protected List getMultiValue(DSpaceObject item, String metadata) { return retValue; } + public List getSignature(ExternalDataObject object) { + List result = new ArrayList(); + try { + MessageDigest digester = MessageDigest.getInstance("MD5"); + List values = getMultiValue(object, metadata); + if (values != null) { + for (String value : values) { + if (StringUtils.isNotEmpty(value)) { + String valueNorm = normalize(object, value); + digester.update(valueNorm.getBytes("UTF-8")); + byte[] signature = digester.digest(); + char[] arr = new char[signature.length << 1]; + for (int i = 0; i < signature.length; i++) { + int b = signature[i]; + int idx = i << 1; + arr[idx] = HEX_DIGITS[(b >> 4) & 0xf]; + arr[idx + 1] = HEX_DIGITS[b & 0xf]; + } + String sigString = new String(arr); + result.add(sigString); + } + } + } + return result; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + protected List getMultiValue(ExternalDataObject object, String metadata) { + return object.getMetadata() + .stream() + .filter(metadataValueDTO -> + new MetadataFieldName(metadataValueDTO.getSchema(), metadataValueDTO.getElement(), + metadataValueDTO.getQualifier()).toString().equals(metadata)) + .map(MetadataValueDTO::getValue) + .collect(Collectors.toList()); + } + + protected String normalize(ExternalDataObject object, String value) { + String result = value; + if (StringUtils.isEmpty(value)) { + if (StringUtils.isNotEmpty(prefix)) { + result = prefix + object.getId(); + } else { + result = "entity:" + object.getId(); + } + } else { + for (String prefix : ignorePrefix) { + if (value.startsWith(prefix)) { + result = value.substring(prefix.length()); + break; + } + } + if (StringUtils.isNotEmpty(prefix)) { + result = prefix + result; + } + } + + return result; + } + public String getMetadata() { return metadata; } diff --git a/dspace-api/src/main/java/org/dspace/app/deduplication/utils/Signature.java b/dspace-api/src/main/java/org/dspace/app/deduplication/utils/Signature.java index 2bf662b39d75..81a0fb228911 100644 --- a/dspace-api/src/main/java/org/dspace/app/deduplication/utils/Signature.java +++ b/dspace-api/src/main/java/org/dspace/app/deduplication/utils/Signature.java @@ -11,10 +11,15 @@ import org.dspace.content.DSpaceObject; import org.dspace.core.Context; +import org.dspace.external.model.ExternalDataObject; public interface Signature { public List getSignature(/* BrowsableDSpaceObject */DSpaceObject item, Context context); + public List getPlainSignature(DSpaceObject item, Context context); + + public List getSignature(ExternalDataObject object); + public int getResourceTypeID(); public String getSignatureType(); diff --git a/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java b/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java index f5d88e1045ee..a83cc8692e31 100644 --- a/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java +++ b/dspace-api/src/main/java/org/dspace/authority/CrisConsumer.java @@ -193,7 +193,7 @@ private boolean isMetadataSkippable(MetadataValue metadata) { return true; } - if (isBlank(authority) && isMetadataWithEmptyAuthoritySkippable(metadata)) { + if (isBlank(authority) && (isBlank(metadata.getValue()) || isMetadataWithEmptyAuthoritySkippable(metadata))) { return true; } diff --git a/dspace-api/src/main/java/org/dspace/authority/filler/ExternalDataProviderImportFiller.java b/dspace-api/src/main/java/org/dspace/authority/filler/ExternalDataProviderImportFiller.java index ef218c76fb34..7a7d10e63499 100644 --- a/dspace-api/src/main/java/org/dspace/authority/filler/ExternalDataProviderImportFiller.java +++ b/dspace-api/src/main/java/org/dspace/authority/filler/ExternalDataProviderImportFiller.java @@ -7,7 +7,6 @@ */ package org.dspace.authority.filler; -import static org.apache.commons.collections.CollectionUtils.isEmpty; import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.removeStart; import static org.apache.commons.lang3.StringUtils.startsWith; @@ -110,7 +109,11 @@ private void enrichItemWithExternalData(Context context, Item item, ExternalData } private boolean notAlreadyPresent(Item item, MetadataValueDTO value) { - return isEmpty(itemService.getMetadata(item, value.getSchema(), value.getElement(), value.getQualifier(), ANY)); + List metadataValues = itemService.getMetadata(item, value.getSchema(), + value.getElement(), value.getQualifier(), ANY); + + return metadataValues.stream().noneMatch(metadataValue -> + metadataValue.getValue().equals(value.getValue())); } private boolean isTitleNotSet(Item item) { diff --git a/dspace-api/src/main/java/org/dspace/core/CrisConstants.java b/dspace-api/src/main/java/org/dspace/core/CrisConstants.java index 18def2d10316..5bce199cfd76 100644 --- a/dspace-api/src/main/java/org/dspace/core/CrisConstants.java +++ b/dspace-api/src/main/java/org/dspace/core/CrisConstants.java @@ -21,7 +21,7 @@ public class CrisConstants { * same number than the parent leading metadata */ public static final String PLACEHOLDER_PARENT_METADATA_VALUE = "#PLACEHOLDER_PARENT_METADATA_VALUE#"; - + public static final String DSPACE_BASE_VERSION = "DSpace 7.5"; public static final MetadataFieldName MD_ENTITY_TYPE = new MetadataFieldName("dspace", "entity", "type"); public static final MetadataFieldName MD_SUBMISSION_TYPE = new MetadataFieldName("cris", "submission", "definition"); diff --git a/dspace-api/src/main/java/org/dspace/external/model/ExternalDataObject.java b/dspace-api/src/main/java/org/dspace/external/model/ExternalDataObject.java index eac9921df6cc..44ad6a70953e 100644 --- a/dspace-api/src/main/java/org/dspace/external/model/ExternalDataObject.java +++ b/dspace-api/src/main/java/org/dspace/external/model/ExternalDataObject.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; import org.dspace.content.dto.MetadataValueDTO; @@ -38,6 +39,8 @@ public class ExternalDataObject { */ private String displayValue; + private List matchUUIDs; + /** * Default constructor */ @@ -143,4 +146,16 @@ public String getValue() { public void setValue(String value) { this.value = value; } + + public List getMatchUUIDs() { + return matchUUIDs; + } + + public void setMatchUUIDs(List matchUUIDs) { + this.matchUUIDs = matchUUIDs; + } + + public boolean isDuplicated() { + return !matchUUIDs.isEmpty(); + } } diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java index 7a836113936c..a07cf89c503e 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -27,6 +28,7 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.content.MetadataFieldName; import org.dspace.content.dto.MetadataValueDTO; import org.dspace.external.OrcidRestConnector; import org.dspace.external.model.ExternalDataObject; @@ -35,6 +37,7 @@ import org.json.JSONObject; import org.orcid.jaxb.model.v3.release.common.OrcidIdentifier; import org.orcid.jaxb.model.v3.release.record.Person; +import org.orcid.jaxb.model.v3.release.record.Record; import org.orcid.jaxb.model.v3.release.search.Result; import org.springframework.beans.factory.annotation.Autowired; @@ -60,6 +63,8 @@ public class OrcidV3AuthorDataProvider extends AbstractExternalDataProvider { private XMLtoBio converter; + private Map externalIdentifiers; + public static final String ORCID_ID_SYNTAX = "\\d{4}-\\d{4}-\\d{4}-(\\d{3}X|\\d{4})"; private static final int MAX_INDEX = 10000; @@ -113,12 +118,13 @@ public void init() throws IOException { @Override public Optional getExternalDataObject(String id) { - Person person = getBio(id); - ExternalDataObject externalDataObject = convertToExternalDataObject(person); + Record record = getBio(id); + ExternalDataObject externalDataObject = convertToExternalDataObject(record); return Optional.of(externalDataObject); } - protected ExternalDataObject convertToExternalDataObject(Person person) { + protected ExternalDataObject convertToExternalDataObject(Record record) { + Person person = record.getPerson(); ExternalDataObject externalDataObject = new ExternalDataObject(sourceIdentifier); if (person.getName() != null) { String lastName = ""; @@ -141,6 +147,12 @@ protected ExternalDataObject convertToExternalDataObject(Person person) { externalDataObject .addMetadata(new MetadataValueDTO("dc", "identifier", "uri", null, orcidUrl + '/' + person.getName().getPath())); + + appendOtherNames(externalDataObject, person); + appendResearcherUrls(externalDataObject, person); + appendExternalIdentifiers(externalDataObject, person); + appendAffiliations(externalDataObject, record); + if (!StringUtils.isBlank(lastName) && !StringUtils.isBlank(firstName)) { externalDataObject.setDisplayValue(lastName + ", " + firstName); externalDataObject.setValue(lastName + ", " + firstName); @@ -157,24 +169,64 @@ protected ExternalDataObject convertToExternalDataObject(Person person) { return externalDataObject; } + private void appendOtherNames(ExternalDataObject externalDataObject, Person person) { + person.getOtherNames().getOtherNames().forEach(otherName -> + externalDataObject.addMetadata(new MetadataValueDTO("crisrp", "name", "variant", null, + otherName.getContent()))); + } + + private void appendResearcherUrls(ExternalDataObject externalDataObject, Person person) { + person.getResearcherUrls().getResearcherUrls().forEach(researcherUrl -> + externalDataObject.addMetadata(new MetadataValueDTO("oairecerif", "identifier", "url", null, + researcherUrl.getUrl().getValue()))); + } + + private void appendExternalIdentifiers(ExternalDataObject externalDataObject, Person person) { + if (getExternalIdentifiers() != null) { + person.getExternalIdentifiers() + .getExternalIdentifiers() + .forEach(externalIdentifier -> { + String metadataField = externalIdentifiers.get(externalIdentifier.getType()); + if (StringUtils.isNotEmpty(metadataField)) { + MetadataFieldName field = new MetadataFieldName(metadataField); + externalDataObject.addMetadata( + new MetadataValueDTO(field.schema, field.element, field.qualifier, null, + externalIdentifier.getValue())); + } + }); + } + } + + private void appendAffiliations(ExternalDataObject externalDataObject, Record record) { + record.getActivitiesSummary() + .getEmployments() + .getEmploymentGroups() + .stream() + .flatMap(affiliationGroup -> + affiliationGroup.getActivities().stream()) + .forEach(employmentSummary -> + externalDataObject.addMetadata(new MetadataValueDTO("person", "affiliation", "name", + null, employmentSummary.getOrganization().getName()))); + } + /** - * Retrieve a Person object based on a given orcid identifier. + * Retrieve a Record object based on a given orcid identifier. * @param id orcid identifier - * @return Person + * @return Record */ - public Person getBio(String id) { + public Record getBio(String id) { log.debug("getBio called with ID=" + id); if (!isValid(id)) { return null; } - InputStream bioDocument = orcidRestConnector.get(id + ((id.endsWith("/person")) ? "" : "/person"), accessToken); - Person person = converter.convertSinglePerson(bioDocument); + InputStream bioDocument = orcidRestConnector.get(id, accessToken); + Record record = converter.convertToRecord(bioDocument); try { bioDocument.close(); } catch (IOException e) { log.error(e.getMessage(), e); } - return person; + return record; } /** @@ -201,13 +253,13 @@ public List searchExternalDataObjects(String query, int star log.debug("queryBio searchPath=" + searchPath + " accessToken=" + accessToken); InputStream bioDocument = orcidRestConnector.get(searchPath, accessToken); List results = converter.convert(bioDocument); - List bios = new LinkedList<>(); + List bios = new LinkedList<>(); for (Result result : results) { OrcidIdentifier orcidIdentifier = result.getOrcidIdentifier(); if (orcidIdentifier != null) { log.debug("Found OrcidId=" + orcidIdentifier.toString()); String orcid = orcidIdentifier.getPath(); - Person bio = getBio(orcid); + Record bio = getBio(orcid); if (bio != null) { bios.add(bio); } @@ -298,4 +350,11 @@ public void setOrcidRestConnector(OrcidRestConnector orcidRestConnector) { this.orcidRestConnector = orcidRestConnector; } + public Map getExternalIdentifiers() { + return externalIdentifiers; + } + + public void setExternalIdentifiers(Map externalIdentifiers) { + this.externalIdentifiers = externalIdentifiers; + } } diff --git a/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/XMLtoBio.java b/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/XMLtoBio.java index 25b3cf787feb..ff7cedbb47ab 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/XMLtoBio.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/orcid/xml/XMLtoBio.java @@ -14,6 +14,7 @@ import org.apache.logging.log4j.Logger; import org.orcid.jaxb.model.v3.release.record.Person; +import org.orcid.jaxb.model.v3.release.record.Record; import org.orcid.jaxb.model.v3.release.search.Result; import org.orcid.jaxb.model.v3.release.search.Search; import org.xml.sax.SAXException; @@ -64,4 +65,15 @@ public Person convertSinglePerson(InputStream xml) { } return null; } + + public Record convertToRecord(InputStream xml) { + Record record = null; + try { + record = (Record) unmarshall(xml, Record.class); + return record; + } catch (SAXException | URISyntaxException e) { + log.error(e); + } + return record; + } } diff --git a/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java b/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java index 7804dfa5689f..76e4fff4f527 100644 --- a/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java @@ -7,12 +7,24 @@ */ package org.dspace.external.service.impl; +import static org.dspace.app.deduplication.service.impl.SolrDedupServiceImpl.RESOURCE_FLAG_FIELD; +import static org.dspace.app.deduplication.service.impl.SolrDedupServiceImpl.RESOURCE_IDS_FIELD; +import static org.dspace.app.deduplication.service.impl.SolrDedupServiceImpl.RESOURCE_SIGNATURE_FIELD; + import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.UUID; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.common.SolrDocument; +import org.dspace.app.deduplication.service.DedupService; +import org.dspace.app.deduplication.service.impl.SolrDedupServiceImpl; +import org.dspace.app.deduplication.utils.Signature; import org.dspace.app.suggestion.SuggestionProvider; import org.dspace.app.suggestion.SuggestionService; import org.dspace.authorize.AuthorizeException; @@ -22,11 +34,14 @@ import org.dspace.content.dto.MetadataValueDTO; import org.dspace.content.service.ItemService; import org.dspace.content.service.WorkspaceItemService; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogHelper; +import org.dspace.discovery.SearchServiceException; import org.dspace.external.model.ExternalDataObject; import org.dspace.external.provider.ExternalDataProvider; import org.dspace.external.service.ExternalDataService; +import org.dspace.utils.DSpace; import org.springframework.beans.factory.annotation.Autowired; /** @@ -49,6 +64,9 @@ public class ExternalDataServiceImpl implements ExternalDataService { @Autowired private SuggestionService suggestionService; + @Autowired + private DedupService dedupService; + @Override public Optional getExternalDataObject(String source, String id) { ExternalDataProvider provider = getExternalDataProvider(source); @@ -64,9 +82,53 @@ public List searchExternalDataObjects(String source, String if (provider == null) { throw new IllegalArgumentException("Provider for: " + source + " couldn't be found"); } - return provider.searchExternalDataObjects(query, start, limit); + + List externalDataObjects = provider.searchExternalDataObjects(query, start, limit); + appendMatchedUUIDs(externalDataObjects); + + return externalDataObjects; + } + + private void appendMatchedUUIDs(List externalDataObjects) { + for (ExternalDataObject externalDataObject : externalDataObjects) { + List uuids = new ArrayList<>(); + try { + QueryResponse response = dedupService.find("*:*", buildFilters(externalDataObject)); + for (SolrDocument resultDoc : response.getResults()) { + uuids.addAll(resultDoc.getFieldValues(RESOURCE_IDS_FIELD) + .stream() + .map(id -> + UUID.fromString(String.valueOf(id))) + .collect(Collectors.toList())); + } + externalDataObject.setMatchUUIDs(uuids); + } catch (SearchServiceException e) { + throw new RuntimeException(e); + } + } + } + + private String[] buildFilters(ExternalDataObject object) { + List filters = new ArrayList<>(); + List allSignatures = getAllSignatures(object); + + if (!allSignatures.isEmpty()) { + filters.add(RESOURCE_FLAG_FIELD + ":" + SolrDedupServiceImpl.DeduplicationFlag.FAKE.getDescription()); + filters.add(RESOURCE_SIGNATURE_FIELD + ":(" + + StringUtils.joinWith(" OR ", allSignatures.stream().toArray(String[]::new)) + ")"); + } + + return filters.toArray(new String[filters.size()]); } + private List getAllSignatures(ExternalDataObject iu) { + List signAlgo = new DSpace().getServiceManager().getServicesByType(Signature.class); + return signAlgo.stream() + .filter(algo -> Constants.ITEM == algo.getResourceTypeID()) + .flatMap(algo -> algo.getSignature(iu).stream()) + .filter(signature -> StringUtils.isNotEmpty(signature)) + .collect(Collectors.toList()); + } @Override public List getExternalDataProviders() { diff --git a/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java index 0014088c8650..4b6a5aa92e72 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java @@ -117,4 +117,9 @@ public void setMetadataFieldMap(@SuppressWarnings("rawtypes") Map metadataFieldM super.setMetadataFieldMap(metadataFieldMap); } + @Override + public boolean canImportMultipleRecords() { + return true; + } + } diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java b/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java index 28df30b345bc..a444a3609c15 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/ImportService.java @@ -311,7 +311,7 @@ public boolean canImportFromFile(String originalName) { /* * Get a collection of record from File, * The first match will be return. - * + * * @param file The file from which will read records * @param originalName The original file name or full path * @return a single record contains the metadatum @@ -319,28 +319,83 @@ public boolean canImportFromFile(String originalName) { */ public ImportRecord getRecord(File file, String originalName) throws FileMultipleOccurencesException, FileSourceException { - ImportRecord importRecords = null; - for (MetadataSource metadataSource : importSources.values()) { - try (InputStream fileInputStream = new FileInputStream(file)) { - if (metadataSource instanceof FileSource) { - FileSource fileSource = (FileSource)metadataSource; - if (fileSource.isValidSourceForFile(originalName)) { - importRecords = fileSource.getRecord(fileInputStream); - break; + try (InputStream fileInputStream = new FileInputStream(file)) { + FileSource fileSource = this.getFileSource(fileInputStream, originalName); + try { + if (fileSource.isValidSourceForFile(originalName)) { + return fileSource.getRecord(fileInputStream); + } + } catch (FileSourceException e) { + log.debug(fileSource.getImportSource() + " isn't a valid parser for file", e); + } + //catch statements is required because we could have supported format (i.e. XML) + //which fail on schema validation + } catch (FileMultipleOccurencesException e) { + log.debug("File contains multiple metadata, return with error"); + throw e; + } catch (IOException e1) { + throw new FileSourceException("File cannot be read, may be null"); + } + return null; + } + + /** + * Get a collection of record from File, + * + * @param file The file from which will read records + * @param originalName The original file name or full path + * @return records containing metdatum + * @throws FileMultipleOccurencesException if the import configured for the {@code file} + * doesn't allow multiple records import. + * @throws FileSourceException if the file cannot be read. + */ + public List getRecords(File file, String originalName) + throws FileMultipleOccurencesException, FileSourceException { + try (InputStream fileInputStream = new FileInputStream(file)) { + FileSource fileSource = this.getFileSource(fileInputStream, originalName); + try { + if (fileSource.isValidSourceForFile(originalName)) { + List records = fileSource.getRecords(fileInputStream); + if (!fileSource.canImportMultipleRecords() && records.size() > 1) { + throw new FileMultipleOccurencesException( + "Found " + records.size() + " entries in file ( " + + originalName + + " ) but import source ( " + + fileSource.getImportSource() + + " ) not allowed to import multiple records" + ); } + return records; } + } catch (FileSourceException e) { + log.debug(fileSource.getImportSource() + " isn't a valid parser for file", e); + } //catch statements is required because we could have supported format (i.e. XML) //which fail on schema validation - } catch (FileSourceException e) { - log.debug(metadataSource.getImportSource() + " isn't a valid parser for file"); - } catch (FileMultipleOccurencesException e) { - log.debug("File contains multiple metadata, return with error"); - throw e; - } catch (IOException e1) { - throw new FileSourceException("File cannot be read, may be null"); + } catch (IOException e1) { + throw new FileSourceException("File cannot be read, may be null"); + } + return null; + } + + protected FileSource getFileSource(File file, String originalName) throws FileSourceException { + try (InputStream fileInputStream = new FileInputStream(file)) { + return getFileSource(file, originalName); + } catch (IOException e1) { + throw new FileSourceException("File cannot be read, may be null"); + } + } + + protected FileSource getFileSource(InputStream fileInputStream, String originalName) { + for (MetadataSource metadataSource : importSources.values()) { + if (metadataSource instanceof FileSource) { + FileSource fileSource = (FileSource)metadataSource; + if (fileSource.isValidSourceForFile(originalName)) { + return fileSource; + } } } - return importRecords; + return null; } /** diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractPlainMetadataSource.java b/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractPlainMetadataSource.java index 5d83b9a7cce4..b58f69b6665c 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractPlainMetadataSource.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/components/AbstractPlainMetadataSource.java @@ -41,7 +41,7 @@ public abstract class AbstractPlainMetadataSource /** * Set the file extensions supported by this metadata service - * + * * @param supportedExtensions the file extensions (xml,txt,...) supported by this service */ public void setSupportedExtensions(List supportedExtensions) { @@ -64,6 +64,9 @@ public List getSupportedExtensions() { @Override public List getRecords(InputStream is) throws FileSourceException { List datas = readData(is); + if (datas == null) { + return List.of(); + } List records = new ArrayList<>(); for (PlainMetadataSourceDto item : datas) { records.add(toRecord(item)); diff --git a/dspace-api/src/main/java/org/dspace/importer/external/service/components/FileSource.java b/dspace-api/src/main/java/org/dspace/importer/external/service/components/FileSource.java index 801f5474bb4e..fffd476a69ee 100644 --- a/dspace-api/src/main/java/org/dspace/importer/external/service/components/FileSource.java +++ b/dspace-api/src/main/java/org/dspace/importer/external/service/components/FileSource.java @@ -52,7 +52,7 @@ public ImportRecord getRecord(InputStream inputStream) /** * This method is used to decide if the FileSource manage the file format - * + * * @param originalName the file file original name * @return true if the FileSource can parse the file, false otherwise */ @@ -67,4 +67,13 @@ public default boolean isValidSourceForFile(String originalName) { return false; } + /** + * This method is used to determine if we can import multiple records at once placed in the same source file. + * + * @return true if allowed to import multiple records in the same file, false otherwise + */ + public default boolean canImportMultipleRecords() { + return false; + } + } diff --git a/dspace-api/src/main/java/org/dspace/metrics/MetricsExternalServices.java b/dspace-api/src/main/java/org/dspace/metrics/MetricsExternalServices.java index b680e43eeab7..79543f43ce1e 100644 --- a/dspace-api/src/main/java/org/dspace/metrics/MetricsExternalServices.java +++ b/dspace-api/src/main/java/org/dspace/metrics/MetricsExternalServices.java @@ -118,4 +118,8 @@ public int getFetchSize() { public void setFetchSize(int fetchSize) { this.fetchSize = fetchSize; } + + public List getLogs() { + return null; + } } diff --git a/dspace-api/src/main/java/org/dspace/metrics/UpdateCrisMetricsWithExternalSource.java b/dspace-api/src/main/java/org/dspace/metrics/UpdateCrisMetricsWithExternalSource.java index 12877252791b..82c690e62caa 100644 --- a/dspace-api/src/main/java/org/dspace/metrics/UpdateCrisMetricsWithExternalSource.java +++ b/dspace-api/src/main/java/org/dspace/metrics/UpdateCrisMetricsWithExternalSource.java @@ -13,6 +13,7 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Function; @@ -108,6 +109,7 @@ public void internalRun() throws Exception { performUpdate(externalService); context.complete(); } catch (Exception e) { + getLogsFromMetricService(externalService); log.error(e.getMessage(), e); handler.handleException(e); context.abort(); @@ -184,6 +186,7 @@ private void performUpdateWithMultiFetch(MetricsExternalServices metricsServices long updatedItems = metricsServices.updateMetric(context, itemIterator, param); + getLogsFromMetricService(metricsServices); handler.logInfo("Updated " + updatedItems + " metrics"); handler.logInfo("Update end"); @@ -216,6 +219,7 @@ private void performUpdateWithSingleFetches(MetricsExternalServices metricsServi } context.commit(); + getLogsFromMetricService(metricsServices); handler.logInfo("Found " + countFoundItems + " items"); handler.logInfo("Updated " + countUpdatedItems + " metrics"); handler.logInfo("Update end"); @@ -240,4 +244,10 @@ private void assignSpecialGroupsInContext() throws SQLException { } } + private void getLogsFromMetricService(MetricsExternalServices metricsServices) { + List metricLogger = metricsServices.getLogs(); + if (metricLogger != null) { + metricLogger.forEach(message -> handler.logInfo(message)); + } + } } diff --git a/dspace-api/src/main/java/org/dspace/metrics/scopus/ScopusProvider.java b/dspace-api/src/main/java/org/dspace/metrics/scopus/ScopusProvider.java index cf3eb875eb74..9bafca2d5169 100644 --- a/dspace-api/src/main/java/org/dspace/metrics/scopus/ScopusProvider.java +++ b/dspace-api/src/main/java/org/dspace/metrics/scopus/ScopusProvider.java @@ -40,9 +40,15 @@ public class ScopusProvider { private static final Logger log = LogManager.getLogger(ScopusProvider.class); + private List logsCache = new ArrayList<>(); + @Autowired private ScopusRestConnector scopusRestConnector; + public List getLogs() { + return logsCache; + } + /** *

* This methods fetch a list of metrics using the {@code id} param, @@ -54,6 +60,7 @@ public class ScopusProvider { * @return List of CrisMetrics fetched */ public List getScopusList(String id) { + logsCache = new ArrayList<>(); String scopusResponse = getRecords(id); if (StringUtils.isNotBlank(scopusResponse)) { List crisMetricList = mapToCrisMetricList(scopusResponse); @@ -66,7 +73,7 @@ public List getScopusList(String id) { } return crisMetricList; } - log.error("The query : " + id + " is wrong!"); + logAndCache("The query : " + id + " is wrong!"); return List.of(); } @@ -75,7 +82,7 @@ public CrisMetricDTO getScopusObject(String id) { if (StringUtils.isNotBlank(scopusResponse)) { return mapToCrisMetric(scopusResponse); } - log.error("The query : " + id + " is wrong!"); + logAndCache("The query : " + id + " is wrong!"); return null; } @@ -94,7 +101,7 @@ private CrisMetricDTO mapToCrisMetric(String scopusResponse) { docBuilder = docBuilderFactory.newDocumentBuilder(); parsedResponse = docBuilder.parse(new InputSource(new StringReader(scopusResponse))); } catch (ParserConfigurationException | SAXException | IOException e) { - log.error(e.getMessage(), e); + logAndCacheError(e); } return mapToCrisMetric(parsedResponse); } @@ -107,7 +114,7 @@ private List mapToCrisMetricList(String scopusResponse) { docBuilder = docBuilderFactory.newDocumentBuilder(); parsedResponse = docBuilder.parse(new InputSource(new StringReader(scopusResponse))); } catch (ParserConfigurationException | SAXException | IOException e) { - log.error(e.getMessage(), e); + logAndCacheError(e); } return mapToCrisMetricList(parsedResponse); } @@ -134,7 +141,7 @@ private String getNext(String scopusResponse) { .map(element -> element.getAttribute("href")) .orElse(null); } catch (ParserConfigurationException | SAXException | IOException e) { - log.error(e.getMessage(), e); + logAndCacheError(e); } return nextUrl; } @@ -148,7 +155,7 @@ private List mapToCrisMetricList(Document doc) { .filter(Objects::nonNull) .collect(Collectors.toList()); } catch (Exception e) { - log.error(e.getMessage(), e); + logAndCacheError(e); } return scopusCitationList; } @@ -162,7 +169,7 @@ private CrisMetricDTO mapToCrisMetric(Document doc) { .map(this::mapToCrisMetric) .orElse(null); } catch (Exception e) { - log.error(e.getMessage(), e); + logAndCacheError(e); } return scopusCitation; } @@ -170,13 +177,13 @@ private CrisMetricDTO mapToCrisMetric(Document doc) { private CrisMetricDTO mapToCrisMetric(Element dataRoot) { CrisMetricDTO scopusCitation = new CrisMetricDTO(); if (dataRoot == null) { - log.debug("No citation entry found in Scopus"); + logAndCache("No citation entry found in Scopus"); return scopusCitation; } Element errorScopusResp = XMLUtils.getSingleElement(dataRoot, "error"); if (errorScopusResp != null) { - log.debug("Error citation entry found in Scopus: " + errorScopusResp.getTextContent()); + logAndCache("Error citation entry found in Scopus: " + errorScopusResp.getTextContent()); return scopusCitation; } @@ -203,10 +210,25 @@ private CrisMetricDTO mapToCrisMetric(Element dataRoot) { try { scopusCitation.setMetricCount(Double.valueOf(numCitations)); } catch (NullPointerException | NumberFormatException ex) { - log.error("Error while trying to parse numCitations:" + numCitations); + logAndCacheErrorWithMessage("Error while trying to parse numCitations:" + numCitations, ex); } scopusCitation.setRemark(scopusCitation.buildMetricsRemark()); return scopusCitation; } + private void logAndCache(String message) { + logsCache.add("INFO: " + message); + log.debug(message); + } + + private void logAndCacheErrorWithMessage(String message, Throwable e) { + logsCache.add("ERROR: " + message + '\n' + e.getMessage()); + log.error(message, e); + } + + private void logAndCacheError(Throwable e) { + logsCache.add("ERROR: " + e.getMessage()); + log.error(e.getMessage(), e); + } + } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/metrics/scopus/UpdateScopusMetrics.java b/dspace-api/src/main/java/org/dspace/metrics/scopus/UpdateScopusMetrics.java index bd11feb99d3b..782f6f832fb2 100644 --- a/dspace-api/src/main/java/org/dspace/metrics/scopus/UpdateScopusMetrics.java +++ b/dspace-api/src/main/java/org/dspace/metrics/scopus/UpdateScopusMetrics.java @@ -42,6 +42,8 @@ public class UpdateScopusMetrics extends MetricsExternalServices { public static final String SCOPUS_CITATION = "scopusCitation"; + private List logsCache = new ArrayList<>(); + @Autowired private ScopusProvider scopusProvider; @@ -61,6 +63,10 @@ public List getFilters() { return Arrays.asList("dspace.entity.type:Publication", "dc.identifier.doi:* OR dc.identifier.pmid:*"); } + public List getLogs() { + return logsCache; + } + @Override public boolean updateMetric(Context context, Item item, String param) { String id = buildQuery(item); @@ -76,16 +82,20 @@ public long updateMetric(Context context, Iterator itemIterator, String pa long updatedItems = 0; long foundItems = 0; long apiCalls = 0; + logsCache = new ArrayList<>(); try { while (itemIterator.hasNext()) { Map queryMap = new HashMap<>(); List itemList = new ArrayList<>(); for (int i = 0; i < fetchSize && itemIterator.hasNext(); i++) { Item item = itemIterator.next(); + logAndCache("Adding item with uuid: " + item.getID()); setLastImportMetadataValue(context, item); itemList.add(item); } foundItems += itemList.size(); + String id = this.generateQuery(queryMap, itemList); + logAndCache("Getting scopus metrics for " + id); updatedItems += scopusProvider.getScopusList(this.generateQuery(queryMap, itemList)) .stream() @@ -102,11 +112,11 @@ public long updateMetric(Context context, Iterator itemIterator, String pa context.commit(); } } catch (SQLException e) { - log.error("Error while updating scopus' metrics", e); - throw new RuntimeException(e.getMessage(), e); + logAndCacheError("Error while updating scopus' metrics", e); } finally { - log.info("Found and fetched {} with {} api calls!", foundItems, apiCalls); + logAndCache("Found and fetched " + foundItems + " with " + apiCalls + " api calls!"); } + logsCache.addAll(scopusProvider.getLogs()); return updatedItems; } @@ -213,6 +223,7 @@ private boolean updateScopusMetrics(Context context, Item currentItem, CrisMetri createNewScopusMetrics(context,currentItem, scopusMetric, deltaPeriod1, deltaPeriod2); } catch (SQLException | AuthorizeException e) { + logsCache.add(e.getMessage()); log.error(e.getMessage(), e); } return true; @@ -236,4 +247,14 @@ private Double getDeltaPeriod(CrisMetricDTO currentMetric, Optional } return null; } + + private void logAndCache(String message) { + logsCache.add("INFO: " + message); + log.info(message); + } + + private void logAndCacheError(String message, Throwable e) { + logsCache.add("ERROR: " + message + '\n' + e.getMessage()); + log.error(message, e); + } } diff --git a/dspace-api/src/test/java/org/dspace/app/bulkedit/BulkImportIT.java b/dspace-api/src/test/java/org/dspace/app/bulkedit/BulkImportIT.java index e03c414a034c..e1d04f314c68 100644 --- a/dspace-api/src/test/java/org/dspace/app/bulkedit/BulkImportIT.java +++ b/dspace-api/src/test/java/org/dspace/app/bulkedit/BulkImportIT.java @@ -133,7 +133,8 @@ public void beforeTests() throws SQLException, AuthorizeException { public void testEmptyImport() throws InstantiationException, IllegalAccessException { String fileLocation = getXlsFilePath("empty.xls"); - String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -149,7 +150,8 @@ public void testEmptyImport() throws InstantiationException, IllegalAccessExcept public void testEmptyHeadersImport() throws InstantiationException, IllegalAccessException { String fileLocation = getXlsFilePath("empty-headers.xls"); - String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -165,7 +167,8 @@ public void testEmptyHeadersImport() throws InstantiationException, IllegalAcces public void testOneHeaderEmptyImport() throws InstantiationException, IllegalAccessException { String fileLocation = getXlsFilePath("one-header-empty.xls"); - String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -182,7 +185,8 @@ public void testOneHeaderEmptyImport() throws InstantiationException, IllegalAcc public void testWithoutHeadersImport() throws InstantiationException, IllegalAccessException { String fileLocation = getXlsFilePath("without-headers.xls"); - String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -198,7 +202,8 @@ public void testWithoutHeadersImport() throws InstantiationException, IllegalAcc public void testInvalidHeadersImport() throws InstantiationException, IllegalAccessException { String fileLocation = getXlsFilePath("invalid-headers.xls"); - String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -216,7 +221,8 @@ public void testInvalidHeadersImport() throws InstantiationException, IllegalAcc public void testInvalidSheetNameImport() throws InstantiationException, IllegalAccessException { String fileLocation = getXlsFilePath("invalid-sheet-name.xlsx"); - String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -241,7 +247,8 @@ public void testMetadataGroupRowWithManyValuesImport() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("metadata-group-row-with-many-values.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -275,7 +282,8 @@ public void testHeadersDuplicatedImport() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("headers-duplicated.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -300,7 +308,8 @@ public void testCreatePatent() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("create-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -351,7 +360,8 @@ public void testUpdatePatent() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -388,7 +398,8 @@ public void testCreatePublicationWithAuthority() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("create-publication-with-authority.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -439,7 +450,8 @@ public void testManyPublicationImport() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("many-publications.xls"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -515,7 +527,8 @@ public void testManyPublicationImportWithErrorAndNotAbortOnError() throws Except context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("many-publications.xls"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -575,7 +588,8 @@ public void testManyPublicationImportWithErrorAndAbortOnError() throws Exception context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("many-publications.xls"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -630,7 +644,8 @@ public void testCreatePublicationWithOneInvalidAuthorityAndNoAbortOnError() thro context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("create-publication-with-one-invalid-authority.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -675,7 +690,8 @@ public void testCreatePublicationWithOneInvalidAuthorityAndAbortOnError() throws context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("create-publication-with-one-invalid-authority.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -714,7 +730,8 @@ public void testCreatePublicationWithWillBeGeneratedAuthority() throws Exception String publicationCollectionId = publications.getID().toString(); String fileLocation = getXlsFilePath("create-publication-with-will-be-generated-authority.xls"); - String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, admin); @@ -760,7 +777,8 @@ public void testCreatePublicationWithWillBeGeneratedAuthorityAndNoRelatedItemFou String publicationCollectionId = publications.getID().toString(); String fileLocation = getXlsFilePath("create-publication-with-will-be-generated-authority.xls"); - String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, admin); @@ -810,7 +828,8 @@ public void testCreatePublicationWithWillBeReferencedAuthority() throws Exceptio String publicationCollectionId = publications.getID().toString(); String fileLocation = getXlsFilePath("create-publication-with-will-be-referenced-authority.xls"); - String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, admin); @@ -856,7 +875,8 @@ public void testCreatePublicationWithWillBeReferencedAuthorityAndNoRelatedItemFo String publicationCollectionId = publications.getID().toString(); String fileLocation = getXlsFilePath("create-publication-with-will-be-referenced-authority.xls"); - String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, admin); @@ -898,7 +918,8 @@ public void testCreatePublicationInWorkspace() throws Exception { String publicationCollectionId = publications.getID().toString(); String fileLocation = getXlsFilePath("create-workspace-publication.xls"); - String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -942,7 +963,8 @@ public void testCreateArchivedPublication() throws Exception { String publicationCollectionId = publications.getID().toString(); String fileLocation = getXlsFilePath("create-archived-publication.xls"); - String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, + "-e", eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, admin); @@ -995,7 +1017,8 @@ public void testUpdateWorkflowPatentWithValidWorkspaceItem() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-workflow-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1045,7 +1068,8 @@ public void testUpdateWorkflowPatentWithInvalidWorkspaceItem() throws Exception context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-workflow-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1097,7 +1121,8 @@ public void testUpdateWorkflowPatentWithoutWorkspaceItem() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-workflow-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1146,7 +1171,8 @@ public void testUpdateArchivePatentWithWorkspaceItem() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-archive-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1195,7 +1221,8 @@ public void testUpdateArchivePatentWithWorkflowItem() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-archive-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1244,7 +1271,8 @@ public void testUpdateArchivePatentWithAlreadyArchivedItem() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-archive-patent.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1295,7 +1323,8 @@ public void testAutomaticReferenceResolution() throws Exception { String publicationCollectionId = publications.getID().toString(); String fileLocation = getXlsFilePath("create-publication-with-will-be-referenced-authority.xls"); - String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, "-e" }; + String[] args = new String[] { "bulk-import", "-c", publicationCollectionId, "-f", fileLocation, + "-e" , eperson.getEmail(), "-er"}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, admin); @@ -1316,7 +1345,8 @@ public void testAutomaticReferenceResolution() throws Exception { String personsCollectionId = persons.getID().toString(); fileLocation = getXlsFilePath("create-person.xls"); - args = new String[] { "bulk-import", "-c", personsCollectionId, "-f", fileLocation, "-e" }; + args = new String[] { "bulk-import", "-c", personsCollectionId, "-f", fileLocation, + "-e" , eperson.getEmail(), "-er"}; handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, admin); @@ -1350,7 +1380,8 @@ public void testUploadSingleBitstream() throws Exception { String fileLocation = getXlsFilePath("add-bitstream-to-item.xls"); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1404,7 +1435,8 @@ public void testUploadMultipleBitstreams() throws Exception { String fileLocation = getXlsFilePath("add-multiple-bitstreams-to-items.xls"); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1458,7 +1490,8 @@ public void testUploadMultipleBitstreamWithPathTraversal() throws Exception { String fileLocation = getXlsFilePath("add-multiple-bitstreams-with-path-traversal-to-items.xls"); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1509,7 +1542,8 @@ public void testUploadSingleBitstreamUpdate() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("add-bitstream-to-item-update.xls"); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1555,7 +1589,8 @@ public void testUploadMultipleBitstreamsUpdateMultiple() throws Exception { String fileName = "add-bitstream-to-multiple-items-update.xls"; String fileLocation = getXlsFilePath(fileName); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1602,7 +1637,8 @@ public void testUploadSingleBitstreamUpdateWithExistingBundle() throws Exception String fileName = "add-bitstream-to-item-bundle.xls"; String fileLocation = getXlsFilePath(fileName); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1639,7 +1675,8 @@ public void testCreatePublicationInWorkspaceItemsAndItemHasLicense() throws Exce context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("items-with-bitstreams.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1702,7 +1739,8 @@ public void testCreatePublicationInWorkspaceItemsWithBitstreams() throws Excepti String fileName = "items-with-bitstreams.xlsx"; String fileLocation = getXlsFilePath(fileName); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1786,7 +1824,8 @@ public void testUpdateAndDeleteBitstreamsOfItems() throws Exception { String fileName = "update-delete-bitstreams-of-items.xls"; String fileLocation = getXlsFilePath(fileName); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1855,7 +1894,8 @@ public void testBitstreamUpdateAndDeleteWithWrongPosition() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-delete-bitstreams-of-items.xls"); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1918,7 +1958,8 @@ public void testBitstreamUpdateWithAdditionalConditionSetToFalse() throws Except context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-bitstream-policies-without-additional-ac.xls"); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -1981,7 +2022,8 @@ public void testUpdateItems() throws Exception { // start test String fileLocation = getXlsFilePath("update-items.xls"); - String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publication.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); assertThat(handler.getErrorMessages(), empty()); @@ -2031,7 +2073,8 @@ public void testCreatePublicationWithSecurityLevel() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("create-publication-with-security-level.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -2081,7 +2124,8 @@ public void testUpdatePublicationWithSecurityLevel() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("update-publication-with-security-level.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -2121,7 +2165,8 @@ public void testWorkbookWithoutActionColumn() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("without-action-column.xls"); - String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -2182,7 +2227,8 @@ public void testWorkbookWithDiscoverableColumn() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("publications_with_discoverable_column.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -2237,7 +2283,8 @@ public void testWorkbookWithInvalidOptionalColumnPosition() throws Exception { context.restoreAuthSystemState(); String fileLocation = getXlsFilePath("invalid-optional-column-position.xlsx"); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); @@ -2246,6 +2293,28 @@ public void testWorkbookWithInvalidOptionalColumnPosition() throws Exception { + "must be placed before the metadata fields")); } + @Test + public void testCreatePatentByNotCollectionAdmin() throws Exception { + context.turnOffAuthorisationSystem(); + Collection patents = createCollection(context, community) + .withSubmissionDefinition("patent") + .withAdminGroup(admin) + .build(); + context.commit(); + context.restoreAuthSystemState(); + + String fileLocation = getXlsFilePath("create-patent.xls"); + String[] args = new String[] { "bulk-import", "-c", patents.getID().toString(), "-f", fileLocation, + "-e", eperson.getEmail()}; + TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); + + handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); + + List errorMessages = handler.getErrorMessages(); + assertThat("Expected 1 error message", errorMessages, hasSize(1)); + assertThat(errorMessages.get(0), containsString("The user is not an admin of the given collection")); + } + private WorkspaceItem findWorkspaceItem(Item item) throws SQLException { return workspaceItemService.findByItem(context, item); } diff --git a/dspace-api/src/test/java/org/dspace/app/bulkimport/service/BulkImportWorkbookBuilderIT.java b/dspace-api/src/test/java/org/dspace/app/bulkimport/service/BulkImportWorkbookBuilderIT.java index eed2826ea67a..a76642790704 100644 --- a/dspace-api/src/test/java/org/dspace/app/bulkimport/service/BulkImportWorkbookBuilderIT.java +++ b/dspace-api/src/test/java/org/dspace/app/bulkimport/service/BulkImportWorkbookBuilderIT.java @@ -176,7 +176,8 @@ public void testWorkbookBuildingFromItemDtos() throws Exception { String tempLocation = storeInTempLocation(workbook); - String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", tempLocation }; + String[] args = new String[] { "bulk-import", "-c", publications.getID().toString(), "-f", tempLocation, + "-e", admin.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl, eperson); diff --git a/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java b/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java index 562aa86a585e..88c29fd23344 100644 --- a/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java +++ b/dspace-api/src/test/java/org/dspace/authority/orcid/MockOrcid.java @@ -51,6 +51,14 @@ public InputStream answer(InvocationOnMock invocation) { } }); + when(orcidRestConnector.get(ArgumentMatchers.matches("^\\d{4}-\\d{4}-\\d{4}-\\d{4}$"), ArgumentMatchers.any())) + .thenAnswer(new Answer() { + @Override + public InputStream answer(InvocationOnMock invocation) { + return this.getClass().getResourceAsStream("orcid-record.xml"); + } + }); + setOrcidRestConnector(orcidRestConnector); } diff --git a/dspace-api/src/test/java/org/dspace/content/integration/crosswalks/XlsCollectionCrosswalkIT.java b/dspace-api/src/test/java/org/dspace/content/integration/crosswalks/XlsCollectionCrosswalkIT.java index 8929e4d65116..6ed7d8ba3aa7 100644 --- a/dspace-api/src/test/java/org/dspace/content/integration/crosswalks/XlsCollectionCrosswalkIT.java +++ b/dspace-api/src/test/java/org/dspace/content/integration/crosswalks/XlsCollectionCrosswalkIT.java @@ -154,7 +154,7 @@ public void testBulkImportOfCollectionDisseminate() throws Exception { } String[] args = new String[] { "bulk-import", "-c", collection.getID().toString(), - "-f", tempWorkbookFile.getAbsolutePath() }; + "-f", tempWorkbookFile.getAbsolutePath(), "-e", admin.getEmail()}; TestDSpaceRunnableHandler handler = new TestDSpaceRunnableHandler(); diff --git a/dspace-api/src/test/resources/org/dspace/authority/orcid/orcid-record.xml b/dspace-api/src/test/resources/org/dspace/authority/orcid/orcid-record.xml new file mode 100644 index 000000000000..7672e980c8bd --- /dev/null +++ b/dspace-api/src/test/resources/org/dspace/authority/orcid/orcid-record.xml @@ -0,0 +1,270 @@ + + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + + en + + + Direct + 2023-09-19T12:25:43.445Z + 2023-10-12T14:19:06.983Z + true + true + true + + + 2023-10-12T13:28:14.550Z + + 2023-09-19T12:25:43.736Z + 2023-09-19T12:25:43.736Z + Andrea + Bollini + + + 2023-10-12T13:28:14.550Z + + 2023-10-05T07:56:29.001Z + 2023-10-12T13:28:14.550Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + isco + + + 2023-10-12T13:28:14.541Z + 2023-10-12T13:28:14.541Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + Bollini, Andrea + + + + 2023-10-12T13:27:57.187Z + + 2023-10-12T10:35:14.406Z + 2023-10-12T13:27:57.187Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + Linkedin + https://it.linkedin.com/in/andreabollini + + + 2023-10-12T13:27:57.183Z + 2023-10-12T13:27:57.183Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + 4science + https://www.4science.it/ + + + + 2023-10-12T10:38:48.105Z + + 2023-10-12T10:33:21.077Z + 2023-10-12T10:38:48.105Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + test-orcid@mailinator.com + + + + + + 2023-09-04T09:04:52.121Z + + 2023-01-13T11:20:13.803Z + 2023-01-13T11:48:02.979Z + + + https://sandbox.orcid.org/client/0000-0002-3609-4817 + 0000-0002-3609-4817 + sandbox.orcid.org + + Scopus Wizard + + Scopus Author ID + 57432999200 + http://www.scopus.com/inward/authorDetails.url?authorID=57432999200&partnerID=MN8TOARS + self + + + 2023-01-19T14:25:14.512Z + 2023-01-19T14:25:14.512Z + + + https://sandbox.orcid.org/client/0000-0002-3609-4817 + 0000-0002-3609-4817 + sandbox.orcid.org + + Scopus Wizard + + Scopus Author ID + 35233141600 + http://www.scopus.com/inward/authorDetails.url?authorID=35233141600&partnerID=MN8TOARS + self + + + + + 2023-10-12T14:19:06.992Z + + + + 2023-10-12T10:52:26.965Z + + 2023-10-12T10:52:26.965Z + + + 2023-10-12T10:52:26.965Z + 2023-10-12T10:52:26.965Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + + Dspace + + Milan + IT + + + + + + 2023-10-12T10:35:49.079Z + + + 2023-10-12T10:34:17.514Z + 2023-10-12T10:35:49.079Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + + 4Science + + Milan + IT + + + https://ror.org/03vb2cr34 + ROR + + + + + + + + + + + + + + 2023-10-12T14:19:06.992Z + + 2023-10-12T14:19:06.992Z + + + doi + 10.1016/j.procs.2014.06.008 + 10.1016/j.procs.2014.06.008 + https://doi.org/10.1016/j.procs.2014.06.008 + self + + + eid + 55484808800 + 55484808800 + self + + + + 2023-10-12T14:09:25.415Z + 2023-10-12T14:19:06.992Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + + Publication Metadata in CERIF: Inspiration by FRBR + + + + doi + 10.1016/j.procs.2014.06.008 + 10.1016/j.procs.2014.06.008 + https://doi.org/10.1016/j.procs.2014.06.008 + self + + + issn + 1877-0509 + 1877-0509 + https://portal.issn.org/resource/ISSN/1877-0509 + part-of + + + eid + 55484808800 + 55484808800 + self + + + http://dx.doi.org/10.1016/j.procs.2014.06.008 + journal-article + + 2014 + + Procedia Computer Science + + + + + \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ExternalSourceEntryRestConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ExternalSourceEntryRestConverter.java index 585de2a99a57..35921c16d254 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ExternalSourceEntryRestConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ExternalSourceEntryRestConverter.java @@ -7,9 +7,19 @@ */ package org.dspace.app.rest.converter; +import java.sql.SQLException; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + import org.dspace.app.rest.model.ExternalSourceEntryRest; +import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.projection.Projection; +import org.dspace.content.service.ItemService; +import org.dspace.core.Context; import org.dspace.external.model.ExternalDataObject; +import org.dspace.web.ContextUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -22,6 +32,12 @@ public class ExternalSourceEntryRestConverter implements DSpaceConverter convertToItemRests(List uuids, Projection projection) { + + if (uuids == null) { + return List.of(); + } + + Context context = ContextUtil.obtainCurrentRequestContext(); + return uuids.stream() + .map(uuid -> { + try { + return itemService.find(context, uuid); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }) + .filter(item -> Objects.nonNull(item)) + .map(item -> itemConverter.convert(item, projection)) + .collect(Collectors.toList()); + } + public Class getModelClass() { return ExternalDataObject.class; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java index 61f18a5b3c9c..1d81e308e39f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java @@ -10,6 +10,7 @@ import static org.dspace.app.util.Util.getSourceVersion; import org.dspace.app.rest.model.RootRest; +import org.dspace.core.CrisConstants; import org.dspace.services.ConfigurationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -28,7 +29,8 @@ public RootRest convert() { rootRest.setDspaceName(configurationService.getProperty("dspace.name")); rootRest.setDspaceUI(configurationService.getProperty("dspace.ui.url")); rootRest.setDspaceServer(configurationService.getProperty("dspace.server.url")); - rootRest.setDspaceVersion("DSpace " + getSourceVersion()); + rootRest.setDspaceVersion(CrisConstants.DSPACE_BASE_VERSION); + rootRest.setCrisVersion(getSourceVersion()); return rootRest; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java index 06af7e222713..4e578c313870 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java @@ -7,6 +7,8 @@ */ package org.dspace.app.rest.model; +import java.util.List; + import org.dspace.app.rest.ExternalSourcesRestController; /** @@ -38,6 +40,7 @@ public String getType() { private String value; private String externalSource; private MetadataRest metadata = new MetadataRest(); + private List matchObjects; /** * Generic getter for the id @@ -118,4 +121,12 @@ public MetadataRest getMetadata() { public void setMetadata(MetadataRest metadata) { this.metadata = metadata; } + + public List getMatchObjects() { + return matchObjects; + } + + public void setMatchObjects(List matchObjects) { + this.matchObjects = matchObjects; + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java index cef8965601ca..9fd6a1263423 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java @@ -21,6 +21,7 @@ public class RootRest extends RestAddressableModel { private String dspaceName; private String dspaceServer; private String dspaceVersion; + private String crisVersion; public String getCategory() { return CATEGORY; @@ -67,6 +68,14 @@ public void setDspaceVersion(String dspaceVersion) { this.dspaceVersion = dspaceVersion; } + public String getCrisVersion() { + return crisVersion; + } + + public void setCrisVersion(String crisVersion) { + this.crisVersion = crisVersion; + } + @Override public boolean equals(Object object) { return (object instanceof RootRest && @@ -76,6 +85,7 @@ public boolean equals(Object object) { .append(this.getDspaceUI(), ((RootRest) object).getDspaceUI()) .append(this.getDspaceName(), ((RootRest) object).getDspaceName()) .append(this.getDspaceServer(), ((RootRest) object).getDspaceServer()) + .append(this.getCrisVersion(), ((RootRest)object).getCrisVersion()) .isEquals()); } @@ -88,6 +98,7 @@ public int hashCode() { .append(this.getDspaceName()) .append(this.getDspaceUI()) .append(this.getDspaceServer()) + .append(this.getCrisVersion()) .toHashCode(); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java index 770087d0b54b..1f1582596277 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java @@ -317,9 +317,9 @@ public Iterable upload(Context context, HttpServletRequest re for (MultipartFile mpFile : uploadfiles) { File file = Utils.getFile(mpFile, "upload-loader", "filedataloader"); try { - ImportRecord record = importService.getRecord(file, mpFile.getOriginalFilename()); - if (record != null) { - records.add(record); + List recordsFound = importService.getRecords(file, mpFile.getOriginalFilename()); + if (recordsFound != null && !recordsFound.isEmpty()) { + records.addAll(recordsFound); break; } } catch (Exception e) { @@ -334,11 +334,15 @@ public Iterable upload(Context context, HttpServletRequest re } catch (Exception e) { log.error("Error importing metadata", e); } - WorkspaceItem source = submissionService. - createWorkspaceItem(context, getRequestService().getCurrentRequest()); - merge(context, records, source); - result = new ArrayList<>(); - result.add(source); + result = new ArrayList<>(records.size()); + for (ImportRecord importRecord : records) { + WorkspaceItem source = submissionService. + createWorkspaceItem(context, getRequestService().getCurrentRequest()); + + merge(context, importRecord, source); + + result.add(source); + } //perform upload of bitstream if there is exact one result and convert workspaceitem to entity rest if (!result.isEmpty()) { @@ -348,18 +352,17 @@ public Iterable upload(Context context, HttpServletRequest re //load bitstream into bundle ORIGINAL only if there is one result (approximately this is the // right behaviour for pdf file but not for other bibliographic format e.g. bibtex) if (result.size() == 1) { + ClassLoader loader = this.getClass().getClassLoader(); for (int i = 0; i < submissionConfig.getNumberOfSteps(); i++) { SubmissionStepConfig stepConfig = submissionConfig.getStep(i); - ClassLoader loader = this.getClass().getClassLoader(); - Class stepClass; try { - stepClass = loader.loadClass(stepConfig.getProcessingClassName()); - Object stepInstance = stepClass.newInstance(); + Class stepClass = loader.loadClass(stepConfig.getProcessingClassName()); + Object stepInstance = stepClass.getConstructor().newInstance(); if (UploadableStep.class.isAssignableFrom(stepClass)) { UploadableStep uploadableStep = (UploadableStep) stepInstance; for (MultipartFile mpFile : uploadfiles) { - ErrorRest err = uploadableStep.upload(context, - submissionService, stepConfig, wi, mpFile); + ErrorRest err = + uploadableStep.upload(context, submissionService, stepConfig, wi, mpFile); if (err != null) { errors.add(err); } @@ -449,7 +452,7 @@ private BaseObjectRest findItemRestById(Context context, String itemId) throw return authorizationRestUtil.getObject(context, objectId); } - private void merge(Context context, List records, WorkspaceItem item) throws SQLException { + private void merge(Context context, ImportRecord record, WorkspaceItem item) throws SQLException { for (MetadataValue metadataValue : itemService.getMetadata( item.getItem(), Item.ANY, Item.ANY, Item.ANY, Item.ANY)) { itemService.clearMetadata(context, item.getItem(), @@ -458,13 +461,11 @@ private void merge(Context context, List records, WorkspaceItem it metadataValue.getMetadataField().getQualifier(), metadataValue.getLanguage()); } - for (ImportRecord record : records) { - if (record != null && record.getValueList() != null) { - for (MetadatumDTO metadataValue : record.getValueList()) { - itemService.addMetadata(context, item.getItem(), metadataValue.getSchema(), - metadataValue.getElement(), metadataValue.getQualifier(), null, - metadataValue.getValue()); - } + if (record != null && record.getValueList() != null) { + for (MetadatumDTO metadataValue : record.getValueList()) { + itemService.addMetadata(context, item.getItem(), metadataValue.getSchema(), + metadataValue.getElement(), metadataValue.getQualifier(), null, + metadataValue.getValue()); } } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java index 565a4d003f78..7c396e803537 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java @@ -19,15 +19,18 @@ import org.dspace.app.rest.matcher.EntityTypeMatcher; import org.dspace.app.rest.matcher.ExternalSourceEntryMatcher; import org.dspace.app.rest.matcher.ExternalSourceMatcher; +import org.dspace.app.rest.matcher.ItemMatcher; import org.dspace.app.rest.matcher.PageMatcher; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EntityTypeBuilder; +import org.dspace.builder.ItemBuilder; import org.dspace.builder.WorkflowItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.EntityType; +import org.dspace.content.Item; import org.dspace.core.CrisConstants; import org.dspace.external.provider.AbstractExternalDataProvider; import org.dspace.external.provider.ExternalDataProvider; @@ -485,4 +488,60 @@ public void findSupportedEntityTypesOfAnExternalDataProviderPaginationTest() thr } } + @Test + public void findOneExternalSourceEntriesDuplicationTest() throws Exception { + context.turnOffAuthorisationSystem(); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + // create item withDoiIdentifier equals 10.1016/j.procs.2017.03.031 + Item itemOne = ItemBuilder.createItem(context, col1) + .withFullName("Public item one") + .withIssueDate("2023-10-17") + .withDoiIdentifier("10.1016/j.procs.2017.03.031") + .withEntityType("Publication") + .build(); + + // create another item withDoiIdentifier equals 10.1016/j.procs.2017.03.031 + Item itemTwo = ItemBuilder.createItem(context, col1) + .withFullName("Public item two") + .withIssueDate("2023-10-17") + .withDoiIdentifier("10.1016/j.procs.2017.03.031") + .withEntityType("Publication") + .build(); + + context.restoreAuthSystemState(); + + getClient().perform(get("/api/integration/externalsources/mock/entries") + .param("query", "one").param("size", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.externalSourceEntries", Matchers.hasItem( + ExternalSourceEntryMatcher.matchExternalSourceEntry("onetwo", "onetwo", "onetwo", "mock") + ))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].matchObjects", containsInAnyOrder( + ItemMatcher.matchItemProperties(itemOne), + ItemMatcher.matchItemProperties(itemTwo) + ))) + .andExpect(jsonPath("$.page", PageMatcher.pageEntryWithTotalPagesAndElements(0, 1, 2, 2))); + + getClient().perform(get("/api/integration/externalsources/mock/entries") + .param("query", "one").param("size", "1").param("page", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.externalSourceEntries", Matchers.hasItem( + ExternalSourceEntryMatcher.matchExternalSourceEntry("one", "one", "one", "mock") + ))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].matchObjects", containsInAnyOrder( + ItemMatcher.matchItemProperties(itemOne), + ItemMatcher.matchItemProperties(itemTwo) + ))) + .andExpect(jsonPath("$.page", PageMatcher.pageEntryWithTotalPagesAndElements(1, 1, 2, 2))); + } + } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemAuthorityIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemAuthorityIT.java index 9e0ea90afc69..cdfbf2f29b13 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemAuthorityIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemAuthorityIT.java @@ -127,19 +127,25 @@ public void singleItemAuthorityTest() throws Exception { Map.of("data-oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID(), "oairecerif_author_affiliation", "OrgUnit_1::" - + orgUnit_1.getID())), + + orgUnit_1.getID(), + "data-person_identifier_orcid", "", + "person_identifier_orcid", "")), ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_2.getID().toString(), "Author 2", "Author 2", "vocabularyEntry", Map.of("data-oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID(), "oairecerif_author_affiliation", "OrgUnit_1::" - + orgUnit_1.getID())), + + orgUnit_1.getID(), + "data-person_identifier_orcid", "", + "person_identifier_orcid", "")), ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_3.getID().toString(), "Author 3", "Author 3", "vocabularyEntry", Map.of("data-oairecerif_author_affiliation", "OrgUnit_2::" + orgUnit_2.getID(), "oairecerif_author_affiliation", "OrgUnit_2::" - + orgUnit_2.getID())) + + orgUnit_2.getID(), + "data-person_identifier_orcid", "", + "person_identifier_orcid", "")) ))) .andExpect(jsonPath("$.page.totalElements", Matchers.is(3))); } @@ -216,13 +222,19 @@ public void multiItemAuthorityTest() throws Exception { "Author 2(OrgUnit_2)", "Author 2", "vocabularyEntry", Map.of("data-oairecerif_author_affiliation", "OrgUnit_2::" + orgUnit_2.getID(), "oairecerif_author_affiliation", "OrgUnit_2::" + orgUnit_2.getID())), + ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_1.getID().toString(), + "Author 1", "Author 1", "vocabularyEntry", + Map.of("data-person_identifier_orcid", "", "person_identifier_orcid", "")), + ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_2.getID().toString(), + "Author 2", "Author 2", "vocabularyEntry", + Map.of("data-person_identifier_orcid", "", "person_identifier_orcid", "")), // filled with EditorAuthority extra metadata generator - ItemAuthorityMatcher.matchItemAuthorityProperties(author_1.getID().toString(), - "Author 1", "Author 1", "vocabularyEntry"), - ItemAuthorityMatcher.matchItemAuthorityProperties(author_2.getID().toString(), - "Author 2", "Author 2", "vocabularyEntry") + ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_1.getID().toString(), + "Author 1", "Author 1", "vocabularyEntry", Map.of()), + ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_2.getID().toString(), + "Author 2", "Author 2", "vocabularyEntry", Map.of()) ))) - .andExpect(jsonPath("$.page.totalElements", Matchers.is(5))); + .andExpect(jsonPath("$.page.totalElements", Matchers.is(7))); } @Test @@ -250,7 +262,9 @@ public void singleItemAuthorityWithoutOrgUnitTest() throws Exception { .andExpect(jsonPath("$._embedded.entries", Matchers.contains( ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_1.getID().toString(), "Author 1", "Author 1", "vocabularyEntry", - Map.of("data-oairecerif_author_affiliation", "", "oairecerif_author_affiliation", "")) + Map.of("data-oairecerif_author_affiliation", "", "oairecerif_author_affiliation", "", + "data-person_identifier_orcid", "", + "person_identifier_orcid", "")) ))) .andExpect(jsonPath("$.page.totalElements", Matchers.is(1))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidAuthorityIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidAuthorityIT.java index a92253e54437..33bb24f8b029 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidAuthorityIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidAuthorityIT.java @@ -669,8 +669,11 @@ private Item buildPerson(String title, Item affiliation) { private Matcher affiliationEntry(Item item, String title, String otherInfoValue) { return ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(id(item), title, - title, "vocabularyEntry", Map.of("data-oairecerif_author_affiliation", otherInfoValue, - "oairecerif_author_affiliation", otherInfoValue)); + title, "vocabularyEntry", Map.of( + "data-oairecerif_author_affiliation", otherInfoValue, + "oairecerif_author_affiliation", otherInfoValue, + "data-" + ORCID_INFO, "", + ORCID_INFO, "")); } private Matcher orcidEntry(String title, String authorityPrefix, String orcid) { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java index 04592c17da2d..2e797f9ce4ab 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java @@ -150,10 +150,10 @@ public void findOneExternalSourcesMockitoTest() throws Exception { OrcidRestConnector orcidConnector = Mockito.mock(OrcidRestConnector.class); OrcidRestConnector realConnector = orcidV3AuthorDataProvider.getOrcidRestConnector(); orcidV3AuthorDataProvider.setOrcidRestConnector(orcidConnector); - when(orcidConnector.get(ArgumentMatchers.endsWith("/person"), ArgumentMatchers.any())) + when(orcidConnector.get(ArgumentMatchers.matches("^\\d{4}-\\d{4}-\\d{4}-\\d{4}$"), ArgumentMatchers.any())) .thenAnswer(new Answer() { public InputStream answer(InvocationOnMock invocation) { - return getClass().getResourceAsStream("orcid-person-record.xml"); + return getClass().getResourceAsStream("orcid-record.xml"); } }); @@ -193,10 +193,10 @@ public InputStream answer(InvocationOnMock invocation) { return getClass().getResourceAsStream("orcid-search.xml"); } }); - when(orcidConnector.get(ArgumentMatchers.endsWith("/person"), ArgumentMatchers.any())) + when(orcidConnector.get(ArgumentMatchers.matches("^\\d{4}-\\d{4}-\\d{4}-\\d{4}$"), ArgumentMatchers.any())) .thenAnswer(new Answer() { public InputStream answer(InvocationOnMock invocation) { - return getClass().getResourceAsStream("orcid-person-record.xml"); + return getClass().getResourceAsStream("orcid-record.xml"); } }); String q = "orcid:0000-0002-9029-1854"; @@ -246,10 +246,10 @@ public InputStream answer(InvocationOnMock invocation) { return getClass().getResourceAsStream("orcid-search.xml"); } }); - when(orcidConnector.get(ArgumentMatchers.endsWith("/person"), ArgumentMatchers.any())) + when(orcidConnector.get(ArgumentMatchers.matches("^\\d{4}-\\d{4}-\\d{4}-\\d{4}$"), ArgumentMatchers.any())) .thenAnswer(new Answer() { public InputStream answer(InvocationOnMock invocation) { - return getClass().getResourceAsStream("orcid-person-record.xml"); + return getClass().getResourceAsStream("orcid-record.xml"); } }); String q = "family-name:bollini AND given-names:andrea"; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java index c7725805687d..d9d2c0fcf708 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java @@ -60,9 +60,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.matchers.JsonPathMatchers; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; +import org.apache.commons.text.StringEscapeUtils; import org.dspace.app.rest.matcher.CollectionMatcher; import org.dspace.app.rest.matcher.ItemMatcher; import org.dspace.app.rest.matcher.MetadataMatcher; @@ -2027,27 +2027,109 @@ public void createSingleWorkspaceItemsFromSingleFileWithMultipleEntriesTest() th Collection col1 = CollectionBuilder.createCollection(context, child1) .withName("Collection 1") .withSubmitterGroup(eperson) + .withEntityType("Publication") + .withSubmissionDefinition("traditional") .build(); Collection col2 = CollectionBuilder.createCollection(context, child1) .withName("Collection 2") .withSubmitterGroup(eperson) + .withEntityType("Publication") + .withSubmissionDefinition("traditional") .build(); - InputStream bibtex = getClass().getResourceAsStream("bibtex-test-3-entries.bib"); - final MockMultipartFile bibtexFile = new MockMultipartFile("file", "bibtex-test-3-entries.bib", - "application/x-bibtex", - bibtex); + try (InputStream bibtex = getClass().getResourceAsStream("bibtex-test-3-entries.bib")) { + final MockMultipartFile bibtexFile = + new MockMultipartFile( + "file", "bibtex-test-3-entries.bib", + "application/x-bibtex", bibtex + ); - context.restoreAuthSystemState(); + context.restoreAuthSystemState(); - String authToken = getAuthToken(eperson.getEmail(), password); - // create a workspaceitem from a single bibliographic entry file explicitly in the default collection (col1) - getClient(authToken).perform(multipart("/api/submission/workspaceitems") - .file(bibtexFile)) - // create should return return a 422 because we don't allow/support bibliographic files - // that have multiple metadata records - .andExpect(status().is(422)); - bibtex.close(); + String authToken = getAuthToken(eperson.getEmail(), password); + // create a workspaceitem from a single bibliographic entry file explicitly in the default collection (col1) + getClient(authToken) + .perform( + multipart("/api/submission/workspaceitems").file(bibtexFile) + ) + // bulk create should return 200, 201 (created) is better for single resource + .andExpect(status().isOk()) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[0].sections.traditionalpageone['dc.title'][0].value", + is("My Article") + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[0]._embedded.collection.id", + is(col1.getID().toString()) + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[1].sections.traditionalpageone['dc.title'][0].value", + is("My Article 2") + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[1]._embedded.collection.id", + is(col1.getID().toString()) + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[2].sections.traditionalpageone['dc.title'][0].value", + is("My Article 3") + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[2]._embedded.collection.id", + is(col1.getID().toString()) + ) + ) + .andExpect( + jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist()); + getClient(authToken) + .perform( + multipart("/api/submission/workspaceitems") + .file(bibtexFile) + .param("owningCollection", col2.getID().toString()) + ) + .andExpect(status().isOk()) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[0].sections.traditionalpageone['dc.title'][0].value", + is("My Article") + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[0]._embedded.collection.id", + is(col2.getID().toString()) + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[1].sections.traditionalpageone['dc.title'][0].value", + is("My Article 2") + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[1]._embedded.collection.id", + is(col2.getID().toString()) + ) + ) + .andExpect( + jsonPath( + "$._embedded.workspaceitems[2].sections.traditionalpageone['dc.title'][0].value", + is("My Article 3") + ) + ); + } } @Test diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/RootConverterTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/RootConverterTest.java index acb3b0c263d0..73b12848e790 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/RootConverterTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/RootConverterTest.java @@ -13,6 +13,7 @@ import org.dspace.app.rest.model.RootRest; import org.dspace.app.util.Util; +import org.dspace.core.CrisConstants; import org.dspace.services.ConfigurationService; import org.junit.Before; import org.junit.Test; @@ -52,7 +53,8 @@ public void testCorrectPropertiesSetFromConfigurationService() throws Exception assertEquals("dspaceurl", rootRest.getDspaceUI()); assertEquals("dspacename", rootRest.getDspaceName()); assertEquals(restUrl, rootRest.getDspaceServer()); - assertEquals("DSpace " + Util.getSourceVersion(), rootRest.getDspaceVersion()); + assertEquals(CrisConstants.DSPACE_BASE_VERSION, rootRest.getDspaceVersion()); + assertEquals(Util.getSourceVersion(), rootRest.getCrisVersion()); } @Test diff --git a/dspace-server-webapp/src/test/java/org/dspace/authority/CrisConsumerIT.java b/dspace-server-webapp/src/test/java/org/dspace/authority/CrisConsumerIT.java index 0cceb70bb218..3cbbe6850dc9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/authority/CrisConsumerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/authority/CrisConsumerIT.java @@ -22,6 +22,7 @@ import static org.hamcrest.Matchers.nullValue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.matches; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -92,7 +93,7 @@ public class CrisConsumerIT extends AbstractControllerIntegrationTest { @Value("classpath:org/dspace/app/rest/simple-article.pdf") private Resource simpleArticle; - @Value("classpath:org/dspace/authority/orcid/orcid-person-record.xml") + @Value("classpath:org/dspace/authority/orcid/orcid-record.xml") private Resource orcidPersonRecord; private EPerson submitter; @@ -1058,7 +1059,7 @@ public void testOrcidImportFiller() throws Exception { String orcid = "0000-0002-9029-1854"; - when(mockOrcidConnector.get(eq(orcid + "/person"), any())) + when(mockOrcidConnector.get(matches("^\\d{4}-\\d{4}-\\d{4}-\\d{4}$"), any())) .thenAnswer(i -> orcidPersonRecord.getInputStream()); try { @@ -1076,7 +1077,7 @@ public void testOrcidImportFiller() throws Exception { context.restoreAuthSystemState(); - verify(mockOrcidConnector).get(eq(orcid + "/person"), any()); + verify(mockOrcidConnector).get(eq(orcid), any()); verifyNoMoreInteractions(mockOrcidConnector); String authToken = getAuthToken(submitter.getEmail(), password); diff --git a/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockDataProvider.java b/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockDataProvider.java index 894b8e409a4f..0a0b4f062d31 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockDataProvider.java +++ b/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockDataProvider.java @@ -85,6 +85,7 @@ public void init() throws IOException { externalDataObject.setDisplayValue(id); List list = new LinkedList<>(); list.add(new MetadataValueDTO("dc", "contributor", "author", null, "Donald, Smith")); + list.add(new MetadataValueDTO("dc", "identifier", "doi", null, "10.1016/j.procs.2017.03.031")); externalDataObject.setMetadata(list); mockLookupMap.put(id, externalDataObject); diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-record.xml b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-record.xml new file mode 100644 index 000000000000..7672e980c8bd --- /dev/null +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-record.xml @@ -0,0 +1,270 @@ + + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + + en + + + Direct + 2023-09-19T12:25:43.445Z + 2023-10-12T14:19:06.983Z + true + true + true + + + 2023-10-12T13:28:14.550Z + + 2023-09-19T12:25:43.736Z + 2023-09-19T12:25:43.736Z + Andrea + Bollini + + + 2023-10-12T13:28:14.550Z + + 2023-10-05T07:56:29.001Z + 2023-10-12T13:28:14.550Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + isco + + + 2023-10-12T13:28:14.541Z + 2023-10-12T13:28:14.541Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + Bollini, Andrea + + + + 2023-10-12T13:27:57.187Z + + 2023-10-12T10:35:14.406Z + 2023-10-12T13:27:57.187Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + Linkedin + https://it.linkedin.com/in/andreabollini + + + 2023-10-12T13:27:57.183Z + 2023-10-12T13:27:57.183Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + 4science + https://www.4science.it/ + + + + 2023-10-12T10:38:48.105Z + + 2023-10-12T10:33:21.077Z + 2023-10-12T10:38:48.105Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + test-orcid@mailinator.com + + + + + + 2023-09-04T09:04:52.121Z + + 2023-01-13T11:20:13.803Z + 2023-01-13T11:48:02.979Z + + + https://sandbox.orcid.org/client/0000-0002-3609-4817 + 0000-0002-3609-4817 + sandbox.orcid.org + + Scopus Wizard + + Scopus Author ID + 57432999200 + http://www.scopus.com/inward/authorDetails.url?authorID=57432999200&partnerID=MN8TOARS + self + + + 2023-01-19T14:25:14.512Z + 2023-01-19T14:25:14.512Z + + + https://sandbox.orcid.org/client/0000-0002-3609-4817 + 0000-0002-3609-4817 + sandbox.orcid.org + + Scopus Wizard + + Scopus Author ID + 35233141600 + http://www.scopus.com/inward/authorDetails.url?authorID=35233141600&partnerID=MN8TOARS + self + + + + + 2023-10-12T14:19:06.992Z + + + + 2023-10-12T10:52:26.965Z + + 2023-10-12T10:52:26.965Z + + + 2023-10-12T10:52:26.965Z + 2023-10-12T10:52:26.965Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + + Dspace + + Milan + IT + + + + + + 2023-10-12T10:35:49.079Z + + + 2023-10-12T10:34:17.514Z + 2023-10-12T10:35:49.079Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + + 4Science + + Milan + IT + + + https://ror.org/03vb2cr34 + ROR + + + + + + + + + + + + + + 2023-10-12T14:19:06.992Z + + 2023-10-12T14:19:06.992Z + + + doi + 10.1016/j.procs.2014.06.008 + 10.1016/j.procs.2014.06.008 + https://doi.org/10.1016/j.procs.2014.06.008 + self + + + eid + 55484808800 + 55484808800 + self + + + + 2023-10-12T14:09:25.415Z + 2023-10-12T14:19:06.992Z + + + https://sandbox.orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + sandbox.orcid.org + + Andrea Bollini + + + Publication Metadata in CERIF: Inspiration by FRBR + + + + doi + 10.1016/j.procs.2014.06.008 + 10.1016/j.procs.2014.06.008 + https://doi.org/10.1016/j.procs.2014.06.008 + self + + + issn + 1877-0509 + 1877-0509 + https://portal.issn.org/resource/ISSN/1877-0509 + part-of + + + eid + 55484808800 + 55484808800 + self + + + http://dx.doi.org/10.1016/j.procs.2014.06.008 + journal-article + + 2014 + + Procedia Computer Science + + + + + \ No newline at end of file diff --git a/dspace/config/modules/discovery.cfg b/dspace/config/modules/discovery.cfg index ddf01769952c..bdaa7b6042c5 100644 --- a/dspace/config/modules/discovery.cfg +++ b/dspace/config/modules/discovery.cfg @@ -28,6 +28,7 @@ discovery.index.projection=dc.title discovery.index.projection=dc.contributor.* discovery.index.projection=dc.date.issued discovery.index.projection=person.affiliation.name +discovery.index.projection=person.identifier.orcid # Allow auto-reindexing. # If any database migrations are applied to your database (via Flyway), then a diff --git a/dspace/config/spring/api/deduplication.xml b/dspace/config/spring/api/deduplication.xml index bdf2747f47b3..7dd4f1e7bd20 100644 --- a/dspace/config/spring/api/deduplication.xml +++ b/dspace/config/spring/api/deduplication.xml @@ -33,6 +33,7 @@ + @@ -48,6 +49,7 @@ + @@ -55,6 +57,7 @@ + @@ -62,6 +65,7 @@ + @@ -78,6 +82,7 @@ + diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 48b75831f991..ed9e94021895 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -3025,6 +3025,7 @@ organization.legalName + dc.title diff --git a/dspace/config/spring/api/external-services.xml b/dspace/config/spring/api/external-services.xml index 1b521ae700c8..1d91f89a053e 100644 --- a/dspace/config/spring/api/external-services.xml +++ b/dspace/config/spring/api/external-services.xml @@ -64,6 +64,12 @@ Person + + + + + + diff --git a/dspace/config/spring/rest/cris-authority-metadatagenerator.xml b/dspace/config/spring/rest/cris-authority-metadatagenerator.xml index 246e41093a36..e38b9c7beda0 100644 --- a/dspace/config/spring/rest/cris-authority-metadatagenerator.xml +++ b/dspace/config/spring/rest/cris-authority-metadatagenerator.xml @@ -30,6 +30,17 @@ + + + + + + + + + + + diff --git a/dspace/etc/migration/dspace_cris_migration_post_import.kjb b/dspace/etc/migration/dspace_cris_migration_post_import.kjb index b766c5d3723a..0c18927b5849 100644 --- a/dspace/etc/migration/dspace_cris_migration_post_import.kjb +++ b/dspace/etc/migration/dspace_cris_migration_post_import.kjb @@ -381,8 +381,8 @@ N Y 0 - 1448 - 112 + 1024 + 304 @@ -537,10 +537,49 @@ N Y 0 - 1290 + 1248 112 + + UPDATE dc_date_accessioned + + TRANS + + filename + + ${Internal.Entry.Current.Directory}/update_dc_date_accessioned.ktr + + N + N + N + N + N + N + + + N + N + Basic + N + + N + Y + N + N + N + Pentaho local + N + + Y + + N + Y + 1 + 1248 + 304 + + @@ -590,8 +629,17 @@ Migrate doi2item - Successo + UPDATE dc_date_accessioned 0 + 1 + Y + Y + N + + + UPDATE dc_date_accessioned + Successo + 1 0 Y Y diff --git a/dspace/etc/migration/update_dc_date_accessioned.ktr b/dspace/etc/migration/update_dc_date_accessioned.ktr new file mode 100644 index 000000000000..85be8c3c05b0 --- /dev/null +++ b/dspace/etc/migration/update_dc_date_accessioned.ktr @@ -0,0 +1,634 @@ + + + + udpate_dc_date_accessioned + + + + Normal + / + + + + + + + + + + + + ID_BATCH + Y + ID_BATCH + + + CHANNEL_ID + Y + CHANNEL_ID + + + TRANSNAME + Y + TRANSNAME + + + STATUS + Y + STATUS + + + LINES_READ + Y + LINES_READ + + + + LINES_WRITTEN + Y + LINES_WRITTEN + + + + LINES_UPDATED + Y + LINES_UPDATED + + + + LINES_INPUT + Y + LINES_INPUT + + + + LINES_OUTPUT + Y + LINES_OUTPUT + + + + LINES_REJECTED + Y + LINES_REJECTED + + + + ERRORS + Y + ERRORS + + + STARTDATE + Y + STARTDATE + + + ENDDATE + Y + ENDDATE + + + LOGDATE + Y + LOGDATE + + + DEPDATE + Y + DEPDATE + + + REPLAYDATE + Y + REPLAYDATE + + + LOG_FIELD + Y + LOG_FIELD + + + EXECUTING_SERVER + N + EXECUTING_SERVER + + + EXECUTING_USER + N + EXECUTING_USER + + + CLIENT + N + CLIENT + + + + + +
+ + + + ID_BATCH + Y + ID_BATCH + + + SEQ_NR + Y + SEQ_NR + + + LOGDATE + Y + LOGDATE + + + TRANSNAME + Y + TRANSNAME + + + STEPNAME + Y + STEPNAME + + + STEP_COPY + Y + STEP_COPY + + + LINES_READ + Y + LINES_READ + + + LINES_WRITTEN + Y + LINES_WRITTEN + + + LINES_UPDATED + Y + LINES_UPDATED + + + LINES_INPUT + Y + LINES_INPUT + + + LINES_OUTPUT + Y + LINES_OUTPUT + + + LINES_REJECTED + Y + LINES_REJECTED + + + ERRORS + Y + ERRORS + + + INPUT_BUFFER_ROWS + Y + INPUT_BUFFER_ROWS + + + OUTPUT_BUFFER_ROWS + Y + OUTPUT_BUFFER_ROWS + + + + + +
+ + + ID_BATCH + Y + ID_BATCH + + + CHANNEL_ID + Y + CHANNEL_ID + + + LOG_DATE + Y + LOG_DATE + + + LOGGING_OBJECT_TYPE + Y + LOGGING_OBJECT_TYPE + + + OBJECT_NAME + Y + OBJECT_NAME + + + OBJECT_COPY + Y + OBJECT_COPY + + + REPOSITORY_DIRECTORY + Y + REPOSITORY_DIRECTORY + + + FILENAME + Y + FILENAME + + + OBJECT_ID + Y + OBJECT_ID + + + OBJECT_REVISION + Y + OBJECT_REVISION + + + PARENT_CHANNEL_ID + Y + PARENT_CHANNEL_ID + + + ROOT_CHANNEL_ID + Y + ROOT_CHANNEL_ID + + + + + +
+ + + ID_BATCH + Y + ID_BATCH + + + CHANNEL_ID + Y + CHANNEL_ID + + + LOG_DATE + Y + LOG_DATE + + + TRANSNAME + Y + TRANSNAME + + + STEPNAME + Y + STEPNAME + + + STEP_COPY + Y + STEP_COPY + + + LINES_READ + Y + LINES_READ + + + LINES_WRITTEN + Y + LINES_WRITTEN + + + LINES_UPDATED + Y + LINES_UPDATED + + + LINES_INPUT + Y + LINES_INPUT + + + LINES_OUTPUT + Y + LINES_OUTPUT + + + LINES_REJECTED + Y + LINES_REJECTED + + + ERRORS + Y + ERRORS + + + LOG_FIELD + N + LOG_FIELD + + + + + +
+ + + ID_BATCH + Y + ID_BATCH + + + CHANNEL_ID + Y + CHANNEL_ID + + + LOG_DATE + Y + LOG_DATE + + + METRICS_DATE + Y + METRICS_DATE + + + METRICS_CODE + Y + METRICS_CODE + + + METRICS_DESCRIPTION + Y + METRICS_DESCRIPTION + + + METRICS_SUBJECT + Y + METRICS_SUBJECT + + + METRICS_TYPE + Y + METRICS_TYPE + + + METRICS_VALUE + Y + METRICS_VALUE + + + + + +
+ + 0.0 + 0.0 + + 10000 + 50 + 50 + N + Y + 50000 + Y + + N + 1000 + 100 + + + + + + + + + - + 2021/07/23 16:30:09.987 + - + 2021/07/23 16:30:09.987 + H4sIAAAAAAAAAAMAAAAAAAAAAAA= + N + + + + + dspace + ${db_host_name} + POSTGRESQL + Native + ${db_name} + ${db_port_number} + ${db_username} + ${db_password} + + + + + + EXTRA_OPTION_POSTGRESQL.stringtype + unspecified + + + FORCE_IDENTIFIERS_TO_LOWERCASE + N + + + FORCE_IDENTIFIERS_TO_UPPERCASE + N + + + IS_CLUSTERED + N + + + PORT_NUMBER + ${db_port_number} + + + PRESERVE_RESERVED_WORD_CASE + Y + + + QUOTE_ALL_FIELDS + N + + + SUPPORTS_BOOLEAN_DATA_TYPE + Y + + + SUPPORTS_TIMESTAMP_DATA_TYPE + Y + + + USE_POOLING + N + + + + + + Generate rows + Execute SQL script + Y + + + + Execute SQL script + ExecSQL + + Y + + 1 + + none + + + dspace + N + Y + N + N +DO $$ +DECLARE + row_data record; + metadataFieldLegacyId INT; + metadataFieldDateId INT; + row_count integer := 0; +BEGIN + + SELECT m.metadata_field_id + INTO metadataFieldLegacyId + FROM metadatafieldregistry m JOIN metadataschemaregistry s + ON m.metadata_schema_id = s.metadata_schema_id + WHERE s.short_id = 'cris' AND m.element = 'legacyId'; + + SELECT m.metadata_field_id + INTO metadataFieldDateId + FROM metadatafieldregistry m JOIN metadataschemaregistry s + ON m.metadata_schema_id = s.metadata_schema_id + WHERE s.short_id = 'dc' AND m.element = 'date' AND m.qualifier = 'accessioned'; + + FOR row_data IN ( + SELECT m.dspace_object_id, d.timestampcreated + FROM old_cris_do d + JOIN metadatavalue m ON d.crisid = m.text_value + WHERE m.metadata_field_id = metadataFieldLegacyId + + UNION ALL + SELECT m.dspace_object_id, d.timestampcreated + FROM old_cris_rpage d + JOIN metadatavalue m ON d.crisid = m.text_value + WHERE m.metadata_field_id = metadataFieldLegacyId + + UNION ALL + SELECT m.dspace_object_id, d.timestampcreated + FROM old_cris_project d + JOIN metadatavalue m ON d.crisid = m.text_value + WHERE m.metadata_field_id = metadataFieldLegacyId + + UNION ALL + SELECT m.dspace_object_id, d.timestampcreated + FROM old_cris_orgunit d + JOIN metadatavalue m ON d.crisid = m.text_value + WHERE m.metadata_field_id = metadataFieldLegacyId + + ) + LOOP + UPDATE metadatavalue + SET text_value = TO_CHAR(row_data.timestampcreated, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') + WHERE dspace_object_id = row_data.dspace_object_id + AND metadata_field_id = metadataFieldDateId; + + RAISE INFO 'Updating DSpace object with uuid %', row_data.dspace_object_id; + RAISE INFO 'New date is %', TO_CHAR(row_data.timestampcreated, 'YYYY-MM-DD"T"HH24:MI:SS"Z"'); + + row_count := row_count + 1; + END LOOP; + RAISE NOTICE 'Total items processed: %', row_count; +END $$; + + N + + + + + + + + + + + + + + + + 320 + 176 + Y + + + + Generate rows + RowGenerator + + Y + + 1 + + none + + + + + 1 + N + 5000 + now + FiveSecondsAgo + + + + + + + + + + 112 + 176 + Y + + + + + + + N + +