[CST-5303] porting of CrossRef live import service

This commit is contained in:
Mykhaylo
2022-04-02 13:13:38 +02:00
parent 5d0bf51d5a
commit 181bdd04d1
9 changed files with 732 additions and 1 deletions

View File

@@ -337,6 +337,11 @@
<dependencies>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>

View File

@@ -0,0 +1,44 @@
/**
* 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.crossref;
import java.util.ArrayList;
import java.util.Collection;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import org.dspace.importer.external.metadatamapping.contributor.JsonPathMetadataProcessor;
import org.json.JSONArray;
public class CrossRefAuthorMetadataProcessor implements JsonPathMetadataProcessor {
private String givenNameJsonPath;
private String familyNameJsonPath;
public void setGivenNameJsonPath(String givenNameJsonPath) {
this.givenNameJsonPath = givenNameJsonPath;
}
public void setFamilyNameJsonPath(String familyNameJsonPath) {
this.familyNameJsonPath = familyNameJsonPath;
}
@Override
public Collection<String> processMetadata(String json) {
ReadContext ctx = JsonPath.parse(json);
JSONArray givenNames = ctx.read(givenNameJsonPath);
JSONArray familyNames = ctx.read(familyNameJsonPath);
Collection<String> values = new ArrayList<>();
for (int i = 0; i < givenNames.length(); i++) {
String name = givenNames.get(i).toString();
values.add(name + " " + familyNames.get(i).toString());
}
return values;
}
}

View File

@@ -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.crossref;
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 CrossRefFieldMapping 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 = "crossrefMetadataFieldMap")
public void setMetadataFieldMap(Map metadataFieldMap) {
super.setMetadataFieldMap(metadataFieldMap);
}
}

View File

@@ -0,0 +1,332 @@
/**
* 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.crossref;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import javax.el.MethodNotFoundException;
import com.google.gson.Gson;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import net.minidev.json.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.dspace.content.Item;
import org.dspace.importer.external.datamodel.ImportRecord;
import org.dspace.importer.external.datamodel.Query;
import org.dspace.importer.external.exception.MetadataSourceException;
import org.dspace.importer.external.scopus.service.LiveImportClient;
import org.dspace.importer.external.service.AbstractImportMetadataSourceService;
import org.dspace.importer.external.service.DoiCheck;
import org.dspace.importer.external.service.components.QuerySource;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Implements a data source for querying CrossRef
*
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
*/
public class CrossRefImportMetadataSourceServiceImpl extends AbstractImportMetadataSourceService<String>
implements QuerySource {
private static final String ENDPOINT_WORKS = "https://api.crossref.org/works";
@Autowired
private LiveImportClient liveImportClient;
@Override
public String getImportSource() {
return "crossref";
}
@Override
public void init() throws Exception {}
@Override
public ImportRecord getRecord(String recordId) throws MetadataSourceException {
List<ImportRecord> records = null;
String id = getID(recordId);
if (StringUtils.isNotBlank(id)) {
records = retry(new SearchByIdCallable(id));
} else {
records = retry(new SearchByIdCallable(recordId));
}
return records == null || records.isEmpty() ? null : records.get(0);
}
@Override
public int getRecordsCount(String query) throws MetadataSourceException {
String id = getID(query);
if (StringUtils.isNotBlank(id)) {
return retry(new DoiCheckCallable(id));
}
return retry(new CountByQueryCallable(query));
}
@Override
public int getRecordsCount(Query query) throws MetadataSourceException {
String id = getID(query.toString());
if (StringUtils.isNotBlank(id)) {
return retry(new DoiCheckCallable(id));
}
return retry(new CountByQueryCallable(query));
}
@Override
public Collection<ImportRecord> getRecords(String query, int start, int count) throws MetadataSourceException {
String id = getID(query.toString());
if (StringUtils.isNotBlank(id)) {
return retry(new SearchByIdCallable(id));
}
return retry(new SearchByQueryCallable(query, count, start));
}
@Override
public Collection<ImportRecord> getRecords(Query query) throws MetadataSourceException {
String id = getID(query.toString());
if (StringUtils.isNotBlank(id)) {
return retry(new SearchByIdCallable(id));
}
return retry(new SearchByQueryCallable(query));
}
@Override
public ImportRecord getRecord(Query query) throws MetadataSourceException {
List<ImportRecord> records = null;
String id = getID(query.toString());
if (StringUtils.isNotBlank(id)) {
records = retry(new SearchByIdCallable(id));
} else {
records = retry(new SearchByIdCallable(query));
}
return records == null || records.isEmpty() ? null : records.get(0);
}
@Override
public Collection<ImportRecord> findMatchingRecords(Query query) throws MetadataSourceException {
String id = getID(query.toString());
if (StringUtils.isNotBlank(id)) {
return retry(new SearchByIdCallable(id));
}
return retry(new FindMatchingRecordCallable(query));
}
@Override
public Collection<ImportRecord> findMatchingRecords(Item item) throws MetadataSourceException {
throw new MethodNotFoundException("This method is not implemented for CrossRef");
}
public String getID(String query) {
if (DoiCheck.isDoi(query)) {
return "filter=doi:" + query;
}
return StringUtils.EMPTY;
}
private class SearchByQueryCallable implements Callable<List<ImportRecord>> {
private Query query;
private SearchByQueryCallable(String queryString, Integer maxResult, Integer start) {
query = new Query();
query.addParameter("query", queryString);
query.addParameter("count", maxResult);
query.addParameter("start", start);
}
private SearchByQueryCallable(Query query) {
this.query = query;
}
@Override
public List<ImportRecord> call() throws Exception {
List<ImportRecord> results = new ArrayList<>();
Integer count = query.getParameterAsClass("count", Integer.class);
Integer start = query.getParameterAsClass("start", Integer.class);
URIBuilder uriBuilder = new URIBuilder(ENDPOINT_WORKS);
uriBuilder.addParameter("query", query.getParameterAsClass("query", String.class));
if (Objects.nonNull(count)) {
uriBuilder.addParameter("rows", count.toString());
}
if (Objects.nonNull(start)) {
uriBuilder.addParameter("offset", start.toString());
}
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(),
new HashMap<String, String>());
ReadContext ctx = JsonPath.parse(response);
Object o = ctx.read("$.message.items");
if (o.getClass().isAssignableFrom(JSONArray.class)) {
JSONArray array = (JSONArray) o;
int size = array.size();
for (int index = 0; index < size; index++) {
Gson gson = new Gson();
String innerJson = gson.toJson(array.get(index), LinkedHashMap.class);
results.add(transformSourceRecords(innerJson));
}
} else {
results.add(transformSourceRecords(o.toString()));
}
return results;
}
}
private class SearchByIdCallable implements Callable<List<ImportRecord>> {
private Query query;
private SearchByIdCallable(Query query) {
this.query = query;
}
private SearchByIdCallable(String id) {
this.query = new Query();
query.addParameter("id", id);
}
@Override
public List<ImportRecord> call() throws Exception {
List<ImportRecord> results = new ArrayList<>();
URIBuilder uriBuilder = new URIBuilder(
ENDPOINT_WORKS + "/" + query.getParameterAsClass("id", String.class));
String responseString = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(),
new HashMap<String, String>());
ReadContext ctx = JsonPath.parse(responseString);
Object o = ctx.read("$.message");
if (o.getClass().isAssignableFrom(JSONArray.class)) {
JSONArray array = (JSONArray) o;
int size = array.size();
for (int index = 0; index < size; index++) {
Gson gson = new Gson();
String innerJson = gson.toJson(array.get(index), LinkedHashMap.class);
results.add(transformSourceRecords(innerJson));
}
} else {
Gson gson = new Gson();
results.add(transformSourceRecords(gson.toJson(o, Object.class)));
}
return results;
}
}
private class FindMatchingRecordCallable implements Callable<List<ImportRecord>> {
private Query query;
private FindMatchingRecordCallable(Query q) {
query = q;
}
@Override
public List<ImportRecord> call() throws Exception {
String queryValue = query.getParameterAsClass("query", String.class);
Integer count = query.getParameterAsClass("count", Integer.class);
Integer start = query.getParameterAsClass("start", Integer.class);
String author = query.getParameterAsClass("author", String.class);
String title = query.getParameterAsClass("title", String.class);
String bibliographics = query.getParameterAsClass("bibliographics", String.class);
List<ImportRecord> results = new ArrayList<>();
URIBuilder uriBuilder = new URIBuilder(ENDPOINT_WORKS);
if (Objects.nonNull(queryValue)) {
uriBuilder.addParameter("query", queryValue);
}
if (Objects.nonNull(count)) {
uriBuilder.addParameter("rows", count.toString());
}
if (Objects.nonNull(start)) {
uriBuilder.addParameter("offset", start.toString());
}
if (Objects.nonNull(author)) {
uriBuilder.addParameter("query.author", author);
}
if (Objects.nonNull(title )) {
uriBuilder.addParameter("query.container-title", title);
}
if (Objects.nonNull(bibliographics)) {
uriBuilder.addParameter("query.bibliographic", bibliographics);
}
String resp = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(),
new HashMap<String, String>());
ReadContext ctx = JsonPath.parse(resp);
Object o = ctx.read("$.message.items[*]");
if (o.getClass().isAssignableFrom(JSONArray.class)) {
JSONArray array = (JSONArray) o;
int size = array.size();
for (int index = 0; index < size; index++) {
Gson gson = new Gson();
String innerJson = gson.toJson(array.get(index), LinkedHashMap.class);
results.add(transformSourceRecords(innerJson));
}
} else {
results.add(transformSourceRecords(o.toString()));
}
return results;
}
}
private class CountByQueryCallable implements Callable<Integer> {
private Query query;
private CountByQueryCallable(String queryString) {
query = new Query();
query.addParameter("query", queryString);
}
private CountByQueryCallable(Query query) {
this.query = query;
}
@Override
public Integer call() throws Exception {
URIBuilder uriBuilder = new URIBuilder(ENDPOINT_WORKS);
uriBuilder.addParameter("query", query.getParameterAsClass("query", String.class));
String responseString = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(),
new HashMap<String, String>());
ReadContext ctx = JsonPath.parse(responseString);
return ctx.read("$.message.total-results");
}
}
private class DoiCheckCallable implements Callable<Integer> {
private final Query query;
private DoiCheckCallable(final String id) {
final Query query = new Query();
query.addParameter("id", id);
this.query = query;
}
private DoiCheckCallable(final Query query) {
this.query = query;
}
@Override
public Integer call() throws Exception {
URIBuilder uriBuilder = new URIBuilder(
ENDPOINT_WORKS + "/" + query.getParameterAsClass("id", String.class));
String responseString = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(),
new HashMap<String, String>());
ReadContext ctx = JsonPath.parse(responseString);
return StringUtils.equals(ctx.read("$.status"), "ok") ? 1 : 0;
}
}
}

View File

@@ -0,0 +1,16 @@
/**
* 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.metadatamapping.contributor;
import java.util.Collection;
public interface JsonPathMetadataProcessor {
public Collection<String> processMetadata(String json);
}

View File

@@ -0,0 +1,138 @@
/**
* 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.metadatamapping.contributor;
import java.util.ArrayList;
import java.util.Collection;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import net.minidev.json.JSONArray;
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
import org.dspace.importer.external.metadatamapping.MetadataFieldMapping;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
public class SimpleJsonPathMetadataContributor implements MetadataContributor<String> {
private String query;
private MetadataFieldConfig field;
protected JsonPathMetadataProcessor metadataProcessor;
/**
* Initialize SimpleJsonPathMetadataContributor with a query, prefixToNamespaceMapping and MetadataFieldConfig
*
* @param query The JSonPath query
* @param field the matadata field to map the result of the Json path query
* <a href="https://github.com/DSpace/DSpace/tree/master/dspace-api/src/main/java/org/dspace/importer/external#metadata-mapping-">MetadataFieldConfig</a>
*/
public SimpleJsonPathMetadataContributor(String query, MetadataFieldConfig field) {
this.query = query;
this.field = field;
}
/**
* Unused by this implementation
*/
@Override
public void setMetadataFieldMapping(MetadataFieldMapping<String, MetadataContributor<String>> rt) {
}
/**
* Empty constructor for SimpleJsonPathMetadataContributor
*/
public SimpleJsonPathMetadataContributor() {
}
/**
* Return the MetadataFieldConfig used while retrieving MetadatumDTO
*
* @return MetadataFieldConfig
*/
public MetadataFieldConfig getField() {
return field;
}
/**
* Setting the MetadataFieldConfig
*
* @param field MetadataFieldConfig used while retrieving MetadatumDTO
*/
public void setField(MetadataFieldConfig field) {
this.field = field;
}
/**
* Return query used to create the JSonPath
*
* @return the query this instance is based on
*/
public String getQuery() {
return query;
}
/**
* Return query used to create the JSonPath
*
*/
public void setQuery(String query) {
this.query = query;
}
/**
* Used to process data got by jsonpath expression, like arrays to stringify, change date format or else
* If it is null, toString will be used.
*
* @param metadataProcessor
*/
public void setMetadataProcessor(JsonPathMetadataProcessor metadataProcessor) {
this.metadataProcessor = metadataProcessor;
}
/**
* Retrieve the metadata associated with the given object.
* The toString() of the resulting object will be used.
*
* @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(String fullJson) {
Collection<MetadatumDTO> metadata = new ArrayList<>();
Collection<String> metadataValue = new ArrayList<>();
if (metadataProcessor != null) {
metadataValue = metadataProcessor.processMetadata(fullJson);
} else {
ReadContext ctx = JsonPath.parse(fullJson);
Object o = ctx.read(query);
if (o.getClass().isAssignableFrom(JSONArray.class)) {
JSONArray results = (JSONArray)o;
for (int i = 0; i < results.size(); i++) {
String value = results.get(i).toString();
metadataValue.add(value);
}
} else {
metadataValue.add(o.toString());
}
}
for (String value : metadataValue) {
MetadatumDTO metadatumDto = new MetadatumDTO();
metadatumDto.setValue(value);
metadatumDto.setElement(field.getElement());
metadatumDto.setQualifier(field.getQualifier());
metadatumDto.setSchema(field.getSchema());
metadata.add(metadatumDto);
}
return metadata;
}
}

View File

@@ -116,6 +116,11 @@
</bean>
<bean id="CrossRefImportService" class="org.dspace.importer.external.crossref.CrossRefImportMetadataSourceServiceImpl" scope="singleton">
<property name="metadataFieldMapping" ref="CrossRefMetadataFieldMapping"/>
</bean>
<bean id="CrossRefMetadataFieldMapping" class="org.dspace.importer.external.crossref.CrossRefFieldMapping"/>
<!-- Metadatafield used to check against if it's already imported or not during the JSONLookupSearcher-->
<bean id="lookupID" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.identifier.other"/>

View File

@@ -0,0 +1,144 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
<context:annotation-config/>
<!-- allows us to use spring annotations in beans -->
<util:map id="crossrefMetadataFieldMap" key-type="org.dspace.importer.external.metadatamapping.MetadataFieldConfig"
value-type="org.dspace.importer.external.metadatamapping.contributor.MetadataContributor">
<description>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.
</description>
<entry key-ref="crossref.title" value-ref="crossrefTitleContrib"/>
<entry key-ref="crossref.authors" value-ref="crossrefAuthorContrib"/>
<entry key-ref="crossref.isbn" value-ref="crossrefISBNContrib"/>
<entry key-ref="crossref.year" value-ref="crossrefYearContrib"/>
<entry key-ref="crossref.editors" value-ref="crossrefEditorsContrib"/>
<entry key-ref="crossref.type" value-ref="crossrefDoiTypeContrib"/>
<entry key-ref="crossref.journal" value-ref="crossrefJournalContrib"/>
<entry key-ref="crossref.id" value-ref="crossrefIDContrib"/>
<entry key-ref="crossref.issn" value-ref="crossrefIdentifierISSN" />
<entry key-ref="crossref.volume" value-ref="crossrefVolume" />
<entry key-ref="crossref.issue" value-ref="crossrefIssue" />
<entry key-ref="crossref.abstract" value-ref="crossrefAbstract" />
</util:map>
<bean id="crossrefIDContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.id"/>
<property name="query" value="$.DOI"/>
</bean>
<bean id="crossref.id" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.identifier.doi"/>
</bean>
<bean id="crossrefJournalContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.journal"/>
<property name="query" value="$.container-title"/>
</bean>
<bean id="crossref.journal" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.relation.ispartof"/>
</bean>
<bean id="crossrefDoiTypeContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.type"/>
<property name="query" value="$.type"/>
</bean>
<bean id="crossref.type" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.type"/>
</bean>
<bean id="crossrefEditorsContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.editors"/>
<property name="metadataProcessor" ref="crossrefEditorMetadataProcessor"></property>
</bean>
<bean name="crossrefEditorMetadataProcessor" class="org.dspace.importer.external.crossref.CrossRefAuthorMetadataProcessor">
<property name="givenNameJsonPath" value="$.editor[*].given"></property>
<property name="familyNameJsonPath" value="$.editor[*].family"></property>
</bean>
<bean id="crossref.editors" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.contributor.editor"/>
</bean>
<bean id="crossrefYearContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.year"/>
<property name="query" value="$.issued.date-parts[0][0]"/>
</bean>
<bean id="crossref.year" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.date.issued"/>
</bean>
<bean id="crossrefISBNContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.isbn"/>
<property name="query" value="$.ISBN"/>
</bean>
<bean id="crossref.isbn" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.identifier.isbn"/>
</bean>
<bean id="crossrefAuthorContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.authors"/>
<property name="metadataProcessor" ref="crossrefAuthorMetadataProcessor"></property>
</bean>
<bean name="crossrefAuthorMetadataProcessor" class="org.dspace.importer.external.crossref.CrossRefAuthorMetadataProcessor">
<property name="givenNameJsonPath" value="$.author[*].given"></property>
<property name="familyNameJsonPath" value="$.author[*].family"></property>
</bean>
<bean id="crossref.authors" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.contributor.author"/>
</bean>
<bean id="crossrefTitleContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.title"/>
<property name="query" value="$.title"/>
</bean>
<bean id="crossref.title" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.title"/>
</bean>
<bean id="crossrefIdentifierISSN" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.issn"/>
<property name="query" value="$.ISSN"/>
</bean>
<bean id="crossref.issn" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.relation.issn"/>
</bean>
<bean id="crossrefVolume" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.volume"/>
<property name="query" value="$.volume"/>
</bean>
<bean id="crossref.volume" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="oaire.citation.volume"/>
</bean>
<bean id="crossrefIssue" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.issue"/>
<property name="query" value="$.journal-issue.issue"/>
</bean>
<bean id="crossref.issue" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="oaire.citation.issue"/>
</bean>
<bean id="crossrefAbstract" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
<property name="field" ref="crossref.abstract"/>
<property name="query" value="$.abstract"/>
</bean>
<bean id="crossref.abstract" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.description.abstract"/>
</bean>
<bean class="java.lang.Integer" id="maxRetry">
<constructor-arg value="3"/>
</bean>
</beans>

View File

@@ -94,5 +94,15 @@
</property>
</bean>
</beans>
<bean id="crossRefLiveImportDataProvider" class="org.dspace.external.provider.impl.LiveImportDataProvider">
<property name="metadataSource" ref="CrossRefImportService"/>
<property name="sourceIdentifier" value="crossref"/>
<property name="recordIdMetadata" value="dc.identifier.doi"/>
<property name="supportedEntityTypes">
<list>
<value>Publication</value>
</list>
</property>
</bean>
</beans>