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

package org.apache.xmlbeans.impl.values;

import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.*;
import org.apache.xmlbeans.impl.schema.SchemaTypeImpl;
import org.apache.xmlbeans.impl.schema.SchemaTypeVisitorImpl;
import org.apache.xmlbeans.impl.validator.Validator;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.function.IntFunction;

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 static final short KIND_SETTERHELPER_SINGLETON = 1;
    public static final short KIND_SETTERHELPER_ARRAYITEM = 2;

    public final Object monitor() {
        if (has_store()) {
            return get_store().get_locale();
        }
        return this;
    }

    private static XmlObjectBase underlying(XmlObject obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof XmlObjectBase) {
            return (XmlObjectBase) obj;
        }
        while (obj instanceof DelegateXmlObject) {
            obj = ((DelegateXmlObject) obj).underlyingXmlObject();
        }
        if (obj instanceof XmlObjectBase) {
            return (XmlObjectBase) obj;
        }
        throw new IllegalStateException("Non-native implementations of XmlObject should extend FilterXmlObject or implement DelegateXmlObject");
    }

    public final XmlObject copy() {
        if (preCheck()) {
            return _copy();
        } else {
            synchronized (monitor()) {
                return _copy();
            }
        }
    }

    public final XmlObject copy(XmlOptions options) {
        if (preCheck()) {
            return _copy(options);
        } else {
            synchronized (monitor()) {
                return _copy(options);
            }
        }
    }

    private boolean preCheck() {
//        if ( isImmutable() )
//            return true;
        if (has_store()) {
            return get_store().get_locale().noSync();
        }
        return false;
    }

    /**
     * Same as copy() but unsynchronized.
     * Warning: Using this method in mutithreaded environment can cause invalid states.
     */
    public final XmlObject _copy() {
        return _copy(null);
    }

    /**
     * Same as copy() but unsynchronized.
     * If Locale.COPY_USE_NEW_LOCALE is set in the options, a new locale will be created for the copy.
     * Warning: Using this method in mutithreaded environment can cause invalid states.
     */
    public final XmlObject _copy(XmlOptions xmlOptions) {
        // immutable objects don't get copied. They're immutable
        if (isImmutable()) {
            return this;
        }

        check_orphaned();

        SchemaTypeLoader stl = get_store().get_schematypeloader();

        return (XmlObject) get_store().copy(stl, schemaType(), xmlOptions);
    }

    public XmlDocumentProperties documentProperties() {
        XmlCursor cur = newCursorForce();
        try {
            return cur.documentProperties();
        } 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 getDomNode() {
        XmlCursor cur = newCursorForce();
        try {
            return cur.getDomNode();
        } 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 void dump() {
        XmlCursor cur = newCursorForce();
        try {
            cur.dump();
        } finally {
            cur.dispose();
        }
    }

    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.setSaveInner();
        return innerOptions;
    }

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

        check_orphaned();

        // Note that new_cursor does not really need sync ....

        XmlLocale l = getXmlLocale();

        if (l.noSync()) {
            l.enter();
            try {
                return get_store().new_cursor();
            } finally {
                l.exit();
            }
        } else {
            synchronized (l) {
                l.enter();
                try {
                    return get_store().new_cursor();
                } finally {
                    l.exit();
                }
            }
        }

    }

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

        public void invalid(String code, Object[] args) {
            throw new XmlValueOutOfRangeException(code, args);
        }
    }

    /**
     * Used to supply validation context for the validate_value methods
     */
    private static final class ImmutableValueValidationContext implements ValidationContext {
        private final XmlObject _loc;
        private final Collection<XmlError> _coll;

        ImmutableValueValidationContext(Collection<XmlError> coll, XmlObject loc) {
            _coll = coll;
            _loc = loc;
        }

        public void invalid(String message) {
            _coll.add(XmlError.forObject(message, _loc));
        }

        public void invalid(String code, Object[] args) {
            _coll.add(XmlError.forObject(code, args, _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<XmlError> errorListener = options == null ? null : options.getErrorListener();
        XmlErrorWatcher watcher = new XmlErrorWatcher(errorListener);
        if (!(schemaType().isSimpleType() || options != null &&
                                             options.isValidateTextOnly())) {
            // cannot have any required attributes or elements
            SchemaProperty[] properties = schemaType().getProperties();
            for (SchemaProperty property : properties) {
                if (property.getMinOccurs().signum() > 0) {
                    // KHK: error code?
                    if (property.isAttribute()) {
                        watcher.add(XmlError.forObject(XmlErrorCodes.ELEM_COMPLEX_TYPE_LOCALLY_VALID$MISSING_REQUIRED_ATTRIBUTE, new Object[]{QNameHelper.pretty(property.getName()),}, this));
                    } else {
                        watcher.add(XmlError.forObject(XmlErrorCodes.ELEM_COMPLEX_TYPE_LOCALLY_VALID$MISSING_ELEMENT, new Object[]{property.getMinOccurs(), QNameHelper.pretty(property.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) {
    }

    private static XmlObject[] _typedArray(XmlObject[] input) {
        if (input.length == 0) {
            return input;
        }
        SchemaType commonType = input[0].schemaType();
        if (commonType.equals(XmlObject.type) || commonType.isNoType()) {
            return input;
        }
        for (int i = 1; i < input.length; i++) {
            if (input[i].schemaType().isNoType()) {
                return input;
            }
            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 = EMPTY_RESULT;
            } else {
                selections = new XmlObject[c.getSelectionCount()];

                for (int i = 0; c.toNextSelection(); i++) {
                    if ((selections[i] = c.getObject()) == null) {
                        if (!c.toParent() || (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");
            }
            return _typedArray(typeStore.exec_query(queryExpr, options));
        }
    }

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

    public XmlObject substitute(QName name, SchemaType type) {
        if (name == null) {
            throw new IllegalArgumentException("Invalid name (null)");
        }

        if (type == null) {
            throw new IllegalArgumentException("Invalid type (null)");
        }

        if ((_flags & FLAG_STORE) == 0) {
            throw
                new IllegalStateException(
                    "XML Value Objects cannot be used with substitution");
        }

        synchronized (monitor()) {
            check_orphaned();
            return (XmlObject) get_store().substitute(name, 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 &= ~FLAGS_ELEMENT;
        _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);
    }

    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 &&
                (_flags & FLAG_VALIDATE_ON_SET) != 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) {
                get_store().invalidate_text();
                _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.
     * <p>
     * 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.
     * <p>
     * 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;
    }

    public final XmlLocale getXmlLocale() {
        return get_store().get_locale();
    }

    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.
     * <p>
     * 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.
     * <p>
     * Note that we will ignore the xsiType if it turns out to be invalid.
     * <p>
     * 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.
     * <p>
     * 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.
     * <p>
     * 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).
     * <p>
     * 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.)
     * <p>
     * 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;
            if ((_flags & FLAG_SETTINGDEFAULT) == 0) {
                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 XmlValueNotSupportedException("Complex content");
    }

    /**
     * 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 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.setStringValue(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().
     * <p>
     * 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.
     * <p>
     * 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 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 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.
     * <p>
     * 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 &&
                        (_flags & FLAG_VALIDATE_ON_SET) != 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 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 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 getFloatValue() {
        BigDecimal bd = getBigDecimalValue();
        return bd == null ? 0.0f : bd.floatValue();
    }

    public double getDoubleValue() {
        BigDecimal bd = getBigDecimalValue();
        return bd == null ? 0.0 : bd.doubleValue();
    }

    public BigDecimal getBigDecimalValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "numeric"});
    }

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

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

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

    public int getIntValue() {
        long l = getLongValue();
        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 getLongValue() {
        BigInteger b = getBigIntegerValue();
        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 XmlOptions buildInnerPrettyOptions() {
        XmlOptions options = new XmlOptions();
        options.setSaveInner();
        options.setSavePrettyPrint();
        options.setSaveAggressiveNamespaces();
        options.setUseDefaultNamespace();

        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 getEnumValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "enum"});
    }

    // various
    public String getStringValue() {
        if (isImmutable()) {
            if ((_flags & FLAG_NIL) != 0) {
                return null;
            }
            return compute_text(null);
        }
        // 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 byte[] getByteArrayValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "byte[]"});
    }

    public boolean getBooleanValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "boolean"});
    }

    public GDate getGDateValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "Date"});
    }

    public Date getDateValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "Date"});
    }

    public Calendar getCalendarValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "Calendar"});
    }

    public GDuration getGDurationValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "Duration"});
    }

    public QName getQNameValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "QName"});
    }

    public List getListValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "List"});
    }

    public List xgetListValue() {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_S2J,
            new Object[]{getPrimitiveTypeName(), "List"});
    }

    public Object getObjectValue() {
        return java_value(this);
    }

    // set this value
    public final void setBooleanValue(boolean v) {
        synchronized (monitor()) {
            set_prepare();
            set_boolean(v);
            set_commit();
        }
    }

    public final void setByteValue(byte v) {
        synchronized (monitor()) {
            set_prepare();
            set_byte(v);
            set_commit();
        }
    }

    public final void setShortValue(short v) {
        synchronized (monitor()) {
            set_prepare();
            set_short(v);
            set_commit();
        }
    }

    public final void setIntValue(int v) {
        synchronized (monitor()) {
            set_prepare();
            set_int(v);
            set_commit();
        }
    }

    public final void setLongValue(long v) {
        synchronized (monitor()) {
            set_prepare();
            set_long(v);
            set_commit();
        }
    }

    public final void setFloatValue(float v) {
        synchronized (monitor()) {
            set_prepare();
            set_float(v);
            set_commit();
        }
    }

    public final void setDoubleValue(double v) {
        synchronized (monitor()) {
            set_prepare();
            set_double(v);
            set_commit();
        }
    }

    public final void setByteArrayValue(byte[] obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_ByteArray(obj);
                set_commit();
            }
        }
    }

    public final void setEnumValue(StringEnumAbstractBase obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_enum(obj);
                set_commit();
            }
        }
    }

    public final void setBigIntegerValue(BigInteger obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_BigInteger(obj);
                set_commit();
            }
        }
    }

    public final void setBigDecimalValue(BigDecimal obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_BigDecimal(obj);
                set_commit();
            }
        }
    }

    public final void setCalendarValue(Calendar obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_Calendar(obj);
                set_commit();
            }
        }
    }

    public final void setDateValue(Date obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_Date(obj);
                set_commit();
            }
        }
    }

    public final void setGDateValue(GDate obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_GDate(obj);
                set_commit();
            }
        }
    }

    public final void setGDateValue(GDateSpecification obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_GDate(obj);
                set_commit();
            }
        }
    }

    public final void setGDurationValue(GDuration obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_GDuration(obj);
                set_commit();
            }
        }
    }

    public final void setGDurationValue(GDurationSpecification obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_GDuration(obj);
                set_commit();
            }
        }
    }

    public final void setQNameValue(QName obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_QName(obj);
                set_commit();
            }
        }
    }

    public final void setListValue(List<?> obj) {
        if (obj == null) {
            setNil();
        } else {
            synchronized (monitor()) {
                set_prepare();
                set_list(obj);
                set_commit();
            }
        }
    }

    public final void setStringValue(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 setObjectValue(Object o) {
        if (o == null) {
            setNil();
            return;
        }

        if (o instanceof XmlObject) {
            set((XmlObject) o);
        } else if (o instanceof String) {
            setStringValue((String) o);
        } else if (o instanceof StringEnumAbstractBase) {
            setEnumValue((StringEnumAbstractBase) o);
        } else if (o instanceof BigInteger) {
            setBigIntegerValue((BigInteger) o);
        } else if (o instanceof BigDecimal) {
            setBigDecimalValue((BigDecimal) o);
        } else if (o instanceof Byte) {
            setByteValue((Byte) o);
        } else if (o instanceof Short) {
            setShortValue((Short) o);
        } else if (o instanceof Integer) {
            setIntValue((Integer) o);
        } else if (o instanceof Long) {
            setLongValue((Long) o);
        } else if (o instanceof Boolean) {
            setBooleanValue((Boolean) o);
        } else if (o instanceof Float) {
            setFloatValue((Float) o);
        } else if (o instanceof Double) {
            setDoubleValue((Double) o);
        } else if (o instanceof Calendar) {
            setCalendarValue(((Calendar) o));
        } else if (o instanceof Date) {
            setDateValue((Date) o);
        } else if (o instanceof GDateSpecification) {
            setGDateValue((GDateSpecification) o);
        } else if (o instanceof GDurationSpecification) {
            setGDurationValue((GDurationSpecification) o);
        } else if (o instanceof QName) {
            setQNameValue((QName) o);
        } else if (o instanceof List) {
            setListValue((List<?>) o);
        } else if (o instanceof byte[]) {
            setByteArrayValue((byte[]) o);
        } else {
            throw
                new XmlValueNotSupportedException(
                    "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()) {
            setStringValue(obj.getStringValue());
        } else {
            boolean noSyncThis = preCheck();
            boolean noSyncObj = obj.preCheck();

            if (monitor() == obj.monitor())             // both are in the same locale
            {
                if (noSyncThis)                         // the locale is not sync
                {
                    newObj = setterHelper(obj);
                } else                                    // the locale is sync
                {
                    synchronized (monitor()) {
                        newObj = setterHelper(obj);
                    }
                }
            } else                                        // on different locale's
            {
                if (noSyncThis) {
                    if (noSyncObj)                      // both unsync
                    {
                        newObj = setterHelper(obj);
                    } else                                // only obj is sync
                    {
                        synchronized (obj.monitor()) {
                            newObj = setterHelper(obj);
                        }
                    }
                } else {
                    if (noSyncObj)                      // only this is sync
                    {
                        synchronized (monitor()) {
                            newObj = setterHelper(obj);
                        }
                    } else                                // both are sync can't avoid the global lock
                    {
                        boolean acquired = false;

                        try {
                            // 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;
    }

    public final XmlObject generatedSetterHelperImpl(XmlObject src, QName propName, int index,
                                                     short kindSetterHelper) {

        XmlObjectBase srcObj = underlying(src);

        if (srcObj == null) {
            synchronized (monitor()) {
                XmlObjectBase target = getTargetForSetter(propName, index, kindSetterHelper);
                target.setNil();
                return target;
            }
        }

        if (srcObj.isImmutable()) {
            synchronized (monitor()) {
                XmlObjectBase target = getTargetForSetter(propName, index, kindSetterHelper);
                target.setStringValue(srcObj.getStringValue());
                return target;
            }
        }


        boolean noSyncThis = preCheck();
        boolean noSyncObj = srcObj.preCheck();

        if (monitor() == srcObj.monitor()) {
            // both are in the same locale
            if (noSyncThis) {
                // the locale is not sync
                return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
            } else {
                // the locale is sync
                synchronized (monitor()) {
                    return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
                }
            }
        }

        if (noSyncThis) {
            // on different locale's
            if (noSyncObj) {
                // both unsync
                return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
            } else {
                // only obj is sync
                synchronized (srcObj.monitor()) {
                    return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
                }
            }
        } else {
            if (noSyncObj) {
                // only this is sync
                synchronized (monitor()) {
                    return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
                }
            } else {
                // both are sync can't avoid the global lock
                boolean acquired = false;

                try {
                    // about to grab two locks: don't deadlock ourselves
                    GlobalLock.acquire();
                    acquired = true;

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

                            return (XmlObject) objSetterHelper(srcObj, propName, index, kindSetterHelper);
                        }
                    }
                } catch (InterruptedException e) {
                    throw new XmlRuntimeException(e);
                } finally {
                    if (acquired) {
                        GlobalLock.release();
                    }
                }
            }
        }
    }

    private TypeStoreUser objSetterHelper(XmlObjectBase srcObj, QName propName, int index, short kindSetterHelper) {
        XmlObjectBase target = getTargetForSetter(propName, index, kindSetterHelper);

        target.check_orphaned();
        srcObj.check_orphaned();

        return target.get_store().copy_contents_from(srcObj.get_store()).
            get_store().change_type(srcObj.schemaType());
    }

    private XmlObjectBase getTargetForSetter(QName propName, int index, short kindSetterHelper) {
        switch (kindSetterHelper) {
            case KIND_SETTERHELPER_SINGLETON: {
                check_orphaned();
                XmlObjectBase target;
                target = (XmlObjectBase) get_store().find_element_user(propName, index);
                if (target == null) {
                    target = (XmlObjectBase) get_store().add_element_user(propName);
                }

                if (target.isImmutable()) {
                    throw new IllegalStateException("Cannot set the value of an immutable XmlObject");
                }

                return target;
            }

            case KIND_SETTERHELPER_ARRAYITEM: {
                check_orphaned();
                XmlObjectBase target;
                target = (XmlObjectBase) get_store().find_element_user(propName, index);
                if (target == null) {
                    throw new IndexOutOfBoundsException();
                }

                if (target.isImmutable()) {
                    throw new IllegalStateException("Cannot set the value of an immutable XmlObject");
                }

                return target;
            }

            default:
                throw new IllegalArgumentException("Unknown kindSetterHelper: " + kindSetterHelper);
        }
    }

    /**
     * Same as set() but unsynchronized.
     * Warning: Using this method in mutithreaded environment can cause invalid states.
     */
    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()) {
            setStringValue(obj.getStringValue());
        } else {
            check_orphaned();
            obj.check_orphaned();

            newObj = get_store().copy_contents_from(obj.get_store()).
                get_store().change_type(obj.schemaType());
        }
        return (XmlObject) newObj;
    }

    protected void set_list(List<?> list) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"List", getPrimitiveTypeName()});
    }

    protected void set_boolean(boolean v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"boolean", getPrimitiveTypeName()});
    }

    protected void set_byte(byte v) {
        set_int(v);
    }

    protected void set_short(short v) {
        set_int(v);
    }

    protected void set_int(int v) {
        set_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 XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"enum", getPrimitiveTypeName()});
    }

    protected void set_ByteArray(byte[] b) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"byte[]", getPrimitiveTypeName()});
    }

    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_BigDecimal(new BigDecimal(v));
    }

    protected void set_BigDecimal(BigDecimal v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"numeric", getPrimitiveTypeName()});
    }

    protected void set_Date(Date v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"Date", getPrimitiveTypeName()});
    }

    protected void set_Calendar(Calendar v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"Calendar", getPrimitiveTypeName()});
    }

    protected void set_GDate(GDateSpecification v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"Date", getPrimitiveTypeName()});
    }

    protected void set_GDuration(GDurationSpecification v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"Duration", getPrimitiveTypeName()});
    }

    protected void set_ComplexXml(XmlObject v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"complex content", getPrimitiveTypeName()});
    }

    protected void set_QName(QName v) {
        throw new XmlValueNotSupportedException(XmlErrorCodes.EXCEPTION_VALUE_NOT_SUPPORTED_J2S,
            new Object[]{"QName", getPrimitiveTypeName()});
    }

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

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

    private String getPrimitiveTypeName() {
        SchemaType type = schemaType();
        if (type.isNoType()) {
            return "unknown";
        }
        SchemaType t = type.getPrimitiveType();
        if (t == null) {
            return "complex";
        } else {
            return t.getName().getLocalPart();
        }
    }

    private 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 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 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;
                }
            }
        } else {
            Set<SchemaType> 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();
        }
    }

    private static final XmlObject[] EMPTY_RESULT = new XmlObject[0];

    /**
     * Selects the contents of the children elements with the given name.
     */
    public XmlObject[] selectChildren(QName elementName) {
        XmlCursor xc = this.newCursor();
        try {
            if (!xc.isContainer()) {
                return EMPTY_RESULT;
            }

            List<XmlObject> result = new ArrayList<>();

            if (xc.toChild(elementName)) {
                // look for elements
                do {
                    result.add(xc.getObject());
                }
                while (xc.toNextSibling(elementName));
            }
            if (result.size() == 0) {
                return EMPTY_RESULT;
            } else {
                return result.toArray(EMPTY_RESULT);
            }
        } finally {
            xc.dispose();
        }
    }

    /**
     * Selects the contents of the children elements with the given name.
     */
    public XmlObject[] selectChildren(String elementUri, String elementLocalName) {
        return selectChildren(new QName(elementUri, elementLocalName));
    }

    /**
     * Selects the contents of the children elements that are contained in the elementNameSet.
     */
    public XmlObject[] selectChildren(QNameSet elementNameSet) {
        if (elementNameSet == null) {
            throw new IllegalArgumentException();
        }

        XmlCursor xc = this.newCursor();
        try {
            if (!xc.isContainer()) {
                return EMPTY_RESULT;
            }

            List<XmlObject> result = new ArrayList<>();

            if (xc.toFirstChild()) {
                // look for elements
                do {
                    assert xc.isContainer();
                    if (elementNameSet.contains(xc.getName())) {
                        result.add(xc.getObject());
                    }
                }
                while (xc.toNextSibling());
            }
            if (result.size() == 0) {
                return EMPTY_RESULT;
            } else {
                return result.toArray(EMPTY_RESULT);
            }
        } finally {
            xc.dispose();
        }
    }

    /**
     * Selects the content of the attribute with the given name.
     */
    public XmlObject selectAttribute(QName attributeName) {
        XmlCursor xc = this.newCursor();

        try {
            if (!xc.isContainer()) {
                return null;
            }

            if (xc.toFirstAttribute()) {
                //look for attributes
                do {
                    if (xc.getName().equals(attributeName)) {
                        return xc.getObject();
                    }
                }
                while (xc.toNextAttribute());
            }
            return null;
        } finally {
            xc.dispose();
        }
    }

    /**
     * Selects the content of the attribute with the given name.
     */
    public XmlObject selectAttribute(String attributeUri, String attributeLocalName) {
        return selectAttribute(new QName(attributeUri, attributeLocalName));
    }

    /**
     * Selects the contents of the attributes that are contained in the elementNameSet.
     */
    public XmlObject[] selectAttributes(QNameSet attributeNameSet) {
        if (attributeNameSet == null) {
            throw new IllegalArgumentException();
        }

        XmlCursor xc = this.newCursor();
        try {
            if (!xc.isContainer()) {
                return EMPTY_RESULT;
            }

            List<XmlObject> result = new ArrayList<>();

            if (xc.toFirstAttribute()) {
                //look for attributes
                do {
                    if (attributeNameSet.contains(xc.getName())) {
                        result.add(xc.getObject());
                    }
                }
                while (xc.toNextAttribute());
            }

            if (result.size() == 0) {
                return EMPTY_RESULT;
            } else {
                return result.toArray(EMPTY_RESULT);
            }
        } finally {
            xc.dispose();
        }
    }

    /**
     * This method can writeReplace either an unwrapped XmlObjectBase
     * or an XBean proxy.  A "true" argument means unwrapped.
     * <p>
     * The serialization strategy for XmlObjects is this:
     * <p>
     * (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.
     * <p>
     * (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.
     * <p>
     * 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(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;
                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 new IOException(e.getMessage(), 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;
            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(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 base.getFloatValue();

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

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

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

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

                    case SchemaType.SIZE_LONG:
                        return 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();
    }

    private List<XmlObjectBase> getBaseArray(QName elementName) {
        check_orphaned();
        List<XmlObjectBase> targetList = new java.util.ArrayList<>();
        get_store().find_all_element_users(elementName, targetList);
        return targetList;
    }

    private List<XmlObjectBase> getBaseArray(QNameSet elementSet) {
        check_orphaned();
        List<XmlObjectBase> targetList = new java.util.ArrayList<>();
        get_store().find_all_element_users(elementSet, targetList);
        return targetList;
    }

    protected <T> T[] getObjectArray(QName elementName, Function<SimpleValue, T> fun, IntFunction<T[]> arrayCon) {
        synchronized (monitor()) {
            return getBaseArray(elementName).stream().map(fun).toArray(arrayCon);
        }
    }

    protected <T> T[] getEnumArray(QName elementName, IntFunction<T[]> arrayCon) {
        synchronized (monitor()) {
            return getBaseArray(elementName).stream().map(SimpleValue::getEnumValue).toArray(arrayCon);
        }
    }

    protected boolean[] getBooleanArray(QName elementName) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementName);
            boolean[] result = new boolean[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getBooleanValue();
            }
            return result;
        }
    }

    protected float[] getFloatArray(QName elementName) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementName);
            float[] result = new float[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getFloatValue();
            }
            return result;
        }
    }

    protected double[] getDoubleArray(QName elementName) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementName);
            return targetList.stream()
                .map(org.apache.xmlbeans.SimpleValue.class::cast)
                .mapToDouble(org.apache.xmlbeans.SimpleValue::getDoubleValue)
                .toArray();
        }
    }

    protected byte[] getByteArray(QName elementName) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementName);
            byte[] result = new byte[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getByteValue();
            }
            return result;
        }
    }

    protected short[] getShortArray(QName elementName) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementName);
            short[] result = new short[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getShortValue();
            }
            return result;
        }
    }

    protected int[] getIntArray(QName elementName) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementName);
            return targetList.stream()
                .map(org.apache.xmlbeans.SimpleValue.class::cast)
                .mapToInt(org.apache.xmlbeans.SimpleValue::getIntValue)
                .toArray();
        }
    }

    protected long[] getLongArray(QName elementName) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementName);
            return targetList.stream()
                .map(org.apache.xmlbeans.SimpleValue.class::cast)
                .mapToLong(org.apache.xmlbeans.SimpleValue::getLongValue)
                .toArray();
        }
    }

    protected <T extends XmlObject> T[] getXmlObjectArray(QName elementName, T[] arrayCon) {
        synchronized (monitor()) {
            return getBaseArray(elementName).toArray(arrayCon);
        }
    }

    protected <T> T[] getObjectArray(QNameSet elementSet, Function<SimpleValue, T> fun, IntFunction<T[]> arrayCon) {
        synchronized (monitor()) {
            return getBaseArray(elementSet).stream().map(fun).toArray(arrayCon);
        }
    }

    protected <T> T[] getEnumArray(QNameSet elementSet, IntFunction<T[]> arrayCon) {
        synchronized (monitor()) {
            return getBaseArray(elementSet).stream().map(SimpleValue::getEnumValue).toArray(arrayCon);
        }
    }

    protected boolean[] getBooleanArray(QNameSet elementSet) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementSet);
            boolean[] result = new boolean[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getBooleanValue();
            }
            return result;
        }
    }

    protected float[] getFloatArray(QNameSet elementSet) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementSet);
            float[] result = new float[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getFloatValue();
            }
            return result;
        }
    }

    protected double[] getDoubleArray(QNameSet elementSet) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementSet);
            return targetList.stream()
                .map(org.apache.xmlbeans.SimpleValue.class::cast)
                .mapToDouble(org.apache.xmlbeans.SimpleValue::getDoubleValue)
                .toArray();
        }
    }

    protected byte[] getByteArray(QNameSet elementSet) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementSet);
            byte[] result = new byte[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getByteValue();
            }
            return result;
        }
    }

    protected short[] getShortArray(QNameSet elementSet) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementSet);
            short[] result = new short[targetList.size()];
            for (int i = 0; i < result.length; i++) {
                result[i] = ((org.apache.xmlbeans.SimpleValue) targetList.get(i)).getShortValue();
            }
            return result;
        }
    }

    protected int[] getIntArray(QNameSet elementSet) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementSet);
            return targetList.stream()
                .map(org.apache.xmlbeans.SimpleValue.class::cast)
                .mapToInt(org.apache.xmlbeans.SimpleValue::getIntValue)
                .toArray();
        }
    }

    protected long[] getLongArray(QNameSet elementSet) {
        synchronized (monitor()) {
            List<XmlObjectBase> targetList = getBaseArray(elementSet);
            return targetList.stream()
                .map(org.apache.xmlbeans.SimpleValue.class::cast)
                .mapToLong(org.apache.xmlbeans.SimpleValue::getLongValue)
                .toArray();
        }
    }

    protected <T extends XmlObject> T[] getXmlObjectArray(QNameSet elementSet, T[] arrayCon) {
        synchronized (monitor()) {
            return getBaseArray(elementSet).toArray(arrayCon);
        }
    }

    protected <T extends XmlObject> T[] xgetArray(QName elementName, IntFunction<T[]> arrayCon) {
        synchronized (monitor()) {
            check_orphaned();
            java.util.List<T> targetList = new java.util.ArrayList<>();
            get_store().find_all_element_users(elementName, targetList);
            return targetList.stream().toArray(arrayCon);
        }
    }

    protected <T extends XmlObject> T[] xgetArray(QNameSet elementSet, IntFunction<T[]> arrayCon) {
        synchronized (monitor()) {
            check_orphaned();
            java.util.List<T> targetList = new java.util.ArrayList<>();
            get_store().find_all_element_users(elementSet, targetList);
            return targetList.stream().toArray(arrayCon);
        }
    }
}
