/*   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.XmlCursor;
import org.apache.xmlbeans.XmlDocumentProperties;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.common.GlobalLock;
import org.apache.xmlbeans.impl.common.XMLChar;
import org.apache.xmlbeans.impl.store.Locale.ChangeListener;
import org.apache.xmlbeans.impl.store.Saver.TextSaver;
import org.apache.xmlbeans.impl.xpath.XPathEngine;
import org.apache.xmlbeans.impl.xpath.XPathFactory;
import org.apache.xmlbeans.xml.stream.XMLInputStream;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;

public final class Cursor implements XmlCursor, ChangeListener {
    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 TEXT = Cur.TEXT;

    private Cur _cur;
    private XPathEngine _pathEngine;
    private int _currentSelection;

    private ChangeListener _nextChangeListener;

    Cursor(Xobj x, int p) {
        _cur = x._locale.weakCur(this);
        _cur.moveTo(x, p);
        _currentSelection = -1;
    }

    public Cursor(Cur c) {
        this(c._xobj, c._pos);
    }

    private static boolean isValid(Cur c) {
        if (c.kind() <= 0) {
            c.push();

            if (c.toParentRaw()) {
                int pk = c.kind();

                if (pk == COMMENT || pk == PROCINST || pk == ATTR) {
                    return false;
                }
            }

            c.pop();
        }

        return true;
    }

    private boolean isValid() {
        return isValid(_cur);
    }

    Locale locale() {
        return _cur._locale;
    }

    Cur tempCur() {
        return _cur.tempCur();
    }

    public void dump(PrintStream o) {
        _cur.dump(o);
    }

    static void validateLocalName(QName name) {
        if (name == null) {
            throw new IllegalArgumentException("QName is null");
        }

        validateLocalName(name.getLocalPart());
    }

    static void validateLocalName(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Name is null");
        }

        if (name.length() == 0) {
            throw new IllegalArgumentException("Name is empty");
        }

        if (!XMLChar.isValidNCName(name)) {
            throw new IllegalArgumentException("Name is not valid");
        }
    }

    static void validatePrefix(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Prefix is null");
        }

        if (name.length() == 0) {
            throw new IllegalArgumentException("Prefix is empty");
        }

        if (Locale.beginsWithXml(name)) {
            throw new IllegalArgumentException("Prefix begins with 'xml'");
        }

        if (!XMLChar.isValidNCName(name)) {
            throw new IllegalArgumentException("Prefix is not valid");
        }
    }

    private static void complain(String msg) {
        throw new IllegalArgumentException(msg);
    }

    private void checkInsertionValidity(Cur that) {
        int thatKind = that.kind();

        if (thatKind < 0) {
            complain("Can't move/copy/insert an end token.");
        }

        if (thatKind == ROOT) {
            complain("Can't move/copy/insert a whole document.");
        }

        int thisKind = _cur.kind();

        if (thisKind == ROOT) {
            complain("Can't insert before the start of the document.");
        }

        if (thatKind == ATTR) {
            _cur.push();
            _cur.prevWithAttrs();
            int pk = _cur.kind();
            _cur.pop();

            if (pk != ELEM && pk != ROOT && pk != -ATTR) {
                complain("Can only insert attributes before other attributes or after containers.");
            }
        }

        if (thisKind == ATTR && thatKind != ATTR) {
            complain("Can only insert attributes before other attributes or after containers.");
        }
    }

    private void insertNode(Cur that, String text) {
        assert !that.isRoot();
        assert that.isNode();
        assert isValid(that);
        assert isValid();

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

        checkInsertionValidity(that);

        that.moveNode(_cur);

        _cur.toEnd();
        _cur.nextWithAttrs();
    }

    //
    //
    //

    // TODO - deal with cursors moving to other documents upon release?
    // Can I move the ref from one q to another?  If not I will have to
    // change from a phantom ref to a soft/weak ref so I can know what
    // to do when I dequeue from the old q.

    public void _dispose() {
        _cur.release();
        _cur = null;
    }

    public XmlCursor _newCursor() {
        return new Cursor(_cur);
    }

    public QName _getName() {
        // TODO - consider taking this out of the gateway

        switch (_cur.kind()) {
            case ATTR:

                if (_cur.isXmlns()) {
                    return
                        _cur._locale.makeQNameNoCheck(_cur.getXmlnsUri(), _cur.getXmlnsPrefix());
                }

                // Fall thru

            case ELEM:
            case PROCINST:
                return _cur.getName();
        }

        return null;
    }

    public void _setName(QName name) {
        if (name == null) {
            throw new IllegalArgumentException("Name is null");
        }

        switch (_cur.kind()) {
            case ELEM:
            case ATTR: {
                validateLocalName(name.getLocalPart());
                break;
            }

            case PROCINST: {
                validatePrefix(name.getLocalPart());

                if (name.getNamespaceURI().length() > 0) {
                    throw new IllegalArgumentException("Procinst name must have no URI");
                }

                if (name.getPrefix().length() > 0) {
                    throw new IllegalArgumentException("Procinst name must have no prefix");
                }

                break;
            }

            default:
                throw
                    new IllegalStateException("Can set name on element, atrtribute and procinst only");
        }

        _cur.setName(name);
    }

    public TokenType _currentTokenType() {
        assert isValid();

        switch (_cur.kind()) {
            case ROOT:
                return TokenType.STARTDOC;
            case -ROOT:
                return TokenType.ENDDOC;
            case ELEM:
                return TokenType.START;
            case -ELEM:
                return TokenType.END;
            case TEXT:
                return TokenType.TEXT;
            case ATTR:
                return _cur.isXmlns() ? TokenType.NAMESPACE : TokenType.ATTR;
            case COMMENT:
                return TokenType.COMMENT;
            case PROCINST:
                return TokenType.PROCINST;

            default:
                throw new IllegalStateException();
        }
    }

    public boolean _isStartdoc() {
        //return _currentTokenType().isStartdoc();
        assert isValid();
        return _cur.isRoot();
    }

    public boolean _isEnddoc() {
        //return _currentTokenType().isEnddoc();
        assert isValid();
        return _cur.isEndRoot();
    }

    public boolean _isStart() {
        //return _currentTokenType().isStart();
        assert isValid();
        return _cur.isElem();
    }

    public boolean _isEnd() {
        //return _currentTokenType().isEnd();
        assert isValid();
        return _cur.isEnd();
    }

    public boolean _isText() {
        //return _currentTokenType().isText();
        assert isValid();
        return _cur.isText();
    }

    public boolean _isAttr() {
        //return _currentTokenType().isAttr();
        assert isValid();
        return _cur.isNormalAttr();
    }

    public boolean _isNamespace() {
        //return _currentTokenType().isNamespace();
        assert isValid();
        return _cur.isXmlns();
    }

    public boolean _isComment() {
        //return _currentTokenType().isComment();
        assert isValid();
        return _cur.isComment();
    }

    public boolean _isProcinst() {
        //return _currentTokenType().isProcinst();
        assert isValid();
        return _cur.isProcinst();
    }

    public boolean _isContainer() {
        //return _currentTokenType().isContainer();
        assert isValid();
        return _cur.isContainer();
    }

    public boolean _isFinish() {
        //return _currentTokenType().isFinish();
        assert isValid();
        return _cur.isFinish();
    }

    public boolean _isAnyAttr() {
        //return _currentTokenType().isAnyAttr();
        assert isValid();
        return _cur.isAttr();
    }

    public TokenType _toNextToken() {
        assert isValid();

        switch (_cur.kind()) {
            case ROOT:
            case ELEM: {
                if (!_cur.toFirstAttr()) {
                    _cur.next();
                }

                break;
            }

            case ATTR: {
                if (!_cur.toNextSibling()) {
                    _cur.toParent();
                    _cur.next();
                }

                break;
            }

            case COMMENT:
            case PROCINST: {
                _cur.skip();
                break;
            }

            default: {
                if (!_cur.next()) {
                    return TokenType.NONE;
                }

                break;
            }
        }

        return _currentTokenType();
    }

    public TokenType _toPrevToken() {
        assert isValid();

        // This method is different than the Cur version of prev in a few ways.  First,
        // Cursor iterates over attrs inline with all the other content.  Cur will skip attrs, or
        // if the Cur in in attrs, it will not jump out of attrs.  Also, if moving backwards and
        // text is to the left and right, Cur will move to the beginning of that text, while
        // Cursor will move further so that the token type to the right is not text.

        boolean wasText = _cur.isText();

        if (!_cur.prev()) {
            assert _cur.isRoot() || _cur.isAttr();

            if (_cur.isRoot()) {
                return TokenType.NONE;
            }

            _cur.toParent();
        } else {
            int k = _cur.kind();

            if (k == -COMMENT || k == -PROCINST || k == -ATTR) {
                _cur.toParent();
            } else if (_cur.isContainer()) {
                _cur.toLastAttr();
            } else if (wasText && _cur.isText()) {
                return _toPrevToken();
            }
        }

        return _currentTokenType();
    }

    public Object _monitor() {
        // TODO - some of these methods need not be protected by a
        //  gatway.  This is one of them.  Inline this.

        return _cur._locale;
    }

    public boolean _toParent() {
        Cur c = _cur.tempCur();

        if (!c.toParent()) {
            return false;
        }

        _cur.moveToCur(c);

        c.release();

        return true;
    }

    private static final class ChangeStampImpl implements ChangeStamp {
        ChangeStampImpl(Locale l) {
            _locale = l;
            _versionStamp = _locale.version();
        }

        public boolean hasChanged() {
            return _versionStamp != _locale.version();
        }

        private final Locale _locale;
        private final long _versionStamp;
    }

    public ChangeStamp _getDocChangeStamp() {
        return new ChangeStampImpl(_cur._locale);
    }

    //
    // These simply delegate to the version of the method which takes XmlOptions
    //

    /**
     * @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
     */
    public XMLInputStream _newXMLInputStream() {
        return _newXMLInputStream(null);
    }

    public XMLStreamReader _newXMLStreamReader() {
        return _newXMLStreamReader(null);
    }

    public Node _newDomNode() {
        return _newDomNode(null);
    }

    public InputStream _newInputStream() {
        return _newInputStream(null);
    }

    public String _xmlText() {
        return _xmlText(null);
    }

    public Reader _newReader() {
        return _newReader(null);
    }

    public void _save(File file) throws IOException {
        _save(file, null);
    }

    public void _save(OutputStream os) throws IOException {
        _save(os, null);
    }

    public void _save(Writer w) throws IOException {
        _save(w, null);
    }

    public void _save(ContentHandler ch, LexicalHandler lh) throws SAXException {
        _save(ch, lh, null);
    }

    //
    //
    //

    public XmlDocumentProperties _documentProperties() {
        return Locale.getDocProps(_cur, true);
    }

    public XMLStreamReader _newXMLStreamReader(XmlOptions options) {
        return Jsr173.newXmlStreamReader(_cur, options);
    }

    /**
     * @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
     */
    public XMLInputStream _newXMLInputStream(XmlOptions options) {
        return new Saver.XmlInputStreamImpl(_cur, options);
    }

    public String _xmlText(XmlOptions options) {
        assert isValid();

        return new TextSaver(_cur, options, null).saveToString();
    }

    public InputStream _newInputStream(XmlOptions options) {
        return new Saver.InputStreamSaver(_cur, options);
    }

    public Reader _newReader(XmlOptions options) {
        return new Saver.TextReader(_cur, options);
    }

    public void _save(ContentHandler ch, LexicalHandler lh, XmlOptions options)
        throws SAXException {
        new Saver.SaxSaver(_cur, options, ch, lh);
    }

    public void _save(File file, XmlOptions options) throws IOException {
        if (file == null) {
            throw new IllegalArgumentException("Null file specified");
        }

        try (OutputStream os = new FileOutputStream(file)) {
            _save(os, options);
        }
    }

    public void _save(OutputStream os, XmlOptions options) throws IOException {
        if (os == null) {
            throw new IllegalArgumentException("Null OutputStream specified");
        }

        try (InputStream is = _newInputStream(options)) {
            byte[] bytes = new byte[8192];

            for (; ; ) {
                int n = is.read(bytes);

                if (n < 0) {
                    break;
                }

                os.write(bytes, 0, n);
            }
        }
    }

    public void _save(Writer w, XmlOptions options) throws IOException {
        if (w == null) {
            throw new IllegalArgumentException("Null Writer specified");
        }

        if (options != null && options.isSaveOptimizeForSpeed()) {
            Saver.OptimizedForSpeedSaver.save(_cur, w); //ignore all other options
            return;
        }

        try (Reader r = _newReader(options)) {
            char[] chars = new char[8192];

            for (; ; ) {
                int n = r.read(chars);

                if (n < 0) {
                    break;
                }

                w.write(chars, 0, n);
            }
        }
    }

    public Node _getDomNode() {
        return (Node) _cur.getDom();
    }

    private boolean isDomFragment() {
        if (!isStartdoc()) {
            return true;
        }

        boolean seenElement = false;

        XmlCursor c = newCursor();
        int token = c.toNextToken().intValue();

        try {
            LOOP:
            for (; ; ) {
                switch (token) {
                    case TokenType.INT_START:
                        if (seenElement) {
                            return true;
                        }
                        seenElement = true;
                        token = c.toEndToken().intValue();
                        break;

                    case TokenType.INT_TEXT:
                        if (!Locale.isWhiteSpace(c.getChars())) {
                            return true;
                        }
                        token = c.toNextToken().intValue();
                        break;

                    case TokenType.INT_NONE:
                    case TokenType.INT_ENDDOC:
                        break LOOP;

                    case TokenType.INT_ATTR:
                    case TokenType.INT_NAMESPACE:
                        return true;

                    case TokenType.INT_END:
                    case TokenType.INT_COMMENT:
                    case TokenType.INT_PROCINST:
                        token = c.toNextToken().intValue();
                        break;

                    case TokenType.INT_STARTDOC:
                        assert false;
                        break LOOP;
                }
            }
        } finally {
            c.dispose();
        }

        return !seenElement;
    }

    public Node _newDomNode(XmlOptions options) {
        // Must ignore inner options for compat with v1.

        if (options != null && options.isSaveInner()) {
            options = new XmlOptions(options);
            options.setSaveInner(false);
        }

        return new DomSaver(_cur, isDomFragment(), options).saveDom();
    }

    public boolean _toCursor(Cursor other) {
        assert _cur._locale == other._cur._locale;

        _cur.moveToCur(other._cur);

        return true;
    }

    public void _push() {
        _cur.push();
    }

    public boolean _pop() {
        return _cur.pop();
    }

    public void notifyChange() {
        // Force any path to get exausted, cursor may be disposed, but still be on the notification
        // list.

        if (_cur != null) {
            _getSelectionCount();
        }
    }

    public void setNextChangeListener(ChangeListener listener) {
        _nextChangeListener = listener;
    }

    public ChangeListener getNextChangeListener() {
        return _nextChangeListener;
    }

    public void _selectPath(String path) {
        _selectPath(path, null);
    }

    public void _selectPath(String pathExpr, XmlOptions options) {
        _clearSelections();

        assert _pathEngine == null;

        _pathEngine = XPathFactory.getCompiledPath(pathExpr, options).execute(_cur, options);

        _cur._locale.registerForChange(this);
    }

    public boolean _hasNextSelection() {
        int curr = _currentSelection;
        push();

        try {
            return _toNextSelection();
        } finally {
            _currentSelection = curr;
            pop();
        }
    }

    public boolean _toNextSelection() {
        return _toSelection(_currentSelection + 1);
    }

    public boolean _toSelection(int i) {
        if (i < 0) {
            return false;
        }

        while (i >= _cur.selectionCount()) {
            if (_pathEngine == null) {
                return false;
            }

            if (!_pathEngine.next(_cur)) {
                _pathEngine.release();
                _pathEngine = null;

                return false;
            }
        }

        _cur.moveToSelection(_currentSelection = i);

        return true;
    }

    public int _getSelectionCount() {
        // Should never get to MAX_VALUE selection index, so, state should not change
        _toSelection(Integer.MAX_VALUE);

        return _cur.selectionCount();
    }

    public void _addToSelection() {
        _toSelection(Integer.MAX_VALUE);

        _cur.addToSelection();
    }

    public void _clearSelections() {
        if (_pathEngine != null) {
            _pathEngine.release();
            _pathEngine = null;
        }

        _cur.clearSelection();

        _currentSelection = -1;
    }

    public String _namespaceForPrefix(String prefix) {
        if (!_cur.isContainer()) {
            throw new IllegalStateException("Not on a container");
        }

        return _cur.namespaceForPrefix(prefix, true);
    }

    public String _prefixForNamespace(String ns) {
        if (ns == null || ns.length() == 0) {
            throw new IllegalArgumentException("Must specify a namespace");
        }

// Note: I loosen this requirement in v2, can call this from anywhere
//        if (!_cur.isContainer())
//            throw new IllegalStateException( "Not on a container" );

        return _cur.prefixForNamespace(ns, null, true);
    }

    public void _getAllNamespaces(Map<String, String> addToThis) {
        if (!_cur.isContainer()) {
            throw new IllegalStateException("Not on a container");
        }

        if (addToThis != null) {
            Locale.getAllNamespaces(_cur, addToThis);
        }
    }

    public XmlObject _getObject() {
        return _cur.getObject();
    }

    public TokenType _prevTokenType() {
        _cur.push();

        TokenType tt = _toPrevToken();

        _cur.pop();

        return tt;
    }

    public boolean _hasNextToken() {
        //return _cur.kind() != -ROOT;
        return _cur._pos != Cur.END_POS || _cur._xobj.kind() != ROOT;
    }

    public boolean _hasPrevToken() {
        return _cur.kind() != ROOT;
    }

    public TokenType _toFirstContentToken() {
        if (!_cur.isContainer()) {
            return TokenType.NONE;
        }

        _cur.next();

        return currentTokenType();
    }

    public TokenType _toEndToken() {
        if (!_cur.isContainer()) {
            return TokenType.NONE;
        }

        _cur.toEnd();

        return currentTokenType();
    }

    public boolean _toChild(String local) {
        return _toChild(null, local);
    }

    public boolean _toChild(QName name) {
        return _toChild(name, 0);
    }

    public boolean _toChild(int index) {
        return _toChild(null, index);
    }

    public boolean _toChild(String uri, String local) {
        validateLocalName(local);

        return _toChild(_cur._locale.makeQName(uri, local), 0);
    }

    public boolean _toChild(QName name, int index) {
        return Locale.toChild(_cur, name, index);
    }

    public int _toNextChar(int maxCharacterCount) {
        return _cur.nextChars(maxCharacterCount);
    }

    public int _toPrevChar(int maxCharacterCount) {
        return _cur.prevChars(maxCharacterCount);
    }

    public boolean _toPrevSibling() {
        return Locale.toPrevSiblingElement(_cur);
    }

    public boolean _toLastChild() {
        return Locale.toLastChildElement(_cur);
    }

    public boolean _toFirstChild() {
        return Locale.toFirstChildElement(_cur);
    }

    public boolean _toNextSibling(String name) {
        return _toNextSibling(new QName(name));
    }

    public boolean _toNextSibling(String uri, String local) {
        validateLocalName(local);

        return _toNextSibling(_cur._locale._qnameFactory.getQName(uri, local));
    }

    public boolean _toNextSibling(QName name) {
        _cur.push();

        while (___toNextSibling()) {
            if (_cur.getName().equals(name)) {
                _cur.popButStay();
                return true;
            }
        }

        _cur.pop();

        return false;
    }

    public boolean _toFirstAttribute() {
        return _cur.isContainer() && Locale.toFirstNormalAttr(_cur);
    }

    public boolean _toLastAttribute() {
        if (_cur.isContainer()) {
            _cur.push();
            _cur.push();

            boolean foundAttr = false;

            while (_cur.toNextAttr()) {
                if (_cur.isNormalAttr()) {
                    _cur.popButStay();
                    _cur.push();
                    foundAttr = true;
                }
            }

            _cur.pop();

            if (foundAttr) {
                _cur.popButStay();
                return true;
            }

            _cur.pop();
        }

        return false;
    }

    public boolean _toNextAttribute() {
        return _cur.isAttr() && Locale.toNextNormalAttr(_cur);
    }

    public boolean _toPrevAttribute() {
        return _cur.isAttr() && Locale.toPrevNormalAttr(_cur);
    }

    public String _getAttributeText(QName attrName) {
        if (attrName == null) {
            throw new IllegalArgumentException("Attr name is null");
        }

        if (!_cur.isContainer()) {
            return null;
        }

        return _cur.getAttrValue(attrName);
    }

    public boolean _setAttributeText(QName attrName, String value) {
        if (attrName == null) {
            throw new IllegalArgumentException("Attr name is null");
        }

        validateLocalName(attrName.getLocalPart());

        if (!_cur.isContainer()) {
            return false;
        }

        _cur.setAttrValue(attrName, value);

        return true;
    }

    public boolean _removeAttribute(QName attrName) {
        if (attrName == null) {
            throw new IllegalArgumentException("Attr name is null");
        }

        if (!_cur.isContainer()) {
            return false;
        }

        return _cur.removeAttr(attrName);
    }

    public String _getTextValue() {
        if (_cur.isText()) {
            return _getChars();
        }

        if (!_cur.isNode()) {
            throw new IllegalStateException("Can't get text value, current token can have no text value");
        }

        return _cur.hasChildren() ? Locale.getTextValue(_cur) : _cur.getValueAsString();
    }

    public int _getTextValue(char[] chars, int offset, int max) {
        if (_cur.isText()) {
            return _getChars(chars, offset, max);
        }

        if (chars == null) {
            throw new IllegalArgumentException("char buffer is null");
        }

        if (offset < 0) {
            throw new IllegalArgumentException("offset < 0");
        }

        if (offset >= chars.length) {
            throw new IllegalArgumentException("offset off end");
        }

        if (max < 0) {
            max = Integer.MAX_VALUE;
        }

        if (offset + max > chars.length) {
            max = chars.length - offset;
        }

        if (!_cur.isNode()) {
            throw new IllegalStateException("Can't get text value, current token can have no text value");
        }

        // If there are no children (hopefully the common case), I can get the text faster.

        if (_cur.hasChildren()) {
            return Locale.getTextValue(_cur, Locale.WS_PRESERVE, chars, offset, max);
        }

        // Fast way

        Object src = _cur.getFirstChars();

        if (_cur._cchSrc > max) {
            _cur._cchSrc = max;
        }

        if (_cur._cchSrc <= 0) {
            return 0;
        }

        CharUtil.getChars(chars, offset, src, _cur._offSrc, _cur._cchSrc);

        return _cur._cchSrc;
    }

    private void setTextValue(Object src, int off, int cch) {
        if (!_cur.isNode()) {
            throw new IllegalStateException("Can't set text value, current token can have no text value");
        }

        _cur.moveNodeContents(null, false);
        _cur.next();
        _cur.insertChars(src, off, cch);
        _cur.toParent();
    }

    public void _setTextValue(String text) {
        if (text == null) {
            text = "";
        }

        setTextValue(text, 0, text.length());
    }

    public void _setTextValue(char[] sourceChars, int offset, int length) {
        if (length < 0) {
            throw new IndexOutOfBoundsException("setTextValue: length < 0");
        }

        if (sourceChars == null) {
            if (length > 0) {
                throw new IllegalArgumentException("setTextValue: sourceChars == null");
            }

            setTextValue(null, 0, 0);

            return;
        }

        if (offset < 0 || offset >= sourceChars.length) {
            throw new IndexOutOfBoundsException("setTextValue: offset out of bounds");
        }

        if (offset + length > sourceChars.length) {
            length = sourceChars.length - offset;
        }

        CharUtil cu = _cur._locale.getCharUtil();

        setTextValue(cu.saveChars(sourceChars, offset, length), cu._offSrc, cu._cchSrc);
    }

    public String _getChars() {
        return _cur.getCharsAsString();
    }

    public int _getChars(char[] buf, int off, int cch) {
        int cchRight = _cur.cchRight();

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

        if (buf == null || off >= buf.length) {
            return 0;
        }

        if (buf.length - off < cch) {
            cch = buf.length - off;
        }

        Object src = _cur.getChars(cch);

        CharUtil.getChars(buf, off, src, _cur._offSrc, _cur._cchSrc);

        return _cur._cchSrc;
    }

    public void _toStartDoc() {
        _cur.toRoot();
    }

    public void _toEndDoc() {
        _toStartDoc();
        _cur.toEnd();
    }

    public int _comparePosition(Cursor other) {
        int s = _cur.comparePosition(other._cur);

        if (s == 2) {
            throw new IllegalArgumentException("Cursors not in same document");
        }

        assert s >= -1 && s <= 1;

        return s;
    }

    public boolean _isLeftOf(Cursor other) {
        return _comparePosition(other) < 0;
    }

    public boolean _isAtSamePositionAs(Cursor other) {
        return _cur.isSamePos(other._cur);
    }

    public boolean _isRightOf(Cursor other) {
        return _comparePosition(other) > 0;
    }

    public XmlCursor _execQuery(String query) {
        return _execQuery(query, null);
    }

    public XmlCursor _execQuery(String query, XmlOptions options) {
        checkThisCursor();
        return XPathFactory.cursorExecQuery(_cur, query, options);
    }


    public boolean _toBookmark(XmlBookmark bookmark) {
        if (bookmark == null || !(bookmark._currentMark instanceof Bookmark)) {
            return false;
        }

        Bookmark m = (Bookmark) bookmark._currentMark;

        if (m._xobj == null || m._xobj._locale != _cur._locale) {
            return false;
        }

        _cur.moveTo(m._xobj, m._pos);

        return true;
    }

    public XmlBookmark _toNextBookmark(Object key) {
        if (key == null) {
            return null;
        }

        int cch;

        _cur.push();

        for (; ; ) {
            // Move a minimal amount.  If at text, move to a potential bookmark in the text.

            if ((cch = _cur.cchRight()) > 1) {
                _cur.nextChars(1);
                _cur.nextChars((cch = _cur.firstBookmarkInChars(key, cch - 1)) >= 0 ? cch : -1);
            } else if (_toNextToken().isNone()) {
                _cur.pop();
                return null;
            }

            XmlBookmark bm = getBookmark(key, _cur);

            if (bm != null) {
                _cur.popButStay();
                return bm;
            }

            if (_cur.kind() == -ROOT) {
                _cur.pop();
                return null;
            }
        }
    }

    public XmlBookmark _toPrevBookmark(Object key) {
        if (key == null) {
            return null;
        }

        int cch;

        _cur.push();

        for (; ; ) {
            // Move a minimal amount.  If at text, move to a potential bookmark in the text.

            if ((cch = _cur.cchLeft()) > 1) {
                _cur.prevChars(1);

                _cur.prevChars((cch = _cur.firstBookmarkInCharsLeft(key, cch - 1)) >= 0 ? cch : -1);
            } else if (cch == 1) {
                // _toPrevToken will not skip to the beginning of the text, it will go further
                // so that the token to the right is not text.  I need to simply skip to
                // the beginning of the text ...

                _cur.prevChars(1);
            } else if (_toPrevToken().isNone()) {
                _cur.pop();
                return null;
            }

            XmlBookmark bm = getBookmark(key, _cur);

            if (bm != null) {
                _cur.popButStay();
                return bm;
            }

            if (_cur.kind() == ROOT) {
                _cur.pop();
                return null;
            }
        }
    }

    public void _setBookmark(XmlBookmark bookmark) {
        if (bookmark != null) {
            if (bookmark.getKey() == null) {
                throw new IllegalArgumentException("Annotation key is null");
            }

            // TODO - I Don't do weak bookmarks yet ... perhaps I'll never do them ....

            bookmark._currentMark = _cur.setBookmark(bookmark.getKey(), bookmark);
        }
    }

    static XmlBookmark getBookmark(Object key, Cur c) {
        // TODO - I Don't do weak bookmarks yet ...

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

        Object bm = c.getBookmark(key);

        return bm instanceof XmlBookmark ? (XmlBookmark) bm : null;
    }

    public XmlBookmark _getBookmark(Object key) {
        return key == null ? null : getBookmark(key, _cur);
    }

    public void _clearBookmark(Object key) {
        if (key != null) {
            _cur.setBookmark(key, null);
        }
    }

    public void _getAllBookmarkRefs(Collection listToFill) {
        if (listToFill != null) {
            for (Bookmark b = _cur._xobj._bookmarks; b != null; b = b._next) {
                if (b._value instanceof XmlBookmark) {
                    listToFill.add(b._value);
                }
            }
        }
    }

    public boolean _removeXml() {
        if (_cur.isRoot()) {
            throw new IllegalStateException("Can't remove a whole document.");
        }

        if (_cur.isFinish()) {
            return false;
        }

        assert _cur.isText() || _cur.isNode();

        if (_cur.isText()) {
            _cur.moveChars(null, -1);
        } else {
            _cur.moveNode(null);
        }

        return true;
    }

    public boolean _moveXml(Cursor to) {
        to.checkInsertionValidity(_cur);

        // Check for a no-op

        if (_cur.isText()) {
            int cchRight = _cur.cchRight();

            assert cchRight > 0;

            if (_cur.inChars(to._cur, cchRight, true)) {
                return false;
            }

            _cur.moveChars(to._cur, cchRight);

            to._cur.nextChars(cchRight);

            return true;
        }

        if (_cur.contains(to._cur)) {
            return false;
        }

        // Make a cur which will float to the right of the insertion

        Cur c = to.tempCur();

        _cur.moveNode(to._cur);

        to._cur.moveToCur(c);

        c.release();

        return true;
    }

    public boolean _copyXml(Cursor to) {
        to.checkInsertionValidity(_cur);

        assert _cur.isText() || _cur.isNode();

        Cur c = to.tempCur();

        if (_cur.isText()) {
            to._cur.insertChars(_cur.getChars(-1), _cur._offSrc, _cur._cchSrc);
        } else {
            _cur.copyNode(to._cur);
        }

        to._cur.moveToCur(c);

        c.release();

        return true;
    }

    public boolean _removeXmlContents() {
        if (!_cur.isContainer()) {
            return false;
        }

        _cur.moveNodeContents(null, false);

        return true;
    }

    private boolean checkContentInsertionValidity(Cursor to) {
        _cur.push();

        _cur.next();

        if (_cur.isFinish()) {
            _cur.pop();
            return false;
        }

        try {
            to.checkInsertionValidity(_cur);
        } catch (IllegalArgumentException e) {
            _cur.pop();
            throw e;
        }

        _cur.pop();

        return true;
    }

    public boolean _moveXmlContents(Cursor to) {
        if (!_cur.isContainer() || _cur.contains(to._cur)) {
            return false;
        }

        if (!checkContentInsertionValidity(to)) {
            return false;
        }

        Cur c = to.tempCur();

        _cur.moveNodeContents(to._cur, false);

        to._cur.moveToCur(c);

        c.release();

        return true;
    }

    public boolean _copyXmlContents(Cursor to) {
        if (!_cur.isContainer() || _cur.contains(to._cur)) {
            return false;
        }

        if (!checkContentInsertionValidity(to)) {
            return false;
        }

        // I don't have a primitive to copy contents, make a copy of the node and them move the
        // contents

        Cur c = _cur._locale.tempCur();

        _cur.copyNode(c);

        Cur c2 = to._cur.tempCur();

        c.moveNodeContents(to._cur, false);

        c.release();

        to._cur.moveToCur(c2);

        c2.release();

        return true;
    }

    public int _removeChars(int cch) {
        int cchRight = _cur.cchRight();

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

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

        _cur.moveChars(null, cch);

        return _cur._cchSrc;
    }

    public int _moveChars(int cch, Cursor to) {
        int cchRight = _cur.cchRight();

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

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

        to.checkInsertionValidity(_cur);

        _cur.moveChars(to._cur, cch);

        to._cur.nextChars(_cur._cchSrc);

        return _cur._cchSrc;
    }

    public int _copyChars(int cch, Cursor to) {
        int cchRight = _cur.cchRight();

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

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

        to.checkInsertionValidity(_cur);

        to._cur.insertChars(_cur.getChars(cch), _cur._offSrc, _cur._cchSrc);

        to._cur.nextChars(_cur._cchSrc);

        return _cur._cchSrc;
    }

    public void _insertChars(String text) {
        int l = text == null ? 0 : text.length();

        if (l > 0) {
            if (_cur.isRoot() || _cur.isAttr()) {
                throw
                    new IllegalStateException("Can't insert before the document or an attribute.");
            }

            _cur.insertChars(text, 0, l);
            _cur.nextChars(l);
        }
    }

    //
    // Inserting elements
    //

    public void _beginElement(String localName) {
        _insertElementWithText(localName, null, null);
        _toPrevToken();
    }

    public void _beginElement(String localName, String uri) {
        _insertElementWithText(localName, uri, null);
        _toPrevToken();
    }

    public void _beginElement(QName name) {
        _insertElementWithText(name, null);
        _toPrevToken();
    }

    public void _insertElement(String localName) {
        _insertElementWithText(localName, null, null);
    }

    public void _insertElement(String localName, String uri) {
        _insertElementWithText(localName, uri, null);
    }

    public void _insertElement(QName name) {
        _insertElementWithText(name, null);
    }

    public void _insertElementWithText(String localName, String text) {
        _insertElementWithText(localName, null, text);
    }

    public void _insertElementWithText(String localName, String uri, String text) {
        validateLocalName(localName);

        _insertElementWithText(_cur._locale.makeQName(uri, localName), text);
    }

    public void _insertElementWithText(QName name, String text) {
        validateLocalName(name.getLocalPart());

        Cur c = _cur._locale.tempCur();

        c.createElement(name);

        insertNode(c, text);

        c.release();
    }

    //
    //
    //

    public void _insertAttribute(String localName) {
        _insertAttributeWithValue(localName, null);
    }

    public void _insertAttribute(String localName, String uri) {
        _insertAttributeWithValue(localName, uri, null);
    }

    public void _insertAttribute(QName name) {
        _insertAttributeWithValue(name, null);
    }

    public void _insertAttributeWithValue(String localName, String value) {
        _insertAttributeWithValue(localName, null, value);
    }

    public void _insertAttributeWithValue(String localName, String uri, String value) {
        validateLocalName(localName);

        _insertAttributeWithValue(_cur._locale.makeQName(uri, localName), value);
    }

    public void _insertAttributeWithValue(QName name, String text) {
        validateLocalName(name.getLocalPart());

        Cur c = _cur._locale.tempCur();

        c.createAttr(name);

        insertNode(c, text);

        c.release();
    }

    //
    //
    //

    public void _insertNamespace(String prefix, String namespace) {
        _insertAttributeWithValue(_cur._locale.createXmlns(prefix), namespace);
    }

    public void _insertComment(String text) {
        Cur c = _cur._locale.tempCur();

        c.createComment();

        insertNode(c, text);

        c.release();
    }

    public void _insertProcInst(String target, String text) {
        validateLocalName(target);

        if (Locale.beginsWithXml(target) && target.length() == 3) {
            throw new IllegalArgumentException("Target is 'xml'");
        }

        Cur c = _cur._locale.tempCur();

        c.createProcinst(target);

        insertNode(c, text);

        c.release();
    }

    public void _dump() {
        _cur.dump();
    }

    //
    //
    //
    //
    //
    //
    //

    private void checkThisCursor() {
        if (_cur == null) {
            throw new IllegalStateException("This cursor has been disposed");
        }
    }

    private Cursor checkCursors(XmlCursor xOther) {
        checkThisCursor();

        if (xOther == null) {
            throw new IllegalArgumentException("Other cursor is <null>");
        }

        if (!(xOther instanceof Cursor)) {
            throw new IllegalArgumentException("Incompatible cursors: " + xOther);
        }

        Cursor other = (Cursor) xOther;

        if (other._cur == null) {
            throw new IllegalStateException("Other cursor has been disposed");
        }

        return other;
    }

    //
    // The following operations have two cursors, and can be in different documents
    //

    private static final int MOVE_XML = 0;
    private static final int COPY_XML = 1;
    private static final int MOVE_XML_CONTENTS = 2;
    private static final int COPY_XML_CONTENTS = 3;
    private static final int MOVE_CHARS = 4;
    private static final int COPY_CHARS = 5;

    private int twoLocaleOp(XmlCursor xOther, int op, int arg) {
        Cursor other = checkCursors(xOther);

        Locale locale = _cur._locale;
        Locale otherLocale = other._cur._locale;

        if (locale == otherLocale) {
            return syncWrapNoEnter(() -> twoLocaleOp(other, op, arg));
        }

        if (locale.noSync()) {
            if (otherLocale.noSync()) {
                return twoLocaleOp(other, op, arg);
            } else {
                synchronized (otherLocale) {
                    return twoLocaleOp(other, op, arg);
                }
            }
        } else if (otherLocale.noSync()) {
            synchronized (locale) {
                return twoLocaleOp(other, op, arg);
            }
        }

        boolean acquired = false;

        try {
            GlobalLock.acquire();
            acquired = true;

            synchronized (locale) {
                synchronized (otherLocale) {
                    GlobalLock.release();
                    acquired = false;

                    return twoLocaleOp(other, op, arg);
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (acquired) {
                GlobalLock.release();
            }
        }
    }

    private int twoLocaleOp(Cursor other, int op, int arg) {
        Locale locale = _cur._locale;
        Locale otherLocale = other._cur._locale;

        locale.enter(otherLocale);

        try {
            switch (op) {
                case MOVE_XML:
                    return _moveXml(other) ? 1 : 0;
                case COPY_XML:
                    return _copyXml(other) ? 1 : 0;
                case MOVE_XML_CONTENTS:
                    return _moveXmlContents(other) ? 1 : 0;
                case COPY_XML_CONTENTS:
                    return _copyXmlContents(other) ? 1 : 0;
                case MOVE_CHARS:
                    return _moveChars(arg, other);
                case COPY_CHARS:
                    return _copyChars(arg, other);

                default:
                    throw new RuntimeException("Unknown operation: " + op);
            }
        } finally {
            locale.exit(otherLocale);
        }
    }

    public boolean moveXml(XmlCursor xTo) {
        return twoLocaleOp(xTo, MOVE_XML, 0) == 1;
    }

    public boolean copyXml(XmlCursor xTo) {
        return twoLocaleOp(xTo, COPY_XML, 0) == 1;
    }

    public boolean moveXmlContents(XmlCursor xTo) {
        return twoLocaleOp(xTo, MOVE_XML_CONTENTS, 0) == 1;
    }

    public boolean copyXmlContents(XmlCursor xTo) {
        return twoLocaleOp(xTo, COPY_XML_CONTENTS, 0) == 1;
    }

    public int moveChars(int cch, XmlCursor xTo) {
        return twoLocaleOp(xTo, MOVE_CHARS, cch);
    }

    public int copyChars(int cch, XmlCursor xTo) {
        return twoLocaleOp(xTo, COPY_CHARS, cch);
    }


    //
    // Special methods involving multiple cursors which can be in different locales, but do not
    // require sync on both locales.
    //

    public boolean toCursor(XmlCursor xOther) {
        // One may only move cursors within the same locale

        Cursor other = checkCursors(xOther);

        return _cur._locale == other._cur._locale &&
               syncWrap(() -> _toCursor(other));
    }

    public boolean isInSameDocument(XmlCursor xOther) {
        return xOther != null && _cur.isInSameTree(checkCursors(xOther)._cur);
    }

    //
    // The following operations have two cursors, but they must be in the same document
    //

    private Cursor preCheck(XmlCursor xOther) {
        Cursor other = checkCursors(xOther);

        if (_cur._locale != other._cur._locale) {
            throw new IllegalArgumentException("Cursors not in same document");
        }

        return other;
    }

    public int comparePosition(XmlCursor xOther) {
        Cursor other = preCheck(xOther);
        return syncWrap(() -> _comparePosition(other));
    }

    public boolean isLeftOf(XmlCursor xOther) {
        Cursor other = preCheck(xOther);
        return syncWrap(() -> _isLeftOf(other));
    }

    public boolean isAtSamePositionAs(XmlCursor xOther) {
        Cursor other = preCheck(xOther);
        return syncWrap(() -> _isAtSamePositionAs(other));
    }

    public boolean isRightOf(XmlCursor xOther) {
        Cursor other = preCheck(xOther);
        return syncWrap(() -> _isRightOf(other));
    }

    //
    // Create a cursor from an Xobj -- used for XmlBookmark.createCursor
    //

    public static XmlCursor newCursor(Xobj x, int p) {
        Locale l = x._locale;
        if (l.noSync()) {
            l.enter();
            try {
                return new Cursor(x, p);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return new Cursor(x, p);
                } finally {
                    l.exit();
                }
            }
        }
    }

    //
    // The following operations involve only one cursor
    //

    private boolean preCheck() {
        checkThisCursor();
        return _cur._locale.noSync();
    }

    public void dispose() {
        if (_cur != null) {
            syncWrap(this::_dispose);
        }
    }

    public Object monitor() {
        return syncWrap(this::_monitor);
    }

    public XmlDocumentProperties documentProperties() {
        return syncWrap(this::_documentProperties);
    }

    public XmlCursor newCursor() {
        return syncWrap(this::_newCursor);
    }

    public XMLStreamReader newXMLStreamReader() {
        return syncWrap((Supplier<XMLStreamReader>) this::_newXMLStreamReader);
    }

    public XMLStreamReader newXMLStreamReader(XmlOptions options) {
        return syncWrap(() -> _newXMLStreamReader(options));
    }

    /**
     * @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
     */
    public XMLInputStream newXMLInputStream() {
        return syncWrap((Supplier<XMLInputStream>) this::_newXMLInputStream);
    }

    public String xmlText() {
        return syncWrap((Supplier<String>) this::_xmlText);
    }

    public InputStream newInputStream() {
        return syncWrap((Supplier<InputStream>) this::_newInputStream);
    }

    public Reader newReader() {
        return syncWrap((Supplier<Reader>) this::_newReader);
    }

    public Node newDomNode() {
        return syncWrap((Supplier<Node>) this::_newDomNode);
    }

    public Node getDomNode() {
        return syncWrap(this::_getDomNode);
    }

    public void save(ContentHandler ch, LexicalHandler lh) throws SAXException {
        syncWrapSAXEx(() -> _save(ch, lh));
    }

    public void save(File file) throws IOException {
        syncWrapIOEx(() -> _save(file));
    }

    public void save(OutputStream os) throws IOException {
        syncWrapIOEx(() -> _save(os));
    }

    public void save(Writer w) throws IOException {
        syncWrapIOEx(() -> _save(w));
    }

    /**
     * @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
     */
    public XMLInputStream newXMLInputStream(XmlOptions options) {
        return syncWrap(() -> _newXMLInputStream(options));
    }

    public String xmlText(XmlOptions options) {
        return syncWrap(() -> _xmlText(options));
    }

    public InputStream newInputStream(XmlOptions options) {
        return syncWrap(() -> _newInputStream(options));
    }

    public Reader newReader(XmlOptions options) {
        return syncWrap(() -> _newReader(options));
    }

    public Node newDomNode(XmlOptions options) {
        return syncWrap(() -> _newDomNode(options));
    }

    public void save(ContentHandler ch, LexicalHandler lh, XmlOptions options) throws SAXException {
        syncWrapSAXEx(() -> _save(ch, lh, options));
    }

    public void save(File file, XmlOptions options) throws IOException {
        syncWrapIOEx(() -> _save(file, options));
    }

    public void save(OutputStream os, XmlOptions options) throws IOException {
        syncWrapIOEx(() -> _save(os, options));
    }

    public void save(Writer w, XmlOptions options) throws IOException {
        syncWrapIOEx(() -> _save(w, options));
    }

    public void push() {
        syncWrap(this::_push);
    }

    public boolean pop() {
        return syncWrap(this::_pop);
    }

    public void selectPath(String path) {
        syncWrap(() -> _selectPath(path));
    }

    public void selectPath(String path, XmlOptions options) {
        syncWrap(() -> _selectPath(path, options));
    }

    public boolean hasNextSelection() {
        return syncWrap(this::_hasNextSelection);
    }

    public boolean toNextSelection() {
        return syncWrap(this::_toNextSelection);
    }

    public boolean toSelection(int i) {
        return syncWrap(() -> _toSelection(i));
    }

    public int getSelectionCount() {
        return syncWrap(this::_getSelectionCount);
    }

    public void addToSelection() {
        syncWrap(this::_addToSelection);
    }

    public void clearSelections() {
        syncWrap(this::_clearSelections);
    }

    public boolean toBookmark(XmlBookmark bookmark) {
        return syncWrap(() -> _toBookmark(bookmark));
    }

    public XmlBookmark toNextBookmark(Object key) {
        return syncWrap(() -> _toNextBookmark(key));
    }

    public XmlBookmark toPrevBookmark(Object key) {
        return syncWrap(() -> _toPrevBookmark(key));
    }

    public QName getName() {
        return syncWrap(this::_getName);
    }

    public void setName(QName name) {
        syncWrap(() -> _setName(name));
    }

    public String namespaceForPrefix(String prefix) {
        return syncWrap(() -> _namespaceForPrefix(prefix));
    }

    public String prefixForNamespace(String namespaceURI) {
        return syncWrap(() -> _prefixForNamespace(namespaceURI));
    }

    public void getAllNamespaces(Map<String, String> addToThis) {
        syncWrap(() -> _getAllNamespaces(addToThis));
    }

    public XmlObject getObject() {
        return syncWrap(this::_getObject);
    }

    public TokenType currentTokenType() {
        return syncWrapNoEnter(this::_currentTokenType);
    }

    public boolean isStartdoc() {
        return syncWrapNoEnter(this::_isStartdoc);
    }

    public boolean isEnddoc() {
        return syncWrapNoEnter(this::_isEnddoc);
    }

    public boolean isStart() {
        return syncWrapNoEnter(this::_isStart);
    }

    public boolean isEnd() {
        return syncWrapNoEnter(this::_isEnd);
    }

    public boolean isText() {
        return syncWrapNoEnter(this::_isText);
    }

    public boolean isAttr() {
        return syncWrapNoEnter(this::_isAttr);
    }

    public boolean isNamespace() {
        return syncWrapNoEnter(this::_isNamespace);
    }

    public boolean isComment() {
        return syncWrapNoEnter(this::_isComment);
    }

    public boolean isProcinst() {
        return syncWrapNoEnter(this::_isProcinst);
    }

    public boolean isContainer() {
        return syncWrapNoEnter(this::_isContainer);
    }

    public boolean isFinish() {
        return syncWrapNoEnter(this::_isFinish);
    }

    public boolean isAnyAttr() {
        return syncWrapNoEnter(this::_isAnyAttr);
    }

    public TokenType prevTokenType() {
        return syncWrap(this::_prevTokenType);
    }

    public boolean hasNextToken() {
        return syncWrapNoEnter(this::_hasNextToken);
    }

    public boolean hasPrevToken() {
        return syncWrap(this::_hasPrevToken);
    }

    public TokenType toNextToken() {
        return syncWrap(this::_toNextToken);
    }

    public TokenType toPrevToken() {
        return syncWrap(this::_toPrevToken);
    }

    public TokenType toFirstContentToken() {
        return syncWrap(this::_toFirstContentToken);
    }

    public TokenType toEndToken() {
        return syncWrap(this::_toEndToken);
    }

    public int toNextChar(int cch) {
        return syncWrap(() -> _toNextChar(cch));
    }

    public int toPrevChar(int cch) {
        return syncWrap(() -> _toPrevChar(cch));
    }

//    public boolean _toNextSibling()
//    {
//        return Locale.toNextSiblingElement(_cur);
//    }

    public boolean ___toNextSibling() {
        if (!_cur.hasParent()) {
            return false;
        }

        Xobj parent = _cur.getParentNoRoot();

        if (parent == null) {
            _cur._locale.enter();
            try {
                parent = _cur.getParent();
            } finally {
                _cur._locale.exit();
            }
        }

        return Locale.toNextSiblingElement(_cur, parent);
    }

    public boolean toNextSibling() {
        return syncWrapNoEnter(this::___toNextSibling);
    }

    public boolean toPrevSibling() {
        return syncWrap(this::_toPrevSibling);
    }

    public boolean toParent() {
        return syncWrap(this::_toParent);
    }

    public boolean toFirstChild() {
        return syncWrapNoEnter(this::_toFirstChild);
    }

    public boolean toLastChild() {
        return syncWrap(this::_toLastChild);
    }

    public boolean toChild(String name) {
        return syncWrap(() -> _toChild(name));
    }

    public boolean toChild(String namespace, String name) {
        return syncWrap(() -> _toChild(namespace, name));
    }

    public boolean toChild(QName name) {
        return syncWrap(() -> _toChild(name));
    }

    public boolean toChild(int index) {
        return syncWrap(() -> _toChild(index));
    }

    public boolean toChild(QName name, int index) {
        return syncWrap(() -> _toChild(name, index));
    }

    public boolean toNextSibling(String name) {
        return syncWrap(() -> _toNextSibling(name));
    }

    public boolean toNextSibling(String namespace, String name) {
        return syncWrap(() -> _toNextSibling(namespace, name));
    }

    public boolean toNextSibling(QName name) {
        return syncWrap(() -> _toNextSibling(name));
    }

    public boolean toFirstAttribute() {
        return syncWrapNoEnter(this::_toFirstAttribute);
    }

    public boolean toLastAttribute() {
        return syncWrap(this::_toLastAttribute);
    }

    public boolean toNextAttribute() {
        return syncWrap(this::_toNextAttribute);
    }

    public boolean toPrevAttribute() {
        return syncWrap(this::_toPrevAttribute);
    }

    public String getAttributeText(QName attrName) {
        return syncWrap(() -> _getAttributeText(attrName));
    }

    public boolean setAttributeText(QName attrName, String value) {
        return syncWrap(() -> _setAttributeText(attrName, value));
    }

    public boolean removeAttribute(QName attrName) {
        return syncWrap(() -> _removeAttribute(attrName));
    }

    public String getTextValue() {
        return syncWrap((Supplier<String>) this::_getTextValue);
    }

    public int getTextValue(char[] chars, int offset, int cch) {
        return syncWrap(() -> _getTextValue(chars, offset, cch));
    }

    public void setTextValue(String text) {
        syncWrap(() -> _setTextValue(text));
    }

    public void setTextValue(char[] sourceChars, int offset, int length) {
        syncWrap(() -> _setTextValue(sourceChars, offset, length));
    }

    public String getChars() {
        return syncWrap((Supplier<String>) this::_getChars);
    }

    public int getChars(char[] chars, int offset, int cch) {
        return syncWrap(() -> _getChars(chars, offset, cch));
    }

    public void toStartDoc() {
        syncWrapNoEnter(this::_toStartDoc);
    }

    public void toEndDoc() {
        syncWrapNoEnter(this::_toEndDoc);
    }

    public XmlCursor execQuery(String query) {
        return syncWrap(() -> _execQuery(query));
    }

    public XmlCursor execQuery(String query, XmlOptions options) {
        return syncWrap(() -> _execQuery(query, options));
    }

    public ChangeStamp getDocChangeStamp() {
        return syncWrap(this::_getDocChangeStamp);
    }

    public void setBookmark(XmlBookmark bookmark) {
        syncWrap(() -> _setBookmark(bookmark));
    }

    public XmlBookmark getBookmark(Object key) {
        return syncWrap(() -> _getBookmark(key));
    }

    public void clearBookmark(Object key) {
        syncWrap(() -> _clearBookmark(key));
    }

    public void getAllBookmarkRefs(Collection listToFill) {
        syncWrap(() -> _getAllBookmarkRefs(listToFill));
    }

    public boolean removeXml() {
        return syncWrap(this::_removeXml);
    }

    public boolean removeXmlContents() {
        return syncWrap(this::_removeXmlContents);
    }

    public int removeChars(int cch) {
        return syncWrap(() -> _removeChars(cch));
    }

    public void insertChars(String text) {
        syncWrap(() -> _insertChars(text));
    }

    public void insertElement(QName name) {
        syncWrap(() -> _insertElement(name));
    }

    public void insertElement(String localName) {
        syncWrap(() -> _insertElement(localName));
    }

    public void insertElement(String localName, String uri) {
        syncWrap(() -> _insertElement(localName, uri));
    }

    public void beginElement(QName name) {
        syncWrap(() -> _beginElement(name));
    }

    public void beginElement(String localName) {
        syncWrap(() -> _beginElement(localName));
    }

    public void beginElement(String localName, String uri) {
        syncWrap(() -> _beginElement(localName, uri));
    }

    public void insertElementWithText(QName name, String text) {
        syncWrap(() -> _insertElementWithText(name, text));
    }

    public void insertElementWithText(String localName, String text) {
        syncWrap(() -> _insertElementWithText(localName, text));
    }

    public void insertElementWithText(String localName, String uri, String text) {
        syncWrap(() -> _insertElementWithText(localName, uri, text));
    }

    public void insertAttribute(String localName) {
        syncWrap(() -> _insertAttribute(localName));
    }

    public void insertAttribute(String localName, String uri) {
        syncWrap(() -> _insertAttribute(localName, uri));
    }

    public void insertAttribute(QName name) {
        syncWrap(() -> _insertAttribute(name));
    }

    public void insertAttributeWithValue(String name, String value) {
        syncWrap(() -> _insertAttributeWithValue(name, value));
    }

    public void insertAttributeWithValue(String name, String uri, String value) {
        syncWrap(() -> _insertAttributeWithValue(name, uri, value));
    }

    public void insertAttributeWithValue(QName name, String value) {
        syncWrap(() -> _insertAttributeWithValue(name, value));
    }

    public void insertNamespace(String prefix, String namespace) {
        syncWrap(() -> _insertNamespace(prefix, namespace));
    }

    public void insertComment(String text) {
        syncWrap(() -> _insertComment(text));
    }

    public void insertProcInst(String target, String text) {
        syncWrap(() -> _insertProcInst(target, text));
    }

    public void dump() {
        syncWrap(this::_dump);
    }

    private interface WrapSAXEx {
        void run() throws SAXException;
    }

    private interface WrapIOEx {
        void run() throws IOException;
    }


    @SuppressWarnings("SynchronizeOnNonFinalField")
    private void syncWrap(Runnable inner) {
        if (preCheck()) {
            syncWrapHelper(inner, true);
        } else {
            synchronized (_cur._locale) {
                syncWrapHelper(inner, true);
            }
        }
    }

    @SuppressWarnings("SynchronizeOnNonFinalField")
    private <T> T syncWrap(Supplier<T> inner) {
        if (preCheck()) {
            return syncWrapHelper(inner, true);
        } else {
            synchronized (_cur._locale) {
                return syncWrapHelper(inner, true);
            }
        }
    }

    @SuppressWarnings("SynchronizeOnNonFinalField")
    private <T> T syncWrapNoEnter(Supplier<T> inner) {
        if (preCheck()) {
            return syncWrapHelper(inner, false);
        } else {
            synchronized (_cur._locale) {
                return syncWrapHelper(inner, false);
            }
        }
    }

    @SuppressWarnings("SynchronizeOnNonFinalField")
    private void syncWrapNoEnter(Runnable inner) {
        if (preCheck()) {
            syncWrapHelper(inner, false);
        } else {
            synchronized (_cur._locale) {
                syncWrapHelper(inner, false);
            }
        }
    }

    @SuppressWarnings("SynchronizeOnNonFinalField")
    private void syncWrapSAXEx(WrapSAXEx inner) throws SAXException {
        if (preCheck()) {
            syncWrapHelper(inner);
        } else {
            synchronized (_cur._locale) {
                syncWrapHelper(inner);
            }
        }
    }

    @SuppressWarnings("SynchronizeOnNonFinalField")
    private void syncWrapIOEx(WrapIOEx inner) throws IOException {
        if (preCheck()) {
            syncWrapHelper(inner);
        } else {
            synchronized (_cur._locale) {
                syncWrapHelper(inner);
            }
        }
    }

    private void syncWrapHelper(Runnable inner, final boolean enterLocale) {
        final Locale l = _cur._locale;
        if (enterLocale) {
            l.enter();
        }
        try {
            inner.run();
        } finally {
            if (enterLocale) {
                l.exit();
            }
        }
    }

    private <T> T syncWrapHelper(Supplier<T> inner, final boolean enterLocale) {
        final Locale l = _cur._locale;
        if (enterLocale) {
            l.enter();
        }
        try {
            return inner.get();
        } finally {
            if (enterLocale) {
                l.exit();
            }
        }
    }

    private void syncWrapHelper(WrapSAXEx inner) throws SAXException {
        final Locale l = _cur._locale;
        l.enter();
        try {
            inner.run();
        } finally {
            l.exit();
        }
    }

    private void syncWrapHelper(WrapIOEx inner) throws IOException {
        final Locale l = _cur._locale;
        l.enter();
        try {
            inner.run();
        } finally {
            l.exit();
        }
    }
}
