/*   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.xml.sax.Locator;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.xml.sax.DTDHandler;

import java.util.HashMap;
import java.util.Map;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.Reference;
import java.lang.ref.PhantomReference;
import java.lang.ref.SoftReference;

import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.IOException;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamException;

import org.apache.xmlbeans.xml.stream.Attribute;
import org.apache.xmlbeans.xml.stream.AttributeIterator;
import org.apache.xmlbeans.xml.stream.CharacterData;
import org.apache.xmlbeans.xml.stream.ProcessingInstruction;
import org.apache.xmlbeans.xml.stream.Space;
import org.apache.xmlbeans.xml.stream.StartDocument;
import org.apache.xmlbeans.xml.stream.StartElement;
import org.apache.xmlbeans.xml.stream.XMLEvent;
import org.apache.xmlbeans.xml.stream.XMLInputStream;
import org.apache.xmlbeans.xml.stream.XMLName;

import org.apache.xmlbeans.impl.common.SAXHelper;
import org.apache.xmlbeans.impl.common.XMLNameHelper;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.common.XmlLocale;
import org.apache.xmlbeans.impl.common.ResolverUtil;
import org.apache.xmlbeans.impl.common.SystemCache;

import org.apache.xmlbeans.impl.store.Saaj.SaajCallback;

import org.apache.xmlbeans.impl.store.DomImpl.Dom;
import org.apache.xmlbeans.impl.store.DomImpl.TextNode;
import org.apache.xmlbeans.impl.store.DomImpl.CdataNode;
import org.apache.xmlbeans.impl.store.DomImpl.SaajTextNode;
import org.apache.xmlbeans.impl.store.DomImpl.SaajCdataNode;

import org.apache.xmlbeans.impl.store.Cur.Locations;

import org.apache.xmlbeans.CDataBookmark;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlLineNumber;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlCursor.XmlBookmark;
import org.apache.xmlbeans.XmlErrorCodes;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlOptionsBean;
import org.apache.xmlbeans.XmlSaxHandler;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlTokenSource;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.QNameCache;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.XmlRuntimeException;
import org.apache.xmlbeans.XmlDocumentProperties;

import org.apache.xmlbeans.impl.values.TypeStore;
import org.apache.xmlbeans.impl.values.TypeStoreUser;
import org.apache.xmlbeans.impl.values.TypeStoreUserFactory;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Element;

public final class Locale
    implements DOMImplementation, SaajCallback, XmlLocale
{
    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(-1)))
            {
                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.setProperty("http://xml.org/sax/properties/declaration-handler", this);
                _xr.setDTDHandler(this);
                _xr.setErrorHandler(this);
            }
            catch (Throwable e)
            {
                throw new RuntimeException(e.getMessage(), 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();
}
