/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.xmlbeans.impl.store;

import org.apache.xmlbeans.*;
import org.apache.xmlbeans.XmlCursor.XmlBookmark;
import org.apache.xmlbeans.impl.soap.*;
import org.apache.xmlbeans.impl.store.DomImpl.Dom;
import org.apache.xmlbeans.impl.store.Locale.LoadContext;
import org.apache.xmlbeans.impl.values.TypeStoreUser;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;

import javax.xml.namespace.QName;
import java.io.PrintStream;
import java.util.Map;

import static org.apache.xmlbeans.impl.values.TypeStore.WS_PRESERVE;

// DOM Level 3


public final class Cur {
    static final int TEXT = 0; // Must be 0
    static final int ROOT = 1;
    static final int ELEM = 2;
    static final int ATTR = 3;
    static final int COMMENT = 4;
    static final int PROCINST = 5;

    static final int POOLED = 0;
    static final int REGISTERED = 1;
    static final int EMBEDDED = 2;
    static final int DISPOSED = 3;

    static final int END_POS = -1;
    static final int NO_POS = -2;

    Locale _locale;

    Xobj _xobj;
    int _pos;

    int _state;

    String _id;

    Cur _nextTemp;
    Cur _prevTemp;
    int _tempFrame;

    Cur _next;
    Cur _prev;

    Locale.Ref _ref;

    int _stackTop;

    int _selectionFirst;
    int _selectionN;
    int _selectionLoc;
    int _selectionCount;

    private int _posTemp;

    int _offSrc;
    int _cchSrc;


    Cur(Locale l) {
        _locale = l;
        _pos = NO_POS;

        _tempFrame = -1;

        _state = POOLED;

        _stackTop = Locations.NULL;
        _selectionFirst = -1;
        _selectionN = -1;
        _selectionLoc = Locations.NULL;
        _selectionCount = 0;
    }

    public boolean isPositioned() {
        assert isNormal();
        return _xobj != null;
    }

    static boolean kindIsContainer(int k) {
        return k == ELEM || k == ROOT;
    }

    static boolean kindIsFinish(int k) {
        return k == -ELEM || k == -ROOT;
    }

    public int kind() {
        assert isPositioned();
        int kind = _xobj.kind();
        return _pos == 0 ? kind : (_pos == END_POS ? -kind : TEXT);
    }

    public boolean isRoot() {
        assert isPositioned();
        return _pos == 0 && _xobj.kind() == ROOT;
    }

    public boolean isElem() {
        assert isPositioned();
        return _pos == 0 && _xobj.kind() == ELEM;
    }

    public boolean isAttr() {
        assert isPositioned();
        return _pos == 0 && _xobj.kind() == ATTR;
    }

    public boolean isComment() {
        assert isPositioned();
        return _pos == 0 && _xobj.kind() == COMMENT;
    }

    public boolean isProcinst() {
        assert isPositioned();
        return _pos == 0 && _xobj.kind() == PROCINST;
    }

    public boolean isText() {
        assert isPositioned();
        return _pos > 0;
    }

    public boolean isEnd() {
        assert isPositioned();
        return _pos == END_POS && _xobj.kind() == ELEM;
    }

    public boolean isEndRoot() {
        assert isPositioned();
        return _pos == END_POS && _xobj.kind() == ROOT;
    }

    public boolean isNode() {
        assert isPositioned();
        return _pos == 0;
    }

    public boolean isContainer() {
        assert isPositioned();
        return _pos == 0 && kindIsContainer(_xobj.kind());
    }

    public boolean isFinish() {
        assert isPositioned();
        return _pos == END_POS && kindIsContainer(_xobj.kind());
    }

    public boolean isUserNode() {
        assert isPositioned();
        int k = kind();
        return k == ELEM || k == ROOT || (k == ATTR && !isXmlns());
    }

    public boolean isContainerOrFinish() {
        assert isPositioned();

        if (_pos != 0 && _pos != END_POS) {
            return false;
        }

        int kind = _xobj.kind();
        return kind == ELEM || kind == -ELEM || kind == ROOT || kind == -ROOT;
    }

    public boolean isNormalAttr() {
        return isNode() && _xobj.isNormalAttr();
    }

    public boolean isXmlns() {
        return isNode() && _xobj.isXmlns();
    }

    public boolean isTextCData() {
        return _xobj.hasBookmark(CDataBookmark.class, _pos);
    }

    public QName getName() {
        assert isNode() || isEnd();
        return _xobj._name;
    }

    public String getLocal() {
        return getName().getLocalPart();
    }

    public String getUri() {
        return getName().getNamespaceURI();
    }

    public String getXmlnsPrefix() {
        assert isXmlns();
        return _xobj.getXmlnsPrefix();
    }

    public String getXmlnsUri() {
        assert isXmlns();
        return _xobj.getXmlnsUri();
    }

    public boolean isDomDocRoot() {
        return isRoot() && _xobj.getDom() instanceof Document;
    }

    public boolean isDomFragRoot() {
        return isRoot() && _xobj.getDom() instanceof DocumentFragment;
    }

    public int cchRight() {
        assert isPositioned();
        return _xobj.cchRight(_pos);
    }

    public int cchLeft() {
        assert isPositioned();
        return _xobj.cchLeft(_pos);
    }

    //
    // Creation methods
    //

    void createRoot() {
        createDomDocFragRoot();
    }

    void createDomDocFragRoot() {
        moveTo(new DocumentFragXobj(_locale));
    }

    void createDomDocumentRoot() {
        moveTo(createDomDocumentRootXobj(_locale));
    }

    void createAttr(QName name) {
        createHelper(new AttrXobj(_locale, name));
    }

    void createComment() {
        createHelper(new CommentXobj(_locale));
    }

    void createProcinst(String target) {
        createHelper(new ProcInstXobj(_locale, target));
    }

    void createElement(QName name) {
        createElement(name, null);
    }

    void createElement(QName name, QName parentName) {
        createHelper(createElementXobj(_locale, name, parentName));
    }

    static Xobj createDomDocumentRootXobj(Locale l) {
        return createDomDocumentRootXobj(l, false);
    }

    static Xobj createDomDocumentRootXobj(Locale l, boolean fragment) {
        Xobj xo;

        if (l._saaj == null) {
            if (fragment) {
                xo = new DocumentFragXobj(l);
            } else {
                xo = new DocumentXobj(l);
            }
        } else {
            xo = new SoapPartDocXobj(l);
        }

        if (l._ownerDoc == null) {
            l._ownerDoc = xo.getDom();
        }

        return xo;
    }

    static Xobj createElementXobj(Locale l, QName name, QName parentName) {
        if (l._saaj == null) {
            return new ElementXobj(l, name);
        }

        Class<?> c = l._saaj.identifyElement(name, parentName);

        if (c == SOAPElement.class) {
            return new SoapElementXobj(l, name);
        }
        if (c == SOAPBody.class) {
            return new SoapBodyXobj(l, name);
        }
        if (c == SOAPBodyElement.class) {
            return new SoapBodyElementXobj(l, name);
        }
        if (c == SOAPEnvelope.class) {
            return new SoapEnvelopeXobj(l, name);
        }
        if (c == SOAPHeader.class) {
            return new SoapHeaderXobj(l, name);
        }
        if (c == SOAPHeaderElement.class) {
            return new SoapHeaderElementXobj(l, name);
        }
        if (c == SOAPFaultElement.class) {
            return new SoapFaultElementXobj(l, name);
        }
        if (c == Detail.class) {
            return new DetailXobj(l, name);
        }
        if (c == DetailEntry.class) {
            return new DetailEntryXobj(l, name);
        }
        if (c == SOAPFault.class) {
            return new SoapFaultXobj(l, name);
        }

        throw new IllegalStateException("Unknown SAAJ element class: " + c);
    }

    private void createHelper(Xobj x) {
        assert x._locale == _locale;

        // insert the new Xobj into an exisiting tree.

        if (isPositioned()) {
            Cur from = tempCur(x, 0);
            from.moveNode(this);
            from.release();
        }

        moveTo(x);
    }

    //
    // General operations
    //

    boolean isSamePos(Cur that) {
        assert isNormal() && (that == null || that.isNormal());

        return _xobj == that._xobj && _pos == that._pos;
    }

    // is this just after the end of that (that must be the start of a node)

    boolean isJustAfterEnd(Cur that) {
        assert isNormal() && that != null && that.isNormal() && that.isNode();

        return that._xobj.isJustAfterEnd(_xobj, _pos);
    }

    boolean isJustAfterEnd(Xobj x) {
        return x.isJustAfterEnd(_xobj, _pos);
    }

    boolean isAtEndOf(Cur that) {
        assert that != null && that.isNormal() && that.isNode();

        return _xobj == that._xobj && _pos == END_POS;
    }

    boolean isInSameTree(Cur that) {
        assert isPositioned() && that.isPositioned();

        return _xobj.isInSameTree(that._xobj);
    }

    // Retunr -1, 0 or 1 for relative cursor positions.  Return 2 is not in sames trees.

    int comparePosition(Cur that) {
        assert isPositioned() && that.isPositioned();

        // If in differnet locales, then can't comapre

        if (_locale != that._locale) {
            return 2;
        }

        // No need to denormalize, but I want positions which I can compare (no END_POS)

        Xobj xThis = _xobj;
        int pThis = _pos == END_POS ? xThis.posAfter() - 1 : _pos;

        Xobj xThat = that._xobj;
        int pThat = that._pos == END_POS ? xThat.posAfter() - 1 : that._pos;

        // There are several cases:
        //
        // 1. Cursors are on the same xobj
        // 2. One cursor is a child of the other
        // 3. Cursors share a common parent
        // 4. Cursors are not in the same trees
        //
        // Check for the first, trivial, case.  Then, compute the depths of the nodes the
        // cursors are on, checkin for case 2
        //

        if (xThis == xThat) {
            return Integer.compare(pThis, pThat);
        }

        // Compute the depth of xThis.  See if I hit xThat (case 2)

        int dThis = 0;

        for (Xobj x = xThis._parent; x != null; x = x._parent) {
            dThis++;

            if (x == xThat) {
                return pThat < xThat.posAfter() - 1 ? 1 : -1;
            }
        }

        // Compute the depth of xThat.  See if I hit xThis (case 2)

        int dThat = 0;

        for (Xobj x = xThat._parent; x != null; x = x._parent) {
            dThat++;

            if (x == xThis) {
                return pThis < xThis.posAfter() - 1 ? -1 : 1;
            }
        }

        // Must be case 3 or 4 now.  Find a common parent.  If none, then it's case 4

        while (dThis > dThat) {
            dThis--;
            assert (xThis != null);
            xThis = xThis._parent;
        }
        while (dThat > dThis) {
            dThat--;
            assert (xThat != null);
            xThat = xThat._parent;
        }

        assert dThat == dThis;

        if (dThat == 0) {
            return 2;
        }

        assert xThis != null && xThis._parent != null && xThat != null && xThat._parent != null;

        while (xThis._parent != xThat._parent) {
            if ((xThis = xThis._parent) == null) {
                return 2;
            }

            xThat = xThat._parent;
        }

        // Now, see where xThis and XThat are relative to eachother in the childlist.  Apply
        // some quick common checks before iterating.

        if (xThis._prevSibling == null || xThat._nextSibling == null) {
            return -1;
        }

        if (xThis._nextSibling == null || xThat._prevSibling == null) {
            return 1;
        }

        while (xThis != null) {
            if ((xThis = xThis._prevSibling) == xThat) {
                return 1;
            }
        }

        return -1;
    }

    void setName(QName newName) {
        assert isNode() && newName != null;

        _xobj.setName(newName);
    }

    void moveTo(Xobj x) {
        moveTo(x, 0);
    }

    void moveTo(Xobj x, int p) {
        // This cursor may not be normalized upon entry, don't assert isNormal() here

        assert x == null || _locale == x._locale;
        assert x != null || p == NO_POS;
        assert x == null || x.isNormal(p) || (x.isVacant() && x._cchValue == 0 && x._user == null);
        assert _state == REGISTERED || _state == EMBEDDED;
        assert _state == EMBEDDED || (_xobj == null || !isOnList(_xobj._embedded));
        assert _state == REGISTERED || (_xobj != null && isOnList(_xobj._embedded));

        moveToNoCheck(x, p);

        assert isNormal() || (_xobj.isVacant() && _xobj._cchValue == 0 && _xobj._user == null);
    }

    void moveToNoCheck(Xobj x, int p) {
        if (_state == EMBEDDED && x != _xobj) {
            _xobj._embedded = listRemove(_xobj._embedded);
            _locale._registered = listInsert(_locale._registered);
            _state = REGISTERED;
        }

        _xobj = x;
        _pos = p;
    }

    void moveToCur(Cur to) {
        assert isNormal() && (to == null || to.isNormal());

        if (to == null) {
            moveTo(null, NO_POS);
        } else {
            moveTo(to._xobj, to._pos);
        }
    }

    void moveToDom(Dom d) {
        assert _locale == d.locale();
        assert d instanceof Xobj || d instanceof SoapPartDom;

        moveTo(d instanceof Xobj ? (Xobj) d : ((SoapPartDom) d)._docXobj);
    }

    static final class Locations {
        private static final int NULL = -1;

        Locations(Locale l) {
            _locale = l;

            _xobjs = new Xobj[_initialSize];
            _poses = new int[_initialSize];
            _curs = new Cur[_initialSize];
            _next = new int[_initialSize];
            _prev = new int[_initialSize];
            _nextN = new int[_initialSize];
            _prevN = new int[_initialSize];

            for (int i = _initialSize - 1; i >= 0; i--) {
                assert _xobjs[i] == null;
                _poses[i] = NO_POS;
                _next[i] = i + 1;
                _prev[i] = NULL;
                _nextN[i] = NULL;
                _prevN[i] = NULL;
            }

            _next[_initialSize - 1] = NULL;

            _free = 0;
            _naked = NULL;
        }

        boolean isSamePos(int i, Cur c) {
            if (_curs[i] == null) {
                return c._xobj == _xobjs[i] && c._pos == _poses[i];
            } else {
                return c.isSamePos(_curs[i]);
            }
        }

        boolean isAtEndOf(int i, Cur c) {
            assert _curs[i] != null || _poses[i] == 0;
            assert _curs[i] == null || _curs[i].isNode();

            if (_curs[i] == null) {
                return c._xobj == _xobjs[i] && c._pos == END_POS;
            } else {
                return c.isAtEndOf(_curs[i]);
            }
        }

        void moveTo(int i, Cur c) {
            if (_curs[i] == null) {
                c.moveTo(_xobjs[i], _poses[i]);
            } else {
                c.moveToCur(_curs[i]);
            }
        }

        int insert(int head, int before, int i) {
            return insert(head, before, i, _next, _prev);
        }

        int remove(int head, int i) {
            Cur c = _curs[i];

            assert c != null || _xobjs[i] != null;
            assert c != null || _xobjs[i] != null;

            if (c != null) {
                _curs[i].release();
                _curs[i] = null;

                assert _xobjs[i] == null;
                assert _poses[i] == NO_POS;
            } else {
                assert _xobjs[i] != null && _poses[i] != NO_POS;

                _xobjs[i] = null;
                _poses[i] = NO_POS;

                _naked = remove(_naked, i, _nextN, _prevN);
            }

            head = remove(head, i, _next, _prev);

            _next[i] = _free;
            _free = i;

            return head;
        }

        int allocate(Cur addThis) {
            assert addThis.isPositioned();

            if (_free == NULL) {
                makeRoom();
            }

            int i = _free;

            _free = _next[i];

            _next[i] = NULL;
            assert _prev[i] == NULL;

            assert _curs[i] == null;
            assert _xobjs[i] == null;
            assert _poses[i] == NO_POS;

            _xobjs[i] = addThis._xobj;
            _poses[i] = addThis._pos;

            _naked = insert(_naked, NULL, i, _nextN, _prevN);

            return i;
        }

        private static int insert(int head, int before, int i, int[] next, int[] prev) {
            if (head == NULL) {
                assert before == NULL;
                prev[i] = i;
                head = i;
            } else if (before != NULL) {
                prev[i] = prev[before];
                next[i] = before;
                prev[before] = i;

                if (head == before) {
                    head = i;
                }
            } else {
                prev[i] = prev[head];
                assert next[i] == NULL;
                next[prev[head]] = i;
                prev[head] = i;
            }

            return head;
        }

        private static int remove(int head, int i, int[] next, int[] prev) {
            if (prev[i] == i) {
                assert head == i;
                head = NULL;
            } else {
                if (head == i) {
                    head = next[i];
                } else {
                    next[prev[i]] = next[i];
                }

                if (next[i] == NULL) {
                    prev[head] = prev[i];
                } else {
                    prev[next[i]] = prev[i];
                    next[i] = NULL;
                }
            }

            prev[i] = NULL;
            assert next[i] == NULL;

            return head;
        }

        void notifyChange() {
            for (int i; (i = _naked) != NULL; ) {
                assert _curs[i] == null && _xobjs[i] != null && _poses[i] != NO_POS;

                _naked = remove(_naked, i, _nextN, _prevN);

                _curs[i] = _locale.getCur();
                _curs[i].moveTo(_xobjs[i], _poses[i]);

                _xobjs[i] = null;
                _poses[i] = NO_POS;
            }
        }

        int next(int i) {
            return _next[i];
        }

        int prev(int i) {
            return _prev[i];
        }

        private void makeRoom() {
            assert _free == NULL;

            int l = _xobjs.length;

            Xobj[] oldXobjs = _xobjs;
            int[] oldPoses = _poses;
            Cur[] oldCurs = _curs;
            int[] oldNext = _next;
            int[] oldPrev = _prev;
            int[] oldNextN = _nextN;
            int[] oldPrevN = _prevN;

            _xobjs = new Xobj[l * 2];
            _poses = new int[l * 2];
            _curs = new Cur[l * 2];
            _next = new int[l * 2];
            _prev = new int[l * 2];
            _nextN = new int[l * 2];
            _prevN = new int[l * 2];

            System.arraycopy(oldXobjs, 0, _xobjs, 0, l);
            System.arraycopy(oldPoses, 0, _poses, 0, l);
            System.arraycopy(oldCurs, 0, _curs, 0, l);
            System.arraycopy(oldNext, 0, _next, 0, l);
            System.arraycopy(oldPrev, 0, _prev, 0, l);
            System.arraycopy(oldNextN, 0, _nextN, 0, l);
            System.arraycopy(oldPrevN, 0, _prevN, 0, l);

            for (int i = l * 2 - 1; i >= l; i--) {
                _next[i] = i + 1;
                _prev[i] = NULL;
                _nextN[i] = NULL;
                _prevN[i] = NULL;
                _poses[i] = NO_POS;
            }

            _next[l * 2 - 1] = NULL;

            _free = l;
        }

        private static final int _initialSize = 32;

        private final Locale _locale;

        private Xobj[] _xobjs;
        private int[] _poses;
        private Cur[] _curs;
        private int[] _next;
        private int[] _prev;
        private int[] _nextN;
        private int[] _prevN;

        private int _free;   // Unused entries
        private int _naked;  // Entries without Curs
    }

    public void push() {
        assert isPositioned();

        int i = _locale._locations.allocate(this);
        _stackTop = _locale._locations.insert(_stackTop, _stackTop, i);
    }

    void popButStay() {
        if (_stackTop != Locations.NULL) {
            _stackTop = _locale._locations.remove(_stackTop, _stackTop);
        }
    }

    boolean pop() {
        if (_stackTop == Locations.NULL) {
            return false;
        }

        _locale._locations.moveTo(_stackTop, this);
        _stackTop = _locale._locations.remove(_stackTop, _stackTop);

        return true;
    }

    boolean isAtLastPush() {
        assert _stackTop != Locations.NULL;

        return _locale._locations.isSamePos(_stackTop, this);
    }

    public boolean isAtEndOfLastPush() {
        assert _stackTop != Locations.NULL;

        return _locale._locations.isAtEndOf(_stackTop, this);
    }

    public void addToSelection(Cur that) {
        assert that != null && that.isNormal();
        assert isPositioned() && that.isPositioned();

        int i = _locale._locations.allocate(that);
        _selectionFirst = _locale._locations.insert(_selectionFirst, Locations.NULL, i);

        _selectionCount++;
    }

    public void addToSelection() {
        assert isPositioned();

        int i = _locale._locations.allocate(this);
        _selectionFirst = _locale._locations.insert(_selectionFirst, Locations.NULL, i);

        _selectionCount++;
    }

    private int selectionIndex(int i) {
        assert _selectionN >= -1 && i >= 0 && i < _selectionCount;

        if (_selectionN == -1) {
            _selectionN = 0;
            _selectionLoc = _selectionFirst;
        }

        while (_selectionN < i) {
            _selectionLoc = _locale._locations.next(_selectionLoc);
            _selectionN++;
        }

        while (_selectionN > i) {
            _selectionLoc = _locale._locations.prev(_selectionLoc);
            _selectionN--;
        }

        return _selectionLoc;
    }

    void removeFirstSelection() {
        final int i = 0;
        assert i < _selectionCount;

        int j = selectionIndex(i);

        // Update the nth selection indices to accomodate the deletion

        if (i < _selectionN) {
            _selectionN--;
        } else if (i == _selectionN) {
            _selectionN--;
            _selectionLoc = Locations.NULL;
        }

        _selectionFirst = _locale._locations.remove(_selectionFirst, j);

        _selectionCount--;
    }

    public int selectionCount() {
        return _selectionCount;
    }

    public void moveToSelection(int i) {
        assert i >= 0 && i < _selectionCount;

        _locale._locations.moveTo(selectionIndex(i), this);
    }

    public void clearSelection() {
        assert _selectionCount >= 0;

        while (_selectionCount > 0) {
            removeFirstSelection();
        }
    }

    public boolean toParent() {
        return toParent(false);
    }

    public boolean toParentRaw() {
        return toParent(true);
    }

    public Xobj getParent() {
        return getParent(false);
    }

    public Xobj getParentRaw() {
        return getParent(true);
    }

    public boolean hasParent() {
        assert isPositioned();

        if (_pos == END_POS || (_pos >= 1 && _pos < _xobj.posAfter())) {
            return true;
        }

        assert _pos == 0 || _xobj._parent != null;

        return _xobj._parent != null;
    }

    public Xobj getParentNoRoot() {
        assert isPositioned();

        if (_pos == END_POS || (_pos >= 1 && _pos < _xobj.posAfter())) {
            return _xobj;
        }

        assert _pos == 0 || _xobj._parent != null;

        if (_xobj._parent != null) {
            return _xobj._parent;
        }

        return null;
    }

    public Xobj getParent(boolean raw) {
        assert isPositioned();

        if (_pos == END_POS || (_pos >= 1 && _pos < _xobj.posAfter())) {
            return _xobj;
        }

        assert _pos == 0 || _xobj._parent != null;

        if (_xobj._parent != null) {
            return _xobj._parent;
        }

        if (raw || _xobj.isRoot()) {
            return null;
        }

        Cur r = _locale.tempCur();

        r.createRoot();

        Xobj root = r._xobj;

        r.next();
        moveNode(r);
        r.release();

        return root;
    }

    public boolean toParent(boolean raw) {
        Xobj parent = getParent(raw);

        if (parent == null) {
            return false;
        }

        moveTo(parent);

        return true;
    }

    public void toRoot() {
        Xobj xobj = _xobj;
        while (!xobj.isRoot()) {
            if (xobj._parent == null) {
                Cur r = _locale.tempCur();

                r.createRoot();

                Xobj root = r._xobj;

                r.next();
                moveNode(r);
                r.release();

                xobj = root;
                break;
            }
            xobj = xobj._parent;
        }
        moveTo(xobj);
    }

    public boolean hasText() {
        assert isNode();

        return _xobj.hasTextEnsureOccupancy();
    }

    public boolean hasAttrs() {
        assert isNode();

        return _xobj.hasAttrs();
    }

    public boolean hasChildren() {
        assert isNode();

        return _xobj.hasChildren();
    }

    public boolean toFirstChild() {
        assert isNode();

        if (!_xobj.hasChildren()) {
            return false;
        }

        for (Xobj x = _xobj._firstChild; ; x = x._nextSibling) {
            if (!x.isAttr()) {
                moveTo(x);
                return true;
            }
        }
    }

    public boolean toLastChild() {
        assert isNode();

        if (!_xobj.hasChildren()) {
            return false;
        }

        moveTo(_xobj._lastChild);

        return true;
    }

    public boolean toNextSibling() {
        assert isNode();

        if (_xobj.isAttr()) {
            if (_xobj._nextSibling != null && _xobj._nextSibling.isAttr()) {
                moveTo(_xobj._nextSibling);
                return true;
            }
        } else if (_xobj._nextSibling != null) {
            moveTo(_xobj._nextSibling);
            return true;
        }

        return false;
    }

    public void setValueAsQName(QName qname) {
        assert isNode();

        String value = qname.getLocalPart();
        String ns = qname.getNamespaceURI();

        String prefix =
            prefixForNamespace(
                ns, qname.getPrefix().length() > 0 ? qname.getPrefix() : null, true);

        if (prefix.length() > 0) {
            value = prefix + ":" + value;
        }

        setValue(value);
    }

    public void setValue(String value) {
        assert isNode();

        moveNodeContents(null, false);

        next();

        insertString(value);

        toParent();
    }

    public void removeFollowingAttrs() {
        assert isAttr();

        QName attrName = getName();

        push();

        if (toNextAttr()) {
            while (isAttr()) {
                if (getName().equals(attrName)) {
                    moveNode(null);
                } else if (!toNextAttr()) {
                    break;
                }
            }
        }

        pop();
    }

    public String getAttrValue(QName name) {
        String s = null;

        push();

        if (toAttr(name)) {
            s = getValueAsString();
        }

        pop();

        return s;
    }

    public void setAttrValueAsQName(QName value) {
        assert isContainer();

        final QName name = Locale._xsiType;

        if (value == null) {
            _xobj.removeAttr(name);
            return;
        }

        if (toAttr(name)) {
            removeFollowingAttrs();
        } else {
            next();
            createAttr(name);
        }
        setValueAsQName(value);
        toParent();
    }

    public boolean removeAttr(QName name) {
        assert isContainer();

        return _xobj.removeAttr(name);
    }

    public void setAttrValue(QName name, String value) {
        assert isContainer();

        _xobj.setAttr(name, value);
    }

    public boolean toAttr(QName name) {
        assert isNode();

        Xobj a = _xobj.getAttr(name);

        if (a == null) {
            return false;
        }

        moveTo(a);

        return true;
    }

    public boolean toFirstAttr() {
        assert isNode();

        Xobj firstAttr = _xobj.firstAttr();

        if (firstAttr == null) {
            return false;
        }

        moveTo(firstAttr);

        return true;
    }

    public boolean toLastAttr() {
        assert isNode();

        if (!toFirstAttr()) {
            return false;
        }

        //noinspection StatementWithEmptyBody
        while (toNextAttr()) {
        }

        return true;
    }

    public boolean toNextAttr() {
        assert isAttr() || isContainer();

        Xobj nextAttr = _xobj.nextAttr();

        if (nextAttr == null) {
            return false;
        }

        moveTo(nextAttr);

        return true;
    }

    @SuppressWarnings("UnusedReturnValue")
    public boolean toPrevAttr() {
        if (isAttr()) {
            if (_xobj._prevSibling == null) {
                moveTo(_xobj.ensureParent());
            } else {
                moveTo(_xobj._prevSibling);
            }

            return true;
        }

        prev();

        if (!isContainer()) {
            next();
            return false;
        }

        return toLastAttr();
    }

    @SuppressWarnings("UnusedReturnValue")
    public boolean skipWithAttrs() {
        assert isNode();

        if (skip()) {
            return true;
        }

        if (_xobj.isRoot()) {
            return false;
        }

        assert _xobj.isAttr();

        toParent();

        next();

        return true;
    }

    public boolean skip() {
        assert isNode();

        if (_xobj.isRoot()) {
            return false;
        }

        if (_xobj.isAttr()) {
            if (_xobj._nextSibling == null || !_xobj._nextSibling.isAttr()) {
                return false;
            }

            moveTo(_xobj._nextSibling, 0);
        } else {
            moveTo(getNormal(_xobj, _xobj.posAfter()), _posTemp);
        }

        return true;
    }

    public void toEnd() {
        assert isNode();

        moveTo(_xobj, END_POS);
    }

    public void moveToCharNode(CharNode node) {
        assert node.getDom() != null && node.getDom().locale() == _locale;

        moveToDom(node.getDom());

        CharNode n;

        _xobj.ensureOccupancy();

        n = _xobj._charNodesValue =
            updateCharNodes(_locale, _xobj, _xobj._charNodesValue, _xobj._cchValue);

        for (; n != null; n = n._next) {
            if (node == n) {
                moveTo(getNormal(_xobj, n._off + 1), _posTemp);
                return;
            }
        }

        n = _xobj._charNodesAfter =
            updateCharNodes(_locale, _xobj, _xobj._charNodesAfter, _xobj._cchAfter);

        for (; n != null; n = n._next) {
            if (node == n) {
                moveTo(getNormal(_xobj, n._off + _xobj._cchValue + 2), _posTemp);
                return;
            }
        }

        assert false;
    }

    @SuppressWarnings("UnusedReturnValue")
    public boolean prevWithAttrs() {
        if (prev()) {
            return true;
        }

        if (!isAttr()) {
            return false;
        }

        toParent();

        return true;
    }

    public boolean prev() {
        assert isPositioned();

        if (_xobj.isRoot() && _pos == 0) {
            return false;
        }

        if (_xobj.isAttr() && _pos == 0 && _xobj._prevSibling == null) {
            return false;
        }

        Xobj x = getDenormal();
        int p = _posTemp;

        assert p > 0;

        int pa = x.posAfter();

        if (p > pa) {
            p = pa;
        } else if (p == pa) {
            // Text after an attr is allowed only on the last attr,
            // and that text belongs to the parent container..
            //
            // If we're a thte end of the last attr, then we were just
            // inside the container, and we need to skip the attrs.

            if (x.isAttr() &&
                (x._cchAfter > 0 || x._nextSibling == null || !x._nextSibling.isAttr())) {
                x = x.ensureParent();
                p = 0;
            } else {
                p = END_POS;
            }
        } else if (p == pa - 1) {
            x.ensureOccupancy();
            p = x._cchValue > 0 ? 1 : 0;
        } else if (p > 1) {
            p = 1;
        } else {
            //noinspection ConstantConditions
            assert p == 1;
            p = 0;
        }

        moveTo(getNormal(x, p), _posTemp);

        return true;
    }

    @SuppressWarnings("UnusedReturnValue")
    public boolean next(boolean withAttrs) {
        return withAttrs ? nextWithAttrs() : next();
    }

    public boolean nextWithAttrs() {
        int k = kind();

        if (kindIsContainer(k)) {
            if (toFirstAttr()) {
                return true;
            }
        } else if (k == -ATTR) {
            if (next()) {
                return true;
            }

            toParent();

            if (!toParentRaw()) {
                return false;
            }
        }

        return next();
    }

    public boolean next() {
        assert isNormal();

        Xobj x = _xobj;
        int p = _pos;

        int pa = x.posAfter();

        if (p >= pa) {
            p = _xobj.posMax();
        } else if (p == END_POS) {
            if (x.isRoot() || (x.isAttr() && (x._nextSibling == null || !x._nextSibling.isAttr()))) {
                return false;
            }

            p = pa;
        } else if (p > 0) {
            assert x._firstChild == null || !x._firstChild.isAttr();

            if (x._firstChild != null) {
                x = x._firstChild;
                p = 0;
            } else {
                p = END_POS;
            }
        } else {
            assert p == 0;

            x.ensureOccupancy();

            p = 1;

            if (x._cchValue == 0) {
                if (x._firstChild != null) {
                    if (x._firstChild.isAttr()) {
                        Xobj a = x._firstChild;

                        while (a._nextSibling != null && a._nextSibling.isAttr()) {
                            a = a._nextSibling;
                        }

                        if (a._cchAfter > 0) {
                            x = a;
                            p = a.posAfter();
                        } else if (a._nextSibling != null) {
                            x = a._nextSibling;
                            p = 0;
                        }
                    } else {
                        x = x._firstChild;
                        p = 0;
                    }
                }
            }
        }

        moveTo(getNormal(x, p), _posTemp);

        return true;
    }

    int prevChars(int cch) {
        assert isPositioned();

        int cchLeft = cchLeft();

        if (cch < 0 || cch > cchLeft) {
            cch = cchLeft;
        }

        // Dang, I love this stmt :-)

        if (cch != 0) {
            moveTo(getNormal(getDenormal(), _posTemp - cch), _posTemp);
        }

        return cch;
    }

    int nextChars(int cch) {
        assert isPositioned();

        int cchRight = cchRight();

        if (cchRight == 0) {
            return 0;
        }

        if (cch < 0 || cch >= cchRight) {
            // Use next to not skip over children
            next();
            return cchRight;
        }

        moveTo(getNormal(_xobj, _pos + cch), _posTemp);

        return cch;
    }

    void setCharNodes(CharNode nodes) {
        assert nodes == null || _locale == nodes.locale();
        assert isPositioned();

        Xobj x = getDenormal();
        int p = _posTemp;

        assert !x.isRoot() || (p > 0 && p < x.posAfter());

        if (p >= x.posAfter()) {
            x._charNodesAfter = nodes;
        } else {
            x._charNodesValue = nodes;
        }

        for (; nodes != null; nodes = nodes._next) {
            nodes.setDom((Dom) x);
        }

        // No Need to notify text change or alter version, text nodes are
        // not part of the infoset
    }

    CharNode getCharNodes() {
        assert isPositioned();
        assert !isRoot();

        Xobj x = getDenormal();

        CharNode nodes;

        if (_posTemp >= x.posAfter()) {
            nodes = x._charNodesAfter =
                updateCharNodes(_locale, x, x._charNodesAfter, x._cchAfter);
        } else {
            x.ensureOccupancy();

            nodes = x._charNodesValue =
                updateCharNodes(_locale, x, x._charNodesValue, x._cchValue);
        }

        return nodes;
    }

    // private
    static CharNode updateCharNodes(Locale l, Xobj x, CharNode nodes, int cch) {
        assert nodes == null || nodes.locale() == l;

        CharNode node = nodes;
        int i = 0;

        while (node != null && cch > 0) {
            assert node.getDom() == x;

            if (node._cch > cch) {
                node._cch = cch;
            }

            node._off = i;
            i += node._cch;
            cch -= node._cch;

            node = node._next;
        }

        if (cch <= 0) {
            for (; node != null; node = node._next) {
                assert node.getDom() == x;

                if (node._cch != 0) {
                    node._cch = 0;
                }

                node._off = i;
            }
        } else {
            node = l.createTextNode();
            node.setDom((Dom) x);
            node._cch = cch;
            node._off = i;
            nodes = CharNode.appendNode(nodes, node);
        }

        return nodes;
    }

    final QName getXsiTypeName() {
        assert isNode();

        return _xobj.getXsiTypeName();
    }

    final void setXsiType(QName value) {
        assert isContainer();

        setAttrValueAsQName(value);
    }

    final String namespaceForPrefix(String prefix, boolean defaultAlwaysMapped) {
        return _xobj.namespaceForPrefix(prefix, defaultAlwaysMapped);
    }

    final String prefixForNamespace(String ns, String suggestion, boolean createIfMissing) {
        return
            (isContainer() ? _xobj : getParent()).
                prefixForNamespace(ns, suggestion, createIfMissing);
    }

    // Does the node at this cursor properly contain the position specified by the argument

    boolean contains(Cur that) {
        assert isNode();
        assert that != null && that.isPositioned();

        return _xobj.contains(that);
    }

    void insertString(String s) {
        if (s != null) {
            insertChars(s, 0, s.length());
        }
    }

    void insertChars(Object src, int off, int cch) {
        assert isPositioned() && !isRoot();
        assert CharUtil.isValid(src, off, cch);

        // Check for nothing to insert

        if (cch <= 0) {
            return;
        }

        _locale.notifyChange();

        // The only situation where I need to ensure occupancy is when I'm at the end of a node.
        // All other positions will require occupancy.  For example, if I'm at the beginning of a
        // node, then I will either insert in the after text of the previous sibling, or I will
        // insert in the value of the parent.  In the latter case, because the parent has a child,
        // it cannot be vacant.

        if (_pos == END_POS) {
            _xobj.ensureOccupancy();
        }

        // Get the denormailized Xobj and pos.  This is the Xobj which will actually receive
        // the new chars.  Note that a denormalized position can never be <= 0.

        Xobj x = getDenormal();
        int p = _posTemp;

        assert p > 0;

        // This will move "this" cursor to be after the inserted text. No worries, I'll update its
        // position after.  This insertChars takes care of all the appropriate invalidations
        // (passing true as last arg).

        x.insertCharsHelper(p, src, off, cch, true);

        // Reposition the cursor to be just before the newly inserted text.  It's current
        // position could have been shifted, or it may have been just before the end tag, or
        // normalized on another Xobj.

        moveTo(x, p);

        _locale._versionAll++;
    }

    // Move the chars just after this Cur to the "to" Cur.  If no "to" Cur is specified,
    // then remove the chars.

    Object moveChars(Cur to, int cchMove) {
        assert isPositioned();
        assert cchMove <= 0 || cchMove <= cchRight();
        assert to == null || (to.isPositioned() && !to.isRoot());

        if (cchMove < 0) {
            cchMove = cchRight();
        }

        // If we're instructed to move 0 characters, then return the null triple.

        if (cchMove == 0) {
            _offSrc = 0;
            _cchSrc = 0;

            return null;
        }

        // Here I record the triple of the chars to move.  I will return this.  No need to save
        // cch 'cause cchMove will be that value.

        Object srcMoved = getChars(cchMove);
        int offMoved = _offSrc;

        // Either I'm moving text from the value or the after text.  If after, then the container
        // must be occupied.  If in the value, because we're just before text, it must be occupied.

        assert isText() && (_pos >= _xobj.posAfter() ? _xobj._parent : _xobj).isOccupied();

        if (to == null) {
            // In this case, I'm removing chars vs moving them.  Normally I would like to blow
            // them away entirely, but if there are any references to those chars via a bookmark
            // I need to keep them alive.  I do this by moving these chars to a new root.  Note
            // that because Curs will stay behind, I don't have to check for them.

            for (Bookmark b = _xobj._bookmarks; b != null; b = b._next) {
                if (inChars(b, cchMove, false)) {
                    Cur c = _locale.tempCur();

                    c.createRoot();
                    c.next();

                    Object chars = moveChars(c, cchMove);

                    c.release();

                    return chars;
                }
            }
        } else {
            // If the target, "to", is inside or on the edge of the text to be moved, then this
            // is a no-op.  In this case, I still want to return the text "moved".
            //
            // Note how I move "to" and this cur around.  I move "to" to be at the beginning of the
            // chars moved and "this" to be at the end.  If the text were really moving to a
            // different location, then "to" would be at the beginning of the newly moved chars,
            // and "this" would be at the gap left by the newly removed chars.

            if (inChars(to, cchMove, true)) {
                // BUGBUG - may want to consider shuffling the interior cursors to the right just
                // like I move "this" to the right...

                to.moveToCur(this);
                nextChars(cchMove);

                _offSrc = offMoved;
                _cchSrc = cchMove;

                return srcMoved;
            }

            // Copy the chars here, I'll remove the originals next

            to.insertChars(srcMoved, offMoved, cchMove);
        }

        // Notice that I can delay the general change notification to this point because any
        // modifications up to this point are made by calling other high level operations which
        // generate this notification themselves.  Also, no need to notify of general change in
        // the "to" locale because the insertion of chars above handles that.

        _locale.notifyChange();

        //
        //if ( _xobj != null )
        {
            if (to == null) {
                _xobj.removeCharsHelper(_pos, cchMove, null, NO_POS, false, true);
            } else {
                _xobj.removeCharsHelper(_pos, cchMove, to._xobj, to._pos, false, true);
            }
        }

        // Need to update the position of this cursor even though it did not move anywhere.  This
        // needs to happen because it may not be properly normalized anymore.  Note that because
        // of the removal of the text, this cur may not be normal any more, thus I call moveTo
        // which does not assume this.

        _locale._versionAll++;

        _offSrc = offMoved;
        _cchSrc = cchMove;

        return srcMoved;
    }

    void moveNode(Cur to) {
        assert isNode() && !isRoot();
        assert to == null || to.isPositioned();
        assert to == null || !contains(to);
        assert to == null || !to.isRoot();

        // TODO - should assert that is an attr is being moved, it is ok there


        // Record the node to move and skip this cur past it.  This moves this cur to be after
        // the move to move/remove -- it's final resting place.  The only piece of information
        // about the source of the move is the node itself.

        Xobj x = _xobj;

        skip();

        // I call another function here to move the node.  I do this because  I don't have to
        // worry about messing with "this" here given that it not should be treated like any other
        // cursor after this point.

        moveNode(x, to);
    }

    // Moves text from one place to another in a low-level way, used as a helper for the higher
    // level functions.  Takes care of moving bookmarks and cursors.  In the high level content
    // manipulation functions, cursors do not follow content, but this helper moves them.  The
    // arguments are denormalized.  The Xobj's must be different from eachother but from the same
    // locale.  The destination must not be not be vacant.

    private static void transferChars(Xobj xFrom, int pFrom, Xobj xTo, int pTo, int cch) {
        assert xFrom != xTo;
        assert xFrom._locale == xTo._locale;
        assert pFrom > 0 && pFrom < xFrom.posMax();
        assert pTo > 0 && pTo <= xTo.posMax();
        assert cch > 0 && cch <= xFrom.cchRight(pFrom);
        assert pTo >= xTo.posAfter() || xTo.isOccupied();

        // Copy the chars from -> to without performing any invalidations.  This will scoot curs
        // and marks around appropriately.  Note that I get the cars with getCharsHelper which
        // does not check for normalization because the state of the tree at this moment may not
        // exactly be "correct" here.

        xTo.insertCharsHelper(
            pTo, xFrom.getCharsHelper(pFrom, cch),
            xFrom._locale._offSrc, xFrom._locale._cchSrc, false);

        xFrom.removeCharsHelper(pFrom, cch, xTo, pTo, true, false);
    }

    // Moves the node x to "to", or removes it if to is null.

    static void moveNode(Xobj x, Cur to) {
        assert x != null && !x.isRoot();
        assert to == null || to.isPositioned();
        assert to == null || !x.contains(to);
        assert to == null || !to.isRoot();

        if (to != null) {
            // Before I go much further, I want to make sure that if "to" is in the container of
            // a vacant node, I get it occupied.  I do not need to worry about the source being
            // vacant.

            if (to._pos == END_POS) {
                to._xobj.ensureOccupancy();
            }

            // See if the destination is on the edge of the node to be moved (a no-op).  It is
            // illegal to call this fcn when to is contained within the node to be moved.  Note
            // that I make sure that to gets oved to the beginning of the node.  The position of
            // to in all operations should leave to just before the content moved/inserted.

            if ((to._pos == 0 && to._xobj == x) || to.isJustAfterEnd(x)) {
                // TODO - should shuffle contained curs to the right???

                to.moveTo(x);
                return;
            }
        }

        // Notify the locale(s) about the change I am about to make.

        x._locale.notifyChange();

        x._locale._versionAll++;
        x._locale._versionSansText++;

        if (to != null && to._locale != x._locale) {
            to._locale.notifyChange();

            to._locale._versionAll++;
            to._locale._versionSansText++;
        }

        // Node is going away.  Invalidate the parent (the text around the node is merging).
        // Also, this node may be an attribute -- invalidate special attrs ...

        if (x.isAttr()) {
            x.invalidateSpecialAttr(to == null ? null : to.getParentRaw());
        } else {
            if (x._parent != null) {
                x._parent.invalidateUser();
            }

            if (to != null && to.hasParent()) {
                to.getParent().invalidateUser();
            }
        }

        // If there is any text after x, I move it to be before x.  This frees me to extract x
        // and it's contents with out this text coming along for the ride.  Note that if this
        // node is the last attr and there is text after it, transferText will move the text
        // to a potential previous attr.  This is an invalid state for a short period of time.
        // I need to move this text away here so that when I walk the tree next, *all* curs
        // embedded in this node or deeper will be moved off this node.

        if (x._cchAfter > 0) {
            transferChars(x, x.posAfter(), x.getDenormal(0), x.posTemp(), x._cchAfter);
        }

        assert x._cchAfter == 0;

        // Walk the node tree, moving curs out, disconnecting users and relocating to a, possibly,
        // new locale.  I embed the cursors in this locale before itersting to just cause the
        // embed to happen once.

        x._locale.embedCurs();

        for (Xobj y = x; y != null; y = y.walk(x, true)) {
            while (y._embedded != null) {
                y._embedded.moveTo(x.getNormal(x.posAfter()));
            }

            y.disconnectUser();

            if (to != null) {
                y._locale = to._locale;
            }
        }

        // Now, actually remove the node

        x.removeXobj();

        // Now, if there is a destination, insert the node there and shuffle the text in the
        // vicinity of the destination appropriately.

        if (to != null) {
            // To know where I should insert/append the node to move, I need to see where "to"
            // would be if there were no text after it.  However, I need to keep "to" where it
            // is when I move the text after it later.

            Xobj here = to._xobj;
            boolean append = to._pos != 0;

            int cchRight = to.cchRight();

            if (cchRight > 0) {
                to.push();
                to.next();
                here = to._xobj;
                append = to._pos != 0;
                to.pop();
            }

            if (append) {
                here.appendXobj(x);
            } else {
                here.insertXobj(x);
            }

            // The only text I need to move is that to the right of "to".  Even considering all
            // the cases where an attribute is involed!

            if (cchRight > 0) {
                transferChars(to._xobj, to._pos, x, x.posAfter(), cchRight);
            }

            to.moveTo(x);
        }
    }

    void moveNodeContents(Cur to, boolean moveAttrs) {
        assert _pos == 0;
        assert to == null || !to.isRoot();

        // By calling this helper, I do not have to deal with this Cur any longer.  Basically,
        // this Cur is out of the picture, it behaves like any other cur at this point.

        moveNodeContents(_xobj, to, moveAttrs);
    }

    static void moveNodeContents(Xobj x, Cur to, boolean moveAttrs) {
        // TODO - should assert that is an attr is being moved, it is ok there

        assert to == null || !to.isRoot();

        // Collect a bit of information about the contents to move first.  Note that the collection
        // of this info must not cause a vacant value to become occupied.

        boolean hasAttrs = x.hasAttrs();
        boolean noSubNodesToMove = !x.hasChildren() && (!moveAttrs || !hasAttrs);

        // Deal with the cases where only text is involved in the move

        if (noSubNodesToMove) {
            // If we're vacant and there is no place to move a potential value, then I can avoid
            // acquiring the text from the TypeStoreUser.  Otherwise, there may be text here I
            // need to move somewhere else.

            if (x.isVacant() && to == null) {
                x.clearBit(Xobj.VACANT);

                x.invalidateUser();
                x.invalidateSpecialAttr(null);
                x._locale._versionAll++;
            } else if (x.hasTextEnsureOccupancy()) {
                Cur c = x.tempCur();
                c.next();
                c.moveChars(to, -1);
                c.release();
            }

            return;
        }

        // Here I check to see if "to" is just inside x.  In this case this is a no-op.  Note that
        // the value of x may still be vacant.

        if (to != null) {
            // Quick check of the right edge.  If it is there, I need to move "to" to the left edge
            // so that it is positioned at the beginning of the "moved" content.

            if (x == to._xobj && to._pos == END_POS) {
                // TODO - shuffle interior curs?

                to.moveTo(x);
                to.next(moveAttrs && hasAttrs);

                return;
            }

            // Here I need to see if to is at the left edge.  I push to's current position and
            // then navigate it to the left edge then compare it to the pushed position...
            // Note: gotta be careful to make sure to and x are not in different locales, curs
            // may not go to a different locale.

            boolean isAtLeftEdge = false;

            if (to._locale == x._locale) {
                to.push();
                to.moveTo(x);
                to.next(moveAttrs && hasAttrs);
                isAtLeftEdge = to.isAtLastPush();
                to.pop();
            }

            // TODO - shuffle interior curs?

            if (isAtLeftEdge) {
                return;
            }

            // Now, after dealing with the edge condition, I can assert that to is not inside x

            assert !x.contains(to);

            // So, at this point, I've taken case of the no-op cases and the movement of just text.
            // Also, to must be occupied because I took care of the text only and nothing to move
            // cases.

            assert to.getParent().isOccupied();
        }

        // TODO - did I forget to put a changeNotification here?  Look more closely ...

        // Deal with the value text of x which is either on x or the last attribute of x.
        // I need to get it out of the way to properly deal with the walk of the contents.
        // In order to reposition "to" properly later, I need to record how many chars were moved.

        int valueMovedCch = 0;

        if (x.hasTextNoEnsureOccupancy()) {
            Cur c = x.tempCur();
            c.next();
            c.moveChars(to, -1);
            c.release();

            if (to != null) {
                to.nextChars(valueMovedCch = c._cchSrc);
            }
        }

        // Now, walk all the contents, invalidating special attrs, reportioning cursors,
        // disconnecting users and relocating to a potentially different locale.  Because I moved
        // the value text above, no top level attrs should have any text.

        x._locale.embedCurs();

        Xobj firstToMove = x.walk(x, true);
        boolean sawBookmark = false;

        for (Xobj y = firstToMove; y != null; y = y.walk(x, true)) {
            if (y._parent == x && y.isAttr()) {
                assert y._cchAfter == 0;

                if (!moveAttrs) {
                    firstToMove = y._nextSibling;
                    continue;
                }

                y.invalidateSpecialAttr(to == null ? null : to.getParent());
            }

            for (Cur c; (c = y._embedded) != null; ) {
                c.moveTo(x, END_POS);
            }

            y.disconnectUser();

            if (to != null) {
                y._locale = to._locale;
            }

            sawBookmark = sawBookmark || y._bookmarks != null;
        }

        Xobj lastToMove = x._lastChild;

        // If there were any bookmarks in the tree to remove, to preserve the content that these
        // bookmarks reference, move the contents to a new root.  Note that I already moved the
        // first piece of text above elsewhere.  Note: this has the effect of keeping all of the
        // contents alive even if there is one bookmark deep into the tree.  I should really
        // disband all the content, except for the pieces which are bookmarked.

        Cur surragateTo = null;

        if (sawBookmark && to == null) {
            surragateTo = to = x._locale.tempCur();
            to.createRoot();
            to.next();
        }

        // Perform the rest of the invalidations.  If only attrs are moving, then no user
        // invalidation needed.  If I've move text to "to" already, no need to invalidate
        // again.

        if (!lastToMove.isAttr()) {
            x.invalidateUser();
        }

        x._locale._versionAll++;
        x._locale._versionSansText++;

        if (to != null && valueMovedCch == 0) {
            to.getParent().invalidateUser();
            to._locale._versionAll++;
            to._locale._versionSansText++;
        }

        // Remove the children and, if needed, move them

        x.removeXobjs(firstToMove, lastToMove);

        if (to != null) {
            // To know where I should insert/append the contents to move, I need to see where "to"
            // would be if there were no text after it.

            Xobj here = to._xobj;
            boolean append = to._pos != 0;

            int cchRight = to.cchRight();

            if (cchRight > 0) {
                to.push();
                to.next();
                here = to._xobj;
                append = to._pos != 0;
                to.pop();
            }

            // Now, I have to shuffle the text around "to" in special ways.  A complication is
            // the insertion of attributes.  First, if I'm inserting attrs here then, logically,
            // there can be no text to the left because attrs can only live after another attr
            // or just inside a container.  So, If attrs are being inserted and there is value
            // text on the target container, I will need to move this value text to be after
            // the lew last attribute.  Note that this value text may already live on a current
            // last attr (before the inserting).  Also, I need to figure this all out before I
            // move the text after "to" because this text may end up being sent to the same place
            // as the containers value text when the last new node being inserted is an attr!
            // Whew!

            if (firstToMove.isAttr()) {
                Xobj lastNewAttr = firstToMove;

                while (lastNewAttr._nextSibling != null && lastNewAttr._nextSibling.isAttr()) {
                    lastNewAttr = lastNewAttr._nextSibling;
                }

                // Get to's parnet now before I potentially move him with the next transfer

                Xobj y = to.getParent();

                if (cchRight > 0) {
                    transferChars(to._xobj, to._pos, lastNewAttr, lastNewAttr.posMax(), cchRight);
                }

                if (y.hasTextNoEnsureOccupancy()) {
                    int p, cch;

                    if (y._cchValue > 0) {
                        p = 1;
                        cch = y._cchValue;
                    } else {
                        y = y.lastAttr();
                        assert (y != null);
                        p = y.posAfter();
                        cch = y._cchAfter;
                    }

                    transferChars(y, p, lastNewAttr, lastNewAttr.posAfter(), cch);
                }
            } else if (cchRight > 0) {
                transferChars(to._xobj, to._pos, lastToMove, lastToMove.posMax(), cchRight);
            }

            // After mucking with the text, splice the new tree in

            if (append) {
                here.appendXobjs(firstToMove, lastToMove);
            } else {
                here.insertXobjs(firstToMove, lastToMove);
            }

            // Position "to" to be at the beginning of the newly inserted contents

            to.moveTo(firstToMove);
            to.prevChars(valueMovedCch);
        }

        // If I consed up a to, release it here

        if (surragateTo != null) {
            surragateTo.release();
        }
    }

    protected final Bookmark setBookmark(Object key, Object value) {
        assert isNormal();
        assert key != null;

        return _xobj.setBookmark(_pos, key, value);
    }

    Object getBookmark(Object key) {
        assert isNormal();
        assert key != null;

        for (Bookmark b = _xobj._bookmarks; b != null; b = b._next) {
            if (b._pos == _pos && b._key == key) {
                return b._value;
            }
        }

        return null;
    }

    int firstBookmarkInChars(Object key, int cch) {
        assert isNormal();
        assert key != null;
        assert cch > 0;
        assert cch <= cchRight();

        int d = -1;

        if (isText()) {
            for (Bookmark b = _xobj._bookmarks; b != null; b = b._next) {
                if (b._key == key && inChars(b, cch, false)) {
                    d = (d == -1 || b._pos - _pos < d) ? b._pos - _pos : d;
                }
            }
        }

        return d;
    }

    int firstBookmarkInCharsLeft(Object key, int cch) {
        assert isNormal();
        assert key != null;
        assert cch > 0;
        assert cch <= cchLeft();

        int d = -1;

        if (cchLeft() > 0) {
            Xobj x = getDenormal();
            int p = _posTemp - cch;

            for (Bookmark b = x._bookmarks; b != null; b = b._next) {
                if (b._key == key && x.inChars(p, b._xobj, b._pos, cch, false)) {
                    d = (d == -1 || b._pos - p < d) ? b._pos - p : d;
                }
            }
        }

        return d;
    }

    String getCharsAsString() {
        assert isNormal() && _xobj != null;

        return getCharsAsString(WS_PRESERVE);
    }

    String getCharsAsString(int wsr) {
        return _xobj.getCharsAsString(_pos, -1, wsr);
    }

    String getValueAsString(int wsr) {
        assert isNode();

        return _xobj.getValueAsString(wsr);
    }

    String getValueAsString() {
        assert isNode();
        assert !hasChildren();

        return _xobj.getValueAsString();
    }

    Object getChars(int cch) {
        assert isPositioned();

        return _xobj.getChars(_pos, cch, this);
    }

    Object getFirstChars() {
        assert isNode();

        Object src = _xobj.getFirstChars();

        _offSrc = _locale._offSrc;
        _cchSrc = _locale._cchSrc;

        return src;
    }

    void copyNode(Cur to) {
        assert to != null;
        assert isNode();

        Xobj copy = _xobj.copyNode(to._locale);

        // TODO - in the moveNode case, I would not have to walk the tree for cursors ... optimize

        if (to.isPositioned()) {
            Cur.moveNode(copy, to);
        } else {
            to.moveTo(copy);
        }
    }

    public Cur weakCur(Object o) {
        Cur c = _locale.weakCur(o);
        c.moveToCur(this);
        return c;
    }

    Cur tempCur() {
        String id = null;
        Cur c = _locale.tempCur(id);
        c.moveToCur(this);
        return c;
    }

    private Cur tempCur(Xobj x, int p) {
        assert (x == null || _locale == x._locale);
        assert (x != null || p == NO_POS);

        Cur c = _locale.tempCur();

        if (x != null) {
            c.moveTo(getNormal(x, p), _posTemp);
        }

        return c;
    }

    // Is a cursor (c) in the chars defined by cch chars after where this Cur is positioned.
    // Is inclusive on the left, and inclusive/exclusive on the right depending on the value
    // of includeEnd.

    boolean inChars(Cur c, int cch, boolean includeEnd) {
        assert isPositioned() && isText() && cchRight() >= cch;
        assert c.isNormal();

        return _xobj.inChars(_pos, c._xobj, c._pos, cch, includeEnd);
    }

    boolean inChars(Bookmark b, int cch, boolean includeEnd) {
        assert isPositioned() && isText() && cchRight() >= cch;
        assert b._xobj.isNormal(b._pos);

        return _xobj.inChars(_pos, b._xobj, b._pos, cch, includeEnd);
    }

    // Can't be static because I need to communicate pos in _posTemp :-(
    // I wish I had multiple return vars ...

    private Xobj getNormal(Xobj x, int p) {
        Xobj nx = x.getNormal(p);
        _posTemp = x._locale._posTemp;
        return nx;
    }

    private Xobj getDenormal() {
        assert isPositioned();

        return getDenormal(_xobj, _pos);
    }

    private Xobj getDenormal(Xobj x, int p) {
        Xobj dx = x.getDenormal(p);
        _posTemp = x._locale._posTemp;
        return dx;
    }

    // May throw IllegalArgumentException if can't change the type

    void setType(SchemaType type) {
        setType(type, true);
    }

    void setType(SchemaType type, boolean complain) {
        assert type != null;
        assert isUserNode();

        TypeStoreUser user = peekUser();

        if (user != null && user.get_schema_type() == type) {
            return;
        }

        if (isRoot()) {
            _xobj.setStableType(type);
            return;
        }

        // Gotta get the parent user to make sure this type is ok here

        TypeStoreUser parentUser = _xobj.ensureParent().getUser();

        // One may only set the type of an attribute to its 'natural' type because
        // attributes cannot take advantage of the xsiType attribute.

        if (isAttr()) {
            if (complain && parentUser.get_attribute_type(getName()) != type) {
                throw new IllegalArgumentException("Can't set type of attribute to " + type.toString());
            }

            return;
        }

        assert isElem();

        // First check to see if this type can be here sans xsi:type.
        // If so, make sure there is no xsi:type

        if (parentUser.get_element_type(getName(), null) == type) {
            removeAttr(Locale._xsiType);
            return;
        }

        // If the desired type has no name, then it cannot be
        // referenced via xsi:type

        QName typeName = type.getName();

        if (typeName == null) {
            if (complain) {
                throw new IllegalArgumentException("Can't set type of element, type is un-named");
            } else {
                return;
            }
        }

        // See if setting xsiType would result in the target type

        if (parentUser.get_element_type(getName(), typeName) != type) {
            if (complain) {
                throw new IllegalArgumentException("Can't set type of element, invalid type");
            } else {
                return;
            }
        }

        setAttrValueAsQName(typeName);
    }

    void setSubstitution(QName name, SchemaType type) {
        assert name != null;
        assert type != null;
        assert isUserNode();

        TypeStoreUser user = peekUser();

        if (user != null && user.get_schema_type() == type && name.equals(getName())) {
            return;
        }

        if (isRoot()) {
            // If this is the root node, we can't set its name, so the whole
            // operation is aborted
            return;
        }

        // Gotta get the parent user to make sure this type is ok here

        TypeStoreUser parentUser = _xobj.ensureParent().getUser();

        // One may only set the type of an attribute to its 'natural' type because
        // attributes cannot take advantage of the xsiType attribute.

        if (isAttr()) {
            // Can't use substitution with attributes
            return;
        }

        assert isElem();

        // First check to see if this type can be here sans xsi:type.
        // If so, make sure there is no xsi:type

        if (parentUser.get_element_type(name, null) == type) {
            setName(name);
            removeAttr(Locale._xsiType);
            return;
        }

        // If the desired type has no name, then it cannot be
        // referenced via xsi:type

        QName typeName = type.getName();

        if (typeName == null) {
            // Can't set xsi:type on element, type is un-named
            return;
        }

        // See if setting xsiType would result in the target type

        if (parentUser.get_element_type(name, typeName) != type) {
            // Can't set xsi:type on element, invalid type
            return;
        }

        setName(name);
        setAttrValueAsQName(typeName);
    }

    TypeStoreUser peekUser() {
        assert isUserNode();

        return _xobj._user;
    }

    public XmlObject getObject() {
        return isUserNode() ? (XmlObject) getUser() : null;
    }

    TypeStoreUser getUser() {
        assert isUserNode();

        return _xobj.getUser();
    }

    public Dom getDom() {
        assert isNormal();
        assert isPositioned();

        if (isText()) {
            int cch = cchLeft();

            for (CharNode cn = getCharNodes(); ; cn = cn._next) {
                if ((cch -= cn._cch) < 0) {
                    return cn;
                }
            }
        }

        return _xobj.getDom();
    }

    public void release() {
        if (_tempFrame >= 0) {
            if (_nextTemp != null) {
                _nextTemp._prevTemp = _prevTemp;
            }

            if (_prevTemp == null) {
                _locale._tempFrames[_tempFrame] = _nextTemp;
            } else {
                _prevTemp._nextTemp = _nextTemp;
            }

            _prevTemp = _nextTemp = null;
            _tempFrame = -1;
        }

        if (_state != POOLED && _state != DISPOSED) {
            // Clean up any state

            while (_stackTop != -1) {
                popButStay();
            }

            clearSelection();

            _id = null;

            // Unposition

            moveToCur(null);

            assert isNormal();

            assert _xobj == null;
            assert _pos == NO_POS;

            // Release weak reference and attacked value

            if (_ref != null) {
                _ref.clear();
                _ref._cur = null;
            }

            _ref = null;

            // Unregister and either diapose of cursor or add it back to pool

            assert _state == REGISTERED;
            _locale._registered = listRemove(_locale._registered);

            if (_locale._curPoolCount < 16) {
                _locale._curPool = listInsert(_locale._curPool);
                _state = POOLED;
                _locale._curPoolCount++;
            } else {
                _locale = null;
                _state = DISPOSED;
            }
        }
    }

    boolean isOnList(Cur head) {
        for (; head != null; head = head._next) {
            if (head == this) {
                return true;
            }
        }

        return false;
    }

    Cur listInsert(Cur head) {
        assert _next == null && _prev == null;

        if (head == null) {
            head = _prev = this;
        } else {
            _prev = head._prev;
            head._prev = head._prev._next = this;
        }

        return head;
    }

    Cur listRemove(Cur head) {
        assert _prev != null && isOnList(head);

        if (_prev == this) {
            head = null;
        } else {
            if (head == this) {
                head = _next;
            } else {
                _prev._next = _next;
            }

            if (_next == null) {
                if (head != null) {
                    head._prev = _prev;
                }
            } else {
                _next._prev = _prev;
                _next = null;
            }
        }

        _prev = null;
        assert _next == null;

        return head;
    }

//    boolean isNormal ( Cur that )
//    {
//        return isNormal() && (that == null || (_locale == that._locale && that.isNormal()));
//    }

    boolean isNormal() {
        if (_state == POOLED || _state == DISPOSED) {
            return false;
        }

        if (_xobj == null) {
            return _pos == NO_POS;
        }

        if (!_xobj.isNormal(_pos)) {
            return false;
        }

        if (_state == EMBEDDED) {
            return isOnList(_xobj._embedded);
        }

        assert _state == REGISTERED;

        return isOnList(_locale._registered);
    }

    public static final class CurLoadContext extends LoadContext {
        public CurLoadContext(Locale l, XmlOptions options) {
            options = XmlOptions.maskNull(options);

            _locale = l;

            _charUtil =
                options.isLoadUseLocaleCharUtil()
                    ? _locale.getCharUtil()
                    : CharUtil.getThreadLocalCharUtil();

            _frontier = createDomDocumentRootXobj(_locale);
            _after = false;

            _lastXobj = _frontier;
            _lastPos = 0;

            _replaceDocElem = options.getLoadReplaceDocumentElement();
            _discardDocElem = options.hasOption(XmlOptions.XmlOptionsKeys.LOAD_REPLACE_DOCUMENT_ELEMENT);

            _stripWhitespace = options.isSetLoadStripWhitespace();
            _stripComments = options.isLoadStripComments();
            _stripProcinsts = options.isLoadStripProcinsts();

            _substituteNamespaces = options.getLoadSubstituteNamespaces();
            _additionalNamespaces = options.getLoadAdditionalNamespaces();

            _locale._versionAll++;
            _locale._versionSansText++;
        }

        //
        // Really primitive load context operations
        //

        private void start(Xobj xo) {
            assert _frontier != null;
            assert !_after || _frontier._parent != null;

            flushText();

            if (_after) {
                _frontier = _frontier._parent;
                _after = false;
            }

            _frontier.appendXobj(xo);
            _frontier = xo;

            _lastXobj = xo;
            _lastPos = 0;
        }

        private void end() {
            assert _frontier != null;
            assert !_after || _frontier._parent != null;

            flushText();

            if (_after) {
                _frontier = _frontier._parent;
            } else {
                _after = true;
            }

            _lastXobj = _frontier;
            _lastPos = END_POS;
        }

        private void text(Object src, int off, int cch) {
            if (cch <= 0) {
                return;
            }

            _lastXobj = _frontier;
            _lastPos = _frontier._cchValue + 1;

            if (_after) {
                _lastPos += _frontier._cchAfter + 1;

                _frontier._srcAfter =
                    _charUtil.saveChars(
                        src, off, cch,
                        _frontier._srcAfter, _frontier._offAfter, _frontier._cchAfter);

                _frontier._offAfter = _charUtil._offSrc;
                _frontier._cchAfter = _charUtil._cchSrc;

            } else {
                _frontier._srcValue =
                    _charUtil.saveChars(
                        src, off, cch,
                        _frontier._srcValue, _frontier._offValue, _frontier._cchValue);

                _frontier._offValue = _charUtil._offSrc;
                _frontier._cchValue = _charUtil._cchSrc;
            }
        }

        private void flushText() {
            if (_stripWhitespace) {
                if (_after) {
                    _frontier._srcAfter =
                        _charUtil.stripRight(
                            _frontier._srcAfter, _frontier._offAfter, _frontier._cchAfter);

                    _frontier._offAfter = _charUtil._offSrc;
                    _frontier._cchAfter = _charUtil._cchSrc;
                } else {
                    _frontier._srcValue =
                        _charUtil.stripRight(
                            _frontier._srcValue, _frontier._offValue, _frontier._cchValue);

                    _frontier._offValue = _charUtil._offSrc;
                    _frontier._cchValue = _charUtil._cchSrc;
                }
            }
        }

        private Xobj parent() {
            return _after ? _frontier._parent : _frontier;
        }

        private QName checkName(QName name, boolean local) {
            if (_substituteNamespaces != null && (!local || name.getNamespaceURI().length() > 0)) {
                String substituteUri = _substituteNamespaces.get(name.getNamespaceURI());

                if (substituteUri != null) {
                    name = _locale.makeQName(substituteUri, name.getLocalPart(), name.getPrefix());
                }
            }

            return name;
        }

        protected void startDTD(String name, String publicId, String systemId) {
            _doctypeName = name;
            _doctypePublicId = publicId;
            _doctypeSystemId = systemId;
        }

        protected void endDTD() {
        }

        protected void startElement(QName name) {
            start(createElementXobj(_locale, checkName(name, false), parent()._name));
            _stripLeft = true;
        }

        protected void endElement() {
            assert parent().isElem();

            end();
            _stripLeft = true;
        }

        protected void xmlns(String prefix, String uri) {
            assert parent().isContainer();
            // BUGBUG - should assert there that there is no text before this attr

            // Namespace attrs are different than regular attrs -- I don't change their name,
            // I change their value!

            if (_substituteNamespaces != null) {
                String substituteUri = _substituteNamespaces.get(uri);

                if (substituteUri != null) {
                    uri = substituteUri;
                }
            }

            Xobj x = new AttrXobj(_locale, _locale.createXmlns(prefix));

            start(x);
            text(uri, 0, uri.length());
            end();

            _lastXobj = x;
            _lastPos = 0;
        }

        public void attr(QName name, String value) {
            assert parent().isContainer();
            // BUGBUG - should assert there that there is no text before this attr

            QName parentName = _after ?
                _lastXobj._parent.getQName() : _lastXobj.getQName();
            boolean isId = isAttrOfTypeId(name, parentName);

            Xobj x = isId ?
                new AttrIdXobj(_locale, checkName(name, true)) :
                new AttrXobj(_locale, checkName(name, true));
            start(x);
            text(value, 0, value.length());
            end();
            if (isId) {
                Cur c1 = x.tempCur();
                c1.toRoot();
                Xobj doc = c1._xobj;
                c1.release();
                if (doc instanceof DocumentXobj) {
                    ((DocumentXobj) doc).addIdElement(value,
                        x._parent.getDom());
                }
            }
            _lastXobj = x;
            _lastPos = 0;
        }

        protected void attr(String local, String uri, String prefix, String value) {
            attr(_locale.makeQName(uri, local, prefix), value);
        }

        protected void procInst(String target, String value) {
            if (!_stripProcinsts) {
                Xobj x = new ProcInstXobj(_locale, target);

                start(x);
                text(value, 0, value.length());
                end();

                _lastXobj = x;
                _lastPos = 0;
            }
            _stripLeft = true;
        }

        protected void comment(String comment) {
            if (!_stripComments) {
                comment(comment, 0, comment.length());
            }
            _stripLeft = true;
        }

        protected void comment(char[] chars, int off, int cch) {
            if (!_stripComments) {
                comment(
                    _charUtil.saveChars(chars, off, cch),
                    _charUtil._offSrc, _charUtil._cchSrc);
            }
            _stripLeft = true;
        }

        private void comment(Object src, int off, int cch) {
            Xobj x = new CommentXobj(_locale);

            start(x);
            text(src, off, cch);
            end();

            _lastXobj = x;
            _lastPos = 0;
        }

        private boolean _stripLeft = true;

        private void stripText(Object src, int off, int cch) {
            if (_stripWhitespace) {
                // this is to avoid bug in cases like <company>Procter &amp; Gamble</company>
                if (_stripLeft) {
                    src = _charUtil.stripLeft(src, off, cch);
                    _stripLeft = false;
                    off = _charUtil._offSrc;
                    cch = _charUtil._cchSrc;
                }
            }

            text(src, off, cch);
        }

        protected void text(String s) {
            if (s == null) {
                return;
            }

            stripText(s, 0, s.length());
        }

        protected void text(char[] src, int off, int cch) {
            stripText(src, off, cch);
        }

        protected void bookmark(XmlBookmark bm) {
            _lastXobj.setBookmark(_lastPos, bm.getKey(), bm);
        }

        protected void bookmarkLastNonAttr(XmlBookmark bm) {
            if (_lastPos > 0 || !_lastXobj.isAttr()) {
                _lastXobj.setBookmark(_lastPos, bm.getKey(), bm);
            } else {
                assert _lastXobj._parent != null;

                _lastXobj._parent.setBookmark(0, bm.getKey(), bm);
            }
        }

        protected void bookmarkLastAttr(QName attrName, XmlBookmark bm) {
            if (_lastPos == 0 && _lastXobj.isAttr()) {
                assert _lastXobj._parent != null;

                Xobj a = _lastXobj._parent.getAttr(attrName);

                if (a != null) {
                    a.setBookmark(0, bm.getKey(), bm);
                }
            }
        }

        protected void lineNumber(int line, int column, int offset) {
            _lastXobj.setBookmark(
                _lastPos,
                XmlLineNumber.class,
                new XmlLineNumber(line, column, offset));
        }

        protected void abort() {
            _stripLeft = true;
            while (!parent().isRoot()) {
                end();
            }

            finish().release();
        }

        public Cur finish() {
            flushText();

            if (_after) {
                _frontier = _frontier._parent;
            }

            assert _frontier != null && _frontier._parent == null && _frontier.isRoot();

            Cur c = _frontier.tempCur();

            if (!Locale.toFirstChildElement(c)) {
                return c;
            }

            // See if the document element is a fragment

            boolean isFrag = Locale.isFragmentQName(c.getName());

            if (_discardDocElem || isFrag) {
                if (_replaceDocElem != null) {
                    c.setName(_replaceDocElem);
                } else {
                    // Remove the content around the element to remove so that that content
                    // does not appear to have been the contents of the removed element.

                    //noinspection StatementWithEmptyBody
                    while (c.toParent()) {
                    }

                    c.next();

                    while (!c.isElem()) {
                        if (c.isText()) {
                            c.moveChars(null, -1);
                        } else {
                            c.moveNode(null);
                        }
                    }

                    assert c.isElem();
                    c.skip();

                    while (!c.isFinish()) {
                        if (c.isText()) {
                            c.moveChars(null, -1);
                        } else {
                            c.moveNode(null);
                        }
                    }

                    c.toParent();

                    c.next();

                    assert c.isElem();

                    Cur c2 = c.tempCur();

                    c.moveNodeContents(c, true);

                    c.moveToCur(c2);

                    c2.release();

                    c.moveNode(null);
                }

                // Remove the fragment namespace decl

                if (isFrag) {
                    c.moveTo(_frontier);

                    if (c.toFirstAttr()) {
                        for (; ; ) {
                            if (c.isXmlns() && c.getXmlnsUri().equals(Locale._openFragUri)) {
                                c.moveNode(null);

                                if (!c.isAttr()) {
                                    break;
                                }
                            } else if (!c.toNextAttr()) {
                                break;
                            }
                        }
                    }

                    c.moveTo(_frontier);
                    _frontier = createDomDocumentRootXobj(_locale, true);

                    Cur c2 = _frontier.tempCur();
                    c2.next();
                    c.moveNodeContents(c2, true);
                    c.moveTo(_frontier);
                    c2.release();
                }
            }


            if (_additionalNamespaces != null) {
                c.moveTo(_frontier);
                Locale.toFirstChildElement(c);
                Locale.applyNamespaces(c, _additionalNamespaces);
            }

            if (_doctypeName != null && (_doctypePublicId != null || _doctypeSystemId != null)) {
                XmlDocumentProperties props = Locale.getDocProps(c, true);
                props.setDoctypeName(_doctypeName);
                if (_doctypePublicId != null) {
                    props.setDoctypePublicId(_doctypePublicId);
                }
                if (_doctypeSystemId != null) {
                    props.setDoctypeSystemId(_doctypeSystemId);
                }
            }

            c.moveTo(_frontier);

            assert c.isRoot();

            return c;
        }

        public void dump() {
            _frontier.dump();
        }

        private final Locale _locale;
        private final CharUtil _charUtil;

        private Xobj _frontier;
        private boolean _after;

        private Xobj _lastXobj;
        private int _lastPos;

        private final boolean _discardDocElem;
        private final QName _replaceDocElem;
        private final boolean _stripWhitespace;
        private final boolean _stripComments;
        private final boolean _stripProcinsts;
        private final Map<String, String> _substituteNamespaces;
        private final Map<String, String> _additionalNamespaces;

        private String _doctypeName;
        private String _doctypePublicId;
        private String _doctypeSystemId;
    }

    static String kindName(int kind) {
        switch (kind) {
            case ROOT:
                return "ROOT";
            case ELEM:
                return "ELEM";
            case ATTR:
                return "ATTR";
            case COMMENT:
                return "COMMENT";
            case PROCINST:
                return "PROCINST";
            case TEXT:
                return "TEXT";
            default:
                return "<< Unknown Kind (" + kind + ") >>";
        }
    }

    void dump() {
        dump(System.out, _xobj, this);
    }

    void dump(PrintStream o) {
        if (_xobj == null) {
            o.println("Unpositioned xptr");
            return;
        }

        dump(o, _xobj, this);
    }

    public static void dump(PrintStream o, Xobj xo, Object ref) {
        if (ref == null) {
            ref = xo;
        }

        while (xo._parent != null) {
            xo = xo._parent;
        }

        dumpXobj(o, xo, 0, ref);

        o.println();
    }

    private static void dumpCur(PrintStream o, String prefix, Cur c, Object ref) {
        o.print(" ");

        if (ref == c) {
            o.print("*:");
        }

        o.print(prefix + (c._id == null ? "<cur>" : c._id) + "[" + c._pos + "]");
    }

    private static void dumpCurs(PrintStream o, Xobj xo, Object ref) {
        for (Cur c = xo._embedded; c != null; c = c._next) {
            dumpCur(o, "E:", c, ref);
        }

        for (Cur c = xo._locale._registered; c != null; c = c._next) {
            if (c._xobj == xo) {
                dumpCur(o, "R:", c, ref);
            }
        }
    }

    private static void dumpBookmarks(PrintStream o, Xobj xo, Object ref) {
        for (Bookmark b = xo._bookmarks; b != null; b = b._next) {
            o.print(" ");

            if (ref == b) {
                o.print("*:");
            }

            if (b._value instanceof XmlLineNumber) {
                XmlLineNumber l = (XmlLineNumber) b._value;
                o.print("<line:" + l.getLine() + ">" + "[" + b._pos + "]");
            } else {
                o.print("<mark>" + "[" + b._pos + "]");
            }
        }
    }

    private static void dumpCharNodes(PrintStream o, CharNode nodes, Object ref) {
        for (CharNode n = nodes; n != null; n = n._next) {
            o.print(" ");

            if (n == ref) {
                o.print("*");
            }

            o.print((n instanceof TextNode ? "TEXT" : "CDATA") + "[" + n._cch + "]");
        }
    }

    private static void dumpChars(PrintStream o, Object src, int off, int cch) {

        o.print("\"");

        String s = CharUtil.getString(src, off, cch);

        for (int i = 0; i < s.length(); ) {
            if (i == 36) {
                o.print("...");
                break;
            }

            int codePoint = s.codePointAt(i);
            char[] chars = Character.toChars(codePoint);

            if (chars.length == 1) {
                char ch = chars[0];
                if (ch >= 32 && ch < 127 && ch != '\"') {
                    o.print(ch);
                } else if (ch == '\n') {
                    o.print("\\n");
                } else if (ch == '\r') {
                    o.print("\\r");
                } else if (ch == '\t') {
                    o.print("\\t");
                } else if (ch == '\"') {
                    o.print("\\\"");
                } else {
                    o.print("<#" + ((int) ch) + ">");
                }
            } else {
                o.print("<#" + codePoint + ">");
            }

            i += Character.charCount(codePoint);
        }

        o.print("\"");
    }

    private static void dumpXobj(PrintStream o, Xobj xo, int level, Object ref) {
        if (xo == null) {
            return;
        }

        if (xo == ref) {
            o.print("* ");
        } else {
            o.print("  ");
        }

        for (int i = 0; i < level; i++) {
            o.print("  ");
        }

        o.print(kindName(xo.kind()));

        if (xo._name != null) {
            o.print(" ");

            if (xo._name.getPrefix().length() > 0) {
                o.print(xo._name.getPrefix() + ":");
            }

            o.print(xo._name.getLocalPart());

            if (xo._name.getNamespaceURI().length() > 0) {
                o.print("@" + xo._name.getNamespaceURI());
            }
        }

        if (xo._srcValue != null || xo._charNodesValue != null) {
            o.print(" Value( ");
            dumpChars(o, xo._srcValue, xo._offValue, xo._cchValue);
            dumpCharNodes(o, xo._charNodesValue, ref);
            o.print(" )");
        }

        if (xo._user != null) {
            o.print(" (USER)");
        }

        if (xo.isVacant()) {
            o.print(" (VACANT)");
        }

        if (xo._srcAfter != null || xo._charNodesAfter != null) {
            o.print(" After( ");
            dumpChars(o, xo._srcAfter, xo._offAfter, xo._cchAfter);
            dumpCharNodes(o, xo._charNodesAfter, ref);
            o.print(" )");
        }

        dumpCurs(o, xo, ref);
        dumpBookmarks(o, xo, ref);

        String className = xo.getClass().getName();

        int i = className.lastIndexOf('.');

        if (i > 0) {
            className = className.substring(i + 1);

            i = className.lastIndexOf('$');

            if (i > 0) {
                className = className.substring(i + 1);
            }
        }

        o.print(" (");
        o.print(className);
        o.print(")");

        o.println();

        for (xo = xo._firstChild; xo != null; xo = xo._nextSibling) {
            dumpXobj(o, xo, level + 1, ref);
        }
    }

    void setId(String id) {
        _id = id;
    }

    public Locale getLocale() {
        return _locale;
    }
}