SchemaSetCompiler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Xml / System / Xml / schema / SchemaSetCompiler.cs / 1 / SchemaSetCompiler.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Xml.Schema { 

    using System; 
    using System.Collections;
    using System.Globalization;
    using System.Text;
    using System.Diagnostics; 

    internal sealed class Compiler : BaseProcessor { 
        string restrictionErrorMsg; 
        XmlSchemaObjectTable attributes = new XmlSchemaObjectTable();
        XmlSchemaObjectTable attributeGroups = new XmlSchemaObjectTable(); 
        XmlSchemaObjectTable elements = new XmlSchemaObjectTable();
        XmlSchemaObjectTable schemaTypes = new XmlSchemaObjectTable();
        XmlSchemaObjectTable groups = new XmlSchemaObjectTable();
        XmlSchemaObjectTable notations = new XmlSchemaObjectTable(); 
        XmlSchemaObjectTable examplars = new XmlSchemaObjectTable();
        XmlSchemaObjectTable identityConstraints = new XmlSchemaObjectTable(); 
        Stack complexTypeStack = new Stack(); 
        Hashtable schemasToCompile = new Hashtable();
        Hashtable importedSchemas = new Hashtable(); 

        XmlSchema schemaForSchema;

        public Compiler(XmlNameTable nameTable, ValidationEventHandler eventHandler, XmlSchema schemaForSchema, XmlSchemaCompilationSettings compilationSettings) : base(nameTable, null, eventHandler, compilationSettings) { 
            this.schemaForSchema = schemaForSchema;
        } 
 
        public bool Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo) {
            Compile(); 
            if (!HasErrors) {
                Output(schemaCompiledInfo);
                schemaSet.elements = elements;
                schemaSet.attributes = attributes; 
                schemaSet.schemaTypes = schemaTypes;
                schemaSet.substitutionGroups = examplars; 
            } 
            return !HasErrors;
        } 

        internal void Prepare(XmlSchema schema, bool cleanup) {
            if (schemasToCompile[schema] != null) {
                return; 
            }
            schemasToCompile.Add(schema, schema); 
            foreach (XmlSchemaElement element in schema.Elements.Values) { 
                if (cleanup) {
                    CleanupElement(element); 
                }
                AddToTable(elements, element.QualifiedName, element);
            }
            foreach (XmlSchemaAttribute attribute in schema.Attributes.Values) { 
                if (cleanup) {
                    CleanupAttribute(attribute); 
                } 
                AddToTable(attributes, attribute.QualifiedName, attribute);
            } 
            foreach (XmlSchemaGroup group in schema.Groups.Values) {
                if (cleanup) {
                    CleanupGroup(group);
                } 
                AddToTable(groups, group.QualifiedName, group);
            } 
            foreach (XmlSchemaAttributeGroup attributeGroup in schema.AttributeGroups.Values) { 
                if (cleanup) {
                    CleanupAttributeGroup(attributeGroup); 
                }
                AddToTable(attributeGroups, attributeGroup.QualifiedName, attributeGroup);
            }
            foreach (XmlSchemaType type in schema.SchemaTypes.Values) { 
                if (cleanup) {
                    XmlSchemaComplexType ct = type as XmlSchemaComplexType; 
                    if (ct != null) { 
                        CleanupComplexType(ct);
                    } 
                    else {
                        CleanupSimpleType(type as XmlSchemaSimpleType);
                    }
                } 
                AddToTable(schemaTypes, type.QualifiedName, type);
            } 
            foreach (XmlSchemaNotation notation in schema.Notations.Values) { 
                AddToTable(notations, notation.QualifiedName, notation);
            } 
            foreach (XmlSchemaIdentityConstraint ic in schema.IdentityConstraints.Values) {
                AddToTable(identityConstraints, ic.QualifiedName, ic);
            }
        } 

        private void UpdateSForSSimpleTypes() { 
            Debug.Assert(schemaForSchema != null); 
            XmlSchemaSimpleType[] schemaSimpleTypes = DatatypeImplementation.GetBuiltInTypes();
            XmlSchemaSimpleType builtInType; 
            //Using enumToTypeCode array; indexed by XmlTypeCode; Start indexing from 12 since schema types start there and iterate till Length - 2 as the last 2 are xquery types
            int numberOfSchemaTypes = schemaSimpleTypes.Length - 3; //skip last 2 xquery types
            for (int i = 12; i < numberOfSchemaTypes; i++) {
                builtInType = schemaSimpleTypes[i]; 
                schemaForSchema.SchemaTypes.Replace(builtInType.QualifiedName, builtInType);
                this.schemaTypes.Replace(builtInType.QualifiedName, builtInType); 
            } 
        }
 
        private void Output(SchemaInfo schemaInfo) {
            string tns;
            foreach(XmlSchema schema in schemasToCompile.Values) {
                tns = schema.TargetNamespace; 
                if (tns == null) {
                    tns = string.Empty; 
                } 
                schemaInfo.TargetNamespaces[tns] = tns;
            } 
            foreach (XmlSchemaElement element in elements.Values) {
                schemaInfo.ElementDecls.Add(element.QualifiedName, element.ElementDecl);
            }
            foreach (XmlSchemaAttribute attribute in attributes.Values) { 
                schemaInfo.AttributeDecls.Add(attribute.QualifiedName, attribute.AttDef);
            } 
            foreach (XmlSchemaType type in schemaTypes.Values) { 
                schemaInfo.ElementDeclsByType.Add(type.QualifiedName, type.ElementDecl);
            } 
            foreach (XmlSchemaNotation notation in notations.Values) {
                SchemaNotation no = new SchemaNotation(notation.QualifiedName);
                no.SystemLiteral = notation.System;
                no.Pubid = notation.Public; 
                if (schemaInfo.Notations[no.Name.Name] == null) {
                    schemaInfo.Notations.Add(no.Name.Name, no); 
                } 
            }
 
        }

        internal void ImportAllCompiledSchemas(XmlSchemaSet schemaSet) {
              XmlSchema currentSchema; 
              int schemaIndex;
              SortedList schemas = schemaSet.SortedSchemas; 
              for (schemaIndex = 0; schemaIndex < schemas.Count; schemaIndex++) { 
                  currentSchema = (XmlSchema)schemas.GetByIndex(schemaIndex);
                  if (currentSchema.IsCompiledBySet) { //Import already compiled schemas 
                    Prepare(currentSchema, false);
                  }
              }
        } 

        internal bool Compile() { 
            schemaTypes.Insert(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType); 
            if (schemaForSchema != null) { //Get our built-in types
                schemaForSchema.SchemaTypes.Replace(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType); 
                UpdateSForSSimpleTypes();
            }
            foreach(XmlSchemaGroup group in groups.Values) {
                CompileGroup(group); 
            }
            foreach(XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) { 
                CompileAttributeGroup(attributeGroup); 
            }
            foreach (XmlSchemaType type in schemaTypes.Values) { 
                XmlSchemaComplexType ct = type as XmlSchemaComplexType;
                if (ct != null) {
                    CompileComplexType(ct);
                } 
                else {
                    CompileSimpleType((XmlSchemaSimpleType)type); 
                } 
            }
            foreach (XmlSchemaElement element in elements.Values) { 
                if (element.ElementDecl == null) {
                    CompileElement(element);
                }
            } 
            foreach (XmlSchemaAttribute attribute in attributes.Values) {
                if (attribute.AttDef == null) { 
                    CompileAttribute(attribute); 
                }
            } 
            foreach (XmlSchemaIdentityConstraint identityConstraint in identityConstraints.Values) {
                if (identityConstraint.CompiledConstraint == null) {
                    CompileIdentityConstraint(identityConstraint);
                } 
            }
            while (this.complexTypeStack.Count > 0) { 
                XmlSchemaComplexType type = (XmlSchemaComplexType)complexTypeStack.Pop(); 
                CompileComplexTypeElements(type);
            } 

            ProcessSubstitutionGroups();

            foreach (XmlSchemaType type in schemaTypes.Values) { 
                XmlSchemaComplexType localType = type as XmlSchemaComplexType;
                if (localType != null) { 
                    CheckParticleDerivation(localType); 
                }
            } 

            foreach (XmlSchemaElement element in elements.Values) {
                XmlSchemaComplexType localComplexType = element.ElementSchemaType as XmlSchemaComplexType;
                if (localComplexType != null && element.SchemaTypeName == XmlQualifiedName.Empty) { // only local schemaTypes 
                    CheckParticleDerivation(localComplexType);
                } 
            } 
            foreach (XmlSchemaGroup group in groups.Values) { //Check particle derivation for redefined groups
                XmlSchemaGroup baseGroup = group.Redefined; 
                if (baseGroup != null) {
                    RecursivelyCheckRedefinedGroups(group, baseGroup);
                }
            } 

            foreach (XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) { 
                XmlSchemaAttributeGroup baseAttributeGroup = attributeGroup.Redefined; 
                if (baseAttributeGroup != null) {
                    RecursivelyCheckRedefinedAttributeGroups(attributeGroup, baseAttributeGroup); 
                }
            }
            return !HasErrors;
        } 

        private void CleanupAttribute(XmlSchemaAttribute attribute) { 
            if (attribute.SchemaType != null) { 
                CleanupSimpleType((XmlSchemaSimpleType)attribute.SchemaType);
            } 
            attribute.AttDef = null;
        }

        private void CleanupAttributeGroup(XmlSchemaAttributeGroup attributeGroup) { 
            CleanupAttributes(attributeGroup.Attributes);
            attributeGroup.AttributeUses.Clear(); 
            attributeGroup.AttributeWildcard = null; 
            if (attributeGroup.Redefined != null) {
                CleanupAttributeGroup(attributeGroup.Redefined); 
            }
        }

        private void CleanupComplexType(XmlSchemaComplexType complexType) { 
            if (complexType.QualifiedName == DatatypeImplementation.QnAnyType) { //if it is built-in anyType dont clean it.
                return; 
            } 
            if (complexType.ContentModel != null) { //simpleContent or complexContent
                if (complexType.ContentModel is XmlSchemaSimpleContent) { 
                    XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
                    if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
                        XmlSchemaSimpleContentExtension simpleExtension = (XmlSchemaSimpleContentExtension)simpleContent.Content;
                        CleanupAttributes(simpleExtension.Attributes); 
                    }
                    else { //simpleContent.Content is XmlSchemaSimpleContentRestriction 
                        XmlSchemaSimpleContentRestriction simpleRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content; 
                        CleanupAttributes(simpleRestriction.Attributes);
                    } 
                }
                else { // complexType.ContentModel is XmlSchemaComplexContent
                    XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
                    if (complexContent.Content is XmlSchemaComplexContentExtension) { 
                        XmlSchemaComplexContentExtension complexExtension = (XmlSchemaComplexContentExtension)complexContent.Content;
                        CleanupParticle(complexExtension.Particle); 
                        CleanupAttributes(complexExtension.Attributes); 

                    } 
                    else { //XmlSchemaComplexContentRestriction
                        XmlSchemaComplexContentRestriction complexRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content;
                        CleanupParticle(complexRestriction.Particle);
                        CleanupAttributes(complexRestriction.Attributes); 
                    }
                } 
            } 
            else { //equals XmlSchemaComplexContent with baseType is anyType
                CleanupParticle(complexType.Particle); 
                CleanupAttributes(complexType.Attributes);
            }
            complexType.LocalElements.Clear();
            complexType.AttributeUses.Clear(); 
            complexType.SetAttributeWildcard(null);
            complexType.SetContentTypeParticle(XmlSchemaParticle.Empty); 
            complexType.ElementDecl = null; 
            complexType.HasDuplicateDecls = false;
            complexType.HasWildCard = false; 

            //Clean up the original type if this is a redefined type
            if (complexType.Redefined != null) {
                CleanupComplexType(complexType.Redefined as XmlSchemaComplexType); 
            }
        } 
 
        private void CleanupSimpleType(XmlSchemaSimpleType simpleType) {
            if (simpleType == XmlSchemaType.GetBuiltInSimpleType(simpleType.TypeCode)) { //If it is a built-in simple type dont clean up 
                return;
            }
            simpleType.ElementDecl = null;
            //Clean up the original group if this is a redefined group 
            if (simpleType.Redefined != null) {
                CleanupSimpleType(simpleType.Redefined as XmlSchemaSimpleType); 
            } 
        }
 
        private void CleanupElement(XmlSchemaElement element) {
            if (element.SchemaType != null) {
                XmlSchemaComplexType complexType = element.SchemaType as XmlSchemaComplexType;
                if (complexType != null) { 
                    CleanupComplexType(complexType);
                } 
                else { 
                    CleanupSimpleType((XmlSchemaSimpleType)element.SchemaType);
                } 
            }
            foreach (XmlSchemaIdentityConstraint constr in element.Constraints) {
                constr.CompiledConstraint = null;
            } 
            element.ElementDecl = null;
            element.IsLocalTypeDerivationChecked = false; //clear Local element type derivation check 
        } 

        private void CleanupAttributes(XmlSchemaObjectCollection attributes) { 
            foreach (XmlSchemaObject obj in attributes) {
                if (obj is XmlSchemaAttribute) {
                    CleanupAttribute((XmlSchemaAttribute)obj);
                } 
            }
        } 
 
        private void CleanupGroup(XmlSchemaGroup group) {
            CleanupParticle(group.Particle); 
            group.CanonicalParticle = null;
            //Clean up the original group if this is a redefined group
            if (group.Redefined != null) {
                CleanupGroup(group.Redefined); 
            }
        } 
 
        private void CleanupParticle(XmlSchemaParticle particle) {
            if (particle is XmlSchemaElement) { 
                CleanupElement((XmlSchemaElement)particle);
            }
            else if (particle is XmlSchemaGroupBase) {
                foreach(XmlSchemaParticle p in ((XmlSchemaGroupBase)particle).Items) { 
                    CleanupParticle(p);
                } 
            } 
        }
 
        private void ProcessSubstitutionGroups() {
            foreach (XmlSchemaElement element in this.elements.Values) {
                if (!element.SubstitutionGroup.IsEmpty) {
                    XmlSchemaElement headElement = this.elements[element.SubstitutionGroup] as XmlSchemaElement; 
                    if (headElement == null) {
                        SendValidationEvent(Res.Sch_NoExamplar, element); 
                        continue; 
                    }
                    //Check derivation of member's type against head's type 
                    if (!XmlSchemaType.IsDerivedFrom(element.ElementSchemaType, headElement.ElementSchemaType, headElement.FinalResolved)) {
                        SendValidationEvent(Res.Sch_InvalidSubstitutionMember, (element.QualifiedName).ToString(), (headElement.QualifiedName).ToString(), element);
                    }
                    if ((headElement.BlockResolved & XmlSchemaDerivationMethod.Substitution) != 0) { //head element blocks substitution, dont build substGroup 
                        continue;
                    } 
                    //Create substitutionGroup 
                    XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)this.examplars[element.SubstitutionGroup];
                    if (substitutionGroup == null) { 
                        substitutionGroup = new XmlSchemaSubstitutionGroup();
                        substitutionGroup.Examplar = element.SubstitutionGroup;
                        examplars.Add(element.SubstitutionGroup, substitutionGroup);
                    } 
                    ArrayList members = substitutionGroup.Members;
                    if (!members.Contains(element)) { //Members might contain element if the same schema is included and imported through different paths. Imp, hence will be added to set directly 
                        members.Add(element); 
                    }
                } 
            }

            //Check the subst groups that we just built
            foreach (XmlSchemaSubstitutionGroup substitutionGroup in examplars.Values) { 
                CompileSubstitutionGroup(substitutionGroup);
            } 
        } 
        private void CompileSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup) {
            if (substitutionGroup.IsProcessing) { 
                foreach (XmlSchemaElement element in substitutionGroup.Members) {
                    SendValidationEvent(Res.Sch_SubstitutionCircularRef, element);
                    return;
                } 
            }
            XmlSchemaElement examplar = (XmlSchemaElement)elements[substitutionGroup.Examplar]; 
            Debug.Assert(examplar != null); //Headelement presence is checked while building subst groups 
            if (substitutionGroup.Members.Contains(examplar)) {// already checked
                return; 
            }
            substitutionGroup.IsProcessing = true;
            try {
                if (examplar.FinalResolved == XmlSchemaDerivationMethod.All) { 
                    SendValidationEvent(Res.Sch_InvalidExamplar, examplar);
                } 
                //Build transitive members 
                ArrayList newMembers = null;
                foreach (XmlSchemaElement element in substitutionGroup.Members) { 
                    //Chain to other head's that are members of this head's substGroup
                    XmlSchemaSubstitutionGroup g = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName];
                    if (g != null) {
                        CompileSubstitutionGroup(g); 
                        foreach (XmlSchemaElement element1 in g.Members) {
                            if (element1 != element) { //Exclude the head 
                                if (newMembers == null) { 
                                    newMembers = new ArrayList();
                                } 
                                newMembers.Add(element1);
                            }
                        }
                    } 
                }
                if (newMembers != null) { 
                    foreach (XmlSchemaElement newMember in newMembers) { 
                        substitutionGroup.Members.Add(newMember);
                    } 
                }
                substitutionGroup.Members.Add(examplar); // Compiled mark
            }
            finally { 
                substitutionGroup.IsProcessing = false;
            } 
        } 

        private void RecursivelyCheckRedefinedGroups(XmlSchemaGroup redefinedGroup, XmlSchemaGroup baseGroup) { 
            if (baseGroup.Redefined != null) {
                RecursivelyCheckRedefinedGroups(baseGroup, baseGroup.Redefined);
            }
            if (redefinedGroup.SelfReferenceCount == 0) { 
                if (baseGroup.CanonicalParticle == null) {
                    baseGroup.CanonicalParticle = CannonicalizeParticle(baseGroup.Particle, true); 
                } 
                if (redefinedGroup.CanonicalParticle == null) {
                    redefinedGroup.CanonicalParticle = CannonicalizeParticle(redefinedGroup.Particle, true); 
                }
                CompileParticleElements(redefinedGroup.CanonicalParticle);
                CompileParticleElements(baseGroup.CanonicalParticle);
                CheckParticleDerivation(redefinedGroup.CanonicalParticle, baseGroup.CanonicalParticle); 
            }
        } 
 
        private void RecursivelyCheckRedefinedAttributeGroups(XmlSchemaAttributeGroup attributeGroup, XmlSchemaAttributeGroup baseAttributeGroup) {
            if (baseAttributeGroup.Redefined != null) { 
                RecursivelyCheckRedefinedAttributeGroups(baseAttributeGroup, baseAttributeGroup.Redefined);
            }
            if (attributeGroup.SelfReferenceCount == 0) {
                CompileAttributeGroup(baseAttributeGroup); 
                CompileAttributeGroup(attributeGroup);
                CheckAtrributeGroupRestriction(baseAttributeGroup, attributeGroup); 
            } 
        }
 
        private void CompileGroup(XmlSchemaGroup group) {
            if (group.IsProcessing) {
                SendValidationEvent(Res.Sch_GroupCircularRef, group);
                group.CanonicalParticle = XmlSchemaParticle.Empty; 
            }
            else { 
                group.IsProcessing = true; 
                if (group.CanonicalParticle == null) {
                    group.CanonicalParticle = CannonicalizeParticle(group.Particle, true); 
                }
                Debug.Assert(group.CanonicalParticle != null);
                group.IsProcessing = false; //Not enclosung in try -finally as cannonicalizeParticle will not throw exception
            } 
        }
 
        private void CompileSimpleType(XmlSchemaSimpleType simpleType) { 
            if (simpleType.IsProcessing) {
                throw new XmlSchemaException(Res.Sch_TypeCircularRef, simpleType); 
            }
            if (simpleType.ElementDecl != null) { // already compiled
                return;
            } 
            simpleType.IsProcessing = true;
            try { 
                if (simpleType.Content is XmlSchemaSimpleTypeList) { 
                    XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)simpleType.Content;
                    XmlSchemaDatatype datatype; 
                    simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType);
                    if (list.ItemTypeName.IsEmpty) {
                        CompileSimpleType(list.ItemType);
                        list.BaseItemType = list.ItemType; 
                        datatype = list.ItemType.Datatype;
                    } 
                    else { 
                        XmlSchemaSimpleType type = GetSimpleType(list.ItemTypeName);
                        if (type != null) { 
                            if ((type.FinalResolved & XmlSchemaDerivationMethod.List) != 0) {
                                SendValidationEvent(Res.Sch_BaseFinalList, simpleType);
                            }
                            list.BaseItemType = type; 
                            datatype = type.Datatype;
                        } 
                        else { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, list.ItemTypeName.ToString(), list);
                        } 
                    }
                    simpleType.SetDatatype(datatype.DeriveByList(simpleType));
                    simpleType.SetDerivedBy(XmlSchemaDerivationMethod.List);
                } 
                else if (simpleType.Content is XmlSchemaSimpleTypeRestriction) {
                    XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content; 
                    XmlSchemaDatatype datatype; 
                    if (restriction.BaseTypeName.IsEmpty) {
                        CompileSimpleType(restriction.BaseType); 
                        simpleType.SetBaseSchemaType(restriction.BaseType);
                        datatype = restriction.BaseType.Datatype;
                    }
                    else if (simpleType.Redefined != null && restriction.BaseTypeName == simpleType.Redefined.QualifiedName) { 
                        CompileSimpleType((XmlSchemaSimpleType)simpleType.Redefined);
                        simpleType.SetBaseSchemaType(simpleType.Redefined.BaseXmlSchemaType); 
                        datatype = simpleType.Redefined.Datatype; 
                    }
                    else { 
                        if (restriction.BaseTypeName.Equals(DatatypeImplementation.QnAnySimpleType)) {
                            XmlSchema parentSchema = Preprocessor.GetParentSchema(simpleType);
                            if (parentSchema.TargetNamespace != XmlSchema.Namespace) { //If it is not SForS, then error
                                throw new XmlSchemaException(Res.Sch_InvalidSimpleTypeRestriction, restriction.BaseTypeName.ToString(), simpleType); 
                            }
                        } 
                        XmlSchemaSimpleType type = GetSimpleType(restriction.BaseTypeName); 
                        if (type != null) {
                            if ((type.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) { 
                                SendValidationEvent(Res.Sch_BaseFinalRestriction, simpleType);
                            }
                            simpleType.SetBaseSchemaType(type);
                            datatype = type.Datatype; 
                        }
                        else { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, restriction.BaseTypeName.ToString(), restriction); 
                        }
                    } 
                    simpleType.SetDatatype(datatype.DeriveByRestriction(restriction.Facets, NameTable, simpleType));
                    simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
                }
                else { //simpleType.Content is XmlSchemaSimpleTypeUnion 
                    XmlSchemaSimpleType[] baseTypes = CompileBaseMemberTypes(simpleType);
                    simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType); 
                    simpleType.SetDatatype(XmlSchemaDatatype.DeriveByUnion(baseTypes, simpleType)); 
                    simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Union);
                } 
            }
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) {
                    e.SetSource(simpleType); 
                }
                SendValidationEvent(e); 
                simpleType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype); 
            }
            finally { 
                SchemaElementDecl decl = new SchemaElementDecl();
                decl.ContentValidator = ContentValidator.TextOnly;
                decl.SchemaType = simpleType;
                decl.Datatype = simpleType.Datatype; 
                simpleType.ElementDecl = decl;
                simpleType.IsProcessing = false; 
            } 
        }
 
        private XmlSchemaSimpleType[] CompileBaseMemberTypes(XmlSchemaSimpleType simpleType) {
            XmlSchemaSimpleType unionMember;
            ArrayList memberTypeDefinitions = new ArrayList();
 
            XmlSchemaSimpleTypeUnion mainUnion = (XmlSchemaSimpleTypeUnion)simpleType.Content;
 
            Array mainMemberTypes = mainUnion.MemberTypes; 
            if (mainMemberTypes != null) {
                foreach(XmlQualifiedName memberName in mainMemberTypes) { 
                    unionMember = GetSimpleType(memberName);
                    if (unionMember != null) {
                        if (unionMember.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
                            CheckUnionType(unionMember, memberTypeDefinitions, simpleType); 
                        }
                        else { //its list or atomic 
                            memberTypeDefinitions.Add(unionMember); 
                        }
                        //Check derivation method of the member that is referenced 
                        if ((unionMember.FinalResolved & XmlSchemaDerivationMethod.Union) != 0) {
                            SendValidationEvent(Res.Sch_BaseFinalUnion, simpleType);
                        }
                    } 
                    else {
                        throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, memberName.ToString(), mainUnion); 
                    } 
                }
            } 

            //Now add the baseTypes that are defined inside the union itself
            XmlSchemaObjectCollection mainBaseTypes = mainUnion.BaseTypes; //
            if (mainBaseTypes != null) { 
                foreach(XmlSchemaSimpleType st in mainBaseTypes) {
                    CompileSimpleType(st); 
                    if (st.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union 
                        CheckUnionType(st, memberTypeDefinitions, simpleType);
                    } 
                    else {  //its list or atomic
                        memberTypeDefinitions.Add(st);
                    }
                } 
            }
            //set all types 
            mainUnion.SetBaseMemberTypes(memberTypeDefinitions.ToArray(typeof(XmlSchemaSimpleType)) as XmlSchemaSimpleType[]); 
            return mainUnion.BaseMemberTypes;
        } 

        private void CheckUnionType(XmlSchemaSimpleType unionMember, ArrayList memberTypeDefinitions, XmlSchemaSimpleType parentType) {
            XmlSchemaDatatype unionDatatype = unionMember.Datatype;
            if (unionMember.DerivedBy == XmlSchemaDerivationMethod.Restriction && (unionDatatype.HasLexicalFacets || unionDatatype.HasValueFacets) ) { 
                SendValidationEvent(Res.Sch_UnionFromUnion, parentType);
            } 
            else { 
                Datatype_union uniondt = unionMember.Datatype as Datatype_union;
                memberTypeDefinitions.AddRange(uniondt.BaseMemberTypes); 
            }
        }

        private void CompileComplexType(XmlSchemaComplexType complexType) { 
            if (complexType.ElementDecl != null) { //already compiled
                return; 
            } 
            if (complexType.IsProcessing) {
                SendValidationEvent(Res.Sch_TypeCircularRef, complexType); 
                return;
            }
            complexType.IsProcessing = true;
            try { 
                if (complexType.ContentModel != null) { //simpleContent or complexContent
                    if (complexType.ContentModel is XmlSchemaSimpleContent) { 
                        XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel; 
                        complexType.SetContentType(XmlSchemaContentType.TextOnly);
                        if (simpleContent.Content is XmlSchemaSimpleContentExtension) { 
                            CompileSimpleContentExtension(complexType, (XmlSchemaSimpleContentExtension)simpleContent.Content);
                        }
                        else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
                            CompileSimpleContentRestriction(complexType, (XmlSchemaSimpleContentRestriction)simpleContent.Content); 
                        }
                    } 
                    else { // complexType.ContentModel is XmlSchemaComplexContent 
                        XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
                        if (complexContent.Content is XmlSchemaComplexContentExtension) { 
                            CompileComplexContentExtension(complexType, complexContent, (XmlSchemaComplexContentExtension)complexContent.Content);
                        }
                        else { // complexContent.Content is XmlSchemaComplexContentRestriction
                            CompileComplexContentRestriction(complexType, complexContent, (XmlSchemaComplexContentRestriction)complexContent.Content); 
                        }
                    } 
                } 
                else { //equals XmlSchemaComplexContent with baseType is anyType
                        complexType.SetBaseSchemaType(XmlSchemaComplexType.AnyType); 
                        CompileLocalAttributes(XmlSchemaComplexType.AnyType, complexType, complexType.Attributes, complexType.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
                        complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
                        complexType.SetContentTypeParticle(CompileContentTypeParticle(complexType.Particle));
                        complexType.SetContentType(GetSchemaContentType(complexType, null, complexType.ContentTypeParticle)); 
                }
                if (complexType.ContainsIdAttribute(true)) { 
                    SendValidationEvent(Res.Sch_TwoIdAttrUses, complexType); 
                }
                SchemaElementDecl decl = new SchemaElementDecl(); 
                decl.ContentValidator = CompileComplexContent(complexType);
                decl.SchemaType = complexType;
                decl.IsAbstract = complexType.IsAbstract;
                decl.Datatype = complexType.Datatype; 
                decl.Block = complexType.BlockResolved;
                decl.AnyAttribute = complexType.AttributeWildcard; 
                foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) { 
                    if (attribute.Use == XmlSchemaUse.Prohibited) {
                        if (decl.ProhibitedAttributes[attribute.QualifiedName] == null) { 
                            decl.ProhibitedAttributes.Add(attribute.QualifiedName, attribute.QualifiedName);
                        }
                    }
                    else { 
                        if (decl.AttDefs[attribute.QualifiedName] == null && attribute.AttDef != null && attribute.AttDef.Name != XmlQualifiedName.Empty && attribute.AttDef != SchemaAttDef.Empty) {
                            decl.AddAttDef(attribute.AttDef); 
                        } 
                    }
                } 
                decl.EndAddAttDef();
                complexType.ElementDecl = decl;
            }
            finally { 
                complexType.IsProcessing = false;
            } 
        } 

 
        private void CompileSimpleContentExtension(XmlSchemaComplexType complexType, XmlSchemaSimpleContentExtension simpleExtension) {
            XmlSchemaComplexType baseType = null;
            if (complexType.Redefined != null && simpleExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
                baseType = (XmlSchemaComplexType)complexType.Redefined; 
                CompileComplexType(baseType);
                complexType.SetBaseSchemaType(baseType); 
                complexType.SetDatatype(baseType.Datatype); 
            }
            else { 
                XmlSchemaType bto = GetAnySchemaType(simpleExtension.BaseTypeName);
                if (bto == null) {
                    SendValidationEvent(Res.Sch_UndeclaredType, simpleExtension.BaseTypeName.ToString(), simpleExtension);
                } 
                else {
                    complexType.SetBaseSchemaType(bto); 
                    complexType.SetDatatype(bto.Datatype); 
                }
                baseType = bto as XmlSchemaComplexType; 
            }
            if (baseType != null) {
                if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
                    SendValidationEvent(Res.Sch_BaseFinalExtension, complexType); 
                }
                if (baseType.ContentType != XmlSchemaContentType.TextOnly) { 
                    SendValidationEvent(Res.Sch_NotSimpleContent, complexType); 
                }
            } 
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
            CompileLocalAttributes(baseType, complexType, simpleExtension.Attributes, simpleExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
        }
 
        private void CompileSimpleContentRestriction(XmlSchemaComplexType complexType, XmlSchemaSimpleContentRestriction simpleRestriction) {
            XmlSchemaComplexType baseType = null; 
            XmlSchemaDatatype datatype = null; 
            if (complexType.Redefined != null && simpleRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
                baseType = (XmlSchemaComplexType)complexType.Redefined; 
                CompileComplexType(baseType);
                datatype = baseType.Datatype;
            }
            else { 
                baseType = GetComplexType(simpleRestriction.BaseTypeName);
                if (baseType == null) { 
                    SendValidationEvent(Res.Sch_UndefBaseRestriction, simpleRestriction.BaseTypeName.ToString(), simpleRestriction); 
                    return;
                } 
                if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
                    if (simpleRestriction.BaseType == null) {
                        datatype = baseType.Datatype;
                        //There is a bug here. Need to check if simpleRestriction has facets. 
                        //If yes, Need tp apply these facets as well.
                    } 
                    else { 
                        CompileSimpleType(simpleRestriction.BaseType);
                        if(!XmlSchemaType.IsDerivedFromDatatype(simpleRestriction.BaseType.Datatype, baseType.Datatype, XmlSchemaDerivationMethod.None)) { 
                           SendValidationEvent(Res.Sch_DerivedNotFromBase, simpleRestriction);
                        }
                        datatype = simpleRestriction.BaseType.Datatype;
                    } 
                }
                else if (baseType.ContentType == XmlSchemaContentType.Mixed && baseType.ElementDecl.ContentValidator.IsEmptiable) { 
                    if (simpleRestriction.BaseType != null) { 
                        CompileSimpleType(simpleRestriction.BaseType);
                        complexType.SetBaseSchemaType(simpleRestriction.BaseType); 
                        datatype = simpleRestriction.BaseType.Datatype;
                    }
                    else {
                        SendValidationEvent(Res.Sch_NeedSimpleTypeChild, simpleRestriction); 
                    }
                } 
                else { 
                    SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
                } 
            }
            if (baseType != null && baseType.ElementDecl != null) {
                if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
                    SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType); 
                }
            } 
            if (baseType != null) { 
                complexType.SetBaseSchemaType(baseType);
            } 
            if (datatype != null) {
                try {
                    complexType.SetDatatype(datatype.DeriveByRestriction(simpleRestriction.Facets, NameTable, complexType));
                } 
                catch (XmlSchemaException e) {
                    if (e.SourceSchemaObject == null) { 
                        e.SetSource(complexType); 
                    }
                    SendValidationEvent(e); 
                    complexType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
                }
            }
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction); 
            CompileLocalAttributes(baseType, complexType, simpleRestriction.Attributes, simpleRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
        } 
 
        private void CompileComplexContentExtension(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentExtension complexExtension) {
            XmlSchemaComplexType baseType = null; 
            if (complexType.Redefined != null && complexExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
                baseType = (XmlSchemaComplexType)complexType.Redefined;
                CompileComplexType(baseType);
            } 
            else {
                baseType = GetComplexType(complexExtension.BaseTypeName); 
                if (baseType == null) { 
                    SendValidationEvent(Res.Sch_UndefBaseExtension, complexExtension.BaseTypeName.ToString(), complexExtension);
                    return; 
                }
            }
            if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
                SendValidationEvent(Res.Sch_BaseFinalExtension, complexType); 
            }
            CompileLocalAttributes(baseType, complexType, complexExtension.Attributes, complexExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension); 
 
            XmlSchemaParticle baseParticle = baseType.ContentTypeParticle;
            XmlSchemaParticle extendedParticle = CannonicalizeParticle(complexExtension.Particle, true); 
            if (baseParticle != XmlSchemaParticle.Empty) {
                if (extendedParticle != XmlSchemaParticle.Empty) {
                    XmlSchemaSequence compiledParticle = new XmlSchemaSequence();
                    compiledParticle.Items.Add(baseParticle); 
                    compiledParticle.Items.Add(extendedParticle);
                    complexType.SetContentTypeParticle(CompileContentTypeParticle(compiledParticle)); 
                } 
                else {
                    complexType.SetContentTypeParticle(baseParticle); 
                }
            }
            else {
                complexType.SetContentTypeParticle(extendedParticle); 
            }
            XmlSchemaContentType contentType = GetSchemaContentType(complexType, complexContent, extendedParticle); 
            if (contentType == XmlSchemaContentType.Empty) { //Derived content type is empty, Get ContentType from base 
                contentType = baseType.ContentType;
            } 
            complexType.SetContentType(contentType);

            if (baseType.ContentType != XmlSchemaContentType.Empty && complexType.ContentType != baseType.ContentType) { //If base is empty, do not check
                SendValidationEvent(Res.Sch_DifContentType, complexType); 
                return;
            } 
            complexType.SetBaseSchemaType(baseType); 
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
        } 

        private void CompileComplexContentRestriction(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentRestriction complexRestriction) {
            XmlSchemaComplexType baseType = null;
            if (complexType.Redefined != null && complexRestriction.BaseTypeName == complexType.Redefined.QualifiedName) { 
                baseType = (XmlSchemaComplexType)complexType.Redefined;
                CompileComplexType(baseType); 
            } 
            else {
                baseType = GetComplexType(complexRestriction.BaseTypeName); 
                if (baseType == null) {
                    SendValidationEvent(Res.Sch_UndefBaseRestriction, complexRestriction.BaseTypeName.ToString(), complexRestriction);
                    return;
                } 
            }
            complexType.SetBaseSchemaType(baseType); 
            if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) { 
                SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
            } 
            CompileLocalAttributes(baseType, complexType, complexRestriction.Attributes, complexRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);

            complexType.SetContentTypeParticle(CompileContentTypeParticle(complexRestriction.Particle));
            XmlSchemaContentType derivedContentType = GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle); 
            complexType.SetContentType(derivedContentType);
            switch(derivedContentType) { 
                case XmlSchemaContentType.Empty: 
                    if (baseType.ElementDecl != null && !baseType.ElementDecl.ContentValidator.IsEmptiable) { //base is either TextOnly or its ElementOnly/Mixed and not emptiable
                        SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToEmpty), complexType); 
                    }
                break;

                case XmlSchemaContentType.Mixed: 
                    if (baseType.ContentType != XmlSchemaContentType.Mixed) {
                        SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToMixed), complexType); 
                    } 
                break;
            } 
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
        }

        private void CheckParticleDerivation(XmlSchemaComplexType complexType) { 
            XmlSchemaComplexType baseType = complexType.BaseXmlSchemaType as XmlSchemaComplexType;
            restrictionErrorMsg = null; 
            if (baseType != null && baseType != XmlSchemaComplexType.AnyType && complexType.DerivedBy == XmlSchemaDerivationMethod.Restriction) { 
                XmlSchemaParticle derivedParticle = CannonicalizePointlessRoot(complexType.ContentTypeParticle);
                XmlSchemaParticle baseParticle = CannonicalizePointlessRoot(baseType.ContentTypeParticle); 
                if (!IsValidRestriction(derivedParticle, baseParticle)) {
#if DEBUG
                    if(complexType.ContentTypeParticle != null && baseType.ContentTypeParticle != null) {
                        string position = string.Empty; 
                        if (complexType.SourceUri != null) {
                            position = " in " + complexType.SourceUri + "(" + complexType.LineNumber + ", " + complexType.LinePosition + ")"; 
                        } 
                        Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType content restriction" + position);
                        Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpContentModel(baseType.ContentTypeParticle)); 
                        Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpContentModel(complexType.ContentTypeParticle));
                    }
#endif
                    if (restrictionErrorMsg != null) { 
                        SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, complexType);
                    } 
                    else { 
                        SendValidationEvent(Res.Sch_InvalidParticleRestriction, complexType);
                    } 
                }
            }
            else if (baseType == XmlSchemaComplexType.AnyType) { //The complex type itself is not explicitly derived by restriction but it could have local elements which have anonymous types that are derived by restriction
                foreach(XmlSchemaElement localElement in complexType.LocalElements.Values) { 
                    if (localElement.IsLocalTypeDerivationChecked) { //Element already checked
                        continue; 
                    } 
                    XmlSchemaComplexType localComplexType = localElement.ElementSchemaType as XmlSchemaComplexType;
                    if (localComplexType != null && localElement.SchemaTypeName == XmlQualifiedName.Empty && localElement.RefName == XmlQualifiedName.Empty) { //Only local elements 
                        localElement.IsLocalTypeDerivationChecked = true; //Not clearing this flag after recursion to make sure this check is not repeated for multiple references of the same local element (through group refs)
                        CheckParticleDerivation(localComplexType);
                    }
                } 
            }
        } 
 
        private void CheckParticleDerivation(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
            restrictionErrorMsg = null; 
            derivedParticle = CannonicalizePointlessRoot(derivedParticle);
            baseParticle = CannonicalizePointlessRoot(baseParticle);
            if (!IsValidRestriction(derivedParticle, baseParticle)) {
                if (restrictionErrorMsg != null) { 
                    SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, derivedParticle);
                } 
                else { 
                    SendValidationEvent(Res.Sch_InvalidParticleRestriction, derivedParticle);
                } 
            }
        }

        private XmlSchemaParticle CompileContentTypeParticle(XmlSchemaParticle particle) { 
            XmlSchemaParticle ctp = CannonicalizeParticle(particle, true);
            XmlSchemaChoice choice = ctp as XmlSchemaChoice; 
            if (choice != null && choice.Items.Count == 0) { 
                if (choice.MinOccurs != decimal.Zero) {
                    SendValidationEvent(Res.Sch_EmptyChoice, choice, XmlSeverityType.Warning); 
                }
                return XmlSchemaParticle.Empty;
            }
            return ctp; 
        }
 
        private XmlSchemaParticle CannonicalizeParticle(XmlSchemaParticle particle, bool root) { 
            if (particle == null || particle.IsEmpty) {
                return XmlSchemaParticle.Empty; 
            }
            else if (particle is XmlSchemaElement) {
                //return CannonicalizeElement((XmlSchemaElement)particle, substitution);
                return particle; 
            }
            else if (particle is XmlSchemaGroupRef) { 
                return CannonicalizeGroupRef((XmlSchemaGroupRef)particle, root); 
            }
            else if (particle is XmlSchemaAll) { 
                return CannonicalizeAll((XmlSchemaAll)particle, root);
            }
            else if (particle is XmlSchemaChoice) {
                return CannonicalizeChoice((XmlSchemaChoice)particle, root); 
            }
            else if (particle is XmlSchemaSequence) { 
                return CannonicalizeSequence((XmlSchemaSequence)particle, root); 
            }
            else { 
                return particle;
            }
        }
 
        private XmlSchemaParticle CannonicalizeElement(XmlSchemaElement element) {
            if (!element.RefName.IsEmpty && (element.ElementDecl.Block & XmlSchemaDerivationMethod.Substitution) == 0) { 
                XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName]; 
                if (substitutionGroup == null) {
                    return element; 
                }
                else {
                    XmlSchemaChoice choice = new XmlSchemaChoice();
                    foreach(XmlSchemaElement elem in substitutionGroup.Members) { 
                        choice.Items.Add(elem);
                    } 
                    choice.MinOccurs = element.MinOccurs; 
                    choice.MaxOccurs = element.MaxOccurs;
                    CopyPosition(choice, element, false); 
                    return choice;
                }
            }
            else { 
                return element;
            } 
        } 

        private XmlSchemaParticle CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root) { 
            XmlSchemaGroup group;
            if (groupRef.Redefined != null) {
                group = groupRef.Redefined;
            } 
            else {
                group = (XmlSchemaGroup)groups[groupRef.RefName]; 
            } 
            if (group == null) {
                SendValidationEvent(Res.Sch_UndefGroupRef, groupRef.RefName.ToString(), groupRef); 
                return XmlSchemaParticle.Empty;
            }
            if (group.CanonicalParticle == null) {
                CompileGroup(group); 
            }
            if (group.CanonicalParticle == XmlSchemaParticle.Empty) { 
                return XmlSchemaParticle.Empty; 
            }
            XmlSchemaGroupBase groupBase = (XmlSchemaGroupBase)group.CanonicalParticle; 
            if (groupBase is XmlSchemaAll) {
                if (!root) {
                    SendValidationEvent(Res.Sch_AllRefNotRoot, "", groupRef);
                    return XmlSchemaParticle.Empty; 
                }
                if (groupRef.MinOccurs > decimal.One || groupRef.MaxOccurs != decimal.One) { 
                    SendValidationEvent(Res.Sch_AllRefMinMax, groupRef); 
                    return XmlSchemaParticle.Empty;
                } 
            }
            else if (groupBase is XmlSchemaChoice && groupBase.Items.Count == 0) {
                if (groupRef.MinOccurs != decimal.Zero) {
                    SendValidationEvent(Res.Sch_EmptyChoice, groupRef, XmlSeverityType.Warning); 
                }
                return XmlSchemaParticle.Empty; 
            } 
            XmlSchemaGroupBase groupRefBase = (
                (groupBase is XmlSchemaSequence) ? (XmlSchemaGroupBase)new XmlSchemaSequence() : 
                (groupBase is XmlSchemaChoice)   ? (XmlSchemaGroupBase)new XmlSchemaChoice() :
                                                   (XmlSchemaGroupBase)new XmlSchemaAll()
            );
            groupRefBase.MinOccurs = groupRef.MinOccurs; 
            groupRefBase.MaxOccurs = groupRef.MaxOccurs;
            groupRefBase.LineNumber = groupRef.LineNumber; 
            groupRefBase.LinePosition = groupRef.LinePosition; 

            foreach (XmlSchemaParticle particle in groupBase.Items) { 
                groupRefBase.Items.Add(particle);
            }
            groupRef.SetParticle(groupRefBase);
            return groupRefBase; 
        }
 
        private XmlSchemaParticle CannonicalizeAll(XmlSchemaAll all, bool root) { 
            if (all.Items.Count > 0) {
                XmlSchemaAll newAll = new XmlSchemaAll(); 
                newAll.MinOccurs = all.MinOccurs;
                newAll.MaxOccurs = all.MaxOccurs;
                CopyPosition(newAll, all, true);
                foreach (XmlSchemaElement e in all.Items) { 
                    XmlSchemaParticle p = CannonicalizeParticle(e, false);
                    if (p != XmlSchemaParticle.Empty) { 
                        newAll.Items.Add(p); 
                    }
                } 
                all = newAll;
            }
            if (all.Items.Count == 0) {
                return XmlSchemaParticle.Empty; 
            }
            else if (!root) { 
                SendValidationEvent(Res.Sch_NotAllAlone, all); 
                return XmlSchemaParticle.Empty;
            } 
            else {
                return all;
            }
        } 

        private XmlSchemaParticle CannonicalizeChoice(XmlSchemaChoice choice, bool root) { 
            XmlSchemaChoice oldChoice = choice; 
            if (choice.Items.Count > 0) {
                XmlSchemaChoice newChoice = new XmlSchemaChoice(); 
                newChoice.MinOccurs = choice.MinOccurs;
                newChoice.MaxOccurs = choice.MaxOccurs;
                CopyPosition(newChoice, choice, true);
                foreach (XmlSchemaParticle p in choice.Items) { 
                    XmlSchemaParticle p1 = CannonicalizeParticle(p, false);
                    if (p1 != XmlSchemaParticle.Empty) { 
                        if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaChoice) { 
                            foreach (XmlSchemaParticle p2 in ((XmlSchemaChoice)p1).Items) {
                                newChoice.Items.Add(p2); 
                            }
                        }
                        else {
                            newChoice.Items.Add(p1); 
                        }
                    } 
                } 
                choice = newChoice;
            } 
            if (!root && choice.Items.Count == 0) {
                if (choice.MinOccurs != decimal.Zero) {
                    SendValidationEvent(Res.Sch_EmptyChoice, oldChoice, XmlSeverityType.Warning);
                } 
                return XmlSchemaParticle.Empty;
            } 
            else if (!root && choice.Items.Count == 1 && choice.MinOccurs == decimal.One && choice.MaxOccurs == decimal.One) { 
                return (XmlSchemaParticle)choice.Items[0];
            } 
            else {
                return choice;
            }
        } 

        private XmlSchemaParticle CannonicalizeSequence(XmlSchemaSequence sequence, bool root) { 
            if (sequence.Items.Count > 0) { 
                XmlSchemaSequence newSequence = new XmlSchemaSequence();
                newSequence.MinOccurs = sequence.MinOccurs; 
                newSequence.MaxOccurs = sequence.MaxOccurs;
                CopyPosition(newSequence, sequence, true);
                foreach (XmlSchemaParticle p in sequence.Items) {
                    XmlSchemaParticle p1 = CannonicalizeParticle(p, false); 
                    if (p1 != XmlSchemaParticle.Empty) {
                        if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaSequence) { 
                            foreach (XmlSchemaParticle p2 in ((XmlSchemaSequence)p1).Items) { 
                                newSequence.Items.Add(p2);
                            } 
                        }
                        else {
                            newSequence.Items.Add(p1);
                        } 
                    }
                } 
                sequence = newSequence; 
            }
            if (sequence.Items.Count == 0) { 
                return XmlSchemaParticle.Empty;
            }
            else if (!root && sequence.Items.Count == 1 && sequence.MinOccurs == decimal.One && sequence.MaxOccurs == decimal.One) {
                return (XmlSchemaParticle)sequence.Items[0]; 
            }
            else { 
                return sequence; 
            }
        } 

        private XmlSchemaParticle CannonicalizePointlessRoot(XmlSchemaParticle particle) {
            if (particle == null) {
                return null; 
            }
            XmlSchemaSequence xss; 
            XmlSchemaChoice xsc; 
            XmlSchemaAll xsa;
            decimal one = decimal.One; 
            if ( (xss = (particle as XmlSchemaSequence)) != null ) {
                XmlSchemaObjectCollection items = xss.Items;
                int count = items.Count;
                if (count == 1) { 
                    if (xss.MinOccurs == one && xss.MaxOccurs == one) {
                        return (XmlSchemaParticle)items[0]; 
                    } 
                }
            } 
            else if ( (xsc = (particle as XmlSchemaChoice)) != null ) {
                XmlSchemaObjectCollection items = xsc.Items;
                int count = items.Count;
                if (count == 1) { 
                    if (xsc.MinOccurs == one && xsc.MaxOccurs == one) {
                        return (XmlSchemaParticle)items[0]; 
                    } 
                }
                else if (count == 0) { 
                    return XmlSchemaParticle.Empty;
                }
            }
            else if ( (xsa = (particle as XmlSchemaAll)) != null ) { 
                XmlSchemaObjectCollection items = xsa.Items;
                int count = items.Count; 
                if (count == 1) { 
                    if (xsa.MinOccurs == one && xsa.MaxOccurs == one) {
                        return (XmlSchemaParticle)items[0]; 
                    }
                }
            }
            return particle; 
        }
 
        private bool IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) { 
            if (derivedParticle == baseParticle) {
                return true; 
            }
            else if (derivedParticle == null || derivedParticle == XmlSchemaParticle.Empty) {
                return IsParticleEmptiable(baseParticle);
            } 
            else if (baseParticle == null || baseParticle == XmlSchemaParticle.Empty) {
                return false; 
            } 
            if (derivedParticle is XmlSchemaElement) { //check for derived element being head of substitutionGroup
                XmlSchemaElement derivedElem = (XmlSchemaElement)derivedParticle; 
                derivedParticle = CannonicalizeElement(derivedElem);
            }
            if (baseParticle is XmlSchemaElement) {
                XmlSchemaElement baseElem = (XmlSchemaElement)baseParticle; 
                XmlSchemaParticle newBaseParticle;
                newBaseParticle = CannonicalizeElement(baseElem); 
                if (newBaseParticle is XmlSchemaChoice) { //Base Element is subs grp head. 
                    return IsValidRestriction(derivedParticle, newBaseParticle);
                } 
                else if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromElement((XmlSchemaElement)derivedParticle, baseElem);
                }
                else { 
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForElem);
                    return false; 
                } 
            }
            else if (baseParticle is XmlSchemaAny) { 
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromAny((XmlSchemaElement)derivedParticle, (XmlSchemaAny)baseParticle);
                }
                else if (derivedParticle is XmlSchemaAny) { 
                    return IsAnyFromAny((XmlSchemaAny)derivedParticle, (XmlSchemaAny)baseParticle);
                } 
                else { 
                    return IsGroupBaseFromAny((XmlSchemaGroupBase)derivedParticle, (XmlSchemaAny)baseParticle);
                } 
            }
            else if (baseParticle is XmlSchemaAll) {
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 
                }
                else if (derivedParticle is XmlSchemaAll) { 
                    if(IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) { 
                        return true;
                    } 
                }
                else if (derivedParticle is XmlSchemaSequence) {
                    if(IsSequenceFromAll((XmlSchemaSequence)derivedParticle, (XmlSchemaAll)baseParticle)) {
                        return true; 
                    }
                    restrictionErrorMsg = Res.GetString(Res.Sch_SeqFromAll, derivedParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
                } 
                else if (derivedParticle is XmlSchemaChoice || derivedParticle is XmlSchemaAny) {
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForAll); 
                }
                return false;
            }
            else if (baseParticle is XmlSchemaChoice ) { 
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 
                } 
                else if (derivedParticle is XmlSchemaChoice) {
                    XmlSchemaChoice baseChoice = baseParticle as XmlSchemaChoice; 
                    XmlSchemaChoice derivedChoice = derivedParticle as XmlSchemaChoice;
                    if (baseChoice.Parent == null || derivedChoice.Parent == null) { //using parent property to indicate this choice was created on the fly for substitutionGroup
                        return IsChoiceFromChoiceSubstGroup(derivedChoice, baseChoice);
                    } 
                    if(IsGroupBaseFromGroupBase(derivedChoice, baseChoice, false)) {
                        return true; 
                    } 
                }
                else if (derivedParticle is XmlSchemaSequence) { 
                    if(IsSequenceFromChoice((XmlSchemaSequence)derivedParticle, (XmlSchemaChoice)baseParticle)) {
                        return true;
                    }
                    restrictionErrorMsg = Res.GetString(Res.Sch_SeqFromChoice, derivedParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
                }
                else { 
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForChoice); 
                }
                return false; 
            }
            else if (baseParticle is XmlSchemaSequence) {
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 
                }
                else if (derivedParticle is XmlSchemaSequence || (derivedParticle is XmlSchemaAll && ((XmlSchemaGroupBase)derivedParticle).Items.Count ==1)) { 
                    if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) { 
                        return true;
                    } 
                }
                else {
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForSeq);
                } 
                return false;
            } 
            else { 
                Debug.Assert(false);
            } 

            return false;
        }
 
        private bool IsElementFromElement(XmlSchemaElement derivedElement, XmlSchemaElement baseElement) {
            if(! ((derivedElement.QualifiedName == baseElement.QualifiedName) && 
                 (baseElement.IsNillable || !derivedElement.IsNillable) && 
                 IsValidOccurrenceRangeRestriction(derivedElement, baseElement) &&
                 (baseElement.FixedValue == null || IsFixedEqual(baseElement.ElementDecl, derivedElement.ElementDecl) ) && 
                 ((derivedElement.ElementDecl.Block | baseElement.ElementDecl.Block) ==  derivedElement.ElementDecl.Block) &&
                 (derivedElement.ElementSchemaType != null) && (baseElement.ElementSchemaType != null) &&
                 XmlSchemaType.IsDerivedFrom(derivedElement.ElementSchemaType, baseElement.ElementSchemaType, ~(XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.List | XmlSchemaDerivationMethod.Union))) ) {
 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromElement, derivedElement.QualifiedName, baseElement.QualifiedName);
                return false; 
            } 
            return true;
        } 

        private bool IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny) {
            if (!baseAny.Allows(derivedElement.QualifiedName)) {
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule1, derivedElement.QualifiedName.ToString()); 
                return false;
            } 
            if (!IsValidOccurrenceRangeRestriction(derivedElement, baseAny)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule2, derivedElement.QualifiedName.ToString());
                return false; 
            }
            return true;
        }
 
        private bool IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny) {
            if (!IsValidOccurrenceRangeRestriction(derivedAny, baseAny)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule1); 
                return false;
            } 
            if (!NamespaceList.IsSubset(derivedAny.NamespaceList, baseAny.NamespaceList)) {
                restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule2);
                return false;
            } 
            if ((int)derivedAny.ProcessContentsCorrect < (int)baseAny.ProcessContentsCorrect) {
                restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule3); 
                return false; 
            }
            return true; 
        }

        private bool IsGroupBaseFromAny(XmlSchemaGroupBase derivedGroupBase, XmlSchemaAny baseAny) {
            decimal minOccurs, maxOccurs; 
            CalculateEffectiveTotalRange(derivedGroupBase, out minOccurs, out maxOccurs);
            if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseAny.MinOccurs, baseAny.MaxOccurs)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseFromAny2, derivedGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseAny.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseAny.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
                return false;
            } 
            // eliminate occurrance range check
            string minOccursAny = baseAny.MinOccursString;
            baseAny.MinOccurs = decimal.Zero;
            foreach (XmlSchemaParticle p in derivedGroupBase.Items) { 
                if (!IsValidRestriction(p, baseAny)) {
                    restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseFromAny1); 
                    baseAny.MinOccursString = minOccursAny; 
                    return false;
                } 
            }
            baseAny.MinOccursString = minOccursAny;
            return true;
        } 

#if [....] 
        private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) { 
            if (!IsRangeSimple(baseGroupBase.MinOccurs, baseGroupBase.MaxOccurs) || !IsRangeSimple(derivedElement.MinOccurs, derivedElement.MaxOccurs)) {
                return IsElementFromGroupBase(derivedElement, baseGroupBase); //SPEC COMPLIANT 
            }
            else {
                //Base partilce's and Derived Element's range is simple
                //If all particles in baseParticle also have simple ranges, then can use our algorithm 
                //So that we dont break common cases that we used to accept earlier
                //Example Choice -> Element 
                if (IsElementFromGroupBaseHack(derivedElement, baseGroupBase, skipEmptableOnly)) { 
                    return true;
                } 
                else { //Fall back to regular checking
                    return IsElementFromGroupBase(derivedElement, baseGroupBase);
                }
            } 
        }
 
        private bool IsElementFromGroupBaseHack(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) { 
            bool isMatched = false;
 
            foreach(XmlSchemaParticle baseParticle in baseGroupBase.Items) {
                if (!isMatched && IsRangeSimple(baseParticle.MinOccurs, baseParticle.MaxOccurs)) {
                    string minOccursElement = baseParticle.MinOccursString;
                    string maxOccursElement = baseParticle.MaxOccursString; 
                    baseParticle.MinOccurs *= baseGroupBase.MinOccurs;
                    if ( baseParticle.MaxOccurs != decimal.MaxValue) { 
                        if (baseGroupBase.MaxOccurs == decimal.MaxValue) 
                             baseParticle.MaxOccurs = decimal.MaxValue;
                        else 
                             baseParticle.MaxOccurs *= baseGroupBase.MaxOccurs;
                    }
                    isMatched  = IsValidRestriction(derivedElement, baseParticle);
                    baseParticle.MinOccursString = minOccursElement; 
                    baseParticle.MaxOccursString = maxOccursElement;
                } 
                if (!isMatched && skipEmptableOnly && !IsParticleEmptiable(baseParticle)) { 
                    return false;
                } 
            }
            return isMatched;
        }
#endif 
        private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase) {
            if (baseGroupBase is XmlSchemaSequence) { 
                XmlSchemaSequence virtualSeq = new XmlSchemaSequence(); 
                virtualSeq.MinOccurs = 1;
                virtualSeq.MaxOccurs = 1; 
                virtualSeq.Items.Add(derivedElement);
                if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualSeq, baseGroupBase, true)) {
                    return true;
                } 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase1, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo));
            } 
            else if (baseGroupBase is XmlSchemaChoice) { 
                XmlSchemaChoice virtualChoice = new XmlSchemaChoice();
                virtualChoice.MinOccurs = 1; 
                virtualChoice.MaxOccurs = 1;
                virtualChoice.Items.Add(derivedElement);
                if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualChoice, baseGroupBase, false)) {
                    return true; 
                }
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase2, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
            } 
            else if (baseGroupBase is XmlSchemaAll) {
                XmlSchemaAll virtualAll = new XmlSchemaAll(); 
                virtualAll.MinOccurs = 1;
                virtualAll.MaxOccurs = 1;
                virtualAll.Items.Add(derivedElement);
                if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualAll, baseGroupBase, true)) { 
                    return true;
                } 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase3, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
            }
            return false; 
        }

        private bool IsChoiceFromChoiceSubstGroup(XmlSchemaChoice derivedChoice, XmlSchemaChoice baseChoice) {
            if (!IsValidOccurrenceRangeRestriction(derivedChoice, baseChoice)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid);
                return false; 
            } 
            foreach(XmlSchemaParticle particle in derivedChoice.Items) {
                if (GetMappingParticle(particle, baseChoice.Items) < 0) { 
                    return false;
                }
            }
            return true; 
        }
 
        private bool IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) { 
            if (!IsValidOccurrenceRangeRestriction(derivedGroupBase, baseGroupBase)) {
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid); 
                return false;
            }
            if (derivedGroupBase.Items.Count > baseGroupBase.Items.Count) {
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNoMap); 
                return false;
            } 
            int count = 0; 
            foreach(XmlSchemaParticle baseParticle in baseGroupBase.Items) {
                if ((count < derivedGroupBase.Items.Count) && IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[count], baseParticle)) { 
                    count ++;
                }
                else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
                    if (restrictionErrorMsg == null) { //If restriction failed on previous check, do not overwrite error 
                        restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNotEmptiable);
                    } 
                    return false; 
                }
            } 
            if (count < derivedGroupBase.Items.Count) {
                return false;
            }
            return true; 
        }
 
        private bool IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll) { 
            if (!IsValidOccurrenceRangeRestriction(derivedSequence, baseAll) || derivedSequence.Items.Count > baseAll.Items.Count) {
                return false; 
            }
            BitSet map = new BitSet(baseAll.Items.Count);
            foreach (XmlSchemaParticle p in derivedSequence.Items) {
                int i = GetMappingParticle(p, baseAll.Items); 
                if (i >= 0) {
                    if (map[i]) { 
                        return false; 
                    }
                    else { 
                        map.Set(i);
                    }
                }
                else { 
                    return false;
                } 
            } 
            for (int i = 0; i < baseAll.Items.Count; i++) {
                if (!map[i] && !IsParticleEmptiable((XmlSchemaParticle)baseAll.Items[i])) { 
                    return false;
                }
            }
            return true; 
        }
 
        private bool IsSequenceFromChoice(XmlSchemaSequence derivedSequence, XmlSchemaChoice baseChoice) { 
            decimal minOccurs, maxOccurs;
            minOccurs = derivedSequence.MinOccurs * derivedSequence.Items.Count; 
            if (derivedSequence.MaxOccurs == decimal.MaxValue) {
                maxOccurs = decimal.MaxValue;
            }
            else { 
                maxOccurs = derivedSequence.MaxOccurs * derivedSequence.Items.Count;
            } 
            if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseChoice.MinOccurs, baseChoice.MaxOccurs) || derivedSequence.Items.Count > baseChoice.Items.Count) { 
                return false;
            } 
            foreach (XmlSchemaParticle particle in derivedSequence.Items) {
                if (GetMappingParticle(particle, baseChoice.Items) < 0)
                    return false;
            } 
            return true;
        } 
 
        private bool IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
            return IsValidOccurrenceRangeRestriction(derivedParticle.MinOccurs, derivedParticle.MaxOccurs, baseParticle.MinOccurs, baseParticle.MaxOccurs); 
        }

        private bool IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs) {
            return (baseMinOccurs <= minOccurs) && (maxOccurs <= baseMaxOccurs); 
        }
 
        private int GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection) { 
            for (int i = 0; i < collection.Count; i++) {
                if (IsValidRestriction(particle, (XmlSchemaParticle)collection[i])) 
                    return i;
            }
            return -1;
        } 

        private bool IsParticleEmptiable(XmlSchemaParticle particle) { 
            decimal minOccurs, maxOccurs; 
            CalculateEffectiveTotalRange(particle, out minOccurs, out maxOccurs);
            return minOccurs == decimal.Zero; 
        }

        private void CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs) {
            if (particle is XmlSchemaElement || particle is XmlSchemaAny) { 
                minOccurs = particle.MinOccurs;
                maxOccurs = particle.MaxOccurs; 
            } 
            else if (particle is XmlSchemaChoice) {
                if (((XmlSchemaChoice)particle).Items.Count == 0) { 
                    minOccurs = maxOccurs = decimal.Zero;
                }
                else {
                    minOccurs = decimal.MaxValue; 
                    maxOccurs = decimal.Zero;
                    foreach (XmlSchemaParticle p in ((XmlSchemaChoice)particle).Items) { 
                        decimal min, max; 
                        CalculateEffectiveTotalRange(p, out min, out max);
                        if (min < minOccurs) { 
                            minOccurs = min;
                        }
                        if (max > maxOccurs) {
                            maxOccurs = max; 
                        }
                    } 
                    minOccurs *= particle.MinOccurs; 
                    if (maxOccurs != decimal.MaxValue) {
                        if (particle.MaxOccurs == decimal.MaxValue) 
                            maxOccurs = decimal.MaxValue;
                        else
                            maxOccurs *= particle.MaxOccurs;
                    } 
                }
            } 
            else { 
                XmlSchemaObjectCollection collection = ((XmlSchemaGroupBase)particle).Items;
                if (collection.Count == 0) { 
                    minOccurs = maxOccurs = decimal.Zero;
                }
                else {
                    minOccurs = 0; 
                    maxOccurs = 0;
                    foreach (XmlSchemaParticle p in collection) { 
                        decimal min, max; 
                        CalculateEffectiveTotalRange(p, out min, out max);
                        minOccurs += min; 
                        if (maxOccurs != decimal.MaxValue) {
                            if (max == decimal.MaxValue)
                                maxOccurs = decimal.MaxValue;
                            else 
                                maxOccurs += max;
                        } 
                    } 
                    minOccurs *= particle.MinOccurs;
                    if (maxOccurs != decimal.MaxValue) { 
                        if (particle.MaxOccurs == decimal.MaxValue)
                            maxOccurs = decimal.MaxValue;
                        else
                            maxOccurs *= particle.MaxOccurs; 
                    }
                } 
            } 
        }
 
        private void PushComplexType(XmlSchemaComplexType complexType) {
            this.complexTypeStack.Push(complexType);
        }
 
        private XmlSchemaContentType GetSchemaContentType(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaParticle particle) {
            if ((complexContent != null && complexContent.IsMixed) || 
                (complexContent == null && complexType.IsMixed)) { 
                return XmlSchemaContentType.Mixed;
            } 
            else if (particle != null && !particle.IsEmpty) {
                return XmlSchemaContentType.ElementOnly;
            }
            else { 
                return XmlSchemaContentType.Empty;
            } 
        } 

        private void CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup) { 
            if (attributeGroup.IsProcessing) {
                SendValidationEvent(Res.Sch_AttributeGroupCircularRef, attributeGroup);
                return;
            } 
            if (attributeGroup.AttributeUses.Count > 0) {// already checked
                return; 
            } 
            attributeGroup.IsProcessing = true;
            XmlSchemaAnyAttribute anyAttribute = attributeGroup.AnyAttribute; 

            try {
                foreach (XmlSchemaObject obj in attributeGroup.Attributes) {
                    if (obj is XmlSchemaAttribute) { 
                        XmlSchemaAttribute attribute = (XmlSchemaAttribute)obj;
                        if (attribute.Use == XmlSchemaUse.Prohibited) { 
                            continue; 
                        }
                        CompileAttribute(attribute); 
                        if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) {
                            attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute);
                        }
                        else  { 
                            SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
                        } 
                    } 
                    else { // XmlSchemaAttributeGroupRef
                        XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)obj; 
                        XmlSchemaAttributeGroup attributeGroupResolved;
                        if (attributeGroup.Redefined != null && attributeGroupRef.RefName == attributeGroup.Redefined.QualifiedName) {
                            attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroup.Redefined;
                        } 
                        else {
                            attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName]; 
                        } 
                        if (attributeGroupResolved != null) {
                            CompileAttributeGroup(attributeGroupResolved); 
                            foreach (XmlSchemaAttribute attribute in attributeGroupResolved.AttributeUses.Values) {
                                if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) {
                                    attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute);
                                } 
                                else {
                                    SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute); 
                                } 
                            }
                            anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroupResolved.AttributeWildcard); 
                        }
                        else {
                            SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
                        } 
                    }
                } 
                attributeGroup.AttributeWildcard = anyAttribute; 
            }
            finally { 
                attributeGroup.IsProcessing = false;
            }
        }
 
        private void CompileLocalAttributes(XmlSchemaComplexType baseType, XmlSchemaComplexType derivedType, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaDerivationMethod derivedBy) {
            XmlSchemaAnyAttribute baseAttributeWildcard = baseType != null ? baseType.AttributeWildcard : null; 
            foreach (XmlSchemaObject obj in attributes) { 
                if (obj is XmlSchemaAttribute) {
                    XmlSchemaAttribute attribute = (XmlSchemaAttribute)obj; 
                    if (attribute.Use != XmlSchemaUse.Prohibited) {
                        CompileAttribute(attribute);
                    }
                    if (attribute.Use != XmlSchemaUse.Prohibited || 
                        (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
 
                        if (derivedType.AttributeUses[attribute.QualifiedName] == null) { 
                            derivedType.AttributeUses.Add(attribute.QualifiedName, attribute);
                        } 
                        else  {
                            SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
                        }
                    } 
                    else {
                        SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning); 
                    } 

                } 
                else { // is XmlSchemaAttributeGroupRef
                    XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)obj;
                    XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName];
                    if (attributeGroup != null) { 
                        CompileAttributeGroup(attributeGroup);
                        foreach (XmlSchemaAttribute attribute in attributeGroup.AttributeUses.Values) { 
                          if (attribute.Use != XmlSchemaUse.Prohibited || 
                             (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
                            if (derivedType.AttributeUses[attribute.QualifiedName] == null) { 
                                derivedType.AttributeUses.Add(attribute.QualifiedName, attribute);
                            }
                            else {
                                SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attributeGroupRef); 
                            }
                          } 
                          else { 
                            SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning);
                          } 

                        }
                        anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroup.AttributeWildcard);
                    } 
                    else {
                        SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef); 
                    } 
                }
            } 

            // check derivation rules
            if (baseType != null) {
                if (derivedBy == XmlSchemaDerivationMethod.Extension) { 
                    derivedType.SetAttributeWildcard(CompileAnyAttributeUnion(anyAttribute, baseAttributeWildcard));
                    foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) { 
                        XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName]; 
                        if (attribute == null) {
                            derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase); 
                        }
                        else {
                            Debug.Assert(attribute.Use != XmlSchemaUse.Prohibited);
                            if (attributeBase.Use != XmlSchemaUse.Prohibited && attribute.AttributeSchemaType != attributeBase.AttributeSchemaType) { //Extension allows previously prohibited attributes to be re-added, 
                                SendValidationEvent(Res.Sch_InvalidAttributeExtension, attribute);
                            } 
                        } 
                    }
                } 
                else {  // derivedBy == XmlSchemaDerivationMethod.Restriction
                    // Schema Component Constraint: Derivation Valid (Restriction, Complex)
                    if ((anyAttribute != null) && (baseAttributeWildcard == null || !XmlSchemaAnyAttribute.IsSubset(anyAttribute, baseAttributeWildcard) || !IsProcessContentsRestricted(baseType, anyAttribute, baseAttributeWildcard)) ) {
                        SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedType); 
                    }
                    else { 
                        derivedType.SetAttributeWildcard(anyAttribute); //complete wildcard 
                    }
 
                    // Add form the base
                    foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
                        XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
                        if (attribute == null) { 
                            derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
                        } 
                        else { 
                            if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
#if DEBUG 
                                string position = string.Empty;
                                if (derivedType.SourceUri != null) {
                                    position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
                                } 
                                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
                                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard)); 
                                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard)); 
#endif
                                SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute); 
                            }
                            else if (attributeBase.Use == XmlSchemaUse.Required && (attribute.Use != XmlSchemaUse.Required)) { //If base is required, derived should also be required
                                SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute);
                            } 
                            else if (attribute.Use == XmlSchemaUse.Prohibited) {
                                continue; 
                            } 
                            else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
                                SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute); 
                            }
                            else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
                                SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
                            } 
                        }
                    } 
 
                    // Check additional ones are valid restriction of base's wildcard
                    foreach(XmlSchemaAttribute attribute in derivedType.AttributeUses.Values) { 
                        XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseType.AttributeUses[attribute.QualifiedName];
                        if (attributeBase != null) {
                            continue;
                        } 
                        if (baseAttributeWildcard == null || !baseAttributeWildcard.Allows(attribute.QualifiedName)) {
#if DEBUG 
                            string position = string.Empty; 
                            if (derivedType.SourceUri != null) {
                                position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")"; 
                            }
                            Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
                            Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
                            Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard)); 
#endif
                            SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute); 
                        } 
                    }
                } 
            }
            else {
                derivedType.SetAttributeWildcard(anyAttribute);
            } 
       }
 
        private void CheckAtrributeGroupRestriction(XmlSchemaAttributeGroup baseAttributeGroup, XmlSchemaAttributeGroup derivedAttributeGroup) { 
            XmlSchemaAnyAttribute baseAnyAtt = baseAttributeGroup.AttributeWildcard;
            XmlSchemaAnyAttribute derivedAnyAtt = derivedAttributeGroup.AttributeWildcard; 

            if ((derivedAnyAtt != null) && (baseAnyAtt == null || !XmlSchemaAnyAttribute.IsSubset(derivedAnyAtt, baseAnyAtt) || !IsProcessContentsRestricted(null, derivedAnyAtt, baseAnyAtt))) {
                SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedAttributeGroup);
            } 
            foreach(XmlSchemaAttribute attributeBase in baseAttributeGroup.AttributeUses.Values) {
                XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedAttributeGroup.AttributeUses[attributeBase.QualifiedName]; 
                if (attribute != null) { 
                    if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
                        SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute); 
                    }
                    else if (attributeBase.Use == XmlSchemaUse.Required && attribute.Use != XmlSchemaUse.Required) {
                        SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute);
                    } 
                    else if (attribute.Use == XmlSchemaUse.Prohibited) { //If derived att is prohibited, continue
                        continue; 
                    } 
                    else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
                        SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute); 
                    }
                    else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
                        SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
                    } 
                }
                else if (attributeBase.Use == XmlSchemaUse.Required) { 
                    SendValidationEvent(Res.Sch_NoDerivedAttribute, attributeBase.QualifiedName.ToString(), baseAttributeGroup.QualifiedName.ToString(), derivedAttributeGroup); 
                }
            } 
            // Check additional ones are valid restriction of base's wildcard
            foreach(XmlSchemaAttribute attribute in derivedAttributeGroup.AttributeUses.Values) {
                XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseAttributeGroup.AttributeUses[attribute.QualifiedName];
                if (attributeBase != null) { 
                    continue;
                } 
                if (baseAnyAtt == null || !baseAnyAtt.Allows(attribute.QualifiedName)) { 
                    SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
                } 
            }
        }

#if DEBUG 
        private string DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard) {
            StringBuilder sb = new StringBuilder(); 
            sb.Append("["); 
            bool first = true;
            foreach (XmlSchemaAttribute attribute in attributeUses.Values) { 
                if (attribute.Use != XmlSchemaUse.Prohibited) {
                    if (first) {
                        first = false;
                    } 
                    else {
                        sb.Append(" "); 
                    } 
                    sb.Append(attribute.QualifiedName.Name);
                    if (attribute.Use == XmlSchemaUse.Optional || attribute.Use == XmlSchemaUse.None) { 
                        sb.Append("?");
                    }
                }
            } 
            if (attributeWildcard != null) {
                if (attributeUses.Count != 0) { 
                    sb.Append(" "); 
                }
                sb.Append("<"); 
                sb.Append(attributeWildcard.NamespaceList.ToString());
                sb.Append(">");
            }
            sb.Append("] - ["); 
            first = true;
            foreach (XmlSchemaAttribute attribute in attributeUses.Values) { 
                if (attribute.Use == XmlSchemaUse.Prohibited) { 
                    if (first) {
                        first = false; 
                    }
                    else {
                        sb.Append(" ");
                    } 
                    sb.Append(attribute.QualifiedName.Name);
                } 
            } 
            sb.Append("]");
            return sb.ToString(); 
        }
#endif

        private bool IsProcessContentsRestricted(XmlSchemaComplexType baseType, XmlSchemaAnyAttribute derivedAttributeWildcard, XmlSchemaAnyAttribute baseAttributeWildcard) { 
            if (baseType == XmlSchemaComplexType.AnyType) {
                return true; 
            } 
            if ((int)derivedAttributeWildcard.ProcessContentsCorrect >= (int)baseAttributeWildcard.ProcessContentsCorrect) {
                return true; 
            }
            return false;
        }
 
        private XmlSchemaAnyAttribute CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
            if (a == null) { 
                return b; 
            }
            else if (b == null) { 
                return a;
            }
            else {
                XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Union(a, b, false); //false is for v1Compatd 
                if (attribute == null) {
                    SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a); 
                } 
                return attribute;
            } 

        }

        private XmlSchemaAnyAttribute CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) { 
            if (a == null) {
                return b; 
            } 
            else if (b == null) {
                return a; 
            }
            else {
                XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Intersection(a, b, false); //false is for v1Compat
                if (attribute == null) { 
                    SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
                } 
                return attribute; 
            }
        } 

         private void CompileAttribute(XmlSchemaAttribute xa) {
            if (xa.IsProcessing) {
                SendValidationEvent(Res.Sch_AttributeCircularRef, xa); 
                return;
            } 
            if (xa.AttDef != null) { //already compiled? 
                return;
            } 
            xa.IsProcessing = true;
            SchemaAttDef decl = null;
            try {
                if (!xa.RefName.IsEmpty) { 
                    XmlSchemaAttribute a = (XmlSchemaAttribute)attributes[xa.RefName];
                    if (a == null) { 
                        throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, xa.RefName.ToString(), xa); 
                    }
                    CompileAttribute(a); 
                    if (a.AttDef == null) {
                        throw new XmlSchemaException(Res.Sch_RefInvalidAttribute, xa.RefName.ToString(), xa);
                    }
                    decl = a.AttDef.Clone(); 
                    XmlSchemaDatatype datatype = decl.Datatype;
 
                    if (datatype != null) { 
                        if (a.FixedValue == null && a.DefaultValue == null) {
                            SetDefaultFixed(xa, decl); 
                        }
                        else if (a.FixedValue != null) {
                            if (xa.DefaultValue != null) {
                                throw new XmlSchemaException(Res.Sch_FixedDefaultInRef, xa.RefName.ToString(), xa); 
                            }
                            else if (xa.FixedValue != null ) { 
                                object refFixedValue = datatype.ParseValue(xa.FixedValue, NameTable, new SchemaNamespaceManager(xa), true); 
                                if ( !datatype.IsEqual(decl.DefaultValueTyped, refFixedValue)) {
                                    throw new XmlSchemaException(Res.Sch_FixedInRef, xa.RefName.ToString(), xa); 
                                }
                            }
                        }
                    } 
                    xa.SetAttributeType(a.AttributeSchemaType);
                } 
                else { 
                    decl = new SchemaAttDef(xa.QualifiedName, xa.Prefix);
                    if (xa.SchemaType != null) { 
                        CompileSimpleType(xa.SchemaType);
                        xa.SetAttributeType(xa.SchemaType);
                        decl.SchemaType = xa.SchemaType;
                        decl.Datatype = xa.SchemaType.Datatype; 
                    }
                    else if (!xa.SchemaTypeName.IsEmpty) { 
                        XmlSchemaSimpleType simpleType = GetSimpleType(xa.SchemaTypeName); 
                        if (simpleType != null) {
                            xa.SetAttributeType(simpleType); 
                            decl.Datatype = simpleType.Datatype;
                            decl.SchemaType = simpleType;
                        }
                        else { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, xa.SchemaTypeName.ToString(), xa);
                        } 
                    } 
                    else {
                        decl.SchemaType = DatatypeImplementation.AnySimpleType; 
                        decl.Datatype = DatatypeImplementation.AnySimpleType.Datatype;
                        xa.SetAttributeType(DatatypeImplementation.AnySimpleType);
                    }
                    //} //Removed this here since the following should be done only if RefName is Empty 
                    if (decl.Datatype != null) {
                        decl.Datatype.VerifySchemaValid(notations, xa); 
                    } 
                    SetDefaultFixed(xa, decl);
                } //End of Else for !RefName.IsEmpty 

                decl.SchemaAttribute = xa; //So this is available for PSVI
                xa.AttDef = decl;
            } 
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) { 
                    e.SetSource(xa); 
                }
                SendValidationEvent(e); 
                xa.AttDef = SchemaAttDef.Empty;
            }
            finally {
                xa.IsProcessing = false; 
            }
        } 
 
        private void SetDefaultFixed(XmlSchemaAttribute xa, SchemaAttDef decl) {
            if (xa.DefaultValue != null || xa.FixedValue != null) { 
                if (xa.DefaultValue != null) {
                    decl.Presence = SchemaDeclBase.Use.Default;
                    decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.DefaultValue;
                } 
                else {
                    if (xa.Use == XmlSchemaUse.Required) { 
                        decl.Presence = SchemaDeclBase.Use.RequiredFixed; 
                    }
                    else { 
                        decl.Presence = SchemaDeclBase.Use.Fixed;
                    }
                    decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.FixedValue;
                } 
                if(decl.Datatype != null) {
                    if (decl.Datatype.TypeCode == XmlTypeCode.Id) { 
                        SendValidationEvent(Res.Sch_DefaultIdValue, xa); 
                    }
                    else { 
                        decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
                    }
                }
            } 
            else {
                switch (xa.Use) { 
                    case XmlSchemaUse.None: 
                    case XmlSchemaUse.Optional:
                        decl.Presence = SchemaDeclBase.Use.Implied; 
                        break;
                    case XmlSchemaUse.Required:
                        decl.Presence = SchemaDeclBase.Use.Required;
                        break; 
                    case XmlSchemaUse.Prohibited:
                        break; 
                } 
            }
        } 

        private void CompileIdentityConstraint (XmlSchemaIdentityConstraint xi) {
            if (xi.IsProcessing) {
                xi.CompiledConstraint = CompiledIdentityConstraint.Empty; 
                SendValidationEvent(Res.Sch_IdentityConstraintCircularRef, xi);
                return; 
            } 

            if (xi.CompiledConstraint != null) { 
                return;
            }

            xi.IsProcessing = true; 
            CompiledIdentityConstraint compic = null;
            try { 
                SchemaNamespaceManager xnmgr = new SchemaNamespaceManager(xi); 
                compic = new CompiledIdentityConstraint(xi, xnmgr);
                if (xi is XmlSchemaKeyref) { 
                    XmlSchemaIdentityConstraint ic = (XmlSchemaIdentityConstraint)this.identityConstraints[((XmlSchemaKeyref)xi).Refer];
                    if (ic == null) {
                        throw new XmlSchemaException(Res.Sch_UndeclaredIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
                    } 
                    CompileIdentityConstraint(ic);
                    if (ic.CompiledConstraint == null) { 
                        throw new XmlSchemaException(Res.Sch_RefInvalidIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi); 
                    }
                    // keyref has the different cardinality with the key it referred 
                    if (ic.Fields.Count != xi.Fields.Count) {
                        throw new XmlSchemaException(Res.Sch_RefInvalidCardin, xi.QualifiedName.ToString(), xi);
                    }
                    // keyref can only refer to key/unique 
                    if (ic.CompiledConstraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) {
                        throw new XmlSchemaException(Res.Sch_ReftoKeyref, xi.QualifiedName.ToString(), xi); 
                    } 
                }
                xi.CompiledConstraint = compic; 
            }
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) {
                    e.SetSource(xi); 
                }
                SendValidationEvent(e); 
                xi.CompiledConstraint = CompiledIdentityConstraint.Empty; 
                // empty is better than null here, stop quickly when circle referencing
            } 
            finally {
                xi.IsProcessing = false;
            }
 
        }
 
        private void CompileElement(XmlSchemaElement xe) { 
            if (xe.IsProcessing) {
                SendValidationEvent(Res.Sch_ElementCircularRef, xe); 
                return;
            }
            if (xe.ElementDecl != null) {
                return; 
            }
            xe.IsProcessing = true; 
            SchemaElementDecl decl = null; 
            try {
                if (!xe.RefName.IsEmpty) { 
                    XmlSchemaElement e = (XmlSchemaElement)elements[xe.RefName];
                    if (e == null) {
                        throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe);
                    } 
                    CompileElement(e);
                    if (e.ElementDecl == null) { 
                        throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe); 
                    }
                    xe.SetElementType(e.ElementSchemaType); 
                    decl = e.ElementDecl.Clone();
                }
                else {
                    if (xe.SchemaType != null) { 
                        xe.SetElementType(xe.SchemaType);
                    } 
                    else if (!xe.SchemaTypeName.IsEmpty) { 
                        xe.SetElementType(GetAnySchemaType(xe.SchemaTypeName));
                        if (xe.ElementSchemaType == null) { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredType, xe.SchemaTypeName.ToString(), xe);
                        }
                    }
                    else  if (!xe.SubstitutionGroup.IsEmpty) { 
                        XmlSchemaElement examplar = (XmlSchemaElement)elements[xe.SubstitutionGroup];
                        if (examplar == null) { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredEquivClass, xe.SubstitutionGroup.Name.ToString(CultureInfo.InvariantCulture), xe); 
                        }
                        if (examplar.IsProcessing) { //Circular subst group; already detected by now 
                            return;
                        }
                        CompileElement(examplar);
                        if (examplar.ElementDecl == null) { //If head is invalid, fall back to AnyType 
                            xe.SetElementType(XmlSchemaComplexType.AnyType);
                            decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone(); 
                        } 
                        else {
                            xe.SetElementType(examplar.ElementSchemaType); 
                            decl = examplar.ElementDecl.Clone();
                        }
                    }
                    else { 
                        xe.SetElementType(XmlSchemaComplexType.AnyType);
                        decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone(); 
                    } 

                    if (decl == null) { 
                        Debug.Assert(xe.ElementSchemaType != null);
                        if (xe.ElementSchemaType is XmlSchemaComplexType) {
                            XmlSchemaComplexType complexType = (XmlSchemaComplexType)xe.ElementSchemaType;
                            CompileComplexType(complexType); 
                            if (complexType.ElementDecl != null) {
                                decl = complexType.ElementDecl.Clone(); 
//                                decl.LocalElements = complexType.LocalElementDecls; 
                            }
                        } 
                        else if (xe.ElementSchemaType is XmlSchemaSimpleType) {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)xe.ElementSchemaType;
                            CompileSimpleType(simpleType);
                            if (simpleType.ElementDecl != null) { 
                                decl = simpleType.ElementDecl.Clone();
                            } 
                        } 
                    }
                    Debug.Assert(decl != null); 
                    decl.Name = xe.QualifiedName;
                    decl.IsAbstract = xe.IsAbstract;
                    XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType;
                    if (ct != null) { 
                        decl.IsAbstract |= ct.IsAbstract;
                    } 
                    decl.IsNillable = xe.IsNillable; 
                    decl.Block |= xe.BlockResolved;
                } 
                if (decl.Datatype != null) {
                    decl.Datatype.VerifySchemaValid(notations, xe);
                }
 
                if (xe.DefaultValue != null || xe.FixedValue != null) {
                    if (decl.ContentValidator != null) { 
                        if (decl.ContentValidator.ContentType == XmlSchemaContentType.TextOnly || (decl.ContentValidator.ContentType == XmlSchemaContentType.Mixed && decl.ContentValidator.IsEmptiable)) { 
                            if (xe.DefaultValue != null) {
                                decl.Presence = SchemaDeclBase.Use.Default; 
                                decl.DefaultValueRaw = xe.DefaultValue;
                            }
                            else {
                                decl.Presence = SchemaDeclBase.Use.Fixed; 
                                decl.DefaultValueRaw = xe.FixedValue;
                            } 
                            if (decl.Datatype != null) { 
                                if (decl.Datatype.TypeCode == XmlTypeCode.Id) {
                                    SendValidationEvent(Res.Sch_DefaultIdValue, xe); 
                                }
                                else {
                                    decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true);
                                } 
                            }
                            else { //Mixed with emptiable particle 
                                decl.DefaultValueTyped = DatatypeImplementation.AnySimpleType.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe)); 
                            }
                        } 
                        else {
                            throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe);
                        }
                    } 
                }
                if (xe.HasConstraints) { 
                    XmlSchemaObjectCollection constraints = xe.Constraints; 
                    CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count];
                    int idx = 0; 
                    foreach(XmlSchemaIdentityConstraint constraint in constraints) {
                        CompileIdentityConstraint (constraint);
                        compiledConstraints[idx ++] = constraint.CompiledConstraint;
                    } 
                    decl.Constraints = compiledConstraints;
                } 
                decl.SchemaElement = xe; //So this is available for PSVI 
                xe.ElementDecl = decl;
            } 
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) {
                    e.SetSource(xe);
                } 
                SendValidationEvent(e);
                xe.ElementDecl = SchemaElementDecl.Empty; 
            } 
            finally {
                xe.IsProcessing = false; 
            }
        }

        private ContentValidator CompileComplexContent(XmlSchemaComplexType complexType) { 
            if (complexType.ContentType == XmlSchemaContentType.Empty) {
                return ContentValidator.Empty; 
            } 
            else if (complexType.ContentType == XmlSchemaContentType.TextOnly) {
                return ContentValidator.TextOnly; 
            }
            XmlSchemaParticle particle = complexType.ContentTypeParticle;
            if (particle == null || particle == XmlSchemaParticle.Empty) {
                if (complexType.ContentType == XmlSchemaContentType.ElementOnly) { 
                    return ContentValidator.Empty;
                } 
                else { 
                    return ContentValidator.Mixed;
                } 
            }
            PushComplexType(complexType);
            if (particle is XmlSchemaAll) {
                XmlSchemaAll all = (XmlSchemaAll)particle; 
                AllElementsContentValidator contentValidator = new AllElementsContentValidator(complexType.ContentType, all.Items.Count, all.MinOccurs == decimal.Zero);
                foreach (XmlSchemaElement localElement in all.Items) { 
                    if (!contentValidator.AddElement(localElement.QualifiedName, localElement, localElement.MinOccurs == decimal.Zero)) { 
                       SendValidationEvent(Res.Sch_DupElement, localElement.QualifiedName.ToString(), localElement);
                    } 
                }
                return contentValidator;
            }
            else { 
                ParticleContentValidator contentValidator = new ParticleContentValidator(complexType.ContentType, CompilationSettings.EnableUpaCheck);
#if DEBUG 
                string name = complexType.Name != null ? complexType.Name : string.Empty; 
                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceVerbose, "CompileComplexContent: "+ name  + DumpContentModel(particle));
#endif 
                try {
                    contentValidator.Start();
                    complexType.HasWildCard = BuildParticleContentModel(contentValidator, particle);
                    return contentValidator.Finish(true); 
                }
                catch(UpaException e) { 
                    if (e.Particle1 is XmlSchemaElement) { 
                        if (e.Particle2 is XmlSchemaElement) {
                            SendValidationEvent(Res.Sch_NonDeterministic, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2); 
                        }
                        else {
                            SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaAny)e.Particle2);
                        } 
                    }
                    else { 
                        if (e.Particle2 is XmlSchemaElement) { 
                            SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaElement)e.Particle2).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2);
                        } 
                        else {
                            SendValidationEvent(Res.Sch_NonDeterministicAnyAny, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, (XmlSchemaAny)e.Particle2);
                        }
                    } 
                    return XmlSchemaComplexType.AnyTypeContentValidator;
                } 
                catch(NotSupportedException) { 
                    SendValidationEvent(Res.Sch_ComplexContentModel, complexType, XmlSeverityType.Warning);
                    return XmlSchemaComplexType.AnyTypeContentValidator; 
                }
            }
        }
 
#if DEBUG
        private string DumpContentModel(XmlSchemaParticle particle) { 
            StringBuilder sb = new StringBuilder(); 
            DumpContentModelTo(sb, particle);
            return sb.ToString(); 
        }

        private void DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle) {
            if (particle is XmlSchemaElement) { 
                sb.Append(((XmlSchemaElement)particle).QualifiedName);
            } 
            else if (particle is XmlSchemaAny) { 
                sb.Append("<");
                sb.Append(((XmlSchemaAny)particle).NamespaceList.ToString()); 
                sb.Append(">");
            }
            else if (particle is XmlSchemaAll) {
                XmlSchemaAll all = (XmlSchemaAll)particle; 
                sb.Append("[");
                bool first = true; 
                foreach (XmlSchemaElement localElement in all.Items) { 
                    if (first) {
                        first = false; 
                    }
                    else {
                        sb.Append(", ");
                    } 
                    sb.Append(localElement.QualifiedName.Name);
                    if (localElement.MinOccurs == decimal.Zero) { 
                        sb.Append("?"); 
                    }
                } 
                sb.Append("]");
            }
            else if (particle is XmlSchemaGroupBase) {
                XmlSchemaGroupBase gb = (XmlSchemaGroupBase)particle; 
                sb.Append("(");
                string delimeter = (particle is XmlSchemaChoice) ? " | " : ", "; 
                bool first = true; 
                foreach (XmlSchemaParticle p in gb.Items) {
                    if (first) { 
                        first = false;
                    }
                    else {
                        sb.Append(delimeter); 
                    }
                    DumpContentModelTo(sb, p); 
                } 
                sb.Append(")");
            } else { 
                Debug.Assert(particle == XmlSchemaParticle.Empty);
                sb.Append("<>");
            }
            if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) { 
                // nothing
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) { 
                sb.Append("?");
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
                sb.Append("*");
            }
            else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) { 
                sb.Append("+");
            } 
            else { 
                sb.Append("{" + particle.MinOccurs.ToString(NumberFormatInfo.InvariantInfo) +", " + particle.MaxOccurs.ToString(NumberFormatInfo.InvariantInfo) + "}");
            } 
        }
#endif

        private bool BuildParticleContentModel(ParticleContentValidator contentValidator, XmlSchemaParticle particle) { 
            bool hasWildCard = false;
            if (particle is XmlSchemaElement) { 
                XmlSchemaElement element = (XmlSchemaElement)particle; 
                contentValidator.AddName(element.QualifiedName, element);
             } 
            else if (particle is XmlSchemaAny) {
                hasWildCard = true;
                XmlSchemaAny any = (XmlSchemaAny)particle;
                contentValidator.AddNamespaceList(any.NamespaceList, any); 
            }
            else if (particle is XmlSchemaGroupBase) { 
                XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 
                bool isChoice = particle is XmlSchemaChoice;
                contentValidator.OpenGroup(); 
                bool first = true;
                foreach (XmlSchemaParticle p in particles) {
                    Debug.Assert(!p.IsEmpty);
                    if (first) { 
                        first = false;
                    } 
                    else if (isChoice) { 
                        contentValidator.AddChoice();
                    } 
                    else {
                        contentValidator.AddSequence();
                    }
                    hasWildCard = BuildParticleContentModel(contentValidator, p); 
                }
                contentValidator.CloseGroup(); 
            } 
            else {
                Debug.Assert(false); 
            }
            if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
                // nothing
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
                contentValidator.AddQMark(); 
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
                contentValidator.AddStar(); 
            }
            else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
                contentValidator.AddPlus();
            } 
            else {
                contentValidator.AddLeafRange(particle.MinOccurs, particle.MaxOccurs); 
            } 
            return hasWildCard;
        } 

        private void CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle) {
            if (particle is XmlSchemaElement) {
                XmlSchemaElement localElement = (XmlSchemaElement)particle; 
                CompileElement(localElement);
                if (complexType.LocalElements[localElement.QualifiedName] == null) { 
                    complexType.LocalElements.Add(localElement.QualifiedName, localElement); 
                }
                else { 
                    complexType.HasDuplicateDecls = true;
                    XmlSchemaElement element = (XmlSchemaElement)complexType.LocalElements[localElement.QualifiedName];
                    if (element.ElementSchemaType != localElement.ElementSchemaType) {
                        SendValidationEvent(Res.Sch_ElementTypeCollision, particle); 
                    }
                } 
            } 
            else if (particle is XmlSchemaGroupBase) {
                XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 
                foreach (XmlSchemaParticle p in particles) {
                    CompileParticleElements(complexType, p);
                }
            } 
        }
 
        private void CompileParticleElements(XmlSchemaParticle particle) { //For checking redefined group particle derivation 
            if (particle is XmlSchemaElement) {
                XmlSchemaElement localElement = (XmlSchemaElement)particle; 
                CompileElement(localElement);
            }
            else if (particle is XmlSchemaGroupBase) {
                XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 
                foreach (XmlSchemaParticle p in particles) {
                    CompileParticleElements(p); 
                } 
            }
        } 

        private void CompileComplexTypeElements(XmlSchemaComplexType complexType) {
            if (complexType.IsProcessing) {
                SendValidationEvent(Res.Sch_TypeCircularRef, complexType); 
                return;
            } 
            complexType.IsProcessing = true; 
            try {
                if (complexType.ContentTypeParticle != XmlSchemaParticle.Empty) { 
                    CompileParticleElements(complexType, complexType.ContentTypeParticle);
                }
            }
            finally { 
                complexType.IsProcessing = false;
            } 
        } 

        private XmlSchemaSimpleType GetSimpleType(XmlQualifiedName name) { 
            XmlSchemaSimpleType type = schemaTypes[name] as XmlSchemaSimpleType;
            if (type != null) {
                CompileSimpleType(type);
            } 
            else {
                type = DatatypeImplementation.GetSimpleTypeFromXsdType(name); 
            } 
            return type;
        } 

        private XmlSchemaComplexType GetComplexType(XmlQualifiedName name) {
            XmlSchemaComplexType type = schemaTypes[name] as XmlSchemaComplexType;
            if (type != null) { 
                CompileComplexType(type);
            } 
            return type; 
        }
 
         private XmlSchemaType GetAnySchemaType(XmlQualifiedName name) {
                XmlSchemaType type = (XmlSchemaType)schemaTypes[name];
                if (type != null) {
                    if (type is XmlSchemaComplexType) { 
                        CompileComplexType((XmlSchemaComplexType)type);
                    } 
                    else { 
                        CompileSimpleType((XmlSchemaSimpleType)type);
                    } 
                    return type;
                }
                else { //Its is a built-in simpleType
                    XmlSchemaSimpleType simpleType = DatatypeImplementation.GetSimpleTypeFromXsdType(name); 
                    return simpleType;
                } 
        } 

         private void CopyPosition(XmlSchemaObject to, XmlSchemaObject from, bool copyParent) { 
             to.SourceUri = from.SourceUri;
             to.LinePosition = from.LinePosition;
             to.LineNumber = from.LineNumber;
             if (copyParent) { 
                to.Parent = from.Parent;
             } 
         } 

         private bool IsFixedEqual(SchemaDeclBase baseDecl, SchemaDeclBase derivedDecl) { 

            if (baseDecl.Presence == SchemaDeclBase.Use.Fixed || baseDecl.Presence == SchemaDeclBase.Use.RequiredFixed) {
                object baseFixedValue = baseDecl.DefaultValueTyped;
                object derivedFixedValue = derivedDecl.DefaultValueTyped; 

                Debug.Assert(baseFixedValue != null); 
                if (derivedDecl.Presence != SchemaDeclBase.Use.Fixed && derivedDecl.Presence != SchemaDeclBase.Use.RequiredFixed) { 
                    return false;
                } 
                Debug.Assert(derivedFixedValue != null);
                XmlSchemaDatatype baseDatatype = baseDecl.Datatype;
                XmlSchemaDatatype derivedDatatype = derivedDecl.Datatype;
 
                if (baseDatatype.Variety == XmlSchemaDatatypeVariety.Union) {
                    if (derivedDatatype.Variety == XmlSchemaDatatypeVariety.Union) { 
                        if ( !derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue) ) { 
                            return false;
                        } 
                    }
                    else { //Base is union and derived is member of union
                        XsdSimpleValue simpleFixedValue = baseDecl.DefaultValueTyped as XsdSimpleValue;
                        Debug.Assert(simpleFixedValue != null); 
                        XmlSchemaDatatype memberType = simpleFixedValue.XmlType.Datatype;
                        if (!memberType.IsComparable(derivedDatatype) || !derivedDatatype.IsEqual(simpleFixedValue.TypedValue, derivedFixedValue)) { //base type {Union of long & string}, derived type {int} 
                            return false; 
                        }
                    } 
                }
                else if (!derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue)) {
                    return false;
                } 
            }
            return true; 
         } 
    };
 
} // namespace System.Xml

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Xml.Schema { 

    using System; 
    using System.Collections;
    using System.Globalization;
    using System.Text;
    using System.Diagnostics; 

    internal sealed class Compiler : BaseProcessor { 
        string restrictionErrorMsg; 
        XmlSchemaObjectTable attributes = new XmlSchemaObjectTable();
        XmlSchemaObjectTable attributeGroups = new XmlSchemaObjectTable(); 
        XmlSchemaObjectTable elements = new XmlSchemaObjectTable();
        XmlSchemaObjectTable schemaTypes = new XmlSchemaObjectTable();
        XmlSchemaObjectTable groups = new XmlSchemaObjectTable();
        XmlSchemaObjectTable notations = new XmlSchemaObjectTable(); 
        XmlSchemaObjectTable examplars = new XmlSchemaObjectTable();
        XmlSchemaObjectTable identityConstraints = new XmlSchemaObjectTable(); 
        Stack complexTypeStack = new Stack(); 
        Hashtable schemasToCompile = new Hashtable();
        Hashtable importedSchemas = new Hashtable(); 

        XmlSchema schemaForSchema;

        public Compiler(XmlNameTable nameTable, ValidationEventHandler eventHandler, XmlSchema schemaForSchema, XmlSchemaCompilationSettings compilationSettings) : base(nameTable, null, eventHandler, compilationSettings) { 
            this.schemaForSchema = schemaForSchema;
        } 
 
        public bool Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo) {
            Compile(); 
            if (!HasErrors) {
                Output(schemaCompiledInfo);
                schemaSet.elements = elements;
                schemaSet.attributes = attributes; 
                schemaSet.schemaTypes = schemaTypes;
                schemaSet.substitutionGroups = examplars; 
            } 
            return !HasErrors;
        } 

        internal void Prepare(XmlSchema schema, bool cleanup) {
            if (schemasToCompile[schema] != null) {
                return; 
            }
            schemasToCompile.Add(schema, schema); 
            foreach (XmlSchemaElement element in schema.Elements.Values) { 
                if (cleanup) {
                    CleanupElement(element); 
                }
                AddToTable(elements, element.QualifiedName, element);
            }
            foreach (XmlSchemaAttribute attribute in schema.Attributes.Values) { 
                if (cleanup) {
                    CleanupAttribute(attribute); 
                } 
                AddToTable(attributes, attribute.QualifiedName, attribute);
            } 
            foreach (XmlSchemaGroup group in schema.Groups.Values) {
                if (cleanup) {
                    CleanupGroup(group);
                } 
                AddToTable(groups, group.QualifiedName, group);
            } 
            foreach (XmlSchemaAttributeGroup attributeGroup in schema.AttributeGroups.Values) { 
                if (cleanup) {
                    CleanupAttributeGroup(attributeGroup); 
                }
                AddToTable(attributeGroups, attributeGroup.QualifiedName, attributeGroup);
            }
            foreach (XmlSchemaType type in schema.SchemaTypes.Values) { 
                if (cleanup) {
                    XmlSchemaComplexType ct = type as XmlSchemaComplexType; 
                    if (ct != null) { 
                        CleanupComplexType(ct);
                    } 
                    else {
                        CleanupSimpleType(type as XmlSchemaSimpleType);
                    }
                } 
                AddToTable(schemaTypes, type.QualifiedName, type);
            } 
            foreach (XmlSchemaNotation notation in schema.Notations.Values) { 
                AddToTable(notations, notation.QualifiedName, notation);
            } 
            foreach (XmlSchemaIdentityConstraint ic in schema.IdentityConstraints.Values) {
                AddToTable(identityConstraints, ic.QualifiedName, ic);
            }
        } 

        private void UpdateSForSSimpleTypes() { 
            Debug.Assert(schemaForSchema != null); 
            XmlSchemaSimpleType[] schemaSimpleTypes = DatatypeImplementation.GetBuiltInTypes();
            XmlSchemaSimpleType builtInType; 
            //Using enumToTypeCode array; indexed by XmlTypeCode; Start indexing from 12 since schema types start there and iterate till Length - 2 as the last 2 are xquery types
            int numberOfSchemaTypes = schemaSimpleTypes.Length - 3; //skip last 2 xquery types
            for (int i = 12; i < numberOfSchemaTypes; i++) {
                builtInType = schemaSimpleTypes[i]; 
                schemaForSchema.SchemaTypes.Replace(builtInType.QualifiedName, builtInType);
                this.schemaTypes.Replace(builtInType.QualifiedName, builtInType); 
            } 
        }
 
        private void Output(SchemaInfo schemaInfo) {
            string tns;
            foreach(XmlSchema schema in schemasToCompile.Values) {
                tns = schema.TargetNamespace; 
                if (tns == null) {
                    tns = string.Empty; 
                } 
                schemaInfo.TargetNamespaces[tns] = tns;
            } 
            foreach (XmlSchemaElement element in elements.Values) {
                schemaInfo.ElementDecls.Add(element.QualifiedName, element.ElementDecl);
            }
            foreach (XmlSchemaAttribute attribute in attributes.Values) { 
                schemaInfo.AttributeDecls.Add(attribute.QualifiedName, attribute.AttDef);
            } 
            foreach (XmlSchemaType type in schemaTypes.Values) { 
                schemaInfo.ElementDeclsByType.Add(type.QualifiedName, type.ElementDecl);
            } 
            foreach (XmlSchemaNotation notation in notations.Values) {
                SchemaNotation no = new SchemaNotation(notation.QualifiedName);
                no.SystemLiteral = notation.System;
                no.Pubid = notation.Public; 
                if (schemaInfo.Notations[no.Name.Name] == null) {
                    schemaInfo.Notations.Add(no.Name.Name, no); 
                } 
            }
 
        }

        internal void ImportAllCompiledSchemas(XmlSchemaSet schemaSet) {
              XmlSchema currentSchema; 
              int schemaIndex;
              SortedList schemas = schemaSet.SortedSchemas; 
              for (schemaIndex = 0; schemaIndex < schemas.Count; schemaIndex++) { 
                  currentSchema = (XmlSchema)schemas.GetByIndex(schemaIndex);
                  if (currentSchema.IsCompiledBySet) { //Import already compiled schemas 
                    Prepare(currentSchema, false);
                  }
              }
        } 

        internal bool Compile() { 
            schemaTypes.Insert(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType); 
            if (schemaForSchema != null) { //Get our built-in types
                schemaForSchema.SchemaTypes.Replace(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType); 
                UpdateSForSSimpleTypes();
            }
            foreach(XmlSchemaGroup group in groups.Values) {
                CompileGroup(group); 
            }
            foreach(XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) { 
                CompileAttributeGroup(attributeGroup); 
            }
            foreach (XmlSchemaType type in schemaTypes.Values) { 
                XmlSchemaComplexType ct = type as XmlSchemaComplexType;
                if (ct != null) {
                    CompileComplexType(ct);
                } 
                else {
                    CompileSimpleType((XmlSchemaSimpleType)type); 
                } 
            }
            foreach (XmlSchemaElement element in elements.Values) { 
                if (element.ElementDecl == null) {
                    CompileElement(element);
                }
            } 
            foreach (XmlSchemaAttribute attribute in attributes.Values) {
                if (attribute.AttDef == null) { 
                    CompileAttribute(attribute); 
                }
            } 
            foreach (XmlSchemaIdentityConstraint identityConstraint in identityConstraints.Values) {
                if (identityConstraint.CompiledConstraint == null) {
                    CompileIdentityConstraint(identityConstraint);
                } 
            }
            while (this.complexTypeStack.Count > 0) { 
                XmlSchemaComplexType type = (XmlSchemaComplexType)complexTypeStack.Pop(); 
                CompileComplexTypeElements(type);
            } 

            ProcessSubstitutionGroups();

            foreach (XmlSchemaType type in schemaTypes.Values) { 
                XmlSchemaComplexType localType = type as XmlSchemaComplexType;
                if (localType != null) { 
                    CheckParticleDerivation(localType); 
                }
            } 

            foreach (XmlSchemaElement element in elements.Values) {
                XmlSchemaComplexType localComplexType = element.ElementSchemaType as XmlSchemaComplexType;
                if (localComplexType != null && element.SchemaTypeName == XmlQualifiedName.Empty) { // only local schemaTypes 
                    CheckParticleDerivation(localComplexType);
                } 
            } 
            foreach (XmlSchemaGroup group in groups.Values) { //Check particle derivation for redefined groups
                XmlSchemaGroup baseGroup = group.Redefined; 
                if (baseGroup != null) {
                    RecursivelyCheckRedefinedGroups(group, baseGroup);
                }
            } 

            foreach (XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) { 
                XmlSchemaAttributeGroup baseAttributeGroup = attributeGroup.Redefined; 
                if (baseAttributeGroup != null) {
                    RecursivelyCheckRedefinedAttributeGroups(attributeGroup, baseAttributeGroup); 
                }
            }
            return !HasErrors;
        } 

        private void CleanupAttribute(XmlSchemaAttribute attribute) { 
            if (attribute.SchemaType != null) { 
                CleanupSimpleType((XmlSchemaSimpleType)attribute.SchemaType);
            } 
            attribute.AttDef = null;
        }

        private void CleanupAttributeGroup(XmlSchemaAttributeGroup attributeGroup) { 
            CleanupAttributes(attributeGroup.Attributes);
            attributeGroup.AttributeUses.Clear(); 
            attributeGroup.AttributeWildcard = null; 
            if (attributeGroup.Redefined != null) {
                CleanupAttributeGroup(attributeGroup.Redefined); 
            }
        }

        private void CleanupComplexType(XmlSchemaComplexType complexType) { 
            if (complexType.QualifiedName == DatatypeImplementation.QnAnyType) { //if it is built-in anyType dont clean it.
                return; 
            } 
            if (complexType.ContentModel != null) { //simpleContent or complexContent
                if (complexType.ContentModel is XmlSchemaSimpleContent) { 
                    XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
                    if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
                        XmlSchemaSimpleContentExtension simpleExtension = (XmlSchemaSimpleContentExtension)simpleContent.Content;
                        CleanupAttributes(simpleExtension.Attributes); 
                    }
                    else { //simpleContent.Content is XmlSchemaSimpleContentRestriction 
                        XmlSchemaSimpleContentRestriction simpleRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content; 
                        CleanupAttributes(simpleRestriction.Attributes);
                    } 
                }
                else { // complexType.ContentModel is XmlSchemaComplexContent
                    XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
                    if (complexContent.Content is XmlSchemaComplexContentExtension) { 
                        XmlSchemaComplexContentExtension complexExtension = (XmlSchemaComplexContentExtension)complexContent.Content;
                        CleanupParticle(complexExtension.Particle); 
                        CleanupAttributes(complexExtension.Attributes); 

                    } 
                    else { //XmlSchemaComplexContentRestriction
                        XmlSchemaComplexContentRestriction complexRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content;
                        CleanupParticle(complexRestriction.Particle);
                        CleanupAttributes(complexRestriction.Attributes); 
                    }
                } 
            } 
            else { //equals XmlSchemaComplexContent with baseType is anyType
                CleanupParticle(complexType.Particle); 
                CleanupAttributes(complexType.Attributes);
            }
            complexType.LocalElements.Clear();
            complexType.AttributeUses.Clear(); 
            complexType.SetAttributeWildcard(null);
            complexType.SetContentTypeParticle(XmlSchemaParticle.Empty); 
            complexType.ElementDecl = null; 
            complexType.HasDuplicateDecls = false;
            complexType.HasWildCard = false; 

            //Clean up the original type if this is a redefined type
            if (complexType.Redefined != null) {
                CleanupComplexType(complexType.Redefined as XmlSchemaComplexType); 
            }
        } 
 
        private void CleanupSimpleType(XmlSchemaSimpleType simpleType) {
            if (simpleType == XmlSchemaType.GetBuiltInSimpleType(simpleType.TypeCode)) { //If it is a built-in simple type dont clean up 
                return;
            }
            simpleType.ElementDecl = null;
            //Clean up the original group if this is a redefined group 
            if (simpleType.Redefined != null) {
                CleanupSimpleType(simpleType.Redefined as XmlSchemaSimpleType); 
            } 
        }
 
        private void CleanupElement(XmlSchemaElement element) {
            if (element.SchemaType != null) {
                XmlSchemaComplexType complexType = element.SchemaType as XmlSchemaComplexType;
                if (complexType != null) { 
                    CleanupComplexType(complexType);
                } 
                else { 
                    CleanupSimpleType((XmlSchemaSimpleType)element.SchemaType);
                } 
            }
            foreach (XmlSchemaIdentityConstraint constr in element.Constraints) {
                constr.CompiledConstraint = null;
            } 
            element.ElementDecl = null;
            element.IsLocalTypeDerivationChecked = false; //clear Local element type derivation check 
        } 

        private void CleanupAttributes(XmlSchemaObjectCollection attributes) { 
            foreach (XmlSchemaObject obj in attributes) {
                if (obj is XmlSchemaAttribute) {
                    CleanupAttribute((XmlSchemaAttribute)obj);
                } 
            }
        } 
 
        private void CleanupGroup(XmlSchemaGroup group) {
            CleanupParticle(group.Particle); 
            group.CanonicalParticle = null;
            //Clean up the original group if this is a redefined group
            if (group.Redefined != null) {
                CleanupGroup(group.Redefined); 
            }
        } 
 
        private void CleanupParticle(XmlSchemaParticle particle) {
            if (particle is XmlSchemaElement) { 
                CleanupElement((XmlSchemaElement)particle);
            }
            else if (particle is XmlSchemaGroupBase) {
                foreach(XmlSchemaParticle p in ((XmlSchemaGroupBase)particle).Items) { 
                    CleanupParticle(p);
                } 
            } 
        }
 
        private void ProcessSubstitutionGroups() {
            foreach (XmlSchemaElement element in this.elements.Values) {
                if (!element.SubstitutionGroup.IsEmpty) {
                    XmlSchemaElement headElement = this.elements[element.SubstitutionGroup] as XmlSchemaElement; 
                    if (headElement == null) {
                        SendValidationEvent(Res.Sch_NoExamplar, element); 
                        continue; 
                    }
                    //Check derivation of member's type against head's type 
                    if (!XmlSchemaType.IsDerivedFrom(element.ElementSchemaType, headElement.ElementSchemaType, headElement.FinalResolved)) {
                        SendValidationEvent(Res.Sch_InvalidSubstitutionMember, (element.QualifiedName).ToString(), (headElement.QualifiedName).ToString(), element);
                    }
                    if ((headElement.BlockResolved & XmlSchemaDerivationMethod.Substitution) != 0) { //head element blocks substitution, dont build substGroup 
                        continue;
                    } 
                    //Create substitutionGroup 
                    XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)this.examplars[element.SubstitutionGroup];
                    if (substitutionGroup == null) { 
                        substitutionGroup = new XmlSchemaSubstitutionGroup();
                        substitutionGroup.Examplar = element.SubstitutionGroup;
                        examplars.Add(element.SubstitutionGroup, substitutionGroup);
                    } 
                    ArrayList members = substitutionGroup.Members;
                    if (!members.Contains(element)) { //Members might contain element if the same schema is included and imported through different paths. Imp, hence will be added to set directly 
                        members.Add(element); 
                    }
                } 
            }

            //Check the subst groups that we just built
            foreach (XmlSchemaSubstitutionGroup substitutionGroup in examplars.Values) { 
                CompileSubstitutionGroup(substitutionGroup);
            } 
        } 
        private void CompileSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup) {
            if (substitutionGroup.IsProcessing) { 
                foreach (XmlSchemaElement element in substitutionGroup.Members) {
                    SendValidationEvent(Res.Sch_SubstitutionCircularRef, element);
                    return;
                } 
            }
            XmlSchemaElement examplar = (XmlSchemaElement)elements[substitutionGroup.Examplar]; 
            Debug.Assert(examplar != null); //Headelement presence is checked while building subst groups 
            if (substitutionGroup.Members.Contains(examplar)) {// already checked
                return; 
            }
            substitutionGroup.IsProcessing = true;
            try {
                if (examplar.FinalResolved == XmlSchemaDerivationMethod.All) { 
                    SendValidationEvent(Res.Sch_InvalidExamplar, examplar);
                } 
                //Build transitive members 
                ArrayList newMembers = null;
                foreach (XmlSchemaElement element in substitutionGroup.Members) { 
                    //Chain to other head's that are members of this head's substGroup
                    XmlSchemaSubstitutionGroup g = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName];
                    if (g != null) {
                        CompileSubstitutionGroup(g); 
                        foreach (XmlSchemaElement element1 in g.Members) {
                            if (element1 != element) { //Exclude the head 
                                if (newMembers == null) { 
                                    newMembers = new ArrayList();
                                } 
                                newMembers.Add(element1);
                            }
                        }
                    } 
                }
                if (newMembers != null) { 
                    foreach (XmlSchemaElement newMember in newMembers) { 
                        substitutionGroup.Members.Add(newMember);
                    } 
                }
                substitutionGroup.Members.Add(examplar); // Compiled mark
            }
            finally { 
                substitutionGroup.IsProcessing = false;
            } 
        } 

        private void RecursivelyCheckRedefinedGroups(XmlSchemaGroup redefinedGroup, XmlSchemaGroup baseGroup) { 
            if (baseGroup.Redefined != null) {
                RecursivelyCheckRedefinedGroups(baseGroup, baseGroup.Redefined);
            }
            if (redefinedGroup.SelfReferenceCount == 0) { 
                if (baseGroup.CanonicalParticle == null) {
                    baseGroup.CanonicalParticle = CannonicalizeParticle(baseGroup.Particle, true); 
                } 
                if (redefinedGroup.CanonicalParticle == null) {
                    redefinedGroup.CanonicalParticle = CannonicalizeParticle(redefinedGroup.Particle, true); 
                }
                CompileParticleElements(redefinedGroup.CanonicalParticle);
                CompileParticleElements(baseGroup.CanonicalParticle);
                CheckParticleDerivation(redefinedGroup.CanonicalParticle, baseGroup.CanonicalParticle); 
            }
        } 
 
        private void RecursivelyCheckRedefinedAttributeGroups(XmlSchemaAttributeGroup attributeGroup, XmlSchemaAttributeGroup baseAttributeGroup) {
            if (baseAttributeGroup.Redefined != null) { 
                RecursivelyCheckRedefinedAttributeGroups(baseAttributeGroup, baseAttributeGroup.Redefined);
            }
            if (attributeGroup.SelfReferenceCount == 0) {
                CompileAttributeGroup(baseAttributeGroup); 
                CompileAttributeGroup(attributeGroup);
                CheckAtrributeGroupRestriction(baseAttributeGroup, attributeGroup); 
            } 
        }
 
        private void CompileGroup(XmlSchemaGroup group) {
            if (group.IsProcessing) {
                SendValidationEvent(Res.Sch_GroupCircularRef, group);
                group.CanonicalParticle = XmlSchemaParticle.Empty; 
            }
            else { 
                group.IsProcessing = true; 
                if (group.CanonicalParticle == null) {
                    group.CanonicalParticle = CannonicalizeParticle(group.Particle, true); 
                }
                Debug.Assert(group.CanonicalParticle != null);
                group.IsProcessing = false; //Not enclosung in try -finally as cannonicalizeParticle will not throw exception
            } 
        }
 
        private void CompileSimpleType(XmlSchemaSimpleType simpleType) { 
            if (simpleType.IsProcessing) {
                throw new XmlSchemaException(Res.Sch_TypeCircularRef, simpleType); 
            }
            if (simpleType.ElementDecl != null) { // already compiled
                return;
            } 
            simpleType.IsProcessing = true;
            try { 
                if (simpleType.Content is XmlSchemaSimpleTypeList) { 
                    XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)simpleType.Content;
                    XmlSchemaDatatype datatype; 
                    simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType);
                    if (list.ItemTypeName.IsEmpty) {
                        CompileSimpleType(list.ItemType);
                        list.BaseItemType = list.ItemType; 
                        datatype = list.ItemType.Datatype;
                    } 
                    else { 
                        XmlSchemaSimpleType type = GetSimpleType(list.ItemTypeName);
                        if (type != null) { 
                            if ((type.FinalResolved & XmlSchemaDerivationMethod.List) != 0) {
                                SendValidationEvent(Res.Sch_BaseFinalList, simpleType);
                            }
                            list.BaseItemType = type; 
                            datatype = type.Datatype;
                        } 
                        else { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, list.ItemTypeName.ToString(), list);
                        } 
                    }
                    simpleType.SetDatatype(datatype.DeriveByList(simpleType));
                    simpleType.SetDerivedBy(XmlSchemaDerivationMethod.List);
                } 
                else if (simpleType.Content is XmlSchemaSimpleTypeRestriction) {
                    XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content; 
                    XmlSchemaDatatype datatype; 
                    if (restriction.BaseTypeName.IsEmpty) {
                        CompileSimpleType(restriction.BaseType); 
                        simpleType.SetBaseSchemaType(restriction.BaseType);
                        datatype = restriction.BaseType.Datatype;
                    }
                    else if (simpleType.Redefined != null && restriction.BaseTypeName == simpleType.Redefined.QualifiedName) { 
                        CompileSimpleType((XmlSchemaSimpleType)simpleType.Redefined);
                        simpleType.SetBaseSchemaType(simpleType.Redefined.BaseXmlSchemaType); 
                        datatype = simpleType.Redefined.Datatype; 
                    }
                    else { 
                        if (restriction.BaseTypeName.Equals(DatatypeImplementation.QnAnySimpleType)) {
                            XmlSchema parentSchema = Preprocessor.GetParentSchema(simpleType);
                            if (parentSchema.TargetNamespace != XmlSchema.Namespace) { //If it is not SForS, then error
                                throw new XmlSchemaException(Res.Sch_InvalidSimpleTypeRestriction, restriction.BaseTypeName.ToString(), simpleType); 
                            }
                        } 
                        XmlSchemaSimpleType type = GetSimpleType(restriction.BaseTypeName); 
                        if (type != null) {
                            if ((type.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) { 
                                SendValidationEvent(Res.Sch_BaseFinalRestriction, simpleType);
                            }
                            simpleType.SetBaseSchemaType(type);
                            datatype = type.Datatype; 
                        }
                        else { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, restriction.BaseTypeName.ToString(), restriction); 
                        }
                    } 
                    simpleType.SetDatatype(datatype.DeriveByRestriction(restriction.Facets, NameTable, simpleType));
                    simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
                }
                else { //simpleType.Content is XmlSchemaSimpleTypeUnion 
                    XmlSchemaSimpleType[] baseTypes = CompileBaseMemberTypes(simpleType);
                    simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType); 
                    simpleType.SetDatatype(XmlSchemaDatatype.DeriveByUnion(baseTypes, simpleType)); 
                    simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Union);
                } 
            }
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) {
                    e.SetSource(simpleType); 
                }
                SendValidationEvent(e); 
                simpleType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype); 
            }
            finally { 
                SchemaElementDecl decl = new SchemaElementDecl();
                decl.ContentValidator = ContentValidator.TextOnly;
                decl.SchemaType = simpleType;
                decl.Datatype = simpleType.Datatype; 
                simpleType.ElementDecl = decl;
                simpleType.IsProcessing = false; 
            } 
        }
 
        private XmlSchemaSimpleType[] CompileBaseMemberTypes(XmlSchemaSimpleType simpleType) {
            XmlSchemaSimpleType unionMember;
            ArrayList memberTypeDefinitions = new ArrayList();
 
            XmlSchemaSimpleTypeUnion mainUnion = (XmlSchemaSimpleTypeUnion)simpleType.Content;
 
            Array mainMemberTypes = mainUnion.MemberTypes; 
            if (mainMemberTypes != null) {
                foreach(XmlQualifiedName memberName in mainMemberTypes) { 
                    unionMember = GetSimpleType(memberName);
                    if (unionMember != null) {
                        if (unionMember.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
                            CheckUnionType(unionMember, memberTypeDefinitions, simpleType); 
                        }
                        else { //its list or atomic 
                            memberTypeDefinitions.Add(unionMember); 
                        }
                        //Check derivation method of the member that is referenced 
                        if ((unionMember.FinalResolved & XmlSchemaDerivationMethod.Union) != 0) {
                            SendValidationEvent(Res.Sch_BaseFinalUnion, simpleType);
                        }
                    } 
                    else {
                        throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, memberName.ToString(), mainUnion); 
                    } 
                }
            } 

            //Now add the baseTypes that are defined inside the union itself
            XmlSchemaObjectCollection mainBaseTypes = mainUnion.BaseTypes; //
            if (mainBaseTypes != null) { 
                foreach(XmlSchemaSimpleType st in mainBaseTypes) {
                    CompileSimpleType(st); 
                    if (st.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union 
                        CheckUnionType(st, memberTypeDefinitions, simpleType);
                    } 
                    else {  //its list or atomic
                        memberTypeDefinitions.Add(st);
                    }
                } 
            }
            //set all types 
            mainUnion.SetBaseMemberTypes(memberTypeDefinitions.ToArray(typeof(XmlSchemaSimpleType)) as XmlSchemaSimpleType[]); 
            return mainUnion.BaseMemberTypes;
        } 

        private void CheckUnionType(XmlSchemaSimpleType unionMember, ArrayList memberTypeDefinitions, XmlSchemaSimpleType parentType) {
            XmlSchemaDatatype unionDatatype = unionMember.Datatype;
            if (unionMember.DerivedBy == XmlSchemaDerivationMethod.Restriction && (unionDatatype.HasLexicalFacets || unionDatatype.HasValueFacets) ) { 
                SendValidationEvent(Res.Sch_UnionFromUnion, parentType);
            } 
            else { 
                Datatype_union uniondt = unionMember.Datatype as Datatype_union;
                memberTypeDefinitions.AddRange(uniondt.BaseMemberTypes); 
            }
        }

        private void CompileComplexType(XmlSchemaComplexType complexType) { 
            if (complexType.ElementDecl != null) { //already compiled
                return; 
            } 
            if (complexType.IsProcessing) {
                SendValidationEvent(Res.Sch_TypeCircularRef, complexType); 
                return;
            }
            complexType.IsProcessing = true;
            try { 
                if (complexType.ContentModel != null) { //simpleContent or complexContent
                    if (complexType.ContentModel is XmlSchemaSimpleContent) { 
                        XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel; 
                        complexType.SetContentType(XmlSchemaContentType.TextOnly);
                        if (simpleContent.Content is XmlSchemaSimpleContentExtension) { 
                            CompileSimpleContentExtension(complexType, (XmlSchemaSimpleContentExtension)simpleContent.Content);
                        }
                        else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
                            CompileSimpleContentRestriction(complexType, (XmlSchemaSimpleContentRestriction)simpleContent.Content); 
                        }
                    } 
                    else { // complexType.ContentModel is XmlSchemaComplexContent 
                        XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
                        if (complexContent.Content is XmlSchemaComplexContentExtension) { 
                            CompileComplexContentExtension(complexType, complexContent, (XmlSchemaComplexContentExtension)complexContent.Content);
                        }
                        else { // complexContent.Content is XmlSchemaComplexContentRestriction
                            CompileComplexContentRestriction(complexType, complexContent, (XmlSchemaComplexContentRestriction)complexContent.Content); 
                        }
                    } 
                } 
                else { //equals XmlSchemaComplexContent with baseType is anyType
                        complexType.SetBaseSchemaType(XmlSchemaComplexType.AnyType); 
                        CompileLocalAttributes(XmlSchemaComplexType.AnyType, complexType, complexType.Attributes, complexType.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
                        complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
                        complexType.SetContentTypeParticle(CompileContentTypeParticle(complexType.Particle));
                        complexType.SetContentType(GetSchemaContentType(complexType, null, complexType.ContentTypeParticle)); 
                }
                if (complexType.ContainsIdAttribute(true)) { 
                    SendValidationEvent(Res.Sch_TwoIdAttrUses, complexType); 
                }
                SchemaElementDecl decl = new SchemaElementDecl(); 
                decl.ContentValidator = CompileComplexContent(complexType);
                decl.SchemaType = complexType;
                decl.IsAbstract = complexType.IsAbstract;
                decl.Datatype = complexType.Datatype; 
                decl.Block = complexType.BlockResolved;
                decl.AnyAttribute = complexType.AttributeWildcard; 
                foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) { 
                    if (attribute.Use == XmlSchemaUse.Prohibited) {
                        if (decl.ProhibitedAttributes[attribute.QualifiedName] == null) { 
                            decl.ProhibitedAttributes.Add(attribute.QualifiedName, attribute.QualifiedName);
                        }
                    }
                    else { 
                        if (decl.AttDefs[attribute.QualifiedName] == null && attribute.AttDef != null && attribute.AttDef.Name != XmlQualifiedName.Empty && attribute.AttDef != SchemaAttDef.Empty) {
                            decl.AddAttDef(attribute.AttDef); 
                        } 
                    }
                } 
                decl.EndAddAttDef();
                complexType.ElementDecl = decl;
            }
            finally { 
                complexType.IsProcessing = false;
            } 
        } 

 
        private void CompileSimpleContentExtension(XmlSchemaComplexType complexType, XmlSchemaSimpleContentExtension simpleExtension) {
            XmlSchemaComplexType baseType = null;
            if (complexType.Redefined != null && simpleExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
                baseType = (XmlSchemaComplexType)complexType.Redefined; 
                CompileComplexType(baseType);
                complexType.SetBaseSchemaType(baseType); 
                complexType.SetDatatype(baseType.Datatype); 
            }
            else { 
                XmlSchemaType bto = GetAnySchemaType(simpleExtension.BaseTypeName);
                if (bto == null) {
                    SendValidationEvent(Res.Sch_UndeclaredType, simpleExtension.BaseTypeName.ToString(), simpleExtension);
                } 
                else {
                    complexType.SetBaseSchemaType(bto); 
                    complexType.SetDatatype(bto.Datatype); 
                }
                baseType = bto as XmlSchemaComplexType; 
            }
            if (baseType != null) {
                if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
                    SendValidationEvent(Res.Sch_BaseFinalExtension, complexType); 
                }
                if (baseType.ContentType != XmlSchemaContentType.TextOnly) { 
                    SendValidationEvent(Res.Sch_NotSimpleContent, complexType); 
                }
            } 
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
            CompileLocalAttributes(baseType, complexType, simpleExtension.Attributes, simpleExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
        }
 
        private void CompileSimpleContentRestriction(XmlSchemaComplexType complexType, XmlSchemaSimpleContentRestriction simpleRestriction) {
            XmlSchemaComplexType baseType = null; 
            XmlSchemaDatatype datatype = null; 
            if (complexType.Redefined != null && simpleRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
                baseType = (XmlSchemaComplexType)complexType.Redefined; 
                CompileComplexType(baseType);
                datatype = baseType.Datatype;
            }
            else { 
                baseType = GetComplexType(simpleRestriction.BaseTypeName);
                if (baseType == null) { 
                    SendValidationEvent(Res.Sch_UndefBaseRestriction, simpleRestriction.BaseTypeName.ToString(), simpleRestriction); 
                    return;
                } 
                if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
                    if (simpleRestriction.BaseType == null) {
                        datatype = baseType.Datatype;
                        //There is a bug here. Need to check if simpleRestriction has facets. 
                        //If yes, Need tp apply these facets as well.
                    } 
                    else { 
                        CompileSimpleType(simpleRestriction.BaseType);
                        if(!XmlSchemaType.IsDerivedFromDatatype(simpleRestriction.BaseType.Datatype, baseType.Datatype, XmlSchemaDerivationMethod.None)) { 
                           SendValidationEvent(Res.Sch_DerivedNotFromBase, simpleRestriction);
                        }
                        datatype = simpleRestriction.BaseType.Datatype;
                    } 
                }
                else if (baseType.ContentType == XmlSchemaContentType.Mixed && baseType.ElementDecl.ContentValidator.IsEmptiable) { 
                    if (simpleRestriction.BaseType != null) { 
                        CompileSimpleType(simpleRestriction.BaseType);
                        complexType.SetBaseSchemaType(simpleRestriction.BaseType); 
                        datatype = simpleRestriction.BaseType.Datatype;
                    }
                    else {
                        SendValidationEvent(Res.Sch_NeedSimpleTypeChild, simpleRestriction); 
                    }
                } 
                else { 
                    SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
                } 
            }
            if (baseType != null && baseType.ElementDecl != null) {
                if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
                    SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType); 
                }
            } 
            if (baseType != null) { 
                complexType.SetBaseSchemaType(baseType);
            } 
            if (datatype != null) {
                try {
                    complexType.SetDatatype(datatype.DeriveByRestriction(simpleRestriction.Facets, NameTable, complexType));
                } 
                catch (XmlSchemaException e) {
                    if (e.SourceSchemaObject == null) { 
                        e.SetSource(complexType); 
                    }
                    SendValidationEvent(e); 
                    complexType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
                }
            }
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction); 
            CompileLocalAttributes(baseType, complexType, simpleRestriction.Attributes, simpleRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
        } 
 
        private void CompileComplexContentExtension(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentExtension complexExtension) {
            XmlSchemaComplexType baseType = null; 
            if (complexType.Redefined != null && complexExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
                baseType = (XmlSchemaComplexType)complexType.Redefined;
                CompileComplexType(baseType);
            } 
            else {
                baseType = GetComplexType(complexExtension.BaseTypeName); 
                if (baseType == null) { 
                    SendValidationEvent(Res.Sch_UndefBaseExtension, complexExtension.BaseTypeName.ToString(), complexExtension);
                    return; 
                }
            }
            if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
                SendValidationEvent(Res.Sch_BaseFinalExtension, complexType); 
            }
            CompileLocalAttributes(baseType, complexType, complexExtension.Attributes, complexExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension); 
 
            XmlSchemaParticle baseParticle = baseType.ContentTypeParticle;
            XmlSchemaParticle extendedParticle = CannonicalizeParticle(complexExtension.Particle, true); 
            if (baseParticle != XmlSchemaParticle.Empty) {
                if (extendedParticle != XmlSchemaParticle.Empty) {
                    XmlSchemaSequence compiledParticle = new XmlSchemaSequence();
                    compiledParticle.Items.Add(baseParticle); 
                    compiledParticle.Items.Add(extendedParticle);
                    complexType.SetContentTypeParticle(CompileContentTypeParticle(compiledParticle)); 
                } 
                else {
                    complexType.SetContentTypeParticle(baseParticle); 
                }
            }
            else {
                complexType.SetContentTypeParticle(extendedParticle); 
            }
            XmlSchemaContentType contentType = GetSchemaContentType(complexType, complexContent, extendedParticle); 
            if (contentType == XmlSchemaContentType.Empty) { //Derived content type is empty, Get ContentType from base 
                contentType = baseType.ContentType;
            } 
            complexType.SetContentType(contentType);

            if (baseType.ContentType != XmlSchemaContentType.Empty && complexType.ContentType != baseType.ContentType) { //If base is empty, do not check
                SendValidationEvent(Res.Sch_DifContentType, complexType); 
                return;
            } 
            complexType.SetBaseSchemaType(baseType); 
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
        } 

        private void CompileComplexContentRestriction(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentRestriction complexRestriction) {
            XmlSchemaComplexType baseType = null;
            if (complexType.Redefined != null && complexRestriction.BaseTypeName == complexType.Redefined.QualifiedName) { 
                baseType = (XmlSchemaComplexType)complexType.Redefined;
                CompileComplexType(baseType); 
            } 
            else {
                baseType = GetComplexType(complexRestriction.BaseTypeName); 
                if (baseType == null) {
                    SendValidationEvent(Res.Sch_UndefBaseRestriction, complexRestriction.BaseTypeName.ToString(), complexRestriction);
                    return;
                } 
            }
            complexType.SetBaseSchemaType(baseType); 
            if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) { 
                SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
            } 
            CompileLocalAttributes(baseType, complexType, complexRestriction.Attributes, complexRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);

            complexType.SetContentTypeParticle(CompileContentTypeParticle(complexRestriction.Particle));
            XmlSchemaContentType derivedContentType = GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle); 
            complexType.SetContentType(derivedContentType);
            switch(derivedContentType) { 
                case XmlSchemaContentType.Empty: 
                    if (baseType.ElementDecl != null && !baseType.ElementDecl.ContentValidator.IsEmptiable) { //base is either TextOnly or its ElementOnly/Mixed and not emptiable
                        SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToEmpty), complexType); 
                    }
                break;

                case XmlSchemaContentType.Mixed: 
                    if (baseType.ContentType != XmlSchemaContentType.Mixed) {
                        SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToMixed), complexType); 
                    } 
                break;
            } 
            complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
        }

        private void CheckParticleDerivation(XmlSchemaComplexType complexType) { 
            XmlSchemaComplexType baseType = complexType.BaseXmlSchemaType as XmlSchemaComplexType;
            restrictionErrorMsg = null; 
            if (baseType != null && baseType != XmlSchemaComplexType.AnyType && complexType.DerivedBy == XmlSchemaDerivationMethod.Restriction) { 
                XmlSchemaParticle derivedParticle = CannonicalizePointlessRoot(complexType.ContentTypeParticle);
                XmlSchemaParticle baseParticle = CannonicalizePointlessRoot(baseType.ContentTypeParticle); 
                if (!IsValidRestriction(derivedParticle, baseParticle)) {
#if DEBUG
                    if(complexType.ContentTypeParticle != null && baseType.ContentTypeParticle != null) {
                        string position = string.Empty; 
                        if (complexType.SourceUri != null) {
                            position = " in " + complexType.SourceUri + "(" + complexType.LineNumber + ", " + complexType.LinePosition + ")"; 
                        } 
                        Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType content restriction" + position);
                        Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpContentModel(baseType.ContentTypeParticle)); 
                        Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpContentModel(complexType.ContentTypeParticle));
                    }
#endif
                    if (restrictionErrorMsg != null) { 
                        SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, complexType);
                    } 
                    else { 
                        SendValidationEvent(Res.Sch_InvalidParticleRestriction, complexType);
                    } 
                }
            }
            else if (baseType == XmlSchemaComplexType.AnyType) { //The complex type itself is not explicitly derived by restriction but it could have local elements which have anonymous types that are derived by restriction
                foreach(XmlSchemaElement localElement in complexType.LocalElements.Values) { 
                    if (localElement.IsLocalTypeDerivationChecked) { //Element already checked
                        continue; 
                    } 
                    XmlSchemaComplexType localComplexType = localElement.ElementSchemaType as XmlSchemaComplexType;
                    if (localComplexType != null && localElement.SchemaTypeName == XmlQualifiedName.Empty && localElement.RefName == XmlQualifiedName.Empty) { //Only local elements 
                        localElement.IsLocalTypeDerivationChecked = true; //Not clearing this flag after recursion to make sure this check is not repeated for multiple references of the same local element (through group refs)
                        CheckParticleDerivation(localComplexType);
                    }
                } 
            }
        } 
 
        private void CheckParticleDerivation(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
            restrictionErrorMsg = null; 
            derivedParticle = CannonicalizePointlessRoot(derivedParticle);
            baseParticle = CannonicalizePointlessRoot(baseParticle);
            if (!IsValidRestriction(derivedParticle, baseParticle)) {
                if (restrictionErrorMsg != null) { 
                    SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, derivedParticle);
                } 
                else { 
                    SendValidationEvent(Res.Sch_InvalidParticleRestriction, derivedParticle);
                } 
            }
        }

        private XmlSchemaParticle CompileContentTypeParticle(XmlSchemaParticle particle) { 
            XmlSchemaParticle ctp = CannonicalizeParticle(particle, true);
            XmlSchemaChoice choice = ctp as XmlSchemaChoice; 
            if (choice != null && choice.Items.Count == 0) { 
                if (choice.MinOccurs != decimal.Zero) {
                    SendValidationEvent(Res.Sch_EmptyChoice, choice, XmlSeverityType.Warning); 
                }
                return XmlSchemaParticle.Empty;
            }
            return ctp; 
        }
 
        private XmlSchemaParticle CannonicalizeParticle(XmlSchemaParticle particle, bool root) { 
            if (particle == null || particle.IsEmpty) {
                return XmlSchemaParticle.Empty; 
            }
            else if (particle is XmlSchemaElement) {
                //return CannonicalizeElement((XmlSchemaElement)particle, substitution);
                return particle; 
            }
            else if (particle is XmlSchemaGroupRef) { 
                return CannonicalizeGroupRef((XmlSchemaGroupRef)particle, root); 
            }
            else if (particle is XmlSchemaAll) { 
                return CannonicalizeAll((XmlSchemaAll)particle, root);
            }
            else if (particle is XmlSchemaChoice) {
                return CannonicalizeChoice((XmlSchemaChoice)particle, root); 
            }
            else if (particle is XmlSchemaSequence) { 
                return CannonicalizeSequence((XmlSchemaSequence)particle, root); 
            }
            else { 
                return particle;
            }
        }
 
        private XmlSchemaParticle CannonicalizeElement(XmlSchemaElement element) {
            if (!element.RefName.IsEmpty && (element.ElementDecl.Block & XmlSchemaDerivationMethod.Substitution) == 0) { 
                XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName]; 
                if (substitutionGroup == null) {
                    return element; 
                }
                else {
                    XmlSchemaChoice choice = new XmlSchemaChoice();
                    foreach(XmlSchemaElement elem in substitutionGroup.Members) { 
                        choice.Items.Add(elem);
                    } 
                    choice.MinOccurs = element.MinOccurs; 
                    choice.MaxOccurs = element.MaxOccurs;
                    CopyPosition(choice, element, false); 
                    return choice;
                }
            }
            else { 
                return element;
            } 
        } 

        private XmlSchemaParticle CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root) { 
            XmlSchemaGroup group;
            if (groupRef.Redefined != null) {
                group = groupRef.Redefined;
            } 
            else {
                group = (XmlSchemaGroup)groups[groupRef.RefName]; 
            } 
            if (group == null) {
                SendValidationEvent(Res.Sch_UndefGroupRef, groupRef.RefName.ToString(), groupRef); 
                return XmlSchemaParticle.Empty;
            }
            if (group.CanonicalParticle == null) {
                CompileGroup(group); 
            }
            if (group.CanonicalParticle == XmlSchemaParticle.Empty) { 
                return XmlSchemaParticle.Empty; 
            }
            XmlSchemaGroupBase groupBase = (XmlSchemaGroupBase)group.CanonicalParticle; 
            if (groupBase is XmlSchemaAll) {
                if (!root) {
                    SendValidationEvent(Res.Sch_AllRefNotRoot, "", groupRef);
                    return XmlSchemaParticle.Empty; 
                }
                if (groupRef.MinOccurs > decimal.One || groupRef.MaxOccurs != decimal.One) { 
                    SendValidationEvent(Res.Sch_AllRefMinMax, groupRef); 
                    return XmlSchemaParticle.Empty;
                } 
            }
            else if (groupBase is XmlSchemaChoice && groupBase.Items.Count == 0) {
                if (groupRef.MinOccurs != decimal.Zero) {
                    SendValidationEvent(Res.Sch_EmptyChoice, groupRef, XmlSeverityType.Warning); 
                }
                return XmlSchemaParticle.Empty; 
            } 
            XmlSchemaGroupBase groupRefBase = (
                (groupBase is XmlSchemaSequence) ? (XmlSchemaGroupBase)new XmlSchemaSequence() : 
                (groupBase is XmlSchemaChoice)   ? (XmlSchemaGroupBase)new XmlSchemaChoice() :
                                                   (XmlSchemaGroupBase)new XmlSchemaAll()
            );
            groupRefBase.MinOccurs = groupRef.MinOccurs; 
            groupRefBase.MaxOccurs = groupRef.MaxOccurs;
            groupRefBase.LineNumber = groupRef.LineNumber; 
            groupRefBase.LinePosition = groupRef.LinePosition; 

            foreach (XmlSchemaParticle particle in groupBase.Items) { 
                groupRefBase.Items.Add(particle);
            }
            groupRef.SetParticle(groupRefBase);
            return groupRefBase; 
        }
 
        private XmlSchemaParticle CannonicalizeAll(XmlSchemaAll all, bool root) { 
            if (all.Items.Count > 0) {
                XmlSchemaAll newAll = new XmlSchemaAll(); 
                newAll.MinOccurs = all.MinOccurs;
                newAll.MaxOccurs = all.MaxOccurs;
                CopyPosition(newAll, all, true);
                foreach (XmlSchemaElement e in all.Items) { 
                    XmlSchemaParticle p = CannonicalizeParticle(e, false);
                    if (p != XmlSchemaParticle.Empty) { 
                        newAll.Items.Add(p); 
                    }
                } 
                all = newAll;
            }
            if (all.Items.Count == 0) {
                return XmlSchemaParticle.Empty; 
            }
            else if (!root) { 
                SendValidationEvent(Res.Sch_NotAllAlone, all); 
                return XmlSchemaParticle.Empty;
            } 
            else {
                return all;
            }
        } 

        private XmlSchemaParticle CannonicalizeChoice(XmlSchemaChoice choice, bool root) { 
            XmlSchemaChoice oldChoice = choice; 
            if (choice.Items.Count > 0) {
                XmlSchemaChoice newChoice = new XmlSchemaChoice(); 
                newChoice.MinOccurs = choice.MinOccurs;
                newChoice.MaxOccurs = choice.MaxOccurs;
                CopyPosition(newChoice, choice, true);
                foreach (XmlSchemaParticle p in choice.Items) { 
                    XmlSchemaParticle p1 = CannonicalizeParticle(p, false);
                    if (p1 != XmlSchemaParticle.Empty) { 
                        if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaChoice) { 
                            foreach (XmlSchemaParticle p2 in ((XmlSchemaChoice)p1).Items) {
                                newChoice.Items.Add(p2); 
                            }
                        }
                        else {
                            newChoice.Items.Add(p1); 
                        }
                    } 
                } 
                choice = newChoice;
            } 
            if (!root && choice.Items.Count == 0) {
                if (choice.MinOccurs != decimal.Zero) {
                    SendValidationEvent(Res.Sch_EmptyChoice, oldChoice, XmlSeverityType.Warning);
                } 
                return XmlSchemaParticle.Empty;
            } 
            else if (!root && choice.Items.Count == 1 && choice.MinOccurs == decimal.One && choice.MaxOccurs == decimal.One) { 
                return (XmlSchemaParticle)choice.Items[0];
            } 
            else {
                return choice;
            }
        } 

        private XmlSchemaParticle CannonicalizeSequence(XmlSchemaSequence sequence, bool root) { 
            if (sequence.Items.Count > 0) { 
                XmlSchemaSequence newSequence = new XmlSchemaSequence();
                newSequence.MinOccurs = sequence.MinOccurs; 
                newSequence.MaxOccurs = sequence.MaxOccurs;
                CopyPosition(newSequence, sequence, true);
                foreach (XmlSchemaParticle p in sequence.Items) {
                    XmlSchemaParticle p1 = CannonicalizeParticle(p, false); 
                    if (p1 != XmlSchemaParticle.Empty) {
                        if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaSequence) { 
                            foreach (XmlSchemaParticle p2 in ((XmlSchemaSequence)p1).Items) { 
                                newSequence.Items.Add(p2);
                            } 
                        }
                        else {
                            newSequence.Items.Add(p1);
                        } 
                    }
                } 
                sequence = newSequence; 
            }
            if (sequence.Items.Count == 0) { 
                return XmlSchemaParticle.Empty;
            }
            else if (!root && sequence.Items.Count == 1 && sequence.MinOccurs == decimal.One && sequence.MaxOccurs == decimal.One) {
                return (XmlSchemaParticle)sequence.Items[0]; 
            }
            else { 
                return sequence; 
            }
        } 

        private XmlSchemaParticle CannonicalizePointlessRoot(XmlSchemaParticle particle) {
            if (particle == null) {
                return null; 
            }
            XmlSchemaSequence xss; 
            XmlSchemaChoice xsc; 
            XmlSchemaAll xsa;
            decimal one = decimal.One; 
            if ( (xss = (particle as XmlSchemaSequence)) != null ) {
                XmlSchemaObjectCollection items = xss.Items;
                int count = items.Count;
                if (count == 1) { 
                    if (xss.MinOccurs == one && xss.MaxOccurs == one) {
                        return (XmlSchemaParticle)items[0]; 
                    } 
                }
            } 
            else if ( (xsc = (particle as XmlSchemaChoice)) != null ) {
                XmlSchemaObjectCollection items = xsc.Items;
                int count = items.Count;
                if (count == 1) { 
                    if (xsc.MinOccurs == one && xsc.MaxOccurs == one) {
                        return (XmlSchemaParticle)items[0]; 
                    } 
                }
                else if (count == 0) { 
                    return XmlSchemaParticle.Empty;
                }
            }
            else if ( (xsa = (particle as XmlSchemaAll)) != null ) { 
                XmlSchemaObjectCollection items = xsa.Items;
                int count = items.Count; 
                if (count == 1) { 
                    if (xsa.MinOccurs == one && xsa.MaxOccurs == one) {
                        return (XmlSchemaParticle)items[0]; 
                    }
                }
            }
            return particle; 
        }
 
        private bool IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) { 
            if (derivedParticle == baseParticle) {
                return true; 
            }
            else if (derivedParticle == null || derivedParticle == XmlSchemaParticle.Empty) {
                return IsParticleEmptiable(baseParticle);
            } 
            else if (baseParticle == null || baseParticle == XmlSchemaParticle.Empty) {
                return false; 
            } 
            if (derivedParticle is XmlSchemaElement) { //check for derived element being head of substitutionGroup
                XmlSchemaElement derivedElem = (XmlSchemaElement)derivedParticle; 
                derivedParticle = CannonicalizeElement(derivedElem);
            }
            if (baseParticle is XmlSchemaElement) {
                XmlSchemaElement baseElem = (XmlSchemaElement)baseParticle; 
                XmlSchemaParticle newBaseParticle;
                newBaseParticle = CannonicalizeElement(baseElem); 
                if (newBaseParticle is XmlSchemaChoice) { //Base Element is subs grp head. 
                    return IsValidRestriction(derivedParticle, newBaseParticle);
                } 
                else if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromElement((XmlSchemaElement)derivedParticle, baseElem);
                }
                else { 
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForElem);
                    return false; 
                } 
            }
            else if (baseParticle is XmlSchemaAny) { 
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromAny((XmlSchemaElement)derivedParticle, (XmlSchemaAny)baseParticle);
                }
                else if (derivedParticle is XmlSchemaAny) { 
                    return IsAnyFromAny((XmlSchemaAny)derivedParticle, (XmlSchemaAny)baseParticle);
                } 
                else { 
                    return IsGroupBaseFromAny((XmlSchemaGroupBase)derivedParticle, (XmlSchemaAny)baseParticle);
                } 
            }
            else if (baseParticle is XmlSchemaAll) {
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 
                }
                else if (derivedParticle is XmlSchemaAll) { 
                    if(IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) { 
                        return true;
                    } 
                }
                else if (derivedParticle is XmlSchemaSequence) {
                    if(IsSequenceFromAll((XmlSchemaSequence)derivedParticle, (XmlSchemaAll)baseParticle)) {
                        return true; 
                    }
                    restrictionErrorMsg = Res.GetString(Res.Sch_SeqFromAll, derivedParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
                } 
                else if (derivedParticle is XmlSchemaChoice || derivedParticle is XmlSchemaAny) {
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForAll); 
                }
                return false;
            }
            else if (baseParticle is XmlSchemaChoice ) { 
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 
                } 
                else if (derivedParticle is XmlSchemaChoice) {
                    XmlSchemaChoice baseChoice = baseParticle as XmlSchemaChoice; 
                    XmlSchemaChoice derivedChoice = derivedParticle as XmlSchemaChoice;
                    if (baseChoice.Parent == null || derivedChoice.Parent == null) { //using parent property to indicate this choice was created on the fly for substitutionGroup
                        return IsChoiceFromChoiceSubstGroup(derivedChoice, baseChoice);
                    } 
                    if(IsGroupBaseFromGroupBase(derivedChoice, baseChoice, false)) {
                        return true; 
                    } 
                }
                else if (derivedParticle is XmlSchemaSequence) { 
                    if(IsSequenceFromChoice((XmlSchemaSequence)derivedParticle, (XmlSchemaChoice)baseParticle)) {
                        return true;
                    }
                    restrictionErrorMsg = Res.GetString(Res.Sch_SeqFromChoice, derivedParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseParticle.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
                }
                else { 
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForChoice); 
                }
                return false; 
            }
            else if (baseParticle is XmlSchemaSequence) {
                if (derivedParticle is XmlSchemaElement) {
                    return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle); 
                }
                else if (derivedParticle is XmlSchemaSequence || (derivedParticle is XmlSchemaAll && ((XmlSchemaGroupBase)derivedParticle).Items.Count ==1)) { 
                    if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) { 
                        return true;
                    } 
                }
                else {
                    restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForSeq);
                } 
                return false;
            } 
            else { 
                Debug.Assert(false);
            } 

            return false;
        }
 
        private bool IsElementFromElement(XmlSchemaElement derivedElement, XmlSchemaElement baseElement) {
            if(! ((derivedElement.QualifiedName == baseElement.QualifiedName) && 
                 (baseElement.IsNillable || !derivedElement.IsNillable) && 
                 IsValidOccurrenceRangeRestriction(derivedElement, baseElement) &&
                 (baseElement.FixedValue == null || IsFixedEqual(baseElement.ElementDecl, derivedElement.ElementDecl) ) && 
                 ((derivedElement.ElementDecl.Block | baseElement.ElementDecl.Block) ==  derivedElement.ElementDecl.Block) &&
                 (derivedElement.ElementSchemaType != null) && (baseElement.ElementSchemaType != null) &&
                 XmlSchemaType.IsDerivedFrom(derivedElement.ElementSchemaType, baseElement.ElementSchemaType, ~(XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.List | XmlSchemaDerivationMethod.Union))) ) {
 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromElement, derivedElement.QualifiedName, baseElement.QualifiedName);
                return false; 
            } 
            return true;
        } 

        private bool IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny) {
            if (!baseAny.Allows(derivedElement.QualifiedName)) {
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule1, derivedElement.QualifiedName.ToString()); 
                return false;
            } 
            if (!IsValidOccurrenceRangeRestriction(derivedElement, baseAny)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule2, derivedElement.QualifiedName.ToString());
                return false; 
            }
            return true;
        }
 
        private bool IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny) {
            if (!IsValidOccurrenceRangeRestriction(derivedAny, baseAny)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule1); 
                return false;
            } 
            if (!NamespaceList.IsSubset(derivedAny.NamespaceList, baseAny.NamespaceList)) {
                restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule2);
                return false;
            } 
            if ((int)derivedAny.ProcessContentsCorrect < (int)baseAny.ProcessContentsCorrect) {
                restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule3); 
                return false; 
            }
            return true; 
        }

        private bool IsGroupBaseFromAny(XmlSchemaGroupBase derivedGroupBase, XmlSchemaAny baseAny) {
            decimal minOccurs, maxOccurs; 
            CalculateEffectiveTotalRange(derivedGroupBase, out minOccurs, out maxOccurs);
            if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseAny.MinOccurs, baseAny.MaxOccurs)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseFromAny2, derivedGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseAny.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseAny.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
                return false;
            } 
            // eliminate occurrance range check
            string minOccursAny = baseAny.MinOccursString;
            baseAny.MinOccurs = decimal.Zero;
            foreach (XmlSchemaParticle p in derivedGroupBase.Items) { 
                if (!IsValidRestriction(p, baseAny)) {
                    restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseFromAny1); 
                    baseAny.MinOccursString = minOccursAny; 
                    return false;
                } 
            }
            baseAny.MinOccursString = minOccursAny;
            return true;
        } 

#if [....] 
        private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) { 
            if (!IsRangeSimple(baseGroupBase.MinOccurs, baseGroupBase.MaxOccurs) || !IsRangeSimple(derivedElement.MinOccurs, derivedElement.MaxOccurs)) {
                return IsElementFromGroupBase(derivedElement, baseGroupBase); //SPEC COMPLIANT 
            }
            else {
                //Base partilce's and Derived Element's range is simple
                //If all particles in baseParticle also have simple ranges, then can use our algorithm 
                //So that we dont break common cases that we used to accept earlier
                //Example Choice -> Element 
                if (IsElementFromGroupBaseHack(derivedElement, baseGroupBase, skipEmptableOnly)) { 
                    return true;
                } 
                else { //Fall back to regular checking
                    return IsElementFromGroupBase(derivedElement, baseGroupBase);
                }
            } 
        }
 
        private bool IsElementFromGroupBaseHack(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) { 
            bool isMatched = false;
 
            foreach(XmlSchemaParticle baseParticle in baseGroupBase.Items) {
                if (!isMatched && IsRangeSimple(baseParticle.MinOccurs, baseParticle.MaxOccurs)) {
                    string minOccursElement = baseParticle.MinOccursString;
                    string maxOccursElement = baseParticle.MaxOccursString; 
                    baseParticle.MinOccurs *= baseGroupBase.MinOccurs;
                    if ( baseParticle.MaxOccurs != decimal.MaxValue) { 
                        if (baseGroupBase.MaxOccurs == decimal.MaxValue) 
                             baseParticle.MaxOccurs = decimal.MaxValue;
                        else 
                             baseParticle.MaxOccurs *= baseGroupBase.MaxOccurs;
                    }
                    isMatched  = IsValidRestriction(derivedElement, baseParticle);
                    baseParticle.MinOccursString = minOccursElement; 
                    baseParticle.MaxOccursString = maxOccursElement;
                } 
                if (!isMatched && skipEmptableOnly && !IsParticleEmptiable(baseParticle)) { 
                    return false;
                } 
            }
            return isMatched;
        }
#endif 
        private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase) {
            if (baseGroupBase is XmlSchemaSequence) { 
                XmlSchemaSequence virtualSeq = new XmlSchemaSequence(); 
                virtualSeq.MinOccurs = 1;
                virtualSeq.MaxOccurs = 1; 
                virtualSeq.Items.Add(derivedElement);
                if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualSeq, baseGroupBase, true)) {
                    return true;
                } 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase1, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo));
            } 
            else if (baseGroupBase is XmlSchemaChoice) { 
                XmlSchemaChoice virtualChoice = new XmlSchemaChoice();
                virtualChoice.MinOccurs = 1; 
                virtualChoice.MaxOccurs = 1;
                virtualChoice.Items.Add(derivedElement);
                if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualChoice, baseGroupBase, false)) {
                    return true; 
                }
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase2, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
            } 
            else if (baseGroupBase is XmlSchemaAll) {
                XmlSchemaAll virtualAll = new XmlSchemaAll(); 
                virtualAll.MinOccurs = 1;
                virtualAll.MaxOccurs = 1;
                virtualAll.Items.Add(derivedElement);
                if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualAll, baseGroupBase, true)) { 
                    return true;
                } 
                restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromGroupBase3, derivedElement.QualifiedName.ToString(), derivedElement.LineNumber.ToString(NumberFormatInfo.InvariantInfo), derivedElement.LinePosition.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LineNumber.ToString(NumberFormatInfo.InvariantInfo), baseGroupBase.LinePosition.ToString(NumberFormatInfo.InvariantInfo)); 
            }
            return false; 
        }

        private bool IsChoiceFromChoiceSubstGroup(XmlSchemaChoice derivedChoice, XmlSchemaChoice baseChoice) {
            if (!IsValidOccurrenceRangeRestriction(derivedChoice, baseChoice)) { 
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid);
                return false; 
            } 
            foreach(XmlSchemaParticle particle in derivedChoice.Items) {
                if (GetMappingParticle(particle, baseChoice.Items) < 0) { 
                    return false;
                }
            }
            return true; 
        }
 
        private bool IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) { 
            if (!IsValidOccurrenceRangeRestriction(derivedGroupBase, baseGroupBase)) {
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid); 
                return false;
            }
            if (derivedGroupBase.Items.Count > baseGroupBase.Items.Count) {
                restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNoMap); 
                return false;
            } 
            int count = 0; 
            foreach(XmlSchemaParticle baseParticle in baseGroupBase.Items) {
                if ((count < derivedGroupBase.Items.Count) && IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[count], baseParticle)) { 
                    count ++;
                }
                else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
                    if (restrictionErrorMsg == null) { //If restriction failed on previous check, do not overwrite error 
                        restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNotEmptiable);
                    } 
                    return false; 
                }
            } 
            if (count < derivedGroupBase.Items.Count) {
                return false;
            }
            return true; 
        }
 
        private bool IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll) { 
            if (!IsValidOccurrenceRangeRestriction(derivedSequence, baseAll) || derivedSequence.Items.Count > baseAll.Items.Count) {
                return false; 
            }
            BitSet map = new BitSet(baseAll.Items.Count);
            foreach (XmlSchemaParticle p in derivedSequence.Items) {
                int i = GetMappingParticle(p, baseAll.Items); 
                if (i >= 0) {
                    if (map[i]) { 
                        return false; 
                    }
                    else { 
                        map.Set(i);
                    }
                }
                else { 
                    return false;
                } 
            } 
            for (int i = 0; i < baseAll.Items.Count; i++) {
                if (!map[i] && !IsParticleEmptiable((XmlSchemaParticle)baseAll.Items[i])) { 
                    return false;
                }
            }
            return true; 
        }
 
        private bool IsSequenceFromChoice(XmlSchemaSequence derivedSequence, XmlSchemaChoice baseChoice) { 
            decimal minOccurs, maxOccurs;
            minOccurs = derivedSequence.MinOccurs * derivedSequence.Items.Count; 
            if (derivedSequence.MaxOccurs == decimal.MaxValue) {
                maxOccurs = decimal.MaxValue;
            }
            else { 
                maxOccurs = derivedSequence.MaxOccurs * derivedSequence.Items.Count;
            } 
            if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseChoice.MinOccurs, baseChoice.MaxOccurs) || derivedSequence.Items.Count > baseChoice.Items.Count) { 
                return false;
            } 
            foreach (XmlSchemaParticle particle in derivedSequence.Items) {
                if (GetMappingParticle(particle, baseChoice.Items) < 0)
                    return false;
            } 
            return true;
        } 
 
        private bool IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
            return IsValidOccurrenceRangeRestriction(derivedParticle.MinOccurs, derivedParticle.MaxOccurs, baseParticle.MinOccurs, baseParticle.MaxOccurs); 
        }

        private bool IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs) {
            return (baseMinOccurs <= minOccurs) && (maxOccurs <= baseMaxOccurs); 
        }
 
        private int GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection) { 
            for (int i = 0; i < collection.Count; i++) {
                if (IsValidRestriction(particle, (XmlSchemaParticle)collection[i])) 
                    return i;
            }
            return -1;
        } 

        private bool IsParticleEmptiable(XmlSchemaParticle particle) { 
            decimal minOccurs, maxOccurs; 
            CalculateEffectiveTotalRange(particle, out minOccurs, out maxOccurs);
            return minOccurs == decimal.Zero; 
        }

        private void CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs) {
            if (particle is XmlSchemaElement || particle is XmlSchemaAny) { 
                minOccurs = particle.MinOccurs;
                maxOccurs = particle.MaxOccurs; 
            } 
            else if (particle is XmlSchemaChoice) {
                if (((XmlSchemaChoice)particle).Items.Count == 0) { 
                    minOccurs = maxOccurs = decimal.Zero;
                }
                else {
                    minOccurs = decimal.MaxValue; 
                    maxOccurs = decimal.Zero;
                    foreach (XmlSchemaParticle p in ((XmlSchemaChoice)particle).Items) { 
                        decimal min, max; 
                        CalculateEffectiveTotalRange(p, out min, out max);
                        if (min < minOccurs) { 
                            minOccurs = min;
                        }
                        if (max > maxOccurs) {
                            maxOccurs = max; 
                        }
                    } 
                    minOccurs *= particle.MinOccurs; 
                    if (maxOccurs != decimal.MaxValue) {
                        if (particle.MaxOccurs == decimal.MaxValue) 
                            maxOccurs = decimal.MaxValue;
                        else
                            maxOccurs *= particle.MaxOccurs;
                    } 
                }
            } 
            else { 
                XmlSchemaObjectCollection collection = ((XmlSchemaGroupBase)particle).Items;
                if (collection.Count == 0) { 
                    minOccurs = maxOccurs = decimal.Zero;
                }
                else {
                    minOccurs = 0; 
                    maxOccurs = 0;
                    foreach (XmlSchemaParticle p in collection) { 
                        decimal min, max; 
                        CalculateEffectiveTotalRange(p, out min, out max);
                        minOccurs += min; 
                        if (maxOccurs != decimal.MaxValue) {
                            if (max == decimal.MaxValue)
                                maxOccurs = decimal.MaxValue;
                            else 
                                maxOccurs += max;
                        } 
                    } 
                    minOccurs *= particle.MinOccurs;
                    if (maxOccurs != decimal.MaxValue) { 
                        if (particle.MaxOccurs == decimal.MaxValue)
                            maxOccurs = decimal.MaxValue;
                        else
                            maxOccurs *= particle.MaxOccurs; 
                    }
                } 
            } 
        }
 
        private void PushComplexType(XmlSchemaComplexType complexType) {
            this.complexTypeStack.Push(complexType);
        }
 
        private XmlSchemaContentType GetSchemaContentType(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaParticle particle) {
            if ((complexContent != null && complexContent.IsMixed) || 
                (complexContent == null && complexType.IsMixed)) { 
                return XmlSchemaContentType.Mixed;
            } 
            else if (particle != null && !particle.IsEmpty) {
                return XmlSchemaContentType.ElementOnly;
            }
            else { 
                return XmlSchemaContentType.Empty;
            } 
        } 

        private void CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup) { 
            if (attributeGroup.IsProcessing) {
                SendValidationEvent(Res.Sch_AttributeGroupCircularRef, attributeGroup);
                return;
            } 
            if (attributeGroup.AttributeUses.Count > 0) {// already checked
                return; 
            } 
            attributeGroup.IsProcessing = true;
            XmlSchemaAnyAttribute anyAttribute = attributeGroup.AnyAttribute; 

            try {
                foreach (XmlSchemaObject obj in attributeGroup.Attributes) {
                    if (obj is XmlSchemaAttribute) { 
                        XmlSchemaAttribute attribute = (XmlSchemaAttribute)obj;
                        if (attribute.Use == XmlSchemaUse.Prohibited) { 
                            continue; 
                        }
                        CompileAttribute(attribute); 
                        if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) {
                            attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute);
                        }
                        else  { 
                            SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
                        } 
                    } 
                    else { // XmlSchemaAttributeGroupRef
                        XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)obj; 
                        XmlSchemaAttributeGroup attributeGroupResolved;
                        if (attributeGroup.Redefined != null && attributeGroupRef.RefName == attributeGroup.Redefined.QualifiedName) {
                            attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroup.Redefined;
                        } 
                        else {
                            attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName]; 
                        } 
                        if (attributeGroupResolved != null) {
                            CompileAttributeGroup(attributeGroupResolved); 
                            foreach (XmlSchemaAttribute attribute in attributeGroupResolved.AttributeUses.Values) {
                                if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) {
                                    attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute);
                                } 
                                else {
                                    SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute); 
                                } 
                            }
                            anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroupResolved.AttributeWildcard); 
                        }
                        else {
                            SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
                        } 
                    }
                } 
                attributeGroup.AttributeWildcard = anyAttribute; 
            }
            finally { 
                attributeGroup.IsProcessing = false;
            }
        }
 
        private void CompileLocalAttributes(XmlSchemaComplexType baseType, XmlSchemaComplexType derivedType, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaDerivationMethod derivedBy) {
            XmlSchemaAnyAttribute baseAttributeWildcard = baseType != null ? baseType.AttributeWildcard : null; 
            foreach (XmlSchemaObject obj in attributes) { 
                if (obj is XmlSchemaAttribute) {
                    XmlSchemaAttribute attribute = (XmlSchemaAttribute)obj; 
                    if (attribute.Use != XmlSchemaUse.Prohibited) {
                        CompileAttribute(attribute);
                    }
                    if (attribute.Use != XmlSchemaUse.Prohibited || 
                        (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
 
                        if (derivedType.AttributeUses[attribute.QualifiedName] == null) { 
                            derivedType.AttributeUses.Add(attribute.QualifiedName, attribute);
                        } 
                        else  {
                            SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
                        }
                    } 
                    else {
                        SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning); 
                    } 

                } 
                else { // is XmlSchemaAttributeGroupRef
                    XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)obj;
                    XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName];
                    if (attributeGroup != null) { 
                        CompileAttributeGroup(attributeGroup);
                        foreach (XmlSchemaAttribute attribute in attributeGroup.AttributeUses.Values) { 
                          if (attribute.Use != XmlSchemaUse.Prohibited || 
                             (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
                            if (derivedType.AttributeUses[attribute.QualifiedName] == null) { 
                                derivedType.AttributeUses.Add(attribute.QualifiedName, attribute);
                            }
                            else {
                                SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attributeGroupRef); 
                            }
                          } 
                          else { 
                            SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning);
                          } 

                        }
                        anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroup.AttributeWildcard);
                    } 
                    else {
                        SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef); 
                    } 
                }
            } 

            // check derivation rules
            if (baseType != null) {
                if (derivedBy == XmlSchemaDerivationMethod.Extension) { 
                    derivedType.SetAttributeWildcard(CompileAnyAttributeUnion(anyAttribute, baseAttributeWildcard));
                    foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) { 
                        XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName]; 
                        if (attribute == null) {
                            derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase); 
                        }
                        else {
                            Debug.Assert(attribute.Use != XmlSchemaUse.Prohibited);
                            if (attributeBase.Use != XmlSchemaUse.Prohibited && attribute.AttributeSchemaType != attributeBase.AttributeSchemaType) { //Extension allows previously prohibited attributes to be re-added, 
                                SendValidationEvent(Res.Sch_InvalidAttributeExtension, attribute);
                            } 
                        } 
                    }
                } 
                else {  // derivedBy == XmlSchemaDerivationMethod.Restriction
                    // Schema Component Constraint: Derivation Valid (Restriction, Complex)
                    if ((anyAttribute != null) && (baseAttributeWildcard == null || !XmlSchemaAnyAttribute.IsSubset(anyAttribute, baseAttributeWildcard) || !IsProcessContentsRestricted(baseType, anyAttribute, baseAttributeWildcard)) ) {
                        SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedType); 
                    }
                    else { 
                        derivedType.SetAttributeWildcard(anyAttribute); //complete wildcard 
                    }
 
                    // Add form the base
                    foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
                        XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
                        if (attribute == null) { 
                            derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
                        } 
                        else { 
                            if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
#if DEBUG 
                                string position = string.Empty;
                                if (derivedType.SourceUri != null) {
                                    position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
                                } 
                                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
                                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard)); 
                                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard)); 
#endif
                                SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute); 
                            }
                            else if (attributeBase.Use == XmlSchemaUse.Required && (attribute.Use != XmlSchemaUse.Required)) { //If base is required, derived should also be required
                                SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute);
                            } 
                            else if (attribute.Use == XmlSchemaUse.Prohibited) {
                                continue; 
                            } 
                            else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
                                SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute); 
                            }
                            else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
                                SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
                            } 
                        }
                    } 
 
                    // Check additional ones are valid restriction of base's wildcard
                    foreach(XmlSchemaAttribute attribute in derivedType.AttributeUses.Values) { 
                        XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseType.AttributeUses[attribute.QualifiedName];
                        if (attributeBase != null) {
                            continue;
                        } 
                        if (baseAttributeWildcard == null || !baseAttributeWildcard.Allows(attribute.QualifiedName)) {
#if DEBUG 
                            string position = string.Empty; 
                            if (derivedType.SourceUri != null) {
                                position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")"; 
                            }
                            Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
                            Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
                            Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard)); 
#endif
                            SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute); 
                        } 
                    }
                } 
            }
            else {
                derivedType.SetAttributeWildcard(anyAttribute);
            } 
       }
 
        private void CheckAtrributeGroupRestriction(XmlSchemaAttributeGroup baseAttributeGroup, XmlSchemaAttributeGroup derivedAttributeGroup) { 
            XmlSchemaAnyAttribute baseAnyAtt = baseAttributeGroup.AttributeWildcard;
            XmlSchemaAnyAttribute derivedAnyAtt = derivedAttributeGroup.AttributeWildcard; 

            if ((derivedAnyAtt != null) && (baseAnyAtt == null || !XmlSchemaAnyAttribute.IsSubset(derivedAnyAtt, baseAnyAtt) || !IsProcessContentsRestricted(null, derivedAnyAtt, baseAnyAtt))) {
                SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedAttributeGroup);
            } 
            foreach(XmlSchemaAttribute attributeBase in baseAttributeGroup.AttributeUses.Values) {
                XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedAttributeGroup.AttributeUses[attributeBase.QualifiedName]; 
                if (attribute != null) { 
                    if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
                        SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute); 
                    }
                    else if (attributeBase.Use == XmlSchemaUse.Required && attribute.Use != XmlSchemaUse.Required) {
                        SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute);
                    } 
                    else if (attribute.Use == XmlSchemaUse.Prohibited) { //If derived att is prohibited, continue
                        continue; 
                    } 
                    else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
                        SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute); 
                    }
                    else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
                        SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
                    } 
                }
                else if (attributeBase.Use == XmlSchemaUse.Required) { 
                    SendValidationEvent(Res.Sch_NoDerivedAttribute, attributeBase.QualifiedName.ToString(), baseAttributeGroup.QualifiedName.ToString(), derivedAttributeGroup); 
                }
            } 
            // Check additional ones are valid restriction of base's wildcard
            foreach(XmlSchemaAttribute attribute in derivedAttributeGroup.AttributeUses.Values) {
                XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseAttributeGroup.AttributeUses[attribute.QualifiedName];
                if (attributeBase != null) { 
                    continue;
                } 
                if (baseAnyAtt == null || !baseAnyAtt.Allows(attribute.QualifiedName)) { 
                    SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
                } 
            }
        }

#if DEBUG 
        private string DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard) {
            StringBuilder sb = new StringBuilder(); 
            sb.Append("["); 
            bool first = true;
            foreach (XmlSchemaAttribute attribute in attributeUses.Values) { 
                if (attribute.Use != XmlSchemaUse.Prohibited) {
                    if (first) {
                        first = false;
                    } 
                    else {
                        sb.Append(" "); 
                    } 
                    sb.Append(attribute.QualifiedName.Name);
                    if (attribute.Use == XmlSchemaUse.Optional || attribute.Use == XmlSchemaUse.None) { 
                        sb.Append("?");
                    }
                }
            } 
            if (attributeWildcard != null) {
                if (attributeUses.Count != 0) { 
                    sb.Append(" "); 
                }
                sb.Append("<"); 
                sb.Append(attributeWildcard.NamespaceList.ToString());
                sb.Append(">");
            }
            sb.Append("] - ["); 
            first = true;
            foreach (XmlSchemaAttribute attribute in attributeUses.Values) { 
                if (attribute.Use == XmlSchemaUse.Prohibited) { 
                    if (first) {
                        first = false; 
                    }
                    else {
                        sb.Append(" ");
                    } 
                    sb.Append(attribute.QualifiedName.Name);
                } 
            } 
            sb.Append("]");
            return sb.ToString(); 
        }
#endif

        private bool IsProcessContentsRestricted(XmlSchemaComplexType baseType, XmlSchemaAnyAttribute derivedAttributeWildcard, XmlSchemaAnyAttribute baseAttributeWildcard) { 
            if (baseType == XmlSchemaComplexType.AnyType) {
                return true; 
            } 
            if ((int)derivedAttributeWildcard.ProcessContentsCorrect >= (int)baseAttributeWildcard.ProcessContentsCorrect) {
                return true; 
            }
            return false;
        }
 
        private XmlSchemaAnyAttribute CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
            if (a == null) { 
                return b; 
            }
            else if (b == null) { 
                return a;
            }
            else {
                XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Union(a, b, false); //false is for v1Compatd 
                if (attribute == null) {
                    SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a); 
                } 
                return attribute;
            } 

        }

        private XmlSchemaAnyAttribute CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) { 
            if (a == null) {
                return b; 
            } 
            else if (b == null) {
                return a; 
            }
            else {
                XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Intersection(a, b, false); //false is for v1Compat
                if (attribute == null) { 
                    SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
                } 
                return attribute; 
            }
        } 

         private void CompileAttribute(XmlSchemaAttribute xa) {
            if (xa.IsProcessing) {
                SendValidationEvent(Res.Sch_AttributeCircularRef, xa); 
                return;
            } 
            if (xa.AttDef != null) { //already compiled? 
                return;
            } 
            xa.IsProcessing = true;
            SchemaAttDef decl = null;
            try {
                if (!xa.RefName.IsEmpty) { 
                    XmlSchemaAttribute a = (XmlSchemaAttribute)attributes[xa.RefName];
                    if (a == null) { 
                        throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, xa.RefName.ToString(), xa); 
                    }
                    CompileAttribute(a); 
                    if (a.AttDef == null) {
                        throw new XmlSchemaException(Res.Sch_RefInvalidAttribute, xa.RefName.ToString(), xa);
                    }
                    decl = a.AttDef.Clone(); 
                    XmlSchemaDatatype datatype = decl.Datatype;
 
                    if (datatype != null) { 
                        if (a.FixedValue == null && a.DefaultValue == null) {
                            SetDefaultFixed(xa, decl); 
                        }
                        else if (a.FixedValue != null) {
                            if (xa.DefaultValue != null) {
                                throw new XmlSchemaException(Res.Sch_FixedDefaultInRef, xa.RefName.ToString(), xa); 
                            }
                            else if (xa.FixedValue != null ) { 
                                object refFixedValue = datatype.ParseValue(xa.FixedValue, NameTable, new SchemaNamespaceManager(xa), true); 
                                if ( !datatype.IsEqual(decl.DefaultValueTyped, refFixedValue)) {
                                    throw new XmlSchemaException(Res.Sch_FixedInRef, xa.RefName.ToString(), xa); 
                                }
                            }
                        }
                    } 
                    xa.SetAttributeType(a.AttributeSchemaType);
                } 
                else { 
                    decl = new SchemaAttDef(xa.QualifiedName, xa.Prefix);
                    if (xa.SchemaType != null) { 
                        CompileSimpleType(xa.SchemaType);
                        xa.SetAttributeType(xa.SchemaType);
                        decl.SchemaType = xa.SchemaType;
                        decl.Datatype = xa.SchemaType.Datatype; 
                    }
                    else if (!xa.SchemaTypeName.IsEmpty) { 
                        XmlSchemaSimpleType simpleType = GetSimpleType(xa.SchemaTypeName); 
                        if (simpleType != null) {
                            xa.SetAttributeType(simpleType); 
                            decl.Datatype = simpleType.Datatype;
                            decl.SchemaType = simpleType;
                        }
                        else { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, xa.SchemaTypeName.ToString(), xa);
                        } 
                    } 
                    else {
                        decl.SchemaType = DatatypeImplementation.AnySimpleType; 
                        decl.Datatype = DatatypeImplementation.AnySimpleType.Datatype;
                        xa.SetAttributeType(DatatypeImplementation.AnySimpleType);
                    }
                    //} //Removed this here since the following should be done only if RefName is Empty 
                    if (decl.Datatype != null) {
                        decl.Datatype.VerifySchemaValid(notations, xa); 
                    } 
                    SetDefaultFixed(xa, decl);
                } //End of Else for !RefName.IsEmpty 

                decl.SchemaAttribute = xa; //So this is available for PSVI
                xa.AttDef = decl;
            } 
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) { 
                    e.SetSource(xa); 
                }
                SendValidationEvent(e); 
                xa.AttDef = SchemaAttDef.Empty;
            }
            finally {
                xa.IsProcessing = false; 
            }
        } 
 
        private void SetDefaultFixed(XmlSchemaAttribute xa, SchemaAttDef decl) {
            if (xa.DefaultValue != null || xa.FixedValue != null) { 
                if (xa.DefaultValue != null) {
                    decl.Presence = SchemaDeclBase.Use.Default;
                    decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.DefaultValue;
                } 
                else {
                    if (xa.Use == XmlSchemaUse.Required) { 
                        decl.Presence = SchemaDeclBase.Use.RequiredFixed; 
                    }
                    else { 
                        decl.Presence = SchemaDeclBase.Use.Fixed;
                    }
                    decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.FixedValue;
                } 
                if(decl.Datatype != null) {
                    if (decl.Datatype.TypeCode == XmlTypeCode.Id) { 
                        SendValidationEvent(Res.Sch_DefaultIdValue, xa); 
                    }
                    else { 
                        decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
                    }
                }
            } 
            else {
                switch (xa.Use) { 
                    case XmlSchemaUse.None: 
                    case XmlSchemaUse.Optional:
                        decl.Presence = SchemaDeclBase.Use.Implied; 
                        break;
                    case XmlSchemaUse.Required:
                        decl.Presence = SchemaDeclBase.Use.Required;
                        break; 
                    case XmlSchemaUse.Prohibited:
                        break; 
                } 
            }
        } 

        private void CompileIdentityConstraint (XmlSchemaIdentityConstraint xi) {
            if (xi.IsProcessing) {
                xi.CompiledConstraint = CompiledIdentityConstraint.Empty; 
                SendValidationEvent(Res.Sch_IdentityConstraintCircularRef, xi);
                return; 
            } 

            if (xi.CompiledConstraint != null) { 
                return;
            }

            xi.IsProcessing = true; 
            CompiledIdentityConstraint compic = null;
            try { 
                SchemaNamespaceManager xnmgr = new SchemaNamespaceManager(xi); 
                compic = new CompiledIdentityConstraint(xi, xnmgr);
                if (xi is XmlSchemaKeyref) { 
                    XmlSchemaIdentityConstraint ic = (XmlSchemaIdentityConstraint)this.identityConstraints[((XmlSchemaKeyref)xi).Refer];
                    if (ic == null) {
                        throw new XmlSchemaException(Res.Sch_UndeclaredIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
                    } 
                    CompileIdentityConstraint(ic);
                    if (ic.CompiledConstraint == null) { 
                        throw new XmlSchemaException(Res.Sch_RefInvalidIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi); 
                    }
                    // keyref has the different cardinality with the key it referred 
                    if (ic.Fields.Count != xi.Fields.Count) {
                        throw new XmlSchemaException(Res.Sch_RefInvalidCardin, xi.QualifiedName.ToString(), xi);
                    }
                    // keyref can only refer to key/unique 
                    if (ic.CompiledConstraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) {
                        throw new XmlSchemaException(Res.Sch_ReftoKeyref, xi.QualifiedName.ToString(), xi); 
                    } 
                }
                xi.CompiledConstraint = compic; 
            }
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) {
                    e.SetSource(xi); 
                }
                SendValidationEvent(e); 
                xi.CompiledConstraint = CompiledIdentityConstraint.Empty; 
                // empty is better than null here, stop quickly when circle referencing
            } 
            finally {
                xi.IsProcessing = false;
            }
 
        }
 
        private void CompileElement(XmlSchemaElement xe) { 
            if (xe.IsProcessing) {
                SendValidationEvent(Res.Sch_ElementCircularRef, xe); 
                return;
            }
            if (xe.ElementDecl != null) {
                return; 
            }
            xe.IsProcessing = true; 
            SchemaElementDecl decl = null; 
            try {
                if (!xe.RefName.IsEmpty) { 
                    XmlSchemaElement e = (XmlSchemaElement)elements[xe.RefName];
                    if (e == null) {
                        throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe);
                    } 
                    CompileElement(e);
                    if (e.ElementDecl == null) { 
                        throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe); 
                    }
                    xe.SetElementType(e.ElementSchemaType); 
                    decl = e.ElementDecl.Clone();
                }
                else {
                    if (xe.SchemaType != null) { 
                        xe.SetElementType(xe.SchemaType);
                    } 
                    else if (!xe.SchemaTypeName.IsEmpty) { 
                        xe.SetElementType(GetAnySchemaType(xe.SchemaTypeName));
                        if (xe.ElementSchemaType == null) { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredType, xe.SchemaTypeName.ToString(), xe);
                        }
                    }
                    else  if (!xe.SubstitutionGroup.IsEmpty) { 
                        XmlSchemaElement examplar = (XmlSchemaElement)elements[xe.SubstitutionGroup];
                        if (examplar == null) { 
                            throw new XmlSchemaException(Res.Sch_UndeclaredEquivClass, xe.SubstitutionGroup.Name.ToString(CultureInfo.InvariantCulture), xe); 
                        }
                        if (examplar.IsProcessing) { //Circular subst group; already detected by now 
                            return;
                        }
                        CompileElement(examplar);
                        if (examplar.ElementDecl == null) { //If head is invalid, fall back to AnyType 
                            xe.SetElementType(XmlSchemaComplexType.AnyType);
                            decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone(); 
                        } 
                        else {
                            xe.SetElementType(examplar.ElementSchemaType); 
                            decl = examplar.ElementDecl.Clone();
                        }
                    }
                    else { 
                        xe.SetElementType(XmlSchemaComplexType.AnyType);
                        decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone(); 
                    } 

                    if (decl == null) { 
                        Debug.Assert(xe.ElementSchemaType != null);
                        if (xe.ElementSchemaType is XmlSchemaComplexType) {
                            XmlSchemaComplexType complexType = (XmlSchemaComplexType)xe.ElementSchemaType;
                            CompileComplexType(complexType); 
                            if (complexType.ElementDecl != null) {
                                decl = complexType.ElementDecl.Clone(); 
//                                decl.LocalElements = complexType.LocalElementDecls; 
                            }
                        } 
                        else if (xe.ElementSchemaType is XmlSchemaSimpleType) {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)xe.ElementSchemaType;
                            CompileSimpleType(simpleType);
                            if (simpleType.ElementDecl != null) { 
                                decl = simpleType.ElementDecl.Clone();
                            } 
                        } 
                    }
                    Debug.Assert(decl != null); 
                    decl.Name = xe.QualifiedName;
                    decl.IsAbstract = xe.IsAbstract;
                    XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType;
                    if (ct != null) { 
                        decl.IsAbstract |= ct.IsAbstract;
                    } 
                    decl.IsNillable = xe.IsNillable; 
                    decl.Block |= xe.BlockResolved;
                } 
                if (decl.Datatype != null) {
                    decl.Datatype.VerifySchemaValid(notations, xe);
                }
 
                if (xe.DefaultValue != null || xe.FixedValue != null) {
                    if (decl.ContentValidator != null) { 
                        if (decl.ContentValidator.ContentType == XmlSchemaContentType.TextOnly || (decl.ContentValidator.ContentType == XmlSchemaContentType.Mixed && decl.ContentValidator.IsEmptiable)) { 
                            if (xe.DefaultValue != null) {
                                decl.Presence = SchemaDeclBase.Use.Default; 
                                decl.DefaultValueRaw = xe.DefaultValue;
                            }
                            else {
                                decl.Presence = SchemaDeclBase.Use.Fixed; 
                                decl.DefaultValueRaw = xe.FixedValue;
                            } 
                            if (decl.Datatype != null) { 
                                if (decl.Datatype.TypeCode == XmlTypeCode.Id) {
                                    SendValidationEvent(Res.Sch_DefaultIdValue, xe); 
                                }
                                else {
                                    decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true);
                                } 
                            }
                            else { //Mixed with emptiable particle 
                                decl.DefaultValueTyped = DatatypeImplementation.AnySimpleType.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe)); 
                            }
                        } 
                        else {
                            throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe);
                        }
                    } 
                }
                if (xe.HasConstraints) { 
                    XmlSchemaObjectCollection constraints = xe.Constraints; 
                    CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count];
                    int idx = 0; 
                    foreach(XmlSchemaIdentityConstraint constraint in constraints) {
                        CompileIdentityConstraint (constraint);
                        compiledConstraints[idx ++] = constraint.CompiledConstraint;
                    } 
                    decl.Constraints = compiledConstraints;
                } 
                decl.SchemaElement = xe; //So this is available for PSVI 
                xe.ElementDecl = decl;
            } 
            catch (XmlSchemaException e) {
                if (e.SourceSchemaObject == null) {
                    e.SetSource(xe);
                } 
                SendValidationEvent(e);
                xe.ElementDecl = SchemaElementDecl.Empty; 
            } 
            finally {
                xe.IsProcessing = false; 
            }
        }

        private ContentValidator CompileComplexContent(XmlSchemaComplexType complexType) { 
            if (complexType.ContentType == XmlSchemaContentType.Empty) {
                return ContentValidator.Empty; 
            } 
            else if (complexType.ContentType == XmlSchemaContentType.TextOnly) {
                return ContentValidator.TextOnly; 
            }
            XmlSchemaParticle particle = complexType.ContentTypeParticle;
            if (particle == null || particle == XmlSchemaParticle.Empty) {
                if (complexType.ContentType == XmlSchemaContentType.ElementOnly) { 
                    return ContentValidator.Empty;
                } 
                else { 
                    return ContentValidator.Mixed;
                } 
            }
            PushComplexType(complexType);
            if (particle is XmlSchemaAll) {
                XmlSchemaAll all = (XmlSchemaAll)particle; 
                AllElementsContentValidator contentValidator = new AllElementsContentValidator(complexType.ContentType, all.Items.Count, all.MinOccurs == decimal.Zero);
                foreach (XmlSchemaElement localElement in all.Items) { 
                    if (!contentValidator.AddElement(localElement.QualifiedName, localElement, localElement.MinOccurs == decimal.Zero)) { 
                       SendValidationEvent(Res.Sch_DupElement, localElement.QualifiedName.ToString(), localElement);
                    } 
                }
                return contentValidator;
            }
            else { 
                ParticleContentValidator contentValidator = new ParticleContentValidator(complexType.ContentType, CompilationSettings.EnableUpaCheck);
#if DEBUG 
                string name = complexType.Name != null ? complexType.Name : string.Empty; 
                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceVerbose, "CompileComplexContent: "+ name  + DumpContentModel(particle));
#endif 
                try {
                    contentValidator.Start();
                    complexType.HasWildCard = BuildParticleContentModel(contentValidator, particle);
                    return contentValidator.Finish(true); 
                }
                catch(UpaException e) { 
                    if (e.Particle1 is XmlSchemaElement) { 
                        if (e.Particle2 is XmlSchemaElement) {
                            SendValidationEvent(Res.Sch_NonDeterministic, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2); 
                        }
                        else {
                            SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaAny)e.Particle2);
                        } 
                    }
                    else { 
                        if (e.Particle2 is XmlSchemaElement) { 
                            SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaElement)e.Particle2).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2);
                        } 
                        else {
                            SendValidationEvent(Res.Sch_NonDeterministicAnyAny, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, (XmlSchemaAny)e.Particle2);
                        }
                    } 
                    return XmlSchemaComplexType.AnyTypeContentValidator;
                } 
                catch(NotSupportedException) { 
                    SendValidationEvent(Res.Sch_ComplexContentModel, complexType, XmlSeverityType.Warning);
                    return XmlSchemaComplexType.AnyTypeContentValidator; 
                }
            }
        }
 
#if DEBUG
        private string DumpContentModel(XmlSchemaParticle particle) { 
            StringBuilder sb = new StringBuilder(); 
            DumpContentModelTo(sb, particle);
            return sb.ToString(); 
        }

        private void DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle) {
            if (particle is XmlSchemaElement) { 
                sb.Append(((XmlSchemaElement)particle).QualifiedName);
            } 
            else if (particle is XmlSchemaAny) { 
                sb.Append("<");
                sb.Append(((XmlSchemaAny)particle).NamespaceList.ToString()); 
                sb.Append(">");
            }
            else if (particle is XmlSchemaAll) {
                XmlSchemaAll all = (XmlSchemaAll)particle; 
                sb.Append("[");
                bool first = true; 
                foreach (XmlSchemaElement localElement in all.Items) { 
                    if (first) {
                        first = false; 
                    }
                    else {
                        sb.Append(", ");
                    } 
                    sb.Append(localElement.QualifiedName.Name);
                    if (localElement.MinOccurs == decimal.Zero) { 
                        sb.Append("?"); 
                    }
                } 
                sb.Append("]");
            }
            else if (particle is XmlSchemaGroupBase) {
                XmlSchemaGroupBase gb = (XmlSchemaGroupBase)particle; 
                sb.Append("(");
                string delimeter = (particle is XmlSchemaChoice) ? " | " : ", "; 
                bool first = true; 
                foreach (XmlSchemaParticle p in gb.Items) {
                    if (first) { 
                        first = false;
                    }
                    else {
                        sb.Append(delimeter); 
                    }
                    DumpContentModelTo(sb, p); 
                } 
                sb.Append(")");
            } else { 
                Debug.Assert(particle == XmlSchemaParticle.Empty);
                sb.Append("<>");
            }
            if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) { 
                // nothing
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) { 
                sb.Append("?");
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
                sb.Append("*");
            }
            else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) { 
                sb.Append("+");
            } 
            else { 
                sb.Append("{" + particle.MinOccurs.ToString(NumberFormatInfo.InvariantInfo) +", " + particle.MaxOccurs.ToString(NumberFormatInfo.InvariantInfo) + "}");
            } 
        }
#endif

        private bool BuildParticleContentModel(ParticleContentValidator contentValidator, XmlSchemaParticle particle) { 
            bool hasWildCard = false;
            if (particle is XmlSchemaElement) { 
                XmlSchemaElement element = (XmlSchemaElement)particle; 
                contentValidator.AddName(element.QualifiedName, element);
             } 
            else if (particle is XmlSchemaAny) {
                hasWildCard = true;
                XmlSchemaAny any = (XmlSchemaAny)particle;
                contentValidator.AddNamespaceList(any.NamespaceList, any); 
            }
            else if (particle is XmlSchemaGroupBase) { 
                XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 
                bool isChoice = particle is XmlSchemaChoice;
                contentValidator.OpenGroup(); 
                bool first = true;
                foreach (XmlSchemaParticle p in particles) {
                    Debug.Assert(!p.IsEmpty);
                    if (first) { 
                        first = false;
                    } 
                    else if (isChoice) { 
                        contentValidator.AddChoice();
                    } 
                    else {
                        contentValidator.AddSequence();
                    }
                    hasWildCard = BuildParticleContentModel(contentValidator, p); 
                }
                contentValidator.CloseGroup(); 
            } 
            else {
                Debug.Assert(false); 
            }
            if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
                // nothing
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
                contentValidator.AddQMark(); 
            } 
            else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
                contentValidator.AddStar(); 
            }
            else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
                contentValidator.AddPlus();
            } 
            else {
                contentValidator.AddLeafRange(particle.MinOccurs, particle.MaxOccurs); 
            } 
            return hasWildCard;
        } 

        private void CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle) {
            if (particle is XmlSchemaElement) {
                XmlSchemaElement localElement = (XmlSchemaElement)particle; 
                CompileElement(localElement);
                if (complexType.LocalElements[localElement.QualifiedName] == null) { 
                    complexType.LocalElements.Add(localElement.QualifiedName, localElement); 
                }
                else { 
                    complexType.HasDuplicateDecls = true;
                    XmlSchemaElement element = (XmlSchemaElement)complexType.LocalElements[localElement.QualifiedName];
                    if (element.ElementSchemaType != localElement.ElementSchemaType) {
                        SendValidationEvent(Res.Sch_ElementTypeCollision, particle); 
                    }
                } 
            } 
            else if (particle is XmlSchemaGroupBase) {
                XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 
                foreach (XmlSchemaParticle p in particles) {
                    CompileParticleElements(complexType, p);
                }
            } 
        }
 
        private void CompileParticleElements(XmlSchemaParticle particle) { //For checking redefined group particle derivation 
            if (particle is XmlSchemaElement) {
                XmlSchemaElement localElement = (XmlSchemaElement)particle; 
                CompileElement(localElement);
            }
            else if (particle is XmlSchemaGroupBase) {
                XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items; 
                foreach (XmlSchemaParticle p in particles) {
                    CompileParticleElements(p); 
                } 
            }
        } 

        private void CompileComplexTypeElements(XmlSchemaComplexType complexType) {
            if (complexType.IsProcessing) {
                SendValidationEvent(Res.Sch_TypeCircularRef, complexType); 
                return;
            } 
            complexType.IsProcessing = true; 
            try {
                if (complexType.ContentTypeParticle != XmlSchemaParticle.Empty) { 
                    CompileParticleElements(complexType, complexType.ContentTypeParticle);
                }
            }
            finally { 
                complexType.IsProcessing = false;
            } 
        } 

        private XmlSchemaSimpleType GetSimpleType(XmlQualifiedName name) { 
            XmlSchemaSimpleType type = schemaTypes[name] as XmlSchemaSimpleType;
            if (type != null) {
                CompileSimpleType(type);
            } 
            else {
                type = DatatypeImplementation.GetSimpleTypeFromXsdType(name); 
            } 
            return type;
        } 

        private XmlSchemaComplexType GetComplexType(XmlQualifiedName name) {
            XmlSchemaComplexType type = schemaTypes[name] as XmlSchemaComplexType;
            if (type != null) { 
                CompileComplexType(type);
            } 
            return type; 
        }
 
         private XmlSchemaType GetAnySchemaType(XmlQualifiedName name) {
                XmlSchemaType type = (XmlSchemaType)schemaTypes[name];
                if (type != null) {
                    if (type is XmlSchemaComplexType) { 
                        CompileComplexType((XmlSchemaComplexType)type);
                    } 
                    else { 
                        CompileSimpleType((XmlSchemaSimpleType)type);
                    } 
                    return type;
                }
                else { //Its is a built-in simpleType
                    XmlSchemaSimpleType simpleType = DatatypeImplementation.GetSimpleTypeFromXsdType(name); 
                    return simpleType;
                } 
        } 

         private void CopyPosition(XmlSchemaObject to, XmlSchemaObject from, bool copyParent) { 
             to.SourceUri = from.SourceUri;
             to.LinePosition = from.LinePosition;
             to.LineNumber = from.LineNumber;
             if (copyParent) { 
                to.Parent = from.Parent;
             } 
         } 

         private bool IsFixedEqual(SchemaDeclBase baseDecl, SchemaDeclBase derivedDecl) { 

            if (baseDecl.Presence == SchemaDeclBase.Use.Fixed || baseDecl.Presence == SchemaDeclBase.Use.RequiredFixed) {
                object baseFixedValue = baseDecl.DefaultValueTyped;
                object derivedFixedValue = derivedDecl.DefaultValueTyped; 

                Debug.Assert(baseFixedValue != null); 
                if (derivedDecl.Presence != SchemaDeclBase.Use.Fixed && derivedDecl.Presence != SchemaDeclBase.Use.RequiredFixed) { 
                    return false;
                } 
                Debug.Assert(derivedFixedValue != null);
                XmlSchemaDatatype baseDatatype = baseDecl.Datatype;
                XmlSchemaDatatype derivedDatatype = derivedDecl.Datatype;
 
                if (baseDatatype.Variety == XmlSchemaDatatypeVariety.Union) {
                    if (derivedDatatype.Variety == XmlSchemaDatatypeVariety.Union) { 
                        if ( !derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue) ) { 
                            return false;
                        } 
                    }
                    else { //Base is union and derived is member of union
                        XsdSimpleValue simpleFixedValue = baseDecl.DefaultValueTyped as XsdSimpleValue;
                        Debug.Assert(simpleFixedValue != null); 
                        XmlSchemaDatatype memberType = simpleFixedValue.XmlType.Datatype;
                        if (!memberType.IsComparable(derivedDatatype) || !derivedDatatype.IsEqual(simpleFixedValue.TypedValue, derivedFixedValue)) { //base type {Union of long & string}, derived type {int} 
                            return false; 
                        }
                    } 
                }
                else if (!derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue)) {
                    return false;
                } 
            }
            return true; 
         } 
    };
 
} // namespace System.Xml

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK