throws DOMException {
if (last == null || last.getNode() == null)
//TODO : same test as above ? -pb
{throw new DOMException(DOMException.INVALID_MODIFICATION_ERR, "invalid node");}
final DocumentImpl owner = (DocumentImpl)getOwnerDocument();
DBBroker broker = null;
try {
broker = ownerDocument.getBrokerPool().get(null);
switch (child.getNodeType()) {
case Node.DOCUMENT_FRAGMENT_NODE :
appendChildren(transaction, newNodeId, null, last, lastPath,
child.getChildNodes(), listener);
return null; // TODO: implement document fragments so
//we can return all newly appended children
case Node.ELEMENT_NODE :
// create new element
final ElementImpl elem =
new ElementImpl(
new QName(child.getLocalName() == null ?
child.getNodeName() : child.getLocalName(),
child.getNamespaceURI(),
child.getPrefix()),
broker.getBrokerPool().getSymbols()
);
elem.setNodeId(newNodeId);
elem.setOwnerDocument(owner);
final NodeListImpl ch = new NodeListImpl();
final NamedNodeMap attribs = child.getAttributes();
int numActualAttribs = 0;
for (int i = 0; i < attribs.getLength(); i++) {
final Attr attr = (Attr) attribs.item(i);
if (!attr.getNodeName().startsWith("xmlns")) {
ch.add(attr);
numActualAttribs++;
} else {
final String xmlnsDecl = attr.getNodeName();
final String prefix = xmlnsDecl.length() == 5 ? "" : xmlnsDecl.substring(6);
elem.addNamespaceMapping(prefix,attr.getNodeValue());
}
}
final NodeList cl = child.getChildNodes();
for (int i = 0; i < cl.getLength(); i++) {
final Node n = cl.item(i);
if (n.getNodeType() != Node.ATTRIBUTE_NODE)
{ch.add(n);}
}
elem.setChildCount(ch.getLength());
if (numActualAttribs != (short) numActualAttribs)
{throw new DOMException(DOMException.INVALID_MODIFICATION_ERR, "Too many attributes");}
elem.setAttributes((short) numActualAttribs);
lastPath.addComponent(elem.getQName());
// insert the node
broker.insertNodeAfter(transaction, last.getNode(), elem);
broker.indexNode(transaction, elem, lastPath);
broker.getIndexController().indexNode(transaction, elem, lastPath, listener);
elem.setChildCount(0);
last.setNode(elem);
//process child nodes
elem.appendChildren(transaction, newNodeId.newChild(), null, last, lastPath, ch, listener);
broker.endElement(elem, lastPath, null);
broker.getIndexController().endElement(transaction, elem, lastPath, listener);
lastPath.removeLastComponent();
return elem;
case Node.TEXT_NODE :
final TextImpl text = new TextImpl(newNodeId, ((Text) child).getData());
text.setOwnerDocument(owner);
// insert the node
broker.insertNodeAfter(transaction, last.getNode(), text);
broker.indexNode(transaction, text, lastPath);
broker.getIndexController().indexNode(transaction, text, lastPath, listener);
last.setNode(text);
return text;
case Node.CDATA_SECTION_NODE :
final CDATASectionImpl cdata = new CDATASectionImpl(newNodeId, ((CDATASection) child).getData());
cdata.setOwnerDocument(owner);
// insert the node
broker.insertNodeAfter(transaction, last.getNode(), cdata);
broker.indexNode(transaction, cdata, lastPath);
last.setNode(cdata);
return cdata;
case Node.ATTRIBUTE_NODE:
final Attr attr = (Attr) child;
final String ns = attr.getNamespaceURI();
final String prefix = (Namespaces.XML_NS.equals(ns) ? "xml" : attr.getPrefix());
String name = attr.getLocalName();
if (name == null) {name = attr.getName();}
final QName attrName = new QName(name, ns, prefix);
final AttrImpl attrib = new AttrImpl(attrName, attr.getValue(), broker.getBrokerPool().getSymbols());
attrib.setNodeId(newNodeId);
attrib.setOwnerDocument(owner);
if (ns != null && attrName.compareTo(Namespaces.XML_ID_QNAME) == Constants.EQUAL) {
// an xml:id attribute. Normalize the attribute and set its type to ID
attrib.setValue(StringValue.trimWhitespace(StringValue.collapseWhitespace(attrib.getValue())));
attrib.setType(AttrImpl.ID);
} else {
attrName.setNameType(ElementValue.ATTRIBUTE);
}
broker.insertNodeAfter(transaction, last.getNode(), attrib);
broker.indexNode(transaction, attrib, lastPath);
broker.getIndexController().indexNode(transaction, attrib, lastPath, listener);
last.setNode(attrib);
return attrib;
case Node.COMMENT_NODE:
final CommentImpl comment = new CommentImpl(((Comment) child).getData());
comment.setNodeId(newNodeId);
comment.setOwnerDocument(owner);
// insert the node
broker.insertNodeAfter(transaction, last.getNode(), comment);
broker.indexNode(transaction, comment, lastPath);
last.setNode(comment);
return comment;
case Node.PROCESSING_INSTRUCTION_NODE:
final ProcessingInstructionImpl pi =
new ProcessingInstructionImpl(newNodeId,
((ProcessingInstruction) child).getTarget(),
((ProcessingInstruction) child).getData());
pi.setOwnerDocument(owner);
//insert the node
broker.insertNodeAfter(transaction, last.getNode(), pi);
broker.indexNode(transaction, pi, lastPath);
last.setNode(pi);
return pi;
default :
throw new DOMException(DOMException.INVALID_MODIFICATION_ERR,
"Unknown node type: " +
child.getNodeType() + " " + child.getNodeName());
}
} catch (final EXistException e) {
LOG.warn("Exception while appending node: " + e.getMessage(), e);
} finally {
if (broker != null)
broker.release();
}
return null;
}