/*   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.util.LongUTFDataInputStream;
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<? extends XmlObject> 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<? extends XmlAnySimpleType> 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<? extends XmlObject> _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);
        }

        @SuppressWarnings("unchecked")
        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<? extends XmlObject>) 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:
                        if (minorVersionNum == 1) {
                            xmlText = (String) in.readObject();
                            in.readBoolean(); // ignored
                        } else {
                            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
            LongUTFDataInputStream dis = null;
            String str;
            try {
                dis = new LongUTFDataInputStream(new ByteArrayInputStream(bArray));
                str = dis.readLongUTF();
            } 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);
        }
    }
}
