in src/main/java/org/apache/xmlbeans/impl/store/DomImpl.java [1542:1704]
public static Node node_insertBefore(Dom p, Dom nc, final Dom rc) {
assert nc != null;
// Inserting self before self is a no-op
if (nc == rc) {
return (Node) nc;
}
if (rc != null && parent(rc) != p) {
throw new NotFoundErr("RefChild is not a child of this node");
}
// TODO - obey readonly status of a substree
int nck = nc.nodeType();
if (nck == DOCFRAG) {
for (Node c = firstChild(nc); c != null; c = nextSibling((Dom) c)) {
validateNewChild(p, (Dom) c);
}
for (Node c = firstChild(nc); c != null; ) {
Node n = nextSibling((Dom) c);
if (rc == null) {
append((Dom) c, p);
} else {
insert((Dom) c, rc);
}
c = n;
}
return (Node) nc;
}
//
// Make sure the new child is allowed here
//
validateNewChild(p, nc);
//
// Orphan the child before establishing a new parent
//
remove(nc);
int pk = p.nodeType();
// Only these nodes can be modifiable parents
assert pk == ATTR || pk == DOCFRAG || pk == DOCUMENT || pk == ELEMENT;
switch (nck) {
case ELEMENT:
case COMMENT:
case PROCINST: {
if (rc == null) {
Cur cTo = p.tempCur();
cTo.toEnd();
Cur.moveNode((Xobj) nc, cTo);
cTo.release();
} else {
int rck = rc.nodeType();
if (rck == TEXT || rck == CDATA) {
// Quick and dirty impl....
List<Dom> charNodes = new ArrayList<>();
Dom rc2 = rc;
while (rc2 != null && (rc2.nodeType() == TEXT || rc2.nodeType() == CDATA)) {
Node next = nextSibling(rc2);
charNodes.add((Dom) remove(rc2));
rc2 = (Dom) next;
}
if (rc2 == null) {
append(nc, p);
} else {
insert(nc, rc2);
}
rc2 = (Dom) nextSibling(nc);
for (Object charNode : charNodes) {
Dom n = (Dom) charNode;
if (rc2 == null) {
append(n, p);
} else {
insert(n, rc2);
}
}
} else if (rck == ENTITYREF) {
throw new RuntimeException("Not implemented");
} else {
assert rck == ELEMENT || rck == PROCINST || rck == COMMENT;
Cur cTo = rc.tempCur();
Cur.moveNode((Xobj) nc, cTo);
cTo.release();
}
}
break;
}
case TEXT:
case CDATA: {
CharNode n = (CharNode) nc;
assert n._prev == null && n._next == null;
CharNode refCharNode = null;
Cur c = p.tempCur();
if (rc == null) {
c.toEnd();
} else {
int rck = rc.nodeType();
if (rck == TEXT || rck == CDATA) {
c.moveToCharNode(refCharNode = (CharNode) rc);
} else if (rck == ENTITYREF) {
throw new RuntimeException("Not implemented");
} else {
c.moveToDom(rc);
}
}
CharNode nodes = c.getCharNodes();
nodes = CharNode.insertNode(nodes, n, refCharNode);
c.insertChars(n.getObject(), n._off, n._cch);
c.setCharNodes(nodes);
c.release();
break;
}
case ENTITYREF: {
throw new RuntimeException("Not implemented");
}
case DOCTYPE: {
// TODO - don't actually insert this here, associate it with the
// doc?? Hmm .. Perhaps I should disallow insertion into the tree
// at all.
throw new RuntimeException("Not implemented");
}
default:
throw new RuntimeException("Unexpected child node type");
}
return (Node) nc;
}