diff --git a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java index 2ac9ad92d071b5c87fa376b2d635dcf409b03cd0..2ef969f7ad513c7724e722060c5d0fec5d39e81c 100644 --- a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java +++ b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java @@ -69,6 +69,7 @@ public class OAIConstants { public static final String OAI_DC_NAMESPACE = "http://www.openarchives.org/OAI/2.0/oai_dc/"; // OAI Identifier public static final String OAI_ID = "oai-identifier"; + public static final String OAI_ID_SCHEMA = "http://www.openarchives.org/OAI/2.0/oai-identifier.xsd"; public static final String OAI_ID_NAMESPACE = "http://www.openarchives.org/OAI/2.0/oai-identifier"; // Dublin Core public static final String DC = "dc"; diff --git a/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java b/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java index bfb61be0cd24c052461d81ad6275554d3ae62cc7..98f815ce30637fd1f914d229976315aa4d1e39d9 100644 --- a/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java +++ b/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java @@ -47,4 +47,7 @@ public interface OAIRepositoryInfo { JAXBElement<?> getRepositoryDefinition(); + String getRepositoryNamepsace(); + + String getRepositorySchema(); } diff --git a/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java b/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java index 78293bdbf9f4485c8bc123aace1f54cdc04cf3c6..b37b9dbc41491c70ade437818f7be63439da474f 100644 --- a/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java +++ b/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java @@ -29,6 +29,8 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import java.io.IOException; import java.time.Instant; import java.time.ZoneOffset; +import java.util.HashMap; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.xml.bind.JAXBException; @@ -61,6 +63,7 @@ import ch.unige.solidify.controller.OAIController; import ch.unige.solidify.exception.OAIException; import ch.unige.solidify.exception.SolidifyResourceNotFoundException; import ch.unige.solidify.exception.SolidifyRuntimeException; +import ch.unige.solidify.model.oai.OAIMetadataPrefix; import ch.unige.solidify.model.oai.OAIPMH; import ch.unige.solidify.model.xml.oai.v2.OAIPMHerrorcodeType; import ch.unige.solidify.model.xml.oai.v2.OAIPMHtype; @@ -92,6 +95,7 @@ public class OAIProviderController implements ControllerWithHateoasHome { @RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) { final OAIPMHtype oai = new OAIPMHtype(); final String oaiUrl = this.getBaseUrl(request) + this.getRequestUri(request); // OAI provider base URL + final Map<String, String> schemaLocations = new HashMap<>(); try { switch (this.oaiService.getVerb(verb)) { case GET_RECORD: @@ -99,12 +103,20 @@ public class OAIProviderController implements ControllerWithHateoasHome { // ------------ // https://www.openarchives.org/OAI/openarchivesprotocol.html#GetRecord oai.setGetRecord(this.oaiService.getRecord(this.getRootUrl(request), identifier, metadataPrefix)); + final OAIMetadataPrefix oaiMetadataPrefixForRecord = this.oaiService.getOAIMetadataPrefix(metadataPrefix); + schemaLocations.put(oaiMetadataPrefixForRecord.getSchemaNamespace(), oaiMetadataPrefixForRecord.getSchemaUrl().toString()); break; case IDENTIFY: // Specification // ------------ // https://www.openarchives.org/OAI/openarchivesprotocol.html#Identify oai.setIdentify(this.oaiService.getIdentify(oaiUrl)); + // OAI Identifier + schemaLocations.put(OAIConstants.OAI_ID_NAMESPACE, OAIConstants.OAI_ID_SCHEMA); + // OAI Repository + schemaLocations.put( + this.oaiService.getOaiRepositoryInfo().getRepositoryNamepsace(), + oaiUrl + SolidifyConstants.URL_SEP + SolidifyConstants.SCHEMA); break; case LIST_IDENTIFIERS: // Specification @@ -123,6 +135,8 @@ public class OAIProviderController implements ControllerWithHateoasHome { // ------------ // https://www.openarchives.org/OAI/openarchivesprotocol.html#ListRecords oai.setListRecords(this.oaiService.listRecords(this.getBaseUrl(request), metadataPrefix, from, until, set, token)); + final OAIMetadataPrefix oaiMetadataPrefixForList = this.oaiService.getOAIMetadataPrefix(metadataPrefix); + schemaLocations.put(oaiMetadataPrefixForList.getSchemaNamespace(), oaiMetadataPrefixForList.getSchemaUrl().toString()); break; case LIST_SETS: // Specification @@ -159,7 +173,7 @@ public class OAIProviderController implements ControllerWithHateoasHome { if (!StringTool.isNullOrEmpty(smartView)) { xslUrl = oaiUrl + SolidifyConstants.URL_SEP + SolidifyConstants.XSL + "?" + OAIConstants.OAI_VIEW + "=" + smartView; } - result = this.oaiService.printOAIPMH(oai, xslUrl); + result = this.oaiService.printOAIPMH(oai, xslUrl, schemaLocations); log.trace(result); } catch (final JAXBException e) { log.error("In converting OAI in xml", e); @@ -180,14 +194,14 @@ public class OAIProviderController implements ControllerWithHateoasHome { } @GetMapping - public HttpEntity<?> status() { + public HttpEntity<OAIPMH> status() { final OAIPMH oaiPmh = new OAIPMH(); final OAIPMHtype oai = new OAIPMHtype(); final WebMvcLinkBuilder linkBuilder = linkTo(methodOn(this.getClass()).process(null, null, null, null, null, null, null, null, null)); oai.setIdentify(this.oaiService.getIdentify(linkBuilder.toUri().toASCIIString())); oaiPmh.setOai(oai); oaiPmh.add(linkTo(this.getClass()).withSelfRel()); - oaiPmh.add(Tool.link(linkTo(methodOn(this.getClass()).xsl(null, null)).toUriComponentsBuilder()).withRel(SolidifyConstants.XSL)); + oaiPmh.add(Tool.link(linkTo(methodOn(this.getClass()).xsl(null)).toUriComponentsBuilder()).withRel(SolidifyConstants.XSL)); oaiPmh.add(OAITool.oaiLink(linkBuilder.toUriComponentsBuilder(), OAIConstants.OAI_IDENTIFY).withRel(OAIConstants.OAI_IDENTIFY)); oaiPmh.add(OAITool.oaiLink(linkBuilder.toUriComponentsBuilder(), OAIConstants.OAI_LIST_METADATA_FORMATS) .withRel(OAIConstants.OAI_LIST_METADATA_FORMATS)); @@ -201,19 +215,19 @@ public class OAIProviderController implements ControllerWithHateoasHome { } @GetMapping(SolidifyConstants.URL_SEP + OAIConstants.OAI_RESOURCE + SolidifyConstants.URL_SEP + SolidifyConstants.XSL) - public HttpEntity<String> xsl(HttpServletRequest request, @RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) { + public HttpEntity<String> xsl(@RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) { try { - String result = null; + String result; if (StringTool.isNullOrEmpty(smartView)) { - result = ""; - result += "<xmlTransformation>"; + StringBuilder xslt = new StringBuilder(); + xslt.append("<xmlTransformation>"); for (final Resource f : FileTool.scanClassPath("classpath:" + SolidifyConstants.XSL_HOME + "/*.xsl")) { - result += "<xslFile>" + f.getFilename() + "</xslFile>"; + xslt.append("<xslFile>").append(f.getFilename()).append("</xslFile>"); } - result += "</xmlTransformation>"; + xslt.append("</xmlTransformation>"); + result = xslt.toString(); } else { final ClassPathResource xsl = new ClassPathResource(SolidifyConstants.XSL_HOME + SolidifyConstants.URL_SEP + smartView); - result = FileTool.toString(xsl.getInputStream()); } final HttpHeaders headers = new HttpHeaders(); @@ -223,7 +237,22 @@ public class OAIProviderController implements ControllerWithHateoasHome { log.error("XML Transformation error", e); return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + } + @GetMapping(SolidifyConstants.URL_SEP + OAIConstants.OAI_RESOURCE + SolidifyConstants.URL_SEP + SolidifyConstants.SCHEMA) + public HttpEntity<String> xsd() { + try { + final ClassPathResource xsl = new ClassPathResource( + SolidifyConstants.SCHEMA_HOME + SolidifyConstants.URL_SEP + this.oaiService.getOaiRepositoryInfo().getRepositorySchema()); + String result = FileTool.toString(xsl.getInputStream()); + + final HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_XML_VALUE); + return new ResponseEntity<>(result, headers, HttpStatus.OK); + } catch (final Exception e) { + log.error("XML Schema error", e); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } } /** diff --git a/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java b/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java index 335c92e2caabd3681f375028fbf848eabdaa4e39..354fb8bdc6072846aa422c6e12c85026eaa89c10 100644 --- a/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java +++ b/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java @@ -30,6 +30,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; + import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; @@ -99,6 +100,7 @@ public class OAIService { private final ObjectFactory oaiDcFactory = new ObjectFactory(); // OAI Objects private final OAIRepositoryInfo oaiRepositoryInfo; + private final OAIMetadataPrefixService oaiMetadataPrefixService; private final OAISetService oaiSetService; // OAI Service @@ -138,6 +140,10 @@ public class OAIService { return oaiError; } + public OAIRepositoryInfo getOaiRepositoryInfo() { + return this.oaiRepositoryInfo; + } + public IdentifyType getIdentify(String oaiUrl) { final IdentifyType oaiIdentify = new IdentifyType(); oaiIdentify.setRepositoryName(this.oaiRepositoryInfo.getLongName()); @@ -170,6 +176,10 @@ public class OAIService { return oaiIdentify; } + public OAIMetadataPrefix getOAIMetadataPrefix(String metadataPrefix) { + return this.oaiMetadataPrefixService.findByPrefix(metadataPrefix); + } + public GetRecordType getRecord(String baseUrl, String identifier, String metadataPrefix) throws JAXBException { // Check Parameters this.checkParameters(identifier, metadataPrefix); @@ -268,10 +278,6 @@ public class OAIService { PageRequest.of(0, RestCollectionPage.MAX_SIZE_PAGE, Sort.by("prefix"))); } - private OAIMetadataPrefix getMetadataPrefix(String metadataPrefix) { - return this.oaiMetadataPrefixService.findByPrefix(metadataPrefix); - } - public ListRecordsType listRecords(String baseUrl, String metadataPrefix, String from, String until, String set, String token) throws JAXBException { // Check Parameters @@ -329,13 +335,28 @@ public class OAIService { return setTypes; } - public String printOAIPMH(OAIPMHtype oai, String rootUrl) throws JAXBException { + public String printOAIPMH(OAIPMHtype oai, String rootUrl, Map<String, String> schemaLocationList) throws JAXBException { final Marshaller marshaller = this.metadataService.getMarshaller(this.jaxbContext); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); if (!StringTool.isNullOrEmpty(rootUrl)) { marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml-stylesheet type='text/xsl' href='" + rootUrl + "'?>"); } - marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, OAIConstants.OAI_PMH_NAMESPACE + " " + OAIConstants.OAI_PMH_SCHEMA); + // Build schema location string + StringBuilder schemaLocations = new StringBuilder(); + schemaLocations + .append(OAIConstants.OAI_PMH_NAMESPACE) + .append(" ") + .append(OAIConstants.OAI_PMH_SCHEMA); + if (schemaLocationList != null && !schemaLocationList.isEmpty()) { + for (Map.Entry<String, String> schemaLocation : schemaLocationList.entrySet()) { + schemaLocations + .append(" ") + .append(schemaLocation.getKey()) + .append(" ") + .append(schemaLocation.getValue()); + } + } + marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocations.toString()); final JAXBElement<OAIPMHtype> root = this.getXML(oai); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); marshaller.marshal(root, bos); @@ -446,7 +467,7 @@ public class OAIService { @SuppressWarnings("squid:S128") private Object getMetadata(String baseUrl, String metadataPrefix, OAIRecord oaiRecord) throws JAXBException { final String archiveUrl = this.getArchiveUrl(); - final OAIMetadataPrefix oaiMetadataPrefix = this.getMetadataPrefix(metadataPrefix); + final OAIMetadataPrefix oaiMetadataPrefix = this.getOAIMetadataPrefix(metadataPrefix); if (oaiMetadataPrefix == null) { throw new OAIException(OAIPMHerrorcodeType.NO_METADATA_FORMATS, "Undefined metadata prefix " + metadataPrefix + " this record"); } diff --git a/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java b/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java index d4f96b8f5428b4e1a3ca9cc6ea0a44224671642e..aad50c1ca23747b4f638d1930f829e8b0bcd3572 100644 --- a/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java +++ b/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java @@ -148,7 +148,7 @@ public abstract class OAIServiceTest { void identityTest() throws JAXBException, IOException { final OAIPMHtype oai = new OAIPMHtype(); oai.setIdentify(this.oaiService.getIdentify(HOST_URL)); - String result = this.oaiService.printOAIPMH(oai, null); + String result = this.oaiService.printOAIPMH(oai, null, null); this.checkResult(result, "oaiIdentity.xml"); } @@ -156,7 +156,7 @@ public abstract class OAIServiceTest { void listMetadataFormatsTest() throws JAXBException, IOException { final OAIPMHtype oai = new OAIPMHtype(); oai.setListMetadataFormats(this.oaiService.listMetadataFormats(null)); - String result = this.oaiService.printOAIPMH(oai, null); + String result = this.oaiService.printOAIPMH(oai, null, null); this.checkResult(result, "oaiListMetadataFormats.xml"); } @@ -166,7 +166,7 @@ public abstract class OAIServiceTest { try { final OAIPMHtype oai = new OAIPMHtype(); oai.setListIdentifiers(this.oaiService.listIdentifiers(metadata, null, null, null, null)); - String result = this.oaiService.printOAIPMH(oai, null); + String result = this.oaiService.printOAIPMH(oai, null, null); this.checkResult(result, "oaiIdentity-" + metadata + ".xml"); } catch (final Exception e) { this.returnException(e); @@ -185,7 +185,7 @@ public abstract class OAIServiceTest { try { oai.setGetRecord(this.oaiService.getRecord(HOST_URL, "xxx", OAIConstants.OAI_DC)); } catch (OAIException e) { - String result = this.oaiService.printOAIPMH(oai, null); + String result = this.oaiService.printOAIPMH(oai, null, null); this.checkResult(result, "oaiGetRecordNotFound.xml"); } } @@ -197,7 +197,7 @@ public abstract class OAIServiceTest { try { final OAIPMHtype oai = new OAIPMHtype(); oai.setGetRecord(this.oaiService.getRecord(HOST_URL, id, metadataPrefix)); - String result = this.oaiService.printOAIPMH(oai, null); + String result = this.oaiService.printOAIPMH(oai, null, null); this.checkResult(result, "oaiGetRecord-" + metadataPrefix + "-" + id + ".xml"); } catch (final Exception e) { this.returnException(e); @@ -212,7 +212,7 @@ public abstract class OAIServiceTest { try { final OAIPMHtype oai = new OAIPMHtype(); oai.setListRecords(this.oaiService.listRecords(HOST_URL, metadataPrefix, null, null, null, null)); - String result = this.oaiService.printOAIPMH(oai, null); + String result = this.oaiService.printOAIPMH(oai, null, null); this.checkResult(result, "oaiListRecords-" + metadataPrefix + ".xml"); } catch (final Exception e) { this.returnException(e); @@ -224,7 +224,7 @@ public abstract class OAIServiceTest { void listSetsTest() throws JAXBException, IOException { final OAIPMHtype oai = new OAIPMHtype(); oai.setListSets(this.oaiService.listSets(null)); - String result = this.oaiService.printOAIPMH(oai, null); + String result = this.oaiService.printOAIPMH(oai, null, null); this.checkResult(result, "oaiListSets.xml"); } diff --git a/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java b/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java index 26b57739642d4fa7283d25175b601c8fa66e5b1c..cc09e7e33b5687342e8396f689f8b09a4a39767d 100644 --- a/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java +++ b/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java @@ -92,6 +92,7 @@ public class SolidifyConstants { // XML public static final String SCHEMA_HOME = "schemas"; + public static final String SCHEMA = "schema"; public static final String XSL_HOME = "xslt"; public static final String XSL = "xsl";