/*   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.apache.xmlbeans.impl.values.TypeStore;
import org.apache.xmlbeans.xml.stream.CharacterData;
import org.apache.xmlbeans.xml.stream.ProcessingInstruction;
import org.apache.xmlbeans.xml.stream.*;
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;

public final class Locale
    implements DOMImplementation, SaajCallback, XmlLocale
{
    private static final XBLogger logger = XBLogFactory.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 int WS_UNSPECIFIED = TypeStore.WS_UNSPECIFIED;
    static final int WS_PRESERVE = TypeStore.WS_PRESERVE;
    static final int WS_REPLACE = TypeStore.WS_REPLACE;
    static final int WS_COLLAPSE = TypeStore.WS_COLLAPSE;

    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.hasOption(XmlOptions.UNSYNCHRONIZED);

        _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.hasOption(XmlOptions.VALIDATE_ON_SET);

        //
        // Check for Saaj implementation request
        //

        Object saajObj = options.get(Saaj.SAAJ_IMPL);

        if (saajObj != null)
        {
            if (!(saajObj instanceof Saaj))
                throw new IllegalStateException(
                    "Saaj impl not correct type: " + saajObj);

            _saaj = (Saaj) saajObj;

            _saaj.setCallback(this);
        }
    }

    //
    //
    //

    public static final String USE_SAME_LOCALE = "USE_SAME_LOCALE";
    /**
     * This option is checked in XmlObjectBase._copy(XmlOptions), the locale is used as the synchronization domain.
     * useNewLocale = true: copy will use a new locale, false: copy will use the same locale as the source
     * @deprecated Replace usages with CopyUseNewSynchronizationDomain option
     * @see org.apache.xmlbeans.XmlOptions#setCopyUseNewSynchronizationDomain(boolean)
     */
    public static final String COPY_USE_NEW_LOCALE             = "COPY_USE_NEW_LOCALE";

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

        options = XmlOptions.maskNull(options);

        Locale l = null;

        if (options.hasOption(USE_SAME_LOCALE))
        {
            Object source = options.get(USE_SAME_LOCALE);

            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.get(Saaj.SAAJ_IMPL))
                throw new IllegalArgumentException(
                    "Source locale does not support same saaj");

            if (l._validateOnSet &&
                !options.hasOption(XmlOptions.VALIDATE_ON_SET))
                throw new IllegalArgumentException(
                    "Source locale does not support same validate on set");

            // TODO - other things to check?
        }
        else
            l = new Locale(stl, options);

        return l;
    }

    //
    //
    //

    static void associateSourceName(Cur c, XmlOptions options)
    {
        String sourceName = (String) XmlOptions.safeGet(options,
            XmlOptions.DOCUMENT_SOURCE_NAME);

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

    //
    //
    //

    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 = (SchemaType) options.get(
            XmlOptions.DOCUMENT_TYPE);

        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;

        if (n1.getNamespaceURI() == n2.getNamespaceURI())
            return true;

        if (n1.getNamespaceURI() == null || n2.getNamespaceURI() == null)
            return false;

        return n1.getNamespaceURI().equals(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 ");
                        sb.append("expected " + docElemName.getLocalPart());
                        sb.append(" got " + name.getLocalPart());
                    }
                    else
                    {
                        sb.append(": document 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();
        }
    }

    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

            assert k != ATTR;

            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 = (SchemaType) options.get(XmlOptions.DOCUMENT_TYPE);

        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 (DOMImplementation) 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
    {
        Reader r = new StringReader(s);

        try
        {
            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);
        }
        finally
        {
            try
            {
                r.close();
            }
            catch (IOException e)
            {
            }
        }
    }

    //
    //
    //

    /**
     * @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
     */
    public static XmlObject parseToXmlObject(SchemaTypeLoader stl,
        XMLInputStream xis, SchemaType type, XmlOptions options)
        throws XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException
    {
        Locale l = getLocale(stl, options);

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

    /**
     * @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
     */
    public XmlObject parseToXmlObject(XMLInputStream xis, SchemaType type,
        XmlOptions options)
        throws XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException
    {
        Cur c;

        try
        {
            c = loadXMLInputStream(xis, options);
        }
        catch (org.apache.xmlbeans.xml.stream.XMLStreamException e)
        {
            throw new XmlException(e.getMessage(), e);
        }

        autoTypeDocument(c, type, options);

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

        c.release();

        return x;
    }

    //
    //
    //

    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(XMLEvent xe, LoadContext context)
    {
        org.apache.xmlbeans.xml.stream.Location loc = xe.getLocation();

        if (loc != null)
            context.lineNumber(loc.getLineNumber(), loc.getColumnNumber(), -1);
    }

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

    }

    /**
     * @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
     */
    private Cur loadXMLInputStream(XMLInputStream xis, XmlOptions options)
        throws org.apache.xmlbeans.xml.stream.XMLStreamException
    {
        options = XmlOptions.maskNull(options);

        boolean lineNums = options.hasOption(XmlOptions.LOAD_LINE_NUMBERS);

        XMLEvent x = xis.peek();

        if (x != null && x.getType() == XMLEvent.START_ELEMENT)
        {
            Map nsMap = ((StartElement) x).getNamespaceMap();

            if (nsMap != null && nsMap.size() > 0)
            {
                Map namespaces = new HashMap();

                namespaces.putAll(nsMap);

                options = new XmlOptions(options);

                options.put(XmlOptions.LOAD_ADDITIONAL_NAMESPACES, namespaces);
            }
        }

        String systemId = null;
        String encoding = null;
        String version = null;
        boolean standAlone = true;

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

        events:
        for (XMLEvent xe = xis.next(); xe != null; xe = xis.next())
        {
            switch (xe.getType())
            {
            case XMLEvent.START_DOCUMENT:
                StartDocument doc = (StartDocument) xe;

                systemId = doc.getSystemId();
                encoding = doc.getCharacterEncodingScheme();
                version = doc.getVersion();
                standAlone = doc.isStandalone();
                standAlone = doc.isStandalone();

                if (lineNums)
                    lineNumber(xe, context);

                break;

            case XMLEvent.END_DOCUMENT:
                if (lineNums)
                    lineNumber(xe, context);

                break events;

            case XMLEvent.NULL_ELEMENT:
                if (!xis.hasNext())
                    break events;
                break;

            case XMLEvent.START_ELEMENT:
                context.startElement(XMLNameHelper.getQName(xe.getName()));

                if (lineNums)
                    lineNumber(xe, context);

                for (AttributeIterator ai = ((StartElement) xe).getAttributes();
                     ai.hasNext();)
                {
                    Attribute attr = ai.next();

                    context.attr(XMLNameHelper.getQName(attr.getName()),
                        attr.getValue());
                }

                for (AttributeIterator ai = ((StartElement) xe).getNamespaces()
                    ; ai.hasNext();)
                {
                    Attribute attr = ai.next();

                    XMLName name = attr.getName();
                    String local = name.getLocalName();

                    if (name.getPrefix() == null && local.equals("xmlns"))
                        local = "";

                    context.xmlns(local, attr.getValue());
                }

                break;

            case XMLEvent.END_ELEMENT:
                context.endElement();

                if (lineNums)
                    lineNumber(xe, context);

                break;

            case XMLEvent.SPACE:
                if (((Space) xe).ignorable())
                    break;

                // Fall through

            case XMLEvent.CHARACTER_DATA:
                CharacterData cd = (CharacterData) xe;

                if (cd.hasContent())
                {
                    context.text(cd.getContent());

                    if (lineNums)
                        lineNumber(xe, context);
                }

                break;

            case XMLEvent.COMMENT:
                org.apache.xmlbeans.xml.stream.Comment comment =
                    (org.apache.xmlbeans.xml.stream.Comment) xe;

                if (comment.hasContent())
                {
                    context.comment(comment.getContent());

                    if (lineNums)
                        lineNumber(xe, context);
                }

                break;

            case XMLEvent.PROCESSING_INSTRUCTION:
                ProcessingInstruction procInstr = (ProcessingInstruction) xe;

                context.procInst(procInstr.getTarget(), procInstr.getData());

                if (lineNums)
                    lineNumber(xe, context);

                break;

                // These are ignored
            case XMLEvent.ENTITY_REFERENCE:
            case XMLEvent.START_PREFIX_MAPPING:
            case XMLEvent.END_PREFIX_MAPPING:
            case XMLEvent.CHANGE_PREFIX_MAPPING:
            case XMLEvent.XML_EVENT:
                break;

            default :
                throw new RuntimeException(
                    "Unhandled xml event type: " + xe.getTypeAsString());
            }
        }

        Cur c = context.finish();

        associateSourceName(c, options);

        XmlDocumentProperties props = getDocProps(c, true);

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

        return c;
    }

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

        boolean lineNums = options.hasOption(XmlOptions.LOAD_LINE_NUMBERS);

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

    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().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 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.put(Cur.LOAD_USE_LOCALE_CHAR_UTIL);

            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 SchemaType _type;
        private 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 HashMap _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 == Locale.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 == Locale.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 == Locale.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 StringBuffer _sb;
    }

    private static ThreadLocal tl_scrubBuffer =
        new ThreadLocal()
        {
            protected Object initialValue()
            {
                return new SoftReference(new ScrubBuffer());
            }
        };

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

    static ScrubBuffer getScrubBuffer(int wsr)
    {
        SoftReference softRef = (SoftReference) tl_scrubBuffer.get();
        ScrubBuffer 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;
    }

    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 namespaces)
    {
        assert c.isContainer();

        java.util.Iterator i = namespaces.keySet().iterator();

        while (i.hasNext())
        {
            String prefix = (String) i.next();

            // Usually, this is the predefined xml namespace
            if (!prefix.toLowerCase().startsWith("xml"))
            {
                if (c.namespaceForPrefix(prefix, false) == null)
                {
                    c.push();

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

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

                    c.pop();
                }
            }
        }
    }

    static Map getAllNamespaces(Cur c, Map 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 = DomImpl.firstChild(_parent);
                    _len = 0;

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

                for (; x != null; x = 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 = DomImpl.firstChild(_parent); x != null; x = 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 = DomImpl.nextSibling(_child); ; x = DomImpl.nextSibling(x) )
                    {
                        if (x == null)
                            return null;

                        _child = x;
                        _n++;

                        break;
                    }
                }
            }
            else if (n < _n)
            {
                while ( n < _n )
                {
                    for (Dom x = DomImpl.prevSibling(_child); ; x = 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;
    }

    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
    //

    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();

        protected 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);

        protected 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.hasOption(XmlOptions.LOAD_USE_DEFAULT_RESOLVER))
        {
            er = (EntityResolver) options.get(XmlOptions.ENTITY_RESOLVER);

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

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

        XMLReader xr = (XMLReader) options.get(
            XmlOptions.LOAD_USE_XMLREADER);

        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.hasOption(XmlOptions.LOAD_LINE_NUMBERS);
            _wantLineNumbersAtEndElt = safeOptions.hasOption(XmlOptions.LOAD_LINE_NUMBERS_END_ELEMENT);
            _wantCdataBookmarks = safeOptions.hasOption(XmlOptions.LOAD_SAVE_CDATA_BOOKMARKS);

            if (safeOptions.hasOption(XmlOptions.LOAD_ENTITY_BYTES_LIMIT))
                _entityBytesLimit = (Integer) (safeOptions.get(XmlOptions.LOAD_ENTITY_BYTES_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.log(XBLogger.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(),
                        (String) XmlOptions.safeGet(options,
                            XmlOptions.DOCUMENT_SOURCE_NAME),
                        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);
    }


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