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

net.sf.xolite.dom.DomXMLSerializer Maven / Gradle / Ivy

Go to download

This project provides a lightweight framework to serialize/deserialize (or marshall/unmarshall) java objects into XML. The implementation is based on standard SAX (Simple Api for Xml) but it follows a original approach based on the strong data encapsulation paradigm of Object Oriented (OO) programming.

The newest version!
/*-------------------------------------------------------------------------
 Copyright 2006 Olivier Berlanger

 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.sf.xolite.dom;


import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import net.sf.xolite.XMLSerializable;
import net.sf.xolite.XMLSerializeException;
import net.sf.xolite.XMLSerializer;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;


/**
 * Serializer transforming a java object to a DOM tree.
 */
public class DomXMLSerializer implements XMLSerializer {


    private static final String NAMESPACE_DEFINITION_URI = "http://www.w3.org/2000/xmlns/";

    private DocumentBuilder builder;
    private Document currentDocument;
    private Node currentNode;
    private Map prefixMappings;
    private Map customObjects;


    public DomXMLSerializer() {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException pce) {
            throw new IllegalStateException("Cannot create DocumentBuilder: " + pce);
        }
        prefixMappings = new HashMap();
    }


    public DomXMLSerializer(DocumentBuilder docBuilder) {
        if (docBuilder == null) throw new IllegalArgumentException("docBuilder cannot be null");
        builder = docBuilder;
        prefixMappings = new HashMap();
    }


    public void clearPrefixMapping() {
        prefixMappings.clear();
    }


    public Document serializeToDOM(XMLSerializable src) throws XMLSerializeException {
        startDocument();
        src.serialize(this);
        endDocument();
        return currentDocument;
    }


    public void startDocument() throws XMLSerializeException {
        Document doc = builder.newDocument();
        currentDocument = doc;
        currentNode = doc;
    }


    public void endDocument() throws XMLSerializeException {
        if (currentNode != currentDocument)
            throw new XMLSerializeException(
                    "Not all the document nodes are ended (with endElement(..) notification) remaining = " + currentNode);
        currentNode = null;
    }


    public Document getDocument() {
        return currentDocument;
    }


    private String getPrefix(String uri, String localName) throws XMLSerializeException {
        String prefix;
        if (uri == null) {
            prefix = null;
        } else {
            prefix = prefixMappings.get(uri);
            if (prefix == null)
                throw new XMLSerializeException("No prefix defined for URI '" + uri + "' of element <" + localName + ">");
        }
        return prefix;
    }


    private void ensurePrefixMappingDefined(String prefix, String uri, Element baseElement) {
        if ((prefix != null) && (uri != null)) {
            Element elem = baseElement;
            String attrName = (prefix.equals("")) ? "xmlns" : "xmlns:" + prefix;
            String attrVal;
            Node parent;
            boolean prefixNotDefined = true;
            while (prefixNotDefined) {
                if ((elem != baseElement) && prefix.equals(elem.getPrefix()) && uri.equals(elem.getNamespaceURI())) {
                    prefixNotDefined = false;
                    break;
                } else {
                    // seach namespace definitions
                    attrVal = elem.getAttribute(attrName);
                    if ((attrVal != null) && (attrVal.equals(uri))) {
                        prefixNotDefined = false;
                        break;
                    }
                }
                parent = elem.getParentNode();
                if ((parent != null) && (parent.getNodeType() == Node.ELEMENT_NODE)) elem = (Element) parent;
                else break;
            }
            if (prefixNotDefined) {
                baseElement.setAttributeNS(NAMESPACE_DEFINITION_URI, attrName, uri);
            }
        }
    }


    // ------------------------ XMLSerializer interface implementation -------------------------


    public void startPrefixMapping(String prefix, String namespaceUri) throws XMLSerializeException {
        if (!prefixMappings.containsKey(namespaceUri)) prefixMappings.put(namespaceUri, prefix);
    }


    public void startElement(String uri, String localName) throws XMLSerializeException {
        if ((currentDocument == null) || (currentNode == null)) throw new XMLSerializeException("Document not started");
        String prefix = getPrefix(uri, localName);
        String qName = ((prefix == null) || (prefix.equals(""))) ? localName : prefix + ":" + localName;
        Element el = currentDocument.createElementNS(uri, qName);
        currentNode.appendChild(el);
        ensurePrefixMappingDefined(prefix, uri, el);
        currentNode = el;
    }


    public void attribute(String name, String value) throws XMLSerializeException {
        attribute(null, name, value);
    }


    public void attribute(String uri, String localName, String value) throws XMLSerializeException {
        if ((currentDocument == null) || (currentNode == null)) throw new XMLSerializeException("Document not started");
        if (!(currentNode instanceof Element))
            throw new XMLSerializeException("You can only add attributes inside an Element");
        Element current = (Element) currentNode;
        String prefix = getPrefix(uri, localName);
        String qName = ((prefix == null) || (prefix.equals(""))) ? localName : prefix + ":" + localName;
        current.setAttributeNS(uri, qName, value);
        ensurePrefixMappingDefined(prefix, uri, current);
    }


    public void characters(String text) throws XMLSerializeException {
        if ((currentDocument == null) || (currentNode == null)) throw new XMLSerializeException("Document not started");
        if (!(currentNode instanceof Element)) throw new XMLSerializeException("You can only add text inside an Element");
        Text txt = currentDocument.createTextNode(text);
        currentNode.appendChild(txt);
    }


    public void charactersMultiLine(String text) throws XMLSerializeException {
        // Not implemented here, as formatting is difficult to do inside dom.
        characters(text);
    }


    public void endElement(String uri, String localName) throws XMLSerializeException {
        if ((currentDocument == null) || (currentNode == null)) throw new XMLSerializeException("Document not started");
        if ((uri != null) && !uri.equals(currentNode.getNamespaceURI()))
            throw new XMLSerializeException("Current node namespace URI is not <" + uri + "> but <"
                    + currentNode.getNamespaceURI() + ">");
        if (!localName.equals(currentNode.getLocalName()))
            throw new XMLSerializeException("Current node is not <" + localName + "> but <" + currentNode.getNodeName() + ">");
        Node parent = currentNode.getParentNode();
        if (parent == null) throw new XMLSerializeException("Error while colsing node");
        currentNode = parent;
    }


    public void simpleElement(String namespaceUri, String localName, String text) throws XMLSerializeException {
        startElement(namespaceUri, localName);
        characters(text);
        endElement(namespaceUri, localName);
    }


    public Object getCustomObject(Object key) {
        return (customObjects == null) ? null : customObjects.get(key);
    }


    public void putCustomObject(Object key, Object value) {
        if (customObjects == null) customObjects = new HashMap();
        customObjects.put(key, value);
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy