All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.oneandone.sushi.xml.Builder Maven / Gradle / Ivy

/*
 * Copyright 1&1 Internet AG, https://github.com/1and1/
 *
 * 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.
 */
package net.oneandone.sushi.xml;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;

/** Wraps xml parser to implement the method signatures we need */

public class Builder {
    private final DocumentBuilder builder;

    /** Create a non-validating builder */
    public Builder() {
        this.builder = createDocumentBuilder();
    }

    /** Create a validating builder */
    public Builder(net.oneandone.sushi.fs.Node schema) throws IOException, SAXException {
        this.builder = createValidatingDocumentBuilder(schema);
    }

    /** This method is not called "parse" to avoid confusion with file parsing methods */
    public Document parseString(String text) throws SAXException {
        try {
            return parse(new InputSource(new StringReader(text)));
        } catch (IOException e) {
            throw new RuntimeException("unexpected world exception while reading memory stream", e);
        }
    }

    /** asserts a valid document */
    public Document literal(String text) {
        try {
            return parseString(text);        
        } catch (SAXException e) {
            throw new RuntimeException(text, e);
        }
    }

    public Document parse(net.oneandone.sushi.fs.Node node) throws SAXException, IOException {
        InputSource src;

        try (InputStream stream = node.newInputStream()) {
            src = new InputSource();
            src.setSystemId(node.toString());
            src.setByteStream(stream);
            return parse(src);
        }
    }
    
    public Document parse(Reader reader) throws SAXException, IOException {
        return parse(new InputSource(reader));
    }

    public Document parse(InputStream stream) throws SAXException, IOException {
        return parse(new InputSource(stream));
    }

    public Document parse(InputSource src) throws SAXException, IOException {
        return builder.parse(src);
    }

    //--
    
    public Document createDocument() {
        return builder.newDocument();
    }

    public Document createDocument(String name) {
    	return createDocument(name, null);
    }

    public Document createDocument(String name, Namespace namespace) {
        Document doc;
        
        doc = createDocument();
        doc.appendChild(standaloneElement(doc, name, namespace));
        return doc;
    }
    
    //-- create methods 
    
    public static void add(Element parent, NodeList list) {
        int size;
        int i;

        size = list.getLength();
        for (i = 0; i < size; i++) {
            addNode(parent, list.item(i));
        }
        
    }
    
    public static Element add(Element parent, Element child) {
        return (Element) addNode(parent, child);
    }

    public static Node addNode(Element parent, Node child) {
        Document doc;
        
        doc = parent.getOwnerDocument();
        child = doc.importNode(child, true);
        parent.appendChild(child);
        return child;
    }
    
    /** @return newly created element */
    public static Element element(Element parent, String name) {
    	return element(parent, name, null);
    }

    /** @return newly created element */
    public static Element element(Element parent, String name, Namespace namespace) {
        Element result;
        
        result = standaloneElement(parent.getOwnerDocument(), name, namespace);
        parent.appendChild(result);
        return result;
    }

	public static Element standaloneElement(Document doc, String name, Namespace namespace) {
		if (namespace != null) {
            String prefixname = 
            	Namespace.EMPTY_NAMESPACE.equals(namespace) || Namespace.EMPTY_NAMESPACE.getPrefix().equals(namespace.getPrefix()) ?
                 name : namespace.getPrefix() + ":" + name;
            return doc.createElementNS(namespace.getUri(), prefixname);
        } else {
            return doc.createElement(name);
        }
	}
    
    public static Text text(Element parent, String content) {
        Document doc;
        Text result;
        
        doc = parent.getOwnerDocument();
        result = doc.createTextNode(content);
        parent.appendChild(result);
        return result;
    }

    public static Text textElement(Element parent, String name, String content) {
        return textElement(parent, name, null, content);
    }

    public static Text textElement(Element parent, String name, Namespace namespace, String content) {
        return text(element(parent, name, namespace), content);
    }

    public static void clear(Element root) {
        Node child;
        
        while (true) {
            child = root.getFirstChild();
            if (child == null) {
                break;
            }
            root.removeChild(child);
        }
    }
    
    //-- document builder
    
    public static synchronized DocumentBuilder createDocumentBuilder() {
        DocumentBuilder result;
        try {
            result = FACTORY_NON_VALIDATING.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("createDocumentBuilder failed", e);
        }
        result.setErrorHandler(ERROR_HANDLER);
        return result;
    }

    public static DocumentBuilder createValidatingDocumentBuilder(net.oneandone.sushi.fs.Node schema) throws IOException, SAXException {
        DocumentBuilderFactory factory;
        DocumentBuilder builder;

        factory = Factories.document(schema);
        try {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
        builder.setErrorHandler(ERROR_HANDLER);
        return builder;
    }

    public static SAXParser createValidatingSAXParser(net.oneandone.sushi.fs.Node schema) throws IOException {
        return Factories.saxParser(schema);
    }

    public static SAXParser createSAXParser() {
        return Factories.saxParser();
    }

    // TODO: avoid problems with old xerces versions in classpath
    private static final DocumentBuilderFactory FACTORY_NON_VALIDATING;
    private static final ErrorHandler ERROR_HANDLER;
    
    static {
        FACTORY_NON_VALIDATING = Factories.document();
        if (!FACTORY_NON_VALIDATING.isNamespaceAware()) {
            FACTORY_NON_VALIDATING.setNamespaceAware(true);
        }
        if (FACTORY_NON_VALIDATING.isValidating()) {
            FACTORY_NON_VALIDATING.setValidating(false);
        }
        
        ERROR_HANDLER = new ErrorHandler() {
            public void error(SAXParseException exception) throws SAXException {
                report(exception);
            }
            public void fatalError(SAXParseException exception) throws SAXException {
                report(exception);
            }
            public void warning(SAXParseException exception) throws SAXException {
                report(exception);
            }
            private void report(SAXParseException exception) throws SAXException {
                throw exception;
            }
        };
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy