package no.met.metadataeditor.datastore; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathException; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import no.met.metadataeditor.EditorException; import no.met.metadataeditor.validationclient.SimplePutValidationClient; import no.met.metadataeditor.validationclient.ValidationClient; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Utility functions for DataStore classes. */ public class DataStoreUtils { /** * Find the XML format used by the a metadata file by looking at the first tag in the file. * @param metadataXML The raw XML for the metadata file. * @throws EditorException Thrown if the format is not known. * @return The format used by the XML file. */ public static SupportedFormat getFormat(List<SupportedFormat> formats, String metadataXML){ StringReader metadataReader = new StringReader(metadataXML); XMLStreamReader reader; SupportedFormat format = null; try { reader = XMLInputFactory.newInstance().createXMLStreamReader(metadataReader); while( reader.hasNext() ){ int code = reader.next(); if( code == XMLStreamConstants.START_ELEMENT ){ String rootNode = reader.getLocalName(); String namespace = reader.getNamespaceURI(); format = testFormats(formats, rootNode, namespace); // we are only interested in the first element. break; } } } catch (XMLStreamException | FactoryConfigurationError e) { throw new EditorException(e.getMessage(), e, EditorException.METADATA_PARSE_ERROR); } return format; } private static SupportedFormat testFormats(List<SupportedFormat> formats, String rootNode, String namespace) { SupportedFormat format = null; for (SupportedFormat f : formats) { if (f.matches(rootNode, namespace)) { format = f; break; } } if (format == null) { throw new EditorException("The metadata is not in one of the supported formats", EditorException.UNSUPPORTED_FORMAT); } return format; } static List<SupportedFormat> parseSupportedFormats(Document doc) { List<SupportedFormat> formats = new ArrayList<>(); try { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile("//supportedMetadataFormats/format"); NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < nodes.getLength(); i++) { Node formatNode = nodes.item(i); String tag = xpath.evaluate("@tag", formatNode); NodeList detectors = (NodeList) xpath.evaluate("detector", formatNode, XPathConstants.NODESET); if (detectors.getLength() != 1) { throw new EditorException(String.format("found %d detectors, need exactly 1 for format %s", detectors.getLength(), tag), EditorException.SETUP_XML_ERROR); } String detectorType = xpath.evaluate("@type", detectors.item(0)); if (!"rootNode".equals(detectorType)) { throw new EditorException(String.format( "found detector-type '%s' for format '%s', currently only 'rootNode' allowed in %s", detectorType, tag), EditorException.SETUP_XML_ERROR); } String rootNode = xpath.evaluate("arg[@name='rootNode']/@value", detectors.item(0)); String namespace = xpath.evaluate("arg[@name='namespace']/@value", detectors.item(0)); ValidationClient validationClient = parseValidationPart(formatNode, xpath); formats.add(new SupportedFormat(tag, rootNode, namespace, validationClient)); } } catch (XPathException e) { Logger.getLogger(DataStoreImpl.class.getName()).log(Level.SEVERE, null, e); } return formats; } private static ValidationClient parseValidationPart(Node formatNode, XPath xpath) throws XPathExpressionException{ Node validatorNode = (Node) xpath.evaluate("validator", formatNode, XPathConstants.NODE); if( validatorNode == null ){ return null; } String validatorType = xpath.evaluate("@type", validatorNode); if("simplePutService".equals(validatorType)){ String url = xpath.evaluate("arg[@name='URL']/@value", validatorNode); ValidationClient client = SimplePutValidationClient.getInstance(url); return client; } throw new EditorException("Invalid type for validation: " + validatorType, EditorException.SETUP_XML_ERROR ); } }