/**
* 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.service;
import org.apache.log4j.Logger;
import org.dspace.content.Item;
import org.dspace.importer.external.exception.MetadataSourceException;
import org.dspace.importer.external.datamodel.Query;
import org.dspace.importer.external.datamodel.ImportRecord;
import org.dspace.importer.external.service.components.Destroyable;
import org.dspace.importer.external.service.components.MetadataSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
/** Main entry point for the import framework.
* Instead of calling the different importer implementations, the ImportService should be called instead.
* This class contains the same methods as the other implementations, but has an extra parameter URL.
* This URL should be the same identifier that is returned by the "getImportSource" method that is defined in the importer implementation you want to use.
* @author Roeland Dillen (roeland at atmire dot com)
*/
public class ImportService implements Destroyable {
private HashMap<String, MetadataSource> importSources = new HashMap<>();
Logger log = Logger.getLogger(ImportService.class);
/**
* Constructs an empty ImportService class object
*/
public ImportService() {
}
protected static final String ANY = "*";
/**
* Sets the importsources that will be used to delegate the retrieving and matching of records to
* @param importSources A list of {@link MetadataSource} to set to this service
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
@Autowired(required = false)
public void setImportSources(List<MetadataSource> importSources) throws MetadataSourceException {
log.info("Loading " + importSources.size() + " import sources.");
for (MetadataSource metadataSource : importSources) {
this.importSources.put(metadataSource.getImportSource(), metadataSource);
}
}
/**
* Retrieve the importSources set to this class.
* @return An unmodifiableMap of importSources
*/
protected Map<String, MetadataSource> getImportSources() {
return Collections.unmodifiableMap(importSources);
}
/**
* Utility method to find what import implementations match the imports uri.
* @param uri the identifier of the import implementation or * for all
* @return matching MetadataSource implementations
*/
protected Collection<MetadataSource> matchingImports(String uri) {
if (ANY.equals(uri)) {
return importSources.values();
} else {
if(importSources.containsKey(uri))
return Collections.singletonList(importSources.get(uri));
else
return Collections.emptyList();
}
}
/** Finds records based on an item
* Delegates to one or more MetadataSource implementations based on the uri. Results will be aggregated.
* @param uri the identifier of the import implementation or * for all
* @param item an item to base the search on
* @return a collection of import records. Only the identifier of the found records may be put in the record.
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public Collection<ImportRecord> findMatchingRecords(String uri, Item item) throws MetadataSourceException {
try {
List<ImportRecord> recordList = new LinkedList<ImportRecord>();
for (MetadataSource metadataSource : matchingImports(uri)) {
recordList.addAll(metadataSource.findMatchingRecords(item));
}
return recordList;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Finds records based on query object.
* Delegates to one or more MetadataSource implementations based on the uri. Results will be aggregated.
* @param uri the identifier of the import implementation or * for all
* @param query a query object to base the search on. The implementation decides how the query is interpreted.
* @return a collection of import records. Only the identifier of the found records may be put in the record.
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public Collection<ImportRecord> findMatchingRecords(String uri, Query query) throws MetadataSourceException {
try {
List<ImportRecord> recordList = new LinkedList<ImportRecord>();
for (MetadataSource metadataSource : matchingImports(uri)) {
recordList.addAll(metadataSource.findMatchingRecords(query));
}
return recordList;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Find the number of records matching a string query;
*
* @param uri the identifier of the import implementation or * for all
* @param query a query to base the search on
* @return the sum of the matching records over all import sources
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public int getNbRecords(String uri, String query) throws MetadataSourceException {
try {
int total = 0;
for (MetadataSource MetadataSource : matchingImports(uri)) {
total += MetadataSource.getNbRecords(query);
}
return total;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Find the number of records matching a query;
*
* @param uri the identifier of the import implementation or * for all
* @param query a query object to base the search on The implementation decides how the query is interpreted.
* @return the sum of the matching records over all import sources
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public int getNbRecords(String uri, Query query) throws MetadataSourceException {
try {
int total = 0;
for (MetadataSource MetadataSource : matchingImports(uri)) {
total += MetadataSource.getNbRecords(query);
}
return total;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Find the number of records matching a string query. Supports pagination
*
* @param uri the identifier of the import implementation or * for all
* @param query a query object to base the search on. The implementation decides how the query is interpreted.
* @param start offset to start at
* @param count number of records to retrieve.
* @return a set of records. Fully transformed.
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public Collection<ImportRecord> getRecords(String uri, String query, int start, int count) throws MetadataSourceException {
try {
List<ImportRecord> recordList = new LinkedList<>();
for (MetadataSource metadataSource : matchingImports(uri)) {
recordList.addAll(metadataSource.getRecords(query, start, count));
}
return recordList;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Find the number of records matching a object query.
*
* @param uri the identifier of the import implementation or * for all
* @param query a query object to base the search on. The implementation decides how the query is interpreted.
* @return a set of records. Fully transformed.
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public Collection<ImportRecord> getRecords(String uri, Query query) throws MetadataSourceException {
try {
List<ImportRecord> recordList = new LinkedList<>();
for (MetadataSource metadataSource : matchingImports(uri)) {
recordList.addAll(metadataSource.getRecords(query));
}
return recordList;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Get a single record from a source.
* The first match will be returned
* @param uri uri the identifier of the import implementation or * for all
* @param id identifier for the record
* @return a matching record
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public ImportRecord getRecord(String uri, String id) throws MetadataSourceException {
try {
for (MetadataSource metadataSource : matchingImports(uri)) {
if (metadataSource.getRecord(id) != null) return metadataSource.getRecord(id);
}
return null;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Get a single record from the source.
* The first match will be returned
* @param uri uri the identifier of the import implementation or * for all
* @param query a query matching a single record
* @return a matching record
* @throws MetadataSourceException if the underlying methods throw any exception.
*/
public ImportRecord getRecord(String uri, Query query) throws MetadataSourceException {
try {
for (MetadataSource metadataSource : matchingImports(uri)) {
if (metadataSource.getRecord(query) != null) return metadataSource.getRecord(query);
}
return null;
} catch (Exception e) {
throw new MetadataSourceException(e);
}
}
/** Retrieve the importUrls that are set on the importSources .
* @return a Collection of string, representing the configured importUrls
*/
public Collection<String> getImportUrls() {
return importSources.keySet();
}
/** Call destroy on all {@link Destroyable} {@link MetadataSource} objects set in this ImportService
*/
@Override
public void destroy() throws Exception {
for (MetadataSource metadataSource : importSources.values()) {
if (metadataSource instanceof Destroyable) ((Destroyable) metadataSource).destroy();
}
}
}