package org.gcube.common.metadataprofilediscovery; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.net.URL; 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.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; 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.metadataprofilediscovery.bean.MetadataProfile; import org.gcube.common.metadataprofilediscovery.jaxb.MetadataFormat; import org.gcube.common.metadataprofilediscovery.jaxb.NamespaceCategory; import org.gcube.common.metadataprofilediscovery.reader.MetadataFormatDiscovery; import org.gcube.common.metadataprofilediscovery.reader.MetadataFormatReader; import org.gcube.common.metadataprofilediscovery.reader.NamespaceCategoryReader; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * The Class DataCalogueMetadataReader. * * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jun 8, 2016 */ public class DataCalogueMetadataFormatReader implements DataCatalogueMetadataDiscovery { private static String SCHEMA_FILENAME = "Gdcmetadataprofilev3.xsd"; private MetadataFormatDiscovery medataFormatDiscovery; private ScopeBean scope; 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()) throw new Exception("Please set a valid scope into ScopeProvider"); scope = new ScopeBean(scopeString); readNamespaces(); readMetadaFormats(); } /** * Read metada formats. * * @throws Exception the exception */ private void readMetadaFormats() throws Exception { medataFormatDiscovery = new MetadataFormatDiscovery(scope); 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) continue; MetadataFormatReader reader = new MetadataFormatReader(scope, mT.getId()); hashMetadataFormats.put(mT.getId(), reader.getMetadataFormat()); logger.debug("MetadataType id: " + mT.getId() + " cached as: " + reader.getMetadataFormat()); } } /** * Read namespaces. */ private void readNamespaces() { 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) { logger.debug("An error occurred during read namespaces for categories: ", e); } } /** * Gets the profile schema string. * * @return the profile schema string */ public static String getProfileSchemaString() { InputStream inputStream = DataCalogueMetadataFormatReader.getProfileSchemaInputStream(); return new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n")); } /** * Gets the profile schema input stream. * * @return the profile schema input stream */ public static InputStream getProfileSchemaInputStream() { return DataCalogueMetadataFormatReader.class.getResourceAsStream(SCHEMA_FILENAME); } /** * Gets the profile schema URL. * * @return the profile schema URL */ public static URL getProfileSchemaURL() { return DataCalogueMetadataFormatReader.class.getResource(SCHEMA_FILENAME); } /** * Validate against XSD. * * @param xml the xml * @param xsd the xsd * @throws SAXException the SAX exception * @throws IOException Signals that an I/O exception has occurred. */ static void validateAgainstXSD(Source xml, URL 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); } /** * Validate profile. * * @param xml the xml * @throws Exception the exception */ public static void validateProfile(InputStream xml) throws Exception { validateAgainstXSD(new StreamSource(xml), getProfileSchemaURL()); } /* * (non-Javadoc) * * @see * org.gcube.common.metadataprofilediscovery.DataCatalogueMetadataDiscovery# * getMetadataFormatForMetadataProfile(org.gcube.common.metadataprofilediscovery * .bean.MetadataProfile) */ public MetadataFormat getMetadataFormatForMetadataProfile(MetadataProfile profile) throws Exception { if (profile == null) throw new Exception("Input " + MetadataProfile.class.getSimpleName() + " is null"); MetadataFormat format = hashMetadataFormats.get(profile.getId()); if (format != null) return format; MetadataFormatReader reader = new MetadataFormatReader(scope, profile.getId()); return reader.getMetadataFormat(); } /* * (non-Javadoc) * * @see * org.gcube.common.metadataprofilediscovery.DataCatalogueMetadataDiscovery# * getListOfMetadataProfiles() */ public List getListOfMetadataProfiles() throws Exception { if (medataFormatDiscovery == null) readMetadaFormats(); return medataFormatDiscovery.getMetadataProfiles(); } /* * (non-Javadoc) * * @see * org.gcube.common.metadataprofilediscovery.DataCatalogueMetadataDiscovery# * getListOfNamespaceCategories() */ public List getListOfNamespaceCategories() throws Exception { if (namespaceCategories == null) readNamespaces(); return namespaceCategories; } /* * (non-Javadoc) * * @see * org.gcube.common.metadataprofilediscovery.DataCatalogueMetadataDiscovery# * resetMetadataProfile() */ public void resetMetadataProfile() { medataFormatDiscovery = null; hashMetadataFormats = null; } /* * (non-Javadoc) * * @see * org.gcube.common.metadataprofilediscovery.DataCatalogueMetadataDiscovery# * resetNamespaceCategories() */ public void resetNamespaceCategories() { namespaceCategories = null; } /* * (non-Javadoc) * * @see * org.gcube.common.metadataprofilediscovery.DataCatalogueMetadataDiscovery# * getProfileSchema() */ public String getProfileSchema() { if (profileSchema == null) { profileSchema = DataCalogueMetadataFormatReader.getProfileSchemaString(); } return profileSchema; } /* * (non-Javadoc) * * @see * org.gcube.common.metadataprofilediscovery.DataCatalogueMetadataDiscovery# * validateProfile(java.lang.String) */ public void validateProfile(String xmlProfile) throws ParserConfigurationException, SAXException, IOException { DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = db.parse(new InputSource(new StringReader(xmlProfile))); DOMSource source = new DOMSource(doc); validateAgainstXSD(source, getProfileSchemaURL()); } }