Thu, 11 Jul 2024 19:30:55 +0200
Added tag v3.1 for changeset 44c7423d6ce2
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2014 Mike Becker. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ package de.uapcore.sigred.doc.base; import de.uapcore.sigred.doc.Resources; import de.uapcore.sigrapi.impl.Digraph; import de.uapcore.sigrapi.impl.Graph; import de.uapcore.sigrapi.IGraph; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.apache.xerces.impl.Constants; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Namespace; import org.dom4j.QName; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public abstract class AbstractGraphDocument<T extends IGraph> extends FileBackedDocument { protected static final Namespace NAMESPACE = Namespace.get("sigred", "http://develop.uap-core.de/sigred/"); private static final QName TAG_GRAPHDOC = QName.get("graph-document", NAMESPACE); private static final QName TAG_GRAPH = QName.get("graph", NAMESPACE); private static final QName TAG_DIGRAPH = QName.get("digraph", NAMESPACE); private static final QName TAG_METADATA = QName.get("metadata", NAMESPACE); protected final T graph; private final GraphDocumentMetadata metadata; public AbstractGraphDocument(Class<T> graphType) { T g; try { g = graphType.newInstance(); } catch (ReflectiveOperationException e) { assert false; g = null; // for the compiler } graph = g; metadata = new GraphDocumentMetadata(); } public T getGraph() { return graph; } public GraphDocumentMetadata getMetadata() { return metadata; } protected abstract void writeGraph(Element rootNode) throws IOException; protected abstract void readGraph(Element rootNode) throws IOException; @Override public void writeTo(OutputStream out) throws IOException { Document doc = DocumentHelper.createDocument(); Element rootNode = doc.addElement(TAG_GRAPHDOC); Element metadataNode = rootNode.addElement(TAG_METADATA); metadata.write(metadataNode); if (graph instanceof Graph) { writeGraph(rootNode.addElement(TAG_GRAPH)); } else if (graph instanceof Digraph) { writeGraph(rootNode.addElement(TAG_DIGRAPH)); } else { throw new IOException("unsupported graph type"); } XMLWriter writer = new XMLWriter(out, OutputFormat.createPrettyPrint()); writer.write(doc); writer.flush(); } @Override public void readFrom(InputStream in) throws IOException { try { SAXReader reader = new SAXReader(true); reader.setStripWhitespaceText(true); reader.setFeature(Constants.XERCES_FEATURE_PREFIX+ Constants.SCHEMA_VALIDATION_FEATURE, true); reader.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION, String.format("%s %s", NAMESPACE.getURI(), Resources.class.getResource( "graph-document.xsd").toExternalForm())); final AtomicBoolean passed = new AtomicBoolean(true); final AtomicReference<SAXParseException> xmlerror = new AtomicReference<>(); // TODO: we should do more detailed error handling here reader.setErrorHandler(new ErrorHandler() { @Override public void warning(SAXParseException exception) throws SAXException { } @Override public void error(SAXParseException exception) throws SAXException { xmlerror.set(exception); passed.set(false); } @Override public void fatalError(SAXParseException exception) throws SAXException { xmlerror.set(exception); passed.set(false); } }); Document doc = reader.read(in); if (!passed.get()) { // TODO: provide details (maybe via separate error object?) throw xmlerror.get(); } doc.normalize(); Element root = doc.getRootElement(); metadata.read(root.element(TAG_METADATA)); if (graph instanceof Graph) { readGraph(root.element(TAG_GRAPH)); } else if (graph instanceof Digraph) { readGraph(root.element(TAG_DIGRAPH)); } else { throw new IOException("unsupported graph type"); } } catch (DocumentException | SAXException ex) { throw new IOException(ex); } } }