Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Schema / SchemaSetCompiler.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="Compiler.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>                                                                
6 //------------------------------------------------------------------------------
7
8 namespace System.Xml.Schema {
9
10     using System;
11     using System.Collections;
12     using System.Globalization;
13     using System.Text; 
14     using System.Diagnostics;
15
16     internal sealed class Compiler : BaseProcessor {
17         string restrictionErrorMsg;
18         XmlSchemaObjectTable attributes = new XmlSchemaObjectTable();
19         XmlSchemaObjectTable attributeGroups = new XmlSchemaObjectTable();
20         XmlSchemaObjectTable elements = new XmlSchemaObjectTable();
21         XmlSchemaObjectTable schemaTypes = new XmlSchemaObjectTable();
22         XmlSchemaObjectTable groups = new XmlSchemaObjectTable();
23         XmlSchemaObjectTable notations = new XmlSchemaObjectTable();
24         XmlSchemaObjectTable examplars = new XmlSchemaObjectTable();
25         XmlSchemaObjectTable identityConstraints = new XmlSchemaObjectTable();
26         Stack complexTypeStack = new Stack();
27         Hashtable schemasToCompile = new Hashtable();
28         Hashtable importedSchemas = new Hashtable();
29
30         XmlSchema schemaForSchema;
31
32         public Compiler(XmlNameTable nameTable, ValidationEventHandler eventHandler, XmlSchema schemaForSchema, XmlSchemaCompilationSettings compilationSettings) : base(nameTable, null, eventHandler, compilationSettings) {
33             this.schemaForSchema = schemaForSchema;
34         }
35
36         public bool Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo) {
37             Compile();
38             if (!HasErrors) {
39                 Output(schemaCompiledInfo);
40                 schemaSet.elements = elements;
41                 schemaSet.attributes = attributes;
42                 schemaSet.schemaTypes = schemaTypes;
43                 schemaSet.substitutionGroups = examplars;
44             }
45             return !HasErrors;
46         }
47         
48         internal void Prepare(XmlSchema schema, bool cleanup) {
49             if (schemasToCompile[schema] != null) {
50                 return;
51             }
52             schemasToCompile.Add(schema, schema);
53             foreach (XmlSchemaElement element in schema.Elements.Values) {
54                 if (cleanup) {
55                     CleanupElement(element);
56                 }
57                 AddToTable(elements, element.QualifiedName, element);
58             }
59             foreach (XmlSchemaAttribute attribute in schema.Attributes.Values) {
60                 if (cleanup) {
61                     CleanupAttribute(attribute);
62                 }
63                 AddToTable(attributes, attribute.QualifiedName, attribute);
64             }
65             foreach (XmlSchemaGroup group in schema.Groups.Values) {
66                 if (cleanup) {
67                     CleanupGroup(group);
68                 }
69                 AddToTable(groups, group.QualifiedName, group);
70             }
71             foreach (XmlSchemaAttributeGroup attributeGroup in schema.AttributeGroups.Values) {
72                 if (cleanup) {
73                     CleanupAttributeGroup(attributeGroup);
74                 }
75                 AddToTable(attributeGroups, attributeGroup.QualifiedName, attributeGroup);
76             }
77             foreach (XmlSchemaType type in schema.SchemaTypes.Values) {
78                 if (cleanup) {
79                     XmlSchemaComplexType ct = type as XmlSchemaComplexType;
80                     if (ct != null) {
81                         CleanupComplexType(ct);
82                     }
83                     else {
84                         CleanupSimpleType(type as XmlSchemaSimpleType);
85                     }
86                 }
87                 AddToTable(schemaTypes, type.QualifiedName, type);
88             }
89             foreach (XmlSchemaNotation notation in schema.Notations.Values) {
90                 AddToTable(notations, notation.QualifiedName, notation);
91             }
92             foreach (XmlSchemaIdentityConstraint ic in schema.IdentityConstraints.Values) {
93                 AddToTable(identityConstraints, ic.QualifiedName, ic);
94             }
95         }
96         
97         private void UpdateSForSSimpleTypes() {
98             Debug.Assert(schemaForSchema != null);
99             XmlSchemaSimpleType[] schemaSimpleTypes = DatatypeImplementation.GetBuiltInTypes();
100             XmlSchemaSimpleType builtInType;
101             //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
102             int numberOfSchemaTypes = schemaSimpleTypes.Length - 3; //skip last 2 xquery types
103             for (int i = 12; i < numberOfSchemaTypes; i++) {
104                 builtInType = schemaSimpleTypes[i];
105                 schemaForSchema.SchemaTypes.Replace(builtInType.QualifiedName, builtInType);
106                 this.schemaTypes.Replace(builtInType.QualifiedName, builtInType);
107             }
108         }
109
110         private void Output(SchemaInfo schemaInfo) {
111             string tns;
112             foreach(XmlSchema schema in schemasToCompile.Values) {
113                 tns = schema.TargetNamespace;
114                 if (tns == null) {
115                     tns = string.Empty;
116                 }
117                 schemaInfo.TargetNamespaces[tns] = true;
118             }
119             foreach (XmlSchemaElement element in elements.Values) {
120                 schemaInfo.ElementDecls.Add(element.QualifiedName, element.ElementDecl);
121             }
122             foreach (XmlSchemaAttribute attribute in attributes.Values) {
123                 schemaInfo.AttributeDecls.Add(attribute.QualifiedName, attribute.AttDef);
124             }    
125             foreach (XmlSchemaType type in schemaTypes.Values) {
126                 schemaInfo.ElementDeclsByType.Add(type.QualifiedName, type.ElementDecl);
127             }
128             foreach (XmlSchemaNotation notation in notations.Values) {
129                 SchemaNotation no = new SchemaNotation(notation.QualifiedName);
130                 no.SystemLiteral = notation.System;
131                 no.Pubid = notation.Public;
132                 if (!schemaInfo.Notations.ContainsKey(no.Name.Name)) {
133                     schemaInfo.Notations.Add(no.Name.Name, no);
134                 }
135             }
136            
137         }
138
139         internal void ImportAllCompiledSchemas(XmlSchemaSet schemaSet) {
140               XmlSchema currentSchema;
141               int schemaIndex;
142               SortedList schemas = schemaSet.SortedSchemas; 
143               for (schemaIndex = 0; schemaIndex < schemas.Count; schemaIndex++) {
144                   currentSchema = (XmlSchema)schemas.GetByIndex(schemaIndex);
145                   if (currentSchema.IsCompiledBySet) { //Import already compiled schemas
146                     Prepare(currentSchema, false);
147                   }
148               }
149         }
150
151         internal bool Compile() {
152             schemaTypes.Insert(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType);
153             if (schemaForSchema != null) { //Get our built-in types
154                 schemaForSchema.SchemaTypes.Replace(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType);
155                 UpdateSForSSimpleTypes();
156             }
157
158             foreach(XmlSchemaGroup group in groups.Values) {
159                 CompileGroup(group);
160             }
161             foreach(XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) {
162                 CompileAttributeGroup(attributeGroup);
163             }
164             foreach (XmlSchemaType type in schemaTypes.Values) {
165                 XmlSchemaComplexType ct = type as XmlSchemaComplexType;
166                 if (ct != null) {
167                     CompileComplexType(ct);
168                 }
169                 else {
170                     CompileSimpleType((XmlSchemaSimpleType)type);
171                 }
172             }
173             foreach (XmlSchemaElement element in elements.Values) {
174                 if (element.ElementDecl == null) {
175                     CompileElement(element);
176                 }
177             }
178             foreach (XmlSchemaAttribute attribute in attributes.Values) {
179                 if (attribute.AttDef == null) {
180                     CompileAttribute(attribute);
181                 }
182             }
183             foreach (XmlSchemaIdentityConstraint identityConstraint in identityConstraints.Values) {
184                 if (identityConstraint.CompiledConstraint == null) {
185                     CompileIdentityConstraint(identityConstraint);
186                 }
187             }
188             while (this.complexTypeStack.Count > 0) {
189                 XmlSchemaComplexType type = (XmlSchemaComplexType)complexTypeStack.Pop();
190                 CompileComplexTypeElements(type);
191             }
192
193             ProcessSubstitutionGroups();
194
195             foreach (XmlSchemaType type in schemaTypes.Values) {
196                 XmlSchemaComplexType localType = type as XmlSchemaComplexType;
197                 if (localType != null) {
198                     CheckParticleDerivation(localType);
199                 }
200             }
201             
202             foreach (XmlSchemaElement element in elements.Values) {
203                 XmlSchemaComplexType localComplexType = element.ElementSchemaType as XmlSchemaComplexType;
204                 if (localComplexType != null && element.SchemaTypeName == XmlQualifiedName.Empty) { // only local schemaTypes
205                     CheckParticleDerivation(localComplexType);
206                 }
207             }
208             foreach (XmlSchemaGroup group in groups.Values) { //Check particle derivation for redefined groups
209                 XmlSchemaGroup baseGroup = group.Redefined;
210                 if (baseGroup != null) {
211                     RecursivelyCheckRedefinedGroups(group, baseGroup);
212                 }
213             }
214
215             foreach (XmlSchemaAttributeGroup attributeGroup in attributeGroups.Values) {
216                 XmlSchemaAttributeGroup baseAttributeGroup = attributeGroup.Redefined;
217                 if (baseAttributeGroup != null) {
218                     RecursivelyCheckRedefinedAttributeGroups(attributeGroup, baseAttributeGroup);
219                 }
220             }
221             return !HasErrors;
222         }
223
224         private void CleanupAttribute(XmlSchemaAttribute attribute) {
225             if (attribute.SchemaType != null) {
226                 CleanupSimpleType((XmlSchemaSimpleType)attribute.SchemaType);
227             }
228             attribute.AttDef = null;
229         }
230         
231         private void CleanupAttributeGroup(XmlSchemaAttributeGroup attributeGroup) {
232             CleanupAttributes(attributeGroup.Attributes);
233             attributeGroup.AttributeUses.Clear();
234             attributeGroup.AttributeWildcard = null;
235             if (attributeGroup.Redefined != null) {
236                 CleanupAttributeGroup(attributeGroup.Redefined);
237             }
238         }
239         
240         private void CleanupComplexType(XmlSchemaComplexType complexType) {
241             if (complexType.QualifiedName == DatatypeImplementation.QnAnyType) { //if it is built-in anyType dont clean it.
242                 return;
243             }
244             if (complexType.ContentModel != null) { //simpleContent or complexContent
245                 if (complexType.ContentModel is XmlSchemaSimpleContent) {
246                     XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
247                     if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
248                         XmlSchemaSimpleContentExtension simpleExtension = (XmlSchemaSimpleContentExtension)simpleContent.Content;
249                         CleanupAttributes(simpleExtension.Attributes);
250                     }
251                     else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
252                         XmlSchemaSimpleContentRestriction simpleRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content;
253                         CleanupAttributes(simpleRestriction.Attributes);
254                     }
255                 }
256                 else { // complexType.ContentModel is XmlSchemaComplexContent
257                     XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
258                     if (complexContent.Content is XmlSchemaComplexContentExtension) {
259                         XmlSchemaComplexContentExtension complexExtension = (XmlSchemaComplexContentExtension)complexContent.Content;
260                         CleanupParticle(complexExtension.Particle);
261                         CleanupAttributes(complexExtension.Attributes);
262
263                     }
264                     else { //XmlSchemaComplexContentRestriction
265                         XmlSchemaComplexContentRestriction complexRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content;
266                         CleanupParticle(complexRestriction.Particle);
267                         CleanupAttributes(complexRestriction.Attributes);
268                     }
269                 }
270             }
271             else { //equals XmlSchemaComplexContent with baseType is anyType
272                 CleanupParticle(complexType.Particle);
273                 CleanupAttributes(complexType.Attributes);
274             }
275             complexType.LocalElements.Clear();
276             complexType.AttributeUses.Clear();
277             complexType.SetAttributeWildcard(null);
278             complexType.SetContentTypeParticle(XmlSchemaParticle.Empty);
279             complexType.ElementDecl = null;
280             complexType.HasWildCard = false;
281
282             //Clean up the original type if this is a redefined type
283             if (complexType.Redefined != null) {
284                 CleanupComplexType(complexType.Redefined as XmlSchemaComplexType);
285             }
286         }
287         
288         private void CleanupSimpleType(XmlSchemaSimpleType simpleType) {
289             if (simpleType == XmlSchemaType.GetBuiltInSimpleType(simpleType.TypeCode)) { //If it is a built-in simple type dont clean up
290                 return;
291             }
292             simpleType.ElementDecl = null;
293             //Clean up the original group if this is a redefined group
294             if (simpleType.Redefined != null) {
295                 CleanupSimpleType(simpleType.Redefined as XmlSchemaSimpleType);
296             }
297         }
298         
299         private void CleanupElement(XmlSchemaElement element) {
300             if (element.SchemaType != null) {
301                 XmlSchemaComplexType complexType = element.SchemaType as XmlSchemaComplexType;
302                 if (complexType != null) {
303                     CleanupComplexType(complexType);
304                 }
305                 else {
306                     CleanupSimpleType((XmlSchemaSimpleType)element.SchemaType);
307                 }
308             }
309             for (int i = 0; i < element.Constraints.Count; ++i) {
310                 ((XmlSchemaIdentityConstraint)element.Constraints[i]).CompiledConstraint = null;
311             }
312             element.ElementDecl = null;
313             element.IsLocalTypeDerivationChecked = false; //clear Local element type derivation check 
314         }
315         
316         private void CleanupAttributes(XmlSchemaObjectCollection attributes) {
317             for (int i = 0; i < attributes.Count; ++i) {
318                 XmlSchemaAttribute attribute = attributes[i] as XmlSchemaAttribute;
319                 if (attribute != null) {
320                     CleanupAttribute(attribute);
321                 }
322             }
323         }
324
325         private void CleanupGroup(XmlSchemaGroup group) {
326             CleanupParticle(group.Particle);
327             group.CanonicalParticle = null;
328             //Clean up the original group if this is a redefined group
329             if (group.Redefined != null) {
330                 CleanupGroup(group.Redefined);
331             }
332         }
333
334         private void CleanupParticle(XmlSchemaParticle particle) {
335             XmlSchemaElement element = particle as XmlSchemaElement;
336             if (element != null) {
337                 CleanupElement(element);
338                 return;
339             }
340
341             XmlSchemaGroupBase groupBase = particle as XmlSchemaGroupBase;
342             if (groupBase != null) {
343                 for (int i = 0; i < groupBase.Items.Count; ++i) {
344                     CleanupParticle((XmlSchemaParticle)groupBase.Items[i]);
345                 }
346             }
347         }
348
349         private void ProcessSubstitutionGroups() {
350             foreach (XmlSchemaElement element in this.elements.Values) {
351                 if (!element.SubstitutionGroup.IsEmpty) {
352                     XmlSchemaElement headElement = this.elements[element.SubstitutionGroup] as XmlSchemaElement;
353                     if (headElement == null) {
354                         SendValidationEvent(Res.Sch_NoExamplar, element);
355                         continue;
356                     }
357                     //Check derivation of member's type against head's type
358                     if (!XmlSchemaType.IsDerivedFrom(element.ElementSchemaType, headElement.ElementSchemaType, headElement.FinalResolved)) {
359                         SendValidationEvent(Res.Sch_InvalidSubstitutionMember, (element.QualifiedName).ToString(), (headElement.QualifiedName).ToString(), element);
360                     }
361
362                     //Create substitutionGroup
363                     XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)this.examplars[element.SubstitutionGroup];
364                     if (substitutionGroup == null) {
365                         substitutionGroup = new XmlSchemaSubstitutionGroup();
366                         substitutionGroup.Examplar = element.SubstitutionGroup;
367                         examplars.Add(element.SubstitutionGroup, substitutionGroup);
368                     }
369                     ArrayList members = substitutionGroup.Members;
370                     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
371                         members.Add(element);
372                     }
373                 }
374             }
375
376             //Check the subst groups that we just built
377             foreach (XmlSchemaSubstitutionGroup substitutionGroup in examplars.Values) {
378                 CompileSubstitutionGroup(substitutionGroup);
379             }
380         }
381
382         private void CompileSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup) {
383             if (substitutionGroup.IsProcessing && substitutionGroup.Members.Count > 0) {
384                 SendValidationEvent(Res.Sch_SubstitutionCircularRef, (XmlSchemaElement)substitutionGroup.Members[0]);
385                 return;
386             }
387             XmlSchemaElement examplar = (XmlSchemaElement)elements[substitutionGroup.Examplar];
388             Debug.Assert(examplar != null); //Headelement presence is checked while building subst groups
389             if (substitutionGroup.Members.Contains(examplar)) {// already checked
390                 return;
391             }
392             substitutionGroup.IsProcessing = true;
393             try {
394                 if (examplar.FinalResolved == XmlSchemaDerivationMethod.All) {
395                     SendValidationEvent(Res.Sch_InvalidExamplar, examplar);
396                 }
397                 //Build transitive members
398                 ArrayList newMembers = null;
399                 for (int i = 0; i < substitutionGroup.Members.Count; ++i) {
400                     XmlSchemaElement element = (XmlSchemaElement)substitutionGroup.Members[i];
401                     //Chain to other head's that are members of this head's substGroup
402                     if ((element.ElementDecl.Block & XmlSchemaDerivationMethod.Substitution) == 0) { //Chain only if substitution is not blocked
403                         XmlSchemaSubstitutionGroup g = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName];
404                         if (g != null) {
405                             CompileSubstitutionGroup(g);
406                             for (int j = 0; j < g.Members.Count; ++j) {
407                                 if (g.Members[j] != element) { //Exclude the head
408                                     if (newMembers == null) {
409                                         newMembers = new ArrayList();
410                                     }
411                                     newMembers.Add(g.Members[j]);
412                                 }
413                             }
414                         }
415                     }
416                 }
417                 if (newMembers != null) {
418                     for (int i = 0; i < newMembers.Count; ++i) {
419                         substitutionGroup.Members.Add(newMembers[i]);
420                     }
421                 }
422                 substitutionGroup.Members.Add(examplar); // Compiled mark
423             }
424             finally {
425                 substitutionGroup.IsProcessing = false;              
426             }
427         }
428
429         private void RecursivelyCheckRedefinedGroups(XmlSchemaGroup redefinedGroup, XmlSchemaGroup baseGroup) {
430             if (baseGroup.Redefined != null) {
431                 RecursivelyCheckRedefinedGroups(baseGroup, baseGroup.Redefined);
432             }
433             if (redefinedGroup.SelfReferenceCount == 0) {
434                 if (baseGroup.CanonicalParticle == null) {
435                     baseGroup.CanonicalParticle = CannonicalizeParticle(baseGroup.Particle, true);
436                 }
437                 if (redefinedGroup.CanonicalParticle == null) {
438                     redefinedGroup.CanonicalParticle = CannonicalizeParticle(redefinedGroup.Particle, true);
439                 }
440                 CompileParticleElements(redefinedGroup.CanonicalParticle);
441                 CompileParticleElements(baseGroup.CanonicalParticle);
442                 CheckParticleDerivation(redefinedGroup.CanonicalParticle, baseGroup.CanonicalParticle);
443             }
444         }
445
446         private void RecursivelyCheckRedefinedAttributeGroups(XmlSchemaAttributeGroup attributeGroup, XmlSchemaAttributeGroup baseAttributeGroup) {
447             if (baseAttributeGroup.Redefined != null) {
448                 RecursivelyCheckRedefinedAttributeGroups(baseAttributeGroup, baseAttributeGroup.Redefined);
449             }
450             if (attributeGroup.SelfReferenceCount == 0) {
451                 CompileAttributeGroup(baseAttributeGroup);
452                 CompileAttributeGroup(attributeGroup);
453                 CheckAtrributeGroupRestriction(baseAttributeGroup, attributeGroup);
454             }
455         }
456
457         private void CompileGroup(XmlSchemaGroup group) {
458             if (group.IsProcessing) {
459                 SendValidationEvent(Res.Sch_GroupCircularRef, group);
460                 group.CanonicalParticle = XmlSchemaParticle.Empty;
461             } 
462             else {
463                 group.IsProcessing = true;
464                 if (group.CanonicalParticle == null) { 
465                     group.CanonicalParticle = CannonicalizeParticle(group.Particle, true); 
466                 }
467                 Debug.Assert(group.CanonicalParticle != null);
468                 group.IsProcessing = false; //Not enclosung in try -finally as cannonicalizeParticle will not throw exception
469             }
470         }
471
472         private void CompileSimpleType(XmlSchemaSimpleType simpleType) {
473             if (simpleType.IsProcessing) {
474                 throw new XmlSchemaException(Res.Sch_TypeCircularRef, simpleType);
475             }
476             if (simpleType.ElementDecl != null) { // already compiled
477                 return;
478             }
479             simpleType.IsProcessing = true;
480             try {
481                 if (simpleType.Content is XmlSchemaSimpleTypeList) {
482                     XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)simpleType.Content;
483                     XmlSchemaDatatype datatype;
484                     simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType); 
485                     if (list.ItemTypeName.IsEmpty) {
486                         CompileSimpleType(list.ItemType);
487                         list.BaseItemType = list.ItemType;
488                         datatype = list.ItemType.Datatype;
489                     }
490                     else {
491                         XmlSchemaSimpleType type = GetSimpleType(list.ItemTypeName);
492                         if (type != null) {
493                             if ((type.FinalResolved & XmlSchemaDerivationMethod.List) != 0) {
494                                 SendValidationEvent(Res.Sch_BaseFinalList, simpleType);
495                             }
496                             list.BaseItemType = type;
497                             datatype = type.Datatype;
498                         }
499                         else {
500                             throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, list.ItemTypeName.ToString(), list);   
501                         }
502                     }
503                     simpleType.SetDatatype(datatype.DeriveByList(simpleType));
504                     simpleType.SetDerivedBy(XmlSchemaDerivationMethod.List);
505                 }
506                 else if (simpleType.Content is XmlSchemaSimpleTypeRestriction) {
507                     XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content;
508                     XmlSchemaDatatype datatype;
509                     if (restriction.BaseTypeName.IsEmpty) {
510                         CompileSimpleType(restriction.BaseType);
511                         simpleType.SetBaseSchemaType(restriction.BaseType);
512                         datatype = restriction.BaseType.Datatype;
513                     }
514                     else if (simpleType.Redefined != null && restriction.BaseTypeName == simpleType.Redefined.QualifiedName) {
515                         CompileSimpleType((XmlSchemaSimpleType)simpleType.Redefined);
516                         simpleType.SetBaseSchemaType(simpleType.Redefined.BaseXmlSchemaType);
517                         datatype = simpleType.Redefined.Datatype;
518                     }
519                     else {
520                         if (restriction.BaseTypeName.Equals(DatatypeImplementation.QnAnySimpleType)) {
521                             XmlSchema parentSchema = Preprocessor.GetParentSchema(simpleType);
522                             if (parentSchema.TargetNamespace != XmlSchema.Namespace) { //If it is not SForS, then error
523                                 throw new XmlSchemaException(Res.Sch_InvalidSimpleTypeRestriction, restriction.BaseTypeName.ToString(), simpleType);   
524                             }
525                         }
526                         XmlSchemaSimpleType type = GetSimpleType(restriction.BaseTypeName);
527                         if (type != null) {
528                             if ((type.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
529                                 SendValidationEvent(Res.Sch_BaseFinalRestriction, simpleType);
530                             }
531                             simpleType.SetBaseSchemaType(type);
532                             datatype = type.Datatype;
533                         }
534                         else {
535                             throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, restriction.BaseTypeName.ToString(), restriction);   
536                         }
537                     }
538                     simpleType.SetDatatype(datatype.DeriveByRestriction(restriction.Facets, NameTable, simpleType));
539                     simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
540                 }
541                 else { //simpleType.Content is XmlSchemaSimpleTypeUnion
542                     XmlSchemaSimpleType[] baseTypes = CompileBaseMemberTypes(simpleType);
543                     simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType);
544                     simpleType.SetDatatype(XmlSchemaDatatype.DeriveByUnion(baseTypes, simpleType));
545                     simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Union);
546                 }
547             } 
548             catch (XmlSchemaException e) {
549                 if (e.SourceSchemaObject == null) {
550                     e.SetSource(simpleType);
551                 }
552                 SendValidationEvent(e);
553                 simpleType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
554             } 
555             finally {
556                 SchemaElementDecl decl = new SchemaElementDecl();
557                 decl.ContentValidator = ContentValidator.TextOnly;
558                 decl.SchemaType = simpleType;
559                 decl.Datatype = simpleType.Datatype;
560                 simpleType.ElementDecl = decl;
561                 simpleType.IsProcessing = false;
562             }
563         }
564
565         private XmlSchemaSimpleType[] CompileBaseMemberTypes(XmlSchemaSimpleType simpleType) {
566             XmlSchemaSimpleType unionMember;
567             ArrayList memberTypeDefinitions = new ArrayList();
568
569             XmlSchemaSimpleTypeUnion mainUnion = (XmlSchemaSimpleTypeUnion)simpleType.Content;
570
571             XmlQualifiedName[] mainMemberTypes = mainUnion.MemberTypes;
572             if (mainMemberTypes != null) {
573                 for (int i = 0; i < mainMemberTypes.Length; ++i) {
574                     unionMember = GetSimpleType(mainMemberTypes[i]);
575                     if (unionMember != null) {
576                         if (unionMember.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
577                             CheckUnionType(unionMember, memberTypeDefinitions, simpleType);
578                         }
579                         else { //its list or atomic
580                             memberTypeDefinitions.Add(unionMember);
581                         }
582                         //Check derivation method of the member that is referenced
583                         if ((unionMember.FinalResolved & XmlSchemaDerivationMethod.Union) != 0) {
584                             SendValidationEvent(Res.Sch_BaseFinalUnion, simpleType);
585                         }
586                     }
587                     else {
588                         throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, mainMemberTypes[i].ToString(), mainUnion);   
589                     }
590                 }
591             }
592
593             //Now add the baseTypes that are defined inside the union itself
594             XmlSchemaObjectCollection mainBaseTypes = mainUnion.BaseTypes; //
595             if (mainBaseTypes != null) {
596                 for (int i = 0; i < mainBaseTypes.Count; ++i) {
597                     XmlSchemaSimpleType st = (XmlSchemaSimpleType)mainBaseTypes[i];
598                     CompileSimpleType(st);
599                     if (st.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
600                         CheckUnionType(st, memberTypeDefinitions, simpleType);
601                     }
602                     else {  //its list or atomic
603                         memberTypeDefinitions.Add(st);
604                     }
605                 }
606             }
607             //set all types
608             mainUnion.SetBaseMemberTypes(memberTypeDefinitions.ToArray(typeof(XmlSchemaSimpleType)) as XmlSchemaSimpleType[]);
609             return mainUnion.BaseMemberTypes;
610         }
611
612         private void CheckUnionType(XmlSchemaSimpleType unionMember, ArrayList memberTypeDefinitions, XmlSchemaSimpleType parentType) {
613             XmlSchemaDatatype unionDatatype = unionMember.Datatype;
614             if (unionMember.DerivedBy == XmlSchemaDerivationMethod.Restriction && (unionDatatype.HasLexicalFacets || unionDatatype.HasValueFacets) ) {
615                 SendValidationEvent(Res.Sch_UnionFromUnion, parentType);
616             }
617             else {
618                 Datatype_union uniondt = unionMember.Datatype as Datatype_union;
619                 memberTypeDefinitions.AddRange(uniondt.BaseMemberTypes);
620             }
621         }
622
623         private void CompileComplexType(XmlSchemaComplexType complexType) {
624             if (complexType.ElementDecl != null) { //already compiled
625                 return;
626             }
627             if (complexType.IsProcessing) {
628                 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
629                 return;
630             }
631             complexType.IsProcessing = true;
632             try {
633                 if (complexType.ContentModel != null) { //simpleContent or complexContent
634                     if (complexType.ContentModel is XmlSchemaSimpleContent) {
635                         XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
636                         complexType.SetContentType(XmlSchemaContentType.TextOnly);
637                         if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
638                             CompileSimpleContentExtension(complexType, (XmlSchemaSimpleContentExtension)simpleContent.Content);
639                         }
640                         else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
641                             CompileSimpleContentRestriction(complexType, (XmlSchemaSimpleContentRestriction)simpleContent.Content);
642                         }
643                     }
644                     else { // complexType.ContentModel is XmlSchemaComplexContent
645                         XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
646                         if (complexContent.Content is XmlSchemaComplexContentExtension) {
647                             CompileComplexContentExtension(complexType, complexContent, (XmlSchemaComplexContentExtension)complexContent.Content);
648                         }
649                         else { // complexContent.Content is XmlSchemaComplexContentRestriction
650                             CompileComplexContentRestriction(complexType, complexContent, (XmlSchemaComplexContentRestriction)complexContent.Content);
651                         }
652                     }
653                 }
654                 else { //equals XmlSchemaComplexContent with baseType is anyType
655                         complexType.SetBaseSchemaType(XmlSchemaComplexType.AnyType);
656                         CompileLocalAttributes(XmlSchemaComplexType.AnyType, complexType, complexType.Attributes, complexType.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
657                         complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
658                         complexType.SetContentTypeParticle(CompileContentTypeParticle(complexType.Particle));
659                         complexType.SetContentType(GetSchemaContentType(complexType, null, complexType.ContentTypeParticle));
660                 }
661                 if (complexType.ContainsIdAttribute(true)) {
662                     SendValidationEvent(Res.Sch_TwoIdAttrUses, complexType);
663                 }
664                 SchemaElementDecl decl = new SchemaElementDecl();
665                 decl.ContentValidator = CompileComplexContent(complexType);
666                 decl.SchemaType = complexType;
667                 decl.IsAbstract = complexType.IsAbstract;
668                 decl.Datatype = complexType.Datatype;
669                 decl.Block = complexType.BlockResolved;
670                 decl.AnyAttribute = complexType.AttributeWildcard;
671                 foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) {
672                     if (attribute.Use == XmlSchemaUse.Prohibited) {
673                         if (!decl.ProhibitedAttributes.ContainsKey(attribute.QualifiedName)) {
674                             decl.ProhibitedAttributes.Add(attribute.QualifiedName, attribute.QualifiedName);
675                         }
676                     }
677                     else {
678                         if (!decl.AttDefs.ContainsKey(attribute.QualifiedName) && attribute.AttDef != null && attribute.AttDef.Name != XmlQualifiedName.Empty && attribute.AttDef != SchemaAttDef.Empty) {
679                             decl.AddAttDef(attribute.AttDef);
680                         }
681                     }
682                 }
683                 complexType.ElementDecl = decl;
684             }
685             finally {
686                 complexType.IsProcessing = false;
687             }
688         }
689
690
691         private void CompileSimpleContentExtension(XmlSchemaComplexType complexType, XmlSchemaSimpleContentExtension simpleExtension) {
692             XmlSchemaComplexType baseType = null;
693             if (complexType.Redefined != null && simpleExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
694                 baseType = (XmlSchemaComplexType)complexType.Redefined;
695                 CompileComplexType(baseType);
696                 complexType.SetBaseSchemaType(baseType);
697                 complexType.SetDatatype(baseType.Datatype);
698             }
699             else {
700                 XmlSchemaType bto = GetAnySchemaType(simpleExtension.BaseTypeName);
701                 if (bto == null) {
702                     SendValidationEvent(Res.Sch_UndeclaredType, simpleExtension.BaseTypeName.ToString(), simpleExtension);   
703                 } 
704                 else {
705                     complexType.SetBaseSchemaType(bto);
706                     complexType.SetDatatype(bto.Datatype);
707                 }
708                 baseType = bto as XmlSchemaComplexType;
709             }
710             if (baseType != null) {
711                 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
712                     SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
713                 }
714                 if (baseType.ContentType != XmlSchemaContentType.TextOnly) {
715                     SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
716                 }
717             } 
718             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
719             CompileLocalAttributes(baseType, complexType, simpleExtension.Attributes, simpleExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
720         }
721
722         private void CompileSimpleContentRestriction(XmlSchemaComplexType complexType, XmlSchemaSimpleContentRestriction simpleRestriction) {
723             XmlSchemaComplexType baseType = null;
724             XmlSchemaDatatype datatype = null;
725             if (complexType.Redefined != null && simpleRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
726                 baseType = (XmlSchemaComplexType)complexType.Redefined;
727                 CompileComplexType(baseType);
728                 datatype = baseType.Datatype;
729             }
730             else {
731                 baseType = GetComplexType(simpleRestriction.BaseTypeName);
732                 if (baseType == null) {
733                     SendValidationEvent(Res.Sch_UndefBaseRestriction, simpleRestriction.BaseTypeName.ToString(), simpleRestriction);
734                     return;
735                 }
736                 if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
737                     if (simpleRestriction.BaseType == null) { 
738                         datatype = baseType.Datatype; 
739                         //There is a bug here. Need to check if simpleRestriction has facets.
740                         //If yes, Need tp apply these facets as well. 
741                     }
742                     else {
743                         CompileSimpleType(simpleRestriction.BaseType);
744                         if(!XmlSchemaType.IsDerivedFromDatatype(simpleRestriction.BaseType.Datatype, baseType.Datatype, XmlSchemaDerivationMethod.None)) {
745                            SendValidationEvent(Res.Sch_DerivedNotFromBase, simpleRestriction);
746                         }
747                         datatype = simpleRestriction.BaseType.Datatype;
748                     }
749                 }
750                 else if (baseType.ContentType == XmlSchemaContentType.Mixed && baseType.ElementDecl.ContentValidator.IsEmptiable) {
751                     if (simpleRestriction.BaseType != null) {
752                         CompileSimpleType(simpleRestriction.BaseType);
753                         complexType.SetBaseSchemaType(simpleRestriction.BaseType);
754                         datatype = simpleRestriction.BaseType.Datatype;
755                     }
756                     else {
757                         SendValidationEvent(Res.Sch_NeedSimpleTypeChild, simpleRestriction);
758                     }
759                 }
760                 else {
761                     SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
762                 }
763             }
764             if (baseType != null && baseType.ElementDecl != null) {
765                 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
766                     SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
767                 }
768             }
769             if (baseType != null) {
770                 complexType.SetBaseSchemaType(baseType);
771             }
772             if (datatype != null) {
773                 try {
774                     complexType.SetDatatype(datatype.DeriveByRestriction(simpleRestriction.Facets, NameTable, complexType));
775                 }
776                 catch (XmlSchemaException e) {
777                     if (e.SourceSchemaObject == null) {
778                         e.SetSource(complexType);
779                     }
780                     SendValidationEvent(e);
781                     complexType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
782                 } 
783             }
784             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
785             CompileLocalAttributes(baseType, complexType, simpleRestriction.Attributes, simpleRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
786         }
787
788         private void CompileComplexContentExtension(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentExtension complexExtension) {
789             XmlSchemaComplexType baseType = null;
790             if (complexType.Redefined != null && complexExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
791                 baseType = (XmlSchemaComplexType)complexType.Redefined;
792                 CompileComplexType(baseType);
793             }
794             else {
795                 baseType = GetComplexType(complexExtension.BaseTypeName);
796                 if (baseType == null) {
797                     SendValidationEvent(Res.Sch_UndefBaseExtension, complexExtension.BaseTypeName.ToString(), complexExtension);   
798                     return;
799                 }
800             }
801             if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
802                 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
803             }
804             CompileLocalAttributes(baseType, complexType, complexExtension.Attributes, complexExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
805
806             XmlSchemaParticle baseParticle = baseType.ContentTypeParticle;
807             XmlSchemaParticle extendedParticle = CannonicalizeParticle(complexExtension.Particle, true);
808             if (baseParticle != XmlSchemaParticle.Empty) {
809                 if (extendedParticle != XmlSchemaParticle.Empty) {
810                     XmlSchemaSequence compiledParticle = new XmlSchemaSequence();
811                     compiledParticle.Items.Add(baseParticle);
812                     compiledParticle.Items.Add(extendedParticle);
813                     complexType.SetContentTypeParticle(CompileContentTypeParticle(compiledParticle));
814                 }
815                 else {
816                     complexType.SetContentTypeParticle(baseParticle);
817                 }
818             }
819             else {
820                 complexType.SetContentTypeParticle(extendedParticle);
821             }
822             XmlSchemaContentType contentType = GetSchemaContentType(complexType, complexContent, extendedParticle);
823             if (contentType == XmlSchemaContentType.Empty) { //Derived content type is empty, Get ContentType from base
824                 contentType = baseType.ContentType;
825                 // In case of a simple base type (content type is TextOnly) the derived type
826                 //   will be the same as the base type. So set the same content type and then also
827                 //   set the same data type.
828                 if (contentType == XmlSchemaContentType.TextOnly) {
829                     complexType.SetDatatype(baseType.Datatype);
830                 }
831             }
832             complexType.SetContentType(contentType);
833
834             if (baseType.ContentType != XmlSchemaContentType.Empty && complexType.ContentType != baseType.ContentType) { //If base is empty, do not check
835                 SendValidationEvent(Res.Sch_DifContentType, complexType);
836                 return;
837             }
838             complexType.SetBaseSchemaType(baseType);
839             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
840         }
841
842         private void CompileComplexContentRestriction(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentRestriction complexRestriction) {
843             XmlSchemaComplexType baseType = null;
844             if (complexType.Redefined != null && complexRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
845                 baseType = (XmlSchemaComplexType)complexType.Redefined;
846                 CompileComplexType(baseType);
847             }
848             else {
849                 baseType = GetComplexType(complexRestriction.BaseTypeName);
850                 if (baseType == null) {
851                     SendValidationEvent(Res.Sch_UndefBaseRestriction, complexRestriction.BaseTypeName.ToString(), complexRestriction);   
852                     return;
853                 }
854             } 
855             complexType.SetBaseSchemaType(baseType);
856             if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
857                 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
858             }
859             CompileLocalAttributes(baseType, complexType, complexRestriction.Attributes, complexRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
860             
861             complexType.SetContentTypeParticle(CompileContentTypeParticle(complexRestriction.Particle));
862             XmlSchemaContentType derivedContentType = GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle);
863             complexType.SetContentType(derivedContentType);
864             switch(derivedContentType) {
865                 case XmlSchemaContentType.Empty:
866                     if (baseType.ElementDecl != null && !baseType.ElementDecl.ContentValidator.IsEmptiable) { //base is either TextOnly or its ElementOnly/Mixed and not emptiable 
867                         SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToEmpty), complexType);
868                     }
869                 break;
870
871                 case XmlSchemaContentType.Mixed:
872                     if (baseType.ContentType != XmlSchemaContentType.Mixed) {
873                         SendValidationEvent(Res.Sch_InvalidContentRestrictionDetailed, Res.GetString(Res.Sch_InvalidBaseToMixed), complexType);
874                     }
875                 break;
876             }
877             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
878         }
879
880         private void CheckParticleDerivation(XmlSchemaComplexType complexType) {
881             XmlSchemaComplexType baseType = complexType.BaseXmlSchemaType as XmlSchemaComplexType;
882             restrictionErrorMsg = null;
883             if (baseType != null && baseType != XmlSchemaComplexType.AnyType && complexType.DerivedBy == XmlSchemaDerivationMethod.Restriction) {
884                 XmlSchemaParticle derivedParticle = CannonicalizePointlessRoot(complexType.ContentTypeParticle);
885                 XmlSchemaParticle baseParticle = CannonicalizePointlessRoot(baseType.ContentTypeParticle);
886                 if (!IsValidRestriction(derivedParticle, baseParticle)) {
887 #if DEBUG
888                     if(complexType.ContentTypeParticle != null && baseType.ContentTypeParticle != null) {
889                         string position = string.Empty;
890                         if (complexType.SourceUri != null) {
891                             position = " in " + complexType.SourceUri + "(" + complexType.LineNumber + ", " + complexType.LinePosition + ")";
892                         }
893                         Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType content restriction" + position);
894                         Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpContentModel(baseType.ContentTypeParticle));
895                         Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpContentModel(complexType.ContentTypeParticle));
896                     }
897 #endif
898                     if (restrictionErrorMsg != null) {
899                         SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, complexType);
900                     }
901                     else {
902                         SendValidationEvent(Res.Sch_InvalidParticleRestriction, complexType);
903                     }
904                 }
905             }
906             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
907                 foreach(XmlSchemaElement localElement in complexType.LocalElements.Values) {
908                     if (localElement.IsLocalTypeDerivationChecked) { //Element already checked
909                         continue;
910                     }
911                     XmlSchemaComplexType localComplexType = localElement.ElementSchemaType as XmlSchemaComplexType;
912                     if (localComplexType != null && localElement.SchemaTypeName == XmlQualifiedName.Empty && localElement.RefName == XmlQualifiedName.Empty) { //Only local elements
913                         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)
914                         CheckParticleDerivation(localComplexType);
915                     }
916                 }
917             }
918         }
919
920         private void CheckParticleDerivation(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
921             restrictionErrorMsg = null;
922             derivedParticle = CannonicalizePointlessRoot(derivedParticle);
923             baseParticle = CannonicalizePointlessRoot(baseParticle);
924             if (!IsValidRestriction(derivedParticle, baseParticle)) {
925                 if (restrictionErrorMsg != null) {
926                     SendValidationEvent(Res.Sch_InvalidParticleRestrictionDetailed, restrictionErrorMsg, derivedParticle);
927                 }
928                 else {
929                     SendValidationEvent(Res.Sch_InvalidParticleRestriction, derivedParticle);
930                 }
931             }
932         }
933
934         private XmlSchemaParticle CompileContentTypeParticle(XmlSchemaParticle particle) {
935             XmlSchemaParticle ctp = CannonicalizeParticle(particle, true);
936             XmlSchemaChoice choice = ctp as XmlSchemaChoice;
937             if (choice != null && choice.Items.Count == 0) {
938                 if (choice.MinOccurs != decimal.Zero) {
939                     SendValidationEvent(Res.Sch_EmptyChoice, choice, XmlSeverityType.Warning);
940                 }
941                 return XmlSchemaParticle.Empty;
942             }
943             return ctp;
944         }
945
946         private XmlSchemaParticle CannonicalizeParticle(XmlSchemaParticle particle, bool root) {
947             if (particle == null || particle.IsEmpty) {
948                 return XmlSchemaParticle.Empty;
949             }
950             else if (particle is XmlSchemaElement) {
951                 //return CannonicalizeElement((XmlSchemaElement)particle, substitution);
952                 return particle;
953             }
954             else if (particle is XmlSchemaGroupRef) {
955                 return CannonicalizeGroupRef((XmlSchemaGroupRef)particle, root);
956             }
957             else if (particle is XmlSchemaAll) {
958                 return CannonicalizeAll((XmlSchemaAll)particle, root);
959             }
960             else if (particle is XmlSchemaChoice) {
961                 return CannonicalizeChoice((XmlSchemaChoice)particle, root);
962             }
963             else if (particle is XmlSchemaSequence) {
964                 return CannonicalizeSequence((XmlSchemaSequence)particle, root);
965             }
966             else {
967                 return particle;
968             }
969         }
970
971         private XmlSchemaParticle CannonicalizeElement(XmlSchemaElement element) {
972             if (!element.RefName.IsEmpty && (element.ElementDecl.Block & XmlSchemaDerivationMethod.Substitution) == 0) {
973                 XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)examplars[element.QualifiedName];
974                 if (substitutionGroup == null) {
975                     return element;
976                 }
977                 else {
978                     XmlSchemaChoice choice = new XmlSchemaChoice(); 
979                     for (int i = 0; i < substitutionGroup.Members.Count; ++i) {
980                         choice.Items.Add((XmlSchemaElement)substitutionGroup.Members[i]);
981                     }
982                     choice.MinOccurs = element.MinOccurs;
983                     choice.MaxOccurs = element.MaxOccurs;
984                     CopyPosition(choice, element, false);
985                     return choice;
986                 }
987             }
988             else {
989                 return element;
990             }
991         }
992         
993         private XmlSchemaParticle CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root) {
994             XmlSchemaGroup group;
995             if (groupRef.Redefined != null) {
996                 group = groupRef.Redefined;
997             }
998             else {
999                 group = (XmlSchemaGroup)groups[groupRef.RefName];
1000             }
1001             if (group == null) {
1002                 SendValidationEvent(Res.Sch_UndefGroupRef, groupRef.RefName.ToString(), groupRef);
1003                 return XmlSchemaParticle.Empty;
1004             }
1005             if (group.CanonicalParticle == null) {
1006                 CompileGroup(group);
1007             }
1008             if (group.CanonicalParticle == XmlSchemaParticle.Empty) {
1009                 return XmlSchemaParticle.Empty;
1010             }
1011             XmlSchemaGroupBase groupBase = (XmlSchemaGroupBase)group.CanonicalParticle;
1012             if (groupBase is XmlSchemaAll) {
1013                 if (!root) {
1014                     SendValidationEvent(Res.Sch_AllRefNotRoot, "", groupRef);
1015                     return XmlSchemaParticle.Empty;
1016                 }
1017                 if (groupRef.MinOccurs > decimal.One || groupRef.MaxOccurs != decimal.One) {
1018                     SendValidationEvent(Res.Sch_AllRefMinMax, groupRef);
1019                     return XmlSchemaParticle.Empty;
1020                 }
1021             }
1022             else if (groupBase is XmlSchemaChoice && groupBase.Items.Count == 0) {
1023                 if (groupRef.MinOccurs != decimal.Zero) {
1024                     SendValidationEvent(Res.Sch_EmptyChoice, groupRef, XmlSeverityType.Warning);
1025                 }
1026                 return XmlSchemaParticle.Empty;
1027             }
1028             XmlSchemaGroupBase groupRefBase = (
1029                 (groupBase is XmlSchemaSequence) ? (XmlSchemaGroupBase)new XmlSchemaSequence() :
1030                 (groupBase is XmlSchemaChoice)   ? (XmlSchemaGroupBase)new XmlSchemaChoice() :
1031                                                    (XmlSchemaGroupBase)new XmlSchemaAll()
1032             );
1033             groupRefBase.MinOccurs = groupRef.MinOccurs;
1034             groupRefBase.MaxOccurs = groupRef.MaxOccurs;
1035             CopyPosition(groupRefBase, groupRef, true);
1036
1037             for (int i = 0; i < groupBase.Items.Count; ++i) {
1038                 groupRefBase.Items.Add(groupBase.Items[i]);
1039             }
1040             groupRef.SetParticle(groupRefBase);
1041             return groupRefBase;
1042         }
1043
1044         private XmlSchemaParticle CannonicalizeAll(XmlSchemaAll all, bool root) {
1045             if (all.Items.Count > 0) {
1046                 XmlSchemaAll newAll = new XmlSchemaAll();
1047                 newAll.MinOccurs = all.MinOccurs;
1048                 newAll.MaxOccurs = all.MaxOccurs;
1049                 CopyPosition(newAll, all, true);
1050                 for (int i = 0; i < all.Items.Count; ++i) {
1051                     XmlSchemaParticle p = CannonicalizeParticle((XmlSchemaElement)all.Items[i], false);
1052                     if (p != XmlSchemaParticle.Empty) {
1053                         newAll.Items.Add(p);
1054                     }
1055                 }
1056                 all = newAll;
1057             }
1058             if (all.Items.Count == 0) {
1059                 return XmlSchemaParticle.Empty;
1060             }
1061             else if (!root) {
1062                 SendValidationEvent(Res.Sch_NotAllAlone, all);
1063                 return XmlSchemaParticle.Empty;
1064             }
1065             else {
1066                 return all;
1067             }
1068         }
1069         
1070         private XmlSchemaParticle CannonicalizeChoice(XmlSchemaChoice choice, bool root) {
1071             XmlSchemaChoice oldChoice = choice;
1072             if (choice.Items.Count > 0) {
1073                 XmlSchemaChoice newChoice = new XmlSchemaChoice();
1074                 newChoice.MinOccurs = choice.MinOccurs;
1075                 newChoice.MaxOccurs = choice.MaxOccurs;
1076                 CopyPosition(newChoice, choice, true);
1077                 for (int i = 0; i < choice.Items.Count; ++i) {
1078                     XmlSchemaParticle p1 = CannonicalizeParticle((XmlSchemaParticle)choice.Items[i], false);
1079                     if (p1 != XmlSchemaParticle.Empty) {
1080                         if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaChoice) {
1081                             XmlSchemaChoice p1Choice = p1 as XmlSchemaChoice;
1082                             for (int j = 0; j < p1Choice.Items.Count; ++j) {
1083                                 newChoice.Items.Add(p1Choice.Items[j]);
1084                             }
1085                         }
1086                         else {
1087                             newChoice.Items.Add(p1);
1088                         }
1089                     }
1090                 }
1091                 choice = newChoice;
1092             }
1093             if (!root && choice.Items.Count == 0) {
1094                 if (choice.MinOccurs != decimal.Zero) {
1095                     SendValidationEvent(Res.Sch_EmptyChoice, oldChoice, XmlSeverityType.Warning);
1096                 }
1097                 return XmlSchemaParticle.Empty;
1098             }
1099             else if (!root && choice.Items.Count == 1 && choice.MinOccurs == decimal.One && choice.MaxOccurs == decimal.One) {
1100                 return (XmlSchemaParticle)choice.Items[0];
1101             }
1102             else {
1103                 return choice;
1104             }
1105         }
1106
1107         private XmlSchemaParticle CannonicalizeSequence(XmlSchemaSequence sequence, bool root) {
1108             if (sequence.Items.Count > 0) {
1109                 XmlSchemaSequence newSequence = new XmlSchemaSequence();
1110                 newSequence.MinOccurs = sequence.MinOccurs;
1111                 newSequence.MaxOccurs = sequence.MaxOccurs;
1112                 CopyPosition(newSequence, sequence, true);
1113                 for (int i = 0; i < sequence.Items.Count; ++i) {
1114                     XmlSchemaParticle p1 = CannonicalizeParticle((XmlSchemaParticle)sequence.Items[i], false);
1115                     if (p1 != XmlSchemaParticle.Empty) {
1116                         XmlSchemaSequence p1Sequence = p1 as XmlSchemaSequence;
1117                         if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1Sequence != null) {
1118                             for (int j = 0; j < p1Sequence.Items.Count; ++j) {
1119                                 newSequence.Items.Add(p1Sequence.Items[j]);
1120                             }
1121                         }
1122                         else {
1123                             newSequence.Items.Add(p1);
1124                         }
1125                     }
1126                 }
1127                 sequence = newSequence;
1128             }
1129             if (sequence.Items.Count == 0) {
1130                 return XmlSchemaParticle.Empty;
1131             }
1132             else if (!root && sequence.Items.Count == 1 && sequence.MinOccurs == decimal.One && sequence.MaxOccurs == decimal.One) {
1133                     return (XmlSchemaParticle)sequence.Items[0];
1134             }
1135             else {
1136                 return sequence;
1137             }
1138         }
1139         
1140         private XmlSchemaParticle CannonicalizePointlessRoot(XmlSchemaParticle particle) {
1141             if (particle == null) {
1142                 return null;
1143             }
1144             XmlSchemaSequence xss;
1145             XmlSchemaChoice xsc;
1146             XmlSchemaAll xsa;
1147             decimal one = decimal.One;
1148
1149             if ( (xss = (particle as XmlSchemaSequence)) != null ) {
1150                 XmlSchemaObjectCollection items = xss.Items;
1151                 int count = items.Count;
1152                 if (count == 1) {
1153                     if (xss.MinOccurs == one && xss.MaxOccurs == one) {
1154                         return (XmlSchemaParticle)items[0];
1155                     }
1156                 }
1157             }
1158             else if ( (xsc = (particle as XmlSchemaChoice)) != null ) {
1159                 XmlSchemaObjectCollection items = xsc.Items;
1160                 int count = items.Count;
1161
1162                 if (count == 1) {
1163                     if (xsc.MinOccurs == one && xsc.MaxOccurs == one) {
1164                         return (XmlSchemaParticle)items[0];
1165                     }
1166                 }
1167                 else if (count == 0) {
1168                     return XmlSchemaParticle.Empty;
1169                 }
1170             }
1171             else if ( (xsa = (particle as XmlSchemaAll)) != null ) {
1172                 XmlSchemaObjectCollection items = xsa.Items;
1173                 int count = items.Count;
1174
1175                 if (count == 1) {
1176                     if (xsa.MinOccurs == one && xsa.MaxOccurs == one) {
1177                         return (XmlSchemaParticle)items[0];
1178                     }
1179                 }
1180             }
1181
1182             return particle;
1183         }
1184
1185         private bool IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1186             if (derivedParticle == baseParticle) {
1187                 return true;
1188             }
1189             else if (derivedParticle == null || derivedParticle == XmlSchemaParticle.Empty) {
1190                 return IsParticleEmptiable(baseParticle);
1191             }
1192             else if (baseParticle == null || baseParticle == XmlSchemaParticle.Empty) {
1193                 return false;
1194             }
1195             if (derivedParticle is XmlSchemaElement) { //check for derived element being head of substitutionGroup
1196                 XmlSchemaElement derivedElem = (XmlSchemaElement)derivedParticle;
1197                 derivedParticle = CannonicalizeElement(derivedElem);
1198             }
1199             if (baseParticle is XmlSchemaElement) {
1200                 XmlSchemaElement baseElem = (XmlSchemaElement)baseParticle;
1201                 XmlSchemaParticle newBaseParticle;
1202                 newBaseParticle = CannonicalizeElement(baseElem);
1203                 if (newBaseParticle is XmlSchemaChoice) { //Base Element is subs grp head.
1204                     return IsValidRestriction(derivedParticle, newBaseParticle);
1205                 }
1206                 else if (derivedParticle is XmlSchemaElement) {
1207                     return IsElementFromElement((XmlSchemaElement)derivedParticle, baseElem);
1208                 }
1209                 else {
1210                     restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForElem);
1211                     return false;
1212                 }
1213             }
1214             else if (baseParticle is XmlSchemaAny) {
1215                 if (derivedParticle is XmlSchemaElement) {
1216                     return IsElementFromAny((XmlSchemaElement)derivedParticle, (XmlSchemaAny)baseParticle);
1217                 }
1218                 else if (derivedParticle is XmlSchemaAny) {
1219                     return IsAnyFromAny((XmlSchemaAny)derivedParticle, (XmlSchemaAny)baseParticle);
1220                 }
1221                 else {
1222                     return IsGroupBaseFromAny((XmlSchemaGroupBase)derivedParticle, (XmlSchemaAny)baseParticle);
1223                 }
1224             }
1225             else if (baseParticle is XmlSchemaAll) {
1226                 if (derivedParticle is XmlSchemaElement) {
1227                     return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle);
1228                 }
1229                 else if (derivedParticle is XmlSchemaAll) {
1230                     if(IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) {
1231                         return true;    
1232                     }
1233                 }
1234                 else if (derivedParticle is XmlSchemaSequence) {
1235                     if(IsSequenceFromAll((XmlSchemaSequence)derivedParticle, (XmlSchemaAll)baseParticle)) {
1236                         return true;
1237                     }
1238                     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));
1239                 }
1240                 else if (derivedParticle is XmlSchemaChoice || derivedParticle is XmlSchemaAny) {
1241                     restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForAll);
1242                 }
1243                 return false;
1244             }
1245             else if (baseParticle is XmlSchemaChoice ) {
1246                 if (derivedParticle is XmlSchemaElement) {
1247                     return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase) baseParticle);
1248                 }
1249                 else if (derivedParticle is XmlSchemaChoice) {
1250                     XmlSchemaChoice baseChoice = baseParticle as XmlSchemaChoice;
1251                     XmlSchemaChoice derivedChoice = derivedParticle as XmlSchemaChoice;
1252
1253                     if (baseChoice.Parent == null || derivedChoice.Parent == null) { //using parent property to indicate this choice was created on the fly for substitutionGroup
1254                         return IsChoiceFromChoiceSubstGroup(derivedChoice, baseChoice);
1255                     }
1256                     if(IsGroupBaseFromGroupBase(derivedChoice, baseChoice, false)) {
1257                         return true;
1258                     }
1259                 }
1260                 else if (derivedParticle is XmlSchemaSequence) {
1261                     if(IsSequenceFromChoice((XmlSchemaSequence)derivedParticle, (XmlSchemaChoice) baseParticle)) {
1262                         return true;
1263                     }
1264                     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));
1265                 }
1266                 else {
1267                     restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForChoice); 
1268                 }
1269                 return false;
1270             }
1271             else if (baseParticle is XmlSchemaSequence) {
1272                 if (derivedParticle is XmlSchemaElement) {
1273                     return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle);
1274                 }
1275                 else if (derivedParticle is XmlSchemaSequence || (derivedParticle is XmlSchemaAll && ((XmlSchemaGroupBase)derivedParticle).Items.Count ==1)) {
1276                     if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true)) {
1277                         return true;    
1278                     }
1279                 }
1280                 else {
1281                     restrictionErrorMsg = Res.GetString(Res.Sch_ForbiddenDerivedParticleForSeq); 
1282                 }
1283                 return false;
1284             }
1285             else {
1286                 Debug.Assert(false);
1287             }
1288
1289             return false;
1290         }
1291
1292         private bool IsElementFromElement(XmlSchemaElement derivedElement, XmlSchemaElement baseElement) {
1293             // In case of elements the block value '#all' is 100% equivalent to the value of 'substitution restriction extension'.
1294             // Since below we perform a logical operation on the bit fields we need to convert the #all (0xFF)
1295             //   to the equivalent set of substitution, restriction and extension, so that the operation works as expected.
1296             // (The goal of the (derived | base) == derived is to fail if the derived is not a bitwise superset of base)
1297             XmlSchemaDerivationMethod baseEffectiveBlock =
1298                 baseElement.ElementDecl.Block == XmlSchemaDerivationMethod.All ?
1299                     XmlSchemaDerivationMethod.Substitution | XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension :
1300                     baseElement.ElementDecl.Block;
1301             XmlSchemaDerivationMethod derivedEffectiveBlock =
1302                 derivedElement.ElementDecl.Block == XmlSchemaDerivationMethod.All ?
1303                     XmlSchemaDerivationMethod.Substitution | XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension :
1304                     derivedElement.ElementDecl.Block;
1305
1306             if(! ((derivedElement.QualifiedName == baseElement.QualifiedName) &&
1307                  (baseElement.IsNillable || !derivedElement.IsNillable) &&
1308                  IsValidOccurrenceRangeRestriction(derivedElement, baseElement) &&
1309                  (baseElement.FixedValue == null || IsFixedEqual(baseElement.ElementDecl, derivedElement.ElementDecl) ) &&
1310                  ((derivedEffectiveBlock | baseEffectiveBlock) == derivedEffectiveBlock) &&
1311                  (derivedElement.ElementSchemaType != null) && (baseElement.ElementSchemaType != null) &&
1312                  XmlSchemaType.IsDerivedFrom(derivedElement.ElementSchemaType, baseElement.ElementSchemaType, ~(XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.List | XmlSchemaDerivationMethod.Union))) ) {
1313                 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromElement, derivedElement.QualifiedName, baseElement.QualifiedName);    
1314                 return false;
1315             }
1316             return true;
1317         }
1318
1319         private bool IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny) {
1320             if (!baseAny.Allows(derivedElement.QualifiedName)) {
1321                 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule1, derivedElement.QualifiedName.ToString());
1322                 return false;
1323             }
1324             if (!IsValidOccurrenceRangeRestriction(derivedElement, baseAny)) {
1325                 restrictionErrorMsg = Res.GetString(Res.Sch_ElementFromAnyRule2, derivedElement.QualifiedName.ToString());
1326                 return false;
1327             }
1328             return true;
1329         }
1330
1331         private bool IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny) {
1332             if (!IsValidOccurrenceRangeRestriction(derivedAny, baseAny)) {
1333                 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule1);
1334                 return false;
1335             }
1336             if (!NamespaceList.IsSubset(derivedAny.NamespaceList, baseAny.NamespaceList)) {
1337                 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule2);
1338                 return false;
1339             }
1340             if ((int)derivedAny.ProcessContentsCorrect < (int)baseAny.ProcessContentsCorrect) {
1341                 restrictionErrorMsg = Res.GetString(Res.Sch_AnyFromAnyRule3);
1342                 return false;
1343             }
1344             return true;
1345         }
1346
1347         private bool IsGroupBaseFromAny(XmlSchemaGroupBase derivedGroupBase, XmlSchemaAny baseAny) {
1348             decimal minOccurs, maxOccurs;
1349             CalculateEffectiveTotalRange(derivedGroupBase, out minOccurs, out maxOccurs);
1350             if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseAny.MinOccurs, baseAny.MaxOccurs)) {
1351                 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));
1352                 return false;
1353             }
1354             // eliminate occurrance range check
1355             string minOccursAny = baseAny.MinOccursString;
1356             baseAny.MinOccurs = decimal.Zero;
1357             for (int i = 0; i < derivedGroupBase.Items.Count; ++i) {
1358                 if (!IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[i], baseAny)) {
1359                     restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseFromAny1);
1360                     baseAny.MinOccursString = minOccursAny;
1361                     return false;
1362                 }
1363             }
1364             baseAny.MinOccursString = minOccursAny;
1365             return true;
1366         }
1367   
1368 #if Microsoft      
1369         private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) {
1370             if (!IsRangeSimple(baseGroupBase.MinOccurs, baseGroupBase.MaxOccurs) || !IsRangeSimple(derivedElement.MinOccurs, derivedElement.MaxOccurs)) {
1371                 return IsElementFromGroupBase(derivedElement, baseGroupBase); //SPEC COMPLIANT
1372             }
1373             else {
1374                 //Base partilce's and Derived Element's range is simple
1375                 //If all particles in baseParticle also have simple ranges, then can use our algorithm
1376                 //So that we dont break common cases that we used to accept earlier 
1377                 //Example Choice -> Element
1378                 if (IsElementFromGroupBaseHack(derivedElement, baseGroupBase, skipEmptableOnly)) {
1379                     return true;
1380                 }
1381                 else { //Fall back to regular checking
1382                     return IsElementFromGroupBase(derivedElement, baseGroupBase);
1383                 }
1384             }
1385         }
1386
1387         private bool IsElementFromGroupBaseHack(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) {
1388             bool isMatched = false;
1389
1390             foreach(XmlSchemaParticle baseParticle in baseGroupBase.Items) {
1391                 if (!isMatched && IsRangeSimple(baseParticle.MinOccurs, baseParticle.MaxOccurs)) {
1392                     string minOccursElement = baseParticle.MinOccursString;
1393                     string maxOccursElement = baseParticle.MaxOccursString;
1394                     baseParticle.MinOccurs *= baseGroupBase.MinOccurs;
1395                     if ( baseParticle.MaxOccurs != decimal.MaxValue) {
1396                         if (baseGroupBase.MaxOccurs == decimal.MaxValue)
1397                              baseParticle.MaxOccurs = decimal.MaxValue;
1398                         else 
1399                              baseParticle.MaxOccurs *= baseGroupBase.MaxOccurs;
1400                     }
1401                     isMatched  = IsValidRestriction(derivedElement, baseParticle);
1402                     baseParticle.MinOccursString = minOccursElement;
1403                     baseParticle.MaxOccursString = maxOccursElement;
1404                 }
1405                 if (!isMatched && skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
1406                     return false;
1407                 }
1408             }
1409             return isMatched;
1410         }
1411 #endif        
1412         private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase) {
1413             if (baseGroupBase is XmlSchemaSequence) {
1414                 XmlSchemaSequence virtualSeq = new XmlSchemaSequence();
1415                 virtualSeq.MinOccurs = 1;
1416                 virtualSeq.MaxOccurs = 1;
1417                 virtualSeq.Items.Add(derivedElement);
1418                 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualSeq, baseGroupBase, true)) {
1419                     return true;
1420                 }
1421                 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));
1422             }
1423             else if (baseGroupBase is XmlSchemaChoice) {
1424                 XmlSchemaChoice virtualChoice = new XmlSchemaChoice();
1425                 virtualChoice.MinOccurs = 1;
1426                 virtualChoice.MaxOccurs = 1;
1427                 virtualChoice.Items.Add(derivedElement);
1428                 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualChoice, baseGroupBase, false)) {
1429                     return true;
1430                 }
1431                 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));
1432             }
1433             else if (baseGroupBase is XmlSchemaAll) {
1434                 XmlSchemaAll virtualAll = new XmlSchemaAll();
1435                 virtualAll.MinOccurs = 1;
1436                 virtualAll.MaxOccurs = 1;
1437                 virtualAll.Items.Add(derivedElement);
1438                 if (IsGroupBaseFromGroupBase((XmlSchemaGroupBase)virtualAll, baseGroupBase, true)) {
1439                     return true;
1440                 }
1441                 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));
1442             }
1443             return false;
1444         }
1445         
1446         private bool IsChoiceFromChoiceSubstGroup(XmlSchemaChoice derivedChoice, XmlSchemaChoice baseChoice) {
1447             if (!IsValidOccurrenceRangeRestriction(derivedChoice, baseChoice)) {
1448                 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid);
1449                 return false;
1450             }
1451             for (int i = 0; i < derivedChoice.Items.Count; ++i) {
1452                 if (GetMappingParticle((XmlSchemaParticle)derivedChoice.Items[i], baseChoice.Items) < 0) {
1453                     return false;
1454                 }
1455             }
1456             return true;
1457         }
1458
1459         private bool IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) {
1460             if (!IsValidOccurrenceRangeRestriction(derivedGroupBase, baseGroupBase)) {
1461                 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestRangeInvalid);
1462                 return false;
1463             }
1464             if (derivedGroupBase.Items.Count > baseGroupBase.Items.Count) {
1465                 restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNoMap);
1466                 return false;
1467             }
1468             int count = 0;
1469             for (int i = 0; i < baseGroupBase.Items.Count; ++i) {
1470                 XmlSchemaParticle baseParticle = (XmlSchemaParticle)baseGroupBase.Items[i];
1471                 if ((count < derivedGroupBase.Items.Count)
1472                         && IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[count], baseParticle)) {
1473                     count ++;
1474                 }
1475                 else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
1476                     if (restrictionErrorMsg == null) { //If restriction failed on previous check, do not overwrite error 
1477                         restrictionErrorMsg = Res.GetString(Res.Sch_GroupBaseRestNotEmptiable);
1478                     }
1479                     return false;
1480                 }
1481             }
1482             if (count < derivedGroupBase.Items.Count) {
1483                 return false;
1484             }
1485             return true;
1486         }
1487
1488         private bool IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll) {
1489             if (!IsValidOccurrenceRangeRestriction(derivedSequence, baseAll) || derivedSequence.Items.Count > baseAll.Items.Count) {
1490                 return false;
1491             }
1492             BitSet map = new BitSet(baseAll.Items.Count);
1493             for (int j = 0; j < derivedSequence.Items.Count; ++j) {
1494                 int i = GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[j], baseAll.Items);
1495                 if (i >= 0) {
1496                     if (map[i]) {
1497                         return false;
1498                     }
1499                     else {
1500                         map.Set(i);
1501                     }
1502                 }
1503                 else {
1504                     return false;
1505                 }
1506             }
1507             for (int i = 0; i < baseAll.Items.Count; i++) {
1508                 if (!map[i] && !IsParticleEmptiable((XmlSchemaParticle)baseAll.Items[i])) {
1509                     return false;
1510                 }
1511             }
1512             return true;
1513         }
1514
1515         private bool IsSequenceFromChoice(XmlSchemaSequence derivedSequence, XmlSchemaChoice baseChoice) {
1516             decimal minOccurs, maxOccurs;
1517             minOccurs = derivedSequence.MinOccurs * derivedSequence.Items.Count;
1518             if (derivedSequence.MaxOccurs == decimal.MaxValue) {
1519                 maxOccurs = decimal.MaxValue;
1520             }
1521             else {
1522                 maxOccurs = derivedSequence.MaxOccurs * derivedSequence.Items.Count;
1523             }
1524             if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseChoice.MinOccurs, baseChoice.MaxOccurs) || derivedSequence.Items.Count > baseChoice.Items.Count) {
1525                 return false;
1526             }
1527             for (int i = 0; i < derivedSequence.Items.Count; ++i) {
1528                 if (GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[i], baseChoice.Items) < 0)
1529                     return false;
1530             }
1531             return true;
1532         }
1533
1534         private bool IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1535             return IsValidOccurrenceRangeRestriction(derivedParticle.MinOccurs, derivedParticle.MaxOccurs, baseParticle.MinOccurs, baseParticle.MaxOccurs);
1536         }
1537
1538         private bool IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs) {
1539             return (baseMinOccurs <= minOccurs) && (maxOccurs <= baseMaxOccurs);
1540         }
1541
1542         private int GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection) {
1543             for (int i = 0; i < collection.Count; i++) {
1544                 if (IsValidRestriction(particle, (XmlSchemaParticle)collection[i]))
1545                     return i;
1546             }
1547             return -1;
1548         }
1549
1550         private bool IsParticleEmptiable(XmlSchemaParticle particle) {
1551             decimal minOccurs, maxOccurs;
1552             CalculateEffectiveTotalRange(particle, out minOccurs, out maxOccurs);
1553             return minOccurs == decimal.Zero;
1554         }
1555
1556         private void CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs) {
1557             XmlSchemaChoice choice = particle as XmlSchemaChoice;
1558
1559             if (particle is XmlSchemaElement || particle is XmlSchemaAny) {
1560                 minOccurs = particle.MinOccurs;
1561                 maxOccurs = particle.MaxOccurs;
1562             }
1563             else if (choice != null) {
1564                 if (choice.Items.Count == 0) {
1565                     minOccurs = maxOccurs = decimal.Zero;
1566                 }
1567                 else {
1568                     minOccurs = decimal.MaxValue; 
1569                     maxOccurs = decimal.Zero;
1570                     for (int i = 0; i < choice.Items.Count; ++i) {
1571                         decimal min, max;
1572                         CalculateEffectiveTotalRange((XmlSchemaParticle)choice.Items[i], out min, out max);
1573                         if (min < minOccurs) {
1574                             minOccurs = min;
1575                         }
1576                         if (max > maxOccurs) {
1577                             maxOccurs = max;
1578                         }
1579                     }
1580                     minOccurs *= particle.MinOccurs;
1581                     if (maxOccurs != decimal.MaxValue) {
1582                         if (particle.MaxOccurs == decimal.MaxValue)
1583                             maxOccurs = decimal.MaxValue;
1584                         else 
1585                             maxOccurs *= particle.MaxOccurs;
1586                     }
1587                 }
1588             }
1589             else {
1590                 XmlSchemaObjectCollection collection = ((XmlSchemaGroupBase)particle).Items;
1591                 if (collection.Count == 0) {
1592                     minOccurs = maxOccurs = decimal.Zero;
1593                 }
1594                 else {
1595                     minOccurs = 0;
1596                     maxOccurs = 0;
1597                     for (int i = 0; i < collection.Count; ++i) {
1598                         decimal min, max;
1599                         CalculateEffectiveTotalRange((XmlSchemaParticle)collection[i], out min, out max);
1600                         minOccurs += min;
1601                         if (maxOccurs != decimal.MaxValue) {
1602                             if (max == decimal.MaxValue)
1603                                 maxOccurs = decimal.MaxValue;
1604                             else 
1605                                 maxOccurs += max;
1606                         }
1607                     }
1608                     minOccurs *= particle.MinOccurs;
1609                     if (maxOccurs != decimal.MaxValue) {
1610                         if (particle.MaxOccurs == decimal.MaxValue)
1611                             maxOccurs = decimal.MaxValue;
1612                         else 
1613                             maxOccurs *= particle.MaxOccurs;
1614                     }
1615                 }
1616             }
1617         }
1618
1619         private void PushComplexType(XmlSchemaComplexType complexType) {
1620             this.complexTypeStack.Push(complexType);
1621         }
1622
1623         private XmlSchemaContentType GetSchemaContentType(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaParticle particle) {
1624             if ((complexContent != null && complexContent.IsMixed) ||
1625                 (complexContent == null && complexType.IsMixed)) {
1626                 return XmlSchemaContentType.Mixed;      
1627             }
1628             else if (particle != null && !particle.IsEmpty) {
1629                 return XmlSchemaContentType.ElementOnly;
1630             }
1631             else {
1632                 return XmlSchemaContentType.Empty;                            
1633             }
1634         }
1635
1636         private void CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup) {
1637             if (attributeGroup.IsProcessing) {
1638                 SendValidationEvent(Res.Sch_AttributeGroupCircularRef, attributeGroup);
1639                 return;
1640             }
1641             if (attributeGroup.AttributeUses.Count > 0) {// already checked
1642                 return;
1643             }
1644             attributeGroup.IsProcessing = true;
1645             XmlSchemaAnyAttribute anyAttribute = attributeGroup.AnyAttribute;
1646
1647             try {
1648                 for (int i = 0; i < attributeGroup.Attributes.Count; ++i) {
1649                     XmlSchemaAttribute attr = attributeGroup.Attributes[i] as XmlSchemaAttribute;
1650                     if (attr != null) {
1651                         if (attr.Use == XmlSchemaUse.Prohibited) {
1652                             continue;
1653                         }
1654                         CompileAttribute(attr);
1655                         if (attributeGroup.AttributeUses[attr.QualifiedName] == null) {
1656                             attributeGroup.AttributeUses.Add(attr.QualifiedName, attr);
1657                         }
1658                         else  {
1659                             SendValidationEvent(Res.Sch_DupAttributeUse, attr.QualifiedName.ToString(), attr);
1660                         }
1661                     }
1662                     else { // XmlSchemaAttributeGroupRef
1663                         XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)attributeGroup.Attributes[i];
1664                         XmlSchemaAttributeGroup attributeGroupResolved;
1665                         if (attributeGroup.Redefined != null && attributeGroupRef.RefName == attributeGroup.Redefined.QualifiedName) {
1666                             attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroup.Redefined;
1667                         }
1668                         else {
1669                             attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName];
1670                         }
1671                         if (attributeGroupResolved != null) {
1672                             CompileAttributeGroup(attributeGroupResolved);
1673                             foreach (XmlSchemaAttribute attribute in attributeGroupResolved.AttributeUses.Values) {
1674                                 if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) {
1675                                     attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute);
1676                                 }
1677                                 else {
1678                                     SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
1679                                 }
1680                             }
1681                             anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroupResolved.AttributeWildcard);
1682                         }
1683                         else {
1684                             SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
1685                         }
1686                     }
1687                 }          
1688                 attributeGroup.AttributeWildcard = anyAttribute;
1689             }
1690             finally {
1691                 attributeGroup.IsProcessing = false;
1692             }
1693         }
1694
1695         private void CompileLocalAttributes(XmlSchemaComplexType baseType, XmlSchemaComplexType derivedType, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaDerivationMethod derivedBy) {
1696             XmlSchemaAnyAttribute baseAttributeWildcard = baseType != null ? baseType.AttributeWildcard : null;  
1697             for (int i = 0; i < attributes.Count; ++i) {
1698                 XmlSchemaAttribute attr = attributes[i] as XmlSchemaAttribute;
1699                 if (attr != null) {
1700                     if (attr.Use != XmlSchemaUse.Prohibited) {
1701                         CompileAttribute(attr);
1702                     }
1703                     if (attr.Use != XmlSchemaUse.Prohibited || 
1704                         (attr.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
1705
1706                         if (derivedType.AttributeUses[attr.QualifiedName] == null) {
1707                             derivedType.AttributeUses.Add(attr.QualifiedName, attr);
1708                         }
1709                         else  {
1710                             SendValidationEvent(Res.Sch_DupAttributeUse, attr.QualifiedName.ToString(), attr);
1711                         }
1712                     }
1713                     else {
1714                         SendValidationEvent(Res.Sch_AttributeIgnored, attr.QualifiedName.ToString(), attr, XmlSeverityType.Warning);
1715                     }
1716
1717                 }
1718                 else { // is XmlSchemaAttributeGroupRef
1719                     XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef) attributes[i];
1720                     XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName];
1721                     if (attributeGroup != null) {
1722                         CompileAttributeGroup(attributeGroup);
1723                         foreach (XmlSchemaAttribute attribute in attributeGroup.AttributeUses.Values) {
1724                           if (attribute.Use != XmlSchemaUse.Prohibited || 
1725                              (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
1726                             if (derivedType.AttributeUses[attribute.QualifiedName] == null) {
1727                                 derivedType.AttributeUses.Add(attribute.QualifiedName, attribute);
1728                             }
1729                             else {
1730                                 SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attributeGroupRef);
1731                             }
1732                           }
1733                           else {
1734                             SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning);
1735                           }
1736
1737                         }
1738                         anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroup.AttributeWildcard);
1739                     }
1740                     else {
1741                         SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
1742                     }
1743                 }
1744             }
1745
1746             // check derivation rules
1747             if (baseType != null) {
1748                 if (derivedBy == XmlSchemaDerivationMethod.Extension) {
1749                     derivedType.SetAttributeWildcard(CompileAnyAttributeUnion(anyAttribute, baseAttributeWildcard));
1750                     foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
1751                         XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
1752                         if (attribute == null) {
1753                             derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
1754                         }
1755                         else {
1756                             Debug.Assert(attribute.Use != XmlSchemaUse.Prohibited);
1757                             if (attributeBase.Use != XmlSchemaUse.Prohibited && attribute.AttributeSchemaType != attributeBase.AttributeSchemaType) { //Extension allows previously prohibited attributes to be re-added, 
1758                                 SendValidationEvent(Res.Sch_InvalidAttributeExtension, attribute);
1759                             }
1760                         }
1761                     }
1762                 }
1763                 else {  // derivedBy == XmlSchemaDerivationMethod.Restriction
1764                     // Schema Component Constraint: Derivation Valid (Restriction, Complex)
1765                     if ((anyAttribute != null) && (baseAttributeWildcard == null || !XmlSchemaAnyAttribute.IsSubset(anyAttribute, baseAttributeWildcard) || !IsProcessContentsRestricted(baseType, anyAttribute, baseAttributeWildcard)) ) {
1766                         SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedType);
1767                     }
1768                     else {
1769                         derivedType.SetAttributeWildcard(anyAttribute); //complete wildcard
1770                     }
1771
1772                     // Add form the base
1773                     foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
1774                         XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
1775                         if (attribute == null) {
1776                             derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
1777                         } 
1778                         else {
1779                             if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
1780 #if DEBUG
1781                                 string position = string.Empty;
1782                                 if (derivedType.SourceUri != null) {
1783                                     position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
1784                                 }
1785                                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
1786                                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
1787                                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard));
1788 #endif
1789                                 SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute);
1790                             } 
1791                             else if (attributeBase.Use == XmlSchemaUse.Required && (attribute.Use != XmlSchemaUse.Required)) { //If base is required, derived should also be required
1792                                 SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute);
1793                             }
1794                             else if (attribute.Use == XmlSchemaUse.Prohibited) {
1795                                 continue;
1796                             }
1797                             else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
1798                                 SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute);
1799                             }
1800                             else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
1801                                 SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
1802                             }
1803                         }
1804                     }
1805
1806                     // Check additional ones are valid restriction of base's wildcard
1807                     foreach(XmlSchemaAttribute attribute in derivedType.AttributeUses.Values) {
1808                         XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseType.AttributeUses[attribute.QualifiedName];
1809                         if (attributeBase != null) {
1810                             continue;
1811                         }
1812                         if (baseAttributeWildcard == null || !baseAttributeWildcard.Allows(attribute.QualifiedName)) {
1813 #if DEBUG
1814                             string position = string.Empty;
1815                             if (derivedType.SourceUri != null) {
1816                                 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
1817                             }
1818                             Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
1819                             Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
1820                             Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard));
1821 #endif
1822                             SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
1823                         }
1824                     }
1825                 }
1826             } 
1827             else {
1828                 derivedType.SetAttributeWildcard(anyAttribute);
1829             }
1830        }
1831
1832         private void CheckAtrributeGroupRestriction(XmlSchemaAttributeGroup baseAttributeGroup, XmlSchemaAttributeGroup derivedAttributeGroup) {
1833             XmlSchemaAnyAttribute baseAnyAtt = baseAttributeGroup.AttributeWildcard;
1834             XmlSchemaAnyAttribute derivedAnyAtt = derivedAttributeGroup.AttributeWildcard;
1835
1836             if ((derivedAnyAtt != null) && (baseAnyAtt == null || !XmlSchemaAnyAttribute.IsSubset(derivedAnyAtt, baseAnyAtt) || !IsProcessContentsRestricted(null, derivedAnyAtt, baseAnyAtt))) {
1837                 SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedAttributeGroup);
1838             }
1839             foreach(XmlSchemaAttribute attributeBase in baseAttributeGroup.AttributeUses.Values) {
1840                 XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedAttributeGroup.AttributeUses[attributeBase.QualifiedName];
1841                 if (attribute != null) {
1842                     if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
1843                         SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute);
1844                     } 
1845                     else if (attributeBase.Use == XmlSchemaUse.Required && attribute.Use != XmlSchemaUse.Required) {
1846                         SendValidationEvent(Res.Sch_AttributeUseInvalid, attribute);
1847                     }
1848                     else if (attribute.Use == XmlSchemaUse.Prohibited) { //If derived att is prohibited, continue
1849                         continue;
1850                     }
1851                     else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
1852                         SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute);
1853                     }
1854                     else if (!IsFixedEqual(attributeBase.AttDef, attribute.AttDef)) {
1855                         SendValidationEvent(Res.Sch_AttributeFixedInvalid, attribute);
1856                     }    
1857                 }
1858                 else if (attributeBase.Use == XmlSchemaUse.Required) {
1859                     SendValidationEvent(Res.Sch_NoDerivedAttribute, attributeBase.QualifiedName.ToString(), baseAttributeGroup.QualifiedName.ToString(), derivedAttributeGroup);
1860                 }
1861             }
1862             // Check additional ones are valid restriction of base's wildcard
1863             foreach(XmlSchemaAttribute attribute in derivedAttributeGroup.AttributeUses.Values) {
1864                 XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseAttributeGroup.AttributeUses[attribute.QualifiedName];
1865                 if (attributeBase != null) {
1866                     continue;
1867                 }
1868                 if (baseAnyAtt == null || !baseAnyAtt.Allows(attribute.QualifiedName)) {
1869                     SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
1870                 }
1871             }
1872         }
1873
1874 #if DEBUG
1875         private string DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard) {
1876             StringBuilder sb = new StringBuilder();
1877             sb.Append("[");
1878             bool first = true;
1879             foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1880                 if (attribute.Use != XmlSchemaUse.Prohibited) {
1881                     if (first) {
1882                         first = false;
1883                     }
1884                     else {
1885                         sb.Append(" ");
1886                     }
1887                     sb.Append(attribute.QualifiedName.Name);       
1888                     if (attribute.Use == XmlSchemaUse.Optional || attribute.Use == XmlSchemaUse.None) {
1889                         sb.Append("?");                                                                  
1890                     }
1891                 }
1892             }
1893             if (attributeWildcard != null) {
1894                 if (attributeUses.Count != 0) {
1895                     sb.Append(" ");                                                                  
1896                 }
1897                 sb.Append("<");
1898                 sb.Append(attributeWildcard.NamespaceList.ToString());
1899                 sb.Append(">");
1900             }
1901             sb.Append("] - [");
1902             first = true;
1903             foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1904                 if (attribute.Use == XmlSchemaUse.Prohibited) {
1905                     if (first) {
1906                         first = false;
1907                     }
1908                     else {
1909                         sb.Append(" ");
1910                     }
1911                     sb.Append(attribute.QualifiedName.Name);       
1912                 }
1913             }
1914             sb.Append("]");
1915             return sb.ToString();
1916         }
1917 #endif
1918
1919         private bool IsProcessContentsRestricted(XmlSchemaComplexType baseType, XmlSchemaAnyAttribute derivedAttributeWildcard, XmlSchemaAnyAttribute baseAttributeWildcard) {
1920             if (baseType == XmlSchemaComplexType.AnyType) {
1921                 return true;
1922             }
1923             if ((int)derivedAttributeWildcard.ProcessContentsCorrect >= (int)baseAttributeWildcard.ProcessContentsCorrect) {
1924                 return true;
1925             }
1926             return false;
1927         }
1928
1929         private XmlSchemaAnyAttribute CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1930             if (a == null) {
1931                 return b;
1932             }
1933             else if (b == null) {
1934                 return a;
1935             }
1936             else {
1937                 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Union(a, b, false); //false is for v1Compatd
1938                 if (attribute == null) {
1939                     SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1940                 }
1941                 return attribute;
1942             }
1943
1944         }
1945
1946         private XmlSchemaAnyAttribute CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1947             if (a == null) {
1948                 return b;
1949             }
1950             else if (b == null) {
1951                 return a;
1952             }
1953             else {
1954                 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Intersection(a, b, false); //false is for v1Compat
1955                 if (attribute == null) {
1956                     SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1957                 }
1958                 return attribute;
1959             }
1960         }
1961
1962          private void CompileAttribute(XmlSchemaAttribute xa) {
1963             if (xa.IsProcessing) {
1964                 SendValidationEvent(Res.Sch_AttributeCircularRef, xa);
1965                 return;
1966             }
1967             if (xa.AttDef != null) { //already compiled?
1968                 return;
1969             }
1970             xa.IsProcessing = true;
1971             SchemaAttDef decl = null;
1972             try {
1973                 if (!xa.RefName.IsEmpty) {
1974                     XmlSchemaAttribute a = (XmlSchemaAttribute)attributes[xa.RefName];
1975                     if (a == null) {
1976                         throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, xa.RefName.ToString(), xa);
1977                     }     
1978                     CompileAttribute(a);
1979                     if (a.AttDef == null) {
1980                         throw new XmlSchemaException(Res.Sch_RefInvalidAttribute, xa.RefName.ToString(), xa);
1981                     }
1982                     decl = a.AttDef.Clone();
1983                     XmlSchemaDatatype datatype = decl.Datatype;
1984
1985                     if (datatype != null) {
1986                         if (a.FixedValue == null && a.DefaultValue == null) {
1987                             SetDefaultFixed(xa, decl);
1988                         }
1989                         else if (a.FixedValue != null) {
1990                             if (xa.DefaultValue != null) {
1991                                 throw new XmlSchemaException(Res.Sch_FixedDefaultInRef, xa.RefName.ToString(), xa);
1992                             }
1993                             else if (xa.FixedValue != null ) {
1994                                 object refFixedValue = datatype.ParseValue(xa.FixedValue, NameTable, new SchemaNamespaceManager(xa), true);
1995                                 if ( !datatype.IsEqual(decl.DefaultValueTyped, refFixedValue)) {
1996                                     throw new XmlSchemaException(Res.Sch_FixedInRef, xa.RefName.ToString(), xa);
1997                                 }
1998                             }
1999                         }
2000                     }
2001                     xa.SetAttributeType(a.AttributeSchemaType);
2002                 }
2003                 else {
2004                     decl = new SchemaAttDef(xa.QualifiedName);
2005                     if (xa.SchemaType != null) {
2006                         CompileSimpleType(xa.SchemaType);
2007                         xa.SetAttributeType(xa.SchemaType);
2008                         decl.SchemaType = xa.SchemaType;
2009                         decl.Datatype = xa.SchemaType.Datatype;
2010                     }
2011                     else if (!xa.SchemaTypeName.IsEmpty) {
2012                         XmlSchemaSimpleType simpleType = GetSimpleType(xa.SchemaTypeName);
2013                         if (simpleType != null) {
2014                             xa.SetAttributeType(simpleType);
2015                             decl.Datatype = simpleType.Datatype;
2016                             decl.SchemaType = simpleType;
2017                         }
2018                         else {
2019                             throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, xa.SchemaTypeName.ToString(), xa);   
2020                         }
2021                     }
2022                     else {
2023                         decl.SchemaType = DatatypeImplementation.AnySimpleType;
2024                         decl.Datatype = DatatypeImplementation.AnySimpleType.Datatype;
2025                         xa.SetAttributeType(DatatypeImplementation.AnySimpleType);
2026                     }
2027                     //} //Removed this here since the following should be done only if RefName is Empty
2028                     if (decl.Datatype != null) {
2029                         decl.Datatype.VerifySchemaValid(notations, xa);
2030                     }
2031                     SetDefaultFixed(xa, decl);
2032                 } //End of Else for !RefName.IsEmpty
2033
2034                 decl.SchemaAttribute = xa; //So this is available for PSVI
2035                 xa.AttDef = decl;
2036             } 
2037             catch (XmlSchemaException e) {
2038                 if (e.SourceSchemaObject == null) {
2039                     e.SetSource(xa);
2040                 }
2041                 SendValidationEvent(e);
2042                 xa.AttDef = SchemaAttDef.Empty;
2043             } 
2044             finally {
2045                 xa.IsProcessing = false;
2046             }
2047         }
2048         
2049         private void SetDefaultFixed(XmlSchemaAttribute xa, SchemaAttDef decl) {
2050             if (xa.DefaultValue != null || xa.FixedValue != null) {
2051                 if (xa.DefaultValue != null) {
2052                     decl.Presence = SchemaDeclBase.Use.Default; 
2053                     decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.DefaultValue;
2054                 }
2055                 else {
2056                     if (xa.Use == XmlSchemaUse.Required) {
2057                         decl.Presence = SchemaDeclBase.Use.RequiredFixed;
2058                     }
2059                     else {
2060                         decl.Presence = SchemaDeclBase.Use.Fixed; 
2061                     }
2062                     decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.FixedValue;
2063                 }
2064                 if(decl.Datatype != null) {
2065                     if (decl.Datatype.TypeCode == XmlTypeCode.Id) {
2066                         SendValidationEvent(Res.Sch_DefaultIdValue, xa);
2067                     }
2068                     else {
2069                         decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
2070                     }
2071                 }
2072             }
2073             else {
2074                 switch (xa.Use) {
2075                     case XmlSchemaUse.None: 
2076                     case XmlSchemaUse.Optional: 
2077                         decl.Presence = SchemaDeclBase.Use.Implied; 
2078                         break;
2079                     case XmlSchemaUse.Required: 
2080                         decl.Presence = SchemaDeclBase.Use.Required; 
2081                         break;
2082                     case XmlSchemaUse.Prohibited:
2083                         break;
2084                 }
2085             }
2086         }
2087
2088         private void CompileIdentityConstraint (XmlSchemaIdentityConstraint xi) { 
2089             if (xi.IsProcessing) {
2090                 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;       
2091                 SendValidationEvent(Res.Sch_IdentityConstraintCircularRef, xi);
2092                 return;
2093             }
2094
2095             if (xi.CompiledConstraint != null) {
2096                 return;
2097             }
2098             
2099             xi.IsProcessing = true;
2100             CompiledIdentityConstraint compic = null;
2101             try {
2102                 SchemaNamespaceManager xnmgr = new SchemaNamespaceManager(xi);
2103                 compic = new CompiledIdentityConstraint(xi, xnmgr);
2104                 if (xi is XmlSchemaKeyref) {
2105                     XmlSchemaIdentityConstraint ic = (XmlSchemaIdentityConstraint)this.identityConstraints[((XmlSchemaKeyref)xi).Refer];
2106                     if (ic == null) {
2107                         throw new XmlSchemaException(Res.Sch_UndeclaredIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
2108                     }     
2109                     CompileIdentityConstraint(ic);
2110                     if (ic.CompiledConstraint == null) {
2111                         throw new XmlSchemaException(Res.Sch_RefInvalidIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
2112                     }
2113                     // keyref has the different cardinality with the key it referred
2114                     if (ic.Fields.Count != xi.Fields.Count) {
2115                         throw new XmlSchemaException(Res.Sch_RefInvalidCardin, xi.QualifiedName.ToString(), xi);
2116                     }
2117                     // keyref can only refer to key/unique
2118                     if (ic.CompiledConstraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) {
2119                         throw new XmlSchemaException(Res.Sch_ReftoKeyref, xi.QualifiedName.ToString(), xi);
2120                     }
2121                 }
2122                 xi.CompiledConstraint = compic;
2123             }
2124             catch (XmlSchemaException e) {
2125                 if (e.SourceSchemaObject == null) {
2126                     e.SetSource(xi);
2127                 }
2128                 SendValidationEvent(e);
2129                 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;       
2130                 // empty is better than null here, stop quickly when circle referencing
2131             } 
2132             finally {
2133                 xi.IsProcessing = false;
2134             }
2135
2136         }
2137
2138         private void CompileElement(XmlSchemaElement xe) {
2139             if (xe.IsProcessing) {
2140                 SendValidationEvent(Res.Sch_ElementCircularRef, xe);
2141                 return;
2142             }
2143             if (xe.ElementDecl != null) {
2144                 return;
2145             }
2146             xe.IsProcessing = true;
2147             SchemaElementDecl decl = null;
2148             try {
2149                 if (!xe.RefName.IsEmpty) {
2150                     XmlSchemaElement e = (XmlSchemaElement)elements[xe.RefName];
2151                     if (e == null) {
2152                         throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe);
2153                     }  
2154                     CompileElement(e);
2155                     if (e.ElementDecl == null) {
2156                         throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe);
2157                     }
2158                     xe.SetElementType(e.ElementSchemaType);
2159                     decl = e.ElementDecl.Clone();
2160                 }
2161                 else {
2162                     if (xe.SchemaType != null) {
2163                         xe.SetElementType(xe.SchemaType);
2164                     }
2165                     else if (!xe.SchemaTypeName.IsEmpty) {
2166                         xe.SetElementType(GetAnySchemaType(xe.SchemaTypeName));
2167                         if (xe.ElementSchemaType == null) {
2168                             throw new XmlSchemaException(Res.Sch_UndeclaredType, xe.SchemaTypeName.ToString(), xe);   
2169                         }
2170                     }
2171                     else  if (!xe.SubstitutionGroup.IsEmpty) {
2172                         XmlSchemaElement examplar = (XmlSchemaElement)elements[xe.SubstitutionGroup];
2173                         if (examplar == null) {
2174                             throw new XmlSchemaException(Res.Sch_UndeclaredEquivClass, xe.SubstitutionGroup.Name.ToString(CultureInfo.InvariantCulture), xe);   
2175                         }
2176                         if (examplar.IsProcessing) { //Circular subst group; already detected by now
2177                             return;
2178                         }
2179                         CompileElement(examplar);
2180                         if (examplar.ElementDecl == null) { //If head is invalid, fall back to AnyType
2181                             xe.SetElementType(XmlSchemaComplexType.AnyType);
2182                             decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
2183                         }
2184                         else {
2185                             xe.SetElementType(examplar.ElementSchemaType);
2186                             decl = examplar.ElementDecl.Clone();
2187                         }
2188                     }
2189                     else {
2190                         xe.SetElementType(XmlSchemaComplexType.AnyType);
2191                         decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
2192                     }
2193             
2194                     if (decl == null) {
2195                         Debug.Assert(xe.ElementSchemaType != null);
2196                         if (xe.ElementSchemaType is XmlSchemaComplexType) {
2197                             XmlSchemaComplexType complexType = (XmlSchemaComplexType)xe.ElementSchemaType;
2198                             CompileComplexType(complexType);
2199                             if (complexType.ElementDecl != null) {
2200                                 decl = complexType.ElementDecl.Clone();
2201 //                                decl.LocalElements = complexType.LocalElementDecls;
2202                             }
2203                         } 
2204                         else if (xe.ElementSchemaType is XmlSchemaSimpleType) {
2205                             XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)xe.ElementSchemaType;
2206                             CompileSimpleType(simpleType);
2207                             if (simpleType.ElementDecl != null) {
2208                                 decl = simpleType.ElementDecl.Clone();
2209                             }
2210                         } 
2211                     }
2212                     Debug.Assert(decl != null);
2213                     decl.Name = xe.QualifiedName;
2214                     decl.IsAbstract = xe.IsAbstract;
2215                     XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType;
2216                     if (ct != null) {
2217                         decl.IsAbstract |= ct.IsAbstract; 
2218                     }
2219                     decl.IsNillable = xe.IsNillable;
2220                     decl.Block |= xe.BlockResolved;
2221                 }
2222                 if (decl.Datatype != null) {
2223                     decl.Datatype.VerifySchemaValid(notations, xe);
2224                 }
2225
2226                 if (xe.DefaultValue != null || xe.FixedValue != null) {
2227                     if (decl.ContentValidator != null) {
2228                         if (decl.ContentValidator.ContentType == XmlSchemaContentType.TextOnly || (decl.ContentValidator.ContentType == XmlSchemaContentType.Mixed && decl.ContentValidator.IsEmptiable)) {
2229                             if (xe.DefaultValue != null) {
2230                                 decl.Presence = SchemaDeclBase.Use.Default; 
2231                                 decl.DefaultValueRaw = xe.DefaultValue;
2232                             }
2233                             else {
2234                                 decl.Presence = SchemaDeclBase.Use.Fixed; 
2235                                 decl.DefaultValueRaw = xe.FixedValue;
2236                             }
2237                             if (decl.Datatype != null) {
2238                                 if (decl.Datatype.TypeCode == XmlTypeCode.Id) {
2239                                     SendValidationEvent(Res.Sch_DefaultIdValue, xe);
2240                                 }
2241                                 else {
2242                                     decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true);
2243                                 }
2244                             }
2245                             else { //Mixed with emptiable particle
2246                                 decl.DefaultValueTyped = DatatypeImplementation.AnySimpleType.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe));
2247                             }
2248                         }
2249                         else {
2250                             throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe);
2251                         }
2252                     }
2253                 }
2254                 if (xe.HasConstraints) {
2255                     XmlSchemaObjectCollection constraints = xe.Constraints;
2256                     CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count];
2257                     int idx = 0;
2258                     for (int i = 0; i < constraints.Count; ++i) {
2259                         XmlSchemaIdentityConstraint constraint = (XmlSchemaIdentityConstraint)constraints[i];
2260                         CompileIdentityConstraint(constraint);
2261                         compiledConstraints[idx ++] = constraint.CompiledConstraint;
2262                     }
2263                     decl.Constraints = compiledConstraints;
2264                 }
2265                 decl.SchemaElement = xe; //So this is available for PSVI
2266                 xe.ElementDecl = decl;
2267             } 
2268             catch (XmlSchemaException e) {
2269                 if (e.SourceSchemaObject == null) {
2270                     e.SetSource(xe);
2271                 }
2272                 SendValidationEvent(e);
2273                 xe.ElementDecl = SchemaElementDecl.Empty;
2274             } 
2275             finally {
2276                 xe.IsProcessing = false;
2277             }
2278         }
2279
2280         private ContentValidator CompileComplexContent(XmlSchemaComplexType complexType) {
2281             if (complexType.ContentType == XmlSchemaContentType.Empty) {
2282                 return ContentValidator.Empty;
2283             }
2284             else if (complexType.ContentType == XmlSchemaContentType.TextOnly) {
2285                 return ContentValidator.TextOnly;
2286             }
2287             XmlSchemaParticle particle = complexType.ContentTypeParticle;
2288             if (particle == null || particle == XmlSchemaParticle.Empty) {
2289                 if (complexType.ContentType == XmlSchemaContentType.ElementOnly) {
2290                     return ContentValidator.Empty;
2291                 }
2292                 else {
2293                     return ContentValidator.Mixed;
2294                 }
2295             }
2296             PushComplexType(complexType);
2297             if (particle is XmlSchemaAll) {
2298                 XmlSchemaAll all = (XmlSchemaAll)particle;
2299                 AllElementsContentValidator contentValidator = new AllElementsContentValidator(complexType.ContentType, all.Items.Count, all.MinOccurs == decimal.Zero);
2300                 for (int i = 0; i < all.Items.Count; ++i) {
2301                     XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i];
2302                     if (!contentValidator.AddElement(localElement.QualifiedName, localElement, localElement.MinOccurs == decimal.Zero)) {
2303                        SendValidationEvent(Res.Sch_DupElement, localElement.QualifiedName.ToString(), localElement);
2304                     }
2305                 }
2306                 return contentValidator;
2307             }
2308             else {
2309                 ParticleContentValidator contentValidator = new ParticleContentValidator(complexType.ContentType, CompilationSettings.EnableUpaCheck);
2310 #if DEBUG
2311                 string name = complexType.Name != null ? complexType.Name : string.Empty;
2312                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceVerbose, "CompileComplexContent: "+ name  + DumpContentModel(particle));
2313 #endif
2314                 try {
2315                     contentValidator.Start();
2316                     complexType.HasWildCard = BuildParticleContentModel(contentValidator, particle);
2317                     return contentValidator.Finish(true);                         
2318                 }
2319                 catch(UpaException e) {
2320                     if (e.Particle1 is XmlSchemaElement) {
2321                         if (e.Particle2 is XmlSchemaElement) {
2322                             SendValidationEvent(Res.Sch_NonDeterministic, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2);
2323                         }
2324                         else {
2325                             SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaAny)e.Particle2);
2326                         }
2327                     }
2328                     else {
2329                         if (e.Particle2 is XmlSchemaElement) {
2330                             SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaElement)e.Particle2).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2);
2331                         }
2332                         else {
2333                             SendValidationEvent(Res.Sch_NonDeterministicAnyAny, ((XmlSchemaAny)e.Particle1).ResolvedNamespace, ((XmlSchemaAny)e.Particle2).ResolvedNamespace, (XmlSchemaAny)e.Particle2);
2334                         }
2335                     }
2336                     return XmlSchemaComplexType.AnyTypeContentValidator;
2337                 }
2338                 catch(NotSupportedException) {
2339                     SendValidationEvent(Res.Sch_ComplexContentModel, complexType, XmlSeverityType.Warning);
2340                     return XmlSchemaComplexType.AnyTypeContentValidator;
2341                 }
2342             }
2343         }
2344
2345 #if DEBUG
2346         private string DumpContentModel(XmlSchemaParticle particle) {
2347             StringBuilder sb = new StringBuilder();
2348             DumpContentModelTo(sb, particle);
2349             return sb.ToString();
2350         }
2351
2352         private void DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle) {
2353             if (particle is XmlSchemaElement) {
2354                 sb.Append(((XmlSchemaElement)particle).QualifiedName);       
2355             }
2356             else if (particle is XmlSchemaAny) {
2357                 sb.Append("<");
2358                 sb.Append(((XmlSchemaAny)particle).NamespaceList.ToString());
2359                 sb.Append(">");
2360             }
2361             else if (particle is XmlSchemaAll) {
2362                 XmlSchemaAll all = (XmlSchemaAll)particle;
2363                 sb.Append("[");       
2364                 bool first = true;
2365                 for (int i = 0; i < all.Items.Count; ++i) {
2366                     XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i];
2367                     if (first) {
2368                         first = false;
2369                     }
2370                     else {
2371                         sb.Append(", ");
2372                     }
2373                     sb.Append(localElement.QualifiedName.Name);       
2374                     if (localElement.MinOccurs == decimal.Zero) {
2375                         sb.Append("?");                                                                  
2376                     }
2377                 }    
2378                 sb.Append("]");                                
2379             }
2380             else if (particle is XmlSchemaGroupBase) {
2381                 XmlSchemaGroupBase gb = (XmlSchemaGroupBase)particle;
2382                 sb.Append("(");
2383                 string delimeter = (particle is XmlSchemaChoice) ? " | " : ", ";
2384                 bool first = true;
2385                 for (int i = 0; i < gb.Items.Count; ++i) {
2386                     if (first) {
2387                         first = false;
2388                     }
2389                     else {
2390                         sb.Append(delimeter);
2391                     }
2392                     DumpContentModelTo(sb, (XmlSchemaParticle)gb.Items[i]);
2393                 }
2394                 sb.Append(")");
2395             } else {
2396                 Debug.Assert(particle == XmlSchemaParticle.Empty);
2397                 sb.Append("<>");
2398             }
2399             if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2400                 // nothing
2401             }
2402             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2403                 sb.Append("?");
2404             }
2405             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2406                 sb.Append("*");
2407             }
2408             else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2409                 sb.Append("+");
2410             }
2411             else {
2412                 sb.Append("{" + particle.MinOccurs.ToString(NumberFormatInfo.InvariantInfo) +", " + particle.MaxOccurs.ToString(NumberFormatInfo.InvariantInfo) + "}");
2413             }
2414         }
2415 #endif
2416
2417         private bool BuildParticleContentModel(ParticleContentValidator contentValidator, XmlSchemaParticle particle) {
2418             bool hasWildCard = false;
2419             if (particle is XmlSchemaElement) {
2420                 XmlSchemaElement element = (XmlSchemaElement)particle;
2421                 contentValidator.AddName(element.QualifiedName, element);       
2422              }
2423             else if (particle is XmlSchemaAny) {
2424                 hasWildCard = true;
2425                 XmlSchemaAny any = (XmlSchemaAny)particle;
2426                 contentValidator.AddNamespaceList(any.NamespaceList, any);
2427             }
2428             else if (particle is XmlSchemaGroupBase) {
2429                 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2430                 bool isChoice = particle is XmlSchemaChoice;
2431                 contentValidator.OpenGroup();
2432                 bool first = true;
2433                 for (int i = 0; i < particles.Count; ++i) {
2434                     Debug.Assert(!((XmlSchemaParticle)particles[i]).IsEmpty);
2435                     if (first) {
2436                         first = false;
2437                     }
2438                     else if (isChoice) {
2439                         contentValidator.AddChoice();  
2440                     }
2441                     else {
2442                         contentValidator.AddSequence();
2443                     }
2444                     hasWildCard = BuildParticleContentModel(contentValidator, (XmlSchemaParticle)particles[i]);
2445                 }
2446                 contentValidator.CloseGroup();
2447             }
2448             else {
2449                 Debug.Assert(false);
2450             }
2451             if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2452                 // nothing
2453             }
2454             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2455                 contentValidator.AddQMark();
2456             }
2457             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2458                 contentValidator.AddStar();
2459             }
2460             else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2461                 contentValidator.AddPlus();
2462             }
2463             else {
2464                 contentValidator.AddLeafRange(particle.MinOccurs, particle.MaxOccurs);
2465             }
2466             return hasWildCard;
2467         }
2468
2469         private void CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle) {
2470             if (particle is XmlSchemaElement) {
2471                 XmlSchemaElement localElement = (XmlSchemaElement)particle;
2472                 CompileElement(localElement); 
2473                 if (complexType.LocalElements[localElement.QualifiedName] == null) {
2474                     complexType.LocalElements.Add(localElement.QualifiedName, localElement);
2475                 }
2476                 else {
2477                     XmlSchemaElement element = (XmlSchemaElement)complexType.LocalElements[localElement.QualifiedName];
2478                     if (element.ElementSchemaType != localElement.ElementSchemaType) {
2479                         SendValidationEvent(Res.Sch_ElementTypeCollision, particle);
2480                     }
2481                 }                 
2482             }
2483             else if (particle is XmlSchemaGroupBase) {
2484                 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2485                 for (int i = 0; i < particles.Count; ++i) {
2486                     CompileParticleElements(complexType, (XmlSchemaParticle)particles[i]);
2487                 }
2488             }
2489         }
2490
2491         private void CompileParticleElements(XmlSchemaParticle particle) { //For checking redefined group particle derivation
2492             if (particle is XmlSchemaElement) {
2493                 XmlSchemaElement localElement = (XmlSchemaElement)particle;
2494                 CompileElement(localElement);
2495             }
2496             else if (particle is XmlSchemaGroupBase) {
2497                 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2498                 for (int i = 0; i < particles.Count; ++i) {
2499                     CompileParticleElements((XmlSchemaParticle)particles[i]);
2500                 }
2501             }
2502         }
2503
2504         private void CompileComplexTypeElements(XmlSchemaComplexType complexType) {
2505             if (complexType.IsProcessing) {
2506                 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
2507                 return;
2508             }
2509             complexType.IsProcessing = true;
2510             try {
2511                 if (complexType.ContentTypeParticle != XmlSchemaParticle.Empty) {
2512                     CompileParticleElements(complexType, complexType.ContentTypeParticle);
2513                 }
2514             }
2515             finally {
2516                 complexType.IsProcessing = false;
2517             }
2518         }
2519
2520         private XmlSchemaSimpleType GetSimpleType(XmlQualifiedName name) {
2521             XmlSchemaSimpleType type = schemaTypes[name] as XmlSchemaSimpleType;
2522             if (type != null) {
2523                 CompileSimpleType(type);
2524             }
2525             else {
2526                 type = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
2527             }
2528             return type;
2529         }
2530
2531         private XmlSchemaComplexType GetComplexType(XmlQualifiedName name) {
2532             XmlSchemaComplexType type = schemaTypes[name] as XmlSchemaComplexType;
2533             if (type != null) {
2534                 CompileComplexType(type);
2535             }
2536             return type;
2537         }
2538
2539          private XmlSchemaType GetAnySchemaType(XmlQualifiedName name) {
2540                 XmlSchemaType type = (XmlSchemaType)schemaTypes[name];
2541                 if (type != null) {
2542                     if (type is XmlSchemaComplexType) {
2543                         CompileComplexType((XmlSchemaComplexType)type);
2544                     }
2545                     else {
2546                         CompileSimpleType((XmlSchemaSimpleType)type);  
2547                     }
2548                     return type;
2549                 }
2550                 else { //Its is a built-in simpleType
2551                     XmlSchemaSimpleType simpleType = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
2552                     return simpleType;
2553                 }
2554         }
2555
2556          private void CopyPosition(XmlSchemaAnnotated to, XmlSchemaAnnotated from, bool copyParent) {
2557              to.SourceUri = from.SourceUri;
2558              to.LinePosition = from.LinePosition;
2559              to.LineNumber = from.LineNumber;
2560              to.SetUnhandledAttributes(from.UnhandledAttributes);
2561              if (copyParent) {
2562                 to.Parent = from.Parent;
2563              }
2564          }
2565
2566          private bool IsFixedEqual(SchemaDeclBase baseDecl, SchemaDeclBase derivedDecl) {
2567             
2568             if (baseDecl.Presence == SchemaDeclBase.Use.Fixed || baseDecl.Presence == SchemaDeclBase.Use.RequiredFixed) {
2569                 object baseFixedValue = baseDecl.DefaultValueTyped;
2570                 object derivedFixedValue = derivedDecl.DefaultValueTyped;
2571
2572                 Debug.Assert(baseFixedValue != null);
2573                 if (derivedDecl.Presence != SchemaDeclBase.Use.Fixed && derivedDecl.Presence != SchemaDeclBase.Use.RequiredFixed) {
2574                     return false;
2575                 }
2576                 Debug.Assert(derivedFixedValue != null);
2577                 XmlSchemaDatatype baseDatatype = baseDecl.Datatype;
2578                 XmlSchemaDatatype derivedDatatype = derivedDecl.Datatype;
2579
2580                 if (baseDatatype.Variety == XmlSchemaDatatypeVariety.Union) {
2581                     if (derivedDatatype.Variety == XmlSchemaDatatypeVariety.Union) {
2582                         if ( !derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue) ) {
2583                             return false;
2584                         }
2585                     }
2586                     else { //Base is union and derived is member of union
2587                         XsdSimpleValue simpleFixedValue = baseDecl.DefaultValueTyped as XsdSimpleValue;
2588                         Debug.Assert(simpleFixedValue != null);
2589                         XmlSchemaDatatype memberType = simpleFixedValue.XmlType.Datatype;
2590                         if (!memberType.IsComparable(derivedDatatype) || !derivedDatatype.IsEqual(simpleFixedValue.TypedValue, derivedFixedValue)) { //base type {Union of long & string}, derived type {int}
2591                             return false;
2592                         }
2593                     }
2594                 }
2595                 else if (!derivedDatatype.IsEqual(baseFixedValue, derivedFixedValue)) {
2596                     return false;
2597                 }
2598             }
2599             return true;
2600          }
2601     };
2602
2603 } // namespace System.Xml