Skip to content

Commit

Permalink
Merge pull request #2824 from 4Science/DS-4515_submit-external-source
Browse files Browse the repository at this point in the history
DS-4515 - Start new submission via Search or ID Lookup (using Live Import)
  • Loading branch information
tdonohue committed Sep 4, 2020
2 parents bb6413a + 1b4988d commit 4c8c149
Show file tree
Hide file tree
Showing 24 changed files with 870 additions and 1,522 deletions.
8 changes: 8 additions & 0 deletions dspace-api/pom.xml
Expand Up @@ -325,6 +325,14 @@
<artifactId>apache-jena-libs</artifactId>
<type>pom</type>
</dependency>
<!-- Required to support PubMed API call in "PubmedImportMetadataSourceServiceImpl.GetRecord" -->
<!-- Makes runtime operations in Jersey Dependency Injection -->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey.version}</version>
</dependency>

<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
Expand Down
@@ -0,0 +1,162 @@
/**
* 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 java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.dspace.content.dto.MetadataValueDTO;
import org.dspace.external.model.ExternalDataObject;
import org.dspace.external.provider.ExternalDataProvider;
import org.dspace.importer.external.datamodel.ImportRecord;
import org.dspace.importer.external.exception.MetadataSourceException;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
import org.dspace.importer.external.service.components.QuerySource;

/**
* This class allows to configure a Live Import Provider as an External Data Provider
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
*/
public class LiveImportDataProvider implements ExternalDataProvider {
/**
* The {@link QuerySource} live import provider
*/
private QuerySource querySource;

/**
* An unique human readable identifier for this provider
*/
private String sourceIdentifier;

private String recordIdMetadata;

private String displayMetadata = "dc.title";

@Override
public String getSourceIdentifier() {
return sourceIdentifier;
}

/**
* This method set the SourceIdentifier for the ExternalDataProvider
* @param sourceIdentifier The UNIQUE sourceIdentifier to be set on any LiveImport data provider
*/
public void setSourceIdentifier(String sourceIdentifier) {
this.sourceIdentifier = sourceIdentifier;
}

/**
* This method set the MetadataSource for the ExternalDataProvider
* @param metadataSource {@link org.dspace.importer.external.service.components.MetadataSource} implementation used to process the input data
*/
public void setMetadataSource(QuerySource querySource) {
this.querySource = querySource;
}

/**
* This method set dublin core identifier to use as metadata id
* @param recordIdMetadata dublin core identifier to use as metadata id
*/
public void setRecordIdMetadata(String recordIdMetadata) {
this.recordIdMetadata = recordIdMetadata;
}

/**
* This method set the dublin core identifier to display the title
* @param displayMetadata metadata to use as title
*/
public void setDisplayMetadata(String displayMetadata) {
this.displayMetadata = displayMetadata;
}

@Override
public Optional<ExternalDataObject> getExternalDataObject(String id) {
try {
ExternalDataObject externalDataObject = getExternalDataObject(querySource.getRecord(id));
return Optional.of(externalDataObject);
} catch (MetadataSourceException e) {
throw new RuntimeException(
"The live import provider " + querySource.getImportSource() + " throws an exception", e);
}
}

@Override
public List<ExternalDataObject> searchExternalDataObjects(String query, int start, int limit) {
Collection<ImportRecord> records;
try {
records = querySource.getRecords(query, start, limit);
return records.stream().map(r -> getExternalDataObject(r)).collect(Collectors.toList());
} catch (MetadataSourceException e) {
throw new RuntimeException(
"The live import provider " + querySource.getImportSource() + " throws an exception", e);
}
}

@Override
public boolean supports(String source) {
return StringUtils.equalsIgnoreCase(sourceIdentifier, source);
}

@Override
public int getNumberOfResults(String query) {
try {
return querySource.getRecordsCount(query);
} catch (MetadataSourceException e) {
throw new RuntimeException(
"The live import provider " + querySource.getImportSource() + " throws an exception", e);
}
}

/**
* Internal method to convert an ImportRecord to an ExternalDataObject
*
* FIXME it would be useful to remove ImportRecord at all in favor of the
* ExternalDataObject
*
* @param record
* @return
*/
private ExternalDataObject getExternalDataObject(ImportRecord record) {
//return 400 if no record were found
if (record == null) {
throw new IllegalArgumentException("No record found for query or id");
}
ExternalDataObject externalDataObject = new ExternalDataObject(sourceIdentifier);
String id = getFirstValue(record, recordIdMetadata);
String display = getFirstValue(record, displayMetadata);
externalDataObject.setId(id);
externalDataObject.setDisplayValue(display);
externalDataObject.setValue(display);
for (MetadatumDTO dto : record.getValueList()) {
// FIXME it would be useful to remove MetadatumDTO in favor of MetadataValueDTO
MetadataValueDTO mvDTO = new MetadataValueDTO();
mvDTO.setSchema(dto.getSchema());
mvDTO.setElement(dto.getElement());
mvDTO.setQualifier(dto.getQualifier());
mvDTO.setValue(dto.getValue());
externalDataObject.addMetadata(mvDTO);
}
return externalDataObject;
}

private String getFirstValue(ImportRecord record, String metadata) {
String id = null;
String[] split = StringUtils.split(metadata, ".", 3);
Collection<MetadatumDTO> values = record.getValue(split[0], split[1], split.length == 3 ? split[2] : null);
if (!values.isEmpty()) {
id = (values.iterator().next().getValue());
}
return id;
}

}
@@ -0,0 +1,37 @@
/**
* 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.importer.external.arxiv.metadatamapping;

import java.util.Map;
import javax.annotation.Resource;

import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping;

/**
* An implementation of {@link AbstractMetadataFieldMapping}
* Responsible for defining the mapping of the ArXiv metadatum fields on the DSpace metadatum fields
*
* @author Pasquale Cavallo (pasquale.cavallo at 4science dot it)
*/
public class ArXivFieldMapping extends AbstractMetadataFieldMapping {

/**
* Defines which metadatum is mapped on which metadatum. Note that while the key must be unique it
* only matters here for postprocessing of the value. The mapped MetadatumContributor has full control over
* what metadatafield is generated.
*
* @param metadataFieldMap The map containing the link between retrieve metadata and metadata that will be set to
* the item.
*/
@Override
@Resource(name = "arxivMetadataFieldMap")
public void setMetadataFieldMap(Map metadataFieldMap) {
super.setMetadataFieldMap(metadataFieldMap);
}

}
@@ -0,0 +1,60 @@
/**
* 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.importer.external.arxiv.metadatamapping.contributor;

import java.util.Collection;

import org.apache.axiom.om.OMElement;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
import org.dspace.importer.external.metadatamapping.contributor.MetadataContributor;
import org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor;

/**
* Arxiv specific implementation of {@link MetadataContributor}
* Responsible for generating the ArXiv Id from the retrieved item.
*
* @author Pasquale Cavallo (pasquale.cavallo at 4science dot it)
*
*/
public class ArXivIdMetadataContributor extends SimpleXpathMetadatumContributor {

/**
* Retrieve the metadata associated with the given object.
* Depending on the retrieved node (using the query), different types of values will be added to the MetadatumDTO
* list
*
* @param t A class to retrieve metadata from.
* @return a collection of import records. Only the identifier of the found records may be put in the record.
*/
@Override
public Collection<MetadatumDTO> contributeMetadata(OMElement t) {
Collection<MetadatumDTO> values = super.contributeMetadata(t);
parseValue(values);
return values;
}

/**
* ArXiv returns a full URL as in the <id> value, e.g. http://arxiv.org/abs/1911.11405v1.
* This method parses out the identifier from the end of the URL, e.g. 1911.11405v1.
*
* @param dtos Metadata which contains the items uri
*/
private void parseValue(Collection<MetadatumDTO> dtos) {
if (dtos != null) {
for (MetadatumDTO dto : dtos) {
if (dto != null && dto.getValue() != null && dto.getValue().contains("/")) {
int startIndex = dto.getValue().lastIndexOf('/') + 1;
int endIndex = dto.getValue().length();
String id = dto.getValue().substring(startIndex, endIndex);
dto.setValue(id);
}
}
}
}

}

0 comments on commit 4c8c149

Please sign in to comment.