/* * #%L * ===================================================== * _____ _ ____ _ _ _ _ * |_ _|_ __ _ _ ___| |_ / __ \| | | | ___ | | | | * | | | '__| | | / __| __|/ / _` | |_| |/ __|| |_| | * | | | | | |_| \__ \ |_| | (_| | _ |\__ \| _ | * |_| |_| \__,_|___/\__|\ \__,_|_| |_||___/|_| |_| * \____/ * * ===================================================== * * Hochschule Hannover * (University of Applied Sciences and Arts, Hannover) * Faculty IV, Dept. of Computer Science * Ricklinger Stadtweg 118, 30459 Hannover, Germany * * Email: trust@f4-i.fh-hannover.de * Website: http://trust.f4.hs-hannover.de/ * * This file is part of visitmeta-visualization, version 0.6.0, * implemented by the Trust@HsH research group at the Hochschule Hannover. * %% * Copyright (C) 2012 - 2016 Trust@HsH * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ package de.hshannover.f4.trust.visitmeta.util; import java.io.StringReader; import java.io.StringWriter; import java.util.Arrays; import java.util.Iterator; import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.xml.sax.InputSource; import de.hshannover.f4.trust.visitmeta.IfmapStrings; import de.hshannover.f4.trust.visitmeta.interfaces.Identifier; /** * Factory for {@link IdentifierWrapper} instances. * * @author Bastian Hellmann * */ public class IdentifierHelper { private static Logger LOGGER = Logger.getLogger(IdentifierHelper.class); private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance(); private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); /** * Default namespace context which uses the prefixes 'meta' and 'ifmap' * as specified in TNC IF-MAP Binding for SOAP version 2.2. * TODO extended identifier namespaces? */ public static final NamespaceContext DEFAULT_NAMESPACE_CONTEXT = new NamespaceContext() { @Override public Iterator<String> getPrefixes(String namespaceURI) { return Arrays.asList( IfmapStrings.STD_METADATA_PREFIX, IfmapStrings.BASE_PREFIX) .iterator(); } @Override public String getPrefix(String namespaceURI) { if (namespaceURI.equals(IfmapStrings.STD_METADATA_NS_URI)) { return IfmapStrings.STD_METADATA_PREFIX; } else if (namespaceURI.equals(IfmapStrings.BASE_NS_URI)) { return IfmapStrings.BASE_PREFIX; } else { return null; } } @Override public String getNamespaceURI(String prefix) { if (prefix.equals(IfmapStrings.STD_METADATA_PREFIX)) { return IfmapStrings.STD_METADATA_NS_URI; } else if (prefix.equals(IfmapStrings.BASE_PREFIX)) { return IfmapStrings.BASE_NS_URI; } else { return XMLConstants.NULL_NS_URI; } } }; /** * Create a {@link IdentifierWrapper} instance for the given document. * * @param document a identifier document * @return the wrapped Identifier */ public static IdentifierWrapper identifier(Identifier identifier) { try { Transformer printFormatTransformer = TRANSFORMER_FACTORY.newTransformer(); printFormatTransformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); printFormatTransformer.setOutputProperty(OutputKeys.METHOD, "xml"); printFormatTransformer.setOutputProperty(OutputKeys.INDENT, "yes"); printFormatTransformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); printFormatTransformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); Transformer equalsTransformer = TRANSFORMER_FACTORY.newTransformer(); equalsTransformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); equalsTransformer.setOutputProperty(OutputKeys.INDENT, "no"); equalsTransformer.setOutputProperty(OutputKeys.METHOD, "xml"); XPath xPath = XPATH_FACTORY.newXPath(); Document document; DocumentBuilder builder; try { builder = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder(); document = builder.parse( new InputSource(new StringReader(identifier.getRawData()))); return new IdentifierWrapperImpl( identifier.getTypeName(), document, xPath, printFormatTransformer, DEFAULT_NAMESPACE_CONTEXT); } catch (Exception e) { e.printStackTrace(); return null; } } catch (TransformerConfigurationException e) { throw new RuntimeException(e); } } /** * Wrapper implementation which uses {@link XPath} to extract values * from {@link Document} instances representing Identifier. */ private static class IdentifierWrapperImpl implements IdentifierWrapper { final String mTypeName; final Document mDocument; final XPath mXpath; final Transformer mPrintTransformer; /** * Create a wrapper instance for the given document. * * @param document the document to wrap * @param xpath the XPATH instance for this wrapper * @param printFormatTransformer the transformer to use for pretty printing * @param namespaceContext the namespace context for XPath operations * @param equalsTransformer the transformer to use for canonical serialization */ public IdentifierWrapperImpl( String typeName, Document document, XPath xpath, Transformer printFormatTransformer, NamespaceContext namespaceContext) { mTypeName = typeName; mDocument = document; mXpath = xpath; mPrintTransformer = printFormatTransformer; mXpath.setNamespaceContext(namespaceContext); } /** * Evaluate the given XPATH expression on the given document. Return * the result as a string or null if an error occurred. */ private String getValueFromExpression(String expression, Document doc) { try { return mXpath.evaluate(expression, mDocument.getDocumentElement()); } catch (XPathExpressionException e) { LOGGER.error("could not evaluate '" + expression + "' on '" + mDocument + "'"); return null; } } @Override public String getValueForXpathExpression(String xPathExpression) { return getValueFromExpression(xPathExpression, mDocument); } @Override public String getValueForXpathExpressionOrElse(String xPathExpression, String defaultValue) { String result = getValueForXpathExpression(xPathExpression); if (result == null) { return defaultValue; } else { return result; } } @Override public String toFormattedString() { StringWriter writer = new StringWriter(); try { mPrintTransformer.transform( new DOMSource(mDocument), new StreamResult(writer)); } catch (TransformerException e) { throw new RuntimeException(e); } return writer.toString(); } @Override public void setNamespaceContext(NamespaceContext context) { mXpath.setNamespaceContext(context); } @Override public String getTypeName() { return mTypeName; } } }