package org.caudexorigo.jpt;
import nu.xom.Attribute;
import nu.xom.Comment;
import nu.xom.DocType;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Node;
import nu.xom.ParentNode;
import nu.xom.ProcessingInstruction;
import nu.xom.Text;
import nu.xom.XMLException;
public class BaseJptNodeBuilder
{
public BaseJptNodeBuilder(StringBuilder sb)
{
_buffer = sb;
}
public void process(Document doc)
{
int childCount = doc.getChildCount();
for (int i = 0; i < childCount; i++)
processChild(doc.getChild(i));
}
protected void process(Element element)
{
boolean hasRealChildren = false;
int childCount = element.getChildCount();
for (int i = 0; i < childCount; i++)
{
Node child = element.getChild(i);
if (child instanceof Text)
{
Text t = (Text) child;
if (t.getValue().length() == 0)
continue;
}
hasRealChildren = true;
break;
}
if (hasRealChildren)
{
processStartTag(element);
for (int i = 0; i < childCount; i++)
{
Node child = element.getChild(i);
processChild(child);
}
processEndTag(element);
}
else
{
processEmptyElementTag(element);
}
}
protected void processEndTag(Element element)
{
_buffer.append("</");
_buffer.append(element.getQualifiedName());
_buffer.append('>');
}
protected void processStartTag(Element element)
{
processTagBeginning(element);
_buffer.append('>');
}
protected void processEmptyElementTag(Element element)
{
processTagBeginning(element);
_buffer.append("/>");
}
// This just extracts the commonality between processStartTag
// and processEmptyElementTag
private void processTagBeginning(Element element)
{
_buffer.append('<');
_buffer.append(element.getQualifiedName());
processAttributes(element);
processNamespaceDeclarations(element);
}
protected void processAttributes(Element element)
{
int attributeCount = element.getAttributeCount();
for (int i = 0; i < attributeCount; i++)
{
Attribute attribute = element.getAttribute(i);
_buffer.append(' ');
process(attribute);
}
}
protected void processNamespaceDeclarations(Element element)
{
for (int i = 0; i < element.getNamespaceDeclarationCount(); i++)
{
String additionalPrefix = element.getNamespacePrefix(i);
String uri = element.getNamespaceURI(additionalPrefix);
if (isJptNs(uri))
{
continue;
}
ParentNode parentNode = element.getParent();
if (parentNode != null && (parentNode instanceof Element))
{
Element parentElement = (Element) parentNode;
if (uri.equals(parentElement.getNamespaceURI(additionalPrefix)))
{
continue;
}
}
else if (uri.length() == 0)
{
continue; // no need to say xmlns=""
}
_buffer.append(" xmlns");
if (additionalPrefix.length() > 0)
{
_buffer.append(':');
_buffer.append(additionalPrefix);
}
_buffer.append("=\"");
// _buffer.append(escape(uri));
_buffer.append(uri);
_buffer.append('"');
}
}
private boolean isJptNs(String uri)
{
return (uri.equals("http://xml.zope.org/namespaces/tal") || uri.equals("http://xml.zope.org/namespaces/metal") || uri.equals("http://xml.zope.org/namespaces/metal/append-to-slot"));
}
protected void process(Attribute attribute)
{
_buffer.append(attribute.getQualifiedName());
_buffer.append("=\"");
_buffer.append(attribute.getValue());
_buffer.append('"');
}
protected void process(Comment comment)
{
_buffer.append("<!--");
_buffer.append(comment.getValue());
_buffer.append("-->");
}
protected void process(Text text)
{
String value = text.getValue();
_buffer.append(value);
}
protected void process(DocType doctype)
{
_buffer.append("<!DOCTYPE ");
_buffer.append(doctype.getRootElementName());
if (doctype.getPublicID() != null)
{
_buffer.append(" PUBLIC \"" + doctype.getPublicID() + "\" \"" + doctype.getSystemID() + "\"");
}
else if (doctype.getSystemID() != null)
{
_buffer.append(" SYSTEM \"" + doctype.getSystemID() + "\"");
}
_buffer.append(">\n");
}
private void process(ProcessingInstruction pi)
{
// ignore
}
protected void processChild(Node node)
{
if (node instanceof Element)
process((Element) node);
else if (node instanceof Text)
process((Text) node);
else if (node instanceof Comment)
process((Comment) node);
else if (node instanceof ProcessingInstruction)
process((ProcessingInstruction) node);
else if (node instanceof DocType)
process((DocType) node);
else
throw new XMLException((new StringBuilder("Cannot process a ")).append(node.getClass().getName()).append(" from the processChild() method").toString());
}
protected final void processAttributeValue(String value)
{
_buffer.append(value);
}
protected final void processRaw(String text)
{
_buffer.append(text);
}
public StringBuilder getBuffer()
{
return _buffer;
}
public void setBuffer(StringBuilder buf)
{
_buffer = buf;
}
private StringBuilder _buffer;
}