diff --git a/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java b/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java index 3b324f2763..9ed3e742ce 100644 --- a/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java +++ b/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java @@ -460,7 +460,7 @@ public class Harvest { List 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"); diff --git a/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollectionServiceImpl.java b/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollectionServiceImpl.java index fadcfb6ea6..bb3057e0cd 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollectionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/harvest/HarvestedCollectionServiceImpl.java @@ -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 verifyOAIharvester(String oaiSource, + String oaiSetId, String metaPrefix, boolean testORE) { + List errorSet = new ArrayList(); + + // 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; + } + } diff --git a/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java b/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java index ab3a7bcf24..bedf494adb 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java +++ b/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java @@ -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 verifyOAIharvester(String oaiSource, - String oaiSetId, String metaPrefix, boolean testORE) { - List errorSet = new ArrayList(); - - // 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> getAvailableMetadataFormats() { List> configs = new ArrayList<>(); String metaString = "oai.harvester.metadataformats."; diff --git a/dspace-api/src/main/java/org/dspace/harvest/service/HarvestedCollectionService.java b/dspace-api/src/main/java/org/dspace/harvest/service/HarvestedCollectionService.java index 3b2220776f..7df961a9c2 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/service/HarvestedCollectionService.java +++ b/dspace-api/src/main/java/org/dspace/harvest/service/HarvestedCollectionService.java @@ -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 verifyOAIharvester(String oaiSource, + String oaiSetId, String metaPrefix, boolean testORE); } diff --git a/dspace-api/src/test/java/org/dspace/harvest/MockHarvestedCollectionServiceImpl.java b/dspace-api/src/test/java/org/dspace/harvest/MockHarvestedCollectionServiceImpl.java new file mode 100644 index 0000000000..1a1e3f40f6 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/harvest/MockHarvestedCollectionServiceImpl.java @@ -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 verifyOAIharvester(String oaiSource, + String oaiSetId, String metaPrefix, boolean testORE) { + + if (metaPrefix.equals("dc")) { + return new ArrayList<>(); + } else { + return Arrays.asList("(Mock error) Incorrect metadataConfigID"); + } + } +} \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java index 05ef1d6383..28b795d06c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionHarvestSettingsController.java @@ -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 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 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 testHarvestSettings(Collection collection, + HarvestedCollectionRest harvestedCollectionRest) { + + int harvestType = harvestedCollectionRest.getHarvestType(); + String metadataConfigId = harvestedCollectionRest.getMetadataConfigId(); + + List errors = new ArrayList<>(); + + // See if metadata config identifier appears in available metadata formats + List> 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 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(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java index dd223d796d..a07eaab6c2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/HarvesterMetadataController.java @@ -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) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvestTypeEnum.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvestTypeEnum.java index 732605f3d4..aa9f24a4b6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvestTypeEnum.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvestTypeEnum.java @@ -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), diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvesterMetadataRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvesterMetadataRest.java index a3c28c9ffe..1b1e428e2c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvesterMetadataRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/HarvesterMetadataRest.java @@ -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 { public static final String NAME = "harvestermetadata"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/HarvesterMetadataResource.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/HarvesterMetadataResource.java index 76e8910474..6cc64c498d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/HarvesterMetadataResource.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/HarvesterMetadataResource.java @@ -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 { public HarvesterMetadataResource(HarvesterMetadataRest data, Utils utils, String... rels) { diff --git a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/core-services.xml b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/core-services.xml new file mode 100644 index 0000000000..b58f7db043 --- /dev/null +++ b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/core-services.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + news-top.html + news-side.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionHarvestSettingsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionHarvestSettingsControllerIT.java index f4d35c2167..25f31d1354 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionHarvestSettingsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionHarvestSettingsControllerIT.java @@ -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") diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/HarvesterMetadataControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/HarvesterMetadataControllerIT.java index bd4ec95054..c12a17948b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/HarvesterMetadataControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/HarvesterMetadataControllerIT.java @@ -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 diff --git a/dspace-server-webapp/src/test/java/org/dspace/harvest/MockHarvestedCollectionServiceImpl.java b/dspace-server-webapp/src/test/java/org/dspace/harvest/MockHarvestedCollectionServiceImpl.java new file mode 100644 index 0000000000..1a1e3f40f6 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/harvest/MockHarvestedCollectionServiceImpl.java @@ -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 verifyOAIharvester(String oaiSource, + String oaiSetId, String metaPrefix, boolean testORE) { + + if (metaPrefix.equals("dc")) { + return new ArrayList<>(); + } else { + return Arrays.asList("(Mock error) Incorrect metadataConfigID"); + } + } +} \ No newline at end of file