/**
 * Node.java This file was generated by XMLSpy 2006sp2 Enterprise Edition. YOU
 * SHOULD NOT MODIFY THIS FILE, BECAUSE IT WILL BE OVERWRITTEN WHEN YOU RE-RUN
 * CODE GENERATION. Refer to the XMLSpy Documentation for further details.
 * http://www.altova.com/xmlspy
 */

package com.jmex.model.collada.xml;

public abstract class Node implements java.io.Serializable {

    private static final long serialVersionUID = 1L;
    final protected static short Attribute = 0;
    final protected static short Element = 1;
    final protected static short Text = 2;
    final protected static short CData = 3;
    final protected static short Comment = 4;
    final protected static short ProcessingInstruction = 5;

    protected org.w3c.dom.Node domNode = null;

    public Node(Node node) {
        domNode = node.domNode;
    }

    public Node(org.w3c.dom.Node domNode) {
        this.domNode = domNode;
    }

    public Node(org.w3c.dom.Document domDocument) {
        this.domNode = domDocument.getDocumentElement();
    }

    public Node(Document doc, String namespaceURI, String prefix, String name) {
        this.domNode = doc.createRootElement(namespaceURI, name);
        mapPrefix(prefix, namespaceURI);
        doc.declareNamespaces(this);
    }

    public org.w3c.dom.Node getDomNode() {
        return domNode;
    }

    protected static String getDomNodeValue(org.w3c.dom.Node node) {
        if (node == null)
            return null;
        String value = node.getNodeValue();
        if (value != null)
            return value;
        return getInnerText(node);
    }

    protected static String getInnerText(org.w3c.dom.Node node) {
        StringBuffer text = new StringBuffer();
        org.w3c.dom.NodeList elements = node.getChildNodes();
        int length = elements.getLength();

        for (int i = 0; i < length; i++) {
            org.w3c.dom.Node child = elements.item(i);
            if (child.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
                text.append(child.getNodeValue());
            else if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)
                text.append(getInnerText(child));
            else if (child.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE)
                text.append(child.getNodeValue());
        }
        return text.toString();
    }

    public static String getNodeTextValue(org.w3c.dom.Node node) {
        return getDomNodeValue(node);
    }

    protected static void setDomNodeValue(org.w3c.dom.Node node, String value) {
        if (node == null)
            return;
        if (node.getNodeValue() != null) {
            node.setNodeValue(value);
            return;
        }
        org.w3c.dom.Node child = node.getFirstChild();
        if (child == null || child.getNodeType() != org.w3c.dom.Node.TEXT_NODE) {
            node.appendChild(node.getOwnerDocument().createTextNode(value));
            return;
        }
    }

    public void mapPrefix(String prefix, String URI) {
        if (URI == null || URI.equals(""))
            return;

        org.w3c.dom.Element element = (org.w3c.dom.Element) domNode;
        if (prefix == null || prefix.equals(""))
            element.setAttribute("xmlns", URI);
        else
            element.setAttribute("xmlns:" + prefix, URI);
    }

    public void assign(com.jmex.model.collada.xml.Node other) {
        setDomNodeValue(domNode, getDomNodeValue(other.domNode).toString());
    }

    protected void declareNamespace(String prefix, String URI) {
        if (URI == null || URI.equals(""))
            return;
        org.w3c.dom.Element root = domNode.getOwnerDocument()
                .getDocumentElement();

        org.w3c.dom.NamedNodeMap attrs = root.getAttributes();
        if (attrs != null) {
            for (int i = 0; i < attrs.getLength(); i++) {
                org.w3c.dom.Attr attr = (org.w3c.dom.Attr) attrs.item(i);
                if (attr.getValue().equals(URI)
                        && attr.getName().startsWith("xmlns")) // namespace URI
                                                                // already
                                                                // mapped?
                    return; // do not overwrite
            }
        }

        if (prefix == null || prefix.equals(""))
            root.setAttribute("xmlns", URI);
        else
            root.setAttribute("xmlns:" + prefix, URI);
    }

    protected org.w3c.dom.Node appendDomChild(int type, String namespaceURI,
            String name, String value) {
        switch (type) {
            case Attribute:
                org.w3c.dom.Attr attribute = domNode.getOwnerDocument()
                        .createAttributeNS(namespaceURI, name);
                attribute.setNodeValue(value);
                domNode.getAttributes().setNamedItemNS(attribute);
                return attribute;

            case Element:
                org.w3c.dom.Element element = domNode.getOwnerDocument()
                        .createElementNS(namespaceURI, name);
                if (value != null && value.length() != 0)
                    element.appendChild(domNode.getOwnerDocument()
                            .createTextNode(value));
                domNode.appendChild(element);
                return element;

            case Text:
                org.w3c.dom.Text text = domNode.getOwnerDocument()
                        .createTextNode(value);
                domNode.appendChild(text);
                return text;

            case CData:
                org.w3c.dom.CDATASection cdata = domNode.getOwnerDocument()
                        .createCDATASection(value);
                domNode.appendChild(cdata);
                return cdata;

            case Comment:
                org.w3c.dom.Comment comment = domNode.getOwnerDocument()
                        .createComment(value);
                domNode.appendChild(comment);
                return comment;

            case ProcessingInstruction:
                org.w3c.dom.ProcessingInstruction piNode = domNode
                        .getOwnerDocument().createProcessingInstruction(name,
                                value);
                domNode.appendChild(piNode);
                return piNode;

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected boolean domNodeNameEquals(org.w3c.dom.Node node,
            String namespaceURI, String localName) {
        if (node == null)
            return false;
        if (localName == null)
            return true;
        String nodeURI = node.getNamespaceURI() == null ? "" : node
                .getNamespaceURI();
        String nodeLocalName = node.getLocalName() == null ? "" : node
                .getLocalName();
        if (namespaceURI == null)
            namespaceURI = "";
        return nodeURI.equals(namespaceURI) && nodeLocalName.equals(localName);
    }

    protected int getDomChildCount(int type, String namespaceURI, String name) {
        switch (type) {
            case Attribute:
                try {
                    return ((org.w3c.dom.Element) domNode).hasAttributeNS(
                            namespaceURI, name) ? 1 : 0;
                } catch (Exception e) {
                    return 0;
                }

            case Element:
                org.w3c.dom.NodeList elements = domNode.getChildNodes();
                int length = elements.getLength();
                int count = 0;

                for (int i = 0; i < length; i++) {
                    org.w3c.dom.Node child = elements.item(i);
                    if (domNodeNameEquals(child, namespaceURI, name))
                        count++;
                }
                return count;

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected boolean hasDomChild(int type, String namespaceURI, String name) {
        switch (type) {
            case Attribute:
                return ((org.w3c.dom.Element) domNode).hasAttributeNS(
                        namespaceURI, name) ? true : false;

            case Element:
                org.w3c.dom.NodeList elements = domNode.getChildNodes();
                int length = elements.getLength();
                for (int i = 0; i < length; i++)
                    if (domNodeNameEquals(elements.item(i), namespaceURI, name))
                        return true;
                return false;

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected org.w3c.dom.Node getDomChildAt(int type, String namespaceURI,
            String name, int index) {
        int length, count = 0;

        switch (type) {
            case Attribute:
                return domNode.getAttributes().getNamedItemNS(namespaceURI,
                        name);

            case Element:
                org.w3c.dom.NodeList elements = domNode.getChildNodes();
                length = elements.getLength();
                for (int i = 0; i < length; i++) {
                    org.w3c.dom.Node child = elements.item(i);
                    if (domNodeNameEquals(child, namespaceURI, name)
                            && count++ == index)
                        return child;
                }
                throw new XmlException("Index out of range");

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected org.w3c.dom.Node getDomFirstChild(int type, String namespaceURI,
            String name) {

        switch (type) {
            case Attribute:
                if (((org.w3c.dom.Element) domNode).hasAttributeNS(
                        namespaceURI, name) == false)
                    return null;
                return domNode.getAttributes().getNamedItemNS(namespaceURI,
                        name);

            case Element:
                if (domNode.hasChildNodes() == false)
                    return null;
                org.w3c.dom.Node child = domNode.getFirstChild();
                while (child != null) {
                    if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)
                        if (domNodeNameEquals(child, namespaceURI, name)) {
                            org.w3c.dom.Node retElement = child;
                            child = null;
                            return retElement;
                        }
                    child = child.getNextSibling();
                }
                return null;

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected org.w3c.dom.Node getDomNextChild(int type, String namespaceURI,
            String name, org.w3c.dom.Node childNode) {

        switch (type) {
            case Attribute:
                return null;

            case Element:
                org.w3c.dom.Node child = childNode;
                if (child != null)
                    child = child.getNextSibling();
                while (child != null) {
                    if (domNodeNameEquals(child, namespaceURI, name))
                        return child;
                    child = child.getNextSibling();
                }
                return null;

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected org.w3c.dom.Node getDomChild(int type, String namespaceURI,
            String name) {
        return getDomChildAt(type, namespaceURI, name, 0);
    }

    protected org.w3c.dom.Node insertDomChildAt(int type, String namespaceURI,
            String name, int index, String value) {
        if (type == Attribute) {
            return appendDomChild(type, namespaceURI, name, value);
        } else {
            org.w3c.dom.Element element = domNode.getOwnerDocument()
                    .createElementNS(namespaceURI, name);
            element.appendChild(domNode.getOwnerDocument()
                    .createTextNode(value));
            return domNode.insertBefore(element, getDomChildAt(Element,
                    namespaceURI, name, index));
        }
    }

    protected org.w3c.dom.Node insertDomElementAt(String namespaceURI,
            String name, int index, com.jmex.model.collada.xml.Node srcNode) {
        srcNode.domNode = domNode.insertBefore(cloneDomElementAs(namespaceURI,
                name, srcNode), getDomChildAt(Element, namespaceURI, name,
                index));
        return srcNode.domNode;
    }

    protected org.w3c.dom.Node replaceDomChildAt(int type, String namespaceURI,
            String name, int index, String value) {
        if (type == Attribute) {
            return appendDomChild(type, namespaceURI, name, value);
        } else {
            org.w3c.dom.Element element = domNode.getOwnerDocument()
                    .createElementNS(namespaceURI, name);
            element.appendChild(domNode.getOwnerDocument()
                    .createTextNode(value));
            return domNode.replaceChild(element, getDomChildAt(Element,
                    namespaceURI, name, index));
        }
    }

    protected org.w3c.dom.Node replaceDomElementAt(String namespaceURI,
            String name, int index, com.jmex.model.collada.xml.Node srcNode) {
        srcNode.domNode = domNode.replaceChild(cloneDomElementAs(namespaceURI,
                name, srcNode), getDomChildAt(Element, namespaceURI, name,
                index));
        return srcNode.domNode;
    }

    protected org.w3c.dom.Node setDomChildAt(int type, String namespaceURI,
            String name, String value, int index) {
        int length, count = 0;

        switch (type) {
            case Attribute:
                org.w3c.dom.Attr oldAttr = ((org.w3c.dom.Element) domNode)
                        .getAttributeNodeNS(namespaceURI, name);
                ((org.w3c.dom.Element) domNode).setAttributeNS(namespaceURI,
                        name, value);
                return oldAttr;

            case Element:
                org.w3c.dom.NodeList elements = domNode.getChildNodes();
                length = elements.getLength();
                for (int i = 0; i < length; i++) {
                    org.w3c.dom.Node child = elements.item(i);
                    if (domNodeNameEquals(child, namespaceURI, name)
                            && count++ == index)
                        return child.replaceChild(child.getOwnerDocument()
                                .createTextNode(value), child.getFirstChild());
                }
                throw new XmlException("Index out of range");

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected org.w3c.dom.Node setDomChild(int type, String namespaceURI,
            String name, String value) {
        if (type == Attribute || getDomChildCount(type, namespaceURI, name) > 0) {
            return setDomChildAt(type, namespaceURI, name, value, 0);
        } else {
            appendDomChild(type, namespaceURI, name, value);
            return null;
        }
    }

    protected org.w3c.dom.Node removeDomChildAt(int type, String namespaceURI,
            String name, int index) {
        int length, count = 0;

        switch (type) {
            case Attribute:
                return domNode.getAttributes().removeNamedItemNS(namespaceURI,
                        name);

            case Element:
                org.w3c.dom.NodeList elements = domNode.getChildNodes();
                length = elements.getLength();
                for (int i = 0; i < length; i++) {
                    org.w3c.dom.Node child = elements.item(i);
                    if (domNodeNameEquals(child, namespaceURI, name)
                            && count++ == index)
                        return domNode.removeChild(child);
                }
                throw new XmlException("Index out of range");

            default:
                throw new XmlException("Unknown type");
        }
    }

    protected org.w3c.dom.Node appendDomElement(String namespaceURI,
            String name, com.jmex.model.collada.xml.Node srcNode) {
        srcNode.domNode = domNode.appendChild(cloneDomElementAs(namespaceURI,
                name, srcNode));
        return srcNode.domNode;
    }

    protected org.w3c.dom.Element cloneDomElementAs(String namespaceURI,
            String name, com.jmex.model.collada.xml.Node srcNode) {
        org.w3c.dom.Element newDomNode = domNode.getOwnerDocument()
                .createElementNS(namespaceURI, name);
        org.w3c.dom.Element srcDomNode = (org.w3c.dom.Element) srcNode.domNode;
        org.w3c.dom.Document doc = newDomNode.getOwnerDocument();

        org.w3c.dom.NodeList list = srcDomNode.getChildNodes();
        int length = list.getLength();
        for (int i = 0; i < length; i++)
            newDomNode.appendChild(doc.importNode(list.item(i), true));

        org.w3c.dom.NamedNodeMap srcAttributes = srcDomNode.getAttributes();
        org.w3c.dom.NamedNodeMap newAttributes = newDomNode.getAttributes();
        length = srcAttributes.getLength();
        for (int i = 0; i < length; i++)
            newAttributes.setNamedItemNS(doc.importNode(
                    srcAttributes.item(i), false));

        return newDomNode;
    }

    protected void cloneInto(org.w3c.dom.Element newDomNode) {
        while (domNode.getFirstChild() != null) {
            org.w3c.dom.Node n = newDomNode.getOwnerDocument().importNode(
                    domNode.getFirstChild(), true);
            newDomNode.appendChild(n);
            domNode.removeChild(domNode.getFirstChild());
        }

        org.w3c.dom.NamedNodeMap srcAttributes = ((org.w3c.dom.Element) domNode)
                .getAttributes();
        org.w3c.dom.NamedNodeMap newAttributes = newDomNode.getAttributes();
        while (srcAttributes.getLength() > 0) {
            org.w3c.dom.Node n = srcAttributes.item(0);
            newAttributes.setNamedItem(newDomNode.getOwnerDocument()
                    .importNode(n, true));
            srcAttributes.removeNamedItem(n.getNodeName());
        }

        domNode = newDomNode;
    }

    protected static String lookupPrefix(org.w3c.dom.Node node, String URI) {
        if (node == null || URI == null || URI.equals(""))
            return null;

        if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
            org.w3c.dom.NamedNodeMap attrs = node.getAttributes();
            if (attrs != null) {
                int len = attrs.getLength();
                for (int i = 0; i < len; i++) {
                    org.w3c.dom.Attr attr = (org.w3c.dom.Attr) attrs.item(i);
                    String name = attr.getName();
                    String value = attr.getValue();
                    if (value != null && value.equals(URI)) {
                        if (name.startsWith("xmlns:"))
                            return name.substring(6);
                    }
                }
            }
            return lookupPrefix(node.getParentNode(), URI);
        } else if (node.getNodeType() == org.w3c.dom.Node.ATTRIBUTE_NODE) {
            return lookupPrefix(((org.w3c.dom.Attr) node).getOwnerElement(),
                    URI);
        } else {
            return null;
        }
    }

    protected static String lookupDefaultNamespace(org.w3c.dom.Node node) {
        if (node == null)
            return null;

        if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
            org.w3c.dom.Attr attr = ((org.w3c.dom.Element) node)
                    .getAttributeNode("xmlns");
            if (attr != null)
                return attr.getValue();
        }

        return lookupDefaultNamespace(node.getParentNode());
    }

    protected static void internalAdjustPrefix(org.w3c.dom.Node node,
            boolean qualified) {
        if (node == null)
            return;
        if (qualified) {
            String prefix = lookupPrefix(node, node.getNamespaceURI());
            if (prefix != null)
                node.setPrefix(prefix);
        } else if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
            org.w3c.dom.Element element = (org.w3c.dom.Element) node;
            if (lookupDefaultNamespace(element) != null)
                element.setAttribute("xmlns", "");
        }
    }

    public abstract void adjustPrefix();

}
