mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00
Merge pull request #8268 from 4Science/CST-5799
Porting of OrcidPublicationDataProvider
This commit is contained in:
547
dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidPublicationDataProvider.java
vendored
Normal file
547
dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidPublicationDataProvider.java
vendored
Normal file
@@ -0,0 +1,547 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.external.provider.impl;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
import static java.util.Comparator.comparing;
|
||||||
|
import static java.util.Comparator.reverseOrder;
|
||||||
|
import static java.util.Optional.ofNullable;
|
||||||
|
import static org.apache.commons.collections4.ListUtils.partition;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
import static org.orcid.jaxb.model.common.CitationType.FORMATTED_UNSPECIFIED;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.MetadataFieldName;
|
||||||
|
import org.dspace.content.dto.MetadataValueDTO;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.external.model.ExternalDataObject;
|
||||||
|
import org.dspace.external.provider.AbstractExternalDataProvider;
|
||||||
|
import org.dspace.external.provider.ExternalDataProvider;
|
||||||
|
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||||
|
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
|
||||||
|
import org.dspace.importer.external.service.ImportService;
|
||||||
|
import org.dspace.orcid.OrcidToken;
|
||||||
|
import org.dspace.orcid.client.OrcidClient;
|
||||||
|
import org.dspace.orcid.client.OrcidConfiguration;
|
||||||
|
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
||||||
|
import org.dspace.orcid.model.OrcidWorkFieldMapping;
|
||||||
|
import org.dspace.orcid.service.OrcidSynchronizationService;
|
||||||
|
import org.dspace.orcid.service.OrcidTokenService;
|
||||||
|
import org.dspace.web.ContextUtil;
|
||||||
|
import org.orcid.jaxb.model.common.ContributorRole;
|
||||||
|
import org.orcid.jaxb.model.common.WorkType;
|
||||||
|
import org.orcid.jaxb.model.v3.release.common.Contributor;
|
||||||
|
import org.orcid.jaxb.model.v3.release.common.ContributorAttributes;
|
||||||
|
import org.orcid.jaxb.model.v3.release.common.PublicationDate;
|
||||||
|
import org.orcid.jaxb.model.v3.release.common.Subtitle;
|
||||||
|
import org.orcid.jaxb.model.v3.release.common.Title;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.Citation;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.ExternalIDs;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.SourceAware;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.Work;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.WorkBulk;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.WorkContributors;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.WorkTitle;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.summary.WorkGroup;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.summary.WorkSummary;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.summary.Works;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link ExternalDataProvider} that search for all the works
|
||||||
|
* of the profile with the given orcid id that hava a source other than DSpace.
|
||||||
|
* The id of the external data objects returned by the methods of this class is
|
||||||
|
* the concatenation of the orcid id and the put code associated with the
|
||||||
|
* publication, separated by :: (example 0000-0000-0123-4567::123456)
|
||||||
|
*
|
||||||
|
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class OrcidPublicationDataProvider extends AbstractExternalDataProvider {
|
||||||
|
|
||||||
|
private final static Logger LOGGER = LoggerFactory.getLogger(OrcidPublicationDataProvider.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Examples of valid ORCID IDs:
|
||||||
|
* <ul>
|
||||||
|
* <li>0000-0002-1825-0097</li>
|
||||||
|
* <li>0000-0001-5109-3700</li>
|
||||||
|
* <li>0000-0002-1694-233X</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
private final static Pattern ORCID_ID_PATTERN = Pattern.compile("(\\d{4}-){3}\\d{3}(\\d|X)");
|
||||||
|
|
||||||
|
private final static int MAX_PUT_CODES_SIZE = 100;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OrcidClient orcidClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OrcidConfiguration orcidConfiguration;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OrcidSynchronizationService orcidSynchronizationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ImportService importService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OrcidTokenService orcidTokenService;
|
||||||
|
|
||||||
|
private OrcidWorkFieldMapping fieldMapping;
|
||||||
|
|
||||||
|
private String sourceIdentifier;
|
||||||
|
|
||||||
|
private String readPublicAccessToken;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ExternalDataObject> getExternalDataObject(String id) {
|
||||||
|
|
||||||
|
if (isInvalidIdentifier(id)) {
|
||||||
|
throw new IllegalArgumentException("Invalid identifier '" + id + "', expected <orcid-id>::<put-code>");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] idSections = id.split("::");
|
||||||
|
String orcid = idSections[0];
|
||||||
|
String putCode = idSections[1];
|
||||||
|
|
||||||
|
validateOrcidId(orcid);
|
||||||
|
|
||||||
|
return getWork(orcid, putCode)
|
||||||
|
.filter(work -> hasDifferentSourceClientId(work))
|
||||||
|
.filter(work -> work.getPutCode() != null)
|
||||||
|
.map(work -> convertToExternalDataObject(orcid, work));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ExternalDataObject> searchExternalDataObjects(String orcid, int start, int limit) {
|
||||||
|
|
||||||
|
validateOrcidId(orcid);
|
||||||
|
|
||||||
|
return findWorks(orcid, start, limit).stream()
|
||||||
|
.map(work -> convertToExternalDataObject(orcid, work))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInvalidIdentifier(String id) {
|
||||||
|
return StringUtils.isBlank(id) || id.split("::").length != 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateOrcidId(String orcid) {
|
||||||
|
if (!ORCID_ID_PATTERN.matcher(orcid).matches()) {
|
||||||
|
throw new IllegalArgumentException("The given ORCID ID is not valid: " + orcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the works related to the given ORCID in the range from start and
|
||||||
|
* limit.
|
||||||
|
*
|
||||||
|
* @param orcid the ORCID ID of the author to search for works
|
||||||
|
* @param start the start index
|
||||||
|
* @param limit the limit index
|
||||||
|
* @return the list of the works
|
||||||
|
*/
|
||||||
|
private List<Work> findWorks(String orcid, int start, int limit) {
|
||||||
|
List<WorkSummary> workSummaries = findWorkSummaries(orcid, start, limit);
|
||||||
|
return findWorks(orcid, workSummaries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the works summaries related to the given ORCID in the range from
|
||||||
|
* start and limit.
|
||||||
|
*
|
||||||
|
* @param orcid the ORCID ID of the author to search for works summaries
|
||||||
|
* @param start the start index
|
||||||
|
* @param limit the limit index
|
||||||
|
* @return the list of the works summaries
|
||||||
|
*/
|
||||||
|
private List<WorkSummary> findWorkSummaries(String orcid, int start, int limit) {
|
||||||
|
return getWorks(orcid).getWorkGroup().stream()
|
||||||
|
.filter(workGroup -> allWorkSummariesHaveDifferentSourceClientId(workGroup))
|
||||||
|
.map(workGroup -> getPreferredWorkSummary(workGroup))
|
||||||
|
.flatMap(Optional::stream)
|
||||||
|
.skip(start)
|
||||||
|
.limit(limit > 0 ? limit : Long.MAX_VALUE)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the works related to the given ORCID ID and work summaries (a
|
||||||
|
* work has more details than a work summary).
|
||||||
|
*
|
||||||
|
* @param orcid the ORCID id of the author to search for works
|
||||||
|
* @param workSummaries the work summaries used to search the related works
|
||||||
|
* @return the list of the works
|
||||||
|
*/
|
||||||
|
private List<Work> findWorks(String orcid, List<WorkSummary> workSummaries) {
|
||||||
|
|
||||||
|
List<String> workPutCodes = getPutCodes(workSummaries);
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(workPutCodes)) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workPutCodes.size() == 1) {
|
||||||
|
return getWork(orcid, workPutCodes.get(0)).stream().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return partition(workPutCodes, MAX_PUT_CODES_SIZE).stream()
|
||||||
|
.map(putCodes -> getWorkBulk(orcid, putCodes))
|
||||||
|
.flatMap(workBulk -> getWorks(workBulk).stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search a work by ORCID id and putcode, using API or PUBLIC urls based on
|
||||||
|
* whether the ORCID API keys are configured or not.
|
||||||
|
*
|
||||||
|
* @param orcid the ORCID ID
|
||||||
|
* @param putCode the work's identifier on ORCID
|
||||||
|
* @return the work, if any
|
||||||
|
*/
|
||||||
|
private Optional<Work> getWork(String orcid, String putCode) {
|
||||||
|
if (orcidConfiguration.isApiConfigured()) {
|
||||||
|
String accessToken = getAccessToken(orcid);
|
||||||
|
return orcidClient.getObject(accessToken, orcid, putCode, Work.class);
|
||||||
|
} else {
|
||||||
|
return orcidClient.getObject(orcid, putCode, Work.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the works related to the given ORCID.
|
||||||
|
*
|
||||||
|
* @param orcid the ORCID ID of the author to search for works
|
||||||
|
* @return the list of the works
|
||||||
|
*/
|
||||||
|
private Works getWorks(String orcid) {
|
||||||
|
if (orcidConfiguration.isApiConfigured()) {
|
||||||
|
String accessToken = getAccessToken(orcid);
|
||||||
|
return orcidClient.getWorks(accessToken, orcid);
|
||||||
|
} else {
|
||||||
|
return orcidClient.getWorks(orcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the works related to the given ORCID by the given putCodes.
|
||||||
|
*
|
||||||
|
* @param orcid the ORCID ID of the author to search for works
|
||||||
|
* @param putCodes the work's put codes to search
|
||||||
|
* @return the list of the works
|
||||||
|
*/
|
||||||
|
private WorkBulk getWorkBulk(String orcid, List<String> putCodes) {
|
||||||
|
if (orcidConfiguration.isApiConfigured()) {
|
||||||
|
String accessToken = getAccessToken(orcid);
|
||||||
|
return orcidClient.getWorkBulk(accessToken, orcid, putCodes);
|
||||||
|
} else {
|
||||||
|
return orcidClient.getWorkBulk(orcid, putCodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getAccessToken(String orcid) {
|
||||||
|
List<Item> items = orcidSynchronizationService.findProfilesByOrcid(new Context(), orcid);
|
||||||
|
return Optional.ofNullable(items.isEmpty() ? null : items.get(0))
|
||||||
|
.flatMap(item -> getAccessToken(item))
|
||||||
|
.orElseGet(() -> getReadPublicAccessToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> getAccessToken(Item item) {
|
||||||
|
return ofNullable(orcidTokenService.findByProfileItem(getContext(), item))
|
||||||
|
.map(OrcidToken::getAccessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getReadPublicAccessToken() {
|
||||||
|
if (readPublicAccessToken != null) {
|
||||||
|
return readPublicAccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
OrcidTokenResponseDTO accessTokenResponse = orcidClient.getReadPublicAccessToken();
|
||||||
|
readPublicAccessToken = accessTokenResponse.getAccessToken();
|
||||||
|
|
||||||
|
return readPublicAccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Work> getWorks(WorkBulk workBulk) {
|
||||||
|
return workBulk.getBulk().stream()
|
||||||
|
.filter(bulkElement -> (bulkElement instanceof Work))
|
||||||
|
.map(bulkElement -> ((Work) bulkElement))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getPutCodes(List<WorkSummary> workSummaries) {
|
||||||
|
return workSummaries.stream()
|
||||||
|
.map(WorkSummary::getPutCode)
|
||||||
|
.map(String::valueOf)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<WorkSummary> getPreferredWorkSummary(WorkGroup workGroup) {
|
||||||
|
return workGroup.getWorkSummary().stream()
|
||||||
|
.filter(work -> work.getPutCode() != null)
|
||||||
|
.filter(work -> NumberUtils.isCreatable(work.getDisplayIndex()))
|
||||||
|
.sorted(comparing(work -> Integer.valueOf(work.getDisplayIndex()), reverseOrder()))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExternalDataObject convertToExternalDataObject(String orcid, Work work) {
|
||||||
|
ExternalDataObject externalDataObject = new ExternalDataObject(sourceIdentifier);
|
||||||
|
externalDataObject.setId(orcid + "::" + work.getPutCode().toString());
|
||||||
|
|
||||||
|
String title = getWorkTitle(work);
|
||||||
|
externalDataObject.setDisplayValue(title);
|
||||||
|
externalDataObject.setValue(title);
|
||||||
|
|
||||||
|
addMetadataValue(externalDataObject, fieldMapping.getTitleField(), () -> title);
|
||||||
|
addMetadataValue(externalDataObject, fieldMapping.getTypeField(), () -> getWorkType(work));
|
||||||
|
addMetadataValue(externalDataObject, fieldMapping.getPublicationDateField(), () -> getPublicationDate(work));
|
||||||
|
addMetadataValue(externalDataObject, fieldMapping.getJournalTitleField(), () -> getJournalTitle(work));
|
||||||
|
addMetadataValue(externalDataObject, fieldMapping.getSubTitleField(), () -> getSubTitleField(work));
|
||||||
|
addMetadataValue(externalDataObject, fieldMapping.getShortDescriptionField(), () -> getDescription(work));
|
||||||
|
addMetadataValue(externalDataObject, fieldMapping.getLanguageField(), () -> getLanguage(work));
|
||||||
|
|
||||||
|
for (String contributorField : fieldMapping.getContributorFields().keySet()) {
|
||||||
|
ContributorRole role = fieldMapping.getContributorFields().get(contributorField);
|
||||||
|
addMetadataValues(externalDataObject, contributorField, () -> getContributors(work, role));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String externalIdField : fieldMapping.getExternalIdentifierFields().keySet()) {
|
||||||
|
String type = fieldMapping.getExternalIdentifierFields().get(externalIdField);
|
||||||
|
addMetadataValues(externalDataObject, externalIdField, () -> getExternalIds(work, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
addMetadataValuesFromCitation(externalDataObject, work.getWorkCitation());
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("An error occurs reading the following citation: " + work.getWorkCitation().getCitation(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return externalDataObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean allWorkSummariesHaveDifferentSourceClientId(WorkGroup workGroup) {
|
||||||
|
return workGroup.getWorkSummary().stream().allMatch(this::hasDifferentSourceClientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private boolean hasDifferentSourceClientId(SourceAware sourceAware) {
|
||||||
|
return Optional.ofNullable(sourceAware.getSource())
|
||||||
|
.map(source -> source.getSourceClientId())
|
||||||
|
.map(sourceClientId -> sourceClientId.getPath())
|
||||||
|
.map(clientId -> !StringUtils.equals(orcidConfiguration.getClientId(), clientId))
|
||||||
|
.orElse(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMetadataValues(ExternalDataObject externalData, String metadata, Supplier<List<String>> values) {
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(metadata)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetadataFieldName field = new MetadataFieldName(metadata);
|
||||||
|
for (String value : values.get()) {
|
||||||
|
externalData.addMetadata(new MetadataValueDTO(field.schema, field.element, field.qualifier, null, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMetadataValue(ExternalDataObject externalData, String metadata, Supplier<String> valueSupplier) {
|
||||||
|
addMetadataValues(externalData, metadata, () -> {
|
||||||
|
String value = valueSupplier.get();
|
||||||
|
return isNotBlank(value) ? List.of(value) : emptyList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getWorkTitle(Work work) {
|
||||||
|
WorkTitle workTitle = work.getWorkTitle();
|
||||||
|
if (workTitle == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Title title = workTitle.getTitle();
|
||||||
|
return title != null ? title.getContent() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getWorkType(Work work) {
|
||||||
|
WorkType workType = work.getWorkType();
|
||||||
|
return workType != null ? fieldMapping.convertType(workType.value()) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPublicationDate(Work work) {
|
||||||
|
PublicationDate publicationDate = work.getPublicationDate();
|
||||||
|
if (publicationDate == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder(publicationDate.getYear().getValue());
|
||||||
|
if (publicationDate.getMonth() != null) {
|
||||||
|
builder.append("-");
|
||||||
|
builder.append(publicationDate.getMonth().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publicationDate.getDay() != null) {
|
||||||
|
builder.append("-");
|
||||||
|
builder.append(publicationDate.getDay().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getJournalTitle(Work work) {
|
||||||
|
Title journalTitle = work.getJournalTitle();
|
||||||
|
return journalTitle != null ? journalTitle.getContent() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSubTitleField(Work work) {
|
||||||
|
WorkTitle workTitle = work.getWorkTitle();
|
||||||
|
if (workTitle == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Subtitle subTitle = workTitle.getSubtitle();
|
||||||
|
return subTitle != null ? subTitle.getContent() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDescription(Work work) {
|
||||||
|
return work.getShortDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLanguage(Work work) {
|
||||||
|
return work.getLanguageCode() != null ? fieldMapping.convertLanguage(work.getLanguageCode()) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getContributors(Work work, ContributorRole role) {
|
||||||
|
WorkContributors workContributors = work.getWorkContributors();
|
||||||
|
if (workContributors == null) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return workContributors.getContributor().stream()
|
||||||
|
.filter(contributor -> hasRole(contributor, role))
|
||||||
|
.map(contributor -> getContributorName(contributor))
|
||||||
|
.flatMap(Optional::stream)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMetadataValuesFromCitation(ExternalDataObject externalDataObject, Citation citation)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
if (citation == null || citation.getWorkCitationType() == FORMATTED_UNSPECIFIED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getImportRecord(citation).ifPresent(importRecord -> enrichExternalDataObject(externalDataObject, importRecord));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ImportRecord> getImportRecord(Citation citation) throws Exception {
|
||||||
|
File citationFile = File.createTempFile("temp", "." + citation.getWorkCitationType().value());
|
||||||
|
try (FileOutputStream outputStream = new FileOutputStream(citationFile)) {
|
||||||
|
IOUtils.write(citation.getCitation(), new FileOutputStream(citationFile), Charset.defaultCharset());
|
||||||
|
return Optional.ofNullable(importService.getRecord(citationFile, citationFile.getName()));
|
||||||
|
} finally {
|
||||||
|
citationFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enrichExternalDataObject(ExternalDataObject externalDataObject, ImportRecord importRecord) {
|
||||||
|
importRecord.getValueList().stream()
|
||||||
|
.filter(metadata -> doesNotContains(externalDataObject, metadata))
|
||||||
|
.forEach(metadata -> addMetadata(externalDataObject, metadata));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMetadata(ExternalDataObject externalDataObject, MetadatumDTO metadata) {
|
||||||
|
externalDataObject.addMetadata(new MetadataValueDTO(metadata.getSchema(), metadata.getElement(),
|
||||||
|
metadata.getQualifier(), null, metadata.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doesNotContains(ExternalDataObject externalDataObject, MetadatumDTO metadata) {
|
||||||
|
return externalDataObject.getMetadata().stream()
|
||||||
|
.filter(metadataValue -> StringUtils.equals(metadataValue.getSchema(), metadata.getSchema()))
|
||||||
|
.filter(metadataValue -> StringUtils.equals(metadataValue.getElement(), metadata.getElement()))
|
||||||
|
.filter(metadataValue -> StringUtils.equals(metadataValue.getQualifier(), metadata.getQualifier()))
|
||||||
|
.findAny().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasRole(Contributor contributor, ContributorRole role) {
|
||||||
|
ContributorAttributes attributes = contributor.getContributorAttributes();
|
||||||
|
return attributes != null ? role.equals(attributes.getContributorRole()) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> getContributorName(Contributor contributor) {
|
||||||
|
return Optional.ofNullable(contributor.getCreditName())
|
||||||
|
.map(creditName -> creditName.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getExternalIds(Work work, String type) {
|
||||||
|
ExternalIDs externalIdentifiers = work.getExternalIdentifiers();
|
||||||
|
if (externalIdentifiers == null) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return externalIdentifiers.getExternalIdentifier().stream()
|
||||||
|
.filter(externalId -> type.equals(externalId.getType()))
|
||||||
|
.map(externalId -> externalId.getValue())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Context getContext() {
|
||||||
|
Context context = ContextUtil.obtainCurrentRequestContext();
|
||||||
|
return context != null ? context : new Context();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(String source) {
|
||||||
|
return StringUtils.equals(sourceIdentifier, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfResults(String orcid) {
|
||||||
|
return findWorkSummaries(orcid, 0, -1).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceIdentifier(String sourceIdentifier) {
|
||||||
|
this.sourceIdentifier = sourceIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceIdentifier() {
|
||||||
|
return sourceIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldMapping(OrcidWorkFieldMapping fieldMapping) {
|
||||||
|
this.fieldMapping = fieldMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadPublicAccessToken(String readPublicAccessToken) {
|
||||||
|
this.readPublicAccessToken = readPublicAccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrcidClient getOrcidClient() {
|
||||||
|
return orcidClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrcidClient(OrcidClient orcidClient) {
|
||||||
|
this.orcidClient = orcidClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -7,9 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.orcid.client;
|
package org.dspace.orcid.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.dspace.orcid.exception.OrcidClientException;
|
import org.dspace.orcid.exception.OrcidClientException;
|
||||||
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
||||||
import org.orcid.jaxb.model.v3.release.record.Person;
|
import org.orcid.jaxb.model.v3.release.record.Person;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.WorkBulk;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.summary.Works;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for classes that allow to contact ORCID.
|
* Interface for classes that allow to contact ORCID.
|
||||||
@@ -19,6 +24,15 @@ import org.orcid.jaxb.model.v3.release.record.Person;
|
|||||||
*/
|
*/
|
||||||
public interface OrcidClient {
|
public interface OrcidClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an /read-public access token using a client-credentials OAuth flow,
|
||||||
|
* or 2-step OAuth.
|
||||||
|
*
|
||||||
|
* @return the ORCID token
|
||||||
|
* @throws OrcidClientException if some error occurs during the exchange
|
||||||
|
*/
|
||||||
|
OrcidTokenResponseDTO getReadPublicAccessToken();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exchange the authorization code for an ORCID iD and 3-legged access token.
|
* Exchange the authorization code for an ORCID iD and 3-legged access token.
|
||||||
* The authorization code expires upon use.
|
* The authorization code expires upon use.
|
||||||
@@ -39,6 +53,75 @@ public interface OrcidClient {
|
|||||||
*/
|
*/
|
||||||
Person getPerson(String accessToken, String orcid);
|
Person getPerson(String accessToken, String orcid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the works related to the given orcid.
|
||||||
|
*
|
||||||
|
* @param accessToken the access token
|
||||||
|
* @param orcid the orcid id related to the works
|
||||||
|
* @return the Works
|
||||||
|
* @throws OrcidClientException if some error occurs during the search
|
||||||
|
*/
|
||||||
|
Works getWorks(String accessToken, String orcid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the works related to the given orcid.
|
||||||
|
*
|
||||||
|
* @param orcid the orcid id related to the works
|
||||||
|
* @return the Works
|
||||||
|
* @throws OrcidClientException if some error occurs during the search
|
||||||
|
*/
|
||||||
|
Works getWorks(String orcid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the works with the given putCodes related to the given orcid
|
||||||
|
*
|
||||||
|
* @param accessToken the access token
|
||||||
|
* @param orcid the orcid id
|
||||||
|
* @param putCodes the putCodes of the works to retrieve
|
||||||
|
* @return the Works
|
||||||
|
* @throws OrcidClientException if some error occurs during the search
|
||||||
|
*/
|
||||||
|
WorkBulk getWorkBulk(String accessToken, String orcid, List<String> putCodes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the works with the given putCodes related to the given orcid
|
||||||
|
*
|
||||||
|
* @param orcid the orcid id
|
||||||
|
* @param putCodes the putCodes of the works to retrieve
|
||||||
|
* @return the Works
|
||||||
|
* @throws OrcidClientException if some error occurs during the search
|
||||||
|
*/
|
||||||
|
WorkBulk getWorkBulk(String orcid, List<String> putCodes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an object from ORCID with the given putCode related to the given
|
||||||
|
* orcid.
|
||||||
|
*
|
||||||
|
* @param accessToken the access token
|
||||||
|
* @param orcid the orcid id
|
||||||
|
* @param putCode the object's put code
|
||||||
|
* @param clazz the object's class
|
||||||
|
* @return the Object, if any
|
||||||
|
* @throws OrcidClientException if some error occurs during the search
|
||||||
|
* @throws IllegalArgumentException if the given object class is not an valid
|
||||||
|
* ORCID object
|
||||||
|
*/
|
||||||
|
<T> Optional<T> getObject(String accessToken, String orcid, String putCode, Class<T> clazz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an object from ORCID with the given putCode related to the given
|
||||||
|
* orcid using the public API.
|
||||||
|
*
|
||||||
|
* @param orcid the orcid id
|
||||||
|
* @param putCode the object's put code
|
||||||
|
* @param clazz the object's class
|
||||||
|
* @return the Object, if any
|
||||||
|
* @throws OrcidClientException if some error occurs during the search
|
||||||
|
* @throws IllegalArgumentException if the given object class is not an valid
|
||||||
|
* ORCID object
|
||||||
|
*/
|
||||||
|
<T> Optional<T> getObject(String orcid, String putCode, Class<T> clazz);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push the given object to ORCID.
|
* Push the given object to ORCID.
|
||||||
*
|
*
|
||||||
|
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
import javax.xml.bind.Marshaller;
|
import javax.xml.bind.Marshaller;
|
||||||
@@ -54,6 +55,8 @@ import org.orcid.jaxb.model.v3.release.record.Person;
|
|||||||
import org.orcid.jaxb.model.v3.release.record.PersonExternalIdentifier;
|
import org.orcid.jaxb.model.v3.release.record.PersonExternalIdentifier;
|
||||||
import org.orcid.jaxb.model.v3.release.record.ResearcherUrl;
|
import org.orcid.jaxb.model.v3.release.record.ResearcherUrl;
|
||||||
import org.orcid.jaxb.model.v3.release.record.Work;
|
import org.orcid.jaxb.model.v3.release.record.Work;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.WorkBulk;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.summary.Works;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link OrcidClient}.
|
* Implementation of {@link OrcidClient}.
|
||||||
@@ -114,6 +117,50 @@ public class OrcidClientImpl implements OrcidClient {
|
|||||||
return executeAndUnmarshall(httpUriRequest, false, Person.class);
|
return executeAndUnmarshall(httpUriRequest, false, Person.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Works getWorks(String accessToken, String orcid) {
|
||||||
|
HttpUriRequest httpUriRequest = buildGetUriRequest(accessToken, "/" + orcid + "/works");
|
||||||
|
Works works = executeAndUnmarshall(httpUriRequest, true, Works.class);
|
||||||
|
return works != null ? works : new Works();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Works getWorks(String orcid) {
|
||||||
|
HttpUriRequest httpUriRequest = buildGetUriRequestToPublicEndpoint("/" + orcid + "/works");
|
||||||
|
Works works = executeAndUnmarshall(httpUriRequest, true, Works.class);
|
||||||
|
return works != null ? works : new Works();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkBulk getWorkBulk(String accessToken, String orcid, List<String> putCodes) {
|
||||||
|
String putCode = String.join(",", putCodes);
|
||||||
|
HttpUriRequest httpUriRequest = buildGetUriRequest(accessToken, "/" + orcid + "/works/" + putCode);
|
||||||
|
WorkBulk workBulk = executeAndUnmarshall(httpUriRequest, true, WorkBulk.class);
|
||||||
|
return workBulk != null ? workBulk : new WorkBulk();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkBulk getWorkBulk(String orcid, List<String> putCodes) {
|
||||||
|
String putCode = String.join(",", putCodes);
|
||||||
|
HttpUriRequest httpUriRequest = buildGetUriRequestToPublicEndpoint("/" + orcid + "/works/" + putCode);
|
||||||
|
WorkBulk workBulk = executeAndUnmarshall(httpUriRequest, true, WorkBulk.class);
|
||||||
|
return workBulk != null ? workBulk : new WorkBulk();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Optional<T> getObject(String accessToken, String orcid, String putCode, Class<T> clazz) {
|
||||||
|
String path = getOrcidPathFromOrcidObjectType(clazz);
|
||||||
|
HttpUriRequest httpUriRequest = buildGetUriRequest(accessToken, "/" + orcid + path + "/" + putCode);
|
||||||
|
return Optional.ofNullable(executeAndUnmarshall(httpUriRequest, true, clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Optional<T> getObject(String orcid, String putCode, Class<T> clazz) {
|
||||||
|
String path = getOrcidPathFromOrcidObjectType(clazz);
|
||||||
|
HttpUriRequest httpUriRequest = buildGetUriRequestToPublicEndpoint("/" + orcid + path + "/" + putCode);
|
||||||
|
return Optional.ofNullable(executeAndUnmarshall(httpUriRequest, true, clazz));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OrcidResponse push(String accessToken, String orcid, Object object) {
|
public OrcidResponse push(String accessToken, String orcid, Object object) {
|
||||||
String path = getOrcidPathFromOrcidObjectType(object.getClass());
|
String path = getOrcidPathFromOrcidObjectType(object.getClass());
|
||||||
@@ -131,6 +178,27 @@ public class OrcidClientImpl implements OrcidClient {
|
|||||||
return execute(buildDeleteUriRequest(accessToken, "/" + orcid + path + "/" + putCode), true);
|
return execute(buildDeleteUriRequest(accessToken, "/" + orcid + path + "/" + putCode), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OrcidTokenResponseDTO getReadPublicAccessToken() {
|
||||||
|
return getClientCredentialsAccessToken("/read-public");
|
||||||
|
}
|
||||||
|
|
||||||
|
private OrcidTokenResponseDTO getClientCredentialsAccessToken(String scope) {
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("scope", scope));
|
||||||
|
params.add(new BasicNameValuePair("grant_type", "client_credentials"));
|
||||||
|
params.add(new BasicNameValuePair("client_id", orcidConfiguration.getClientId()));
|
||||||
|
params.add(new BasicNameValuePair("client_secret", orcidConfiguration.getClientSecret()));
|
||||||
|
|
||||||
|
HttpUriRequest httpUriRequest = RequestBuilder.post(orcidConfiguration.getTokenEndpointUrl())
|
||||||
|
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.setEntity(new UrlEncodedFormEntity(params, Charset.defaultCharset()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return executeAndParseJson(httpUriRequest, OrcidTokenResponseDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
private HttpUriRequest buildGetUriRequest(String accessToken, String relativePath) {
|
private HttpUriRequest buildGetUriRequest(String accessToken, String relativePath) {
|
||||||
return get(orcidConfiguration.getApiUrl() + relativePath.trim())
|
return get(orcidConfiguration.getApiUrl() + relativePath.trim())
|
||||||
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||||
@@ -138,6 +206,12 @@ public class OrcidClientImpl implements OrcidClient {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HttpUriRequest buildGetUriRequestToPublicEndpoint(String relativePath) {
|
||||||
|
return get(orcidConfiguration.getPublicUrl() + relativePath.trim())
|
||||||
|
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private HttpUriRequest buildPostUriRequest(String accessToken, String relativePath, Object object) {
|
private HttpUriRequest buildPostUriRequest(String accessToken, String relativePath, Object object) {
|
||||||
return post(orcidConfiguration.getApiUrl() + relativePath.trim())
|
return post(orcidConfiguration.getApiUrl() + relativePath.trim())
|
||||||
.addHeader("Content-Type", "application/vnd.orcid+xml")
|
.addHeader("Content-Type", "application/vnd.orcid+xml")
|
||||||
|
@@ -107,4 +107,8 @@ public final class OrcidConfiguration {
|
|||||||
this.publicUrl = publicUrl;
|
this.publicUrl = publicUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isApiConfigured() {
|
||||||
|
return !StringUtils.isAnyBlank(clientId, clientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -155,4 +155,13 @@ public interface OrcidSynchronizationService {
|
|||||||
* @return the disconnection mode
|
* @return the disconnection mode
|
||||||
*/
|
*/
|
||||||
OrcidProfileDisconnectionMode getDisconnectionMode();
|
OrcidProfileDisconnectionMode getDisconnectionMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the profiles with the given orcid id.
|
||||||
|
*
|
||||||
|
* @param context the relevant DSpace Context.
|
||||||
|
* @param orcid the orcid id to search for
|
||||||
|
* @return the found profile items
|
||||||
|
*/
|
||||||
|
List<Item> findProfilesByOrcid(Context context, String orcid);
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,10 @@ import org.dspace.content.Item;
|
|||||||
import org.dspace.content.MetadataValue;
|
import org.dspace.content.MetadataValue;
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.discovery.DiscoverQuery;
|
||||||
|
import org.dspace.discovery.SearchService;
|
||||||
|
import org.dspace.discovery.SearchServiceException;
|
||||||
|
import org.dspace.discovery.indexobject.IndexableItem;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.service.EPersonService;
|
import org.dspace.eperson.service.EPersonService;
|
||||||
import org.dspace.orcid.OrcidToken;
|
import org.dspace.orcid.OrcidToken;
|
||||||
@@ -62,6 +66,9 @@ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationServ
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EPersonService ePersonService;
|
private EPersonService ePersonService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SearchService searchService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private OrcidTokenService orcidTokenService;
|
private OrcidTokenService orcidTokenService;
|
||||||
|
|
||||||
@@ -306,4 +313,19 @@ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationServ
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Item> findProfilesByOrcid(Context context, String orcid) {
|
||||||
|
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||||
|
discoverQuery.setDSpaceObjectFilter(IndexableItem.TYPE);
|
||||||
|
discoverQuery.addFilterQueries("search.entitytype:" + researcherProfileService.getProfileType());
|
||||||
|
discoverQuery.addFilterQueries("person.identifier.orcid:" + orcid);
|
||||||
|
try {
|
||||||
|
return searchService.search(context, discoverQuery).getIndexableObjects().stream()
|
||||||
|
.map(object -> ((IndexableItem) object).getIndexedObject())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
} catch (SearchServiceException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -57,6 +57,16 @@
|
|||||||
<bean id="orcidRestConnector" class="org.dspace.external.OrcidRestConnector">
|
<bean id="orcidRestConnector" class="org.dspace.external.OrcidRestConnector">
|
||||||
<constructor-arg value="${orcid.api-url}"/>
|
<constructor-arg value="${orcid.api-url}"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="orcidPublicationDataProvider" class="org.dspace.external.provider.impl.OrcidPublicationDataProvider">
|
||||||
|
<property name="sourceIdentifier" value="orcidWorks"/>
|
||||||
|
<property name="fieldMapping" ref="orcidPublicationDataProviderFieldMapping"/>
|
||||||
|
<property name="supportedEntityTypes">
|
||||||
|
<list>
|
||||||
|
<value>Publication</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="pubmedLiveImportDataProvider" class="org.dspace.external.provider.impl.LiveImportDataProvider">
|
<bean id="pubmedLiveImportDataProvider" class="org.dspace.external.provider.impl.LiveImportDataProvider">
|
||||||
<property name="metadataSource" ref="pubmedImportService"/>
|
<property name="metadataSource" ref="pubmedImportService"/>
|
||||||
|
434
dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidPublicationDataProviderIT.java
vendored
Normal file
434
dspace-api/src/test/java/org/dspace/external/provider/impl/OrcidPublicationDataProviderIT.java
vendored
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.external.provider.impl;
|
||||||
|
|
||||||
|
import static java.util.Optional.of;
|
||||||
|
import static org.dspace.app.matcher.LambdaMatcher.has;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThrows;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.Unmarshaller;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.StringUtils;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.builder.OrcidTokenBuilder;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.MetadataFieldName;
|
||||||
|
import org.dspace.content.dto.MetadataValueDTO;
|
||||||
|
import org.dspace.external.model.ExternalDataObject;
|
||||||
|
import org.dspace.orcid.client.OrcidClient;
|
||||||
|
import org.dspace.orcid.client.OrcidConfiguration;
|
||||||
|
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.Work;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.WorkBulk;
|
||||||
|
import org.orcid.jaxb.model.v3.release.record.summary.Works;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for {@link OrcidPublicationDataProvider}.
|
||||||
|
*
|
||||||
|
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class OrcidPublicationDataProviderIT extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
private static final String BASE_XML_DIR_PATH = "org/dspace/app/orcid-works/";
|
||||||
|
|
||||||
|
private static final String ACCESS_TOKEN = "32c83ccb-c6d5-4981-b6ea-6a34a36de8ab";
|
||||||
|
|
||||||
|
private static final String ORCID = "0000-1111-2222-3333";
|
||||||
|
|
||||||
|
private OrcidPublicationDataProvider dataProvider;
|
||||||
|
|
||||||
|
private OrcidConfiguration orcidConfiguration;
|
||||||
|
|
||||||
|
private OrcidClient orcidClient;
|
||||||
|
|
||||||
|
private OrcidClient orcidClientMock;
|
||||||
|
|
||||||
|
private String originalClientId;
|
||||||
|
|
||||||
|
private Collection persons;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
persons = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withEntityType("Person")
|
||||||
|
.withName("Profiles")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
dataProvider = new DSpace().getServiceManager()
|
||||||
|
.getServiceByName("orcidPublicationDataProvider", OrcidPublicationDataProvider.class);
|
||||||
|
|
||||||
|
orcidConfiguration = new DSpace().getServiceManager()
|
||||||
|
.getServiceByName("org.dspace.orcid.client.OrcidConfiguration", OrcidConfiguration.class);
|
||||||
|
|
||||||
|
orcidClientMock = mock(OrcidClient.class);
|
||||||
|
orcidClient = dataProvider.getOrcidClient();
|
||||||
|
|
||||||
|
dataProvider.setReadPublicAccessToken(null);
|
||||||
|
dataProvider.setOrcidClient(orcidClientMock);
|
||||||
|
|
||||||
|
originalClientId = orcidConfiguration.getClientId();
|
||||||
|
orcidConfiguration.setClientId("DSPACE-CLIENT-ID");
|
||||||
|
orcidConfiguration.setClientSecret("DSPACE-CLIENT-SECRET");
|
||||||
|
|
||||||
|
when(orcidClientMock.getReadPublicAccessToken()).thenReturn(buildTokenResponse(ACCESS_TOKEN));
|
||||||
|
|
||||||
|
when(orcidClientMock.getWorks(any(), eq(ORCID))).thenReturn(unmarshall("works.xml", Works.class));
|
||||||
|
when(orcidClientMock.getWorks(eq(ORCID))).thenReturn(unmarshall("works.xml", Works.class));
|
||||||
|
|
||||||
|
when(orcidClientMock.getObject(any(), eq(ORCID), any(), eq(Work.class)))
|
||||||
|
.then((invocation) -> of(unmarshall("work-" + invocation.getArgument(2) + ".xml", Work.class)));
|
||||||
|
when(orcidClientMock.getObject(eq(ORCID), any(), eq(Work.class)))
|
||||||
|
.then((invocation) -> of(unmarshall("work-" + invocation.getArgument(1) + ".xml", Work.class)));
|
||||||
|
|
||||||
|
when(orcidClientMock.getWorkBulk(any(), eq(ORCID), any()))
|
||||||
|
.then((invocation) -> unmarshallWorkBulk(invocation.getArgument(2)));
|
||||||
|
when(orcidClientMock.getWorkBulk(eq(ORCID), any()))
|
||||||
|
.then((invocation) -> unmarshallWorkBulk(invocation.getArgument(1)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void after() {
|
||||||
|
dataProvider.setOrcidClient(orcidClient);
|
||||||
|
orcidConfiguration.setClientId(originalClientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithoutPagination() throws Exception {
|
||||||
|
|
||||||
|
List<ExternalDataObject> externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
|
||||||
|
ExternalDataObject firstObject = externalObjects.get(0);
|
||||||
|
assertThat(firstObject.getDisplayValue(), is("The elements of style and the survey of ophthalmology."));
|
||||||
|
assertThat(firstObject.getValue(), is("The elements of style and the survey of ophthalmology."));
|
||||||
|
assertThat(firstObject.getId(), is(ORCID + "::277904"));
|
||||||
|
assertThat(firstObject.getSource(), is("orcidWorks"));
|
||||||
|
|
||||||
|
List<MetadataValueDTO> metadata = firstObject.getMetadata();
|
||||||
|
assertThat(metadata, hasSize(7));
|
||||||
|
assertThat(metadata, has(metadata("dc.date.issued", "2011")));
|
||||||
|
assertThat(metadata, has(metadata("dc.source", "Test Journal")));
|
||||||
|
assertThat(metadata, has(metadata("dc.language.iso", "it")));
|
||||||
|
assertThat(metadata, has(metadata("dc.type", "Other")));
|
||||||
|
assertThat(metadata, has(metadata("dc.identifier.doi", "10.11234.12")));
|
||||||
|
assertThat(metadata, has(metadata("dc.contributor.author", "Walter White")));
|
||||||
|
assertThat(metadata, has(metadata("dc.title", "The elements of style and the survey of ophthalmology.")));
|
||||||
|
|
||||||
|
ExternalDataObject secondObject = externalObjects.get(1);
|
||||||
|
assertThat(secondObject.getDisplayValue(), is("Another cautionary tale."));
|
||||||
|
assertThat(secondObject.getValue(), is("Another cautionary tale."));
|
||||||
|
assertThat(secondObject.getId(), is(ORCID + "::277902"));
|
||||||
|
assertThat(secondObject.getSource(), is("orcidWorks"));
|
||||||
|
|
||||||
|
metadata = secondObject.getMetadata();
|
||||||
|
assertThat(metadata, hasSize(8));
|
||||||
|
assertThat(metadata, has(metadata("dc.date.issued", "2011-05-01")));
|
||||||
|
assertThat(metadata, has(metadata("dc.description.abstract", "Short description")));
|
||||||
|
assertThat(metadata, has(metadata("dc.relation.ispartof", "Journal title")));
|
||||||
|
assertThat(metadata, has(metadata("dc.contributor.author", "Walter White")));
|
||||||
|
assertThat(metadata, has(metadata("dc.contributor.author", "John White")));
|
||||||
|
assertThat(metadata, has(metadata("dc.contributor.editor", "Jesse Pinkman")));
|
||||||
|
assertThat(metadata, has(metadata("dc.title", "Another cautionary tale.")));
|
||||||
|
assertThat(metadata, has(metadata("dc.type", "Article")));
|
||||||
|
|
||||||
|
ExternalDataObject thirdObject = externalObjects.get(2);
|
||||||
|
assertThat(thirdObject.getDisplayValue(), is("Branch artery occlusion in a young woman."));
|
||||||
|
assertThat(thirdObject.getValue(), is("Branch artery occlusion in a young woman."));
|
||||||
|
assertThat(thirdObject.getId(), is(ORCID + "::277871"));
|
||||||
|
assertThat(thirdObject.getSource(), is("orcidWorks"));
|
||||||
|
|
||||||
|
metadata = thirdObject.getMetadata();
|
||||||
|
assertThat(metadata, hasSize(3));
|
||||||
|
assertThat(metadata, has(metadata("dc.date.issued", "1985-07-01")));
|
||||||
|
assertThat(metadata, has(metadata("dc.title", "Branch artery occlusion in a young woman.")));
|
||||||
|
assertThat(metadata, has(metadata("dc.type", "Article")));
|
||||||
|
|
||||||
|
verify(orcidClientMock).getReadPublicAccessToken();
|
||||||
|
verify(orcidClientMock).getWorks(ACCESS_TOKEN, ORCID);
|
||||||
|
verify(orcidClientMock).getWorkBulk(ACCESS_TOKEN, ORCID, List.of("277904", "277902", "277871"));
|
||||||
|
verifyNoMoreInteractions(orcidClientMock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithInvalidOrcidId() {
|
||||||
|
|
||||||
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> dataProvider.searchExternalDataObjects("0000-1111-2222", 0, -1));
|
||||||
|
|
||||||
|
assertThat(exception.getMessage(), is("The given ORCID ID is not valid: 0000-1111-2222"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithStoredAccessToken() throws Exception {
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
String accessToken = "95cb5ed9-c208-4bbc-bc99-aa0bd76e4452";
|
||||||
|
|
||||||
|
Item profile = ItemBuilder.createItem(context, persons)
|
||||||
|
.withTitle("Profile")
|
||||||
|
.withOrcidIdentifier(ORCID)
|
||||||
|
.withDspaceObjectOwner(eperson.getEmail(), eperson.getID().toString())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
OrcidTokenBuilder.create(context, eperson, accessToken)
|
||||||
|
.withProfileItem(profile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
List<ExternalDataObject> externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
|
||||||
|
verify(orcidClientMock).getWorks(accessToken, ORCID);
|
||||||
|
verify(orcidClientMock).getWorkBulk(accessToken, ORCID, List.of("277904", "277902", "277871"));
|
||||||
|
verifyNoMoreInteractions(orcidClientMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithProfileWithoutAccessToken() throws Exception {
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
ItemBuilder.createItem(context, persons)
|
||||||
|
.withTitle("Profile")
|
||||||
|
.withOrcidIdentifier(ORCID)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
List<ExternalDataObject> externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
verify(orcidClientMock).getReadPublicAccessToken();
|
||||||
|
verify(orcidClientMock).getWorks(ACCESS_TOKEN, ORCID);
|
||||||
|
verify(orcidClientMock).getWorkBulk(ACCESS_TOKEN, ORCID, List.of("277904", "277902", "277871"));
|
||||||
|
verifyNoMoreInteractions(orcidClientMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithoutResults() throws Exception {
|
||||||
|
|
||||||
|
String unknownOrcid = "1111-2222-3333-4444";
|
||||||
|
when(orcidClientMock.getWorks(ACCESS_TOKEN, unknownOrcid)).thenReturn(new Works());
|
||||||
|
|
||||||
|
List<ExternalDataObject> externalObjects = dataProvider.searchExternalDataObjects(unknownOrcid, 0, -1);
|
||||||
|
assertThat(externalObjects, empty());
|
||||||
|
|
||||||
|
verify(orcidClientMock).getReadPublicAccessToken();
|
||||||
|
verify(orcidClientMock).getWorks(ACCESS_TOKEN, unknownOrcid);
|
||||||
|
verifyNoMoreInteractions(orcidClientMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClientCredentialsTokenCache() throws Exception {
|
||||||
|
|
||||||
|
List<ExternalDataObject> externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
|
||||||
|
verify(orcidClientMock).getReadPublicAccessToken();
|
||||||
|
|
||||||
|
externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
|
||||||
|
verify(orcidClientMock, times(1)).getReadPublicAccessToken();
|
||||||
|
|
||||||
|
dataProvider.setReadPublicAccessToken(null);
|
||||||
|
|
||||||
|
externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
|
||||||
|
verify(orcidClientMock, times(2)).getReadPublicAccessToken();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchPagination() throws Exception {
|
||||||
|
|
||||||
|
List<ExternalDataObject> externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277904"))));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277902"))));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277871"))));
|
||||||
|
|
||||||
|
verify(orcidClientMock).getReadPublicAccessToken();
|
||||||
|
verify(orcidClientMock).getWorks(ACCESS_TOKEN, ORCID);
|
||||||
|
verify(orcidClientMock).getWorkBulk(ACCESS_TOKEN, ORCID, List.of("277904", "277902", "277871"));
|
||||||
|
|
||||||
|
externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, 5);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277904"))));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277902"))));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277871"))));
|
||||||
|
|
||||||
|
verify(orcidClientMock, times(2)).getWorks(ACCESS_TOKEN, ORCID);
|
||||||
|
verify(orcidClientMock, times(2)).getWorkBulk(ACCESS_TOKEN, ORCID, List.of("277904", "277902", "277871"));
|
||||||
|
|
||||||
|
externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, 2);
|
||||||
|
assertThat(externalObjects, hasSize(2));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277904"))));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277902"))));
|
||||||
|
|
||||||
|
verify(orcidClientMock, times(3)).getWorks(ACCESS_TOKEN, ORCID);
|
||||||
|
verify(orcidClientMock).getWorkBulk(ACCESS_TOKEN, ORCID, List.of("277904", "277902"));
|
||||||
|
|
||||||
|
externalObjects = dataProvider.searchExternalDataObjects(ORCID, 1, 1);
|
||||||
|
assertThat(externalObjects, hasSize(1));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277902"))));
|
||||||
|
|
||||||
|
verify(orcidClientMock, times(4)).getWorks(ACCESS_TOKEN, ORCID);
|
||||||
|
verify(orcidClientMock).getObject(ACCESS_TOKEN, ORCID, "277902", Work.class);
|
||||||
|
|
||||||
|
externalObjects = dataProvider.searchExternalDataObjects(ORCID, 2, 1);
|
||||||
|
assertThat(externalObjects, hasSize(1));
|
||||||
|
assertThat(externalObjects, has((externalObject -> externalObject.getId().equals(ORCID + "::277871"))));
|
||||||
|
|
||||||
|
verify(orcidClientMock, times(5)).getWorks(ACCESS_TOKEN, ORCID);
|
||||||
|
verify(orcidClientMock).getObject(ACCESS_TOKEN, ORCID, "277871", Work.class);
|
||||||
|
|
||||||
|
verifyNoMoreInteractions(orcidClientMock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetExternalDataObject() {
|
||||||
|
Optional<ExternalDataObject> optional = dataProvider.getExternalDataObject(ORCID + "::277902");
|
||||||
|
assertThat(optional.isPresent(), is(true));
|
||||||
|
|
||||||
|
ExternalDataObject externalDataObject = optional.get();
|
||||||
|
assertThat(externalDataObject.getDisplayValue(), is("Another cautionary tale."));
|
||||||
|
assertThat(externalDataObject.getValue(), is("Another cautionary tale."));
|
||||||
|
assertThat(externalDataObject.getId(), is(ORCID + "::277902"));
|
||||||
|
assertThat(externalDataObject.getSource(), is("orcidWorks"));
|
||||||
|
|
||||||
|
List<MetadataValueDTO> metadata = externalDataObject.getMetadata();
|
||||||
|
assertThat(metadata, hasSize(8));
|
||||||
|
assertThat(metadata, has(metadata("dc.date.issued", "2011-05-01")));
|
||||||
|
assertThat(metadata, has(metadata("dc.description.abstract", "Short description")));
|
||||||
|
assertThat(metadata, has(metadata("dc.relation.ispartof", "Journal title")));
|
||||||
|
assertThat(metadata, has(metadata("dc.contributor.author", "Walter White")));
|
||||||
|
assertThat(metadata, has(metadata("dc.contributor.author", "John White")));
|
||||||
|
assertThat(metadata, has(metadata("dc.contributor.editor", "Jesse Pinkman")));
|
||||||
|
assertThat(metadata, has(metadata("dc.title", "Another cautionary tale.")));
|
||||||
|
assertThat(metadata, has(metadata("dc.type", "Article")));
|
||||||
|
|
||||||
|
verify(orcidClientMock).getReadPublicAccessToken();
|
||||||
|
verify(orcidClientMock).getObject(ACCESS_TOKEN, ORCID, "277902", Work.class);
|
||||||
|
verifyNoMoreInteractions(orcidClientMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetExternalDataObjectWithInvalidOrcidId() {
|
||||||
|
|
||||||
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> dataProvider.getExternalDataObject("invalid::277902"));
|
||||||
|
|
||||||
|
assertThat(exception.getMessage(), is("The given ORCID ID is not valid: invalid" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetExternalDataObjectWithInvalidId() {
|
||||||
|
|
||||||
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> dataProvider.getExternalDataObject("id"));
|
||||||
|
|
||||||
|
assertThat(exception.getMessage(), is("Invalid identifier 'id', expected <orcid-id>::<put-code>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithoutApiKeysConfigured() throws Exception {
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
orcidConfiguration.setClientSecret(null);
|
||||||
|
|
||||||
|
ItemBuilder.createItem(context, persons)
|
||||||
|
.withTitle("Profile")
|
||||||
|
.withOrcidIdentifier(ORCID)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
List<ExternalDataObject> externalObjects = dataProvider.searchExternalDataObjects(ORCID, 0, -1);
|
||||||
|
assertThat(externalObjects, hasSize(3));
|
||||||
|
|
||||||
|
verify(orcidClientMock).getWorks(ORCID);
|
||||||
|
verify(orcidClientMock).getWorkBulk(ORCID, List.of("277904", "277902", "277871"));
|
||||||
|
verifyNoMoreInteractions(orcidClientMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Predicate<MetadataValueDTO> metadata(String metadataField, String value) {
|
||||||
|
MetadataFieldName metadataFieldName = new MetadataFieldName(metadataField);
|
||||||
|
return metadata(metadataFieldName.schema, metadataFieldName.element, metadataFieldName.qualifier, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Predicate<MetadataValueDTO> metadata(String schema, String element, String qualifier, String value) {
|
||||||
|
return dto -> StringUtils.equals(schema, dto.getSchema())
|
||||||
|
&& StringUtils.equals(element, dto.getElement())
|
||||||
|
&& StringUtils.equals(qualifier, dto.getQualifier())
|
||||||
|
&& StringUtils.equals(value, dto.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private OrcidTokenResponseDTO buildTokenResponse(String accessToken) {
|
||||||
|
OrcidTokenResponseDTO response = new OrcidTokenResponseDTO();
|
||||||
|
response.setAccessToken(accessToken);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkBulk unmarshallWorkBulk(List<String> putCodes) throws Exception {
|
||||||
|
return unmarshall("workBulk-" + String.join("-", putCodes) + ".xml", WorkBulk.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T> T unmarshall(String fileName, Class<T> clazz) throws Exception {
|
||||||
|
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
|
||||||
|
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||||
|
URL resource = getClass().getClassLoader().getResource(BASE_XML_DIR_PATH + fileName);
|
||||||
|
if (resource == null) {
|
||||||
|
throw new IllegalStateException("No resource found named " + BASE_XML_DIR_PATH + fileName);
|
||||||
|
}
|
||||||
|
return (T) unmarshaller.unmarshal(new File(resource.getFile()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<work:work put-code="277871" path="/0000-0001-9227-636X/work/277871" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.151Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:25.924Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Branch artery occlusion in a young woman.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:citation>
|
||||||
|
<work:citation-type>formatted-unspecified</work:citation-type>
|
||||||
|
<work:citation-value>Gittinger JW, Miller NR, Keltner JL, Burde RM. Branch artery occlusion in a young woman. Surv Ophthalmol. 1985 Jul-Aug; 30(1):52-8.</work:citation-value>
|
||||||
|
</work:citation>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>1985</common:year>
|
||||||
|
<common:month>07</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work>
|
@@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<work:work put-code="277902" path="/0000-0001-9227-636X/work/277902" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.159Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.327Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Another cautionary tale.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:journal-title>Journal title</work:journal-title>
|
||||||
|
<work:short-description>Short description</work:short-description>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>2011</common:year>
|
||||||
|
<common:month>05</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
<work:contributors>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Walter White</work:credit-name>
|
||||||
|
<work:contributor-email>walter@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>John White</work:credit-name>
|
||||||
|
<work:contributor-email>john@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>additional</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Jesse Pinkman</work:credit-name>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>editor</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
</work:contributors>
|
||||||
|
</work:work>
|
@@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<work:work put-code="277904" path="/0000-0001-9227-636X/work/277904" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.160Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.350Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>The elements of style and the survey of ophthalmology.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:citation>
|
||||||
|
<work:citation-type>bibtex</work:citation-type>
|
||||||
|
<work:citation-value>@article{Test,
|
||||||
|
doi = {10.11234.12},
|
||||||
|
year = 2011,
|
||||||
|
month = {nov},
|
||||||
|
publisher = {Elsevier {BV}},
|
||||||
|
volume = {110},
|
||||||
|
pages = {71--83},
|
||||||
|
author = {Walter White},
|
||||||
|
title = {Title from Bibtex: The elements of style and the survey of ophthalmology.},
|
||||||
|
journal = {Test Journal}
|
||||||
|
}
|
||||||
|
</work:citation-value>
|
||||||
|
</work:citation>
|
||||||
|
<work:type>invention</work:type>
|
||||||
|
<common:external-ids>
|
||||||
|
<common:external-id>
|
||||||
|
<common:external-id-type>agr</common:external-id-type>
|
||||||
|
<common:external-id-value>work:external-identifier-id</common:external-id-value>
|
||||||
|
<common:external-id-url>http://orcid.org</common:external-id-url>
|
||||||
|
<common:external-id-relationship>version-of</common:external-id-relationship>
|
||||||
|
</common:external-id>
|
||||||
|
<common:external-id>
|
||||||
|
<common:external-id-type>doi</common:external-id-type>
|
||||||
|
<common:external-id-value>10.11234.12</common:external-id-value>
|
||||||
|
<common:external-id-url>http://orcid.org</common:external-id-url>
|
||||||
|
<common:external-id-relationship>self</common:external-id-relationship>
|
||||||
|
</common:external-id>
|
||||||
|
</common:external-ids>
|
||||||
|
<work:contributors>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Walter White</work:credit-name>
|
||||||
|
<work:contributor-email>walter@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
</work:contributors>
|
||||||
|
<common:language-code>it</common:language-code>
|
||||||
|
</work:work>
|
@@ -0,0 +1,147 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<bulk:bulk xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<work:work put-code="277904" path="/0000-0001-9227-636X/work/277904" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.160Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.350Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>The elements of style and the survey of ophthalmology.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:citation>
|
||||||
|
<work:citation-type>bibtex</work:citation-type>
|
||||||
|
<work:citation-value>@article{Test,
|
||||||
|
doi = {10.11234.12},
|
||||||
|
year = 2011,
|
||||||
|
month = {nov},
|
||||||
|
publisher = {Elsevier {BV}},
|
||||||
|
volume = {110},
|
||||||
|
pages = {71--83},
|
||||||
|
author = {Walter White},
|
||||||
|
title = {Title from Bibtex: The elements of style and the survey of ophthalmology.},
|
||||||
|
journal = {Test Journal}
|
||||||
|
}
|
||||||
|
</work:citation-value>
|
||||||
|
</work:citation>
|
||||||
|
<work:type>invention</work:type>
|
||||||
|
<common:external-ids>
|
||||||
|
<common:external-id>
|
||||||
|
<common:external-id-type>agr</common:external-id-type>
|
||||||
|
<common:external-id-value>work:external-identifier-id</common:external-id-value>
|
||||||
|
<common:external-id-url>http://orcid.org</common:external-id-url>
|
||||||
|
<common:external-id-relationship>version-of</common:external-id-relationship>
|
||||||
|
</common:external-id>
|
||||||
|
<common:external-id>
|
||||||
|
<common:external-id-type>doi</common:external-id-type>
|
||||||
|
<common:external-id-value>10.11234.12</common:external-id-value>
|
||||||
|
<common:external-id-url>http://orcid.org</common:external-id-url>
|
||||||
|
<common:external-id-relationship>self</common:external-id-relationship>
|
||||||
|
</common:external-id>
|
||||||
|
</common:external-ids>
|
||||||
|
<work:contributors>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Walter White</work:credit-name>
|
||||||
|
<work:contributor-email>walter@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
</work:contributors>
|
||||||
|
<common:language-code>it</common:language-code>
|
||||||
|
</work:work>
|
||||||
|
<work:work put-code="277902" path="/0000-0001-9227-636X/work/277902" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.159Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.327Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Another cautionary tale.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:journal-title>Journal title</work:journal-title>
|
||||||
|
<work:short-description>Short description</work:short-description>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>2011</common:year>
|
||||||
|
<common:month>05</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
<work:contributors>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Walter White</work:credit-name>
|
||||||
|
<work:contributor-email>walter@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>John White</work:credit-name>
|
||||||
|
<work:contributor-email>john@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>additional</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Jesse Pinkman</work:credit-name>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>editor</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
</work:contributors>
|
||||||
|
</work:work>
|
||||||
|
<work:work put-code="277871" path="/0000-0001-9227-636X/work/277871" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.151Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:25.924Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Branch artery occlusion in a young woman.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:citation>
|
||||||
|
<work:citation-type>formatted-unspecified</work:citation-type>
|
||||||
|
<work:citation-value>Gittinger JW, Miller NR, Keltner JL, Burde RM. Branch artery occlusion in a young woman. Surv Ophthalmol. 1985 Jul-Aug; 30(1):52-8.</work:citation-value>
|
||||||
|
</work:citation>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>1985</common:year>
|
||||||
|
<common:month>07</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work>
|
||||||
|
</bulk:bulk>
|
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<bulk:bulk xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<work:work put-code="277904" path="/0000-0001-9227-636X/work/277904" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.160Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.350Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>The elements of style and the survey of ophthalmology.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:citation>
|
||||||
|
<work:citation-type>bibtex</work:citation-type>
|
||||||
|
<work:citation-value>@article{Test,
|
||||||
|
doi = {10.11234.12},
|
||||||
|
year = 2011,
|
||||||
|
month = {nov},
|
||||||
|
publisher = {Elsevier {BV}},
|
||||||
|
volume = {110},
|
||||||
|
pages = {71--83},
|
||||||
|
author = {Walter White},
|
||||||
|
title = {Title from Bibtex: The elements of style and the survey of ophthalmology.},
|
||||||
|
journal = {Test Journal}
|
||||||
|
}
|
||||||
|
</work:citation-value>
|
||||||
|
</work:citation>
|
||||||
|
<work:type>invention</work:type>
|
||||||
|
<common:external-ids>
|
||||||
|
<common:external-id>
|
||||||
|
<common:external-id-type>agr</common:external-id-type>
|
||||||
|
<common:external-id-value>work:external-identifier-id</common:external-id-value>
|
||||||
|
<common:external-id-url>http://orcid.org</common:external-id-url>
|
||||||
|
<common:external-id-relationship>version-of</common:external-id-relationship>
|
||||||
|
</common:external-id>
|
||||||
|
<common:external-id>
|
||||||
|
<common:external-id-type>doi</common:external-id-type>
|
||||||
|
<common:external-id-value>10.11234.12</common:external-id-value>
|
||||||
|
<common:external-id-url>http://orcid.org</common:external-id-url>
|
||||||
|
<common:external-id-relationship>self</common:external-id-relationship>
|
||||||
|
</common:external-id>
|
||||||
|
</common:external-ids>
|
||||||
|
<work:contributors>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Walter White</work:credit-name>
|
||||||
|
<work:contributor-email>walter@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
</work:contributors>
|
||||||
|
<common:language-code>it</common:language-code>
|
||||||
|
</work:work>
|
||||||
|
<work:work put-code="277902" path="/0000-0001-9227-636X/work/277902" visibility="public" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.159Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.327Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Another cautionary tale.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:journal-title>Journal title</work:journal-title>
|
||||||
|
<work:short-description>Short description</work:short-description>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>2011</common:year>
|
||||||
|
<common:month>05</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
<work:contributors>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Walter White</work:credit-name>
|
||||||
|
<work:contributor-email>walter@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>John White</work:credit-name>
|
||||||
|
<work:contributor-email>john@test.com</work:contributor-email>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>additional</work:contributor-sequence>
|
||||||
|
<work:contributor-role>author</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
<work:contributor>
|
||||||
|
<work:credit-name>Jesse Pinkman</work:credit-name>
|
||||||
|
<work:contributor-attributes>
|
||||||
|
<work:contributor-sequence>first</work:contributor-sequence>
|
||||||
|
<work:contributor-role>editor</work:contributor-role>
|
||||||
|
</work:contributor-attributes>
|
||||||
|
</work:contributor>
|
||||||
|
</work:contributors>
|
||||||
|
</work:work>
|
||||||
|
</bulk:bulk>
|
@@ -0,0 +1,196 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<activities:works path="/0000-0001-9227-636X/works" xmlns:internal="http://www.orcid.org/ns/internal" xmlns:education="http://www.orcid.org/ns/education" xmlns:distinction="http://www.orcid.org/ns/distinction" xmlns:deprecated="http://www.orcid.org/ns/deprecated" xmlns:other-name="http://www.orcid.org/ns/other-name" xmlns:membership="http://www.orcid.org/ns/membership" xmlns:error="http://www.orcid.org/ns/error" xmlns:common="http://www.orcid.org/ns/common" xmlns:record="http://www.orcid.org/ns/record" xmlns:personal-details="http://www.orcid.org/ns/personal-details" xmlns:keyword="http://www.orcid.org/ns/keyword" xmlns:email="http://www.orcid.org/ns/email" xmlns:external-identifier="http://www.orcid.org/ns/external-identifier" xmlns:funding="http://www.orcid.org/ns/funding" xmlns:preferences="http://www.orcid.org/ns/preferences" xmlns:address="http://www.orcid.org/ns/address" xmlns:invited-position="http://www.orcid.org/ns/invited-position" xmlns:work="http://www.orcid.org/ns/work" xmlns:history="http://www.orcid.org/ns/history" xmlns:employment="http://www.orcid.org/ns/employment" xmlns:qualification="http://www.orcid.org/ns/qualification" xmlns:service="http://www.orcid.org/ns/service" xmlns:person="http://www.orcid.org/ns/person" xmlns:activities="http://www.orcid.org/ns/activities" xmlns:researcher-url="http://www.orcid.org/ns/researcher-url" xmlns:peer-review="http://www.orcid.org/ns/peer-review" xmlns:bulk="http://www.orcid.org/ns/bulk" xmlns:research-resource="http://www.orcid.org/ns/research-resource">
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.350Z</common:last-modified-date>
|
||||||
|
<activities:group>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.350Z</common:last-modified-date>
|
||||||
|
<common:external-ids/>
|
||||||
|
<work:work-summary put-code="277904" path="/0000-0001-9227-636X/work/277904" visibility="public" display-index="0">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.160Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.350Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>The elements of style and the survey of ophthalmology.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:type>invention</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>2012</common:year>
|
||||||
|
<common:month>11</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work-summary>
|
||||||
|
</activities:group>
|
||||||
|
<activities:group>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.339Z</common:last-modified-date>
|
||||||
|
<common:external-ids/>
|
||||||
|
<work:work-summary put-code="277903" path="/0000-0001-9227-636X/work/277903" visibility="public" display-index="0">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.159Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.339Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/DSPACE-CLIENT-ID</common:uri>
|
||||||
|
<common:path>DSPACE-CLIENT-ID</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>DSPACE-CRIS</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Introduction.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>2011</common:year>
|
||||||
|
<common:month>11</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work-summary>
|
||||||
|
</activities:group>
|
||||||
|
<activities:group>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.327Z</common:last-modified-date>
|
||||||
|
<common:external-ids/>
|
||||||
|
<work:work-summary put-code="277902" path="/0000-0001-9227-636X/work/277902" visibility="public" display-index="1">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.159Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.327Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Another cautionary tale.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>2011</common:year>
|
||||||
|
<common:month>05</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work-summary>
|
||||||
|
<work:work-summary put-code="287902" path="/0000-0001-9227-636X/work/277902" visibility="public" display-index="0">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.159Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.327Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/4Science</common:uri>
|
||||||
|
<common:path>4Science</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Another cautionary tale (4Science).</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>2011</common:year>
|
||||||
|
<common:month>05</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work-summary>
|
||||||
|
</activities:group>
|
||||||
|
<activities:group>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.108Z</common:last-modified-date>
|
||||||
|
<common:external-ids/>
|
||||||
|
<work:work-summary put-code="277885" path="/0000-0001-9227-636X/work/277885" visibility="public" display-index="0">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.155Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.108Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/DSPACE-CLIENT-ID</common:uri>
|
||||||
|
<common:path>DSPACE-CLIENT-ID</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>DSPACE-CRIS</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Functional hemianopsia: a historical perspective.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>1988</common:year>
|
||||||
|
<common:month>05</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work-summary>
|
||||||
|
<work:work-summary put-code="277971" path="/0000-0001-9227-636X/work/277871" visibility="public" display-index="0">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.151Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:25.924Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Branch artery occlusion in a young man.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>1985</common:year>
|
||||||
|
<common:month>07</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work-summary>
|
||||||
|
</activities:group>
|
||||||
|
<activities:group>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:26.108Z</common:last-modified-date>
|
||||||
|
<common:external-ids/>
|
||||||
|
<work:work-summary put-code="277871" path="/0000-0001-9227-636X/work/277871" visibility="public" display-index="0">
|
||||||
|
<common:created-date>2014-01-22T19:11:57.151Z</common:created-date>
|
||||||
|
<common:last-modified-date>2015-06-19T19:14:25.924Z</common:last-modified-date>
|
||||||
|
<common:source>
|
||||||
|
<common:source-orcid>
|
||||||
|
<common:uri>https://sandbox.orcid.org/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-orcid>
|
||||||
|
<common:source-client-id>
|
||||||
|
<common:uri>https://sandbox.orcid.org/client/0000-0002-4105-0763</common:uri>
|
||||||
|
<common:path>0000-0002-4105-0763</common:path>
|
||||||
|
<common:host>sandbox.orcid.org</common:host>
|
||||||
|
</common:source-client-id>
|
||||||
|
<common:source-name>BU Profiles to ORCID Integration Site</common:source-name>
|
||||||
|
</common:source>
|
||||||
|
<work:title>
|
||||||
|
<common:title>Branch artery occlusion in a young woman.</common:title>
|
||||||
|
</work:title>
|
||||||
|
<work:type>journal-article</work:type>
|
||||||
|
<common:publication-date>
|
||||||
|
<common:year>1985</common:year>
|
||||||
|
<common:month>07</common:month>
|
||||||
|
<common:day>01</common:day>
|
||||||
|
</common:publication-date>
|
||||||
|
</work:work-summary>
|
||||||
|
</activities:group>
|
||||||
|
</activities:works>
|
@@ -53,7 +53,7 @@ public class ExternalSourcesRestControllerIT extends AbstractControllerIntegrati
|
|||||||
ExternalSourceMatcher.matchExternalSource(
|
ExternalSourceMatcher.matchExternalSource(
|
||||||
"openAIREFunding", "openAIREFunding", false)
|
"openAIREFunding", "openAIREFunding", false)
|
||||||
)))
|
)))
|
||||||
.andExpect(jsonPath("$.page.totalElements", Matchers.is(8)));
|
.andExpect(jsonPath("$.page.totalElements", Matchers.is(9)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
# Mapping between languages supported by ORCID and the DSpace common iso languages
|
@@ -0,0 +1,12 @@
|
|||||||
|
# Mapping between work type supported by ORCID and the DSpace common publication's types
|
||||||
|
website = Other
|
||||||
|
data-set = Dataset
|
||||||
|
book = Book
|
||||||
|
book-chapter = Book chapter
|
||||||
|
conference-paper = Other
|
||||||
|
journal-article = Article
|
||||||
|
newspaper-article = Article
|
||||||
|
magazine-article = Article
|
||||||
|
patent = Other
|
||||||
|
report = Other
|
||||||
|
book-review = Other
|
@@ -134,4 +134,31 @@ orcid.validation.organization.identifier-sources = LEI
|
|||||||
#------------------------------------------------------------------#
|
#------------------------------------------------------------------#
|
||||||
|
|
||||||
## Configuration for max attempts during ORCID batch synchronization
|
## Configuration for max attempts during ORCID batch synchronization
|
||||||
orcid.bulk-synchronization.max-attempts = 5
|
orcid.bulk-synchronization.max-attempts = 5
|
||||||
|
|
||||||
|
#------------------------------------------------------------------#
|
||||||
|
#--------------------ORCID EXTERNAL DATA MAPPING-------------------#
|
||||||
|
#------------------------------------------------------------------#
|
||||||
|
|
||||||
|
### Work (Publication) external-data.mapping ###
|
||||||
|
orcid.external-data.mapping.publication.title = dc.title
|
||||||
|
|
||||||
|
orcid.external-data.mapping.publication.description = dc.description.abstract
|
||||||
|
orcid.external-data.mapping.publication.issued-date = dc.date.issued
|
||||||
|
orcid.external-data.mapping.publication.language = dc.language.iso
|
||||||
|
orcid.external-data.mapping.publication.language.converter = mapConverterOrcidToDSpaceLanguageCode
|
||||||
|
orcid.external-data.mapping.publication.is-part-of = dc.relation.ispartof
|
||||||
|
orcid.external-data.mapping.publication.type = dc.type
|
||||||
|
orcid.external-data.mapping.publication.type.converter = mapConverterOrcidToDSpacePublicationType
|
||||||
|
|
||||||
|
##orcid.external-data.mapping.publication.contributors syntax is <metadatafield>::<role>
|
||||||
|
orcid.external-data.mapping.publication.contributors = dc.contributor.author::author
|
||||||
|
orcid.external-data.mapping.publication.contributors = dc.contributor.editor::editor
|
||||||
|
|
||||||
|
##orcid.external-data.mapping.publication.external-ids syntax is <metadatafield>::<type> or $simple-handle::<type>
|
||||||
|
##The full list of available external identifiers is available here https://pub.orcid.org/v3.0/identifiers
|
||||||
|
orcid.external-data.mapping.publication.external-ids = dc.identifier.doi::doi
|
||||||
|
orcid.external-data.mapping.publication.external-ids = dc.identifier.scopus::eid
|
||||||
|
orcid.external-data.mapping.publication.external-ids = dc.identifier.pmid::pmid
|
||||||
|
orcid.external-data.mapping.publication.external-ids = dc.identifier.isi::wosuid
|
||||||
|
orcid.external-data.mapping.publication.external-ids = dc.identifier.issn::issn
|
@@ -93,6 +93,16 @@
|
|||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="orcidPublicationDataProvider" class="org.dspace.external.provider.impl.OrcidPublicationDataProvider">
|
||||||
|
<property name="sourceIdentifier" value="orcidWorks"/>
|
||||||
|
<property name="fieldMapping" ref="orcidPublicationDataProviderFieldMapping"/>
|
||||||
|
<property name="supportedEntityTypes">
|
||||||
|
<list>
|
||||||
|
<value>Publication</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="crossRefLiveImportDataProvider" class="org.dspace.external.provider.impl.LiveImportDataProvider">
|
<bean id="crossRefLiveImportDataProvider" class="org.dspace.external.provider.impl.LiveImportDataProvider">
|
||||||
<property name="metadataSource" ref="CrossRefImportService"/>
|
<property name="metadataSource" ref="CrossRefImportService"/>
|
||||||
|
@@ -146,11 +146,37 @@
|
|||||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService" />
|
<property name="configurationService" ref="org.dspace.services.ConfigurationService" />
|
||||||
<property name="defaultValue" value=""/>
|
<property name="defaultValue" value=""/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
<bean id="orcidPublicationDataProviderFieldMapping" class="org.dspace.orcid.model.OrcidWorkFieldMapping" >
|
||||||
|
<property name="contributorFields" value="${orcid.external-data.mapping.publication.contributors}" />
|
||||||
|
<property name="externalIdentifierFields" value="${orcid.external-data.mapping.publication.external-ids}" />
|
||||||
|
<property name="publicationDateField" value="${orcid.external-data.mapping.publication.issued-date}" />
|
||||||
|
<property name="titleField" value="${orcid.external-data.mapping.publication.title}" />
|
||||||
|
<property name="journalTitleField" value="${orcid.external-data.mapping.publication.is-part-of}" />
|
||||||
|
<property name="shortDescriptionField" value="${orcid.external-data.mapping.publication.description}" />
|
||||||
|
<property name="languageField" value="${orcid.external-data.mapping.publication.language}" />
|
||||||
|
<property name="languageConverter" ref="${orcid.external-data.mapping.publication.language.converter}" />
|
||||||
|
<property name="typeField" value="${orcid.external-data.mapping.publication.type}" />
|
||||||
|
<property name="typeConverter" ref="${orcid.external-data.mapping.publication.type.converter}" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean name="mapConverterDSpaceToOrcidAmountCurrency" class="org.dspace.util.SimpleMapConverter" init-method="init">
|
<bean name="mapConverterDSpaceToOrcidAmountCurrency" class="org.dspace.util.SimpleMapConverter" init-method="init">
|
||||||
<property name="converterNameFile" value="orcid/mapConverter-dspace-to-orcid-amount-currency.properties" />
|
<property name="converterNameFile" value="orcid/mapConverter-dspace-to-orcid-amount-currency.properties" />
|
||||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService" />
|
<property name="configurationService" ref="org.dspace.services.ConfigurationService" />
|
||||||
<property name="defaultValue" value=""/>
|
<property name="defaultValue" value=""/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean name="mapConverterOrcidToDSpacePublicationType" class="org.dspace.util.SimpleMapConverter" init-method="init">
|
||||||
|
<property name="converterNameFile" value="orcid/mapConverter-orcid-to-dspace-publication-type.properties" />
|
||||||
|
<property name="configurationService" ref="org.dspace.services.ConfigurationService" />
|
||||||
|
<property name="defaultValue" value="Other"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="mapConverterOrcidToDSpaceLanguageCode" class="org.dspace.util.SimpleMapConverter" init-method="init">
|
||||||
|
<property name="converterNameFile" value="orcid/mapConverter-orcid-to-dspace-language-code.properties" />
|
||||||
|
<property name="configurationService" ref="org.dspace.services.ConfigurationService" />
|
||||||
|
<property name="defaultValue" value=""/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
Reference in New Issue
Block a user