mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 18:14:26 +00:00
Merge pull request #8236 from 4Science/CST-5303-LiveImport-3PR
Migrate extra DSpace-CRIS "Live Import" sources to DSpace (SciELO)
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 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;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
|
||||
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
|
||||
|
||||
/**
|
||||
* This contributor extends SimpleRisToMetadataContributor,
|
||||
* in particular, this one is able to chain multi values into a single one
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.it)
|
||||
*/
|
||||
public class SimpleRisToMetadataConcatContributor extends SimpleRisToMetadataContributor {
|
||||
|
||||
private String tag;
|
||||
|
||||
private MetadataFieldConfig metadata;
|
||||
|
||||
@Override
|
||||
public Collection<MetadatumDTO> contributeMetadata(Map<String, List<String>> record) {
|
||||
List<MetadatumDTO> values = new LinkedList<>();
|
||||
List<String> fieldValues = record.get(this.tag);
|
||||
Optional.ofNullable(fieldValues)
|
||||
.map(fv -> fv.stream())
|
||||
.map(s -> s.collect(Collectors.joining(" ")))
|
||||
.ifPresent(t -> values.add(this.metadataFieldMapping.toDCValue(this.metadata, t)));
|
||||
return values;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public MetadataFieldConfig getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(MetadataFieldConfig metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
|
||||
import org.dspace.importer.external.metadatamapping.MetadataFieldMapping;
|
||||
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
|
||||
|
||||
/**
|
||||
* Metadata contributor that takes a record defined as Map<String,List<String>>
|
||||
* and turns it into metadatums configured in fieldToMetadata
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.it)
|
||||
*/
|
||||
public class SimpleRisToMetadataContributor implements MetadataContributor<Map<String,List<String>>> {
|
||||
|
||||
protected Map<String, MetadataFieldConfig> fieldToMetadata;
|
||||
|
||||
protected MetadataFieldMapping<Map<String,List<String>>,
|
||||
MetadataContributor<Map<String,List<String>>>> metadataFieldMapping;
|
||||
|
||||
public SimpleRisToMetadataContributor() {}
|
||||
|
||||
public SimpleRisToMetadataContributor(Map<String, MetadataFieldConfig> fieldToMetadata) {
|
||||
this.fieldToMetadata = fieldToMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MetadatumDTO> contributeMetadata(Map<String, List<String>> record) {
|
||||
List<MetadatumDTO> values = new LinkedList<>();
|
||||
for (String field : fieldToMetadata.keySet()) {
|
||||
List<String> fieldValues = record.get(field);
|
||||
if (Objects.nonNull(fieldValues)) {
|
||||
for (String value : fieldValues) {
|
||||
values.add(metadataFieldMapping.toDCValue(fieldToMetadata.get(field), value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
public Map<String, MetadataFieldConfig> getFieldToMetadata() {
|
||||
return fieldToMetadata;
|
||||
}
|
||||
|
||||
public void setFieldToMetadata(Map<String, MetadataFieldConfig> fieldToMetadata) {
|
||||
this.fieldToMetadata = fieldToMetadata;
|
||||
}
|
||||
|
||||
public MetadataFieldMapping<Map<String, List<String>>,
|
||||
MetadataContributor<Map<String, List<String>>>> getMetadataFieldMapping() {
|
||||
return metadataFieldMapping;
|
||||
}
|
||||
|
||||
public void setMetadataFieldMapping(MetadataFieldMapping<Map<String, List<String>>,
|
||||
MetadataContributor<Map<String, List<String>>>> metadataFieldMapping) {
|
||||
this.metadataFieldMapping = metadataFieldMapping;
|
||||
}
|
||||
|
||||
}
|
37
dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloFieldMapping.java
vendored
Normal file
37
dspace-api/src/main/java/org/dspace/importer/external/scielo/service/ScieloFieldMapping.java
vendored
Normal 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.scielo.service;
|
||||
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 Scielo metadatum fields on the DSpace metadatum fields
|
||||
*
|
||||
* @author Boychuk Mykhaylo (boychuk.mykhaylo at 4science dot it)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ScieloFieldMapping 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
|
||||
@SuppressWarnings("unchecked")
|
||||
@Resource(name = "scieloMetadataFieldMap")
|
||||
public void setMetadataFieldMap(Map metadataFieldMap) {
|
||||
super.setMetadataFieldMap(metadataFieldMap);
|
||||
}
|
||||
}
|
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* 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.scielo.service;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.el.MethodNotFoundException;
|
||||
import javax.ws.rs.BadRequestException;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
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.FileSourceException;
|
||||
import org.dspace.importer.external.exception.MetadataSourceException;
|
||||
import org.dspace.importer.external.liveimportclient.service.LiveImportClient;
|
||||
import org.dspace.importer.external.service.AbstractImportMetadataSourceService;
|
||||
import org.dspace.importer.external.service.components.QuerySource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Implements a data source for querying Scielo
|
||||
*
|
||||
* @author Boychuk Mykhaylo (boychuk.mykhaylo at 4Science dot it)
|
||||
*/
|
||||
public class ScieloImportMetadataSourceServiceImpl extends AbstractImportMetadataSourceService<Map<String,List<String>>>
|
||||
implements QuerySource {
|
||||
|
||||
/**
|
||||
* This pattern is used when reading the Scielo response,
|
||||
* to check if the fields you are reading is in rid format
|
||||
*/
|
||||
private static final String PATTERN = "^([A-Z][A-Z0-9]) - (.*)$";
|
||||
|
||||
/**
|
||||
* This pattern is used to verify correct format of ScieloId
|
||||
*/
|
||||
private static final String ID_PATTERN = "^(.....)-(.*)-(...)$";
|
||||
|
||||
private int timeout = 1000;
|
||||
|
||||
private String url;
|
||||
|
||||
@Autowired
|
||||
private LiveImportClient liveImportClient;
|
||||
|
||||
@Override
|
||||
public void init() throws Exception {}
|
||||
|
||||
@Override
|
||||
public String getImportSource() {
|
||||
return "scielo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ImportRecord> getRecords(String query, int start, int count) throws MetadataSourceException {
|
||||
return retry(new SearchByQueryCallable(query, count, start));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ImportRecord> getRecords(Query query) throws MetadataSourceException {
|
||||
return retry(new SearchByQueryCallable(query));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ImportRecord getRecord(Query query) throws MetadataSourceException {
|
||||
List<ImportRecord> records = retry(new SearchByQueryCallable(query));
|
||||
return CollectionUtils.isEmpty(records) ? null : records.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImportRecord getRecord(String id) throws MetadataSourceException {
|
||||
List<ImportRecord> records = retry(new FindByIdCallable(id));
|
||||
return CollectionUtils.isEmpty(records) ? null : records.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRecordsCount(String query) throws MetadataSourceException {
|
||||
return retry(new SearchNBByQueryCallable(query));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRecordsCount(Query query) throws MetadataSourceException {
|
||||
throw new MethodNotFoundException("This method is not implemented for Scielo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ImportRecord> findMatchingRecords(Item item) throws MetadataSourceException {
|
||||
throw new MethodNotFoundException("This method is not implemented for Scielo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ImportRecord> findMatchingRecords(Query query) throws MetadataSourceException {
|
||||
throw new MethodNotFoundException("This method is not implemented for Scielo");
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is a Callable implementation to count the number of entries for an Scielo query
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
private class SearchNBByQueryCallable implements Callable<Integer> {
|
||||
|
||||
private String query;
|
||||
|
||||
private SearchNBByQueryCallable(String queryString) {
|
||||
this.query = queryString;
|
||||
}
|
||||
|
||||
private SearchNBByQueryCallable(Query query) {
|
||||
this.query = query.getParameterAsClass("query", String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
URIBuilder uriBuilder = new URIBuilder(url + URLEncoder.encode(query, StandardCharsets.UTF_8));
|
||||
String resp = liveImportClient.executeHttpGetRequest(timeout, uriBuilder.toString(),
|
||||
new HashMap<String, String>());
|
||||
Map<Integer, Map<String, List<String>>> records = getRecords(resp);
|
||||
return Objects.nonNull(records.size()) ? records.size() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is a Callable implementation to get an Scielo entry using ScieloID
|
||||
* The ScieloID to use can be passed through the constructor as a String
|
||||
* or as Query's map entry, with the key "id".
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
private class FindByIdCallable implements Callable<List<ImportRecord>> {
|
||||
|
||||
private String id;
|
||||
|
||||
private FindByIdCallable(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImportRecord> call() throws Exception {
|
||||
List<ImportRecord> results = new ArrayList<>();
|
||||
String scieloId = id.trim();
|
||||
Pattern risPattern = Pattern.compile(ID_PATTERN);
|
||||
Matcher risMatcher = risPattern.matcher(scieloId);
|
||||
if (risMatcher.matches()) {
|
||||
URIBuilder uriBuilder = new URIBuilder(url + URLEncoder.encode(scieloId, StandardCharsets.UTF_8));
|
||||
String resp = liveImportClient.executeHttpGetRequest(timeout, uriBuilder.toString(),
|
||||
new HashMap<String, String>());
|
||||
Map<Integer, Map<String, List<String>>> records = getRecords(resp);
|
||||
if (Objects.nonNull(records) & !records.isEmpty()) {
|
||||
results.add(transformSourceRecords(records.get(1)));
|
||||
}
|
||||
} else {
|
||||
throw new BadRequestException("id provided : " + scieloId + " is not an ScieloID");
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is a Callable implementation to get Scielo entries based on query object.
|
||||
* This Callable use as query value the string queryString passed to constructor.
|
||||
* If the object will be construct through Query.class instance, a Query's map entry with key "query" will be used.
|
||||
* Pagination is supported too, using the value of the Query's map with keys "start" and "count".
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
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("start", start);
|
||||
query.addParameter("count", maxResult);
|
||||
}
|
||||
|
||||
private SearchByQueryCallable(Query query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImportRecord> call() throws Exception {
|
||||
List<ImportRecord> results = new ArrayList<>();
|
||||
String q = query.getParameterAsClass("query", String.class);
|
||||
Integer count = query.getParameterAsClass("count", Integer.class);
|
||||
Integer start = query.getParameterAsClass("start", Integer.class);
|
||||
URIBuilder uriBuilder = new URIBuilder(url + URLEncoder.encode(q, StandardCharsets.UTF_8));
|
||||
uriBuilder.addParameter("start", start.toString());
|
||||
uriBuilder.addParameter("count", count.toString());
|
||||
String resp = liveImportClient.executeHttpGetRequest(timeout, uriBuilder.toString(),
|
||||
new HashMap<String, String>());
|
||||
Map<Integer, Map<String, List<String>>> records = getRecords(resp);
|
||||
for (int record : records.keySet()) {
|
||||
results.add(transformSourceRecords(records.get(record)));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Integer, Map<String,List<String>>> getRecords(String resp) throws FileSourceException {
|
||||
Map<Integer, Map<String, List<String>>> records = new HashMap<Integer, Map<String,List<String>>>();
|
||||
BufferedReader reader;
|
||||
int countRecord = 0;
|
||||
try {
|
||||
reader = new BufferedReader(new StringReader(resp));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.isEmpty() || line.equals("") || line.matches("^\\s*$")) {
|
||||
continue;
|
||||
}
|
||||
line = line.replaceAll("\\uFEFF", "").trim();
|
||||
Pattern risPattern = Pattern.compile(PATTERN);
|
||||
Matcher risMatcher = risPattern.matcher(line);
|
||||
if (risMatcher.matches()) {
|
||||
if (risMatcher.group(1).equals("TY") & risMatcher.group(2).equals("JOUR")) {
|
||||
countRecord ++;
|
||||
Map<String,List<String>> newMap = new HashMap<String, List<String>>();
|
||||
records.put(countRecord, newMap);
|
||||
} else {
|
||||
Map<String, List<String>> tag2values = records.get(countRecord);
|
||||
List<String> values = tag2values.get(risMatcher.group(1));
|
||||
if (Objects.isNull(values)) {
|
||||
List<String> newValues = new ArrayList<String>();
|
||||
newValues.add(risMatcher.group(2));
|
||||
tag2values.put(risMatcher.group(1), newValues);
|
||||
} else {
|
||||
values.add(risMatcher.group(2));
|
||||
tag2values.put(risMatcher.group(1), values);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new FileSourceException("Cannot parse RIS file", e);
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
}
|
@@ -13,7 +13,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility class that provides methods to check if a given string is a DOI and exists on CrossRef services
|
||||
* Utility class that provides methods to check if a given string is a DOI
|
||||
*
|
||||
* @author Corrado Lombardi (corrado.lombardi at 4science.it)
|
||||
*/
|
||||
|
@@ -130,6 +130,12 @@
|
||||
</bean>
|
||||
<bean id="vufindMetadataFieldMapping" class="org.dspace.importer.external.vufind.metadatamapping.VuFindFieldMapping"/>
|
||||
|
||||
<bean id="ScieloImportService" class="org.dspace.importer.external.scielo.service.ScieloImportMetadataSourceServiceImpl" scope="singleton">
|
||||
<property name="metadataFieldMapping" ref="scieloMetadataFieldMapping"/>
|
||||
<property name="url" value="${scielo.url}"/>
|
||||
</bean>
|
||||
<bean id="scieloMetadataFieldMapping" class="org.dspace.importer.external.scielo.service.ScieloFieldMapping"/>
|
||||
|
||||
<!-- 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"/>
|
||||
|
@@ -0,0 +1,236 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.el.MethodNotFoundException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.dspace.builder.CollectionBuilder;
|
||||
import org.dspace.builder.CommunityBuilder;
|
||||
import org.dspace.builder.ItemBuilder;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
import org.dspace.importer.external.liveimportclient.service.LiveImportClientImpl;
|
||||
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
|
||||
import org.dspace.importer.external.scielo.service.ScieloImportMetadataSourceServiceImpl;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ScieloImportMetadataSourceServiceImpl}
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
public class ScieloImportMetadataSourceServiceIT extends AbstractLiveImportIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private LiveImportClientImpl liveImportClientImpl;
|
||||
|
||||
@Autowired
|
||||
private ScieloImportMetadataSourceServiceImpl scieloServiceImpl;
|
||||
|
||||
@Test
|
||||
public void scieloImportMetadataGetRecordsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
CloseableHttpClient originalHttpClient = liveImportClientImpl.getHttpClient();
|
||||
CloseableHttpClient httpClient = Mockito.mock(CloseableHttpClient.class);
|
||||
try (InputStream scieloResp = getClass().getResourceAsStream("scielo-test.txt")) {
|
||||
|
||||
String scieloRipResp = IOUtils.toString(scieloResp, Charset.defaultCharset());
|
||||
|
||||
liveImportClientImpl.setHttpClient(httpClient);
|
||||
CloseableHttpResponse response = mockResponse(scieloRipResp, 200, "OK");
|
||||
when(httpClient.execute(ArgumentMatchers.any())).thenReturn(response);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
ArrayList<ImportRecord> collection2match = getRecords();
|
||||
Collection<ImportRecord> recordsImported = scieloServiceImpl.getRecords("test query", 0, 2);
|
||||
assertEquals(2, recordsImported.size());
|
||||
matchRecords(new ArrayList<ImportRecord>(recordsImported), collection2match);
|
||||
} finally {
|
||||
liveImportClientImpl.setHttpClient(originalHttpClient);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scieloImportMetadataGetRecordsCountTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
CloseableHttpClient originalHttpClient = liveImportClientImpl.getHttpClient();
|
||||
CloseableHttpClient httpClient = Mockito.mock(CloseableHttpClient.class);
|
||||
try (InputStream file = getClass().getResourceAsStream("scielo-test.txt")) {
|
||||
String scieloResp = IOUtils.toString(file, Charset.defaultCharset());
|
||||
|
||||
liveImportClientImpl.setHttpClient(httpClient);
|
||||
CloseableHttpResponse response = mockResponse(scieloResp, 200, "OK");
|
||||
when(httpClient.execute(ArgumentMatchers.any())).thenReturn(response);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
int tot = scieloServiceImpl.getRecordsCount("test query");
|
||||
assertEquals(2, tot);
|
||||
} finally {
|
||||
liveImportClientImpl.setHttpClient(originalHttpClient);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = MethodNotFoundException.class)
|
||||
public void scieloImportMetadataFindMatchingRecordsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
org.dspace.content.Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
|
||||
Item testItem = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("test item")
|
||||
.withIssueDate("2021")
|
||||
.build();
|
||||
context.restoreAuthSystemState();
|
||||
scieloServiceImpl.findMatchingRecords(testItem);
|
||||
}
|
||||
|
||||
@Test(expected = MethodNotFoundException.class)
|
||||
public void scieloImportMetadataGetRecordsCountByQueryTest() throws Exception {
|
||||
Query q = new Query();
|
||||
q.addParameter("query", "test query");
|
||||
scieloServiceImpl.getRecordsCount(q);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scieloImportMetadataGetRecordsByIdTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
CloseableHttpClient originalHttpClient = liveImportClientImpl.getHttpClient();
|
||||
CloseableHttpClient httpClient = Mockito.mock(CloseableHttpClient.class);
|
||||
try (InputStream scieloResp = getClass().getResourceAsStream("scielo-single-record.txt")) {
|
||||
|
||||
String scieloRipResp = IOUtils.toString(scieloResp, Charset.defaultCharset());
|
||||
|
||||
liveImportClientImpl.setHttpClient(httpClient);
|
||||
CloseableHttpResponse response = mockResponse(scieloRipResp, 200, "OK");
|
||||
when(httpClient.execute(ArgumentMatchers.any())).thenReturn(response);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
ArrayList<ImportRecord> collection2match = getRecords();
|
||||
collection2match.remove(1);
|
||||
ImportRecord record = scieloServiceImpl.getRecord("S0185-30582021000200231-mex");
|
||||
assertNotNull(record);
|
||||
Collection<ImportRecord> recordsImported = Arrays.asList(record);
|
||||
matchRecords(new ArrayList<ImportRecord>(recordsImported), collection2match);
|
||||
} finally {
|
||||
liveImportClientImpl.setHttpClient(originalHttpClient);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<ImportRecord> getRecords() {
|
||||
ArrayList<ImportRecord> records = new ArrayList<>();
|
||||
//define first record
|
||||
List<MetadatumDTO> metadatums = new ArrayList<MetadatumDTO>();
|
||||
MetadatumDTO ispartof = createMetadatumDTO("dc", "relation", "ispartof", "Nova tellus");
|
||||
MetadatumDTO date = createMetadatumDTO("dc", "date", "issued", "2021");
|
||||
MetadatumDTO citation = createMetadatumDTO("oaire", "citation", "issue", "2");
|
||||
MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.19130/iifl.nt.2021.39.2.901");
|
||||
MetadatumDTO endPage = createMetadatumDTO("oaire", "citation", "endPage", "236");
|
||||
MetadatumDTO subject = createMetadatumDTO("dc", "subject", null, "Roma");
|
||||
MetadatumDTO subject2 = createMetadatumDTO("dc", "subject", null, "Historia");
|
||||
MetadatumDTO subject3 = createMetadatumDTO("dc", "subject", null, "ritos funerarios");
|
||||
MetadatumDTO subject4 = createMetadatumDTO("dc", "subject", null, "inframundo");
|
||||
MetadatumDTO subject5 = createMetadatumDTO("dc", "subject", null, "epitafios");
|
||||
MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "Torres Marzo, Ricardo");
|
||||
MetadatumDTO title = createMetadatumDTO("dc", "title", null, "Requena Jiménez, Miguel, Los espacios"
|
||||
+ " de la muerte en Roma, Madrid, Síntesis, 2021, 365 págs."
|
||||
+ " más bibliografía en línea, ISBN 978-84-135759-6-4.");
|
||||
MetadatumDTO volume = createMetadatumDTO("oaire", "citation", "volume", "39");
|
||||
MetadatumDTO issn = createMetadatumDTO("dc", "identifier", "issn", "0185-3058");
|
||||
MetadatumDTO other = createMetadatumDTO("dc", "identifier", "other", "S0185-30582021000200231-mex");
|
||||
MetadatumDTO startPage = createMetadatumDTO("oaire", "citation", "startPage", "231");
|
||||
|
||||
metadatums.add(ispartof);
|
||||
metadatums.add(date);
|
||||
metadatums.add(citation);
|
||||
metadatums.add(doi);
|
||||
metadatums.add(endPage);
|
||||
metadatums.add(subject);
|
||||
metadatums.add(subject2);
|
||||
metadatums.add(subject3);
|
||||
metadatums.add(subject4);
|
||||
metadatums.add(subject5);
|
||||
metadatums.add(author);
|
||||
metadatums.add(title);
|
||||
metadatums.add(volume);
|
||||
metadatums.add(issn);
|
||||
metadatums.add(other);
|
||||
metadatums.add(startPage);
|
||||
|
||||
ImportRecord firstrRecord = new ImportRecord(metadatums);
|
||||
|
||||
//define second record
|
||||
List<MetadatumDTO> metadatums2 = new ArrayList<MetadatumDTO>();
|
||||
MetadatumDTO ispartof2 = createMetadatumDTO("dc", "relation", "ispartof", "Revista de Derecho Privado");
|
||||
MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2021");
|
||||
MetadatumDTO citation2 = createMetadatumDTO("oaire", "citation", "issue", "41");
|
||||
MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.18601/01234366.n41.14");
|
||||
MetadatumDTO endPage2 = createMetadatumDTO("oaire", "citation", "endPage", "418");
|
||||
MetadatumDTO subject6 = createMetadatumDTO("dc", "subject", null, "sopravvenienza contrattuale");
|
||||
MetadatumDTO subject7 = createMetadatumDTO("dc", "subject", null, "covro");
|
||||
MetadatumDTO subject8 = createMetadatumDTO("dc", "subject", null, "buona fede in senso oggettivo");
|
||||
MetadatumDTO subject9 = createMetadatumDTO("dc", "subject", null, "obbligo di rinegoziare");
|
||||
MetadatumDTO subject10 = createMetadatumDTO("dc", "subject", null, "revisione del contratto");
|
||||
MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "MAGRI, GEO");
|
||||
MetadatumDTO title2 = createMetadatumDTO("dc", "title", null,
|
||||
"Rinegoziazione e revisione del contratto. Tribunale di Roma, Sez. VI, 27 agosto 2020");
|
||||
MetadatumDTO issn2 = createMetadatumDTO("dc", "identifier", "issn", "0123-4366");
|
||||
MetadatumDTO other2 = createMetadatumDTO("dc", "identifier", "other", "S0123-43662021000200397-col");
|
||||
MetadatumDTO startPage2 = createMetadatumDTO("oaire", "citation", "startPage", "397");
|
||||
MetadatumDTO description = createMetadatumDTO("dc", "description", "abstract",
|
||||
"ABSTRACT: The Tribunal of Rome imposes an obligation to renegotiate long-term contracts,"
|
||||
+ " the balance of which has been modified by the covro pandemic. The decision establishes a"
|
||||
+ " general obligation for the parties to execute the contract in good faith and gives the judge"
|
||||
+ " the possibility of a judicial review. This is a long-awaited decision in doctrine which complies"
|
||||
+ " with the indications of the Supreme Court of Cassation expressed in its memorandum 56/2020.");
|
||||
|
||||
metadatums2.add(ispartof2);
|
||||
metadatums2.add(date2);
|
||||
metadatums2.add(citation2);
|
||||
metadatums2.add(doi2);
|
||||
metadatums2.add(endPage2);
|
||||
metadatums2.add(subject6);
|
||||
metadatums2.add(subject7);
|
||||
metadatums2.add(subject8);
|
||||
metadatums2.add(subject9);
|
||||
metadatums2.add(subject10);
|
||||
metadatums2.add(author2);
|
||||
metadatums2.add(title2);
|
||||
metadatums2.add(issn2);
|
||||
metadatums2.add(other2);
|
||||
metadatums2.add(startPage2);
|
||||
metadatums2.add(description);
|
||||
|
||||
ImportRecord secondRecord = new ImportRecord(metadatums2);
|
||||
records.add(firstrRecord);
|
||||
records.add(secondRecord);
|
||||
return records;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
TY - JOUR
|
||||
AU - Torres Marzo, Ricardo
|
||||
TI - Requena Jiménez, Miguel, Los espacios de la muerte en Roma, Madrid, Síntesis, 2021, 365 págs. más bibliografía en línea, ISBN 978-84-135759-6-4.
|
||||
JO - Nova tellus
|
||||
J2 - Nova tellus
|
||||
SN - 0185-3058
|
||||
VL - 39
|
||||
IS - 2
|
||||
DO - 10.19130/iifl.nt.2021.39.2.901
|
||||
DB - SciELO México
|
||||
DP - http://www.scielo.org/
|
||||
ID - S0185-30582021000200231-mex
|
||||
LA - es
|
||||
SP - 231
|
||||
EP - 236
|
||||
DA - 2021-12
|
||||
PY - 2021
|
||||
UR - http://www.scielo.org.mx/scielo.php?script=sci_arttext&pid=S0185-30582021000200231&lang=pt
|
||||
KW - Roma
|
||||
KW - Historia
|
||||
KW - ritos funerarios
|
||||
KW - inframundo
|
||||
KW - epitafios
|
||||
ER -
|
@@ -0,0 +1,51 @@
|
||||
TY - JOUR
|
||||
AU - Torres Marzo, Ricardo
|
||||
TI - Requena Jiménez, Miguel, Los espacios de la muerte en Roma, Madrid, Síntesis, 2021, 365 págs. más bibliografía en línea, ISBN 978-84-135759-6-4.
|
||||
JO - Nova tellus
|
||||
J2 - Nova tellus
|
||||
SN - 0185-3058
|
||||
VL - 39
|
||||
IS - 2
|
||||
DO - 10.19130/iifl.nt.2021.39.2.901
|
||||
DB - SciELO México
|
||||
DP - http://www.scielo.org/
|
||||
ID - S0185-30582021000200231-mex
|
||||
LA - es
|
||||
SP - 231
|
||||
EP - 236
|
||||
DA - 2021-12
|
||||
PY - 2021
|
||||
UR - http://www.scielo.org.mx/scielo.php?script=sci_arttext&pid=S0185-30582021000200231&lang=pt
|
||||
KW - Roma
|
||||
KW - Historia
|
||||
KW - ritos funerarios
|
||||
KW - inframundo
|
||||
KW - epitafios
|
||||
ER -
|
||||
|
||||
TY - JOUR
|
||||
AU - MAGRI, GEO
|
||||
TI - Rinegoziazione e revisione del contratto. Tribunale di Roma, Sez. VI, 27 agosto 2020
|
||||
JO - Revista de Derecho Privado
|
||||
J2 - Rev. Derecho Privado
|
||||
SN - 0123-4366
|
||||
VL -
|
||||
IS - 41
|
||||
DO - 10.18601/01234366.n41.14
|
||||
DB - SciELO Colômbia
|
||||
DP - http://www.scielo.org/
|
||||
ID - S0123-43662021000200397-col
|
||||
LA - it
|
||||
SP - 397
|
||||
EP - 418
|
||||
DA - 2021-12
|
||||
PY - 2021
|
||||
AB - ABSTRACT: The Tribunal of Rome imposes an obligation to renegotiate long-term contracts, the balance of which has been modified by the covro pandemic. The decision establishes a general obligation for the parties to execute the contract in good faith and gives the judge the possibility of a judicial review. This is a long-awaited decision in doctrine which complies with the indications of the Supreme Court of Cassation expressed in its memorandum 56/2020.
|
||||
UR - http://www.scielo.org.co/scielo.php?script=sci_arttext&pid=S0123-43662021000200397&lang=pt
|
||||
L1 - http://www.scielo.org.co/pdf/rdp/n41/0123-4366-rdp-41-397.pdf
|
||||
KW - sopravvenienza contrattuale
|
||||
KW - covro
|
||||
KW - buona fede in senso oggettivo
|
||||
KW - obbligo di rinegoziare
|
||||
KW - revisione del contratto
|
||||
ER -
|
@@ -20,3 +20,9 @@ vufind.url = https://vufind.org/advanced_demo/api/v1/record
|
||||
vufind.url.search = https://vufind.org/advanced_demo/api/v1/search
|
||||
|
||||
#################################################################
|
||||
#---------------------- Scielo -----------------------------#
|
||||
#---------------------------------------------------------------#
|
||||
|
||||
scielo.url = https://search.scielo.org/?output=ris&q=
|
||||
|
||||
#################################################################
|
@@ -118,4 +118,15 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="scieloLiveImportDataProvider" class="org.dspace.external.provider.impl.LiveImportDataProvider">
|
||||
<property name="metadataSource" ref="ScieloImportService"/>
|
||||
<property name="sourceIdentifier" value="scielo"/>
|
||||
<property name="recordIdMetadata" value="dc.identifier.other"/>
|
||||
<property name="supportedEntityTypes">
|
||||
<list>
|
||||
<value>Publication</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
109
dspace/config/spring/api/scielo-integration.xml
Normal file
109
dspace/config/spring/api/scielo-integration.xml
Normal file
@@ -0,0 +1,109 @@
|
||||
<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="scieloMetadataFieldMap" 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="scielo.doi" value-ref="scieloSimpleContrib"/>
|
||||
<entry key-ref="scielo.abstract" value-ref="scieloAbstractContrib"/>
|
||||
</util:map>
|
||||
|
||||
<bean id="scieloAbstractContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleRisToMetadataConcatContributor">
|
||||
<property name="tag" value="AB"/>
|
||||
<property name="metadata" ref="scielo.abstract"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.abstract" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.description.abstract"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scieloSimpleContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleRisToMetadataContributor">
|
||||
<property name="fieldToMetadata" ref="tag2metadata"/>
|
||||
</bean>
|
||||
|
||||
<util:map id="tag2metadata" map-class="java.util.HashMap"
|
||||
key-type="java.lang.String" value-type="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<entry key="DO" value-ref="scielo.doi"/>
|
||||
<entry key="AU" value-ref="scielo.author"/>
|
||||
<entry key="TI" value-ref="scielo.title"/>
|
||||
<entry key="SN" value-ref="scielo.issn"/>
|
||||
<entry key="VL" value-ref="scielo.volume"/>
|
||||
<entry key="IS" value-ref="scielo.issueIdentifier"/>
|
||||
<entry key="ID" value-ref="scielo.id"/>
|
||||
<entry key="SP" value-ref="scielo.startPage"/>
|
||||
<entry key="EP" value-ref="scielo.endPage"/>
|
||||
<entry key="KW" value-ref="scielo.keywords"/>
|
||||
<entry key="TY" value-ref="scielo.type"/>
|
||||
<entry key="PY" value-ref="scielo.publicationYear"/>
|
||||
<entry key="JO" value-ref="scielo.isPartOf"/>
|
||||
</util:map>
|
||||
|
||||
<bean id="scielo.doi" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.identifier.doi"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.author" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.contributor.author"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.title" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.title"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.issn" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.identifier.issn"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.volume" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="oaire.citation.volume"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.issueIdentifier" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="oaire.citation.issue"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.id" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.identifier.other"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.startPage" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="oaire.citation.startPage"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.endPage" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="oaire.citation.endPage"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.keywords" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.subject"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.type" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.type"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.publicationYear" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.date.issued"/>
|
||||
</bean>
|
||||
|
||||
<bean id="scielo.isPartOf" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||
<constructor-arg value="dc.relation.ispartof"/>
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
Reference in New Issue
Block a user