com.ctc.wstx.dom.DOMOutputElement Maven / Gradle / Ivy
package com.ctc.wstx.dom;
import javax.xml.namespace.NamespaceContext;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.ctc.wstx.sw.OutputElementBase;
import com.ctc.wstx.util.BijectiveNsMap;
/**
* Context object that holds information about an open element
* (one for which START_ELEMENT has been sent, but no END_ELEMENT)
*/
public final class DOMOutputElement
extends OutputElementBase
{
/**
* Reference to the parent element, element enclosing this element.
* Null for root element.
* Non-final to allow temporary pooling
* (on per-writer basis, to keep these short-lived).
*/
private DOMOutputElement mParent;
/**
* DOM node that is the root under which content is written, in case
* where there is no parent (mParent == null). If mParent is not null,
* this will be null.
* Value is of type
* {@link Document}, {@link DocumentFragment} or {@link Element}
*/
private final Node mRootNode;
/**
* Actual DOM element for which this element object acts as a proxy.
*/
private Element mElement;
private boolean mDefaultNsSet;
/**
* Constructor for the virtual root element
*/
private DOMOutputElement(Node rootNode)
{
super();
mRootNode = rootNode;
mParent = null;
mElement = null;
mNsMapping = null;
mNsMapShared = false;
mDefaultNsURI = "";
mRootNsContext = null;
mDefaultNsSet = false;
}
private DOMOutputElement(DOMOutputElement parent, Element element, BijectiveNsMap ns)
{
super(parent, ns);
mRootNode = null;
mParent = parent;
mElement = element;
mNsMapping = ns;
mNsMapShared = (ns != null);
mDefaultNsURI = parent.mDefaultNsURI;
mRootNsContext = parent.mRootNsContext;
mDefaultNsSet = false;
}
/**
* Method called to reuse a pooled instance.
*
* @return Chained pooled instance that should now be head of the
* reuse chain
*/
private void relink(DOMOutputElement parent, Element element)
{
super.relink(parent);
mParent = parent;
mElement = element;
parent.appendNode(element);
mDefaultNsSet = false;
}
public static DOMOutputElement createRoot(Node rootNode)
{
return new DOMOutputElement(rootNode);
}
/**
* Simplest factory method, which gets called when a 1-argument
* element output method is called. It is, then, assumed to
* use the default namespace.
* Will both create the child element and attach it to parent element,
* or lacking own owner document.
*/
protected DOMOutputElement createAndAttachChild(Element element)
{
if (mRootNode != null) {
mRootNode.appendChild(element);
} else {
mElement.appendChild(element);
}
return createChild(element);
}
protected DOMOutputElement createChild(Element element)
{
return new DOMOutputElement(this, element, mNsMapping);
}
/**
* @return New head of the recycle pool
*/
protected DOMOutputElement reuseAsChild(DOMOutputElement parent, Element element)
{
DOMOutputElement poolHead = mParent;
relink(parent, element);
return poolHead;
}
/**
* Method called to temporarily link this instance to a pool, to
* allow reusing of instances with the same reader.
*/
protected void addToPool(DOMOutputElement poolHead)
{
mParent = poolHead;
}
/*
///////////////////////////////////////////////////////////
// Public API, accessors
///////////////////////////////////////////////////////////
*/
public DOMOutputElement getParent() {
return mParent;
}
public boolean isRoot() {
// (Virtual) Root element has no parent...
return (mParent == null);
}
/**
* @return String presentation of the fully-qualified name, in
* "prefix:localName" format (no URI). Useful for error and
* debugging messages.
*/
public String getNameDesc() {
if(mElement != null) {
return mElement.getLocalName();
}
return "#error"; // unexpected case
}
/*
///////////////////////////////////////////////////////////
// Public API, mutators
///////////////////////////////////////////////////////////
*/
public void setDefaultNsUri(String uri) {
mDefaultNsURI = uri;
mDefaultNsSet = true;
}
protected void setRootNsContext(NamespaceContext ctxt)
{
mRootNsContext = ctxt;
/* Let's also see if we have an active default ns mapping:
* (provided it hasn't yet explicitly been set for this element)
*/
if (!mDefaultNsSet) {
String defURI = ctxt.getNamespaceURI("");
if (defURI != null && defURI.length() > 0) {
mDefaultNsURI = defURI;
}
}
}
/*
///////////////////////////////////////////////////////////
// Public API, DOM manipulation
///////////////////////////////////////////////////////////
*/
protected void appendNode(Node n)
{
if (mRootNode != null) {
mRootNode.appendChild(n);
} else {
mElement.appendChild(n);
}
}
protected void addAttribute(String pname, String value)
{
mElement.setAttribute(pname, value);
}
protected void addAttribute(String uri, String qname, String value)
{
mElement.setAttributeNS(uri, qname, value);
}
public void appendChild(Node n) {
mElement.appendChild(n);
}
}