/*   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.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.common.ValidatorListener;
import org.apache.xmlbeans.impl.common.XmlLocale;
import org.apache.xmlbeans.impl.store.DomImpl.Dom;
import org.apache.xmlbeans.impl.values.TypeStore;
import org.apache.xmlbeans.impl.values.TypeStoreUser;
import org.apache.xmlbeans.impl.values.TypeStoreUserFactory;
import org.apache.xmlbeans.impl.values.TypeStoreVisitor;

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

// DOM Level 3

abstract class Xobj implements TypeStore {
    static final int TEXT = Cur.TEXT;
    static final int ROOT = Cur.ROOT;
    static final int ELEM = Cur.ELEM;
    static final int ATTR = Cur.ATTR;
    static final int COMMENT = Cur.COMMENT;
    static final int PROCINST = Cur.PROCINST;

    static final int END_POS = Cur.END_POS;
    static final int NO_POS = Cur.NO_POS;

    Xobj(Locale l, int kind, int domType) {
        assert kind == ROOT || kind == ELEM || kind == ATTR || kind == COMMENT || kind == PROCINST;

        _locale = l;
        _bits = (domType << 4) + kind;
    }

    final boolean entered() {
        return _locale.entered();
    }

    final int kind() {
        return _bits & 0xF;
    }

    final int domType() {
        return (_bits & 0xF0) >> 4;
    }

    final boolean isRoot() {
        return kind() == ROOT;
    }

    final boolean isAttr() {
        return kind() == ATTR;
    }

    final boolean isElem() {
        return kind() == ELEM;
    }

    final boolean isProcinst() {
        return kind() == PROCINST;
    }

    final boolean isComment() {
        return kind() == COMMENT;
    }

    final boolean isContainer() {
        return Cur.kindIsContainer(kind());
    }

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

    final boolean isNormalAttr() {
        return isAttr() && !Locale.isXmlns(_name);
    }

    final boolean isXmlns() {
        return isAttr() && Locale.isXmlns(_name);
    }

    final int cchValue() {
        return _cchValue;
    }

    final int cchAfter() {
        return _cchAfter;
    }

    final int posAfter() {
        return 2 + _cchValue;
    }

    final int posMax() {
        return 2 + _cchValue + _cchAfter;
    }

    final String getXmlnsPrefix() {
        return Locale.xmlnsPrefix(_name);
    }

    final String getXmlnsUri() {
        return getValueAsString();
    }

    final boolean hasTextEnsureOccupancy() {
        ensureOccupancy();
        return hasTextNoEnsureOccupancy();
    }

    final boolean hasTextNoEnsureOccupancy() {
        if (_cchValue > 0) {
            return true;
        }

        Xobj lastAttr = lastAttr();

        return lastAttr != null && lastAttr._cchAfter > 0;
    }

    final boolean hasAttrs() {
        return _firstChild != null && _firstChild.isAttr();
    }

    final boolean hasChildren() {
        return _lastChild != null && !_lastChild.isAttr();
    }


    /**
     * this method is to speed up DomImpl
     * when underlying obj is an Xobj
     *
     * @return 0 or 1 dom children; val 2 indicates that DomImpl needs to
     * compute the result itself
     */
    final protected int getDomZeroOneChildren() {
        if (_firstChild == null &&
            _srcValue == null &&
            _charNodesValue == null) {
            return 0;
        }

        if (_lastChild != null &&
            _lastChild.isAttr() &&
            _lastChild._charNodesAfter == null &&
            _lastChild._srcAfter == null &&
            _srcValue == null &&
            _charNodesValue == null
        ) {
            return 0;
        }

        if (_firstChild == _lastChild &&
            _firstChild != null &&
            !_firstChild.isAttr() &&
            _srcValue == null &&
            _charNodesValue == null &&
            _firstChild._srcAfter == null
        ) {
            return 1;
        }

        if (_firstChild == null &&
            _srcValue != null &&
            (_charNodesValue == null ||
             (_charNodesValue._next == null &&
              _charNodesValue._cch == _cchValue))
        ) {
            return 1;
        }
        //single elem after an attr
        Xobj lastAttr = lastAttr();
        Xobj node = lastAttr == null ?
            null : lastAttr._nextSibling;
        if (lastAttr != null &&
            lastAttr._srcAfter == null &&
            node != null &&
            node._srcAfter == null &&
            node._nextSibling == null) {
            return 1;
        }

        return 2;
    }

    /**
     * can one use the _firstChild pointer to retrieve
     * the first DOM child
     *
     * @return
     */
    final protected boolean isFirstChildPtrDomUsable() {
        if (_firstChild == null &&
            _srcValue == null &&
            _charNodesValue == null) {
            return true;
        }

        if (_firstChild != null &&
            !_firstChild.isAttr() &&
            _srcValue == null &&
            _charNodesValue == null) {
            assert (_firstChild instanceof NodeXobj) :
                "wrong node type";
            return true;
        }
        return false;
    }

    /**
     * can one use the _nextSibling pointer to retrieve
     * the next DOM sibling
     *
     * @return
     */
    final protected boolean isNextSiblingPtrDomUsable() {
        if (_charNodesAfter == null &&
            _srcAfter == null) {
            assert (_nextSibling == null ||
                    _nextSibling instanceof NodeXobj) :
                "wrong node type";
            return true;
        }
        return false;
    }

    /**
     * can one use the _charNodesValue pointer to retrieve
     * the next DOM sibling
     *
     * @return
     */
    final protected boolean isExistingCharNodesValueUsable() {
        if (_srcValue == null) {
            return false;
        }
        if (_charNodesValue != null && _charNodesValue._next == null
            && _charNodesValue._cch == _cchValue) {
            return true;
        }
        return false;
    }

    final protected boolean isCharNodesValueUsable() {
        return isExistingCharNodesValueUsable() ||
               (_charNodesValue =
                   Cur.updateCharNodes(_locale, this,
                       _charNodesValue, _cchValue)) != null;
    }

    /**
     * can one use the _charNodesAfter pointer to retrieve
     * the next DOM sibling
     *
     * @return
     */
    final protected boolean isCharNodesAfterUsable() {
        if (_srcAfter == null) {
            return false;
        }
        if (_charNodesAfter != null && _charNodesAfter._next == null
            && _charNodesAfter._cch == this._cchAfter) {
            return true;
        }
        return (_charNodesAfter =
            Cur.updateCharNodes(_locale, this,
                _charNodesAfter, _cchAfter)) != null;
    }


    final Xobj lastAttr() {
        if (_firstChild == null || !_firstChild.isAttr()) {
            return null;
        }

        Xobj lastAttr = _firstChild;

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

        return lastAttr;
    }

    abstract Dom getDom();

    abstract Xobj newNode(Locale l);

    final int cchLeft(int p) {
        if (isRoot() && p == 0) {
            return 0;
        }

        Xobj x = getDenormal(p);

        p = posTemp();
        int pa = x.posAfter();

        return p - (p < pa ? 1 : pa);
    }

    final int cchRight(int p) {
        assert p < posMax();

        if (p <= 0) {
            return 0;
        }

        int pa = posAfter();

        return p < pa ? pa - p - 1 : posMax() - p;
    }

    //
    // Dom interface
    //

    public final Locale locale() {
        return _locale;
    }

    public final int nodeType() {
        return domType();
    }

    public final QName getQName() {
        return _name;
    }

    public final Cur tempCur() {
        Cur c = _locale.tempCur();
        c.moveTo(this);
        return c;
    }

    public void dump(PrintStream o, Object ref) {
        Cur.dump(o, (Xobj) this, ref);
    }

    public void dump(PrintStream o) {
        Cur.dump(o, this, this);
    }

    public void dump() {
        dump(System.out);
    }

    //
    //
    //

    final Cur getEmbedded() {
        _locale.embedCurs();

        return _embedded;
    }

    // Incoming p must be at text (implicitly denormalized)

    final boolean inChars(int p, Xobj xIn, int pIn, int cch, boolean includeEnd) {
        assert p > 0 && p < posMax() && p != posAfter() - 1 && cch > 0;
        assert xIn.isNormal(pIn);

        // No need to denormalize "in" if the right hand side is excluded.  Denormalizing deals
        // with the case where p is END_POS.

        int offset;

        if (includeEnd) {
            // Can't denormalize at the beginning of the document

            if (xIn.isRoot() && pIn == 0) {
                return false;
            }

            xIn = xIn.getDenormal(pIn);
            pIn = xIn.posTemp();

            offset = 1;
        } else {
            offset = 0;
        }

        return xIn == this && pIn >= p && pIn < p + (cch < 0 ? cchRight(p) : cch) + offset;
    }

    // Is x/p just after the end of this

    final boolean isJustAfterEnd(Xobj x, int p) {
        assert x.isNormal(p);

        // Get denormalize at the beginning of the doc

        if (x.isRoot() && p == 0) {
            return false;
        }

        return
            x == this
                ? p == posAfter()
                : x.getDenormal(p) == this && x.posTemp() == posAfter();
    }

    final boolean isInSameTree(Xobj x) {
        if (_locale != x._locale) {
            return false;
        }

        for (Xobj y = this; ; y = y._parent) {
            if (y == x) {
                return true;
            }

            if (y._parent == null) {
                for (; ; x = x._parent) {
                    if (x == this) {
                        return true;
                    }

                    if (x._parent == null) {
                        return x == y;
                    }
                }
            }
        }
    }

    final boolean contains(Cur c) {
        assert c.isNormal();

        return contains(c._xobj, c._pos);
    }

    final boolean contains(Xobj x, int p) {
        assert x.isNormal(p);

        if (this == x) {
            return p == END_POS || (p > 0 && p < posAfter());
        }

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

        for (; x != null; x = x._parent) {
            if (x == this) {
                return true;
            }
        }

        return false;
    }

    final Bookmark setBookmark(int p, Object key, Object value) {
        assert isNormal(p);

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

                b._value = value;

                return b;
            }
        }

        if (value == null) {
            return null;
        }

        Bookmark b = new Bookmark();

        b._xobj = this;
        b._pos = p;
        b._key = key;
        b._value = value;

        _bookmarks = b.listInsert(_bookmarks);

        return b;
    }

    final boolean hasBookmark(Object key, int pos) {
        for (Bookmark b = _bookmarks; b != null; b = b._next) {
            if (b._pos == pos && key == b._key) {
                //System.out.println("hasCDataBookmark  pos: " + pos + " xobj: " + getQName() + " b._pos: " + _bookmarks._pos);
                return true;
            }
        }

        return false;
    }

    final Xobj findXmlnsForPrefix(String prefix) {
        assert isContainer() && prefix != null;

        for (Xobj c = this; c != null; c = c._parent) {
            for (Xobj a = c.firstAttr(); a != null; a = a.nextAttr()) {
                if (a.isXmlns() && a.getXmlnsPrefix().equals(prefix)) {
                    return a;
                }
            }
        }

        return null;
    }

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

        Xobj a = getAttr(name);

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

        Cur c = a.tempCur();

        for (; ; ) {
            c.moveNode(null);

            a = getAttr(name);

            if (a == null) {
                break;
            }

            c.moveTo(a);
        }

        c.release();

        return true;
    }

    final Xobj setAttr(QName name, String value) {
        assert isContainer();

        Cur c = tempCur();

        if (c.toAttr(name)) {
            c.removeFollowingAttrs();
        } else {
            c.next();
            c.createAttr(name);
        }

        c.setValue(value);

        Xobj a = c._xobj;

        c.release();

        return a;
    }

    final void setName(QName newName) {
        assert isAttr() || isElem() || isProcinst();
        assert newName != null;

        if (!_name.equals(newName) || !_name.getPrefix().equals(newName.getPrefix())) {
// TODO - this is not a structural change .... perhaps should not issue a change here?
            _locale.notifyChange();

            QName oldName = _name;

            _name = newName;
            if (this instanceof NamedNodeXobj) {
                NamedNodeXobj me = (NamedNodeXobj) this;
                me._canHavePrefixUri = true;
            }

            if (!isProcinst()) {
                Xobj disconnectFromHere = this;

                if (isAttr() && _parent != null) {
                    if (oldName.equals(Locale._xsiType) || newName.equals(Locale._xsiType)) {
                        disconnectFromHere = _parent;
                    }

                    if (oldName.equals(Locale._xsiNil) || newName.equals(Locale._xsiNil)) {
                        _parent.invalidateNil();
                    }
                }

                disconnectFromHere.disconnectNonRootUsers();
            }

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

    final Xobj ensureParent() {
        assert _parent != null || (!isRoot() && cchAfter() == 0);
        return _parent == null ? new DocumentFragXobj(_locale).appendXobj(this) : _parent;
    }

    final Xobj firstAttr() {
        return _firstChild == null || !_firstChild.isAttr() ? null : _firstChild;
    }

    final Xobj nextAttr() {
        if (_firstChild != null && _firstChild.isAttr()) {
            return _firstChild;
        }

        if (_nextSibling != null && _nextSibling.isAttr()) {
            return _nextSibling;
        }

        return null;
    }

    final boolean isValid() {
        if (isVacant() && (_cchValue != 0 || _user == null)) {
            return false;
        }

        return true;
    }

    final int posTemp() {
        return _locale._posTemp;
    }

    final Xobj getNormal(int p) {
        assert p == END_POS || (p >= 0 && p <= posMax());

        Xobj x = this;

        if (p == x.posMax()) {
            if (x._nextSibling != null) {
                x = x._nextSibling;
                p = 0;
            } else {
                x = x.ensureParent();
                p = END_POS;
            }
        } else if (p == x.posAfter() - 1) {
            p = END_POS;
        }

        _locale._posTemp = p;

        return x;
    }

    // Can't denormalize a position at the very beginning of the document.  No where to go to the
    // left!

    final Xobj getDenormal(int p) {
        assert END_POS == -1;
        assert !isRoot() || p == END_POS || p > 0;

        Xobj x = this;

        if (p == 0) {
            if (x._prevSibling == null) {
                x = x.ensureParent();
                p = x.posAfter() - 1;
            } else {
                x = x._prevSibling;
                p = x.posMax();
            }
        } else if (p == END_POS) {
            if (x._lastChild == null) {
                p = x.posAfter() - 1;
            } else {
                x = x._lastChild;
                p = x.posMax();
            }
        }

        _locale._posTemp = p;

        return x;
    }

    final boolean isNormal(int p) {
        if (!isValid()) {
            return false;
        }

        if (p == END_POS || p == 0) {
            return true;
        }

        if (p < 0 || p >= posMax()) {
            return false;
        }

        if (p >= posAfter()) {
            if (isRoot()) {
                return false;
            }

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

            if (_parent == null || !_parent.isContainer()) {
                return false;
            }
        }

        if (p == posAfter() - 1) {
            return false;
        }

        return true;
    }

    final Xobj walk(Xobj root, boolean walkChildren) {
        if (_firstChild != null && walkChildren) {
            return _firstChild;
        }

        for (Xobj x = this; x != root; x = x._parent) {
            if (x._nextSibling != null) {
                return x._nextSibling;
            }
        }

        return null;
    }

    final Xobj removeXobj() {
        if (_parent != null) {
            if (_parent._firstChild == this) {
                _parent._firstChild = _nextSibling;
            }

            if (_parent._lastChild == this) {
                _parent._lastChild = _prevSibling;
            }

            if (_prevSibling != null) {
                _prevSibling._nextSibling = _nextSibling;
            }

            if (_nextSibling != null) {
                _nextSibling._prevSibling = _prevSibling;
            }

            _parent = null;
            _prevSibling = null;
            _nextSibling = null;
        }

        return this;
    }

    final Xobj insertXobj(Xobj s) {
        assert _locale == s._locale;
        assert !s.isRoot() && !isRoot();
        assert s._parent == null;
        assert s._prevSibling == null;
        assert s._nextSibling == null;

        ensureParent();

        s._parent = _parent;
        s._prevSibling = _prevSibling;
        s._nextSibling = this;

        if (_prevSibling != null) {
            _prevSibling._nextSibling = s;
        } else {
            _parent._firstChild = s;
        }

        _prevSibling = s;

        return this;
    }

    final Xobj appendXobj(Xobj c) {
        assert _locale == c._locale;
        assert !c.isRoot();
        assert c._parent == null;
        assert c._prevSibling == null;
        assert c._nextSibling == null;
        assert _lastChild == null || _firstChild != null;

        c._parent = this;
        c._prevSibling = _lastChild;

        if (_lastChild == null) {
            _firstChild = c;
        } else {
            _lastChild._nextSibling = c;
        }

        _lastChild = c;

        return this;
    }

    final void removeXobjs(Xobj first, Xobj last) {
        assert last._locale == first._locale;
        assert first._parent == this;
        assert last._parent == this;

        if (_firstChild == first) {
            _firstChild = last._nextSibling;
        }

        if (_lastChild == last) {
            _lastChild = first._prevSibling;
        }

        if (first._prevSibling != null) {
            first._prevSibling._nextSibling = last._nextSibling;
        }

        if (last._nextSibling != null) {
            last._nextSibling._prevSibling = first._prevSibling;
        }

        // Leave the children linked together

        first._prevSibling = null;
        last._nextSibling = null;

        for (; first != null; first = first._nextSibling) {
            first._parent = null;
        }
    }

    final void insertXobjs(Xobj first, Xobj last) {
        assert _locale == first._locale;
        assert last._locale == first._locale;
        assert first._parent == null && last._parent == null;
        assert first._prevSibling == null;
        assert last._nextSibling == null;

        first._prevSibling = _prevSibling;
        last._nextSibling = this;

        if (_prevSibling != null) {
            _prevSibling._nextSibling = first;
        } else {
            _parent._firstChild = first;
        }

        _prevSibling = last;

        for (; first != this; first = first._nextSibling) {
            first._parent = _parent;
        }
    }

    final void appendXobjs(Xobj first, Xobj last) {
        assert _locale == first._locale;
        assert last._locale == first._locale;
        assert first._parent == null && last._parent == null;
        assert first._prevSibling == null;
        assert last._nextSibling == null;
        assert !first.isRoot();

        first._prevSibling = _lastChild;

        if (_lastChild == null) {
            _firstChild = first;
        } else {
            _lastChild._nextSibling = first;
        }

        _lastChild = last;

        for (; first != null; first = first._nextSibling) {
            first._parent = this;
        }
    }

    static final void disbandXobjs(Xobj first, Xobj last) {
        assert last._locale == first._locale;
        assert first._parent == null && last._parent == null;
        assert first._prevSibling == null;
        assert last._nextSibling == null;
        assert !first.isRoot();

        while (first != null) {
            Xobj next = first._nextSibling;
            first._nextSibling = first._prevSibling = null;
            first = next;
        }
    }

    // Potential attr is going to be moved/removed, invalidate parent if it is a special attr

    final void invalidateSpecialAttr(Xobj newParent) {
        if (isAttr()) {
            if (_name.equals(Locale._xsiType)) {
                if (_parent != null) {
                    _parent.disconnectNonRootUsers();
                }

                if (newParent != null) {
                    newParent.disconnectNonRootUsers();
                }
            }

            if (_name.equals(Locale._xsiNil)) {
                if (_parent != null) {
                    _parent.invalidateNil();
                }

                if (newParent != null) {
                    newParent.invalidateNil();
                }
            }
        }
    }

    // Move or remove chars.  Incoming p is denormalized.  Incoming xTo and pTo are denormalized.
    // Option to move curs with text.  Option to perform invalidations.
    //
    // Important note: this fcn must operate under the assumption that the tree may be in an
    // invalid state.  Most likely, there may be text on two different nodes which should belong
    // on the same node.  Assertion of cursor normalization usually detects this problem.  Any of
    // the fcns it calls must also deal with these invalid conditions.  Try not to call so many
    // fcns from here.

    final void removeCharsHelper(
        int p, int cchRemove, Xobj xTo, int pTo, boolean moveCurs, boolean invalidate) {
        assert p > 0 && p < posMax() && p != posAfter() - 1;
        assert cchRemove > 0;
        assert cchRight(p) >= cchRemove;
        assert !moveCurs || xTo != null;

        // Here I check the span of text to be removed for cursors.  If xTo/pTo is not specified,
        // then the caller wants these cursors to collapse to be after the text being removed.  If
        // the caller specifies moveCurs, then the caller has arranged for the text being removed
        // to have been copied to xTp/pTo and wants the cursors to be moved there as well.
        // Note that I call nextChars here.  I do this because trying to shift the cursor to the
        // end of the text to be removed with a moveTo could cause the improper placement of the
        // cursor just before an end tag, instead of placing it just before the first child.  Also,
        // I adjust all positions of curs after the text to be removed to account for the removal.

        for (Cur c = getEmbedded(); c != null; ) {
            Cur next = c._next;

            // Here I test to see if the Cur c is in the range of chars to be removed.  Normally
            // I would call inChars, but it can't handle the invalidity of the tree, so I heve
            // inlined the inChars logic here (includeEnd is false, makes it much simpler).
            // Note that I also call moveToNoCheck because the destination may have afterText
            // and no parent which will cause normaliztion checks in MoveTo to fail.  I don't think
            // that nextChars will be called under such circumstnaces.

            assert c._xobj == this;

            if (c._pos >= p && c._pos < p + cchRemove) {
                if (moveCurs) {
                    c.moveToNoCheck(xTo, pTo + c._pos - p);
                } else {
                    c.nextChars(cchRemove - c._pos + p);
                }
            }

            // If c is still on this Xobj and it's to the right of the chars to remove, adjust
            // it to adapt to the removal of the cars.  I don't have to worry about END_POS
            // here, just curs in text.

            if (c._xobj == this && c._pos >= p + cchRemove) {
                c._pos -= cchRemove;
            }

            c = next;
        }

        // Here I move bookmarks in this text to the span of text at xTo/pTo.  The text at this/p
        // is going away, but a caller of this fcn who specifies xTo/pTo has copied the text to
        // xTo/pTo.  The caller has to make sure that if xTo/pTo is not specified, then there are
        // no bookmarks in the span of text to be removed.

        for (Bookmark b = _bookmarks; b != null; ) {
            Bookmark next = b._next;

            // Similarly, as above, I can't call inChars here

            assert b._xobj == this;

            if (b._pos >= p && b._pos < p + cchRemove) {
                assert xTo != null;
                b.moveTo(xTo, pTo + b._pos - p);
            }

            if (b._xobj == this && b._pos >= p + cchRemove) {
                b._pos -= cchRemove;
            }

            b = b._next;
        }

        // Now, remove the actual chars

        int pa = posAfter();
        CharUtil cu = _locale.getCharUtil();

        if (p < pa) {
            _srcValue = cu.removeChars(p - 1, cchRemove, _srcValue, _offValue, _cchValue);
            _offValue = cu._offSrc;
            _cchValue = cu._cchSrc;

            if (invalidate) {
                invalidateUser();
                invalidateSpecialAttr(null);
            }
        } else {
            _srcAfter = cu.removeChars(p - pa, cchRemove, _srcAfter, _offAfter, _cchAfter);
            _offAfter = cu._offSrc;
            _cchAfter = cu._cchSrc;

            if (invalidate && _parent != null) {
                _parent.invalidateUser();
            }
        }
    }

    // Insert chars into this xobj.  Incoming p is denormalized.  Update bookmarks and cursors.
    // This fcn does not deal with occupation of the value, this needs to be handled by the
    // caller.

    final void insertCharsHelper(int p, Object src, int off, int cch, boolean invalidate) {
        assert p > 0;
        assert p >= posAfter() || isOccupied();

        int pa = posAfter();

        // Here I shuffle bookmarks and cursors affected by the insertion of the new text.  Because
        // getting the embedded cursors is non-trivial, I avoid getting them if I don't need to.
        // Basically, I need to know if p is before any text in the node as a whole.  If it is,
        // then there may be cursors/marks I need to shift right.

        if (p - (p < pa ? 1 : 2) < _cchValue + _cchAfter) {
            for (Cur c = getEmbedded(); c != null; c = c._next) {
                if (c._pos >= p) {
                    c._pos += cch;
                }
            }

            for (Bookmark b = _bookmarks; b != null; b = b._next) {
                if (b._pos >= p) {
                    b._pos += cch;
                }
            }
        }

        // Now, stuff the new characters in!  Also invalidate the proper container and if the
        // value of an attribute is changing, check for special attr invalidation.  Note that
        // I do not assume that inserting after text will have a parent.  There are use cases
        // from moveNodesContents which excersize this.

        CharUtil cu = _locale.getCharUtil();

        if (p < pa) {
            _srcValue = cu.insertChars(p - 1, _srcValue, _offValue, _cchValue, src, off, cch);
            _offValue = cu._offSrc;
            _cchValue = cu._cchSrc;

            if (invalidate) {
                invalidateUser();
                invalidateSpecialAttr(null);
            }
        } else {
            _srcAfter = cu.insertChars(p - pa, _srcAfter, _offAfter, _cchAfter, src, off, cch);
            _offAfter = cu._offSrc;
            _cchAfter = cu._cchSrc;

            if (invalidate && _parent != null) {
                _parent.invalidateUser();
            }
        }
    }

    Xobj copyNode(Locale toLocale) {
        Xobj newParent = null;
        Xobj copy = null;

        for (Xobj x = this; ; ) {
            x.ensureOccupancy();

            Xobj newX = x.newNode(toLocale);

            newX._srcValue = x._srcValue;
            newX._offValue = x._offValue;
            newX._cchValue = x._cchValue;

            newX._srcAfter = x._srcAfter;
            newX._offAfter = x._offAfter;
            newX._cchAfter = x._cchAfter;

            for (Bookmark b = x._bookmarks; b != null; b = b._next) {
                if (x.hasBookmark(CDataBookmark.CDATA_BOOKMARK.getKey(), b._pos)) {
                    newX.setBookmark(b._pos, CDataBookmark.CDATA_BOOKMARK.getKey(), CDataBookmark.CDATA_BOOKMARK);
                }
            }
            // TODO - strange to have charNode stuff inside here .....
            // newX._charNodesValue = CharNode.copyNodes( x._charNodesValue, newX._srcValue );
            // newX._charNodesAfter = CharNode.copyNodes( x._charNodesAfter, newX._srcAfter );

            if (newParent == null) {
                copy = newX;
            } else {
                newParent.appendXobj(newX);
            }

            // Walk to the next in-order xobj.  Record the current (y) to compute newParent

            Xobj y = x;

            if ((x = x.walk(this, true)) == null) {
                break;
            }

            if (y == x._parent) {
                newParent = newX;
            } else {
                for (; y._parent != x._parent; y = y._parent) {
                    newParent = newParent._parent;
                }
            }
        }

        copy._srcAfter = null;
        copy._offAfter = 0;
        copy._cchAfter = 0;

        return copy;
    }

    // Rturns all the chars, even if there is text intermixed with children

    String getCharsAsString(int p, int cch, int wsr) {
        if (cchRight(p) == 0) {
            return "";
        }

        Object src = getChars(p, cch);

        if (wsr == Locale.WS_PRESERVE) {
            return CharUtil.getString(src, _locale._offSrc, _locale._cchSrc);
        }

        Locale.ScrubBuffer scrub = Locale.getScrubBuffer(wsr);

        scrub.scrub(src, _locale._offSrc, _locale._cchSrc);

        return scrub.getResultAsString();
    }

    String getCharsAfterAsString(int off, int cch) {
        int offset = off + _cchValue + 2;
        if (offset == posMax()) {
            offset = -1;
        }
        return getCharsAsString(offset, cch,
            Locale.WS_PRESERVE);
    }

    String getCharsValueAsString(int off, int cch) {
        return getCharsAsString(off + 1, cch,
            Locale.WS_PRESERVE);
    }

    String getValueAsString(int wsr) {
        if (!hasChildren()) {
            Object src = getFirstChars();

            if (wsr == Locale.WS_PRESERVE) {
                String s = CharUtil.getString(src, _locale._offSrc, _locale._cchSrc);

                // Cache string to be able to use it later again

                int cch = s.length();

                if (cch > 0) {
                    Xobj lastAttr = lastAttr();

                    assert (lastAttr == null ? _cchValue : lastAttr._cchAfter) == cch;

                    if (lastAttr != null) {
                        lastAttr._srcAfter = s;
                        lastAttr._offAfter = 0;
                    } else {
                        _srcValue = s;
                        _offValue = 0;
                    }
                }

                return s;
            }

            Locale.ScrubBuffer scrub = Locale.getScrubBuffer(wsr);

            scrub.scrub(src, _locale._offSrc, _locale._cchSrc);

            return scrub.getResultAsString();
        }

        Locale.ScrubBuffer scrub = Locale.getScrubBuffer(wsr);

        Cur c = tempCur();

        c.push();

        for (c.next(); !c.isAtEndOfLastPush(); ) {
            if (c.isText()) {
                scrub.scrub(c.getChars(-1), c._offSrc, c._cchSrc);
            }

            if (c.isComment() || c.isProcinst()) {
                c.skip();
            } else {
                c.next();
            }
        }

        String s = scrub.getResultAsString();

        c.release();

        return s;
    }

    String getValueAsString() {
        return getValueAsString(Locale.WS_PRESERVE);
    }

    String getString(int p, int cch) {
        int cchRight = cchRight(p);

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

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

        int pa = posAfter();

        assert p > 0;

        String s;

        if (p >= pa) {
            s = CharUtil.getString(_srcAfter, _offAfter + p - pa, cch);

            if (p == pa && cch == _cchAfter) {
                _srcAfter = s;
                _offAfter = 0;
            }
        } else {
            s = CharUtil.getString(_srcValue, _offValue + p - 1, cch);

            if (p == 1 && cch == _cchValue) {
                _srcValue = s;
                _offValue = 0;
            }
        }

        return s;
    }

    // Returns just chars just after the begin tag ... does not get all the text if there are
    // children

    Object getFirstChars() {
        ensureOccupancy();

        if (_cchValue > 0) {
            return getChars(1, -1);
        }

        Xobj lastAttr = lastAttr();

        if (lastAttr == null || lastAttr._cchAfter <= 0) {
            _locale._offSrc = 0;
            _locale._cchSrc = 0;

            return null;
        }

        return lastAttr.getChars(lastAttr.posAfter(), -1);
    }

    Object getChars(int pos, int cch, Cur c) {
        Object src = getChars(pos, cch);

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

        return src;
    }

    // These return the remainder of the char triple that getChars starts

    Object getChars(int pos, int cch) {
        assert isNormal(pos);

        int cchRight = cchRight(pos);

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

        if (cch == 0) {
            _locale._offSrc = 0;
            _locale._cchSrc = 0;

            return null;
        }

        return getCharsHelper(pos, cch);
    }

    // Assumes that there are chars to return, does not assume normal x/p

    Object getCharsHelper(int pos, int cch) {
        assert cch > 0 && cchRight(pos) >= cch;

        int pa = posAfter();

        Object src;

        if (pos >= pa) {
            src = _srcAfter;
            _locale._offSrc = _offAfter + pos - pa;
        } else {
            src = _srcValue;
            _locale._offSrc = _offValue + pos - 1;
        }

        _locale._cchSrc = cch;

        return src;
    }

    //
    //
    //

    final void setBit(int mask) {
        _bits |= mask;
    }

    final void clearBit(int mask) {
        _bits &= ~mask;
    }

    final boolean bitIsSet(int mask) {
        return (_bits & mask) != 0;
    }

    final boolean bitIsClear(int mask) {
        return (_bits & mask) == 0;
    }

    static final int VACANT = 0x100;
    static final int STABLE_USER = 0x200;
    static final int INHIBIT_DISCONNECT = 0x400;

    final boolean isVacant() {
        return bitIsSet(VACANT);
    }

    final boolean isOccupied() {
        return bitIsClear(VACANT);
    }

    final boolean inhibitDisconnect() {
        return bitIsSet(INHIBIT_DISCONNECT);
    }

    final boolean isStableUser() {
        return bitIsSet(STABLE_USER);
    }

    void invalidateNil() {
        if (_user != null) {
            _user.invalidate_nilvalue();
        }
    }

    void setStableType(SchemaType type) {
        setStableUser(((TypeStoreUserFactory) type).createTypeStoreUser());
    }

    void setStableUser(TypeStoreUser user) {
        disconnectNonRootUsers();
        disconnectUser();

        assert _user == null;

        _user = user;

        _user.attach_store(this);

        setBit(STABLE_USER);
    }

    void disconnectUser() {
        if (_user != null && !inhibitDisconnect()) {
            ensureOccupancy();
            _user.disconnect_store();
            _user = null;
        }
    }

    // If a node does not have a user, then I don't need to walk its descendents.  NOte that
    // the doconnect happens in document order.  This may be a problem ... not sure ... May want
    // to disconnect in a bottom up manner.

    void disconnectNonRootUsers() {
        Xobj next;

        for (Xobj x = this; x != null; x = next) {
            next = x.walk(this, x._user != null);

            if (!x.isRoot()) {
                x.disconnectUser();
            }
        }
    }

    void disconnectChildrenUsers() {
        Xobj next;

        for (Xobj x = walk(this, _user == null); x != null; x = next) {
            next = x.walk(this, x._user != null);

            x.disconnectUser();
        }
    }

    /**
     * Given a prefix, returns the namespace corresponding to
     * the prefix at this location, or null if there is no mapping
     * for this prefix.
     * <p>
     * prefix="" indicates the absence of a prefix.  A return value
     * of "" indicates the no-namespace, and should not be confused
     * with a return value of null, which indicates an illegal
     * state, where there is no mapping for the given prefix.
     * <p>
     * If the the default namespace is not explicitly mapped in the xml,
     * the xml spec says that it should be mapped to the no-namespace.
     * When the 'defaultAlwaysMapped' parameter is true, the default namepsace
     * will return the no-namespace even if it is not explicity
     * mapped, otherwise the default namespace will return null.
     * <p>
     * This function intercepts the built-in prefixes "xml" and
     * "xmlns" and returns their well-known namespace URIs.
     *
     * @param prefix              The prefix to look up.
     * @param defaultAlwaysMapped If true, return the no-namespace for the default namespace if not set.
     * @return The mapped namespace URI ("" if no-namespace), or null if no mapping.
     */

    final String namespaceForPrefix(String prefix, boolean defaultAlwaysMapped) {
        if (prefix == null) {
            prefix = "";
        }

        // handle built-in prefixes

        if (prefix.equals("xml")) {
            return Locale._xml1998Uri;
        }

        if (prefix.equals("xmlns")) {
            return Locale._xmlnsUri;
        }

        for (Xobj x = this; x != null; x = x._parent) {
            for (Xobj a = x._firstChild; a != null && a.isAttr(); a = a._nextSibling) {
                if (a.isXmlns() && a.getXmlnsPrefix().equals(prefix)) {
                    return a.getXmlnsUri();
                }
            }
        }

        return defaultAlwaysMapped && prefix.length() == 0 ? "" : null;
    }

    final String prefixForNamespace(String ns, String suggestion, boolean createIfMissing) {
        if (ns == null) {
            ns = "";
        }

        // special cases

        if (ns.equals(Locale._xml1998Uri)) {
            return "xml";
        }

        if (ns.equals(Locale._xmlnsUri)) {
            return "xmlns";
        }

        // Get the closest container for the spot we're on

        Xobj base = this;

        while (!base.isContainer()) {
            base = base.ensureParent();
        }

        // Special handling for the no-namespace case

        if (ns.length() == 0) {
            // Search for a namespace decl which defines the default namespace

            Xobj a = base.findXmlnsForPrefix("");

            // If I did not find a default decl or the decl maps to the no namespace, then
            // the default namespace is mapped to ""

            if (a == null || a.getXmlnsUri().length() == 0) {
                return "";
            }

            // At this point, I've found a default namespace which is *not* the no-namespace.
            // If I can't modify the document to mape the desired no-namespace, I must fail.

            if (!createIfMissing) {
                return null;
            }

            // Ok, I need to make the default namespace on the nearest container map to ""

            base.setAttr(_locale.createXmlns(null), "");

            return "";
        }

        // Look for an exisiting mapping for the desired uri which has a visible prefix

        for (Xobj c = base; c != null; c = c._parent) {
            for (Xobj a = c.firstAttr(); a != null; a = a.nextAttr()) {
                if (a.isXmlns() && a.getXmlnsUri().equals(ns)) {
                    if (base.findXmlnsForPrefix(a.getXmlnsPrefix()) == a) {
                        return a.getXmlnsPrefix();
                    }
                }
            }
        }

        // No exisiting xmlns I can use, need to create one.  See if I can first

        if (!createIfMissing) {
            return null;
        }

        // Sanitize the suggestion.

        if (suggestion != null &&
            (suggestion.length() == 0 || suggestion.toLowerCase().startsWith("xml") ||
             base.findXmlnsForPrefix(suggestion) != null)) {
            suggestion = null;
        }

        // If no suggestion, make one up

        if (suggestion == null) {
            String prefixBase = QNameHelper.suggestPrefix(ns);

            suggestion = prefixBase;

            for (int i = 1; ; suggestion = prefixBase + i++) {
                if (base.findXmlnsForPrefix(suggestion) == null) {
                    break;
                }
            }
        }

        // Add a new namespace decl at the top elem if one exists, otherwise at root

        Xobj c = base;

        while (!c.isRoot() && !c.ensureParent().isRoot()) {
            c = c._parent;
        }

        base.setAttr(_locale.createXmlns(suggestion), ns);

        return suggestion;
    }

    final QName getValueAsQName() {
        assert !hasChildren();

        // TODO -
        // caching the QName value in this object would prevent one from having
        // to repeat all this string arithmatic over and over again.  Perhaps
        // when I make the store capable of handling strong simple types this
        // can be done ...

        String value = getValueAsString(Locale.WS_COLLAPSE);

        String prefix, localname;

        int firstcolon = value.indexOf(':');

        if (firstcolon >= 0) {
            prefix = value.substring(0, firstcolon);
            localname = value.substring(firstcolon + 1);
        } else {
            prefix = "";
            localname = value;
        }

        String uri = namespaceForPrefix(prefix, true);

        if (uri == null) {
            return null; // no prefix definition found - that's illegal
        }

        return new QName(uri, localname);
    }

    final Xobj getAttr(QName name) {
        for (Xobj x = _firstChild; x != null && x.isAttr(); x = x._nextSibling) {
            if (x._name.equals(name)) {
                return x;
            }
        }

        return null;
    }

    final QName getXsiTypeName() {
        assert isContainer();

        Xobj a = getAttr(Locale._xsiType);

        return a == null ? null : a.getValueAsQName();
    }

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

    final TypeStoreUser getUser() {
        assert isUserNode();
        assert _user != null || (!isRoot() && !isStableUser());

        if (_user == null) {
            // BUGBUG - this is recursive

            TypeStoreUser parentUser =
                _parent == null
                    ? ((TypeStoreUserFactory) XmlBeans.NO_TYPE).createTypeStoreUser()
                    : _parent.getUser();

            _user =
                isElem()
                    ? parentUser.create_element_user(_name, getXsiTypeName())
                    : parentUser.create_attribute_user(_name);

            _user.attach_store(this);
        }

        return _user;
    }

    final void invalidateUser() {
        assert isValid();
        assert _user == null || isUserNode();

        if (_user != null) {
            _user.invalidate_value();
        }
    }

    final void ensureOccupancy() {
        assert isValid();

        if (isVacant()) {
            assert isUserNode();

            // In order to use Cur to set the value, I mark the
            // value as occupied and remove the user to prohibit
            // further user invalidations

            clearBit(VACANT);

            TypeStoreUser user = _user;
            _user = null;

            String value = user.build_text(this);


            long saveVersion = _locale._versionAll;
            long saveVersionSansText = _locale._versionSansText;


            setValue(value);
            assert saveVersionSansText == _locale._versionSansText;

            _locale._versionAll = saveVersion;


            assert _user == null;
            _user = user;
        }
    }

    private void setValue(String val) {
        assert CharUtil.isValid(val, 0, val.length());

        // Check for nothing to insert

        if (val.length() <= 0) {
            return;
        }

        _locale.notifyChange();
        Xobj lastAttr = lastAttr();
        int startPos = 1;
        Xobj charOwner = this;
        if (lastAttr != null) {
            charOwner = lastAttr;
            startPos = charOwner.posAfter();
        }
        charOwner.insertCharsHelper(startPos, val, 0, val.length(), true);
    }
    //
    // TypeStore
    //

    public SchemaTypeLoader get_schematypeloader() {
        return _locale._schemaTypeLoader;
    }

    public XmlLocale get_locale() {
        return _locale;
    }

    // TODO - remove this when I've replaced the old store
    public Object get_root_object() {
        return _locale;
    }

    public boolean is_attribute() {
        assert isValid();
        return isAttr();
    }

    public boolean validate_on_set() {
        assert isValid();
        return _locale._validateOnSet;
    }

    public void invalidate_text() {
        _locale.enter();

        try {
            assert isValid();

            if (isOccupied()) {
                if (hasTextNoEnsureOccupancy() || hasChildren()) {
                    TypeStoreUser user = _user;
                    _user = null;

                    Cur c = tempCur();
                    c.moveNodeContents(null, false);
                    c.release();

                    assert _user == null;
                    _user = user;
                }

                setBit(VACANT);
            }

            assert isValid();
        } finally {
            _locale.exit();
        }
    }

    public String fetch_text(int wsr) {
        _locale.enter();

        try {
            assert isValid() && isOccupied();

            return getValueAsString(wsr);
        } finally {
            _locale.exit();
        }
    }

    public XmlCursor new_cursor() {
        _locale.enter();

        try {
            Cur c = tempCur();
            XmlCursor xc = new Cursor(c);
            c.release();
            return xc;

        } finally {
            _locale.exit();
        }
    }

    public SchemaField get_schema_field() {
        assert isValid();

        if (isRoot()) {
            return null;
        }

        TypeStoreUser parentUser = ensureParent().getUser();

        if (isAttr()) {
            return parentUser.get_attribute_field(_name);
        }

        assert isElem();

        TypeStoreVisitor visitor = parentUser.new_visitor();

        if (visitor == null) {
            return null;
        }

        for (Xobj x = _parent._firstChild; ; x = x._nextSibling) {
            if (x.isElem()) {
                visitor.visit(x._name);

                if (x == this) {
                    return visitor.get_schema_field();
                }
            }
        }
    }

    public void validate(ValidatorListener eventSink) {
        _locale.enter();

        try {
            Cur c = tempCur();
            Validate validate = new Validate(c, eventSink);
            c.release();
        } finally {
            _locale.exit();
        }
    }

    public TypeStoreUser change_type(SchemaType type) {
        _locale.enter();

        try {
            Cur c = tempCur();
            c.setType(type, false);
            c.release();
        } finally {
            _locale.exit();
        }

        return getUser();
    }

    public TypeStoreUser substitute(QName name, SchemaType type) {
        _locale.enter();

        try {
            Cur c = tempCur();
            c.setSubstitution(name, type);
            c.release();
        } finally {
            _locale.exit();
        }

        return getUser();
    }

    public QName get_xsi_type() {
        return getXsiTypeName();
    }

    public void store_text(String text) {
        _locale.enter();

        TypeStoreUser user = _user;
        _user = null;

        try {
            Cur c = tempCur();

            c.moveNodeContents(null, false);

            if (text != null && text.length() > 0) {
                c.next();
                c.insertString(text);
            }

            c.release();
        } finally {
            assert _user == null;
            _user = user;

            _locale.exit();
        }
    }

    public int compute_flags() {
        if (isRoot()) {
            return 0;
        }

        TypeStoreUser parentUser = ensureParent().getUser();

        if (isAttr()) {
            return parentUser.get_attributeflags(_name);
        }

        int f = parentUser.get_elementflags(_name);

        if (f != -1) {
            return f;
        }

        TypeStoreVisitor visitor = parentUser.new_visitor();

        if (visitor == null) {
            return 0;
        }

        for (Xobj x = _parent._firstChild; ; x = x._nextSibling) {
            if (x.isElem()) {
                visitor.visit(x._name);

                if (x == this) {
                    return visitor.get_elementflags();
                }
            }
        }
    }

    public String compute_default_text() {
        if (isRoot()) {
            return null;
        }

        TypeStoreUser parentUser = ensureParent().getUser();

        if (isAttr()) {
            return parentUser.get_default_attribute_text(_name);
        }

        String result = parentUser.get_default_element_text(_name);

        if (result != null) {
            return result;
        }

        TypeStoreVisitor visitor = parentUser.new_visitor();

        if (visitor == null) {
            return null;
        }

        for (Xobj x = _parent._firstChild; ; x = x._nextSibling) {
            if (x.isElem()) {
                visitor.visit(x._name);

                if (x == this) {
                    return visitor.get_default_text();
                }
            }
        }
    }

    public boolean find_nil() {
        if (isAttr()) {
            return false;
        }

        _locale.enter();

        try {
            Xobj a = getAttr(Locale._xsiNil);

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

            String value = a.getValueAsString(Locale.WS_COLLAPSE);

            return value.equals("true") || value.equals("1");
        } finally {
            _locale.exit();
        }
    }

    public void invalidate_nil() {
        if (isAttr()) {
            return;
        }

        _locale.enter();

        try {
            if (!_user.build_nil()) {
                removeAttr(Locale._xsiNil);
            } else {
                setAttr(Locale._xsiNil, "true");
            }
        } finally {
            _locale.exit();
        }
    }

    public int count_elements(QName name) {
        return _locale.count(this, name, null);
    }

    public int count_elements(QNameSet names) {
        return _locale.count(this, null, names);
    }

    public TypeStoreUser find_element_user(QName name, int i) {
        for (Xobj x = _firstChild; x != null; x = x._nextSibling) {
            if (x.isElem() && x._name.equals(name) && --i < 0) {
                return x.getUser();
            }
        }

        return null;
    }

    public TypeStoreUser find_element_user(QNameSet names, int i) {
        for (Xobj x = _firstChild; x != null; x = x._nextSibling) {
            if (x.isElem() && names.contains(x._name) && --i < 0) {
                return x.getUser();
            }
        }

        return null;
    }

    public void find_all_element_users(QName name, List fillMeUp) {
        for (Xobj x = _firstChild; x != null; x = x._nextSibling) {
            if (x.isElem() && x._name.equals(name)) {
                fillMeUp.add(x.getUser());
            }
        }
    }

    public void find_all_element_users(QNameSet names, List fillMeUp) {
        for (Xobj x = _firstChild; x != null; x = x._nextSibling) {
            if (x.isElem() && names.contains(x._name)) {
                fillMeUp.add(x.getUser());
            }
        }
    }

    private static TypeStoreUser insertElement(QName name, Xobj x, int pos) {
        x._locale.enter();

        try {
            Cur c = x._locale.tempCur();
            c.moveTo(x, pos);
            c.createElement(name);
            TypeStoreUser user = c.getUser();
            c.release();
            return user;
        } finally {
            x._locale.exit();
        }
    }

    public TypeStoreUser insert_element_user(QName name, int i) {
        if (i < 0) {
            throw new IndexOutOfBoundsException();
        }

        if (!isContainer()) {
            throw new IllegalStateException();
        }

        Xobj x = _locale.findNthChildElem(this, name, null, i);

        if (x == null) {
            if (i > _locale.count(this, name, null) + 1) {
                throw new IndexOutOfBoundsException();
            }

            return add_element_user(name);
        }

        return insertElement(name, x, 0);
    }

    public TypeStoreUser insert_element_user(QNameSet names, QName name, int i) {
        if (i < 0) {
            throw new IndexOutOfBoundsException();
        }

        if (!isContainer()) {
            throw new IllegalStateException();
        }

        Xobj x = _locale.findNthChildElem(this, null, names, i);

        if (x == null) {
            if (i > _locale.count(this, null, names) + 1) {
                throw new IndexOutOfBoundsException();
            }

            return add_element_user(name);
        }

        return insertElement(name, x, 0);
    }

    public TypeStoreUser add_element_user(QName name) {
        if (!isContainer()) {
            throw new IllegalStateException();
        }

        QNameSet endSet = null;
        boolean gotEndSet = false;

        Xobj candidate = null;

        for (Xobj x = _lastChild; x != null; x = x._prevSibling) {
            if (x.isContainer()) {
                if (x._name.equals(name)) {
                    break;
                }

                if (!gotEndSet) {
                    endSet = _user.get_element_ending_delimiters(name);
                    gotEndSet = true;
                }

                if (endSet == null || endSet.contains(x._name)) {
                    candidate = x;
                }
            }
        }

        return
            candidate == null
                ? insertElement(name, this, END_POS)
                : insertElement(name, candidate, 0);
    }

    private static void removeElement(Xobj x) {
        if (x == null) {
            throw new IndexOutOfBoundsException();
        }

        x._locale.enter();

        try {
            Cur c = x.tempCur();
            c.moveNode(null);
            c.release();
        } finally {
            x._locale.exit();
        }
    }

    public void remove_element(QName name, int i) {
        if (i < 0) {
            throw new IndexOutOfBoundsException();
        }

        if (!isContainer()) {
            throw new IllegalStateException();
        }

        Xobj x;

        for (x = _firstChild; x != null; x = x._nextSibling) {
            if (x.isElem() && x._name.equals(name) && --i < 0) {
                break;
            }
        }

        removeElement(x);
    }

    public void remove_element(QNameSet names, int i) {
        if (i < 0) {
            throw new IndexOutOfBoundsException();
        }

        if (!isContainer()) {
            throw new IllegalStateException();
        }

        Xobj x;

        for (x = _firstChild; x != null; x = x._nextSibling) {
            if (x.isElem() && names.contains(x._name) && --i < 0) {
                break;
            }
        }

        removeElement(x);
    }

    public TypeStoreUser find_attribute_user(QName name) {
        Xobj a = getAttr(name);

        return a == null ? null : a.getUser();
    }

    public TypeStoreUser add_attribute_user(QName name) {
        if (getAttr(name) != null) {
            throw new IndexOutOfBoundsException();
        }

        _locale.enter();

        try {
            return setAttr(name, "").getUser();
        } finally {
            _locale.exit();
        }
    }

    public void remove_attribute(QName name) {
        _locale.enter();

        try {
            if (!removeAttr(name)) {
                throw new IndexOutOfBoundsException();
            }
        } finally {
            _locale.exit();
        }
    }

    public TypeStoreUser copy_contents_from(TypeStore source) {
        Xobj xSrc = (Xobj) source;

        if (xSrc == this) {
            return getUser();
        }

        _locale.enter();

        try {
            xSrc._locale.enter();

            Cur c = tempCur();

            try {
                Cur cSrc1 = xSrc.tempCur();
                Map<String, String> sourceNamespaces = Locale.getAllNamespaces(cSrc1, null);
                cSrc1.release();

                if (isAttr()) {
                    Cur cSrc = xSrc.tempCur();
                    String value = Locale.getTextValue(cSrc);
                    cSrc.release();

                    c.setValue(value);
                } else {
                    // Here I save away the user of this node so that it does not get whacked
                    // in the following operations.

                    disconnectChildrenUsers();

                    assert !inhibitDisconnect();

                    setBit(INHIBIT_DISCONNECT);

                    QName xsiType = isContainer() ? getXsiTypeName() : null;

                    Xobj copy = xSrc.copyNode(_locale);

                    Cur.moveNodeContents(this, null, true);

                    c.next();

                    Cur.moveNodeContents(copy, c, true);

                    c.moveTo(this);

                    if (xsiType != null) {
                        c.setXsiType(xsiType);
                    }

                    assert inhibitDisconnect();
                    clearBit(INHIBIT_DISCONNECT);
                }

                if (sourceNamespaces != null) {
                    if (!c.isContainer()) {
                        c.toParent();
                    }

                    Locale.applyNamespaces(c, sourceNamespaces);
                }

            } finally {
                c.release();

                xSrc._locale.exit();
            }
        } finally {
            _locale.exit();
        }

        return getUser();
    }

    public TypeStoreUser copy(SchemaTypeLoader stl, SchemaType type, XmlOptions options) {
        //do not use a user's Factory method for copying.
        //XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
        Xobj destination = null;
        options = XmlOptions.maskNull(options);
        SchemaType sType = options.getDocumentType();

        if (sType == null) {
            sType = type == null ? XmlObject.type : type;
        }

        Locale locale = this.locale();
        if (options.isCopyUseNewSynchronizationDomain()) {
            locale = Locale.getLocale(stl, options);
        }

        if (sType.isDocumentType() || (sType.isNoType() && (this instanceof DocumentXobj))) {
            destination = Cur.createDomDocumentRootXobj(locale, false);
        } else {
            destination = Cur.createDomDocumentRootXobj(locale, true);
        }


        locale.enter();
        try {
            Cur c = destination.tempCur();
            c.setType(type);
            c.release();
        } finally {
            locale.exit();
        }

        TypeStoreUser tsu = destination.copy_contents_from(this);
        return tsu;
    }

    public void array_setter(XmlObject[] sources, QName elementName) {
        _locale.enter();

        try {
            // TODO - this is the quick and dirty implementation, make this faster

            int m = sources.length;

            ArrayList copies = new ArrayList();
            ArrayList types = new ArrayList();

            for (int i = 0; i < m; i++) {
                // TODO - deal with null sources[ i ] here -- what to do?

                if (sources[i] == null) {
                    throw new IllegalArgumentException("Array element null");
                } else if (sources[i].isImmutable()) {
                    copies.add(null);
                    types.add(null);
                } else {
                    Xobj x = ((Xobj) ((TypeStoreUser) sources[i]).get_store());

                    if (x._locale == _locale) {
                        copies.add(x.copyNode(_locale));
                    } else {
                        x._locale.enter();

                        try {
                            copies.add(x.copyNode(_locale));
                        } finally {
                            x._locale.exit();
                        }
                    }

                    types.add(sources[i].schemaType());
                }
            }

            int n = count_elements(elementName);

            for (; n > m; n--) {
                remove_element(elementName, m);
            }

            for (; m > n; n++) {
                add_element_user(elementName);
            }

            assert m == n;

            ArrayList elements = new ArrayList();

            find_all_element_users(elementName, elements);

            for (int i = 0; i < elements.size(); i++) {
                elements.set(i, (Xobj) ((TypeStoreUser) elements.get(i)).get_store());
            }

            assert elements.size() == n;

            Cur c = tempCur();

            for (int i = 0; i < n; i++) {
                Xobj x = (Xobj) elements.get(i);

                if (sources[i].isImmutable()) {
                    x.getObject().set(sources[i]);
                } else {
                    Cur.moveNodeContents(x, null, true);

                    c.moveTo(x);
                    c.next();

                    Cur.moveNodeContents((Xobj) copies.get(i), c, true);

                    x.change_type((SchemaType) types.get(i));
                }
            }

            c.release();
        } finally {
            _locale.exit();
        }
    }

    public void visit_elements(TypeStoreVisitor visitor) {
        throw new RuntimeException("Not implemeneted");
    }

    public XmlObject[] exec_query(String queryExpr, XmlOptions options) throws XmlException {
        _locale.enter();

        try {
            Cur c = tempCur();

            XmlObject[] result = Query.objectExecQuery(c, queryExpr, options);

            c.release();

            return result;
        } finally {
            _locale.exit();
        }
    }

    public String find_prefix_for_nsuri(String nsuri, String suggested_prefix) {
        _locale.enter();

        try {
            return prefixForNamespace(nsuri, suggested_prefix, true);
        } finally {
            _locale.exit();
        }
    }

    public String getNamespaceForPrefix(String prefix) {
        return namespaceForPrefix(prefix, true);
    }

    Locale _locale;
    QName _name;

    Cur _embedded;

    Bookmark _bookmarks;

    int _bits;

    Xobj _parent;
    Xobj _nextSibling;
    Xobj _prevSibling;
    Xobj _firstChild;
    Xobj _lastChild;

    Object _srcValue, _srcAfter;
    int _offValue, _offAfter;
    int _cchValue, _cchAfter;

    // TODO - put this in a ptr off this node
    CharNode _charNodesValue;
    CharNode _charNodesAfter;

    // TODO - put this in a ptr off this node
    TypeStoreUser _user;
}
