/*   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.store;

import org.apache.xmlbeans.impl.common.ValidatorListener;
import org.apache.xmlbeans.impl.store.Splay.Attr;
import org.apache.xmlbeans.impl.store.Splay.Begin;
import org.apache.xmlbeans.impl.store.Splay.Container;
import org.apache.xmlbeans.impl.store.Splay.CopyContext;
import org.apache.xmlbeans.impl.store.Splay.Goober;
import org.apache.xmlbeans.impl.values.NamespaceManager;
import org.apache.xmlbeans.impl.values.TypeStore;
import org.apache.xmlbeans.impl.values.TypeStoreUser;
import org.apache.xmlbeans.impl.values.TypeStoreUserFactory;
import org.apache.xmlbeans.impl.values.TypeStoreVisitor;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.SchemaField;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlBeans;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;

public final class Type extends Goober implements TypeStore
{
    Type ( Root r, SchemaType sType, Splay s )
    {
        this( r, ((TypeStoreUserFactory) sType).createTypeStoreUser(), s );
    }
    
    Type ( Root r, TypeStoreUser user, Splay s )
    {
        super( r, Splay.TYPE );
        
        if (XmlBeans.ASSERTS)
        {
            XmlBeans.assertTrue( s.peekType() == null );
            XmlBeans.assertTrue( user != null );
            XmlBeans.assertTrue( s.isTypeable() );
        }

        _user = user;
        
        set( s, 0 );

        if (user.uses_invalidate_value())
            r._cInvalidatableTypes++;

        if (user.is_child_element_order_sensitive())
            r._cElemOrderSensitiveTypes++;
        
        user.attach_store( this );
    }

    void disconnect ( Root r )
    {
        super.disconnect( r );
        
        if (_user.uses_invalidate_value())
            r._cInvalidatableTypes--;

        if (_user.is_child_element_order_sensitive())
            r._cElemOrderSensitiveTypes--;
        
        _user.disconnect_store();
    }

    //
    //
    //

    SchemaType get_schema_type ( )
    {
        return _user.get_schema_type();
    }
    
    SchemaType get_element_type ( QName eltName, QName xsiType )
    {
        return _user.get_element_type( eltName, xsiType );
    }
    
    SchemaType get_attribute_type ( QName attrName )
    {
        return _user.get_attribute_type( attrName );
    }
    
    TypeStoreUser create_element_user ( QName eltName, QName xsiType )
    {
        TypeStoreUser ret = null;
        if (getRoot()._factory != null)
            ret = getRoot()._factory.createElementUser(get_schema_type(), eltName, xsiType);

        if (ret == null)
            ret = _user.create_element_user( eltName, xsiType );

        return ret;
    }
            
    TypeStoreUser create_attribute_user( QName attrName )
    {
        TypeStoreUser ret = null;

        if (getRoot()._factory != null)
            ret = getRoot()._factory.createAttributeUser(get_schema_type(),  attrName);

        if (ret == null)
            ret = _user.create_attribute_user( attrName );

        return ret;
    }

    XmlObject getXmlObject ( )
    {
        return (XmlObject) _user;
    }

    boolean uses_invalidate_value ( )
    {
        return _user.uses_invalidate_value();
    }

    boolean is_child_element_order_sensitive ( )
    {
        return _user.is_child_element_order_sensitive();
    }

    void invalidateText ( )
    {
        if (_inhibitUserInvalidate == 0)
            _user.invalidate_value();
    }

    void invalidateNil ( )
    {
        if (_inhibitUserInvalidate == 0)
            _user.invalidate_nilvalue();
    }
    
    void invalidateElement ( Container container, Splay s )
    {
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.getContainer() == container );
        
        if (_inhibitUserInvalidate > 0)
            return;

        Type containerType = container.peekType();

        if (containerType == null)
            return;

        if (!containerType.is_child_element_order_sensitive())
            return;

        containerType._user.invalidate_value();

        for ( ; ; s = s.nextSplay() )
        {
            if (s.isFinish())
            {
                if (XmlBeans.ASSERTS)
                    XmlBeans.assertTrue( s.getContainer() == container );
                return;
            }

            if (s.isBegin())
            {
                Type childType = s.peekType();

                if (childType != null)
                    childType._user.invalidate_element_order();

                s = s.getFinishSplay();
            }

            break;
        }
    }

    String build_text ( NamespaceManager nsm )
    {
        return _user.build_text( nsm );
    }

    boolean build_nil ( )
    {
        return _user.build_nil();
    }
    
    int validateContent ( Splay s, NamespaceManager nsm )
    {
        Root r = getRoot();
        
        if (XmlBeans.ASSERTS)
        {
            XmlBeans.assertTrue( s.isInvalid() );
            XmlBeans.assertTrue( s.isLeaf() || s.isDoc() );
        }

        String text = build_text( nsm );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( text != null );

        _inhibitUserInvalidate++;

        // Validating does not logically change the doc
        long oldVersion = r.getVersion();
        
        s.toggleIsInvalid(); // Prevents infinite recursion
        
        s.insertChars( 1, r, text, 0, text.length() );

        r.restoreVersion( oldVersion );
        
        _inhibitUserInvalidate--;

        return text.length();
    }
    
    void validateValue ( Splay s, NamespaceManager nsm )
    {
        Root r = getRoot();
        
        if (XmlBeans.ASSERTS)
        {
            XmlBeans.assertTrue( s.isInvalid() );
            XmlBeans.assertTrue( s.isNormalAttr() );
        }

        String text = build_text( nsm );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( text != null );

        // Validating does not logically change the doc
        long oldVersion = r.getVersion();
        
        _inhibitUserInvalidate++;
        
        s.toggleIsInvalid(); // Prevents infinite recursion
        
        s.setText( r, text, 0, text.length() );
        
        r.restoreVersion( oldVersion );
        
        _inhibitUserInvalidate--;
    }

    QNameSet get_element_ending_delimiters( QName qname )
    {
        return _user.get_element_ending_delimiters( qname );
    }

    //
    //
    //
    
    public boolean is_attribute ( )
    {
        return getSplay().isAttr();
    }

    public boolean validate_on_set()
    {
        return getRoot().validateOnSet();
    }

    public XmlCursor new_cursor ( )
    {
        return new Cursor( getRoot(), getSplay() );
    }

    public void validate ( ValidatorListener vEventSink )
    {
        new Saver.ValidatorSaver( getRoot(), getSplay(), 0, null, vEventSink );
    }
    
    public SchemaTypeLoader get_schematypeloader ( )
    {
        return getRoot().getSchemaTypeLoader();
    }
    
    public QName get_xsi_type ( )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() || s.isNormalAttr() );

        if (s.isNormalAttr())
            return null;

        return s.getXsiTypeName( getRoot() );
    }
    
    public TypeStoreUser change_type ( SchemaType sType )
    {
        Splay s = getSplay();

        s.setType( getRoot(), sType, false );

        Type t = s.getType( getRoot() );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( t != null );
        
        return t._user;
    }
    
    public void invalidate_text ( )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isTypeable() );

        if (s.isInvalid())
            return;
        
        _inhibitUserInvalidate++;

        s.removeContent( getRoot(), false );

        s.toggleIsInvalid();
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isInvalid() );
        
        _inhibitUserInvalidate--;
    }
    
    public String fetch_text ( int whitespaceRule )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( !s.isInvalid() );
        
        if (s.isInvalid())
            throw new RuntimeException( "Can't fetch text when invalid" );

        return s.getText( getRoot(), whitespaceRule );
    }
    
    public void store_text ( String text )
    {
        _inhibitUserInvalidate++;
        getSplay().setText( getRoot(), text, 0, text.length() );
        _inhibitUserInvalidate--;
    }
    
    public int compute_flags ( )
    {
        Splay s = getSplay();
        
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isTypeable() );

        if (s.isDoc())
            return 0;

        Container parentContainer = s.getContainer();

        Type parentType = parentContainer.getType( getRoot() );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( parentType != null );

        TypeStoreUser parentUser = parentType._user;

        if (s.isAttr())
            return parentUser.get_attributeflags( s.getName() );

        int f = parentUser.get_elementflags( s.getName() );

        if (f != -1)
            return f;

        TypeStoreVisitor visitor = parentUser.new_visitor();

        if (visitor == null)
            return 0;

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( !parentContainer.isLeaf() );
        
        for ( Splay t = parentContainer.nextSplay() ; ; t = t.nextSplay() )
        {
            switch ( t.getKind() )
            {
            case Splay.END :
                if (XmlBeans.ASSERTS)
                    XmlBeans.assertTrue( false );
                break;

            case Splay.BEGIN :
                visitor.visit( t.getName() );

                if (t == s)
                    return visitor.get_elementflags();

                t = t.getFinishSplay();

                break;
            }
        }
    }

    public SchemaField get_schema_field ( )
    {
        Splay s = getSplay();
        
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isTypeable() );

        if (s.isDoc())
            return null;
        
        Container parentContainer = s.getContainer();

        TypeStoreUser parentUser = parentContainer.getType( getRoot() )._user;
        
        if (s.isAttr())
            return parentUser.get_attribute_field( s.getName() );

        if (XmlBeans.ASSERTS)
        {
            XmlBeans.assertTrue( s.isBegin() );
            XmlBeans.assertTrue( !parentContainer.isLeaf() );
        }

        TypeStoreVisitor visitor = parentUser.new_visitor();

        if (visitor == null)
            return null;

        for ( Splay t = parentContainer.nextSplay() ; ; t = t.nextSplay() )
        {
            switch ( t.getKind() )
            {
            case Splay.END :
                if (XmlBeans.ASSERTS)
                    XmlBeans.assertTrue( false );
                break;

            case Splay.BEGIN :
                visitor.visit( t.getName() );

                if (t == s)
                    return visitor.get_schema_field();

                t = t.getFinishSplay();

                break;
            }
        }
    }
    
    public int count_elements ( QName name )
    {
        return getRoot().count( (Container) getSplay(), name, null );
    }

    public int count_elements(QNameSet names)
    {
        return getRoot().count((Container)getSplay(),  null, names);
    }
    
    public TypeStoreUser find_element_user ( QName name, int i )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );
        
        if (!s.isContainer())
            throw new IllegalStateException();

        Begin nthBegin = getRoot().findNthBegin( s, name, null, i );

        if (nthBegin == null)
            return null;

        Type t = nthBegin.getType( getRoot() );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( t != null );
        
        return t._user;
    }

    public TypeStoreUser find_element_user ( QNameSet names, int i )
    {
        Splay s = getSplay();
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );

        Begin nthBegin = getRoot().findNthBegin(s,  null, names, i);
        if (nthBegin == null) return null;

        Type t = nthBegin.getType(getRoot());
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( t != null );

        return t._user;
    }
    
    private void findAllElementTypes ( QName name, QNameSet set, List fillMeUp )
    {
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( getSplay().isContainer() );

        Splay s = getSplay();

        if (s.isLeaf())
            return;

        loop:
        for ( s = s.nextSplay() ; ; s = s.nextSplay() )
        {
            switch ( s.getKind() )
            {
            case Splay.END  :
            case Splay.ROOT :
            {
                break loop;
            }        
            case Splay.BEGIN :
            {
                if (set == null)
                {
                    if (s.getName().equals( name ))
                    {
                        Type type = s.getType( getRoot() );

                        if (XmlBeans.ASSERTS)
                            XmlBeans.assertTrue( type != null );
                    
                        fillMeUp.add( type );
                    }
                }
                else
                {
                    if (set.contains(s.getName()))
                    {
                        Type type = s.getType(getRoot());
                        if (XmlBeans.ASSERTS)
                            XmlBeans.assertTrue( type != null );
                        fillMeUp.add(type);
                    }
                }

                s = s.getFinishSplay();
                break;
            }
            }
        }
    }

    public void find_all_element_users ( QName name, List fillMeUp )
    {
        int i = fillMeUp.size();
        
        findAllElementTypes( name, null, fillMeUp );

        for ( int j = i ; j < fillMeUp.size() ; j++ )
            fillMeUp.set( j, ((Type) fillMeUp.get( j ))._user );
    }

    public void find_all_element_users (QNameSet names, List fillMeUp)
    {
        int i = fillMeUp.size();
        findAllElementTypes(null, names, fillMeUp);

        for ( int j = i ; j < fillMeUp.size() ; j++ )
            fillMeUp.set( j, ((Type) fillMeUp.get( j ))._user );
    }

    public TypeStoreUser find_attribute_user ( QName name )
    {
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( getSplay().isContainer() );

        Splay a = getSplay().getAttr( name );

        if (a == null)
            return null;

        Type t = a.getType( getRoot() );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( t != null );

        return t._user;
    }
    
    public String compute_default_text ( )
    {
        Splay s = getSplay();
        
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isTypeable() );

        if (s.isDoc())
            return null;

        Container parentContainer = s.getContainer();

        Type parentType = parentContainer.getType( getRoot() );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( parentType != null );

        TypeStoreUser parentUser = parentType._user;

        if (s.isAttr())
            return parentUser.get_default_attribute_text( s.getName() );

        String result = parentUser.get_default_element_text( s.getName() );

        if (result != null)
            return result;

        TypeStoreVisitor visitor = parentUser.new_visitor();

        if (visitor == null)
            return null;

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( !parentContainer.isLeaf() );
        
        for ( Splay t = parentContainer.nextSplay() ; ; t = t.nextSplay() )
        {
            switch ( t.getKind() )
            {
            case Splay.END :
                if (XmlBeans.ASSERTS)
                    XmlBeans.assertTrue( false );
                break;

            case Splay.BEGIN :
                visitor.visit( t.getName() );

                if (t == s)
                    return visitor.get_default_text();

                t = t.getFinishSplay();
                
                break;
            }
        }
    }
    
    public void invalidate_nil ( )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isTypeable() );

        if (!s.isAttr())
            s.setXsiNil( getRoot(), build_nil() );
    }
      
    public boolean find_nil ( )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isTypeable() );
  
        return s.isAttr() ? false : s.getXsiNil( getRoot() );
    }
    
    public String find_prefix_for_nsuri (
        String nsuri, String suggested_prefix )
    {
        Splay s = getSplay();

        if (s.isAttr())
            s = s.getContainer();

        String result = s.prefixForNamespace( getRoot(), nsuri, suggested_prefix, true);

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( result != null );

        return result;
    }
    
    public String getNamespaceForPrefix ( String prefix )
    {
        Splay s = getSplay();

        if (s.isAttr())
            s = s.getContainer();
        
        return s.namespaceForPrefix( prefix, true );
    }

    public TypeStoreUser insert_element_user ( QName name, int i )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );
        
        if (!s.isContainer())
            throw new IllegalStateException();

        if (i < 0)
            throw new IndexOutOfBoundsException();

        Root r = getRoot();
        Container c = (Container) s;

        Begin nthBegin = r.findNthBegin( c, name, null, i );

        if (nthBegin == null)
        {
            if (i > r.count( c, name, null ) + 1)
                throw new IndexOutOfBoundsException();

            return add_element_user( name );
        }

        return insertElement( name, nthBegin, 0 );
    }

    public TypeStoreUser insert_element_user(QNameSet set, QName name, int i)
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );

        if (!s.isContainer())
            throw new IllegalStateException();

        if (i < 0)
            throw new IllegalStateException();

        Root r = getRoot();
        Container c = (Splay.Container) s;

        Begin nthBegin = r.findNthBegin(c, null, set, i);

        if (nthBegin == null)
        {
            if (i > r.count(c, null, set))
                throw new IndexOutOfBoundsException();

            return add_element_user(name);
        }

        return insertElement(name, nthBegin, 0);
    }
    
// TODO - consolidate names, this fcn is very expensive in creating names
    public TypeStoreUser add_element_user ( QName qname )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );
        
        if (!s.isContainer())
            throw new IllegalStateException();

        Splay candidateSplay;
        int candidatePos;
            
        if (s.isLeaf())
        {
            candidateSplay = s;
            candidatePos = s.getPosLeafEnd();
        }
        else
        {
            candidateSplay = s.getFinishSplay();
            candidatePos = 0;

            QNameSet endSet = null;
            
            loop:
            for ( Splay t = candidateSplay ; ; )
            {
                for ( ; ; )
                {
                    t = t.prevSplay();
                    
                    if (t == s)
                        break loop;
                    
                    if (t.isContainer())
                        break;

                    if (t.isEnd())
                    {
                        t = t.getContainer();
                        break;
                    }
                }

                if (XmlBeans.ASSERTS)
                    XmlBeans.assertTrue( t.isContainer() );

                if (t.getName().equals( qname ))
                    break;

                if (endSet == null)
                    endSet = get_element_ending_delimiters( qname );

                if (endSet.contains( t.getName() ))
                    candidateSplay = t;
            }
        }
        
        return insertElement( qname, candidateSplay, candidatePos );
    }

    private TypeStoreUser insertElement ( QName name, Splay s, int p )
    {
        Root r = getRoot();
        
        Begin b = new Begin( name, null );
        b.toggleIsLeaf();
        
        s.insert( r, p, b, null, 0, 0, true );
        
        Type t = b.getType( r );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( t != null );
        
        return t._user;
    }
    
    public void remove_element ( QName qname, int i )
    {
        if (i < 0)
            throw new IndexOutOfBoundsException();
        
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );
        
        if (!s.isContainer())
            throw new IllegalStateException();

        if (s.isLeaf())
            throw new IndexOutOfBoundsException();

        Begin b = getRoot().findNthBegin( s, qname, null, i );

        if (b == null)
            throw new IndexOutOfBoundsException();

        b.remove( getRoot(), true );
    }

    public void remove_element(QNameSet names, int i)
    {
        if (i < 0)
            throw new IndexOutOfBoundsException();

        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );

        if (!s.isContainer())
            throw new IllegalStateException();

        if (s.isLeaf())
            throw new IndexOutOfBoundsException();

        Begin b = getRoot().findNthBegin(s, null, names, i);

        if (b == null)
            throw new IndexOutOfBoundsException();

        b.remove(getRoot(), true);

    }
    
    public TypeStoreUser add_attribute_user ( QName qname )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );
        
        if (!s.isContainer())
            throw new IllegalStateException();

        Splay a = s.getAttr( qname );

        if (a != null)
            throw new IndexOutOfBoundsException();
        
        s.nextSplay().insert(
            getRoot(), 0, a = new Attr( qname ), null, 0, 0, true );
        
        Type t = a.getType( getRoot() );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( t != null );

        return t._user;
    }
    
    public void remove_attribute ( QName qname )
    {
        Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );
        
        if (!s.isContainer())
            throw new IllegalStateException();

        Splay a = s.getAttr( qname );

        if (a == null)
            throw new IndexOutOfBoundsException();
        
        a.remove( getRoot(), true );
    }
    
    public TypeStoreUser copy_contents_from ( TypeStore source )
    {
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( source instanceof Type );

        Type sourceType = (Type) source;

        Splay s = getSplay();

        s.replaceContents( getRoot(), sourceType.getSplay(), sourceType.getRoot(), true, true );
        
        return s.getType( getRoot() )._user;
    }

    public void array_setter ( XmlObject[] sources, QName elementName )
    {
        // TODO - this is the quick and dirty implementation, make this faster
        
        int m = sources.length;

        ArrayList copies = new ArrayList();
        ArrayList types = new ArrayList();

        for ( int i = 0 ; i < m ; i++ )
        {
// TODO - deal with null sources[ i ] here -- what to do?

            if (sources[ i ] == null)
                throw new IllegalArgumentException( "Array element null" );
            
            else if (sources[ i ].isImmutable())
            {
                copies.add( null );
                types.add( null );
            }
            else
            {
                Type type = (Type) ((TypeStoreUser) sources[ i ]).get_store();
                
                copies.add( type.getSplay().copySplayContents( type.getRoot()));
                
                types.add( sources[ i ].schemaType() );
            }
        }

        int n = count_elements( elementName );

        for ( ; n > m ; n-- )
            remove_element( elementName, m );

        for ( ; m > n ; n++ )
            add_element_user( elementName );

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( m == n );
        
        ArrayList elements = new ArrayList();
        
        findAllElementTypes( elementName, null, elements );

        Root r = getRoot();
        
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( elements.size() == n );

        for ( int i = 0 ; i < n ; i++ )
        {
            Type type = (Type) elements.get( i );

            if (sources[ i ].isImmutable())
                type.getXmlObject().set( sources[ i ] );
            else
            {
                Splay s = type.getSplay();

                if (XmlBeans.ASSERTS)
                {
                    XmlBeans.assertTrue( r == type.getRoot() );
                    XmlBeans.assertTrue( s.isContainer() );
                }

                s.removeContent( r, true );
                
                CopyContext copyContext = (CopyContext) copies.get( i );

                Splay copyTree = copyContext.getTree();

                if (copyTree != null)
                {
                    char[] textCopy = copyContext.getText();

                    s.insert(
                        r, 1, copyTree, textCopy, 0, textCopy == null ? 0 : textCopy.length, true );
                }

                type.change_type( (SchemaType) types.get( i ) );
            }
        }
    }
    
    public void visit_elements ( TypeStoreVisitor visitor )
    {
       Splay s = getSplay();

        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue( s.isContainer() );
        
        if (!s.isContainer())
            throw new IllegalStateException();

        if (s.isLeaf())
            return;
        
        for ( s = s.nextSplay() ; ; s = s.nextSplay() )
        {
            switch ( s.getKind() )
            {
            case Splay.END :
                break;

            case Splay.BEGIN :
                visitor.visit( s.getName() );
                s = s.getFinishSplay();
                break;
            }
        }
    }

    public XmlObject[] exec_query ( String queryExpr, XmlOptions options )
        throws XmlException
    {
        return Path.query( this, queryExpr, options );
    }
    
    //
    //
    //
    
    /**
     * Returns the monitor object, used for synchronizing access to the doc.
     */
    public Object get_root_object()
    {
        return getRoot();
    }

    private final TypeStoreUser _user;
    private int _inhibitUserInvalidate;
}
