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

package org.apache.xmlbeans.impl.store;

import org.apache.xmlbeans.*;
import org.apache.xmlbeans.XmlCursor.XmlBookmark;
import org.apache.xmlbeans.impl.common.*;
import org.apache.xmlbeans.impl.store.Cur.Locations;
import org.apache.xmlbeans.impl.store.DomImpl.Dom;
import org.apache.xmlbeans.impl.store.Saaj.SaajCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.*;
import org.xml.sax.*;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

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

public final class Locale
    implements DOMImplementation, SaajCallback, XmlLocale {
    private static final Logger logger = LoggerFactory.getLogger(Locale.class);

    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;

    static final String _xsi = "http://www.w3.org/2001/XMLSchema-instance";
    static final String _schema = "http://www.w3.org/2001/XMLSchema";
    static final String _openFragUri = "http://www.openuri.org/fragment";
    static final String _xml1998Uri = "http://www.w3.org/XML/1998/namespace";
    static final String _xmlnsUri = "http://www.w3.org/2000/xmlns/";

    static final QName _xsiNil = new QName(_xsi, "nil", "xsi");
    static final QName _xsiType = new QName(_xsi, "type", "xsi");
    static final QName _xsiLoc = new QName(_xsi, "schemaLocation", "xsi");
    static final QName _xsiNoLoc = new QName(_xsi, "noNamespaceSchemaLocation",
        "xsi");
    static final QName _openuriFragment = new QName(_openFragUri, "fragment",
        "frag");
    static final QName _xmlFragment = new QName("xml-fragment");

    private Locale(SchemaTypeLoader stl, XmlOptions options) {
        options = XmlOptions.maskNull(options);

        //
        //
        //

        // TODO - add option for no=sync, or make it all thread safe
        //
        // Also - have a thread local setting for thread safety?  .. Perhaps something
        // in the type loader which defines whether ot not sync is on????

        _noSync = options.isUnsynchronized();

        _tempFrames = new Cur[_numTempFramesLeft = 8];

        // BUGBUG - this cannot be thread local ....
        // BUGBUG - this cannot be thread local ....
        // BUGBUG - this cannot be thread local .... uhh what, again?
        //
        // Lazy create this (loading up a locale should use the thread locale one)
        // same goes for the qname factory .. use thread local for hte most part when loading

        _qnameFactory = new DefaultQNameFactory(); //new LocalDocumentQNameFactory();

        _locations = new Locations(this);

        _schemaTypeLoader = stl;

        _validateOnSet = options.isValidateOnSet();

        //
        // Check for Saaj implementation request
        //

        _saaj = options.getSaaj();

        if (_saaj != null) {
            _saaj.setCallback(this);
        }
    }

    //
    //
    //

    public static Locale getLocale(SchemaTypeLoader stl, XmlOptions options) {
        if (stl == null) {
            stl = XmlBeans.getContextTypeLoader();
        }

        options = XmlOptions.maskNull(options);

        if (options.getUseSameLocale() == null) {
            return new Locale(stl, options);
        }

        Object source = options.getUseSameLocale();

        Locale l;

        if (source instanceof Locale) {
            l = (Locale) source;
        } else if (source instanceof XmlTokenSource) {
            l = (Locale) ((XmlTokenSource) source).monitor();
        } else {
            throw new IllegalArgumentException("Source locale not understood: " + source);
        }

        if (l._schemaTypeLoader != stl) {
            throw new IllegalArgumentException(
                "Source locale does not support same schema type loader");
        }

        if (l._saaj != null && l._saaj != options.getSaaj()) {
            throw new IllegalArgumentException(
                "Source locale does not support same saaj");
        }

        if (l._validateOnSet && !options.isValidateOnSet()) {
            throw new IllegalArgumentException(
                "Source locale does not support same validate on set");
        }

        // TODO - other things to check?

        return l;
    }

    //
    //
    //

    public static void associateSourceName(Cur c, XmlOptions options) {
        String sourceName = options == null ? null : options.getDocumentSourceName();

        if (sourceName != null) {
            getDocProps(c, true).setSourceName(sourceName);
        }
    }

    //
    //
    //

    public static void autoTypeDocument(Cur c, SchemaType requestedType,
                                        XmlOptions options)
        throws XmlException {
        assert c.isRoot();

        // The type in the options overrides all sniffing

        options = XmlOptions.maskNull(options);

        SchemaType optionType = options.getDocumentType();

        if (optionType != null) {
            c.setType(optionType);
            return;
        }

        SchemaType type = null;

        // An xsi:type can be used to pick a type out of the loader, or used to refine
        // a type with a name.

        if (requestedType == null || requestedType.getName() != null) {
            QName xsiTypeName = c.getXsiTypeName();

            SchemaType xsiSchemaType =
                xsiTypeName == null ?
                    null : c._locale._schemaTypeLoader.findType(xsiTypeName);

            if (requestedType == null ||
                requestedType.isAssignableFrom(xsiSchemaType)) {
                type = xsiSchemaType;
            }
        }

        // Look for a document element to establish type

        if (type == null &&
            (requestedType == null || requestedType.isDocumentType())) {
            assert c.isRoot();

            c.push();

            QName docElemName =
                !c.hasAttrs() && Locale.toFirstChildElement(c) &&
                !Locale.toNextSiblingElement(c)
                    ? c.getName() : null;

            c.pop();

            if (docElemName != null) {
                type =
                    c._locale._schemaTypeLoader.findDocumentType(docElemName);

                if (type != null && requestedType != null) {
                    QName requesteddocElemNameName = requestedType.getDocumentElementName();

                    if (!requesteddocElemNameName.equals(docElemName) &&
                        !requestedType.isValidSubstitution(docElemName)) {
                        throw
                            new XmlException("Element " +
                                             QNameHelper.pretty(docElemName) +
                                             " is not a valid " +
                                             QNameHelper.pretty(requesteddocElemNameName) +
                                             " document or a valid substitution.");
                    }
                }
            }
        }

        if (type == null && requestedType == null) {
            c.push();

            type =
                Locale.toFirstNormalAttr(c) && !Locale.toNextNormalAttr(c)
                    ?
                    c._locale._schemaTypeLoader.findAttributeType(c.getName()) :
                    null;

            c.pop();
        }

        if (type == null) {
            type = requestedType;
        }

        if (type == null) {
            type = XmlBeans.NO_TYPE;
        }

        c.setType(type);

        if (requestedType != null) {
            if (type.isDocumentType()) {
                verifyDocumentType(c, type.getDocumentElementName());
            } else if (type.isAttributeType()) {
                verifyAttributeType(c, type.getAttributeTypeAttributeName());
            }
        }
    }

    private static boolean namespacesSame(QName n1, QName n2) {
        if (n1 == n2) {
            return true;
        }

        if (n1 == null || n2 == null) {
            return false;
        }

        return Objects.equals(n1.getNamespaceURI(), n2.getNamespaceURI());
    }

    private static void addNamespace(StringBuffer sb, QName name) {
        if (name.getNamespaceURI() == null) {
            sb.append("<no namespace>");
        } else {
            sb.append("\"");
            sb.append(name.getNamespaceURI());
            sb.append("\"");
        }
    }

    private static void verifyDocumentType(Cur c, QName docElemName)
        throws XmlException {
        assert c.isRoot();

        c.push();

        try {
            StringBuffer sb = null;

            if (!Locale.toFirstChildElement(c) ||
                Locale.toNextSiblingElement(c)) {
                sb = new StringBuffer();

                sb.append("The document is not a ");
                sb.append(QNameHelper.pretty(docElemName));
                sb.append(
                    c.isRoot() ?
                        ": no document element" : ": multiple document elements");
            } else {
                QName name = c.getName();

                if (!name.equals(docElemName)) {
                    sb = new StringBuffer();

                    sb.append("The document is not a ");
                    sb.append(QNameHelper.pretty(docElemName));

                    if (docElemName.getLocalPart().equals(name.getLocalPart())) {
                        sb.append(": document element namespace mismatch ");
                        sb.append("expected ");
                        addNamespace(sb, docElemName);
                        sb.append(" got ");
                        addNamespace(sb, name);
                    } else if (namespacesSame(docElemName, name)) {
                        sb.append(": document element local name mismatch expected ")
                            .append(docElemName.getLocalPart())
                            .append(" got ")
                            .append(name.getLocalPart());
                    } else {
                        sb.append(": document element mismatch got ");
                        sb.append(QNameHelper.pretty(name));
                    }
                }
            }

            if (sb != null) {
                XmlError err = XmlError.forCursor(sb.toString(),
                    new Cursor(c));
                throw new XmlException(err.toString(), null, err);
            }
        } finally {
            c.pop();
        }
    }

    private static void verifyAttributeType(Cur c, QName attrName)
        throws XmlException {
        assert c.isRoot();

        c.push();

        try {
            StringBuffer sb = null;

            if (!Locale.toFirstNormalAttr(c) || Locale.toNextNormalAttr(c)) {
                sb = new StringBuffer();

                sb.append("The document is not a ");
                sb.append(QNameHelper.pretty(attrName));
                sb.append(
                    c.isRoot() ? ": no attributes" : ": multiple attributes");
            } else {
                QName name = c.getName();

                if (!name.equals(attrName)) {
                    sb = new StringBuffer();

                    sb.append("The document is not a ");
                    sb.append(QNameHelper.pretty(attrName));

                    if (attrName.getLocalPart().equals(name.getLocalPart())) {
                        sb.append(": attribute namespace mismatch ");
                        sb.append("expected ");
                        addNamespace(sb, attrName);
                        sb.append(" got ");
                        addNamespace(sb, name);
                    } else if (namespacesSame(attrName, name)) {
                        sb.append(": attribute local name mismatch ");
                        sb.append("expected " + attrName.getLocalPart());
                        sb.append(" got " + name.getLocalPart());
                    } else {
                        sb.append(": attribute element mismatch ");
                        sb.append("got ");
                        sb.append(QNameHelper.pretty(name));
                    }
                }
            }

            if (sb != null) {
                XmlError err = XmlError.forCursor(sb.toString(),
                    new Cursor(c));
                throw new XmlException(err.toString(), null, err);
            }
        } finally {
            c.pop();
        }
    }

    static boolean isFragmentQName(QName name) {
        return name.equals(Locale._openuriFragment) ||
               name.equals(Locale._xmlFragment);
    }

    static boolean isFragment(Cur start, Cur end) {
        assert !end.isAttr();

        start.push();
        end.push();

        int numDocElems = 0;
        boolean isFrag = false;

        while (!start.isSamePos(end)) {
            int k = start.kind();

            if (k == ATTR) {
                break;
            }

            if (k == TEXT && !isWhiteSpace(start.getCharsAsString())) {
                isFrag = true;
                break;
            }

            if (k == ELEM && ++numDocElems > 1) {
                isFrag = true;
                break;
            }

            // Move to next token

            if (k != TEXT) {
                start.toEnd();
            }

            start.next();
        }

        start.pop();
        end.pop();

        return isFrag || numDocElems != 1;
    }

    //
    //
    //

    public static XmlObject newInstance(SchemaTypeLoader stl, SchemaType type,
                                        XmlOptions options) {
        Locale l = getLocale(stl, options);

        if (l.noSync()) {
            l.enter();
            try {
                return l.newInstance(type, options);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return l.newInstance(type, options);
                } finally {
                    l.exit();
                }
            }
        }
    }

    private XmlObject newInstance(SchemaType type, XmlOptions options) {
        options = XmlOptions.maskNull(options);

        Cur c = tempCur();


        SchemaType sType = options.getDocumentType();

        if (sType == null) {
            sType = type == null ? XmlObject.type : type;
        }
        if (sType.isDocumentType()) {
            c.createDomDocumentRoot();
        } else {
            c.createRoot();
        }
        c.setType(sType);

        XmlObject x = (XmlObject) c.getUser();

        c.release();

        return x;
    }

    //
    //
    //

    public static DOMImplementation newDomImplementation(SchemaTypeLoader stl,
                                                         XmlOptions options) {
        return getLocale(stl, options);
    }

    //
    //
    //

    public static XmlObject parseToXmlObject(SchemaTypeLoader stl,
                                             String xmlText, SchemaType type, XmlOptions options)
        throws XmlException {
        Locale l = getLocale(stl, options);

        if (l.noSync()) {
            l.enter();
            try {
                return l.parseToXmlObject(xmlText, type, options);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return l.parseToXmlObject(xmlText, type, options);
                } finally {
                    l.exit();
                }
            }
        }
    }

    private XmlObject parseToXmlObject(String xmlText, SchemaType type,
                                       XmlOptions options)
        throws XmlException {
        Cur c = parse(xmlText, type, options);

        XmlObject x = (XmlObject) c.getUser();

        c.release();

        return x;
    }

    Cur parse(String s, SchemaType type, XmlOptions options)
        throws XmlException {

        try (Reader r = new StringReader(s)) {
            Cur c = getSaxLoader(options).load(this, new InputSource(r),
                options);

            autoTypeDocument(c, type, options);

            return c;
        } catch (IOException e) {
            assert false : "StringReader should not throw IOException";

            throw new XmlException(e.getMessage(), e);
        }
    }

    //
    //
    //


    //
    //
    //

    public static XmlObject parseToXmlObject(SchemaTypeLoader stl,
                                             XMLStreamReader xsr, SchemaType type, XmlOptions options)
        throws XmlException {
        Locale l = getLocale(stl, options);

        if (l.noSync()) {
            l.enter();
            try {
                return l.parseToXmlObject(xsr, type, options);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return l.parseToXmlObject(xsr, type, options);
                } finally {
                    l.exit();
                }
            }
        }
    }

    public XmlObject parseToXmlObject(XMLStreamReader xsr, SchemaType type,
                                      XmlOptions options)
        throws XmlException {
        Cur c;

        try {
            c = loadXMLStreamReader(xsr, options);
        } catch (XMLStreamException e) {
            throw new XmlException(e.getMessage(), e);
        }

        autoTypeDocument(c, type, options);

        XmlObject x = (XmlObject) c.getUser();

        c.release();

        return x;
    }

    private static void lineNumber(XMLStreamReader xsr, LoadContext context) {
        javax.xml.stream.Location loc = xsr.getLocation();

        if (loc != null) {
            context.lineNumber(loc.getLineNumber(), loc.getColumnNumber(),
                loc.getCharacterOffset());
        }
    }

    private void doAttributes(XMLStreamReader xsr, LoadContext context) {
        int n = xsr.getAttributeCount();

        for (int a = 0; a < n; a++) {
            context.attr(xsr.getAttributeLocalName(a),
                xsr.getAttributeNamespace(a),
                xsr.getAttributePrefix(a),
                xsr.getAttributeValue(a));
        }
    }

    private void doNamespaces(XMLStreamReader xsr, LoadContext context) {
        int n = xsr.getNamespaceCount();

        for (int a = 0; a < n; a++) {
            String prefix = xsr.getNamespacePrefix(a);

            if (prefix == null || prefix.length() == 0) {
                context.attr("xmlns", _xmlnsUri, null,
                    xsr.getNamespaceURI(a));
            } else {
                context.attr(prefix, _xmlnsUri, "xmlns",
                    xsr.getNamespaceURI(a));
            }
        }

    }

    private Cur loadXMLStreamReader(XMLStreamReader xsr, XmlOptions options)
        throws XMLStreamException {
        options = XmlOptions.maskNull(options);

        boolean lineNums = options.isLoadLineNumbers();

        String encoding = null, version = null;
        boolean standAlone = false;

        LoadContext context = new Cur.CurLoadContext(this, options);
        int depth = 0;

        events:
        for (int eventType = xsr.getEventType(); ; eventType = xsr.next()) {
            switch (eventType) {
                case XMLStreamReader.START_DOCUMENT: {
                    depth++;

                    encoding = xsr.getCharacterEncodingScheme();
                    version = xsr.getVersion();
                    standAlone = xsr.isStandalone();

                    if (lineNums) {
                        lineNumber(xsr, context);
                    }

                    break;
                }

                case XMLStreamReader.END_DOCUMENT: {
                    depth--;

                    if (lineNums) {
                        lineNumber(xsr, context);
                    }

                    break events;
                }

                case XMLStreamReader.START_ELEMENT: {
                    depth++;
                    context.startElement(xsr.getName());

                    if (lineNums) {
                        lineNumber(xsr, context);
                    }

                    doAttributes(xsr, context);
                    doNamespaces(xsr, context);

                    break;
                }

                case XMLStreamReader.END_ELEMENT: {
                    depth--;
                    context.endElement();

                    if (lineNums) {
                        lineNumber(xsr, context);
                    }

                    break;
                }

                case XMLStreamReader.CHARACTERS:
                case XMLStreamReader.CDATA: {
                    context.text(xsr.getTextCharacters(), xsr.getTextStart(),
                        xsr.getTextLength());

                    if (lineNums) {
                        lineNumber(xsr, context);
                    }

                    break;
                }

                case XMLStreamReader.COMMENT: {
                    String comment = xsr.getText();

                    context.comment(comment);

                    if (lineNums) {
                        lineNumber(xsr, context);
                    }

                    break;
                }

                case XMLStreamReader.PROCESSING_INSTRUCTION: {
                    context.procInst(xsr.getPITarget(), xsr.getPIData());

                    if (lineNums) {
                        lineNumber(xsr, context);
                    }

                    break;
                }

                case XMLStreamReader.ATTRIBUTE: {
                    doAttributes(xsr, context);
                    break;
                }

                case XMLStreamReader.NAMESPACE: {
                    doNamespaces(xsr, context);
                    break;
                }

                case XMLStreamReader.ENTITY_REFERENCE: {
                    context.text(xsr.getText());
                    break;
                }

                case XMLStreamReader.SPACE:
                case XMLStreamReader.DTD:
                    break;

                default:
                    throw new RuntimeException(
                        "Unhandled xml event type: " + eventType);
            }

            if (!xsr.hasNext() || depth <= 0) {
                break;
            }
        }

        Cur c = context.finish();

        associateSourceName(c, options);

        XmlDocumentProperties props = getDocProps(c, true);

        props.setEncoding(encoding);
        props.setVersion(version);
        props.setStandalone(standAlone);

        return c;
    }

    //
    //
    //

    public static XmlObject parseToXmlObject(SchemaTypeLoader stl,
                                             InputStream is, SchemaType type, XmlOptions options)
        throws XmlException, IOException {
        Locale l = getLocale(stl, options);

        if (l.noSync()) {
            l.enter();
            try {
                return l.parseToXmlObject(is, type, options);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return l.parseToXmlObject(is, type, options);
                } finally {
                    l.exit();
                }
            }
        }
    }

    private XmlObject parseToXmlObject(InputStream is, SchemaType type,
                                       XmlOptions options)
        throws XmlException, IOException {
        Cur c = getSaxLoader(options).load(this, new InputSource(is),
            options);

        autoTypeDocument(c, type, options);

        XmlObject x = (XmlObject) c.getUser();

        c.release();

        return x;
    }

    //
    //
    //

    public static XmlObject parseToXmlObject(SchemaTypeLoader stl,
                                             Reader reader, SchemaType type, XmlOptions options)
        throws XmlException, IOException {
        Locale l = getLocale(stl, options);

        if (l.noSync()) {
            l.enter();
            try {
                return l.parseToXmlObject(reader, type, options);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return l.parseToXmlObject(reader, type, options);
                } finally {
                    l.exit();
                }
            }
        }
    }

    private XmlObject parseToXmlObject(Reader reader, SchemaType type,
                                       XmlOptions options)
        throws XmlException, IOException {
        Cur c = getSaxLoader(options).load(this, new InputSource(reader),
            options);

        autoTypeDocument(c, type, options);

        XmlObject x = (XmlObject) c.getUser();

        c.release();

        return x;
    }

    //
    //
    //

    public static XmlObject parseToXmlObject(SchemaTypeLoader stl, Node node,
                                             SchemaType type, XmlOptions options)
        throws XmlException {
        Locale l = getLocale(stl, options);

        if (l.noSync()) {
            l.enter();
            try {
                return l.parseToXmlObject(node, type, options);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return l.parseToXmlObject(node, type, options);
                } finally {
                    l.exit();
                }
            }
        }
    }

    public XmlObject parseToXmlObject(Node node, SchemaType type,
                                      XmlOptions options)
        throws XmlException {
        LoadContext context = new Cur.CurLoadContext(this, options);

        loadNode(node, context);

        Cur c = context.finish();

        associateSourceName(c, options);

        autoTypeDocument(c, type, options);

        XmlObject x = (XmlObject) c.getUser();

        c.release();

        return x;
    }

    private void loadNodeChildren(Node n, LoadContext context) {
        for (Node c = n.getFirstChild(); c != null; c = c.getNextSibling()) {
            loadNode(c, context);
        }
    }

    public void loadNode(Node n, LoadContext context) {
        switch (n.getNodeType()) {
            case Node.DOCUMENT_NODE:
            case Node.DOCUMENT_FRAGMENT_NODE:
            case Node.ENTITY_REFERENCE_NODE: {
                loadNodeChildren(n, context);

                break;
            }
            case Node.ELEMENT_NODE: {
                context.startElement(
                    makeQualifiedQName(n.getNamespaceURI(), n.getNodeName()));

                NamedNodeMap attrs = n.getAttributes();

                for (int i = 0; i < attrs.getLength(); i++) {
                    Node a = attrs.item(i);

                    String attrName = a.getNodeName();
                    String attrValue = a.getNodeValue();

                    if (attrName.toLowerCase(java.util.Locale.ROOT).startsWith("xmlns")) {
                        if (attrName.length() == 5) {
                            context.xmlns(null, attrValue);
                        } else {
                            context.xmlns(attrName.substring(6), attrValue);
                        }
                    } else {
                        context.attr(
                            makeQualifiedQName(a.getNamespaceURI(), attrName),
                            attrValue);
                    }
                }

                loadNodeChildren(n, context);

                context.endElement();

                break;
            }
            case Node.TEXT_NODE:
            case Node.CDATA_SECTION_NODE: {
                context.text(n.getNodeValue());
                break;
            }
            case Node.COMMENT_NODE: {
                context.comment(n.getNodeValue());
                break;
            }
            case Node.PROCESSING_INSTRUCTION_NODE: {
                context.procInst(n.getNodeName(), n.getNodeValue());
                break;
            }
            case Node.DOCUMENT_TYPE_NODE:
            case Node.ENTITY_NODE:
            case Node.NOTATION_NODE: {
                Node next = n.getNextSibling();
                if (next != null) {
                    loadNode(next, context);
                }
                break;
            }
            case Node.ATTRIBUTE_NODE: {
                throw new RuntimeException("Unexpected node");
            }
        }
    }

    //
    //
    //

    private static class XmlSaxHandlerImpl
        extends SaxHandler
        implements XmlSaxHandler {
        XmlSaxHandlerImpl(Locale l, SchemaType type, XmlOptions options) {
            super(null);

            _options = options;
            _type = type;

            // Because SAX loading is not atomic with respect to XmlBeans, I can't use the default
            // thread local CharUtil.  Instruct the SaxHandler (and the LoadContext, eventually)
            // to use the Locale specific CharUtil.

            XmlOptions saxHandlerOptions = new XmlOptions(options);
            saxHandlerOptions.setLoadUseLocaleCharUtil(true);
            initSaxHandler(l, saxHandlerOptions);
        }

        public ContentHandler getContentHandler() {
            return _context == null ? null : this;
        }

        public LexicalHandler getLexicalHandler() {
            return _context == null ? null : this;
        }

        public void bookmarkLastEvent(XmlBookmark mark) {
            _context.bookmarkLastNonAttr(mark);
        }

        public void bookmarkLastAttr(QName attrName, XmlBookmark mark) {
            _context.bookmarkLastAttr(attrName, mark);
        }

        public XmlObject getObject()
            throws XmlException {
            if (_context == null) {
                return null;
            }

            _locale.enter();

            try {
                Cur c = _context.finish();

                autoTypeDocument(c, _type, _options);

                XmlObject x = (XmlObject) c.getUser();

                c.release();

                _context = null;

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

        private final SchemaType _type;
        private final XmlOptions _options;
    }

    public static XmlSaxHandler newSaxHandler(SchemaTypeLoader stl,
                                              SchemaType type, XmlOptions options) {
        Locale l = getLocale(stl, options);

        if (l.noSync()) {
            l.enter();
            try {
                return l.newSaxHandler(type, options);
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return l.newSaxHandler(type, options);
                } finally {
                    l.exit();
                }
            }
        }
    }

    public XmlSaxHandler newSaxHandler(SchemaType type, XmlOptions options) {
        return new XmlSaxHandlerImpl(this, type, options);
    }

    // TODO (ericvas ) - have a qname factory here so that the same factory may be
    // used by the parser.  This factory would probably come from my
    // high speed parser.  Otherwise, use a thread local on

    QName makeQName(String uri, String localPart) {
        assert localPart != null && localPart.length() > 0;
        // TODO - make sure name is a well formed name?

        return _qnameFactory.getQName(uri, localPart);
    }

    QName makeQNameNoCheck(String uri, String localPart) {
        return _qnameFactory.getQName(uri, localPart);
    }

    QName makeQName(String uri, String local, String prefix) {
        return _qnameFactory.getQName(uri, local, prefix == null ? "" : prefix);
    }

    QName makeQualifiedQName(String uri, String qname) {
        if (qname == null) {
            qname = "";
        }

        int i = qname.indexOf(':');

        return i < 0
            ?
            _qnameFactory.getQName(uri, qname)
            :
            _qnameFactory.getQName(uri, qname.substring(i + 1),
                qname.substring(0, i));
    }

    static private class DocProps
        extends XmlDocumentProperties {
        private final HashMap<Object, Object> _map = new HashMap<>();

        public Object put(Object key, Object value) {
            return _map.put(key, value);
        }

        public Object get(Object key) {
            return _map.get(key);
        }

        public Object remove(Object key) {
            return _map.remove(key);
        }
    }

    static XmlDocumentProperties getDocProps(Cur c, boolean ensure) {
        c.push();

        while (c.toParent()) {
        }

        DocProps props = (DocProps) c.getBookmark(DocProps.class);

        if (props == null && ensure) {
            c.setBookmark(DocProps.class, props = new DocProps());
        }

        c.pop();

        return props;
    }

    interface ChangeListener {
        void notifyChange();

        void setNextChangeListener(ChangeListener listener);

        ChangeListener getNextChangeListener();
    }

    void registerForChange(ChangeListener listener) {
        if (listener.getNextChangeListener() == null) {
            if (_changeListeners == null) {
                listener.setNextChangeListener(listener);
            } else {
                listener.setNextChangeListener(_changeListeners);
            }

            _changeListeners = listener;
        }
    }

    void notifyChange() {
        // First, notify the registered listeners ...

        while (_changeListeners != null) {
            _changeListeners.notifyChange();

            if (_changeListeners.getNextChangeListener() == _changeListeners) {
                _changeListeners.setNextChangeListener(null);
            }

            ChangeListener next = _changeListeners.getNextChangeListener();

            _changeListeners.setNextChangeListener(null);

            _changeListeners = next;
        }

        // Then, prepare for the change in a locale specific way.  Need to create real Curs for
        // 'virtual' Curs in Locations

        _locations.notifyChange();
    }

    //
    // Cursor helpers
    //

    static String getTextValue(Cur c) {
        assert c.isNode();

        if (!c.hasChildren()) {
            return c.getValueAsString();
        }

        StringBuffer sb = new StringBuffer();

        c.push();

        for (c.next(); !c.isAtEndOfLastPush(); c.next()) {
            if (c.isText()) {
                if ((c._xobj.isComment() || c._xobj.isProcinst()) && c._pos < c._xobj._cchValue) {
                    continue;
                }
                CharUtil.getString(sb, c.getChars(-1), c._offSrc, c._cchSrc);
            }
        }

        c.pop();

        return sb.toString();
    }

    static int getTextValue(Cur c, int wsr, char[] chars, int off, int maxCch) {
        // TODO - hack impl for now ... improve

        assert c.isNode();

        String s = c._xobj.getValueAsString(wsr);

        int n = s.length();

        if (n > maxCch) {
            n = maxCch;
        }

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

        s.getChars(0, n, chars, off);

        return n;
    }

    static String applyWhiteSpaceRule(String s, int wsr) {
        int l = s == null ? 0 : s.length();

        if (l == 0 || wsr == WS_PRESERVE) {
            return s;
        }

        char ch;

        if (wsr == WS_REPLACE) {
            for (int i = 0; i < l; i++) {
                if ((ch = s.charAt(i)) == '\n' || ch == '\r' || ch == '\t') {
                    return processWhiteSpaceRule(s, wsr);
                }
            }
        } else if (wsr == WS_COLLAPSE) {
            if (CharUtil.isWhiteSpace(s.charAt(0)) ||
                CharUtil.isWhiteSpace(s.charAt(l - 1))) {
                return processWhiteSpaceRule(s, wsr);
            }

            boolean lastWasWhite = false;

            for (int i = 1; i < l; i++) {
                boolean isWhite = CharUtil.isWhiteSpace(s.charAt(i));

                if (isWhite && lastWasWhite) {
                    return processWhiteSpaceRule(s, wsr);
                }

                lastWasWhite = isWhite;
            }
        }

        return s;
    }

    static String processWhiteSpaceRule(String s, int wsr) {
        ScrubBuffer sb = getScrubBuffer(wsr);

        sb.scrub(s, 0, s.length());

        return sb.getResultAsString();
    }

    static final class ScrubBuffer {
        ScrubBuffer() {
            _sb = new StringBuffer();
        }

        void init(int wsr) {
            _sb.delete(0, _sb.length());

            _wsr = wsr;
            _state = START_STATE;
        }

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

            if (_wsr == WS_PRESERVE) {
                CharUtil.getString(_sb, src, off, cch);
                return;
            }

            char[] chars;

            if (src instanceof char[]) {
                chars = (char[]) src;
            } else {
                if (cch <= _srcBuf.length) {
                    chars = _srcBuf;
                } else if (cch <= 16384) {
                    chars = _srcBuf = new char[16384];
                } else {
                    chars = new char[cch];
                }

                CharUtil.getChars(chars, 0, src, off, cch);
                off = 0;
            }

            int start = 0;

            for (int i = 0; i < cch; i++) {
                char ch = chars[off + i];

                if (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') {
                    _sb.append(chars, off + start, i - start);

                    start = i + 1;

                    if (_wsr == WS_REPLACE) {
                        _sb.append(' ');
                    } else if (_state == NOSPACE_STATE) {
                        _state = SPACE_SEEN_STATE;
                    }
                } else {
                    if (_state == SPACE_SEEN_STATE) {
                        _sb.append(' ');
                    }

                    _state = NOSPACE_STATE;
                }
            }

            _sb.append(chars, off + start, cch - start);
        }

        String getResultAsString() {
            return _sb.toString();
        }

        private static final int START_STATE = 0;
        private static final int SPACE_SEEN_STATE = 1;
        private static final int NOSPACE_STATE = 2;

        private int _state;

        private int _wsr;

        private char[] _srcBuf = new char[1024];
        private final StringBuffer _sb;
    }

    private static final ThreadLocal<SoftReference<ScrubBuffer>> tl_scrubBuffer =
        ThreadLocal.withInitial(() -> new SoftReference<>(new ScrubBuffer()));

    public static void clearThreadLocals() {
        tl_scrubBuffer.remove();
    }

    static ScrubBuffer getScrubBuffer(int wsr) {
        SoftReference<ScrubBuffer> softRef = tl_scrubBuffer.get();
        ScrubBuffer scrubBuffer = softRef.get();
        if (scrubBuffer == null) {
            scrubBuffer = new ScrubBuffer();
            tl_scrubBuffer.set(new SoftReference<>(scrubBuffer));
        }

        scrubBuffer.init(wsr);
        return scrubBuffer;
    }

    static boolean pushToContainer(Cur c) {
        c.push();

        for (; ; ) {
            switch (c.kind()) {
                case ROOT:
                case ELEM:
                    return true;
                case -ROOT:
                case -ELEM:
                    c.pop();
                    return false;
                case COMMENT:
                case PROCINST:
                    c.skip();
                    break;
                default:
                    c.nextWithAttrs();
                    break;
            }
        }
    }

    static boolean toFirstNormalAttr(Cur c) {
        c.push();

        if (c.toFirstAttr()) {
            do {
                if (!c.isXmlns()) {
                    c.popButStay();
                    return true;
                }
            }
            while (c.toNextAttr());
        }

        c.pop();

        return false;
    }

    static boolean toPrevNormalAttr(Cur c) {
        if (c.isAttr()) {
            c.push();

            for (; ; ) {
                assert c.isAttr();

                // See if I can move backward.  If I'm at the first attr, prev must return
                // false and not move.

                if (!c.prev()) {
                    break;
                }

                // Skip past the text value or attr begin

                c.prev();

                // I might have skipped over text above

                if (!c.isAttr()) {
                    c.prev();
                }

                if (c.isNormalAttr()) {
                    c.popButStay();
                    return true;
                }
            }

            c.pop();
        }

        return false;
    }

    static boolean toNextNormalAttr(Cur c) {
        c.push();

        while (c.toNextAttr()) {
            if (!c.isXmlns()) {
                c.popButStay();
                return true;
            }
        }

        c.pop();

        return false;
    }

    Xobj findNthChildElem(Xobj parent, QName name, QNameSet set, int n) {
        // only one of (set or name) is not null
        // or both are null for a wildcard
        assert (name == null || set == null);
        assert n >= 0;

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

        int da = _nthCache_A.distance(parent, name, set, n);
        int db = _nthCache_B.distance(parent, name, set, n);

        Xobj x =
            da <= db
                ? _nthCache_A.fetch(parent, name, set, n)
                : _nthCache_B.fetch(parent, name, set, n);

        if (da == db) {
            nthCache temp = _nthCache_A;
            _nthCache_A = _nthCache_B;
            _nthCache_B = temp;
        }

        return x;
    }

    int count(Xobj parent, QName name, QNameSet set) {
        int n = 0;

        for (Xobj x = findNthChildElem(parent, name, set, 0);
             x != null; x = x._nextSibling) {
            if (x.isElem()) {
                if (set == null) {
                    if (x._name.equals(name)) {
                        n++;
                    }
                } else if (set.contains(x._name)) {
                    n++;
                }
            }
        }

        return n;
    }

    static boolean toChild(Cur c, QName name, int n) {
        if (n >= 0 && pushToContainer(c)) {
            Xobj x = c._locale.findNthChildElem(c._xobj, name, null, n);

            c.pop();

            if (x != null) {
                c.moveTo(x);
                return true;
            }
        }

        return false;
    }

    public static boolean toFirstChildElement(Cur c) {
//        if (!pushToContainer(c))
//            return false;
//
//        if (!c.toFirstChild() || (!c.isElem() && !toNextSiblingElement(c)))
//        {
//            c.pop();
//            return false;
//        }
//
//        c.popButStay();
//
//        return true;

        Xobj originalXobj = c._xobj;
        int originalPos = c._pos;

        loop:
        for (; ; ) {
            switch (c.kind()) {
                case ROOT:
                case ELEM:
                    break loop;
                case -ROOT:
                case -ELEM:
                    c.moveTo(originalXobj, originalPos);
                    return false;
                case COMMENT:
                case PROCINST:
                    c.skip();
                    break;
                default:
                    c.nextWithAttrs();
                    break;
            }
        }

        if (!c.toFirstChild() || (!c.isElem() && !toNextSiblingElement(c))) {
            c.moveTo(originalXobj, originalPos);
            return false;
        }

        return true;
    }

    static boolean toLastChildElement(Cur c) {
        if (!pushToContainer(c)) {
            return false;
        }

        if (!c.toLastChild() || (!c.isElem() && !toPrevSiblingElement(c))) {
            c.pop();
            return false;
        }

        c.popButStay();

        return true;
    }

    static boolean toPrevSiblingElement(Cur cur) {
        if (!cur.hasParent()) {
            return false;
        }

        Cur c = cur.tempCur();

        boolean moved = false;

        int k = c.kind();

        if (k != ATTR) {
            for (; ; ) {
                if (!c.prev()) {
                    break;
                }

                k = c.kind();

                if (k == ROOT || k == ELEM) {
                    break;
                }

                if (c.kind() == -ELEM) {
                    c.toParent();

                    cur.moveToCur(c);
                    moved = true;

                    break;
                }
            }
        }

        c.release();

        return moved;
    }

    static boolean toNextSiblingElement(Cur c) {
        if (!c.hasParent()) {
            return false;
        }

        c.push();

        int k = c.kind();

        if (k == ATTR) {
            c.toParent();
            c.next();
        } else if (k == ELEM) {
            c.skip();
        }

        while ((k = c.kind()) >= 0) {
            if (k == ELEM) {
                c.popButStay();
                return true;
            }

            if (k > 0) {
                c.toEnd();
            }

            c.next();
        }

        c.pop();

        return false;
    }

    static boolean toNextSiblingElement(Cur c, Xobj parent) {
        Xobj originalXobj = c._xobj;
        int originalPos = c._pos;

        int k = c.kind();

        if (k == ATTR) {
            c.moveTo(parent);
            c.next();
        } else if (k == ELEM) {
            c.skip();
        }

        while ((k = c.kind()) >= 0) {
            if (k == ELEM) {
                return true;
            }

            if (k > 0) {
                c.toEnd();
            }

            c.next();
        }

        c.moveTo(originalXobj, originalPos);

        return false;
    }

    static void applyNamespaces(Cur c, Map<String, String> namespaces) {
        assert c.isContainer();

        for (String prefix : namespaces.keySet()) {
            // Usually, this is the predefined xml namespace
            if (!prefix.toLowerCase(java.util.Locale.ROOT).startsWith("xml")) {
                if (c.namespaceForPrefix(prefix, false) == null) {
                    c.push();

                    c.next();
                    c.createAttr(c._locale.createXmlns(prefix));
                    c.next();

                    c.insertString(namespaces.get(prefix));

                    c.pop();
                }
            }
        }
    }

    static Map<String, String> getAllNamespaces(Cur c, Map<String, String> filleMe) {
        assert c.isNode();

        c.push();

        if (!c.isContainer()) {
            c.toParent();
        }

        assert c.isContainer();

        do {
            QName cName = c.getName();

            while (c.toNextAttr()) {
                if (c.isXmlns()) {
                    String prefix = c.getXmlnsPrefix();
                    String uri = c.getXmlnsUri();

                    if (filleMe == null) {
                        filleMe = new HashMap<>();
                    }

                    if (!filleMe.containsKey(prefix)) {
                        filleMe.put(prefix, uri);
                    }
                }
            }

            if (!c.isContainer()) {
                c.toParentRaw();
            }
        }
        while (c.toParentRaw());

        c.pop();

        return filleMe;
    }

    class nthCache {
        private boolean namesSame(QName pattern, QName name) {
            return pattern == null || pattern.equals(name);
        }

        private boolean setsSame(QNameSet patternSet, QNameSet set) {
            // value equality is probably too expensive. Since the use case
            // involves QNameSets that are generated by the compiler, we
            // can use identity comparison.

            return patternSet != null && patternSet == set;
        }

        private boolean nameHit(QName namePattern, QNameSet setPattern,
                                QName name) {
            return
                setPattern == null
                    ? namesSame(namePattern, name)
                    : setPattern.contains(name);
        }

        private boolean cacheSame(QName namePattern, QNameSet setPattern) {
            return
                setPattern == null
                    ? namesSame(namePattern, _name)
                    : setsSame(setPattern, _set);
        }

        int distance(Xobj parent, QName name, QNameSet set, int n) {
            assert n >= 0;

            if (_version != Locale.this.version()) {
                return Integer.MAX_VALUE - 1;
            }

            if (parent != _parent || !cacheSame(name, set)) {
                return Integer.MAX_VALUE;
            }

            return n > _n ? n - _n : _n - n;
        }

        Xobj fetch(Xobj parent, QName name, QNameSet set, int n) {
            assert n >= 0;

            if (_version != Locale.this.version() || _parent != parent ||
                !cacheSame(name, set) || n == 0) {
                _version = Locale.this.version();
                _parent = parent;
                _name = name;
                _child = null;
                _n = -1;

                loop:
                for (Xobj x = parent._firstChild;
                     x != null; x = x._nextSibling) {
                    if (x.isElem() && nameHit(name, set, x._name)) {
                        _child = x;
                        _n = 0;

                        break loop;
                    }
                }
            }

            if (_n < 0) {
                return null;
            }

            if (n > _n) {
                while (n > _n) {
                    for (Xobj x = _child._nextSibling; ; x = x._nextSibling) {
                        if (x == null) {
                            return null;
                        }

                        if (x.isElem() && nameHit(name, set, x._name)) {
                            _child = x;
                            _n++;

                            break;
                        }
                    }
                }
            } else if (n < _n) {
                while (n < _n) {
                    for (Xobj x = _child._prevSibling; ; x = x._prevSibling) {
                        if (x == null) {
                            return null;
                        }

                        if (x.isElem() && nameHit(name, set, x._name)) {
                            _child = x;
                            _n--;

                            break;
                        }
                    }
                }
            }

            return _child;
        }

        private long _version;
        private Xobj _parent;
        private QName _name;
        private QNameSet _set;
        private Xobj _child;
        private int _n;
    }

    //
    //
    //

    Dom findDomNthChild(Dom parent, int n) {
        assert n >= 0;

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

        int da = _domNthCache_A.distance(parent, n);
        int db = _domNthCache_B.distance(parent, n);


        // the "better" cache should never walk more than 1/2 len
        Dom x = null;
        boolean bInvalidate = (db - _domNthCache_B._len / 2 > 0) &&
                              (db - _domNthCache_B._len / 2 - domNthCache.BLITZ_BOUNDARY > 0);
        boolean aInvalidate = (da - _domNthCache_A._len / 2 > 0) &&
                              (da - _domNthCache_A._len / 2 - domNthCache.BLITZ_BOUNDARY > 0);
        if (da <= db) {
            if (!aInvalidate) {
                x = _domNthCache_A.fetch(parent, n);
            } else {
                _domNthCache_B._version = -1;//blitz the cache
                x = _domNthCache_B.fetch(parent, n);
            }
        } else if (!bInvalidate) {
            x = _domNthCache_B.fetch(parent, n);
        } else {
            _domNthCache_A._version = -1;//blitz the cache
            x = _domNthCache_A.fetch(parent, n);
        }

        if (da == db) {
            domNthCache temp = _domNthCache_A;
            _domNthCache_A = _domNthCache_B;
            _domNthCache_B = temp;
        }

        return x;
    }

    int domLength(Dom parent) {
        if (parent == null) {
            return 0;
        }

        int da = _domNthCache_A.distance(parent, 0);
        int db = _domNthCache_B.distance(parent, 0);

        int len =
            da <= db
                ? _domNthCache_A.length(parent)
                : _domNthCache_B.length(parent);

        if (da == db) {
            domNthCache temp = _domNthCache_A;
            _domNthCache_A = _domNthCache_B;
            _domNthCache_B = temp;
        }

        return len;
    }

    void invalidateDomCaches(Dom d) {
        if (_domNthCache_A._parent == d) {
            _domNthCache_A._version = -1;
        }
        if (_domNthCache_B._parent == d) {
            _domNthCache_B._version = -1;
        }
    }

    boolean isDomCached(Dom d) {
        return _domNthCache_A._parent == d || _domNthCache_B._parent == d;
    }

    class domNthCache {

        int distance(Dom parent, int n) {
            assert n >= 0;

            if (_version != Locale.this.version()) {
                return Integer.MAX_VALUE - 1;
            }

            if (parent != _parent) {
                return Integer.MAX_VALUE;
            }

            return n > _n ? n - _n : _n - n;
        }

        int length(Dom parent) {
            if (_version != Locale.this.version() || _parent != parent) {
                _parent = parent;
                _version = Locale.this.version();
                _child = null;
                _n = -1;
                _len = -1;
            }

            if (_len == -1) {
                Dom x = null;

                if (_child != null && _n != -1) {
                    x = _child;
                    _len = _n;
                } else {
                    x = (Dom) DomImpl.firstChild(_parent);
                    _len = 0;

                    // cache the 0th child
                    _child = x;
                    _n = 0;
                }

                for (; x != null; x = (Dom) DomImpl.nextSibling(x)) {
                    _len++;
                }
            }


            return _len;
        }

        Dom fetch(Dom parent, int n) {
            assert n >= 0;

            if (_version != Locale.this.version() || _parent != parent) {
                _parent = parent;
                _version = Locale.this.version();
                _child = null;
                _n = -1;
                _len = -1;

                for (Dom x = (Dom) DomImpl.firstChild(_parent); x != null; x = (Dom) DomImpl.nextSibling(x)) {
                    _n++;
                    if (_child == null && n == _n) {
                        _child = x;
                        break;
                    }
                }

                return _child;
            }

            if (_n < 0) {
                return null;
            }

            if (n > _n) {
                while (n > _n) {
                    for (Dom x = (Dom) DomImpl.nextSibling(_child); ; x = (Dom) DomImpl.nextSibling(x)) {
                        if (x == null) {
                            return null;
                        }

                        _child = x;
                        _n++;

                        break;
                    }
                }
            } else if (n < _n) {
                while (n < _n) {
                    for (Dom x = (Dom) DomImpl.prevSibling(_child); ; x = (Dom) DomImpl.prevSibling(x)) {
                        if (x == null) {
                            return null;
                        }

                        _child = x;
                        _n--;

                        break;
                    }
                }
            }

            return _child;
        }

        public static final int BLITZ_BOUNDARY = 40; //walk small lists
        private long _version;
        private Dom _parent;
        private Dom _child;
        private int _n;
        private int _len;
    }

    //
    //
    //

    CharUtil getCharUtil() {
        if (_charUtil == null) {
            _charUtil = new CharUtil(1024);
        }

        return _charUtil;
    }

    public long version() {
        return _versionAll;
    }

    Cur weakCur(Object o) {
        assert o != null && !(o instanceof Ref);

        Cur c = getCur();

        assert c._tempFrame == -1;
        assert c._ref == null;

        c._ref = new Ref(c, o);

        return c;
    }

    final ReferenceQueue refQueue() {
        if (_refQueue == null) {
            _refQueue = new ReferenceQueue();
        }

        return _refQueue;
    }

    final static class Ref
        extends PhantomReference {
        Ref(Cur c, Object obj) {
            super(obj, c._locale.refQueue());

            _cur = c;
        }

        Cur _cur;
    }

    Cur tempCur() {
        return tempCur(null);
    }

    Cur tempCur(String id) {
        Cur c = getCur();

        assert c._tempFrame == -1;

        assert _numTempFramesLeft < _tempFrames.length : "Temp frame not pushed";

        int frame = _tempFrames.length - _numTempFramesLeft - 1;

        assert frame >= 0 && frame < _tempFrames.length;

        Cur next = _tempFrames[frame];

        c._nextTemp = next;
        assert c._prevTemp == null;

        if (next != null) {
            assert next._prevTemp == null;
            next._prevTemp = c;
        }

        _tempFrames[frame] = c;
        c._tempFrame = frame;

        c._id = id;

        return c;
    }

    Cur getCur() {
        assert _curPool == null || _curPoolCount > 0;

        Cur c;

        if (_curPool == null) {
            c = new Cur(this);
        } else {
            _curPool = _curPool.listRemove(c = _curPool);
            _curPoolCount--;
        }

        assert c._state == Cur.POOLED;
        assert c._prev == null && c._next == null;
        assert c._xobj == null && c._pos == Cur.NO_POS;
        assert c._ref == null;

        _registered = c.listInsert(_registered);
        c._state = Cur.REGISTERED;

        return c;
    }

    void embedCurs() {
        for (Cur c; (c = _registered) != null; ) {
            assert c._xobj != null;

            _registered = c.listRemove(_registered);
            c._xobj._embedded = c.listInsert(c._xobj._embedded);
            c._state = Cur.EMBEDDED;
        }
    }

    TextNode createTextNode() {
        return _saaj == null ? new TextNode(this) : new SaajTextNode(this);
    }

    CdataNode createCdataNode() {
        return _saaj == null ?
            new CdataNode(this) : new SaajCdataNode(this);
    }

    boolean entered() {
        return _tempFrames.length - _numTempFramesLeft > 0;
    }

    public void enter(Locale otherLocale) {
        enter();

        if (otherLocale != this) {
            otherLocale.enter();
        }
    }

    public void enter() {
        assert _numTempFramesLeft >= 0;

        if (--_numTempFramesLeft <= 0) {
            Cur[] newTempFrames = new Cur[_tempFrames.length * 2];
            //move this assignment down so if array allocation fails, error is not masked
            _numTempFramesLeft = _tempFrames.length;
            System.arraycopy(_tempFrames, 0, newTempFrames, 0,
                _tempFrames.length);
            _tempFrames = newTempFrames;
        }

        if (++_entryCount > 1000) {
            pollQueue();
            _entryCount = 0;
        }
    }

    private void pollQueue() {
        if (_refQueue != null) {
            for (; ; ) {
                Ref ref = (Ref) _refQueue.poll();

                if (ref == null) {
                    break;
                }

                if (ref._cur != null) {
                    ref._cur.release();
                }
            }
        }
    }

    public void exit(Locale otherLocale) {
        exit();

        if (otherLocale != this) {
            otherLocale.exit();
        }
    }

    public void exit() {
        // assert _numTempFramesLeft >= 0;
        //asserts computed frame fits between 0 and _tempFrames.length
        assert _numTempFramesLeft >= 0 &&
               (_numTempFramesLeft <= _tempFrames.length - 1) :
            " Temp frames mismanaged. Impossible stack frame. Unsynchronized: " +
            noSync();

        int frame = _tempFrames.length - ++_numTempFramesLeft;

        while (_tempFrames[frame] != null) {
            _tempFrames[frame].release();
        }
    }

    //
    //
    //

    public boolean noSync() {
        return _noSync;
    }

    public boolean sync() {
        return !_noSync;
    }

    static final boolean isWhiteSpace(String s) {
        int l = s.length();

        while (l-- > 0) {
            if (!CharUtil.isWhiteSpace(s.charAt(l))) {
                return false;
            }
        }

        return true;
    }

    static final boolean isWhiteSpace(StringBuffer sb) {
        int l = sb.length();

        while (l-- > 0) {
            if (!CharUtil.isWhiteSpace(sb.charAt(l))) {
                return false;
            }
        }

        return true;
    }

    static boolean beginsWithXml(String name) {
        if (name.length() < 3) {
            return false;
        }

        char ch;

        if (((ch = name.charAt(0)) == 'x' || ch == 'X') &&
            ((ch = name.charAt(1)) == 'm' || ch == 'M') &&
            ((ch = name.charAt(2)) == 'l' || ch == 'L')) {
            return true;
        }

        return false;
    }

    static boolean isXmlns(QName name) {
        String prefix = name.getPrefix();

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

        return prefix.length() == 0 && name.getLocalPart().equals("xmlns");
    }

    QName createXmlns(String prefix) {
        if (prefix == null) {
            prefix = "";
        }

        return
            prefix.length() == 0
                ? makeQName(_xmlnsUri, "xmlns", "")
                : makeQName(_xmlnsUri, prefix, "xmlns");
    }

    static String xmlnsPrefix(QName name) {
        return name.getPrefix().equals("xmlns") ? name.getLocalPart() : "";
    }

    //
    // Loading/parsing
    //

    public static abstract class LoadContext {
        protected abstract void startDTD(String name, String publicId,
                                         String systemId);

        protected abstract void endDTD();

        protected abstract void startElement(QName name);

        protected abstract void endElement();

        public abstract void attr(QName name, String value);

        protected abstract void attr(String local, String uri, String prefix,
                                     String value);

        protected abstract void xmlns(String prefix, String uri);

        protected abstract void comment(char[] buff, int off, int cch);

        protected abstract void comment(String comment);

        protected abstract void procInst(String target, String value);

        protected abstract void text(char[] buff, int off, int cch);

        protected abstract void text(String s);

        public abstract Cur finish();

        protected abstract void abort();

        protected abstract void bookmark(XmlBookmark bm);

        protected abstract void bookmarkLastNonAttr(XmlBookmark bm);

        protected abstract void bookmarkLastAttr(QName attrName,
                                                 XmlBookmark bm);

        protected abstract void lineNumber(int line, int column, int offset);

        protected void addIdAttr(String eName, String aName) {
            if (_idAttrs == null) {
                _idAttrs = new java.util.Hashtable();
            }
            _idAttrs.put(aName, eName);
        }

        protected boolean isAttrOfTypeId(QName aqn, QName eqn) {
            if (_idAttrs == null) {
                return false;
            }
            String pre = aqn.getPrefix();
            String lName = aqn.getLocalPart();
            String urnName = "".equals(pre) ? lName : pre + ":" + lName;
            String eName = (String) _idAttrs.get(urnName);
            if (eName == null) {
                return false;
            }
            //get the name of the parent elt
            pre = eqn.getPrefix();
            lName = eqn.getLocalPart();
            lName = eqn.getLocalPart();
            urnName = "".equals(pre) ? lName : pre + ":" + lName;
            return eName.equals(urnName);
        }

        private java.util.Hashtable _idAttrs;
    }

    private static class DefaultEntityResolver
        implements EntityResolver {
        public InputSource resolveEntity(String publicId, String systemId) {
            return new InputSource(new StringReader(""));
        }
    }

    private static SaxLoader getSaxLoader(XmlOptions options) throws XmlException {
        options = XmlOptions.maskNull(options);

        EntityResolver er = null;

        if (!options.isLoadUseDefaultResolver()) {
            er = options.getEntityResolver();

            if (er == null) {
                er = ResolverUtil.getGlobalEntityResolver();
            }

            if (er == null) {
                er = new DefaultEntityResolver();
            }
        }

        XMLReader xr = options.getLoadUseXMLReader();

        if (xr == null) {
            try {
                xr = SAXHelper.newXMLReader(new XmlOptionsBean(options));
            } catch (Exception e) {
                throw new XmlException("Problem creating XMLReader", e);
            }
        }

        SaxLoader sl = new XmlReaderSaxLoader(xr);

        // I've noticed that most XMLReaders don't like a null EntityResolver...

        if (er != null) {
            xr.setEntityResolver(er);
        }

        return sl;
    }

    private static class XmlReaderSaxLoader
        extends SaxLoader {
        XmlReaderSaxLoader(XMLReader xr) {
            super(xr, null);
        }
    }

    private static abstract class SaxHandler
        implements ContentHandler, LexicalHandler, DeclHandler, DTDHandler {
        protected Locale _locale;

        protected LoadContext _context;

        private boolean _wantLineNumbers;
        private boolean _wantLineNumbersAtEndElt;
        private boolean _wantCdataBookmarks;
        private Locator _startLocator;
        private boolean _insideCDATA = false;
        private int _entityBytesLimit = 10240;
        private int _entityBytes = 0;
        private int _insideEntity = 0;

        SaxHandler(Locator startLocator) {
            _startLocator = startLocator;
        }

        SaxHandler() {
            this(null);
        }

        void initSaxHandler(Locale l, final XmlOptions options) {
            _locale = l;

            XmlOptions safeOptions = XmlOptions.maskNull(options);

            _context = new Cur.CurLoadContext(_locale, safeOptions);

            _wantLineNumbers = safeOptions.isLoadLineNumbers();
            _wantLineNumbersAtEndElt = safeOptions.isLoadLineNumbersEndElement();
            _wantCdataBookmarks = safeOptions.isUseCDataBookmarks();

            Integer limit = safeOptions.getLoadEntityBytesLimit();
            if (limit != null) {
                _entityBytesLimit = limit;
            }
        }

        public void startDocument() throws SAXException {
            // Do nothing ... start of document is implicit
        }

        public void endDocument()
            throws SAXException {
            // Do nothing ... end of document is implicit
        }

        public void startElement(String uri, String local, String qName,
                                 Attributes atts)
            throws SAXException {
            if (local.length() == 0) {
                local = qName;
            }

            // Out current parser does not error when a
            // namespace is used and not defined.  Check for these here

            if (qName.indexOf(':') >= 0 && uri.length() == 0) {
                XmlError err =
                    XmlError.forMessage("Use of undefined namespace prefix: " +
                                        qName.substring(0, qName.indexOf(':')));

                throw new XmlRuntimeException(err.toString(), null, err);
            }

            _context.startElement(_locale.makeQualifiedQName(uri, qName));

            if (_wantLineNumbers && _startLocator != null) {
                _context.bookmark(
                    new XmlLineNumber(_startLocator.getLineNumber(),
                        _startLocator.getColumnNumber() - 1, -1));
            }

            for (int i = 0, len = atts.getLength(); i < len; i++) {
                String aqn = atts.getQName(i);

                if (aqn.equals("xmlns")) {
                    _context.xmlns("", atts.getValue(i));
                } else if (aqn.startsWith("xmlns:")) {
                    String prefix = aqn.substring(6);

                    if (prefix.length() == 0) {
                        XmlError err =
                            XmlError.forMessage("Prefix not specified",
                                XmlError.SEVERITY_ERROR);

                        throw new XmlRuntimeException(err.toString(), null,
                            err);
                    }

                    String attrUri = atts.getValue(i);

                    if (attrUri.length() == 0) {
                        XmlError err =
                            XmlError.forMessage(
                                "Prefix can't be mapped to no namespace: " +
                                prefix,
                                XmlError.SEVERITY_ERROR);

                        throw new XmlRuntimeException(err.toString(), null,
                            err);
                    }

                    _context.xmlns(prefix, attrUri);
                } else {
                    int colon = aqn.indexOf(':');

                    if (colon < 0) {
                        _context.attr(aqn, atts.getURI(i), null,
                            atts.getValue(i));
                    } else {
                        _context.attr(aqn.substring(colon + 1), atts.getURI(i), aqn.substring(
                            0, colon),
                            atts.getValue(i));
                    }
                }
            }
        }

        public void endElement(String namespaceURI, String localName,
                               String qName)
            throws SAXException {
            _context.endElement();
            if (_wantLineNumbersAtEndElt && _startLocator != null) {
                _context.bookmark(
                    new XmlLineNumber(_startLocator.getLineNumber(),
                        _startLocator.getColumnNumber() - 1, -1));
            }
        }

        public void characters(char ch[], int start, int length)
            throws SAXException {
            _context.text(ch, start, length);

            if (_wantCdataBookmarks && _insideCDATA && _startLocator != null) {
                _context.bookmarkLastNonAttr(CDataBookmark.CDATA_BOOKMARK);
            }

            if (_insideEntity != 0) {
                if ((_entityBytes += length) > _entityBytesLimit) {
                    XmlError err = XmlError.forMessage(XmlErrorCodes.EXCEPTION_EXCEEDED_ENTITY_BYTES,
                        new Integer[]{_entityBytesLimit});

                    throw new SAXException(err.getMessage());
                }
            }
        }

        public void ignorableWhitespace(char ch[], int start, int length)
            throws SAXException {
        }

        public void comment(char ch[], int start, int length)
            throws SAXException {
            _context.comment(ch, start, length);
        }

        public void processingInstruction(String target, String data)
            throws SAXException {
            _context.procInst(target, data);
        }

        public void startDTD(String name, String publicId, String systemId)
            throws SAXException {
            _context.startDTD(name, publicId, systemId);
        }

        public void endDTD()
            throws SAXException {
            _context.endDTD();
        }

        public void startPrefixMapping(String prefix, String uri)
            throws SAXException {
            if (beginsWithXml(prefix) &&
                !("xml".equals(prefix) && _xml1998Uri.equals(uri))) {
                XmlError err =
                    XmlError.forMessage(
                        "Prefix can't begin with XML: " + prefix,
                        XmlError.SEVERITY_ERROR);

                throw new XmlRuntimeException(err.toString(), null, err);
            }
        }

        public void endPrefixMapping(String prefix)
            throws SAXException {
        }

        public void skippedEntity(String name)
            throws SAXException {
//            throw new RuntimeException( "Not impl: skippedEntity" );
        }

        public void startCDATA()
            throws SAXException {
            _insideCDATA = true;
        }

        public void endCDATA()
            throws SAXException {
            _insideCDATA = false;
        }

        public void startEntity(String name)
            throws SAXException {
            _insideEntity++;
        }

        public void endEntity(String name)
            throws SAXException {
            _insideEntity--;
            assert _insideEntity >= 0;

            if (_insideEntity == 0) {
                _entityBytes = 0;
            }
        }

        public void setDocumentLocator(Locator locator) {
            if (_startLocator == null) {
                _startLocator = locator;
            }
        }

        //DeclHandler
        public void attributeDecl(String eName, String aName, String type, String valueDefault, String value) {
            if (type.equals("ID")) {
                _context.addIdAttr(eName, aName);
            }
        }

        public void elementDecl(String name, String model) {
        }

        public void externalEntityDecl(String name, String publicId, String systemId) {
        }

        public void internalEntityDecl(String name, String value) {
        }

        //DTDHandler
        public void notationDecl(String name, String publicId, String systemId) {
        }

        public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) {
        }
    }

    private static abstract class SaxLoader
        extends SaxHandler
        implements ErrorHandler {
        SaxLoader(XMLReader xr, Locator startLocator) {
            super(startLocator);

            _xr = xr;

            try {
                _xr.setFeature(
                    "http://xml.org/sax/features/namespace-prefixes", true);
                _xr.setFeature("http://xml.org/sax/features/namespaces", true);
                _xr.setFeature("http://xml.org/sax/features/validation", false);
                _xr.setProperty(
                    "http://xml.org/sax/properties/lexical-handler", this);
                _xr.setContentHandler(this);
                _xr.setDTDHandler(this);
                _xr.setErrorHandler(this);
            } catch (Throwable e) {
                throw new RuntimeException(e.getMessage(), e);
            }
            try {
                _xr.setProperty("http://xml.org/sax/properties/declaration-handler", this);
            } catch (Throwable e) {
                logger.warn("SAX Declaration Handler is not supported", e);
            }
        }

        void setEntityResolver(EntityResolver er) {
            _xr.setEntityResolver(er);
        }

        void postLoad(Cur c) {
            // fix garbage collection of Locale -> Xobj -> STL
            _locale = null;
            _context = null;
        }

        public Cur load(Locale l, InputSource is, XmlOptions options)
            throws XmlException, IOException {
            is.setSystemId("file://");

            initSaxHandler(l, options);

            try {
                _xr.parse(is);

                Cur c = _context.finish();

                associateSourceName(c, options);

                postLoad(c);

                return c;
            } catch (XmlRuntimeException e) {
                _context.abort();

                throw new XmlException(e);
            } catch (SAXParseException e) {
                _context.abort();

                XmlError err =
                    XmlError.forLocation(e.getMessage(),
                        options == null ? null : options.getDocumentSourceName(),
                        e.getLineNumber(), e.getColumnNumber(), -1);

                throw new XmlException(err.toString(), e, err);
            } catch (SAXException e) {
                _context.abort();

                XmlError err = XmlError.forMessage(e.getMessage());

                throw new XmlException(err.toString(), e, err);
            } catch (RuntimeException e) {
                _context.abort();

                throw e;
            }
        }

        public void fatalError(SAXParseException e)
            throws SAXException {
            throw e;
        }

        public void error(SAXParseException e)
            throws SAXException {
            throw e;
        }

        public void warning(SAXParseException e)
            throws SAXException {
            throw e;
        }

        private XMLReader _xr;
    }

    private Dom load(InputSource is, XmlOptions options)
        throws XmlException, IOException {
        return getSaxLoader(options).load(this, is, options).getDom();
    }

    public Dom load(Reader r)
        throws XmlException, IOException {
        return load(r, null);
    }

    public Dom load(Reader r, XmlOptions options)
        throws XmlException, IOException {
        return load(new InputSource(r), options);
    }

    public Dom load(InputStream in)
        throws XmlException, IOException {
        return load(in, null);
    }

    public Dom load(InputStream in, XmlOptions options)
        throws XmlException, IOException {
        return load(new InputSource(in), options);
    }

    public Dom load(String s)
        throws XmlException {
        return load(s, null);
    }

    public Dom load(String s, XmlOptions options)
        throws XmlException {
        Reader r = new StringReader(s);

        try {
            return load(r, options);
        } catch (IOException e) {
            assert false : "StringReader should not throw IOException";

            throw new XmlException(e.getMessage(), e);
        } finally {
            try {
                r.close();
            } catch (IOException e) {
            }
        }
    }

    //
    // DOMImplementation methods
    //

    public Document createDocument(String uri, String qname,
                                   DocumentType doctype) {
        return DomImpl._domImplementation_createDocument(this, uri, qname,
            doctype);
    }

    public DocumentType createDocumentType(String qname, String publicId,
                                           String systemId) {
        throw new RuntimeException("Not implemented");
//        return DomImpl._domImplementation_createDocumentType( this, qname, publicId, systemId );
    }

    public boolean hasFeature(String feature, String version) {
        return DomImpl._domImplementation_hasFeature(this, feature, version);
    }

    public Object getFeature(String feature, String version) {
        throw new RuntimeException("DOM Level 3 Not implemented");
    }

    //
    // Dom methods
    //

    private static Dom checkNode(Node n) {
        if (n == null) {
            throw new IllegalArgumentException("Node is null");
        }

        if (!(n instanceof Dom)) {
            throw new IllegalArgumentException("Node is not an XmlBeans node");
        }

        return (Dom) n;
    }

    public static XmlCursor nodeToCursor(Node n) {
        return DomImpl._getXmlCursor(checkNode(n));
    }

    public static XmlObject nodeToXmlObject(Node n) {
        return DomImpl._getXmlObject(checkNode(n));
    }

    public static XMLStreamReader nodeToXmlStream(Node n) {
        return DomImpl._getXmlStreamReader(checkNode(n));
    }

    public static Node streamToNode(XMLStreamReader xs) {
        return Jsr173.nodeFromStream(xs);
    }

    //
    // SaajCallback methods
    //

    public void setSaajData(Node n, Object o) {
        assert n instanceof Dom;

        DomImpl.saajCallback_setSaajData((Dom) n, o);
    }

    public Object getSaajData(Node n) {
        assert n instanceof Dom;

        return DomImpl.saajCallback_getSaajData((Dom) n);
    }

    public Element createSoapElement(QName name, QName parentName) {
        assert _ownerDoc != null;

        return DomImpl.saajCallback_createSoapElement(_ownerDoc, name,
            parentName);
    }

    public Element importSoapElement(Document doc, Element elem, boolean deep,
                                     QName parentName) {
        assert doc instanceof Dom;

        return DomImpl.saajCallback_importSoapElement((Dom) doc, elem, deep,
            parentName);
    }

    public SchemaTypeLoader getSchemaTypeLoader() {
        return _schemaTypeLoader;
    }

    private static final class DefaultQNameFactory
        implements QNameFactory {
        private QNameCache _cache = XmlBeans.getQNameCache();

        public QName getQName(String uri, String local) {
            return _cache.getName(uri, local, "");
        }

        public QName getQName(String uri, String local, String prefix) {
            return _cache.getName(uri, local, prefix);
        }

        public QName getQName(char[] uriSrc, int uriPos, int uriCch,
                              char[] localSrc, int localPos, int localCch) {
            return
                _cache.getName(new String(uriSrc, uriPos, uriCch),
                    new String(localSrc, localPos, localCch),
                    "");
        }

        public QName getQName(char[] uriSrc, int uriPos, int uriCch,
                              char[] localSrc, int localPos, int localCch,
                              char[] prefixSrc, int prefixPos, int prefixCch) {
            return
                _cache.getName(new String(uriSrc, uriPos, uriCch),
                    new String(localSrc, localPos, localCch),
                    new String(prefixSrc, prefixPos, prefixCch));
        }
    }


    private static final class LocalDocumentQNameFactory
        implements QNameFactory {
        private QNameCache _cache = new QNameCache(32);

        public QName getQName(String uri, String local) {
            return _cache.getName(uri, local, "");
        }

        public QName getQName(String uri, String local, String prefix) {
            return _cache.getName(uri, local, prefix);
        }

        public QName getQName(char[] uriSrc, int uriPos, int uriCch,
                              char[] localSrc, int localPos, int localCch) {
            return
                _cache.getName(new String(uriSrc, uriPos, uriCch),
                    new String(localSrc, localPos, localCch),
                    "");
        }

        public QName getQName(char[] uriSrc, int uriPos, int uriCch,
                              char[] localSrc, int localPos, int localCch,
                              char[] prefixSrc, int prefixPos, int prefixCch) {
            return
                _cache.getName(new String(uriSrc, uriPos, uriCch),
                    new String(localSrc, localPos, localCch),
                    new String(prefixSrc, prefixPos, prefixCch));
        }
    }

    //
    //
    //

    boolean _noSync;

    SchemaTypeLoader _schemaTypeLoader;

    private ReferenceQueue _refQueue;
    private int _entryCount;

    int _numTempFramesLeft;
    Cur[] _tempFrames;

    Cur _curPool;
    int _curPoolCount;

    Cur _registered;

    ChangeListener _changeListeners;

    long _versionAll;
    long _versionSansText;

    Locations _locations;

    private CharUtil _charUtil;

    int _offSrc;
    int _cchSrc;

    Saaj _saaj;

    Dom _ownerDoc;

    QNameFactory _qnameFactory;

    boolean _validateOnSet;

    int _posTemp;

    nthCache _nthCache_A = new nthCache();
    nthCache _nthCache_B = new nthCache();

    domNthCache _domNthCache_A = new domNthCache();
    domNthCache _domNthCache_B = new domNthCache();
}
