/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache
*    XMLBeans", nor may "Apache" appear in their name, without prior
*    written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2000-2003 BEA Systems
* Inc., <http://www.bea.com/>. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/

package org.apache.xmlbeans.impl.values;

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

import weblogic.xml.stream.XMLInputStream;

import java.math.BigInteger;
import java.math.BigDecimal;
import java.io.Serializable;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.lang.reflect.Array;
import java.util.Date;
import java.util.List;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Calendar;
import java.util.Collection;

import org.apache.xmlbeans.impl.common.XmlWhitespace;
import org.apache.xmlbeans.impl.common.ValidationContext;
import org.apache.xmlbeans.impl.common.GlobalLock;
import org.apache.xmlbeans.impl.common.XmlErrorWatcher;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.schema.SchemaTypeImpl;
import org.apache.xmlbeans.impl.schema.SchemaTypeVisitorImpl;
import org.apache.xmlbeans.impl.validator.Validator;
import org.apache.xmlbeans.impl.values.XmlValueNotNillableException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.SchemaAttributeModel;
import org.apache.xmlbeans.XmlAnySimpleType;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlDocumentProperties;
import org.apache.xmlbeans.SimpleValue;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaField;
import org.apache.xmlbeans.SchemaProperty;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlRuntimeException;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.GDate;
import org.apache.xmlbeans.GDuration;
import org.apache.xmlbeans.GDateSpecification;
import org.apache.xmlbeans.GDurationSpecification;
import org.apache.xmlbeans.StringEnumAbstractBase;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.SchemaLocalAttribute;
import org.apache.xmlbeans.FilterXmlObject;

import org.w3c.dom.Node;

import org.xml.sax.ContentHandler;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.SAXException;

public abstract class XmlObjectBase implements TypeStoreUser, Serializable, XmlObject, SimpleValue
{
    public static final short MAJOR_VERSION_NUMBER = (short) 1; // for serialization
    public static final short MINOR_VERSION_NUMBER = (short) 1; // for serialization

    public final Object monitor()
    {
        if (has_store())
            return get_store().get_root_object();
        return this;
    }
    
    private static XmlObjectBase underlying(XmlObject obj)
    {
        if (obj == null)
            return null;
        if (obj instanceof XmlObjectBase)
            return (XmlObjectBase)obj;
        while (obj instanceof FilterXmlObject)
            obj = ((FilterXmlObject)obj).underlyingXmlObject();
        if (obj instanceof XmlObjectBase)
            return (XmlObjectBase)obj;
        throw new IllegalStateException("Non-native implementations of XmlObject should extend FilterXmlObject");
    }

    public final XmlObject copy()
    {
        synchronized (monitor())
        {
            // immutable objects don't get copied. They're immutable
            if (isImmutable())
                return this;

            check_orphaned();

            // copy the type
            XmlObject result = get_store().get_schematypeloader().newInstance(schemaType(), null);
            

            // copy the data
            XmlObjectBase target = underlying(result);
            target.get_store().copy_contents_from(get_store());
            
            return result;
        }
    }

    public XmlDocumentProperties documentProperties()
        { XmlCursor cur = newCursorForce(); try { return cur.documentProperties(); } finally { cur.dispose(); } }

    public XMLInputStream newXMLInputStream()
        { return newXMLInputStream(null); }

    public XMLInputStream newXMLInputStream(XmlOptions options)
        { XmlCursor cur = newCursorForce(); try { return cur.newXMLInputStream(makeInnerOptions(options)); } finally { cur.dispose(); } }

    public XMLStreamReader newXMLStreamReader()
        { return newXMLStreamReader(null); }
    
    public XMLStreamReader newXMLStreamReader(XmlOptions options)
        { XmlCursor cur = newCursorForce(); try { return cur.newXMLStreamReader(makeInnerOptions(options)); } finally { cur.dispose(); } }

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

    public InputStream newInputStream(XmlOptions options)
        { XmlCursor cur = newCursorForce(); try { return cur.newInputStream(makeInnerOptions(options)); } finally { cur.dispose(); } }

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

    public Reader newReader(XmlOptions options)
        { XmlCursor cur = newCursorForce(); try { return cur.newReader(makeInnerOptions(options)); } finally { cur.dispose(); } }

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

    public Node newDomNode(XmlOptions options)
        { XmlCursor cur = newCursorForce(); try { return cur.newDomNode(makeInnerOptions(options)); } finally { cur.dispose(); } }

    public void save(ContentHandler ch, LexicalHandler lh, XmlOptions options) throws SAXException
        { XmlCursor cur = newCursorForce(); try { cur.save(ch, lh, makeInnerOptions(options)); } finally { cur.dispose(); } }

    public void save(File file, XmlOptions options) throws IOException
        { XmlCursor cur = newCursorForce(); try { cur.save(file, makeInnerOptions(options)); } finally { cur.dispose(); } }

    public void save(OutputStream os, XmlOptions options) throws IOException
        { XmlCursor cur = newCursorForce(); try { cur.save(os, makeInnerOptions(options)); } finally { cur.dispose(); } }

    public void save(Writer w, XmlOptions options) throws IOException
        { XmlCursor cur = newCursorForce(); try { cur.save(w, makeInnerOptions(options)); } finally { cur.dispose(); } }

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

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

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

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

    public XmlCursor newCursorForce()
    {
        synchronized (monitor())
        {
            return ensureStore().newCursor();
        }
    }

    private XmlObject ensureStore()
    {
        if ((_flags & FLAG_STORE) != 0)
            return this;

        check_dated();

        String value =
            (_flags & FLAG_NIL) != 0
                ? ""
                : compute_text( has_store() ? get_store() : null );

        XmlOptions options = new XmlOptions().setDocumentType(schemaType());

        XmlObject x = XmlObject.Factory.newInstance( options );

        XmlCursor c = x.newCursor();
        c.toNextToken();
        c.insertChars( value );

        return x;
    }

    private static XmlOptions makeInnerOptions(XmlOptions options)
    {
        XmlOptions innerOptions = new XmlOptions( options );
        innerOptions.put( XmlOptions.SAVE_INNER );
        return innerOptions;
    }

    public XmlCursor newCursor()
    {
        if ((_flags & FLAG_STORE) == 0)
            throw new IllegalStateException("XML Value Objects cannot create cursors");

        synchronized (monitor())
        {
            check_orphaned();
            return get_store().new_cursor();
        }
    }

    public abstract SchemaType schemaType();

    public SchemaType instanceType()
        { synchronized (monitor()) { return isNil() ? null : schemaType(); } }

    private SchemaField schemaField() {
        SchemaType st = schemaType();
        SchemaField field;

        // First check if this field has an anonymous type
        field = st.getContainerField();

        if (field == null)
            field = get_store().get_schema_field();

        return field;
    }

    /**
     * Use _voorVc when you want to throw a ValueOutOfRangeException when
     * validating a simple type.
     */
    private static final class ValueOutOfRangeValidationContext implements ValidationContext
    {
        public void invalid(String message)
        {
            throw new XmlValueOutOfRangeException( message );
        }
    }

    /**
     * Used to supply validation context for the validate_value methods
     */
    private static final class ImmutableValueValidationContext implements ValidationContext
    {
        private XmlObject _loc;
        private Collection _coll;
        ImmutableValueValidationContext(Collection coll, XmlObject loc)
        {
            _coll = coll;
            _loc = loc;
        }
        public void invalid(String message)
        {
           _coll.add(XmlError.forObject(message, _loc));
        }
    }

    public static final ValidationContext _voorVc = new ValueOutOfRangeValidationContext();

    public boolean validate()
        { return validate(null); }

    public boolean validate(XmlOptions options)
    {
        if ((_flags & FLAG_STORE) == 0)
        {
            if ((_flags & FLAG_IMMUTABLE) != 0)
            {
                return validate_immutable(options);
            }

            throw new IllegalStateException(
                    "XML objects with no underlying store cannot be validated");
        }

        synchronized (monitor())
        {
            if ((_flags & FLAG_ORPHANED) != 0)
                throw new XmlValueDisconnectedException();

            SchemaField field = schemaField();
            SchemaType type = schemaType();

            TypeStore typeStore = get_store();

            Validator validator =
                new Validator(
                    type, field, typeStore.get_schematypeloader(), options, null);

            typeStore.validate( validator );

            return validator.isValid();
        }
    }

    private boolean validate_immutable(XmlOptions options)
    {
        Collection errorListener = options == null ? null : (Collection)options.get(XmlOptions.ERROR_LISTENER);
        XmlErrorWatcher watcher = new XmlErrorWatcher(errorListener);
        if (!schemaType().isSimpleType())
        {
            // cannot have any required attributes or elements
            SchemaProperty[] properties = schemaType().getProperties();
            for (int i = 0; i < properties.length; i++)
            {
                if (properties[i].getMinOccurs().signum() > 0)
                {
                    if (properties[i].isAttribute())
                        watcher.add(XmlError.forObject("Missing required attribute " + QNameHelper.pretty(properties[i].getName()), this));
                    else
                        watcher.add(XmlError.forObject("Missing required element " + QNameHelper.pretty(properties[i].getName()), this));
                }
            }

            if (schemaType().getContentType() != SchemaType.SIMPLE_CONTENT)
                return !watcher.hasError(); // don't validate non-simple-content
        }

        String text = (String)_textsource;
        if (text == null)
            text = "";
        validate_simpleval(text, new ImmutableValueValidationContext(watcher, this));
        return !watcher.hasError();
    }

    protected void validate_simpleval(String lexical, ValidationContext ctx)
    {
        return;
    }

    private static XmlObject[] _typedArray(XmlObject[] input)
    {
        if (input.length == 0)
            return input;
        SchemaType commonType = input[0].schemaType();
        if (commonType.equals(XmlObject.type))
            return input;
        for (int i = 1; i < input.length; i++)
        {
            commonType = commonType.getCommonBaseType(input[i].schemaType());
            if (commonType.equals(XmlObject.type))
                return input;
        }
        Class desiredClass = commonType.getJavaClass();
        while (desiredClass == null)
        {
            commonType = commonType.getBaseType();
            if (XmlObject.type.equals(commonType))
                return input;
            desiredClass = commonType.getJavaClass();
        }

        XmlObject[] result = (XmlObject[])Array.newInstance(desiredClass, input.length);
        System.arraycopy(input, 0, result, 0, input.length);
        return result;
    }

    public XmlObject[] selectPath ( String path )
    {
        return selectPath( path, null );
    }

    public XmlObject[] selectPath ( String path, XmlOptions options )
    {
        XmlObject [] selections;

        // all user-level code; doesn't need to be synchronized

        XmlCursor c = newCursor();

        if (c == null)
            throw new XmlValueDisconnectedException();

        try
        {
            c.selectPath( path, options );

            if (!c.hasNextSelection())
                selections = new XmlObject[ 0 ];
            else
            {
                selections = new XmlObject [ c.getSelectionCount() ];

                for (int i = 0 ; c.toNextSelection() ; i++)
                {
                    if ((selections[ i ] = c.getObject()) == null)
                    {
                        throw
                            new XmlRuntimeException(
                                "Path must select only elements " +
                                    "and attributes" );
                    }
                }
            }
        }
        finally
        {
            c.dispose();
        }

        return _typedArray(selections);
    }

    public XmlObject[] execQuery ( String path )
    {
        return execQuery( path, null );
    }

    public XmlObject[] execQuery ( String queryExpr, XmlOptions options )
    {
        synchronized (monitor())
        {
            TypeStore typeStore = get_store();

            if (typeStore == null)
            {
                throw
                    new XmlRuntimeException(
                        "Cannot do XQuery on XML Value Objects" );
            }

            try
            {
                return _typedArray(typeStore.exec_query( queryExpr, options ));
            }
            catch (XmlException e)
            {
                throw new XmlRuntimeException( e );
            }
        }
    }

    public XmlObject changeType(SchemaType type)
    {
        if (type == null)
            throw new IllegalArgumentException( "Invalid type (null)" );

        if ((_flags & FLAG_STORE) == 0)
        {
            throw
                new IllegalStateException(
                    "XML Value Objects cannot have thier type changed" );
        }

        synchronized (monitor())
        {
            check_orphaned();
            return (XmlObject) get_store().change_type( type );
        }
    }

    private int _flags;
    private Object _textsource;

    protected XmlObjectBase()
    {
        _flags = FLAG_NILLABLE | FLAG_NIL;
    }

    public void init_flags(SchemaProperty prop)
    {
        if (prop == null) return;

        if (prop.hasDefault() == SchemaProperty.VARIABLE ||
            prop.hasFixed() == SchemaProperty.VARIABLE ||
            prop.hasNillable() == SchemaProperty.VARIABLE)
            return;

        _flags |=
            (prop.hasDefault() == SchemaProperty.NEVER ? 0 : TypeStore.HASDEFAULT) |
            (prop.hasFixed() == SchemaProperty.NEVER ? 0 : TypeStore.FIXED) |
            (prop.hasNillable() == SchemaProperty.NEVER ? 0 : TypeStore.NILLABLE) |
            (FLAG_NOT_VARIABLE);
    }

    {
        assert TypeStore.NILLABLE   == 1;
        assert TypeStore.HASDEFAULT == 2;
        assert TypeStore.FIXED      == 4;
    }

    private static final int FLAG_NILLABLE        = TypeStore.NILLABLE;
    private static final int FLAG_HASDEFAULT      = TypeStore.HASDEFAULT;
    private static final int FLAG_FIXED           = TypeStore.FIXED;
    private static final int FLAG_ATTRIBUTE       =     8;
    private static final int FLAG_STORE           =    16;
    private static final int FLAG_VALUE_DATED     =    32;
    private static final int FLAG_NIL             =    64;
    private static final int FLAG_NIL_DATED       =   128;
    private static final int FLAG_ISDEFAULT       =   256;
    private static final int FLAG_ELEMENT_DATED   =   512;
    private static final int FLAG_SETTINGDEFAULT  =  1024;
    private static final int FLAG_ORPHANED        =  2048;
    private static final int FLAG_IMMUTABLE       =  4096;
    private static final int FLAG_COMPLEXTYPE     =  8192;
    private static final int FLAG_COMPLEXCONTENT  = 16384;
    private static final int FLAG_NOT_VARIABLE    = 32768;
    private static final int FLAG_VALIDATE_ON_SET = 65536;


    /**
     * The three dated flags are always stacked:
     *     FLAG_ELEMENT_DATED implies FLAG_NIL_DATED is set
     *     FLAG_NIL_DATED implies FLAG_TEXT_DATED is set.
     * checkers work on the flags from top to bottom.
     */
    private static final int FLAGS_DATED =
            FLAG_VALUE_DATED | FLAG_NIL_DATED | FLAG_ELEMENT_DATED;

    /**
     * The three element status flags have one interrlationshiop:
     *     FLAG_FIXED implies FLAG_HASDEFAULT is set.
     * These flags are used when setting nils, defaults, strings.
     * Since an initial get implies setting from text, they're
     * also used during getting.
     */
    private static final int FLAGS_ELEMENT =
            FLAG_NILLABLE | FLAG_FIXED | FLAG_HASDEFAULT;


    /**
     * Called by restriction subclasses within their constructors to enable
     * complex type support.
     */
    protected void initComplexType(boolean complexType, boolean complexContent)
    {
        _flags |= (complexType ? FLAG_COMPLEXTYPE : 0) |
                  (complexContent ? FLAG_COMPLEXCONTENT : 0);
    }

    protected boolean _isComplexType()
        { return (_flags & FLAG_COMPLEXTYPE) != 0; }

    protected boolean _isComplexContent()
        { return (_flags & FLAG_COMPLEXCONTENT) != 0; }

    public void setValidateOnSet() {
        _flags |= FLAG_VALIDATE_ON_SET;
    }

    protected boolean _validateOnSet()
        { return (_flags & FLAG_VALIDATE_ON_SET) != 0; }

    /**
     * True if the value is nilled.
     */
    public final boolean isNil()
    {
        synchronized (monitor())
        {
            check_dated();
            return ((_flags & FLAG_NIL) != 0);
        }
    }

    /**
     * True if the value is fixed.
     */
    public final boolean isFixed()
    {
        check_element_dated();
        return ((_flags & FLAG_FIXED) != 0);
    }

    /**
     * True if the value is allowed to be nil.
     */
    public final boolean isNillable()
    {
        check_element_dated();
        return ((_flags & FLAG_NILLABLE) != 0);
    }

    /**
     * True if the value is currently defaulted.
     */
    public final boolean isDefaultable()
    {
        check_element_dated();
        return ((_flags & FLAG_HASDEFAULT) != 0);
    }

    /**
     * True if the value is currently defaulted.
     */
    public final boolean isDefault()
    {
        check_dated();
        return ((_flags & FLAG_ISDEFAULT) != 0);
    }


    /**
     * Nils the value.
     */
    public final void setNil()
    {
        synchronized (monitor())
        {
            set_prepare();

            // if we're not nillable, throw exception on setNil(true)
            if ((_flags & FLAG_NILLABLE) == 0)
                throw new XmlValueNotNillableException();

            // the implementation should zero the value to reflect nil
            set_nil();

            // set the nil flag
            _flags |= FLAG_NIL;

            // ordinary commit except no clearing of nil flag
            if ((_flags & FLAG_STORE) != 0)
            {
                _flags &= ~FLAGS_DATED;
                get_store().invalidate_nil();
            }
            else
            {
                _textsource = null;
            }
        }
    }

    /**
     * Used for situations where these flags must be passed on to
     * chained values. (See XmlAnySimpleType (allSimpleValue), union
     * implementations).
     */
    protected int elementFlags()
    {
        check_element_dated();
        return (_flags & FLAGS_ELEMENT);
    }

    /**
     * Used to make a free-standing xml simple value instance immutable.
     * This is a one-way street, and it is illegal to attempt to make a
     * value that is embedded in an xml document immutable.
     *
     * Once a value is marked as immutable, it is illegal to call setters
     * of any kind.
     */
    public void setImmutable()
    {
        if ((_flags & (FLAG_IMMUTABLE | FLAG_STORE)) != 0)
            throw new IllegalStateException();

        _flags |= FLAG_IMMUTABLE;
    }

    /**
     * Is this instance an immutable value?
     */
    public boolean isImmutable()
    {
        return (_flags & FLAG_IMMUTABLE) != 0;
    }




    // TEXTUSER implementation

    /**
     * Called to initialize the TypeStore associated with this XmlObject
     * implementation. If not called, this is a free-floating value holder.
     *
     * When a value is first attached, it is put in a completely invalidated
     * state.
     */
    public final void attach_store(TypeStore store)
    {
        _textsource = store;
        if ((_flags & FLAG_IMMUTABLE) != 0)
            throw new IllegalStateException();
        _flags |= FLAG_STORE | FLAG_VALUE_DATED | FLAG_NIL_DATED | FLAG_ELEMENT_DATED;

        if (store.is_attribute())
            _flags |= FLAG_ATTRIBUTE;

        if (store.validate_on_set())
            _flags |= FLAG_VALIDATE_ON_SET;
    }

    /**
     * Called by a TypeStore to indicate that the text has been
     * invalidated and should be fetched next time the value is
     * needed.
     */
    public final void invalidate_value()
    {
        assert((_flags & FLAG_STORE) != 0);
        _flags |= FLAG_VALUE_DATED;
    }

    public final boolean uses_invalidate_value()
    {
        SchemaType type = schemaType();
        return type.isSimpleType() || type.getContentType() == SchemaType.SIMPLE_CONTENT;
    }

    /**
     * Called by a TypeStore to indicate that the xsi:nil attribute
     * on the containing element (and possibly the text) has been
     * invalidated and both should be consulted next time the value
     * is needed.
     */
    public final void invalidate_nilvalue()
    {
        assert((_flags & FLAG_STORE) != 0);
        _flags |= FLAG_VALUE_DATED | FLAG_NIL_DATED;
    }

    /**
     * Called by a TypeStore to indicate that the element's default
     * value, nillability, fixedness, etc, may have changed by
     * virtue of the element order changing (and xsi:nil and the
     * text may have changed too); so the store should be consulted
     * next time any setter or getter is called.
     */
    public final void invalidate_element_order()
    {
        assert((_flags & FLAG_STORE) != 0);
        _flags |= FLAG_VALUE_DATED | FLAG_NIL_DATED | FLAG_ELEMENT_DATED;
    }

    /**
     * Used by the ComplexTypeImpl subclass to get direct access
     * to the store.
     */
    public final TypeStore get_store()
    {
        assert((_flags & FLAG_STORE) != 0);
        return (TypeStore)_textsource;
    }

    protected final boolean has_store()
    {
        return (_flags & FLAG_STORE) != 0;
    }

    /**
     * Called by a TypeStore to pull out the most reasonable
     * text value from us. This is done after we have invalidated
     * the store (typically when our value has been set).
     */
    public final String build_text(NamespaceManager nsm)
    {
        assert((_flags & FLAG_STORE) != 0);
        assert((_flags & FLAG_VALUE_DATED) == 0);
        if ((_flags & (FLAG_NIL | FLAG_ISDEFAULT)) != 0)
            return "";
        return compute_text(
                    nsm == null ? has_store() ? get_store() : null : nsm);
    }

    /**
     * A store will call back on build_nil after we've called invalidate_nil
     * and it needs to know what the nil value is.
     */
    public boolean build_nil()
    {
        assert((_flags & FLAG_STORE) != 0);
        assert((_flags & FLAG_VALUE_DATED) == 0);
        return (_flags & FLAG_NIL) != 0;
    }

    /**
     * A store will call back on validate_now to force us to look at
     * the text if we're in an invalid state. We're allowed to throw
     * an exception if the text isn't valid for our type.
     */
    public void validate_now()
    {
        check_dated();
    }

    /**
     * A store calls back here in order to force a disconnect.
     * After this is done, the object should be considered invalid.
     * Any attempt to access or set a value should result in an
     * exception.
     *
     * Note that this is how we handle deletions and xsi:type changes.
     */
    public void disconnect_store()
    {
        assert((_flags & FLAG_STORE) != 0);
        _flags |= FLAGS_DATED | FLAG_ORPHANED;
        // do NOT null out _textsource, because we need it non-null for synchronization
    }

    /**
     * A typestore user can create a new TypeStoreUser instance for
     * a given element child name as long as you also pass the
     * qname contained by the xsi:type attribute, if any.
     *
     * Note that we will ignore the xsiType if it turns out to be invalid.
     *
     * Returns null if there is no strongly typed information for that
     * given element (which implies, recusively, no strongly typed information
     * downwards).
     */
    public TypeStoreUser create_element_user(QName eltName, QName xsiType)
    {
        return
            (TypeStoreUser)
                ((SchemaTypeImpl) schemaType()).createElementType(
                    eltName, xsiType, get_store().get_schematypeloader() );

        /*
        SchemaTypeImpl stype = (SchemaTypeImpl)schemaType().getElementType(eltName, xsiType, get_store().get_schematypeloader());
        if (stype == null)
            return null;
        return (TypeStoreUser)stype.createUnattachedNode();
        */
    }

    /**
     * A typestore user can create a new TypeStoreUser instance for
     * a given attribute child, based on the attribute name.
     *
     * Returns null if there is no strongly typed information for that
     * given attributes.
     */
    public TypeStoreUser create_attribute_user(QName attrName)
    {
        return (TypeStoreUser)((SchemaTypeImpl)schemaType()).createAttributeType(attrName, get_store().get_schematypeloader());
    }

    public SchemaType get_schema_type()
    {
        return schemaType();
    }

    public SchemaType get_element_type(QName eltName, QName xsiType)
    {
        return schemaType().getElementType(
            eltName, xsiType, get_store().get_schematypeloader() );
    }

    public SchemaType get_attribute_type(QName attrName)
    {
        return schemaType().getAttributeType(
            attrName, get_store().get_schematypeloader() );
    }

    /**
     * Returns the default element text, if it's consistent. If it's
     * not consistent, returns null, and requires a visitor walk.
     *
     * Also returns null if there is no default at all (although
     * that can also be discovered via get_elementflags without
     * doing a walk).
     */
    public String get_default_element_text(QName eltName)
    {
        assert(_isComplexContent());
        if (!_isComplexContent())
            throw new IllegalStateException();

        SchemaProperty prop = schemaType().getElementProperty(eltName);
        if (prop == null)
            return "";
        return prop.getDefaultText();
    }

    /**
     * Returns the default attribute text for the attribute with
     * the given name, or null if no default.
     */
    public String get_default_attribute_text(QName attrName)
    {
        assert(_isComplexType());
        if (!_isComplexType())
            throw new IllegalStateException();

        SchemaProperty prop = schemaType().getAttributeProperty(attrName);
        if (prop == null)
            return "";
        return prop.getDefaultText();
    }

    /**
     * Returns the elementflags, if they're consistent. If they're
     * not, returns -1, and requires a vistor walk.
     */
    public int get_elementflags(QName eltName)
    {
        if (!_isComplexContent())
            return 0;

        SchemaProperty prop = schemaType().getElementProperty(eltName);
        if (prop == null)
            return 0;
        if (prop.hasDefault() == SchemaProperty.VARIABLE ||
            prop.hasFixed() == SchemaProperty.VARIABLE ||
            prop.hasNillable() == SchemaProperty.VARIABLE)
            return -1;
        return
            (prop.hasDefault() == SchemaProperty.NEVER ? 0 : TypeStore.HASDEFAULT) |
            (prop.hasFixed() == SchemaProperty.NEVER ? 0 : TypeStore.FIXED) |
            (prop.hasNillable() == SchemaProperty.NEVER ? 0 : TypeStore.NILLABLE);
    }

    /**
     * Returns the flags for the given attribute.
     */
    public int get_attributeflags(QName attrName)
    {
        if (!_isComplexType())
            return 0;
        SchemaProperty prop = schemaType().getAttributeProperty(attrName);
        if (prop == null)
            return 0;
        return
            (prop.hasDefault() == SchemaProperty.NEVER ? 0 : TypeStore.HASDEFAULT) |
            (prop.hasFixed() == SchemaProperty.NEVER ? 0 : TypeStore.FIXED);
        // BUGBUG: todo: hook up required?
    }

    /**
     * Returns false if child elements are insensitive to order;
     * if it returns true, you're required to call invalidate_element_order
     * on children to the right of any child order rearrangement.
     */
    public boolean is_child_element_order_sensitive()
    {
        if (!_isComplexType())
            return false;
        return schemaType().isOrderSensitive();
    }

    /**
     * Inserting a new element is always unambiguous except in one
     * situation: when adding an element after the last one with
     * that name (or the first one if there are none).
     *
     * In that case, add the element at the first possible slot
     * BEFORE any element whose qname is contained in the QNameSet
     * given. (If the QNameSet is empty, that means add the new
     * element at the very end.)
     *
     * If the returned QNameSet is null, treat it as if the QNameSet
     * contained all QNames, i.e., add the new element at the very
     * first position possible (adjacent to the last element of the
     * same name, or at the very first slot if it is the first elt
     * with that name).
     */
    public final QNameSet get_element_ending_delimiters(QName eltname)
    {
        SchemaProperty prop = schemaType().getElementProperty(eltname);
        if (prop == null)
            return null;
        return prop.getJavaSetterDelimiter();
    }

    /**
     * A typestore user can return a visitor that is used to compute
     * default text and elementflags for an arbitrary element.
     */
    public TypeStoreVisitor new_visitor()
    {
        if (!_isComplexContent())
            return null;
        return new SchemaTypeVisitorImpl(schemaType().getContentModel());
    }

    public SchemaField get_attribute_field(QName attrName)
    {
        SchemaAttributeModel model = schemaType().getAttributeModel();
        if (model == null)
            return null;
        return model.getAttribute(attrName);
    }


    /**
     * Setting a string preserves any noncanonical literal
     * representation. This is done by storing the actual
     * string in the underlying store after checking it
     * against the primitive type for validity.
     */
    protected void set_String(String v)
    {
        if ((_flags & FLAG_IMMUTABLE) != 0)
            throw new IllegalStateException();

        boolean wasNilled = ((_flags & FLAG_NIL) != 0);

        // update the underlying value from the string
        String wscanon = apply_wscanon(v);
        update_from_wscanon_text(wscanon);

        // Now store the literal text immediately in the underlying
        if ((_flags & FLAG_STORE) != 0)
        {
            _flags &= ~FLAG_VALUE_DATED;
            get_store().store_text(v);
            if (wasNilled)
                get_store().invalidate_nil();
        }
        else
            _textsource = v;
    }

    /**
     * Update the value based on complex content.
     */
    protected void update_from_complex_content()
    {
        throw new XmlValueOutOfRangeException();
    }

    /**
     * Utility to update the value based on a string that
     * was passed either from the text store or from the user.
     * This function handles the cases where there is a default
     * that must be applied, and where the value must match
     * a fixed value.
     */
    private final void update_from_wscanon_text(String v)
    {
        // Whitespace is default if this type treats this space as defaultable
        if ((_flags & FLAG_HASDEFAULT) != 0 &&  (_flags & FLAG_SETTINGDEFAULT) == 0)
        {
            // This isn't quite correct since the .equals("") test should be
            // done on the actual text, not the wscanon text
            if ((_flags & FLAG_ATTRIBUTE) == 0 && v.equals(""))
            {
                String def = get_store().compute_default_text();
                if (def == null)
                    throw new XmlValueOutOfRangeException();

                // protect against recursion with this flag
                _flags |= FLAG_SETTINGDEFAULT;
                try { this.set(def); }
                finally { _flags &= ~FLAG_SETTINGDEFAULT; }
                _flags &= ~FLAG_NIL;
                _flags |= FLAG_ISDEFAULT;
                return;
            }
        }
        // If we haven't returned yet, the default doesn't apply.

        // Ask underlying impl to parse ordinary non-default text
        set_text(v);
        _flags &= ~(FLAG_NIL | FLAG_ISDEFAULT);
    }

    /**
     * Types should return false if they don't treat the given
     * whitespace as a default value.
     */
    protected boolean is_defaultable_ws(String v)
    {
        return true;
    }

    /**
     * Returns the whitespace rule that will be applied before
     * building a string to pass to get_text().
     *
     * Overridden by subclasses that don't need their text
     * for set_text canonicalized; perhaps they already implement
     * scanners that can deal with whitespace, and they know
     * they have no regex pattern restrictions.
     */
    protected int get_wscanon_rule()
    {
        return SchemaType.WS_COLLAPSE;
    }

    /**
     * Called to canonicalize whitespace before calling set_text.
     *
     * Tries to avoid allocation when the string is already canonical, but
     * otherwise this is not particularly efficient. Hopefully the common
     * case is that we pass our wscanon rule to the store via fetch_text
     * and it's canonicalized before we even see it as a string.
     */
    private final String apply_wscanon(String v)
    {
        return XmlWhitespace.collapse(v, get_wscanon_rule());
    }

    /**
     * Called before every set and get, to ensure that we have
     * a correct picture of whether we're nillable, fixed, or
     * if we have a default that can be applied.
     */
    private final void check_element_dated()
    {
        if ((_flags & FLAG_ELEMENT_DATED) != 0 &&
            (_flags & FLAG_NOT_VARIABLE) == 0)
        {
            if ((_flags & FLAG_ORPHANED) != 0)
                throw new XmlValueDisconnectedException();

            int eltflags = get_store().compute_flags();
            // int eltflags = 0;
            _flags &= ~(FLAGS_ELEMENT | FLAG_ELEMENT_DATED);
            _flags |= eltflags;
        }
        if ((_flags & FLAG_NOT_VARIABLE) != 0)
            _flags &= ~(FLAG_ELEMENT_DATED);
    }

    /**
     * Describes the orphaned status of this object.
     */
    protected final boolean is_orphaned()
    {
        return (_flags & FLAG_ORPHANED) != 0;
    }

    /**
     * Called before every getter and setter on the strongly
     * typed classes to ensure that the object has not been
     * orphaned.
     */
    protected final void check_orphaned()
    {
        if (is_orphaned())
            throw new XmlValueDisconnectedException();
    }

    /**
     * Called prior to every get operation, to ensure
     * that the value being read is valid. If the value
     * has been invalidated, it is re-read from the underlying
     * text store, and this may cause an out of range exception.
     *
     * This method deals with nils, nillability, defaults, etc.
     */
    public final void check_dated()
    {
        if ((_flags & FLAGS_DATED) != 0)
        {
            if ((_flags & FLAG_ORPHANED) != 0)
                throw new XmlValueDisconnectedException();

            assert((_flags & FLAG_STORE) != 0);

            check_element_dated();

            if ((_flags & FLAG_ELEMENT_DATED) != 0)
            {
                int eltflags = get_store().compute_flags();
                _flags &= ~(FLAGS_ELEMENT | FLAG_ELEMENT_DATED);
                _flags |= eltflags;
            }

            boolean nilled = false;

            if ((_flags & FLAG_NIL_DATED) != 0)
            {
                if (get_store().find_nil())
                {
                    if ((_flags & FLAG_NILLABLE) == 0)
                        throw new XmlValueOutOfRangeException(); // nil not allowed

                    // let the implementation know that we're nil now
                    set_nil();

                    _flags |= FLAG_NIL;
                    nilled = true;
                }
                else
                {
                    _flags &= ~FLAG_NIL;
                }
                _flags &= ~FLAG_NIL_DATED;
            }

            if (!nilled)
            {
                String text;

                if ((_flags & FLAG_COMPLEXCONTENT) != 0 || (text = get_wscanon_text()) == null)
                    update_from_complex_content();
                else
                {
                    NamespaceContext.push(new NamespaceContext(get_store()));
                    try { update_from_wscanon_text(text); }
                    finally { NamespaceContext.pop(); }
                }
            }

            _flags &= ~FLAG_VALUE_DATED;
        }
    }

    /**
     * Called before every set operation (except for the
     * special case of setting a string) to:
     * (1) get the nillable, fixed, etc flags
     * (2) throw an exception if it's fixed (not for strings)
     */
    private final void set_prepare()
    {
        check_element_dated();
        if ((_flags & FLAG_IMMUTABLE) != 0)
            throw new IllegalStateException();
    }

    /**
     * Called after every set operation to invalidate
     * the attached raw text. Also, if we were dated,
     * we make a note that we're now current, since the
     * latest set beats the previous invalidate. Also,
     * if we were nil, we're no longer.
     */
    private final void set_commit()
    {
        boolean wasNilled = ((_flags & FLAG_NIL) != 0);
          _flags &= ~(FLAG_NIL | FLAG_ISDEFAULT);

        if ((_flags & FLAG_STORE) != 0)
        {
            _flags &= ~(FLAGS_DATED);
            get_store().invalidate_text();
            if (wasNilled)
                get_store().invalidate_nil();
        }
        else
        {
            _textsource = null;
        }
    }

    /**
     * Grabs the undelying litral representation, applying the
     * implementation's wscanon rule.
     * Null if not simple content.
     */
    public final String get_wscanon_text()
    {
        if ((_flags & FLAG_STORE) == 0)
        {
            return apply_wscanon((String)_textsource);
        }
        else return get_store().fetch_text(get_wscanon_rule());
    }

    /**
     * This should set the value of the type from text,
     * or throw an XmlValueOutOfRangeException if it can't.
     */
    abstract protected void set_text(String text);

    /**
     * This should clear the value, and set it to whatever
     * is supposed to be returned when the value is nilled.
     */
    abstract protected void set_nil();

    /**
     * This should return the canonical string value of the primitive.
     * Only called when non-nil.
     */
    abstract protected String compute_text(NamespaceManager nsm);

    // SIMPLE VALUE ACCESSORS BELOW -------------------------------------------

    // numerics: fractional
    public float floatValue()
        { BigDecimal bd = bigDecimalValue(); return bd == null ? 0.0f : bd.floatValue(); }
    public double doubleValue()
        { BigDecimal bd = bigDecimalValue(); return bd == null ? 0.0 : bd.doubleValue(); }
    public BigDecimal bigDecimalValue()
        { throw new XmlValueOutOfRangeException(); }

    // numerics: integral
    public BigInteger bigIntegerValue()
        { BigDecimal bd = bigDecimalValue(); return bd == null ? null : bd.toBigInteger(); }

    public byte byteValue()
    {
        long l = intValue();
        if (l > Byte.MAX_VALUE) throw new XmlValueOutOfRangeException();
        if (l < Byte.MIN_VALUE) throw new XmlValueOutOfRangeException();
        return (byte)l;
    }

    public short shortValue()
    {
        long l = intValue();
        if (l > Short.MAX_VALUE) throw new XmlValueOutOfRangeException();
        if (l < Short.MIN_VALUE) throw new XmlValueOutOfRangeException();
        return (short)l;
    }

    public int intValue()
    {
        long l = longValue();
        if (l > Integer.MAX_VALUE) throw new XmlValueOutOfRangeException();
        if (l < Integer.MIN_VALUE) throw new XmlValueOutOfRangeException();
        return (int)l;
    }
    private static final BigInteger _max = BigInteger.valueOf(Long.MAX_VALUE);
    private static final BigInteger _min = BigInteger.valueOf(Long.MIN_VALUE);

    public long longValue()
    {
        BigInteger b = bigIntegerValue();
        if (b == null) return 0L;
        if (b.compareTo(_max) >= 0) throw new XmlValueOutOfRangeException();
        if (b.compareTo(_min) <= 0) throw new XmlValueOutOfRangeException();
        return b.longValue();
    }

    private static final XmlOptions _toStringOptions =
        buildInnerPrettyOptions();

    static final XmlOptions buildInnerPrettyOptions()
    {
        XmlOptions options = new XmlOptions();
        options.put( XmlOptions.SAVE_INNER );
        options.put( XmlOptions.SAVE_PRETTY_PRINT );
        options.put( XmlOptions.SAVE_AGGRESSIVE_NAMESPACES );
        options.put( XmlOptions.SAVE_USE_DEFAULT_NAMESPACE );
        return options;
    }

    /*
    private static final void dumpStack ( String msg )
    {
        try
        {
            java.io.FileOutputStream fos = new java.io.FileOutputStream( "C:\\ee.txt", true );
            java.io.PrintStream ps = new java.io.PrintStream( fos );
            ps.println( "======================================" );
            ps.println( msg );
            new Exception().printStackTrace( ps );
            ps.close();
            fos.close();
        }
        catch ( Exception e )
        {
        }

    }
    */

    public final String toString( )
    {
        synchronized (monitor())
        {
            return ensureStore().xmlText(_toStringOptions);
        }
    }

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

    public String xmlText (XmlOptions options)
    {
        XmlCursor cur = newCursorForce();

        try
        {
            return cur.xmlText(makeInnerOptions(options));
        }
        finally
        {
            cur.dispose();
        }
    }

    // enums
    public StringEnumAbstractBase enumValue()
        { throw new XmlValueOutOfRangeException(); }

    // various
    public String stringValue()
    {
        // Since complex-content types don't have a "natural" string value, we
        // emit the deeply concatenated, tag-removed content of the tag.
        synchronized (monitor())
        {
            if (_isComplexContent())
                return get_store().fetch_text(TypeStore.WS_PRESERVE);

            check_dated();
            if ((_flags & FLAG_NIL) != 0)
                return null;
            return compute_text(has_store() ? get_store() : null);
        }
    }

    public String getStringValue()
        { return stringValue(); }
    public boolean getBooleanValue()
        { return booleanValue(); }
    public byte getByteValue()
        { return byteValue(); }
    public short getShortValue()
        { return shortValue(); }
    public int getIntValue()
        { return intValue(); }
    public long getLongValue()
        { return longValue(); }
    public BigInteger getBigIntegerValue()
        { return bigIntegerValue(); }
    public BigDecimal getBigDecimalValue()
        { return bigDecimalValue(); }
    public float getFloatValue()
        { return floatValue(); }
    public double getDoubleValue()
        { return doubleValue(); }
    public byte[] getByteArrayValue()
        { return byteArrayValue(); }
    public StringEnumAbstractBase getEnumValue()
        { return enumValue(); }
    public Calendar getCalendarValue()
        { return calendarValue(); }
    public Date getDateValue()
        { return dateValue(); }
    public GDate getGDateValue()
        { return gDateValue(); }
    public GDuration getGDurationValue()
        { return gDurationValue(); }
    public QName getQNameValue()
        { return qNameValue(); }
    public List xgetListValue()
        { return xlistValue(); }
    public List getListValue()
        { return listValue(); }
    public Object getObjectValue()
        { return objectValue(); }

    public void setStringValue(String obj)
        { set(obj); }
    public void setBooleanValue(boolean v)
        { set(v); }
    public void setByteValue(byte v)
        { set(v); }
    public void setShortValue(short v)
        { set(v); }
    public void setIntValue(int v)
        { set(v); }
    public void setLongValue(long v)
        { set(v); }
    public void setBigIntegerValue(BigInteger obj)
        { set(obj); }
    public void setBigDecimalValue(BigDecimal obj)
        { set(obj); }
    public void setFloatValue(float v)
        { set(v); }
    public void setDoubleValue(double v)
        { set(v); }
    public void setByteArrayValue(byte[] obj)
        { set(obj); }
    public void setEnumValue(StringEnumAbstractBase obj)
        { set(obj); }
    public void setCalendarValue(Calendar obj)
        { set(obj); }
    public void setDateValue(Date obj)
        { set(obj); }
    public void setGDateValue(GDate obj)
        { set(obj); }
    public void setGDurationValue(GDuration obj)
        { set(obj); }
    public void setQNameValue(QName obj)
        { set(obj); }
    public void setListValue(List obj)
        { set(obj); }
    public void setObjectValue(Object obj)
        { objectSet(obj); }

    public byte[] byteArrayValue()
        { throw new XmlValueOutOfRangeException(); }
    public boolean booleanValue()
        { throw new XmlValueOutOfRangeException(); }
    public GDate gDateValue()
        { throw new XmlValueOutOfRangeException(); }
    public Date dateValue()
        { throw new XmlValueOutOfRangeException(); }
    public Calendar calendarValue()
        { throw new XmlValueOutOfRangeException(); }
    public GDuration gDurationValue()
        { throw new XmlValueOutOfRangeException(); }
    public QName qNameValue()
        { throw new XmlValueOutOfRangeException(); }
    public List listValue()
        { throw new XmlValueOutOfRangeException(); }
    public List xlistValue()
        { throw new XmlValueOutOfRangeException(); }
    public Object objectValue()
        { return java_value(this); }

    // set this value
    public final void set(boolean v)
        { synchronized (monitor()) { set_prepare(); set_boolean(v); set_commit(); } }
    public final void set(byte v)
        { synchronized (monitor()) { set_prepare(); set_byte(v); set_commit(); } }
    public final void set(short v)
        { synchronized (monitor()) { set_prepare(); set_short(v); set_commit(); } }
    public final void set(int v)
        { synchronized (monitor()) { set_prepare(); set_int(v); set_commit(); } }
    public final void set(long v)
        { synchronized (monitor()) { set_prepare(); set_long(v); set_commit(); } }
    public final void set(float v)
        { synchronized (monitor()) { set_prepare(); set_float(v); set_commit(); } }
    public final void set(double v)
        { synchronized (monitor()) { set_prepare(); set_double(v); set_commit(); } }
    public final void set(byte[] obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_ByteArray(obj); set_commit(); } } }
    public final void set(StringEnumAbstractBase obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_enum(obj); set_commit(); } } }
    public final void set(BigInteger obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_BigInteger(obj); set_commit(); } } }
    public final void set(BigDecimal obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_BigDecimal(obj); set_commit(); } } }
    public final void set(Calendar obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_Calendar(obj); set_commit(); } } }
    public final void set(Date obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_Date(obj); set_commit(); } } }
    public final void set(GDateSpecification obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_GDate(obj); set_commit(); } } }
    public final void set(GDurationSpecification obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_GDuration(obj); set_commit(); } } }
    public final void set(QName obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_QName(obj); set_commit(); } } }
    public final void set(List obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_list(obj); set_commit(); } } }
    public final void set(String obj)
        { if (obj == null) setNil(); else { synchronized (monitor()) { set_prepare(); set_String(obj); /* strings are special, so set_String does its own commit.*/ } } }

    public void objectSet(Object o)
    {
        if (o == null)
        {
            setNil();
            return;
        }

        if (o instanceof XmlObject)
            set( (XmlObject) o );
        else if (o instanceof String)
            set( (String) o );
        else if (o instanceof StringEnumAbstractBase)
            set( (StringEnumAbstractBase) o );
        else if (o instanceof BigInteger)
            set( (BigInteger) o );
        else if (o instanceof BigDecimal)
            set( (BigDecimal) o );
        else if (o instanceof Byte)
            set( ((Byte)o).byteValue() );
        else if (o instanceof Short)
            set( ((Short)o).shortValue() );
        else if (o instanceof Integer)
            set( ((Integer)o).intValue() );
        else if (o instanceof Long)
            set( ((Long)o).longValue() );
        else if (o instanceof Boolean)
            set( ((Boolean)o).booleanValue() );
        else if (o instanceof Float)
            set( ((Float)o).floatValue() );
        else if (o instanceof Double)
            set( ((Double)o).doubleValue() );
        else if (o instanceof Calendar)
            set( ((Calendar)o) );
        else if (o instanceof Date)
            set( (Date) o );
        else if (o instanceof GDateSpecification)
            set( (GDateSpecification) o );
        else if (o instanceof GDurationSpecification)
            set( (GDurationSpecification) o );
        else if (o instanceof QName)
            set( (QName) o );
        else if (o instanceof List)
            set( (List) o );
        else if (o instanceof byte[])
            set( (byte[]) o );
        else
        {
            throw
                new XmlValueOutOfRangeException(
                    "Can't set union object of class : " +
                        o.getClass().getName() );
        }
    }

    public final void set_newValue(XmlObject obj)
    {
        if (obj == null || obj.isNil())
        {
            setNil();
            return;
        }

        primitive:
        if (obj instanceof XmlAnySimpleType)
        {
            XmlAnySimpleType v = (XmlAnySimpleType)obj;
            SchemaType instanceType = ((SimpleValue)v).instanceType();
            assert(instanceType != null) : "Nil case should have been handled already";

            // handle lists
            if (instanceType.getSimpleVariety() == SchemaType.LIST)
            {
                synchronized (monitor())
                {
                    set_prepare();
                    set_list(((SimpleValue)v).xgetListValue());
                    set_commit();
                    return;
                }
            }

            // handle atomic types
            synchronized (monitor())
            {
                assert(instanceType.getSimpleVariety() == SchemaType.ATOMIC);
                switch (instanceType.getPrimitiveType().getBuiltinTypeCode())
                {
                    default:
                        assert(false) : "encountered nonprimitive type.";
                    // case SchemaType.BTC_ANY_SIMPLE:  This is handled below...
                    // but we eventually want to handle it with a treecopy, so
                    // eventually we should break here.
                        break primitive;

                    case SchemaType.BTC_BOOLEAN:
                    {
                        boolean bool = ((SimpleValue)v).getBooleanValue();
                        set_prepare();
                        set_boolean(bool);
                        break;
                    }
                    case SchemaType.BTC_BASE_64_BINARY:
                    {
                        byte[] byteArr = ((SimpleValue)v).getByteArrayValue();
                        set_prepare();
                        set_b64(byteArr);
                        break;
                    }
                    case SchemaType.BTC_HEX_BINARY:
                    {
                        byte[] byteArr = ((SimpleValue)v).getByteArrayValue();
                        set_prepare();
                        set_hex(byteArr);
                        break;
                    }
                    case SchemaType.BTC_QNAME:
                    {
                        QName name = ((SimpleValue)v).getQNameValue();
                        set_prepare();
                        set_QName(name);
                        break;
                    }
                    case SchemaType.BTC_FLOAT:
                    {
                        float f = ((SimpleValue)v).getFloatValue();
                        set_prepare();
                        set_float(f);
                        break;
                    }
                    case SchemaType.BTC_DOUBLE:
                    {
                        double d = ((SimpleValue)v).getDoubleValue();
                        set_prepare();
                        set_double(d);
                        break;
                    }
                    case SchemaType.BTC_DECIMAL:
                    {
                        switch (instanceType.getDecimalSize())
                        {
                            case SchemaType.SIZE_BYTE:
                            {
                                byte b = ((SimpleValue)v).getByteValue();
                                set_prepare();
                                set_byte(b);
                                break;
                            }
                            case SchemaType.SIZE_SHORT:
                            {
                                short s = ((SimpleValue)v).getShortValue();
                                set_prepare();
                                set_short(s);
                                break;
                            }
                            case SchemaType.SIZE_INT:
                            {
                                int i = ((SimpleValue)v).getIntValue();
                                set_prepare();
                                set_int(i);
                                break;
                            }
                            case SchemaType.SIZE_LONG:
                            {
                                long l = ((SimpleValue)v).getLongValue();
                                set_prepare();
                                set_long(l);
                                break;
                            }
                            case SchemaType.SIZE_BIG_INTEGER:
                            {
                                BigInteger bi = ((SimpleValue)v).getBigIntegerValue();
                                set_prepare();
                                set_BigInteger(bi);
                                break;
                            }
                            default:
                            {
                                assert(false) : "invalid numeric bit count";
                                // fallthrough
                            }
                            case SchemaType.SIZE_BIG_DECIMAL:
                            {
                                BigDecimal bd = ((SimpleValue)v).getBigDecimalValue();
                                set_prepare();
                                set_BigDecimal(bd);
                                break;
                            }
                        }
                        break;
                    }
                    case SchemaType.BTC_ANY_URI:
                    {
                        String uri = v.getStringValue();
                        set_prepare();
                        set_text(uri);
                        break;
                    }
                    case SchemaType.BTC_NOTATION:
                    {
                        String s = v.getStringValue();
                        set_prepare();
                        set_notation(s);
                        break;
                    }
                    case SchemaType.BTC_DURATION:
                    {
                        GDuration gd = ((SimpleValue)v).getGDurationValue();
                        set_prepare();
                        set_GDuration(gd);
                        break;
                    }
                    case SchemaType.BTC_DATE_TIME:
                    case SchemaType.BTC_TIME:
                    case SchemaType.BTC_DATE:
                    case SchemaType.BTC_G_YEAR_MONTH:
                    case SchemaType.BTC_G_YEAR:
                    case SchemaType.BTC_G_MONTH_DAY:
                    case SchemaType.BTC_G_DAY:
                    case SchemaType.BTC_G_MONTH:
                    {
                        GDate gd = ((SimpleValue)v).getGDateValue();
                        set_prepare();
                        set_GDate(gd);
                        break;
                    }
                    case SchemaType.BTC_STRING:
                    {
                        String s = v.getStringValue();
                        set_prepare();
                        set_String(s);
                        break;
                    }
                    case SchemaType.BTC_ANY_SIMPLE:
                        {
                            boolean pushed = false;
                            if (!v.isImmutable())
                            {
                                pushed = true;
                                NamespaceContext.push(new NamespaceContext(v));
                            }
                            try
                            {
                                set_prepare();
                                set_xmlanysimple(v);
                            }
                            finally
                            {
                                if (pushed)
                                    NamespaceContext.pop();
                            }
                            break;
                        }
                }
                set_commit();
                return; // primitive node tree copy handled.
            }
        }

        throw new IllegalStateException("Complex type unexpected");
    }

    private TypeStoreUser setterHelper ( XmlObjectBase src )
    {
        check_orphaned();

        src.check_orphaned();

        return
            get_store().copy_contents_from( src.get_store() ).
                get_store().change_type( src.schemaType() );
    }

    public final XmlObject set(XmlObject src)
    {
        if (isImmutable())
            throw new IllegalStateException("Cannot set the value of an immutable XmlObject");

        XmlObjectBase obj = underlying(src);

        TypeStoreUser newObj = this;

        if (obj == null)
        {
            setNil();
            return this;
        }

        if (obj.isImmutable())
            set(obj.stringValue());
        else
        {
            boolean acquired = false;
            try
            {
                if (monitor() == obj.monitor())
                {
                    synchronized (monitor())
                    {
                        newObj = setterHelper( obj );
                    }
                }
                else
                {
                    // about to grab two locks: don't deadlock ourselves
                    GlobalLock.acquire();
                    acquired = true;

                    synchronized (monitor())
                    {
                        synchronized (obj.monitor())
                        {
                            GlobalLock.release();
                            acquired = false;

                            newObj = setterHelper( obj );
                        }
                    }
                }
            }
            catch (InterruptedException e)
            {
                throw new XmlRuntimeException(e);
            }
            finally
            {
                if (acquired)
                    GlobalLock.release();
            }
        }

        return (XmlObject) newObj;
    }

    protected void set_list(List list)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_boolean(boolean v)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_byte(byte v)
        { set_int((int) v); }
    protected void set_short(short v)
        { set_int((int) v); }
    protected void set_int(int v)
        { set_long((long) v); }
    protected void set_long(long v)
        { set_BigInteger(BigInteger.valueOf(v)); }
    protected void set_char(char v)
        { set_String(Character.toString(v)); }
    protected void set_float(float v)
        { set_BigDecimal(new BigDecimal(v)); }
    protected void set_double(double v)
        { set_BigDecimal(new BigDecimal(v)); }

    protected void set_enum(StringEnumAbstractBase e)
        { throw new XmlValueOutOfRangeException(); }

    protected void set_ByteArray(byte[] b)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_b64(byte[] b)
        { set_ByteArray(b); }
    protected void set_hex(byte[] b)
        { set_ByteArray(b); }
    protected void set_BigInteger(BigInteger v)
        { set(new BigDecimal(v)); }
    protected void set_BigDecimal(BigDecimal v)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_Date(Date v)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_Calendar(Calendar v)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_GDate(GDateSpecification v)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_GDuration(GDurationSpecification v)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_ComplexXml(XmlObject v)
        { throw new XmlValueOutOfRangeException(); }
    protected void set_QName(QName v)
        { throw new XmlValueOutOfRangeException(); }

    protected void set_notation(String v)
        { throw new XmlValueOutOfRangeException(); }

    protected void set_xmlanysimple(XmlAnySimpleType v)
        { set_String(v.getStringValue()); }

    private final boolean comparable_value_spaces(SchemaType t1, SchemaType t2)
    {
        assert(t1.getSimpleVariety() != SchemaType.UNION && t2.getSimpleVariety() != SchemaType.UNION);

        if (!t1.isSimpleType() && !t2.isSimpleType())
            return (t1.getContentType() == t2.getContentType());

        if (!t1.isSimpleType() || !t2.isSimpleType())
            return false;

        if (t1.getSimpleVariety() == SchemaType.LIST && t2.getSimpleVariety() == SchemaType.LIST)
            return true;

        if (t1.getSimpleVariety() == SchemaType.LIST || t2.getSimpleVariety() == SchemaType.LIST)
            return false;

        return (t1.getPrimitiveType().equals(t2.getPrimitiveType()));
    }

    private final boolean valueEqualsImpl(XmlObject xmlobj)
    {
        check_dated();

        SchemaType typethis = instanceType();
        SchemaType typeother = ((SimpleValue)xmlobj).instanceType();

        if (typethis == null && typeother == null) // detects nil
            return true;

        if (typethis == null || typeother == null)
            return false;

        if (!comparable_value_spaces(typethis, typeother))
            return false;

        if (xmlobj.schemaType().getSimpleVariety() == SchemaType.UNION)
            return (underlying(xmlobj)).equal_to(this);

        return equal_to(xmlobj);
    }

    public final boolean valueEquals(XmlObject xmlobj)
    {
        boolean acquired = false;
        try
        {
            if (isImmutable())
            {
                if (xmlobj.isImmutable())
                {
                    return valueEqualsImpl(xmlobj);
                }
                else
                {
                    synchronized (xmlobj.monitor())
                    {
                        return valueEqualsImpl(xmlobj);
                    }
                }
            }
            else
            {
                if (xmlobj.isImmutable() || monitor() == xmlobj.monitor())
                {
                    synchronized (monitor())
                    {
                        return valueEqualsImpl(xmlobj);
                    }
                }
                else
                {
                    GlobalLock.acquire();
                    acquired = true;
                    synchronized (monitor())
                    {
                        synchronized (xmlobj.monitor())
                        {
                            GlobalLock.release();
                            acquired = false;
                            return valueEqualsImpl(xmlobj);
                        }
                    }
                }
            }

        }
        catch (InterruptedException e)
        {
            throw new XmlRuntimeException(e);
        }
        finally
        {
            if (acquired)
                GlobalLock.release();
        }
    }

    /**
     * Implements Comparable. This compareTo is inconsistent with
     * equals unless isImmutable() is true.
     */
    public final int compareTo(Object obj)
    {
        int result = compareValue((XmlObject)obj); // can throw ClassCast
        if (result == 2)
            throw new ClassCastException();
        return result;
    }

    /**
     * Allowed to return 2 for incomparable.
     */
    private final int compareValueImpl(XmlObject xmlobj)
    {
        SchemaType type1, type2;

        try
        {
            type1 = instanceType();
            type2 = ((SimpleValue)xmlobj).instanceType();
        }
        catch (XmlValueOutOfRangeException e)
        {
            return 2;
        }

        if (type1 == null && type2 == null)
            return 0;
        if (type1 == null || type2 == null)
            return 2;

        if (!type1.isSimpleType() || type1.isURType())
            return 2;

        if (!type2.isSimpleType() || type2.isURType())
            return 2;

        type1 = type1.getPrimitiveType();
        type2 = type2.getPrimitiveType();

        // Different value spaces: different
        if (type1.getBuiltinTypeCode() != type2.getBuiltinTypeCode())
            return 2;

        // now we'll depend on our impl class to do the work
        return compare_to(xmlobj);
    }

    public final int compareValue(XmlObject xmlobj)
    {
        if (xmlobj == null)
            return 2;

        boolean acquired = false;
        try
        {
            if (isImmutable())
            {
                if (xmlobj.isImmutable())
                {
                    return compareValueImpl(xmlobj);
                }
                else
                {
                    synchronized (xmlobj.monitor())
                    {
                        return compareValueImpl(xmlobj);
                    }
                }
            }
            else
            {
                if (xmlobj.isImmutable() || monitor() == xmlobj.monitor())
                {
                    synchronized (monitor())
                    {
                        return compareValueImpl(xmlobj);
                    }
                }
                else
                {
                    GlobalLock.acquire();
                    acquired = true;
                    synchronized (monitor())
                    {
                        synchronized (xmlobj.monitor())
                        {
                            GlobalLock.release();
                            acquired = false;
                            return compareValueImpl(xmlobj);
                        }
                    }
                }
            }

        }
        catch (InterruptedException e)
        {
            throw new XmlRuntimeException(e);
        }
        finally
        {
            if (acquired)
                GlobalLock.release();
        }
    }
    /**
     * This implementation of compare_to is allowed to do two
     * unusual things:
     * (1) it can assume that the xmlobj passed has a primitive
     *     type underlying the instance type that matches the
     *     current instance, and that neither is nil.
     * (2) it is allowed to return 2 for "incomparable";
     *     it should not throw an exception.
     */
    protected int compare_to(XmlObject xmlobj)
    {
        if (equal_to(xmlobj))
            return 0;
        return 2;
    }

    protected abstract boolean equal_to(XmlObject xmlobj);

    protected abstract int value_hash_code();

    public int valueHashCode()
    {
        synchronized (monitor())
        {
            return value_hash_code();
        }
    }


    public boolean isInstanceOf(SchemaType type)
    {
        SchemaType myType;

        if (type.getSimpleVariety() != SchemaType.UNION)
        {
            for (myType = instanceType(); myType != null; myType = myType.getBaseType())
                if (type == myType)
                    return true;
            return false;
        }
        else
        {
            Set ctypes = new HashSet(Arrays.asList(type.getUnionConstituentTypes()));
            for (myType = instanceType(); myType != null; myType = myType.getBaseType())
                if (ctypes.contains(myType))
                    return true;
            return false;
        }
    }

    public final boolean equals(Object obj)
    {
        if (!isImmutable())
            return super.equals(obj);

        if (!(obj instanceof XmlObject))
            return false;

        XmlObject xmlobj = (XmlObject)obj;
        if (!xmlobj.isImmutable())
            return false;

        return valueEquals(xmlobj);
    }

    public final int hashCode()
    {
        if (!isImmutable())
            return super.hashCode();

        synchronized (monitor())
        {
            if (isNil())
                return 0;

            return value_hash_code();
        }
    }

    /**
     * This method can writeReplace either an unwrapped XmlObjectBase
     * or an XBean proxy.  A "true" argument means unwrapped.
     *
     * The serialization strategy for XmlObjects is this:
     *
     * (1) Only the root XmlObject for a document actually gets
     *     fully serialized; it is serialized as a SerializedRootObject,
     *     which simply saves itself as XML text.
     *
     * (2) Interior XmlObjects get serialized as a reference to the
     *     root XmlObject for their document, plus an integer which
     *     indicates the position of the XmlObject within the owner
     *     document. This pair is stored as a SerializedInteriorObject.
     *
     * Both objects can be maked as wrapped or unwrapped. If wrapped,
     * then the proxy is returned when deserializing; if unwrapped, then
     * the proxy is stripped when deserializing.
     */
    public Object writeReplace()
    {
        synchronized (monitor())
        {
            if (isRootXmlObject())
                return new SerializedRootObject(this);

            return new SerializedInteriorObject(this, getRootXmlObject());
        }
    }

    /**
     * True if the object is at the root of the document.
     */
    private boolean isRootXmlObject()
    {
        XmlCursor cur = newCursor();
        if (cur == null)
            return false;

        boolean result = !cur.toParent();
        cur.dispose();
        return result;
    }

    /**
     * Gets the root XmlObject for this document.
     */
    private XmlObject getRootXmlObject()
    {
        XmlCursor cur = newCursor();
        if (cur == null)
            return this;
        cur.toStartDoc();
        XmlObject result = cur.getObject();
        cur.dispose();
        return result;
    }

    /**
     * Serializable rewrite object that knows how to resolve
     * to an XmlObjectBase or a proxy for the root object of
     * a document.
     */
    private static class SerializedRootObject implements Serializable
    {
        private static final long serialVersionUID = 1;

        transient Class _xbeanClass;
        transient XmlObject _impl;

        private SerializedRootObject()
        {
        }

        private SerializedRootObject(XmlObject impl)
        {
            _xbeanClass = impl.schemaType().getJavaClass();
            _impl = impl;
        }

        private void writeObject(ObjectOutputStream out) throws IOException
        {
            out.writeObject(_xbeanClass);
            // the first short is written out for backwards compatibility
            // it will always be zero for objects written with
            // this code, but it used to be the first 2 bytes of the
            // writeUTF() method
            out.writeShort((short)0);
            out.writeShort(MAJOR_VERSION_NUMBER);
            out.writeShort(MINOR_VERSION_NUMBER);
            // CR122401 - need to use writeObject instead of writeUTF
            // for xmlText as writeUTF has a length limitation of
            // 65535 bytes
            String xmlText = _impl.xmlText();
            out.writeObject(xmlText);
            out.writeBoolean(false);
        }

        private void readObject(ObjectInputStream in) throws IOException
        {
            try
            {
                // read class object first - this is
                // first just for historical reasons - really
                // it would be better to have the version numbers
                // first
                _xbeanClass = (Class)in.readObject();

                int utfBytes = in.readUnsignedShort();

                // determine version numbers
                // if utfBytes is non-zero then we default to 0.0
                // otherwise expect major and minor version numbers
                // to be next entries in stream
                int majorVersionNum = 0;
                int minorVersionNum = 0;
                if (utfBytes == 0)
                {
                    majorVersionNum = in.readUnsignedShort();
                    minorVersionNum = in.readUnsignedShort();
                }

                String xmlText = null;
                switch (majorVersionNum)
                {
                    case 0: // original, unnumbered version
                            // minorVersionNum is always zero
                        xmlText = readObjectV0(in, utfBytes);
                        in.readBoolean(); // ignored
                        break;

                    case 1:
                        switch (minorVersionNum)
                        {
                            case 1:
                                xmlText = (String)in.readObject();
                                in.readBoolean(); // ignored
                                break;

                            default:
                                throw new IOException("Deserialization error: " +
                                        "version number " + majorVersionNum + "." +
                                        minorVersionNum + " not supported.");
                        }
                        break;

                    default:
                        throw new IOException("Deserialization error: " +
                                "version number " + majorVersionNum + "." +
                                minorVersionNum + " not supported.");
                }

                XmlOptions opts = new XmlOptions().setDocumentType(XmlBeans.typeForClass(_xbeanClass));
                _impl = XmlBeans.getContextTypeLoader().parse(xmlText, null, opts);
            }
            catch (Exception e)
            {
                throw (IOException)(new IOException(e.getMessage()).initCause(e));
            }
        }

        // this method is for reading the UTF-8 String that used to be
        // written out for a serialized XmlObject according to the
        // original format before this fix, i.e. it expects it
        // to have been written using the following algorithm:
        //
        // writeObject(Class object)
        // writeUTF(xmlText of object as String)
        // writeBoolean()
        //
        // this method is passed the original input stream positioned as though
        // it had just read the class object plus the next 2 bytes. Those 2
        // bytes are interpreted as an unsigned short saying how many more
        // bytes there are representing the bytes of the UTF-8-formatted String;
        // this value is passed in as the argument utfBytes
        private String readObjectV0(ObjectInputStream in, int utfBytes)
                throws IOException
        {
            // allow an extra 2 bytes up front for the unsigned short
            byte[] bArray = new byte[utfBytes+2];

            // for format of these first 2 bytes see
            // Java API docs - DataOutputStream.writeShort()
            bArray[0] = (byte)( 0xff & (utfBytes >> 8) );
            bArray[1] = (byte)( 0xff & utfBytes );

            // read the next numBytes bytes from the input stream
            // into the byte array starting at offset 2; this may
            // take multiple calls to read()
            int totalBytesRead = 0;
            int numRead;
            while (totalBytesRead < utfBytes)
            {
                numRead =
                    in.read(bArray, 2+totalBytesRead, utfBytes-totalBytesRead);
                if (numRead == -1) // reached end of stream
                    break;

                totalBytesRead += numRead;
            }

            if (totalBytesRead != utfBytes)
            {
                throw new IOException("Error reading backwards compatible " +
                        "XmlObject: number of bytes read (" + totalBytesRead +
                        ") != number expected (" + utfBytes + ")" );
            }

            // now set up a DataInputStream to read those
            // bytes as a UTF-8 String i.e. as though we'd never
            // read the first 2 bytes from the original stream
            DataInputStream dis = null;
            String str = null;
            try
            {
                dis = new DataInputStream(new ByteArrayInputStream(bArray));
                str = dis.readUTF();
            }
            finally
            {
                if (dis != null)
                    dis.close();
            }

            return str;
        }

        private Object readResolve() throws ObjectStreamException
        {
            return _impl;
        }
    }

    /**
     * Serializable rewrite object that knows how to resolve
     * to an XmlObjectBase or a proxy for an interior position
     * within a document.
     */
    private static class SerializedInteriorObject implements Serializable
    {
        private static final long serialVersionUID = 1;

        transient XmlObject _impl;
        transient XmlObject _root;

        private SerializedInteriorObject()
        {
        }

        private SerializedInteriorObject(XmlObject impl, XmlObject root)
        {
            _impl = impl;
            _root = root;
        }

        private void writeObject(ObjectOutputStream out) throws IOException
        {
            out.writeObject(_root);
            out.writeBoolean(false);
            out.writeInt(distanceToRoot());
        }

        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
        {
            _root = (XmlObject)in.readObject();
            in.readBoolean();
            _impl = objectAtDistance(in.readInt());
        }

        private Object readResolve() throws ObjectStreamException
        {
            return _impl;
        }

        private int distanceToRoot()
        {
            XmlCursor cur = _impl.newCursor();
            int count = 0;
            while (!cur.toPrevToken().isNone())
            {
                if (!cur.currentTokenType().isNamespace())
                {
                    count += 1;
                    // System.out.println("Count: " + count + " " + cur.currentTokenType().toString() + " " + QName.pretty(cur.getName()));
                }
            }
            cur.dispose();
            return count;
        }

        private XmlObject objectAtDistance(int count)
        {
            XmlCursor cur = _root.newCursor();
            while (count > 0)
            {
                cur.toNextToken();
                if (!cur.currentTokenType().isNamespace())
                {
                    count -= 1;
                    // System.out.println("Count: " + count + " " + cur.currentTokenType().toString() + " " + QName.pretty(cur.getName()));
                }
            }
            XmlObject result = cur.getObject();
            cur.dispose();
            return result;
        }
    }

    protected static Object java_value(XmlObject obj)
    {
        if (obj.isNil())
            return null;

        if (!(obj instanceof XmlAnySimpleType))
            return obj;

        SchemaType instanceType = ((SimpleValue)obj).instanceType();
        assert(instanceType != null) : "Nil case should have been handled above";

        // handle lists
        if (instanceType.getSimpleVariety() == SchemaType.LIST)
            return ((SimpleValue)obj).getListValue();

        SimpleValue base = (SimpleValue)obj;

        switch (instanceType.getPrimitiveType().getBuiltinTypeCode())
        {
            case SchemaType.BTC_BOOLEAN:
                return base.getBooleanValue() ? Boolean.TRUE : Boolean.FALSE;

            case SchemaType.BTC_BASE_64_BINARY:
            case SchemaType.BTC_HEX_BINARY:
                return base.getByteArrayValue();

            case SchemaType.BTC_QNAME:
                return base.getQNameValue();

            case SchemaType.BTC_FLOAT:
                return new Float(base.getFloatValue());

            case SchemaType.BTC_DOUBLE:
                return new Double(base.getDoubleValue());

            case SchemaType.BTC_DECIMAL:
            {
                switch (instanceType.getDecimalSize())
                {
                    case SchemaType.SIZE_BYTE:
                        return new Byte(base.getByteValue());

                    case SchemaType.SIZE_SHORT:
                        return new Short(base.getShortValue());

                    case SchemaType.SIZE_INT:
                        return new Integer(base.getIntValue());

                    case SchemaType.SIZE_LONG:
                        return new Long(base.getLongValue());

                    case SchemaType.SIZE_BIG_INTEGER:
                        return base.getBigIntegerValue();

                    default:
                        assert(false) : "invalid numeric bit count";
                        // fallthrough
                    case SchemaType.SIZE_BIG_DECIMAL:
                        return base.getBigDecimalValue();
                }
            }
            case SchemaType.BTC_ANY_URI:
                return base.getStringValue();

            case SchemaType.BTC_DURATION:
                return base.getGDurationValue();

            case SchemaType.BTC_DATE_TIME:
            case SchemaType.BTC_TIME:
            case SchemaType.BTC_DATE:
            case SchemaType.BTC_G_YEAR_MONTH:
            case SchemaType.BTC_G_YEAR:
            case SchemaType.BTC_G_MONTH_DAY:
            case SchemaType.BTC_G_DAY:
            case SchemaType.BTC_G_MONTH:
                return base.getCalendarValue();

            default:
                assert(false) : "encountered nonprimitive type.";
                // fallthrough

            // NB: for string enums we just do java.lang.String
            // when in the context of unions. It's easier on users.
            case SchemaType.BTC_NOTATION:
            case SchemaType.BTC_STRING:
            case SchemaType.BTC_ANY_SIMPLE:
                // return base.getStringValue();
            return base.getStringValue();
        }
    }

    /**
     * Called by code generated code to get the default attribute value
     * for a given attribute name, or null if none.
     */
    protected XmlAnySimpleType get_default_attribute_value(QName name)
    {
        SchemaType sType = schemaType();
        SchemaAttributeModel aModel = sType.getAttributeModel();
        if (aModel == null)
            return null;
        SchemaLocalAttribute sAttr = aModel.getAttribute(name);
        if (sAttr == null)
            return null;
        return sAttr.getDefaultValue();
    }
}
