diff --git a/.classpath b/.classpath index ca5a20b..d07777b 100644 --- a/.classpath +++ b/.classpath @@ -1,11 +1,12 @@ - + + @@ -27,5 +28,5 @@ - + diff --git a/pom.xml b/pom.xml index e6c57af..5378994 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ org.gcube.data-catalogue gcubedatacatalogue-metadata-discovery jar - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT The gCube data catalogue metadata discovery library The gCube data catalogue metadata discovery library @@ -112,6 +112,14 @@ 4.8.1 test + + + + ch.qos.logback + logback-classic + 1.0.13 + test + diff --git a/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCalogueMetadataFormatReader.java b/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCalogueMetadataFormatReader.java index 379b26f..79fb112 100644 --- a/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCalogueMetadataFormatReader.java +++ b/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCalogueMetadataFormatReader.java @@ -1,9 +1,21 @@ package org.gcube.datacatalogue.metadatadiscovery; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; + +import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; @@ -15,8 +27,7 @@ import org.gcube.datacatalogue.metadatadiscovery.reader.MetadataFormatReader; import org.gcube.datacatalogue.metadatadiscovery.reader.NamespaceCategoryReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - - +import org.xml.sax.SAXException; /** * The Class DataCalogueMetadataReader. @@ -24,135 +35,167 @@ import org.slf4j.LoggerFactory; * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it * Jun 8, 2016 */ -public class DataCalogueMetadataFormatReader implements DataCatalogueMetadataDiscovery{ - +public class DataCalogueMetadataFormatReader implements DataCatalogueMetadataDiscovery { + + private static String SCHEMA_FILENAME = "Gdcmetadataprofilev3.xsd"; + private MetadataFormatDiscovery medataFormatDiscovery; private ScopeBean scope; - private Map hashMetadataFormats = null; + private Map hashMetadataFormats = null; private List namespaceCategories = null; + private String profileSchema = null; + private static Logger logger = LoggerFactory.getLogger(DataCalogueMetadataFormatReader.class); - + /** * Instantiates a new data calogue metadata format reader. * * @throws Exception the exception */ public DataCalogueMetadataFormatReader() throws Exception { - + String scopeString = ScopeProvider.instance.get(); - logger.debug("Read scope "+scopeString +" from ScopeProvider"); - - if(scopeString==null || scopeString.isEmpty()) + logger.debug("Read scope " + scopeString + " from ScopeProvider"); + + if(scopeString == null || scopeString.isEmpty()) throw new Exception("Please set a valid scope into ScopeProvider"); - - scope = new ScopeBean(scopeString); + + scope = new ScopeBean(scopeString); readNamespaces(); readMetadaFormats(); } - - + /** * Read metada formats. * * @throws Exception the exception */ - private void readMetadaFormats() throws Exception{ - + private void readMetadaFormats() throws Exception { + medataFormatDiscovery = new MetadataFormatDiscovery(scope); - logger.info("MedataFormatDiscovery has retrieved: "+medataFormatDiscovery.getMetadataProfiles().size() +" metadata type/s"); + logger.info("MedataFormatDiscovery has retrieved: " + medataFormatDiscovery.getMetadataProfiles().size() + + " metadata type/s"); logger.debug("filling cache for MedataFormat"); - hashMetadataFormats = new HashMap(medataFormatDiscovery.getMetadataProfiles().size()); - for (MetadataProfile mT : medataFormatDiscovery.getMetadataProfiles()) { - if(mT==null) + hashMetadataFormats = new HashMap(medataFormatDiscovery.getMetadataProfiles().size()); + for(MetadataProfile mT : medataFormatDiscovery.getMetadataProfiles()) { + if(mT == null) continue; - + MetadataFormatReader reader = new MetadataFormatReader(scope, mT.getId()); hashMetadataFormats.put(mT.getId(), reader.getMetadataFormat()); - logger.debug("MetadataType id: "+mT.getId() +" cached as: "+reader.getMetadataFormat()); + logger.debug("MetadataType id: " + mT.getId() + " cached as: " + reader.getMetadataFormat()); } } - - + /** * Read namespaces. */ private void readNamespaces() { - - try{ - if(namespaceCategories == null || namespaceCategories.isEmpty()){ - + + try { + if(namespaceCategories == null || namespaceCategories.isEmpty()) { + if(namespaceCategories == null) namespaceCategories = new ArrayList(); - + NamespaceCategoryReader rd = new NamespaceCategoryReader(scope); namespaceCategories.addAll(rd.getNamespaces().getNamespaceCategories()); } - }catch(Exception e){ + } catch(Exception e) { logger.debug("An error occurred during read namespaces for categories: ", e); } } - + /* (non-Javadoc) * @see org.gcube.datacatalogue.metadatadiscovery.DataCatalogueMetadataDiscovery#getMetadataFormatForMetadataType(org.gcube.datacatalogue.metadatadiscovery.bean.MetadataType) */ @Override public MetadataFormat getMetadataFormatForMetadataProfile(MetadataProfile profile) throws Exception { - - if(profile==null) - throw new Exception("Input "+ MetadataProfile.class.getSimpleName() + " is null"); - + + if(profile == null) + throw new Exception("Input " + MetadataProfile.class.getSimpleName() + " is null"); + MetadataFormat format = hashMetadataFormats.get(profile.getId()); - if(format!=null) + if(format != null) return format; - + MetadataFormatReader reader = new MetadataFormatReader(scope, profile.getId()); return reader.getMetadataFormat(); } - + /* (non-Javadoc) * @see org.gcube.datacatalogue.metadatadiscovery.DataCatalogueMetadataDiscovery#getListOfMetadataTypes() */ @Override public List getListOfMetadataProfiles() throws Exception { - - if(medataFormatDiscovery==null) + + if(medataFormatDiscovery == null) readMetadaFormats(); - + return medataFormatDiscovery.getMetadataProfiles(); } - + /* (non-Javadoc) * @see org.gcube.datacatalogue.metadatadiscovery.DataCatalogueMetadataDiscovery#getListOfNamespaceCategories() */ @Override public List getListOfNamespaceCategories() throws Exception { - + if(namespaceCategories == null) readNamespaces(); - + return namespaceCategories; } - - + /* (non-Javadoc) * @see org.gcube.datacatalogue.metadatadiscovery.DataCatalogueMetadataDiscovery#resetMetadataProfile() */ @Override public void resetMetadataProfile() { - + medataFormatDiscovery = null; hashMetadataFormats = null; } - - + /* (non-Javadoc) * @see org.gcube.datacatalogue.metadatadiscovery.DataCatalogueMetadataDiscovery#resetNamespaceCategories() */ @Override public void resetNamespaceCategories() { - + namespaceCategories = null; } - + + @Override + public String getProfileSchema() { + if(profileSchema == null) { + InputStream inputStream = getProfileSchemaInputStream(); + profileSchema = new BufferedReader(new InputStreamReader(inputStream)).lines() + .collect(Collectors.joining("\n")); + } + return profileSchema; + + } + + static InputStream getProfileSchemaInputStream() { + return DataCalogueMetadataFormatReader.class.getClassLoader().getResourceAsStream(SCHEMA_FILENAME); + } + + static void validateAgainstXSD(StreamSource xml, StreamSource xsd) throws SAXException, IOException { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = factory.newSchema(xsd); + Validator validator = schema.newValidator(); + validator.validate(xml); + } + + @Override + public void validateProfile(String xmlProfile) throws Exception { + validateAgainstXSD(new StreamSource(xmlProfile), new StreamSource(getProfileSchema())); + } + + public static void validateProfile(InputStream xml) throws Exception { + validateAgainstXSD(new StreamSource(xml), new StreamSource(getProfileSchemaInputStream())); + } + } diff --git a/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCatalogueMetadataDiscovery.java b/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCatalogueMetadataDiscovery.java index 865c198..d5d2858 100644 --- a/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCatalogueMetadataDiscovery.java +++ b/src/main/java/org/gcube/datacatalogue/metadatadiscovery/DataCatalogueMetadataDiscovery.java @@ -3,11 +3,13 @@ */ package org.gcube.datacatalogue.metadatadiscovery; +import java.io.IOException; import java.util.List; import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataFormat; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory; +import org.xml.sax.SAXException; @@ -20,7 +22,6 @@ import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory; */ public interface DataCatalogueMetadataDiscovery { - /** * Gets the list of metadata types. * @@ -62,4 +63,19 @@ public interface DataCatalogueMetadataDiscovery { */ void resetNamespaceCategories(); + /** + * Return the XSD of the profile schema + * @return the String representation of the XSD containing the schema for a profile + */ + String getProfileSchema(); + + /** + * Validate the xml provided as argument + * @param xmlProfile the string representation of the XML to validate again the schema + * @throws IOException + * @throws SAXException + */ + void validateProfile(String xmlProfile) throws Exception; + + } diff --git a/Gdcmetadataprofilev3.xsd b/src/main/resources/Gdcmetadataprofilev3.xsd similarity index 100% rename from Gdcmetadataprofilev3.xsd rename to src/main/resources/Gdcmetadataprofilev3.xsd diff --git a/NamespacesCatalogueCategories.xsd b/src/main/resources/NamespacesCatalogueCategories.xsd similarity index 100% rename from NamespacesCatalogueCategories.xsd rename to src/main/resources/NamespacesCatalogueCategories.xsd diff --git a/src/test/java/org/gcube/datacatalogue/metadatadiscovery/TestDataCatalogueMetadataFormatReader.java b/src/test/java/org/gcube/datacatalogue/metadatadiscovery/TestDataCatalogueMetadataFormatReader.java index 83144c1..215aa75 100644 --- a/src/test/java/org/gcube/datacatalogue/metadatadiscovery/TestDataCatalogueMetadataFormatReader.java +++ b/src/test/java/org/gcube/datacatalogue/metadatadiscovery/TestDataCatalogueMetadataFormatReader.java @@ -3,7 +3,11 @@ */ package org.gcube.datacatalogue.metadatadiscovery; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.List; +import java.util.stream.Collectors; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile; @@ -55,4 +59,15 @@ public class TestDataCatalogueMetadataFormatReader { e.printStackTrace(); } } + + + public static String PROFILE_EXAMPLE_FILENAME = "profileExample.xml"; + + @Test + public void validateAgainstProfileSchema() throws Exception { + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(PROFILE_EXAMPLE_FILENAME); + DataCalogueMetadataFormatReader.validateProfile(inputStream); + } } + + diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..1e138b1 --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,19 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}: %msg%n + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/profileExample.xml b/src/test/resources/profileExample.xml new file mode 100644 index 0000000..8ef52fb --- /dev/null +++ b/src/test/resources/profileExample.xml @@ -0,0 +1,80 @@ + + + spatial + false + GeoJSON + 1 + + Insert a geoJSON characterising the spatial coverage of the + dataset. + + + + + + + + timeField + false + Time + 1 + + Insert a time value characterising the temporal coverage of the + dataset. + + + + + + + + timeIntervalField + false + Time_Interval + 1 + + Insert a time interval value characterising the temporal + coverage of the dataset. + + + + + + + + timeListField + false + Times_ListOf + 1 + + Insert a time list characterising the temporal coverage of the + dataset. + + + + + + + + GACSTerms + true + String + * + + Select one or more terms + + GACS.Term1 + GACS.Term2 + GACS.Term3 + GACS.Term4 + GACS.Term5 + GACS.Term6 + GACS.Term7 + GACS.Term8 + GACS.Term9 + + + onValue + + + \ No newline at end of file