mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00
Implement fixes/tweaks and add javadocs
This commit is contained in:
@@ -460,7 +460,7 @@ public class Harvest {
|
||||
List<String> errors;
|
||||
|
||||
System.out.print("Testing basic PMH access: ");
|
||||
errors = OAIHarvester.verifyOAIharvester(server, set,
|
||||
errors = harvestedCollectionService.verifyOAIharvester(server, set,
|
||||
(null != metadataFormat) ? metadataFormat : "dc", false);
|
||||
if (errors.isEmpty()) {
|
||||
System.out.println("OK");
|
||||
@@ -471,7 +471,7 @@ public class Harvest {
|
||||
}
|
||||
|
||||
System.out.print("Testing ORE support: ");
|
||||
errors = OAIHarvester.verifyOAIharvester(server, set,
|
||||
errors = harvestedCollectionService.verifyOAIharvester(server, set,
|
||||
(null != metadataFormat) ? metadataFormat : "dc", true);
|
||||
if (errors.isEmpty()) {
|
||||
System.out.println("OK");
|
||||
|
@@ -7,16 +7,28 @@
|
||||
*/
|
||||
package org.dspace.harvest;
|
||||
|
||||
import static org.dspace.harvest.OAIHarvester.OAI_ADDRESS_ERROR;
|
||||
import static org.dspace.harvest.OAIHarvester.OAI_DMD_ERROR;
|
||||
import static org.dspace.harvest.OAIHarvester.OAI_ORE_ERROR;
|
||||
import static org.dspace.harvest.OAIHarvester.OAI_SET_ERROR;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import ORG.oclc.oai.harvester2.verb.Identify;
|
||||
import ORG.oclc.oai.harvester2.verb.ListIdentifiers;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.harvest.dao.HarvestedCollectionDAO;
|
||||
import org.dspace.harvest.service.HarvestedCollectionService;
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.Namespace;
|
||||
import org.jdom.input.DOMBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
@@ -27,6 +39,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
* @author kevinvandevelde at atmire.com
|
||||
*/
|
||||
public class HarvestedCollectionServiceImpl implements HarvestedCollectionService {
|
||||
|
||||
private static final Namespace ORE_NS = Namespace.getNamespace("http://www.openarchives.org/ore/terms/");
|
||||
private static final Namespace OAI_NS = Namespace.getNamespace("http://www.openarchives.org/OAI/2.0/");
|
||||
|
||||
@Autowired(required = true)
|
||||
protected HarvestedCollectionDAO harvestedCollectionDAO;
|
||||
|
||||
@@ -156,5 +172,94 @@ public class HarvestedCollectionServiceImpl implements HarvestedCollectionServic
|
||||
return 0 < harvestedCollectionDAO.count(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the existence of an OAI server with the specified set and
|
||||
* supporting the provided metadata formats.
|
||||
*
|
||||
* @param oaiSource the address of the OAI-PMH provider
|
||||
* @param oaiSetId OAI set identifier
|
||||
* @param metaPrefix OAI metadataPrefix
|
||||
* @param testORE whether the method should also check the PMH provider for ORE support
|
||||
* @return list of errors encountered during verification. Empty list indicates a "success" condition.
|
||||
*/
|
||||
public List<String> verifyOAIharvester(String oaiSource,
|
||||
String oaiSetId, String metaPrefix, boolean testORE) {
|
||||
List<String> errorSet = new ArrayList<String>();
|
||||
|
||||
// First, see if we can contact the target server at all.
|
||||
try {
|
||||
new Identify(oaiSource);
|
||||
} catch (Exception ex) {
|
||||
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached.");
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
// Next, make sure the metadata we need is supported by the target server
|
||||
Namespace DMD_NS = OAIHarvester.getDMDNamespace(metaPrefix);
|
||||
if (null == DMD_NS) {
|
||||
errorSet.add(OAI_DMD_ERROR + ": " + metaPrefix);
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
String OREOAIPrefix = null;
|
||||
String DMDOAIPrefix = null;
|
||||
|
||||
try {
|
||||
OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, OAIHarvester.getORENamespace().getURI());
|
||||
DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI());
|
||||
} catch (Exception ex) {
|
||||
errorSet.add(OAI_ADDRESS_ERROR
|
||||
+ ": OAI did not respond to ListMetadataFormats query ("
|
||||
+ ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; "
|
||||
+ DMD_NS.getPrefix() + ":" + DMDOAIPrefix + "): "
|
||||
+ ex.getMessage());
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
if (testORE && OREOAIPrefix == null) {
|
||||
errorSet.add(OAI_ORE_ERROR + ": The OAI server does not support ORE dissemination");
|
||||
}
|
||||
if (DMDOAIPrefix == null) {
|
||||
errorSet.add(OAI_DMD_ERROR + ": The OAI server does not support dissemination in this format");
|
||||
}
|
||||
|
||||
// Now scan the sets and make sure the one supplied is in the list
|
||||
boolean foundSet = false;
|
||||
try {
|
||||
//If we do not want to harvest from one set, then skip this.
|
||||
if (!"all".equals(oaiSetId)) {
|
||||
ListIdentifiers ls = new ListIdentifiers(oaiSource, null, null, oaiSetId, DMDOAIPrefix);
|
||||
|
||||
// The only error we can really get here is "noSetHierarchy"
|
||||
if (ls.getErrors() != null && ls.getErrors().getLength() > 0) {
|
||||
for (int i = 0; i < ls.getErrors().getLength(); i++) {
|
||||
String errorCode = ls.getErrors().item(i).getAttributes().getNamedItem("code").getTextContent();
|
||||
errorSet.add(
|
||||
OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec (" +
|
||||
errorCode + ")");
|
||||
}
|
||||
} else {
|
||||
// Drilling down to /OAI-PMH/ListSets/set
|
||||
DOMBuilder db = new DOMBuilder();
|
||||
Document reply = db.build(ls.getDocument());
|
||||
Element root = reply.getRootElement();
|
||||
//Check if we can find items, if so this indicates that we have children and our sets exist
|
||||
foundSet = 0 < root.getChild("ListIdentifiers", OAI_NS).getChildren().size();
|
||||
|
||||
if (!foundSet) {
|
||||
errorSet.add(OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException re) {
|
||||
throw re;
|
||||
} catch (Exception e) {
|
||||
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached");
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -32,7 +32,6 @@ import javax.xml.transform.TransformerException;
|
||||
|
||||
import ORG.oclc.oai.harvester2.verb.GetRecord;
|
||||
import ORG.oclc.oai.harvester2.verb.Identify;
|
||||
import ORG.oclc.oai.harvester2.verb.ListIdentifiers;
|
||||
import ORG.oclc.oai.harvester2.verb.ListMetadataFormats;
|
||||
import ORG.oclc.oai.harvester2.verb.ListRecords;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -106,7 +105,7 @@ public class OAIHarvester {
|
||||
protected BitstreamFormatService bitstreamFormatService;
|
||||
protected BundleService bundleService;
|
||||
protected CollectionService collectionService;
|
||||
protected HarvestedCollectionService harvestedCollection;
|
||||
protected HarvestedCollectionService harvestedCollectionService;
|
||||
protected InstallItemService installItemService;
|
||||
protected ItemService itemService;
|
||||
protected HandleService handleService;
|
||||
@@ -144,7 +143,7 @@ public class OAIHarvester {
|
||||
bundleService = ContentServiceFactory.getInstance().getBundleService();
|
||||
collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||
handleService = HandleServiceFactory.getInstance().getHandleService();
|
||||
harvestedCollection = HarvestServiceFactory.getInstance().getHarvestedCollectionService();
|
||||
harvestedCollectionService = HarvestServiceFactory.getInstance().getHarvestedCollectionService();
|
||||
harvestedItemService = HarvestServiceFactory.getInstance().getHarvestedItemService();
|
||||
itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
installItemService = ContentServiceFactory.getInstance().getInstallItemService();
|
||||
@@ -154,7 +153,6 @@ public class OAIHarvester {
|
||||
|
||||
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
|
||||
|
||||
if (dso.getType() != Constants.COLLECTION) {
|
||||
throw new HarvestingException("OAIHarvester can only harvest collections");
|
||||
}
|
||||
@@ -163,7 +161,7 @@ public class OAIHarvester {
|
||||
targetCollection = (Collection) dso;
|
||||
|
||||
harvestRow = hc;
|
||||
if (harvestRow == null || !harvestedCollection.isHarvestable(harvestRow)) {
|
||||
if (harvestRow == null || !harvestedCollectionService.isHarvestable(harvestRow)) {
|
||||
throw new HarvestingException("Provided collection is not set up for harvesting");
|
||||
}
|
||||
|
||||
@@ -192,7 +190,7 @@ public class OAIHarvester {
|
||||
*
|
||||
* @return Namespace of the supported ORE format. Returns null if not found.
|
||||
*/
|
||||
private static Namespace getORENamespace() {
|
||||
public static Namespace getORENamespace() {
|
||||
String ORESerializationString = null;
|
||||
String ORESeialKey = null;
|
||||
String oreString = "oai.harvester.oreSerializationFormat";
|
||||
@@ -217,7 +215,7 @@ public class OAIHarvester {
|
||||
* @param metadataKey
|
||||
* @return Namespace of the designated metadata format. Returns null of not found.
|
||||
*/
|
||||
private static Namespace getDMDNamespace(String metadataKey) {
|
||||
public static Namespace getDMDNamespace(String metadataKey) {
|
||||
String metadataString = null;
|
||||
String metaString = "oai.harvester.metadataformats";
|
||||
|
||||
@@ -317,7 +315,7 @@ public class OAIHarvester {
|
||||
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_BUSY);
|
||||
harvestRow.setHarvestMessage("Collection harvesting is initializing...");
|
||||
harvestRow.setHarvestStartTime(startTime);
|
||||
harvestedCollection.update(ourContext, harvestRow);
|
||||
harvestedCollectionService.update(ourContext, harvestRow);
|
||||
intermediateCommit();
|
||||
|
||||
// expiration timer starts
|
||||
@@ -358,7 +356,7 @@ public class OAIHarvester {
|
||||
harvestRow.setHarvestStartTime(new Date());
|
||||
harvestRow.setHarvestMessage("OAI server did not contain any updates");
|
||||
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_READY);
|
||||
harvestedCollection.update(ourContext, harvestRow);
|
||||
harvestedCollectionService.update(ourContext, harvestRow);
|
||||
return;
|
||||
} else {
|
||||
throw new HarvestingException(errorSet.toString());
|
||||
@@ -415,7 +413,7 @@ public class OAIHarvester {
|
||||
harvestRow.setHarvestMessage(String
|
||||
.format("Collection is currently being harvested (item %d of %d)",
|
||||
currentRecord, totalListSize));
|
||||
harvestedCollection.update(ourContext, harvestRow);
|
||||
harvestedCollectionService.update(ourContext, harvestRow);
|
||||
} finally {
|
||||
//In case of an exception, make sure to restore our authentication state to the previous state
|
||||
ourContext.restoreAuthSystemState();
|
||||
@@ -433,19 +431,19 @@ public class OAIHarvester {
|
||||
alertAdmin(HarvestedCollection.STATUS_OAI_ERROR, hex);
|
||||
}
|
||||
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_OAI_ERROR);
|
||||
harvestedCollection.update(ourContext, harvestRow);
|
||||
harvestedCollectionService.update(ourContext, harvestRow);
|
||||
ourContext.complete();
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
harvestRow.setHarvestMessage("Unknown error occurred while generating an OAI response");
|
||||
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_UNKNOWN_ERROR);
|
||||
harvestedCollection.update(ourContext, harvestRow);
|
||||
harvestedCollectionService.update(ourContext, harvestRow);
|
||||
alertAdmin(HarvestedCollection.STATUS_UNKNOWN_ERROR, ex);
|
||||
log.error("Error occurred while generating an OAI response: " + ex.getMessage() + " " + ex.getCause(), ex);
|
||||
ourContext.complete();
|
||||
return;
|
||||
} finally {
|
||||
harvestedCollection.update(ourContext, harvestRow);
|
||||
harvestedCollectionService.update(ourContext, harvestRow);
|
||||
ourContext.turnOffAuthorisationSystem();
|
||||
collectionService.update(ourContext, targetCollection);
|
||||
ourContext.restoreAuthSystemState();
|
||||
@@ -460,7 +458,7 @@ public class OAIHarvester {
|
||||
log.info(
|
||||
"Harvest from " + oaiSource + " successful. The process took " + timeTaken + " milliseconds. Harvested "
|
||||
+ currentRecord + " items.");
|
||||
harvestedCollection.update(ourContext, harvestRow);
|
||||
harvestedCollectionService.update(ourContext, harvestRow);
|
||||
|
||||
ourContext.setMode(originalMode);
|
||||
}
|
||||
@@ -904,97 +902,14 @@ public class OAIHarvester {
|
||||
String oaiSetId = harvestRow.getOaiSetId();
|
||||
String metaPrefix = harvestRow.getHarvestMetadataConfig();
|
||||
|
||||
return verifyOAIharvester(oaiSource, oaiSetId, metaPrefix, true);
|
||||
return harvestedCollectionService.verifyOAIharvester(oaiSource, oaiSetId, metaPrefix, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the existence of an OAI server with the specified set and
|
||||
* supporting the provided metadata formats.
|
||||
* Return all available metadata formats
|
||||
*
|
||||
* @param oaiSource the address of the OAI-PMH provider
|
||||
* @param oaiSetId OAI set identifier
|
||||
* @param metaPrefix OAI metadataPrefix
|
||||
* @param testORE whether the method should also check the PMH provider for ORE support
|
||||
* @return list of errors encountered during verification. Empty list indicates a "success" condition.
|
||||
* @return a list containing a map for each supported metadata format
|
||||
*/
|
||||
public static List<String> verifyOAIharvester(String oaiSource,
|
||||
String oaiSetId, String metaPrefix, boolean testORE) {
|
||||
List<String> errorSet = new ArrayList<String>();
|
||||
|
||||
// First, see if we can contact the target server at all.
|
||||
try {
|
||||
new Identify(oaiSource);
|
||||
} catch (Exception ex) {
|
||||
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached.");
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
// Next, make sure the metadata we need is supported by the target server
|
||||
Namespace DMD_NS = OAIHarvester.getDMDNamespace(metaPrefix);
|
||||
if (null == DMD_NS) {
|
||||
errorSet.add(OAI_DMD_ERROR + ": " + metaPrefix);
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
String OREOAIPrefix = null;
|
||||
String DMDOAIPrefix = null;
|
||||
|
||||
try {
|
||||
OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, getORENamespace().getURI());
|
||||
DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI());
|
||||
} catch (Exception ex) {
|
||||
errorSet.add(OAI_ADDRESS_ERROR
|
||||
+ ": OAI did not respond to ListMetadataFormats query ("
|
||||
+ ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; "
|
||||
+ DMD_NS.getPrefix() + ":" + DMDOAIPrefix + "): "
|
||||
+ ex.getMessage());
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
if (testORE && OREOAIPrefix == null) {
|
||||
errorSet.add(OAI_ORE_ERROR + ": The OAI server does not support ORE dissemination");
|
||||
}
|
||||
if (DMDOAIPrefix == null) {
|
||||
errorSet.add(OAI_DMD_ERROR + ": The OAI server does not support dissemination in this format");
|
||||
}
|
||||
|
||||
// Now scan the sets and make sure the one supplied is in the list
|
||||
boolean foundSet = false;
|
||||
try {
|
||||
//If we do not want to harvest from one set, then skip this.
|
||||
if (!"all".equals(oaiSetId)) {
|
||||
ListIdentifiers ls = new ListIdentifiers(oaiSource, null, null, oaiSetId, DMDOAIPrefix);
|
||||
|
||||
// The only error we can really get here is "noSetHierarchy"
|
||||
if (ls.getErrors() != null && ls.getErrors().getLength() > 0) {
|
||||
for (int i = 0; i < ls.getErrors().getLength(); i++) {
|
||||
String errorCode = ls.getErrors().item(i).getAttributes().getNamedItem("code").getTextContent();
|
||||
errorSet.add(
|
||||
OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec (" +
|
||||
errorCode + ")");
|
||||
}
|
||||
} else {
|
||||
// Drilling down to /OAI-PMH/ListSets/set
|
||||
Document reply = db.build(ls.getDocument());
|
||||
Element root = reply.getRootElement();
|
||||
//Check if we can find items, if so this indicates that we have children and our sets exist
|
||||
foundSet = 0 < root.getChild("ListIdentifiers", OAI_NS).getChildren().size();
|
||||
|
||||
if (!foundSet) {
|
||||
errorSet.add(OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException re) {
|
||||
throw re;
|
||||
} catch (Exception e) {
|
||||
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached");
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
return errorSet;
|
||||
}
|
||||
|
||||
public static List<Map<String,String>> getAvailableMetadataFormats() {
|
||||
List<Map<String,String>> configs = new ArrayList<>();
|
||||
String metaString = "oai.harvester.metadataformats.";
|
||||
|
@@ -137,4 +137,15 @@ public interface HarvestedCollectionService {
|
||||
public void update(Context context, HarvestedCollection harvestedCollection) throws SQLException;
|
||||
|
||||
public boolean exists(Context context) throws SQLException;
|
||||
|
||||
/**
|
||||
* Test the given harvest settings
|
||||
* @param oaiSource the address of the OAI-PMH provider
|
||||
* @param oaiSetId OAI set identifier
|
||||
* @param metaPrefix OAI metadataPrefix
|
||||
* @param testORE whether the method should also check the PMH provider for ORE support
|
||||
* @return list of errors encountered during verification. An empty list indicates a "success" condition.
|
||||
*/
|
||||
public List<String> verifyOAIharvester(String oaiSource,
|
||||
String oaiSetId, String metaPrefix, boolean testORE);
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.harvest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A mock for the HarvestedCollectionService
|
||||
* @author Jelle Pelgrims (jelle.atmire at gmail.com)
|
||||
*/
|
||||
public class MockHarvestedCollectionServiceImpl extends HarvestedCollectionServiceImpl {
|
||||
|
||||
@Override
|
||||
public List<String> verifyOAIharvester(String oaiSource,
|
||||
String oaiSetId, String metaPrefix, boolean testORE) {
|
||||
|
||||
if (metaPrefix.equals("dc")) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return Arrays.asList("(Mock error) Incorrect metadataConfigID");
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,7 +9,10 @@ package org.dspace.app.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -34,8 +37,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rest controller that handles the changing of harvest settings for collections
|
||||
*
|
||||
* @author Jelle Pelgrims
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/core/collections/" +
|
||||
"{collectionUuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12" +
|
||||
@@ -48,6 +54,14 @@ public class CollectionHarvestSettingsController {
|
||||
@Autowired
|
||||
HarvestedCollectionService harvestedCollectionService;
|
||||
|
||||
/**
|
||||
* GET Endpoint for updating the settings of a collection.
|
||||
*
|
||||
* @param collectionUuid The collection whose settings should be changed
|
||||
* @param response The response object
|
||||
* @param request The request object
|
||||
* @throws SQLException
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.PUT, consumes = {"application/json"})
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
public void updateHarvestSettingsEndpoint(@PathVariable UUID collectionUuid,
|
||||
@@ -72,37 +86,82 @@ public class CollectionHarvestSettingsController {
|
||||
throw new UnprocessableEntityException("Error parsing request body: " + e.toString(), e);
|
||||
}
|
||||
|
||||
// Create a new harvestedCollection object if there isn't one yet
|
||||
HarvestedCollection harvestedCollection = harvestedCollectionService.find(context, collection);
|
||||
|
||||
if (harvestedCollection == null) {
|
||||
harvestedCollection = harvestedCollectionService.create(context, collection);
|
||||
}
|
||||
|
||||
// Delete harvestedCollection object if harvest type is not set
|
||||
if (harvestedCollectionRest.getHarvestType() == HarvestTypeEnum.NONE.getValue()) {
|
||||
// Delete harvestedCollectionService object if harvest type is not set
|
||||
if (harvestedCollectionRest.getHarvestType() == HarvestTypeEnum.NONE.getValue()
|
||||
&& harvestedCollection != null) {
|
||||
harvestedCollectionService.delete(context, harvestedCollection);
|
||||
} else if (testHarvestSettings(context, collection, harvestedCollectionRest)) {
|
||||
updateCollectionHarvestSettings(context, harvestedCollection, harvestedCollectionRest);
|
||||
} else {
|
||||
throw new UnprocessableEntityException("Incorrect harvest settings in request");
|
||||
|
||||
} else if (harvestedCollectionRest.getHarvestType() != HarvestTypeEnum.NONE.getValue()) {
|
||||
List<String> errors = testHarvestSettings(collection, harvestedCollectionRest);
|
||||
|
||||
if (errors.size() == 0) {
|
||||
if (harvestedCollection == null) {
|
||||
harvestedCollection = harvestedCollectionService.create(context, collection);
|
||||
}
|
||||
|
||||
updateCollectionHarvestSettings(context, harvestedCollection, harvestedCollectionRest);
|
||||
} else {
|
||||
throw new UnprocessableEntityException(
|
||||
"Incorrect harvest settings in request. The following errors were found: " + errors.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
context.complete();
|
||||
}
|
||||
|
||||
private boolean testHarvestSettings(Context context,
|
||||
Collection collection,
|
||||
HarvestedCollectionRest harvestedCollectionRest) throws SQLException {
|
||||
List<String> errors = OAIHarvester.verifyOAIharvester(
|
||||
harvestedCollectionRest.getOaiSource(),
|
||||
harvestedCollectionRest.getOaiSetId(),
|
||||
harvestedCollectionRest.getMetadataConfigId(),
|
||||
true
|
||||
);
|
||||
return errors.size() == 0;
|
||||
/**
|
||||
* Function used to verify that the harvest settings work
|
||||
* @param collection The collection to which the harvest settings should be aplied
|
||||
* @param harvestedCollectionRest A object containg the harvest settings to be tested
|
||||
* @return
|
||||
*/
|
||||
private List<String> testHarvestSettings(Collection collection,
|
||||
HarvestedCollectionRest harvestedCollectionRest) {
|
||||
|
||||
int harvestType = harvestedCollectionRest.getHarvestType();
|
||||
String metadataConfigId = harvestedCollectionRest.getMetadataConfigId();
|
||||
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
// See if metadata config identifier appears in available metadata formats
|
||||
List<Map<String,String>> metadataFormats = OAIHarvester.getAvailableMetadataFormats();
|
||||
boolean inAvailableMetadataFormats = metadataFormats.stream()
|
||||
.filter(x -> x.get("id").equals(metadataConfigId))
|
||||
.count() >= 1;
|
||||
|
||||
if (inAvailableMetadataFormats) {
|
||||
boolean testORE = Arrays.asList(
|
||||
HarvestTypeEnum.METADATA_AND_REF.getValue(),
|
||||
HarvestTypeEnum.METADATA_AND_BITSTREAMS.getValue()
|
||||
).contains(harvestType);
|
||||
|
||||
// Actually verify the harvest settings
|
||||
List<String> verificationErrors = harvestedCollectionService.verifyOAIharvester(
|
||||
harvestedCollectionRest.getOaiSource(),
|
||||
harvestedCollectionRest.getOaiSetId(),
|
||||
metadataConfigId,
|
||||
testORE
|
||||
);
|
||||
errors = verificationErrors;
|
||||
} else {
|
||||
errors.add(
|
||||
"The metadata format with identifier '" + metadataConfigId + "' is not an available metadata format."
|
||||
);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to update the harvest settings of a collection
|
||||
* @param context The context object
|
||||
* @param harvestedCollection The harvestedCollection whose settings should be updated
|
||||
* @param harvestedCollectionRest An object containing the new harvest settings
|
||||
* @throws SQLException
|
||||
*/
|
||||
private void updateCollectionHarvestSettings(Context context, HarvestedCollection harvestedCollection,
|
||||
HarvestedCollectionRest harvestedCollectionRest) throws SQLException {
|
||||
int harvestType = harvestedCollectionRest.getHarvestType();
|
||||
|
@@ -23,8 +23,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rest controller that handles the harvesting metadata formats
|
||||
*
|
||||
* @author Jelle Pelgrims
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/config/harvestermetadata")
|
||||
public class HarvesterMetadataController {
|
||||
@@ -35,6 +38,12 @@ public class HarvesterMetadataController {
|
||||
@Autowired
|
||||
private HalLinkService halLinkService;
|
||||
|
||||
/**
|
||||
* GET endpoint that returns all available metadata formats
|
||||
* @param request The request object
|
||||
* @param response The response object
|
||||
* @return a HarvesterMetadataResource containing all available metadata formats
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public HarvesterMetadataResource get(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
|
@@ -1,5 +1,18 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
/**
|
||||
* An enum containing all the possible harvest types
|
||||
*
|
||||
* @author Jelle Pelgrims (jelle.atmire @ gmail.com)
|
||||
*/
|
||||
public enum HarvestTypeEnum {
|
||||
NONE(0),
|
||||
METADATA_ONLY(1),
|
||||
|
@@ -13,6 +13,11 @@ import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.dspace.app.rest.HarvesterMetadataController;
|
||||
|
||||
/**
|
||||
* The rest resource used for harvester metadata
|
||||
*
|
||||
* @author Jelle Pelgrims
|
||||
*/
|
||||
public class HarvesterMetadataRest extends BaseObjectRest<String> {
|
||||
|
||||
public static final String NAME = "harvestermetadata";
|
||||
|
@@ -10,6 +10,12 @@ package org.dspace.app.rest.model.hateoas;
|
||||
import org.dspace.app.rest.model.HarvesterMetadataRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Harvester metadata rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links.
|
||||
*
|
||||
* @author Jelle Pelgrims (jelle.pelgrims at gmail.com)
|
||||
*/
|
||||
public class HarvesterMetadataResource extends DSpaceResource<HarvesterMetadataRest> {
|
||||
|
||||
public HarvesterMetadataResource(HarvesterMetadataRest data, Utils utils, String... rels) {
|
||||
|
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
|
||||
default-lazy-init="true">
|
||||
|
||||
|
||||
<!-- ******************** -->
|
||||
<!-- Service declarations -->
|
||||
<!-- ******************** -->
|
||||
<bean class="org.dspace.app.requestitem.RequestItemServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.app.itemexport.ItemExportServiceImpl"/>
|
||||
|
||||
<!--Ensure that bean remains prototype ! Uses setters to set certain properties such as should is pass through workflow-->
|
||||
<bean class="org.dspace.app.itemimport.ItemImportServiceImpl" scope="prototype"/>
|
||||
|
||||
<!--Ensure that bean remains prototype ! -->
|
||||
<bean class="org.dspace.app.mediafilter.MediaFilterServiceImpl" scope="prototype"/>
|
||||
|
||||
<bean class="org.dspace.app.sfx.SFXFileReaderServiceImpl" scope="prototype"/>
|
||||
|
||||
<bean class="org.dspace.app.util.MetadataExposureServiceImpl"/>
|
||||
<bean class="org.dspace.app.util.OpenSearchServiceImpl"/>
|
||||
<bean class="org.dspace.app.util.WebAppServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.authenticate.AuthenticationServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.authorize.AuthorizeServiceImpl"/>
|
||||
<bean class="org.dspace.authorize.ResourcePolicyServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.authority.AuthorityValueServiceImpl"/>
|
||||
<bean class="org.dspace.authority.AuthorityServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.checker.ChecksumHistoryServiceImpl"/>
|
||||
<bean class="org.dspace.checker.ChecksumResultServiceImpl"/>
|
||||
<bean class="org.dspace.checker.MostRecentChecksumServiceImpl"/>
|
||||
<bean class="org.dspace.checker.SimpleReporterServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.content.CollectionServiceImpl"/>
|
||||
<bean class="org.dspace.content.BitstreamFormatServiceImpl"/>
|
||||
<bean class="org.dspace.content.BitstreamServiceImpl"/>
|
||||
<bean class="org.dspace.content.BundleServiceImpl"/>
|
||||
<bean class="org.dspace.content.CommunityServiceImpl"/>
|
||||
<bean class="org.dspace.content.InstallItemServiceImpl"/>
|
||||
<bean class="org.dspace.content.ItemServiceImpl"/>
|
||||
<bean class="org.dspace.content.MetadataFieldServiceImpl"/>
|
||||
<bean class="org.dspace.content.MetadataSchemaServiceImpl"/>
|
||||
<bean class="org.dspace.content.MetadataValueServiceImpl"/>
|
||||
<bean class="org.dspace.content.SiteServiceImpl"/>
|
||||
<bean class="org.dspace.content.SupervisedItemServiceImpl"/>
|
||||
<bean class="org.dspace.content.WorkspaceItemServiceImpl"/>
|
||||
<bean class="org.dspace.content.RelationshipServiceImpl"/>
|
||||
<bean class="org.dspace.content.EntityTypeServiceImpl"/>
|
||||
<bean class="org.dspace.content.EntityServiceImpl"/>
|
||||
<bean class="org.dspace.content.RelationshipTypeServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.content.authority.ChoiceAuthorityServiceImpl"/>
|
||||
<bean class="org.dspace.content.authority.MetadataAuthorityServiceImpl" lazy-init="true"/>
|
||||
|
||||
<!-- Ensure PluginService is initialized properly via init() method -->
|
||||
<bean class="org.dspace.core.LegacyPluginServiceImpl" init-method="init"/>
|
||||
<bean class="org.dspace.core.LicenseServiceImpl"/>
|
||||
<bean class="org.dspace.core.NewsServiceImpl">
|
||||
<property name="acceptableFilenames">
|
||||
<list>
|
||||
<value>news-top.html</value>
|
||||
<value>news-side.html</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Ensure WorkflowCuratorService is initialized properly via init() method -->
|
||||
<bean class="org.dspace.curate.WorkflowCuratorServiceImpl" init-method="init"/>
|
||||
|
||||
<bean class="org.dspace.disseminate.CitationDocumentServiceImpl"/>
|
||||
|
||||
<!-- Ensure EmbargoService is initialized properly via init() method -->
|
||||
<bean class="org.dspace.embargo.EmbargoServiceImpl" init-method="init"/>
|
||||
|
||||
<bean class="org.dspace.eperson.AccountServiceImpl"/>
|
||||
<bean class="org.dspace.eperson.EPersonServiceImpl"/>
|
||||
<bean class="org.dspace.eperson.GroupServiceImpl"/>
|
||||
<bean class="org.dspace.eperson.RegistrationDataServiceImpl"/>
|
||||
<bean class="org.dspace.eperson.SubscribeServiceImpl"/>
|
||||
<bean class="org.dspace.eperson.SupervisorServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.event.EventServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.handle.HandleServiceImpl"/>
|
||||
|
||||
<!-- Replace harvestCollectionService with a mocked service -->
|
||||
<bean class="org.dspace.harvest.MockHarvestedCollectionServiceImpl" id="org.dspace.harvest.service.HarvestedCollectionService"/>
|
||||
<bean class="org.dspace.harvest.HarvestedItemServiceImpl"/>
|
||||
<bean class="org.dspace.harvest.HarvestSchedulingServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.identifier.DOIServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.license.CreativeCommonsServiceImpl"/>
|
||||
|
||||
<bean id="spiderDetectorService" class="org.dspace.statistics.util.SpiderDetectorServiceImpl"/>
|
||||
<bean id="clientInfoService" class="org.dspace.service.impl.ClientInfoServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.versioning.VersionHistoryServiceImpl"/>
|
||||
|
||||
<!-- Configurable workflow services -->
|
||||
<bean class="org.dspace.xmlworkflow.storedcomponents.ClaimedTaskServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.storedcomponents.CollectionRoleServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.storedcomponents.InProgressUserServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.storedcomponents.PoolTaskServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.storedcomponents.WorkflowItemRoleServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItemServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.XmlWorkflowServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.WorkflowRequirementsServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.XmlWorkflowFactoryImpl"/>
|
||||
</beans>
|
@@ -25,6 +25,11 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Integration test for collection harvest settings controller
|
||||
*
|
||||
* @author Jelle Pelgrims (jelle.atmire at gmail.com)
|
||||
*/
|
||||
public class CollectionHarvestSettingsControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
Collection collection;
|
||||
@@ -44,11 +49,17 @@ public class CollectionHarvestSettingsControllerIT extends AbstractControllerInt
|
||||
.build();
|
||||
collection = CollectionBuilder.createCollection(context, community).withName("Collection 1").build();
|
||||
|
||||
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create a JSONObject containing the harvest settings
|
||||
* @param harvestType The harvest type
|
||||
* @param oaiSource The OAI source
|
||||
* @param oaiSetId The OAI set id
|
||||
* @param metadataConfigId The metadata config id
|
||||
* @return A JSONObject containing the given harvest settings
|
||||
*/
|
||||
public JSONObject createHarvestSettingsJson(String harvestType,
|
||||
String oaiSource, String oaiSetId, String metadataConfigId) {
|
||||
JSONObject json = new JSONObject();
|
||||
@@ -59,13 +70,11 @@ public class CollectionHarvestSettingsControllerIT extends AbstractControllerInt
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
// This test might fail if the oai_source ("https://dspace.mit.edu/oai/request") is down
|
||||
@Test
|
||||
public void EndpointWorksWithStandardSettings() throws Exception {
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
JSONObject json = createHarvestSettingsJson("METADATA_ONLY", "https://dspace.mit.edu/oai/request", "col_1721.1_114174", "dc");
|
||||
JSONObject json = createHarvestSettingsJson("METADATA_ONLY", "https://dspace.org/oai/request", "col_1721.1_114174", "dc");
|
||||
|
||||
getClient(token).perform(
|
||||
put("/api/core/collections/" + collection.getID() + "/harvester")
|
||||
@@ -99,7 +108,7 @@ public class CollectionHarvestSettingsControllerIT extends AbstractControllerInt
|
||||
public void HarvestSettingsDeletedIfHarvestTypeIsNone() throws Exception {
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
JSONObject json = createHarvestSettingsJson("NONE", "", "", "");
|
||||
JSONObject json = createHarvestSettingsJson("NONE", "", "", "dc");
|
||||
|
||||
getClient(token).perform(
|
||||
put("/api/core/collections/" + collection.getID() + "/harvester")
|
||||
|
@@ -15,7 +15,11 @@ import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.harvest.OAIHarvester;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for harvester metadata controller
|
||||
*
|
||||
* @author Jelle Pelgrims (jelle.atmire at gmail.com)
|
||||
*/
|
||||
public class HarvesterMetadataControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
|
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.harvest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A mock for the HarvestedCollectionService
|
||||
* @author Jelle Pelgrims (jelle.atmire at gmail.com)
|
||||
*/
|
||||
public class MockHarvestedCollectionServiceImpl extends HarvestedCollectionServiceImpl {
|
||||
|
||||
@Override
|
||||
public List<String> verifyOAIharvester(String oaiSource,
|
||||
String oaiSetId, String metaPrefix, boolean testORE) {
|
||||
|
||||
if (metaPrefix.equals("dc")) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return Arrays.asList("(Mock error) Incorrect metadataConfigID");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user