public static Node node_insertBefore()

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;
    }