Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Schema / SchemaCollectionCompiler.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 SchemaCollectionCompiler : BaseProcessor {
17         bool compileContentModel;
18         XmlSchemaObjectTable examplars = new XmlSchemaObjectTable();
19         Stack complexTypeStack = new Stack();
20         XmlSchema schema;
21
22         public SchemaCollectionCompiler(XmlNameTable nameTable, ValidationEventHandler eventHandler) 
23             : base(nameTable, null, eventHandler) {
24         }
25
26         public bool Execute(XmlSchema schema, SchemaInfo schemaInfo, bool compileContentModel) {
27             this.compileContentModel = compileContentModel;
28             this.schema = schema;
29             Prepare();
30             Cleanup();
31             Compile();
32             if (!HasErrors) {
33                 Output(schemaInfo);
34             }
35             return !HasErrors;
36         }
37
38         private void Prepare() {
39             foreach (XmlSchemaElement element in this.schema.Elements.Values) {
40                 if (!element.SubstitutionGroup.IsEmpty) {
41                     XmlSchemaSubstitutionGroup substitutionGroup = (XmlSchemaSubstitutionGroup)this.examplars[element.SubstitutionGroup];
42                     if (substitutionGroup == null) {
43                         substitutionGroup = new XmlSchemaSubstitutionGroupV1Compat();
44                         substitutionGroup.Examplar = element.SubstitutionGroup;
45                         examplars.Add(element.SubstitutionGroup, substitutionGroup);
46                     }
47                     ArrayList members = substitutionGroup.Members;
48                     Debug.Assert(!members.Contains(element));
49                     members.Add(element);
50                 }
51             }
52         }
53
54         private void Cleanup() {
55             foreach (XmlSchemaGroup group in this.schema.Groups.Values) {
56                 CleanupGroup(group);
57             }
58             foreach (XmlSchemaAttributeGroup attributeGroup in this.schema.AttributeGroups.Values) {
59                 CleanupAttributeGroup(attributeGroup);
60             }
61             foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
62                 if (type is XmlSchemaComplexType) {
63                     CleanupComplexType((XmlSchemaComplexType)type);
64                 }
65                 else {
66                     CleanupSimpleType((XmlSchemaSimpleType)type);
67                 }
68             }
69             foreach (XmlSchemaElement element in this.schema.Elements.Values) {
70                 CleanupElement(element);
71             }
72             foreach (XmlSchemaAttribute attribute in this.schema.Attributes.Values) {
73                 CleanupAttribute(attribute);
74             }    
75         }
76
77
78         internal static void Cleanup(XmlSchema schema) {
79             for (int i = 0; i < schema.Includes.Count; ++i) {
80                 XmlSchemaExternal include = (XmlSchemaExternal)schema.Includes[i];
81                 if (include.Schema != null) {
82                     Cleanup(include.Schema);
83                 }
84                 XmlSchemaRedefine rdef = include as XmlSchemaRedefine;
85                 if(rdef != null) {
86                     rdef.AttributeGroups.Clear();
87                     rdef.Groups.Clear();
88                     rdef.SchemaTypes.Clear();
89
90                     for (int j = 0; j < rdef.Items.Count; ++j) {
91                         object item = rdef.Items[j];
92                         XmlSchemaAttribute attr;
93                         XmlSchemaAttributeGroup attrgroup;
94                         XmlSchemaComplexType complextype;
95                         XmlSchemaSimpleType simpletype;
96                         XmlSchemaElement element;
97                         XmlSchemaGroup group;
98
99                         if ((attr = item as XmlSchemaAttribute) != null) {
100                             CleanupAttribute(attr);
101                         } 
102                         else if ((attrgroup = item as XmlSchemaAttributeGroup) != null) {
103                             CleanupAttributeGroup(attrgroup);
104                         } 
105                         else if ((complextype = item as XmlSchemaComplexType) != null) {
106                             CleanupComplexType(complextype);
107                         } 
108                         else if ((simpletype = item as XmlSchemaSimpleType) != null) {
109                             CleanupSimpleType(simpletype);
110                         } 
111                         else if ((element = item as XmlSchemaElement) != null) {
112                             CleanupElement(element);
113                         } 
114                         else if ((group = item as XmlSchemaGroup) != null) {
115                             CleanupGroup(group);
116                         } 
117                     }
118                 }
119             }
120
121             for (int i = 0; i < schema.Items.Count; ++i) {
122                 object item = schema.Items[i];
123                 XmlSchemaAttribute attr;
124                 XmlSchemaAttributeGroup attrgroup;
125                 XmlSchemaComplexType complextype;
126                 XmlSchemaSimpleType simpletype;
127                 XmlSchemaElement element;
128                 XmlSchemaGroup group;
129
130                 if ((attr = item as XmlSchemaAttribute) != null) {
131                     CleanupAttribute(attr);
132                 } 
133                 else if ((attrgroup = schema.Items[i] as XmlSchemaAttributeGroup) != null) {
134                     CleanupAttributeGroup(attrgroup);
135                 } 
136                 else if ((complextype = schema.Items[i] as XmlSchemaComplexType) != null) {
137                     CleanupComplexType(complextype);
138                 } 
139                 else if ((simpletype = schema.Items[i] as XmlSchemaSimpleType) != null) {
140                     CleanupSimpleType(simpletype);
141                 } 
142                 else if ((element = schema.Items[i] as XmlSchemaElement) != null) {
143                     CleanupElement(element);
144                 } 
145                 else if ((group = schema.Items[i] as XmlSchemaGroup) != null) {
146                     CleanupGroup(group);
147                 } 
148             }
149             schema.Attributes.Clear();
150             schema.AttributeGroups.Clear();
151             schema.SchemaTypes.Clear();
152             schema.Elements.Clear();
153             schema.Groups.Clear();
154             schema.Notations.Clear();
155             schema.Ids.Clear();
156             schema.IdentityConstraints.Clear();
157         }
158
159         private void Compile() {
160             this.schema.SchemaTypes.Insert(DatatypeImplementation.QnAnyType, XmlSchemaComplexType.AnyType);
161
162             foreach (XmlSchemaSubstitutionGroupV1Compat substitutionGroup in examplars.Values) {
163                 CompileSubstitutionGroup(substitutionGroup);
164             }
165             foreach (XmlSchemaGroup group in this.schema.Groups.Values) {
166                 CompileGroup(group);
167             }
168             foreach (XmlSchemaAttributeGroup attributeGroup in this.schema.AttributeGroups.Values) {
169                 CompileAttributeGroup(attributeGroup);
170             }
171             foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
172                 if (type is XmlSchemaComplexType) {
173                     CompileComplexType((XmlSchemaComplexType)type);
174                 }
175                 else {
176                     CompileSimpleType((XmlSchemaSimpleType)type);
177                 }
178             }
179             foreach (XmlSchemaElement element in this.schema.Elements.Values) {
180                 if (element.ElementDecl == null) {
181                     CompileElement(element);
182                 }
183             }
184             foreach (XmlSchemaAttribute attribute in this.schema.Attributes.Values) {
185                 if (attribute.AttDef == null) {
186                     CompileAttribute(attribute);
187                 }
188             }    
189             foreach (XmlSchemaIdentityConstraint identityConstraint in this.schema.IdentityConstraints.Values) {
190                 if (identityConstraint.CompiledConstraint == null) {
191                     CompileIdentityConstraint(identityConstraint);
192                 }
193             }    
194             while (this.complexTypeStack.Count > 0) {
195                 XmlSchemaComplexType type = (XmlSchemaComplexType)complexTypeStack.Pop();
196                 CompileCompexTypeElements(type);
197             }
198             foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
199                 if (type is XmlSchemaComplexType) {
200                     CheckParticleDerivation((XmlSchemaComplexType)type);
201                 }
202             }
203             foreach (XmlSchemaElement element in this.schema.Elements.Values) {
204                 if (element.ElementSchemaType is XmlSchemaComplexType && element.SchemaTypeName == XmlQualifiedName.Empty) { // only local schemaTypes
205                     CheckParticleDerivation((XmlSchemaComplexType)element.ElementSchemaType);
206                 }
207             }
208             foreach (XmlSchemaSubstitutionGroup substitutionGroup in examplars.Values) {
209                 CheckSubstitutionGroup(substitutionGroup);
210             }
211
212             this.schema.SchemaTypes.Remove(DatatypeImplementation.QnAnyType); //For backward compatibility
213         }
214
215         private void Output(SchemaInfo schemaInfo) {
216             foreach (XmlSchemaElement element in this.schema.Elements.Values) {
217                 schemaInfo.TargetNamespaces[element.QualifiedName.Namespace] = true;
218                 schemaInfo.ElementDecls.Add(element.QualifiedName, element.ElementDecl);
219             }
220             foreach (XmlSchemaAttribute attribute in this.schema.Attributes.Values) {
221                 schemaInfo.TargetNamespaces[attribute.QualifiedName.Namespace] = true;
222                 schemaInfo.AttributeDecls.Add(attribute.QualifiedName, attribute.AttDef);
223             }    
224             foreach (XmlSchemaType type in this.schema.SchemaTypes.Values) {
225                 schemaInfo.TargetNamespaces[type.QualifiedName.Namespace] = true;
226                  XmlSchemaComplexType complexType = type as XmlSchemaComplexType;
227                  if (complexType == null || (!complexType.IsAbstract && type != XmlSchemaComplexType.AnyType)) {
228                     schemaInfo.ElementDeclsByType.Add(type.QualifiedName, type.ElementDecl);
229                  }
230             }
231             foreach (XmlSchemaNotation notation in this.schema.Notations.Values) {
232                 schemaInfo.TargetNamespaces[notation.QualifiedName.Namespace] = true;
233                 SchemaNotation no = new SchemaNotation(notation.QualifiedName);
234                 no.SystemLiteral = notation.System;
235                 no.Pubid = notation.Public;
236                 if (!schemaInfo.Notations.ContainsKey(no.Name.Name)) {
237                     schemaInfo.Notations.Add(no.Name.Name, no);
238                 }
239             }
240         }
241
242         private static void CleanupAttribute(XmlSchemaAttribute attribute) {
243             if (attribute.SchemaType != null) {
244                 CleanupSimpleType((XmlSchemaSimpleType)attribute.SchemaType);
245             }
246             attribute.AttDef = null;
247         }
248         
249         private static void CleanupAttributeGroup(XmlSchemaAttributeGroup attributeGroup) {
250             CleanupAttributes(attributeGroup.Attributes);
251             attributeGroup.AttributeUses.Clear();
252             attributeGroup.AttributeWildcard = null;
253         }
254         
255         private static void CleanupComplexType(XmlSchemaComplexType complexType) {
256             if (complexType.ContentModel != null) { //simpleContent or complexContent
257                 if (complexType.ContentModel is XmlSchemaSimpleContent) {
258                     XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
259                     if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
260                         XmlSchemaSimpleContentExtension simpleExtension = (XmlSchemaSimpleContentExtension)simpleContent.Content;
261                         CleanupAttributes(simpleExtension.Attributes);
262                     }
263                     else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
264                         XmlSchemaSimpleContentRestriction simpleRestriction = (XmlSchemaSimpleContentRestriction)simpleContent.Content;
265                         CleanupAttributes(simpleRestriction.Attributes);
266                     }
267                 }
268                 else { // complexType.ContentModel is XmlSchemaComplexContent
269                     XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
270                     if (complexContent.Content is XmlSchemaComplexContentExtension) {
271                         XmlSchemaComplexContentExtension complexExtension = (XmlSchemaComplexContentExtension)complexContent.Content;
272                         CleanupParticle(complexExtension.Particle);
273                         CleanupAttributes(complexExtension.Attributes);
274
275                     }
276                     else { //XmlSchemaComplexContentRestriction
277                         XmlSchemaComplexContentRestriction complexRestriction = (XmlSchemaComplexContentRestriction)complexContent.Content;
278                         CleanupParticle(complexRestriction.Particle);
279                         CleanupAttributes(complexRestriction.Attributes);
280                     }
281                 }
282             }
283             else { //equals XmlSchemaComplexContent with baseType is anyType
284                 CleanupParticle(complexType.Particle);
285                 CleanupAttributes(complexType.Attributes);
286             }
287             complexType.LocalElements.Clear();
288             complexType.AttributeUses.Clear();
289             complexType.SetAttributeWildcard(null);
290             complexType.SetContentTypeParticle(XmlSchemaParticle.Empty);
291             complexType.ElementDecl = null;
292         }
293         
294         private static void CleanupSimpleType(XmlSchemaSimpleType simpleType) {
295             simpleType.ElementDecl = null;
296         }
297         
298         private static void CleanupElement(XmlSchemaElement element) {
299             if (element.SchemaType != null) {
300                 XmlSchemaComplexType complexType = element.SchemaType as XmlSchemaComplexType;
301                 if (complexType != null) {
302                     CleanupComplexType(complexType);
303                 }
304                 else {
305                     CleanupSimpleType((XmlSchemaSimpleType)element.SchemaType);
306                 }
307             }
308             for (int i = 0; i < element.Constraints.Count; ++i) {
309                 ((XmlSchemaIdentityConstraint)element.Constraints[i]).CompiledConstraint = null;
310             }
311             element.ElementDecl = null;
312         }
313         
314         private static void CleanupAttributes(XmlSchemaObjectCollection attributes) {
315             for (int i = 0; i < attributes.Count; ++i) {
316                 XmlSchemaAttribute attribute = attributes[i] as XmlSchemaAttribute;
317                 if (attribute != null) {
318                     CleanupAttribute(attribute);
319                 }
320             }
321         }
322
323         private static void CleanupGroup(XmlSchemaGroup group) {
324             CleanupParticle(group.Particle);
325             group.CanonicalParticle = null;
326         }
327
328         private static void CleanupParticle(XmlSchemaParticle particle) {
329             if (particle is XmlSchemaElement) {
330                 CleanupElement((XmlSchemaElement)particle);
331             }
332             else if (particle is XmlSchemaGroupBase) {
333                 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
334                 for (int i = 0; i < particles.Count; ++i) {
335                     CleanupParticle((XmlSchemaParticle)particles[i]);
336                 }
337             }
338         }
339
340         private void CompileSubstitutionGroup(XmlSchemaSubstitutionGroupV1Compat substitutionGroup) {
341             if (substitutionGroup.IsProcessing && substitutionGroup.Members.Count > 0) {
342                 SendValidationEvent(Res.Sch_SubstitutionCircularRef, (XmlSchemaElement)substitutionGroup.Members[0]);
343                 return;
344             }
345             XmlSchemaElement examplar = (XmlSchemaElement)this.schema.Elements[substitutionGroup.Examplar];
346             if (substitutionGroup.Members.Contains(examplar)) {// already checked
347                 return;
348             }
349             substitutionGroup.IsProcessing = true; 
350             if (examplar != null) {
351                 if (examplar.FinalResolved == XmlSchemaDerivationMethod.All) {
352                     SendValidationEvent(Res.Sch_InvalidExamplar, examplar);
353                 }
354
355                 for (int i = 0; i < substitutionGroup.Members.Count; ++i) {
356                     XmlSchemaElement element = (XmlSchemaElement)substitutionGroup.Members[i];
357                     //Chain to other head's that are members of this head's substGroup
358                     XmlSchemaSubstitutionGroupV1Compat g = (XmlSchemaSubstitutionGroupV1Compat)examplars[element.QualifiedName];
359                     if (g != null) {
360                         CompileSubstitutionGroup(g);
361                         for (int j = 0; j < g.Choice.Items.Count; ++j) {
362                             substitutionGroup.Choice.Items.Add(g.Choice.Items[j]);
363                         }
364                     }
365                     else {
366                         substitutionGroup.Choice.Items.Add(element);
367                     }
368                 }
369                 substitutionGroup.Choice.Items.Add(examplar);
370                 substitutionGroup.Members.Add(examplar); // Compiled mark
371             }
372             else if (substitutionGroup.Members.Count > 0) {
373                 SendValidationEvent(Res.Sch_NoExamplar, (XmlSchemaElement)substitutionGroup.Members[0]);
374             }
375             substitutionGroup.IsProcessing = false;
376         }
377
378         private void CheckSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup) {
379             XmlSchemaElement examplar = (XmlSchemaElement)this.schema.Elements[substitutionGroup.Examplar];
380             if (examplar != null) {
381                 for (int i = 0; i < substitutionGroup.Members.Count; ++i) {
382                     XmlSchemaElement element = (XmlSchemaElement)substitutionGroup.Members[i];
383
384                     if (element != examplar) {
385                         if (!XmlSchemaType.IsDerivedFrom(element.ElementSchemaType, examplar.ElementSchemaType, examplar.FinalResolved)) {
386                             SendValidationEvent(Res.Sch_InvalidSubstitutionMember, (element.QualifiedName).ToString(), (examplar.QualifiedName).ToString(), element);
387                         }
388                     }
389                 }
390             }            
391         }
392
393         private void CompileGroup(XmlSchemaGroup group) {
394             if (group.IsProcessing) {
395                 SendValidationEvent(Res.Sch_GroupCircularRef, group);
396                 group.CanonicalParticle = XmlSchemaParticle.Empty;
397             } 
398             else {
399                 group.IsProcessing = true;
400                 if (group.CanonicalParticle == null) { 
401                     group.CanonicalParticle = CannonicalizeParticle(group.Particle, true, true); 
402                 }
403                 Debug.Assert(group.CanonicalParticle != null);
404                 group.IsProcessing = false;
405             }
406         }
407
408         private void CompileSimpleType(XmlSchemaSimpleType simpleType) {
409             if (simpleType.IsProcessing) {
410                 throw new XmlSchemaException(Res.Sch_TypeCircularRef, simpleType);
411             }
412             if (simpleType.ElementDecl != null) { // already compiled
413                 return;
414             }
415             simpleType.IsProcessing = true;
416             try {
417                 if (simpleType.Content is XmlSchemaSimpleTypeList) {
418                     XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)simpleType.Content;
419                     XmlSchemaDatatype datatype;
420                     simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType); 
421                     if (list.ItemTypeName.IsEmpty) {
422                         CompileSimpleType(list.ItemType);
423                         list.BaseItemType = list.ItemType;
424                         datatype = list.ItemType.Datatype;
425                     }
426                     else {
427                         XmlSchemaSimpleType type = GetSimpleType(list.ItemTypeName);
428                         if (type != null) {
429                             if ((type.FinalResolved & XmlSchemaDerivationMethod.List) != 0) {
430                                 SendValidationEvent(Res.Sch_BaseFinalList, simpleType);
431                             }
432                             list.BaseItemType = type;
433                             datatype = type.Datatype;
434                         }
435                         else {
436                             throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, list.ItemTypeName.ToString(), simpleType);   
437                         }
438                     }
439                     simpleType.SetDatatype(datatype.DeriveByList(simpleType));
440                     simpleType.SetDerivedBy(XmlSchemaDerivationMethod.List);
441                 }
442                 else if (simpleType.Content is XmlSchemaSimpleTypeRestriction) {
443                     XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content;
444                     XmlSchemaDatatype datatype;
445                     if (restriction.BaseTypeName.IsEmpty) {
446                         CompileSimpleType(restriction.BaseType);
447                         simpleType.SetBaseSchemaType(restriction.BaseType);
448                         datatype = restriction.BaseType.Datatype;
449                     }
450                     else if (simpleType.Redefined != null && restriction.BaseTypeName == simpleType.Redefined.QualifiedName) {
451                         CompileSimpleType((XmlSchemaSimpleType)simpleType.Redefined);
452                         simpleType.SetBaseSchemaType(simpleType.Redefined.BaseXmlSchemaType);
453                         datatype = simpleType.Redefined.Datatype;
454                     }
455                     else {
456                         if (restriction.BaseTypeName.Equals(DatatypeImplementation.QnAnySimpleType)) {
457                             throw new XmlSchemaException(Res.Sch_InvalidSimpleTypeRestriction, restriction.BaseTypeName.ToString(), simpleType);   
458                         }
459                         XmlSchemaSimpleType type = GetSimpleType(restriction.BaseTypeName);
460                         if (type != null) {
461                             if ((type.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
462                                 SendValidationEvent(Res.Sch_BaseFinalRestriction, simpleType);
463                             }
464                             simpleType.SetBaseSchemaType(type);
465                             datatype = type.Datatype;
466                         }
467                         else {
468                             throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, restriction.BaseTypeName.ToString(), simpleType);   
469                         }
470                     }
471                     simpleType.SetDatatype(datatype.DeriveByRestriction(restriction.Facets, NameTable, simpleType));
472                     simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
473                 }
474                 else { //simpleType.Content is XmlSchemaSimpleTypeUnion
475                     XmlSchemaSimpleType[] baseTypes = CompileBaseMemberTypes(simpleType);
476                     simpleType.SetBaseSchemaType(DatatypeImplementation.AnySimpleType);
477                     simpleType.SetDatatype(XmlSchemaDatatype.DeriveByUnion(baseTypes, simpleType));
478                     simpleType.SetDerivedBy(XmlSchemaDerivationMethod.Union);
479                 }
480             } 
481             catch (XmlSchemaException e) {
482                 if (e.SourceSchemaObject == null) {
483                     e.SetSource(simpleType);
484                 }
485                 SendValidationEvent(e);
486                 simpleType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
487             } 
488             finally {
489                 SchemaElementDecl decl = new SchemaElementDecl();
490                 decl.ContentValidator = ContentValidator.TextOnly;
491                 decl.SchemaType = simpleType;
492                 decl.Datatype = simpleType.Datatype;
493                 simpleType.ElementDecl = decl;
494                 simpleType.IsProcessing = false;
495             }
496         }
497
498         private XmlSchemaSimpleType[] CompileBaseMemberTypes(XmlSchemaSimpleType simpleType) {
499             XmlSchemaSimpleType unionMember;
500             ArrayList memberTypeDefinitions = new ArrayList();
501
502             XmlSchemaSimpleTypeUnion mainUnion = (XmlSchemaSimpleTypeUnion)simpleType.Content;
503
504             XmlQualifiedName[] mainMemberTypes = mainUnion.MemberTypes;
505             if (mainMemberTypes != null) {
506                 for (int i = 0; i < mainMemberTypes.Length; ++i) {
507                     unionMember = GetSimpleType(mainMemberTypes[i]);
508                     if (unionMember != null) {
509                         if (unionMember.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
510                             CheckUnionType(unionMember, memberTypeDefinitions, simpleType);
511                         }
512                         else { //its list or atomic
513                             memberTypeDefinitions.Add(unionMember);
514                         }
515                         //Check derivation method of the member that is referenced
516                         if ((unionMember.FinalResolved & XmlSchemaDerivationMethod.Union) != 0) {
517                             SendValidationEvent(Res.Sch_BaseFinalUnion, simpleType);
518                         }
519                     }
520                     else {
521                         throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, mainMemberTypes[i].ToString(), simpleType);   
522                     }
523                 }
524             }
525
526             //Now add the baseTypes that are defined inside the union itself
527             XmlSchemaObjectCollection mainBaseTypes = mainUnion.BaseTypes; //
528             if (mainBaseTypes != null) {
529                 for (int i = 0; i < mainBaseTypes.Count; ++i) {
530                     XmlSchemaSimpleType st = (XmlSchemaSimpleType)mainBaseTypes[i];
531                     CompileSimpleType(st);
532                     if (st.Datatype.Variety == XmlSchemaDatatypeVariety.Union) { //union of union
533                         CheckUnionType(st, memberTypeDefinitions, simpleType);
534                     }
535                     else {  //its list or atomic
536                         memberTypeDefinitions.Add(st);
537                     }
538                 }
539             }
540             //set all types
541             mainUnion.SetBaseMemberTypes(memberTypeDefinitions.ToArray(typeof(XmlSchemaSimpleType)) as XmlSchemaSimpleType[]);
542             return mainUnion.BaseMemberTypes;
543         }
544
545         private void CheckUnionType(XmlSchemaSimpleType unionMember, ArrayList memberTypeDefinitions, XmlSchemaSimpleType parentType) {
546             XmlSchemaDatatype unionDatatype = unionMember.Datatype;
547             if (unionMember.DerivedBy == XmlSchemaDerivationMethod.Restriction && (unionDatatype.HasLexicalFacets || unionDatatype.HasValueFacets) ) {
548                 SendValidationEvent(Res.Sch_UnionFromUnion, parentType);
549             }
550             else {
551                 Datatype_union uniondt = unionMember.Datatype as Datatype_union;
552                 memberTypeDefinitions.AddRange(uniondt.BaseMemberTypes);
553             }
554         }
555
556         private void CompileComplexType(XmlSchemaComplexType complexType) {
557             if (complexType.ElementDecl != null) { //already compiled
558                 return;
559             }
560             if (complexType.IsProcessing) {
561                 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
562                 return;
563             }
564             complexType.IsProcessing = true;
565             if (complexType.ContentModel != null) { //simpleContent or complexContent
566                 if (complexType.ContentModel is XmlSchemaSimpleContent) {
567                     XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent)complexType.ContentModel;
568                     complexType.SetContentType(XmlSchemaContentType.TextOnly);
569                     if (simpleContent.Content is XmlSchemaSimpleContentExtension) {
570                         CompileSimpleContentExtension(complexType, (XmlSchemaSimpleContentExtension)simpleContent.Content);
571                     }
572                     else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
573                         CompileSimpleContentRestriction(complexType, (XmlSchemaSimpleContentRestriction)simpleContent.Content);
574                     }
575                 }
576                 else { // complexType.ContentModel is XmlSchemaComplexContent
577                     XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
578                     if (complexContent.Content is XmlSchemaComplexContentExtension) {
579                         CompileComplexContentExtension(complexType, complexContent, (XmlSchemaComplexContentExtension)complexContent.Content);
580                     }
581                     else { // complexContent.Content is XmlSchemaComplexContentRestriction
582                         CompileComplexContentRestriction(complexType, complexContent, (XmlSchemaComplexContentRestriction)complexContent.Content);
583                     }
584                 }
585             }
586             else { //equals XmlSchemaComplexContent with baseType is anyType
587                     complexType.SetBaseSchemaType(XmlSchemaComplexType.AnyType);
588                     CompileLocalAttributes(XmlSchemaComplexType.AnyType, complexType, complexType.Attributes, complexType.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
589                     complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
590                     complexType.SetContentTypeParticle(CompileContentTypeParticle(complexType.Particle, true));
591                     complexType.SetContentType(GetSchemaContentType(complexType, null, complexType.ContentTypeParticle));
592             }
593             bool hasID = false;
594             foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) {
595                 if (attribute.Use != XmlSchemaUse.Prohibited) {
596                     XmlSchemaDatatype datatype = attribute.Datatype;
597                     if (datatype != null && datatype.TokenizedType == XmlTokenizedType.ID) {
598                         if (hasID) {
599                             SendValidationEvent(Res.Sch_TwoIdAttrUses, complexType);
600                         }
601                         else {
602                             hasID = true;
603                         }
604                     }
605                 }
606             }
607             SchemaElementDecl decl = new SchemaElementDecl();
608             decl.ContentValidator = CompileComplexContent(complexType);
609             decl.SchemaType = complexType;
610             decl.IsAbstract = complexType.IsAbstract;
611             decl.Datatype = complexType.Datatype;
612             decl.Block = complexType.BlockResolved;
613             decl.AnyAttribute = complexType.AttributeWildcard;
614             foreach(XmlSchemaAttribute attribute in complexType.AttributeUses.Values) {
615                 if (attribute.Use == XmlSchemaUse.Prohibited) {
616                     if (!decl.ProhibitedAttributes.ContainsKey(attribute.QualifiedName)) {
617                         decl.ProhibitedAttributes.Add(attribute.QualifiedName, attribute.QualifiedName);
618                     }
619                 }
620                 else {
621                     if (!decl.AttDefs.ContainsKey(attribute.QualifiedName) && attribute.AttDef != null && attribute.AttDef.Name != XmlQualifiedName.Empty && attribute.AttDef != SchemaAttDef.Empty) {
622                         decl.AddAttDef(attribute.AttDef);
623                     }
624                 }
625             }
626             
627             complexType.ElementDecl = decl;
628
629             complexType.IsProcessing = false;
630         }
631
632
633         private void CompileSimpleContentExtension(XmlSchemaComplexType complexType, XmlSchemaSimpleContentExtension simpleExtension) {
634             XmlSchemaComplexType baseType = null;
635             if (complexType.Redefined != null && simpleExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
636                 baseType = (XmlSchemaComplexType)complexType.Redefined;
637                 CompileComplexType(baseType);
638                 complexType.SetBaseSchemaType(baseType);
639                 complexType.SetDatatype(baseType.Datatype);
640             }
641             else {
642                 XmlSchemaType bto = GetAnySchemaType(simpleExtension.BaseTypeName);
643                 if (bto == null) {
644                     SendValidationEvent(Res.Sch_UndeclaredType, simpleExtension.BaseTypeName.ToString(), complexType);   
645                 } 
646                 else {
647                     complexType.SetBaseSchemaType(bto);
648                     complexType.SetDatatype(bto.Datatype);
649                 }
650                 baseType = bto as XmlSchemaComplexType;
651             }
652             if (baseType != null) {
653                 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
654                     SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
655                 }
656                 if (baseType.ContentType != XmlSchemaContentType.TextOnly) {
657                     SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
658                 }
659             } 
660             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
661             CompileLocalAttributes(baseType, complexType, simpleExtension.Attributes, simpleExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
662         }
663
664         private void CompileSimpleContentRestriction(XmlSchemaComplexType complexType, XmlSchemaSimpleContentRestriction simpleRestriction) {
665             XmlSchemaComplexType baseType = null;
666             XmlSchemaDatatype datatype = null;
667             if (complexType.Redefined != null && simpleRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
668                 baseType = (XmlSchemaComplexType)complexType.Redefined;
669                 CompileComplexType(baseType);
670                 datatype = baseType.Datatype;
671             }
672             else {
673                 baseType = GetComplexType(simpleRestriction.BaseTypeName);
674                 if (baseType == null) {
675                     SendValidationEvent(Res.Sch_UndefBaseRestriction, simpleRestriction.BaseTypeName.ToString(), simpleRestriction);
676                     return;
677                 }
678                 if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
679                     if (simpleRestriction.BaseType == null) { 
680                         datatype = baseType.Datatype; 
681                         //There is a bug here. Need to check if simpleRestriction has facets.
682                         //If yes, Need tp apply these facets as well. 
683                     }
684                     else {
685                         CompileSimpleType(simpleRestriction.BaseType);
686                         if(!XmlSchemaType.IsDerivedFromDatatype(simpleRestriction.BaseType.Datatype, baseType.Datatype, XmlSchemaDerivationMethod.None)) {
687                            SendValidationEvent(Res.Sch_DerivedNotFromBase, simpleRestriction);
688                         }
689                         datatype = simpleRestriction.BaseType.Datatype;
690                     }
691                 }
692                 else if (baseType.ContentType == XmlSchemaContentType.Mixed && baseType.ElementDecl.ContentValidator.IsEmptiable) {
693                     if (simpleRestriction.BaseType != null) {
694                         CompileSimpleType(simpleRestriction.BaseType);
695                         complexType.SetBaseSchemaType(simpleRestriction.BaseType);
696                         datatype = simpleRestriction.BaseType.Datatype;
697                     }
698                     else {
699                         SendValidationEvent(Res.Sch_NeedSimpleTypeChild, simpleRestriction);
700                     }
701                 }
702                 else {
703                     SendValidationEvent(Res.Sch_NotSimpleContent, complexType);
704                 }
705             }
706             if (baseType != null && baseType.ElementDecl != null) {
707                 if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
708                     SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
709                 }
710             }
711             if (baseType != null) {
712                 complexType.SetBaseSchemaType(baseType);
713             }
714             if (datatype != null) {
715                 try {
716                     complexType.SetDatatype(datatype.DeriveByRestriction(simpleRestriction.Facets, NameTable, complexType));
717                 }
718                 catch (XmlSchemaException e) {
719                     if (e.SourceSchemaObject == null) {
720                         e.SetSource(complexType);
721                     }
722                     SendValidationEvent(e);
723                     complexType.SetDatatype(DatatypeImplementation.AnySimpleType.Datatype);
724                 } 
725             }
726             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
727             CompileLocalAttributes(baseType, complexType, simpleRestriction.Attributes, simpleRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
728         }
729
730         private void CompileComplexContentExtension(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentExtension complexExtension) {
731             XmlSchemaComplexType baseType = null;
732             if (complexType.Redefined != null && complexExtension.BaseTypeName == complexType.Redefined.QualifiedName) {
733                 baseType = (XmlSchemaComplexType)complexType.Redefined;
734                 CompileComplexType(baseType);
735             }
736             else {
737                 baseType = GetComplexType(complexExtension.BaseTypeName);
738                 if (baseType == null) {
739                     SendValidationEvent(Res.Sch_UndefBaseExtension, complexExtension.BaseTypeName.ToString(), complexExtension);   
740                     return;
741                 }
742             }
743             if (baseType != null && baseType.ElementDecl != null) {
744                 if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
745                     SendValidationEvent(Res.Sch_NotComplexContent, complexType);
746                     return;
747                 }
748             }
749             complexType.SetBaseSchemaType(baseType);
750             if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0) {
751                 SendValidationEvent(Res.Sch_BaseFinalExtension, complexType);
752             }
753             CompileLocalAttributes(baseType, complexType, complexExtension.Attributes, complexExtension.AnyAttribute, XmlSchemaDerivationMethod.Extension);
754
755             XmlSchemaParticle baseParticle = baseType.ContentTypeParticle;
756             XmlSchemaParticle extendedParticle = CannonicalizeParticle(complexExtension.Particle, true, true);
757             if (baseParticle != XmlSchemaParticle.Empty) {
758                 if (extendedParticle != XmlSchemaParticle.Empty) {
759                     XmlSchemaSequence compiledParticle = new XmlSchemaSequence();
760                     compiledParticle.Items.Add(baseParticle);
761                     compiledParticle.Items.Add(extendedParticle);
762                     complexType.SetContentTypeParticle(CompileContentTypeParticle(compiledParticle, false));
763                 }
764                 else {
765                     complexType.SetContentTypeParticle(baseParticle);
766                 }
767                 XmlSchemaContentType contentType = GetSchemaContentType(complexType, complexContent, extendedParticle);
768                 if (contentType == XmlSchemaContentType.Empty) { //Derived content type is empty, Get ContentType from base
769                     contentType = baseType.ContentType;
770                 }
771                 complexType.SetContentType(contentType);
772                 if (complexType.ContentType != baseType.ContentType) {
773                     SendValidationEvent(Res.Sch_DifContentType, complexType);
774                 }
775             }
776             else {
777                 complexType.SetContentTypeParticle(extendedParticle);
778                 complexType.SetContentType(GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle));
779             }
780             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Extension);
781         }
782
783         private void CompileComplexContentRestriction(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaComplexContentRestriction complexRestriction) {
784             XmlSchemaComplexType baseType = null;
785             if (complexType.Redefined != null && complexRestriction.BaseTypeName == complexType.Redefined.QualifiedName) {
786                 baseType = (XmlSchemaComplexType)complexType.Redefined;
787                 CompileComplexType(baseType);
788             }
789             else {
790                 baseType = GetComplexType(complexRestriction.BaseTypeName);
791                 if (baseType == null) {
792                     SendValidationEvent(Res.Sch_UndefBaseRestriction, complexRestriction.BaseTypeName.ToString(), complexRestriction);   
793                     return;
794                 }
795             } 
796             if (baseType != null && baseType.ElementDecl != null) {
797                 if (baseType.ContentType == XmlSchemaContentType.TextOnly) {
798                     SendValidationEvent(Res.Sch_NotComplexContent, complexType);
799                     return;
800                 }
801             }
802             complexType.SetBaseSchemaType(baseType);
803             if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
804                 SendValidationEvent(Res.Sch_BaseFinalRestriction, complexType);
805             }
806             CompileLocalAttributes(baseType, complexType, complexRestriction.Attributes, complexRestriction.AnyAttribute, XmlSchemaDerivationMethod.Restriction);
807             
808             complexType.SetContentTypeParticle(CompileContentTypeParticle(complexRestriction.Particle, true));
809             complexType.SetContentType(GetSchemaContentType(complexType, complexContent, complexType.ContentTypeParticle));
810             if (complexType.ContentType == XmlSchemaContentType.Empty) {
811                 if (baseType.ElementDecl != null) {
812                     Debug.Assert(baseType.ElementDecl.ContentValidator != null);
813                 }
814                 if (baseType.ElementDecl != null && !baseType.ElementDecl.ContentValidator.IsEmptiable) {
815                     SendValidationEvent(Res.Sch_InvalidContentRestriction, complexType);
816                 }
817             }
818             complexType.SetDerivedBy(XmlSchemaDerivationMethod.Restriction);
819         }
820
821         private void CheckParticleDerivation(XmlSchemaComplexType complexType) {
822             XmlSchemaComplexType baseType = complexType.BaseXmlSchemaType as XmlSchemaComplexType;
823             if (baseType != null && baseType != XmlSchemaComplexType.AnyType && complexType.DerivedBy == XmlSchemaDerivationMethod.Restriction) {
824                 if (!IsValidRestriction(complexType.ContentTypeParticle, baseType.ContentTypeParticle)) {
825 #if DEBUG
826                     if(complexType.ContentTypeParticle != null && baseType.ContentTypeParticle != null) {
827                         string position = string.Empty;
828                         if (complexType.SourceUri != null) {
829                             position = " in " + complexType.SourceUri + "(" + complexType.LineNumber + ", " + complexType.LinePosition + ")";
830                         }
831                         Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType content restriction" + position);
832                         Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpContentModel(baseType.ContentTypeParticle));
833                         Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpContentModel(complexType.ContentTypeParticle));
834                     }
835 #endif
836                     SendValidationEvent(Res.Sch_InvalidParticleRestriction, complexType);
837                 }
838             }
839         }
840
841         private XmlSchemaParticle CompileContentTypeParticle(XmlSchemaParticle particle, bool substitution) {
842             XmlSchemaParticle ctp = CannonicalizeParticle(particle, true, substitution);
843             XmlSchemaChoice choice = ctp as XmlSchemaChoice;
844             if (choice != null && choice.Items.Count == 0) {
845                 if (choice.MinOccurs != decimal.Zero) {
846                     SendValidationEvent(Res.Sch_EmptyChoice, choice, XmlSeverityType.Warning);
847                 }
848                 return XmlSchemaParticle.Empty;
849             }
850             return ctp;
851         }
852
853         private XmlSchemaParticle CannonicalizeParticle(XmlSchemaParticle particle, bool root, bool substitution) {
854             if (particle == null || particle.IsEmpty) {
855                 return XmlSchemaParticle.Empty;
856             }
857             else if (particle is XmlSchemaElement) {
858                 return CannonicalizeElement((XmlSchemaElement)particle, substitution);
859             }
860             else if (particle is XmlSchemaGroupRef) {
861                 return CannonicalizeGroupRef((XmlSchemaGroupRef)particle, root, substitution);
862             }
863             else if (particle is XmlSchemaAll) {
864                 return CannonicalizeAll((XmlSchemaAll)particle, root, substitution);
865             }
866             else if (particle is XmlSchemaChoice) {
867                 return CannonicalizeChoice((XmlSchemaChoice)particle, root, substitution);
868             }
869             else if (particle is XmlSchemaSequence) {
870                 return CannonicalizeSequence((XmlSchemaSequence)particle, root, substitution);
871             }
872             else {
873                 return particle;
874             }
875         }
876
877         private XmlSchemaParticle CannonicalizeElement(XmlSchemaElement element, bool substitution) {
878             if (!element.RefName.IsEmpty && substitution && (element.BlockResolved & XmlSchemaDerivationMethod.Substitution) == 0) {
879                 XmlSchemaSubstitutionGroupV1Compat substitutionGroup = (XmlSchemaSubstitutionGroupV1Compat)examplars[element.QualifiedName];
880                 if (substitutionGroup == null) {
881                     return element;
882                 }
883                 else {
884                     XmlSchemaChoice choice = (XmlSchemaChoice)substitutionGroup.Choice.Clone(); 
885                     choice.MinOccurs = element.MinOccurs;
886                     choice.MaxOccurs = element.MaxOccurs;
887                     return choice;
888                 }
889             }
890             else {
891                 return element;
892             }
893         }
894
895         private XmlSchemaParticle CannonicalizeGroupRef(XmlSchemaGroupRef groupRef, bool root,  bool substitution) {
896             XmlSchemaGroup group;
897             if (groupRef.Redefined != null) {
898                 group = groupRef.Redefined;
899             }
900             else {
901                 group = (XmlSchemaGroup)this.schema.Groups[groupRef.RefName];
902             }
903             if (group == null) {
904                 SendValidationEvent(Res.Sch_UndefGroupRef, groupRef.RefName.ToString(), groupRef);
905                 return XmlSchemaParticle.Empty;
906             }
907             if (group.CanonicalParticle == null) {
908                 CompileGroup(group);
909             }
910             if (group.CanonicalParticle == XmlSchemaParticle.Empty) {
911                 return XmlSchemaParticle.Empty;
912             }
913             XmlSchemaGroupBase groupBase = (XmlSchemaGroupBase)group.CanonicalParticle;
914             if (groupBase is XmlSchemaAll) {
915                 if (!root) {
916                     SendValidationEvent(Res.Sch_AllRefNotRoot, "", groupRef);
917                     return XmlSchemaParticle.Empty;
918                 }
919                 if (groupRef.MinOccurs != decimal.One || groupRef.MaxOccurs != decimal.One) {
920                     SendValidationEvent(Res.Sch_AllRefMinMax, groupRef);
921                     return XmlSchemaParticle.Empty;
922                 }
923             }
924             else if (groupBase is XmlSchemaChoice && groupBase.Items.Count == 0) {
925                 if (groupRef.MinOccurs != decimal.Zero) {
926                     SendValidationEvent(Res.Sch_EmptyChoice, groupRef, XmlSeverityType.Warning);
927                 }
928                 return XmlSchemaParticle.Empty;
929             }
930             XmlSchemaGroupBase groupRefBase = (
931                 (groupBase is XmlSchemaSequence) ? (XmlSchemaGroupBase)new XmlSchemaSequence() :
932                 (groupBase is XmlSchemaChoice)   ? (XmlSchemaGroupBase)new XmlSchemaChoice() :
933                                                    (XmlSchemaGroupBase)new XmlSchemaAll()
934             );
935             groupRefBase.MinOccurs = groupRef.MinOccurs;
936             groupRefBase.MaxOccurs = groupRef.MaxOccurs;
937             for (int i = 0; i < groupBase.Items.Count; ++i) {
938                 groupRefBase.Items.Add((XmlSchemaParticle)groupBase.Items[i]);
939             }
940             groupRef.SetParticle(groupRefBase);
941             return groupRefBase;
942         }
943
944         private XmlSchemaParticle CannonicalizeAll(XmlSchemaAll all, bool root, bool substitution) {
945             if (all.Items.Count > 0) {
946                 XmlSchemaAll newAll = new XmlSchemaAll();
947                 newAll.MinOccurs = all.MinOccurs;
948                 newAll.MaxOccurs = all.MaxOccurs;
949                 newAll.SourceUri = all.SourceUri; // all is the only one that might need and error message
950                 newAll.LineNumber = all.LineNumber;
951                 newAll.LinePosition = all.LinePosition;
952                 for (int i = 0; i < all.Items.Count; ++i) {
953                     XmlSchemaParticle p = CannonicalizeParticle((XmlSchemaElement)all.Items[i], false, substitution);
954                     if (p != XmlSchemaParticle.Empty) {
955                         newAll.Items.Add(p);
956                     }
957                 }
958                 all = newAll;
959             }
960             if (all.Items.Count == 0) {
961                 return XmlSchemaParticle.Empty;
962             }
963             else if (root && all.Items.Count == 1) {
964                 XmlSchemaSequence newSequence = new XmlSchemaSequence();
965                 newSequence.MinOccurs = all.MinOccurs;
966                 newSequence.MaxOccurs = all.MaxOccurs;
967                 newSequence.Items.Add((XmlSchemaParticle)all.Items[0]);
968                 return newSequence;
969             }
970             else if (!root && all.Items.Count == 1 && all.MinOccurs == decimal.One && all.MaxOccurs == decimal.One) {
971                 return (XmlSchemaParticle)all.Items[0];
972             }
973             else if (!root) {
974                 SendValidationEvent(Res.Sch_NotAllAlone, all);
975                 return XmlSchemaParticle.Empty;
976             }
977             else {
978                 return all;
979             }
980         }
981
982         private XmlSchemaParticle CannonicalizeChoice(XmlSchemaChoice choice, bool root, bool substitution) {
983             XmlSchemaChoice oldChoice = choice;
984             if (choice.Items.Count > 0) {
985                 XmlSchemaChoice newChoice = new XmlSchemaChoice();
986                 newChoice.MinOccurs = choice.MinOccurs;
987                 newChoice.MaxOccurs = choice.MaxOccurs;
988                 for (int i = 0; i < choice.Items.Count; ++i) {
989                     XmlSchemaParticle p1 = CannonicalizeParticle((XmlSchemaParticle)choice.Items[i], false, substitution);
990                     if (p1 != XmlSchemaParticle.Empty) {
991                         if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaChoice) {
992                             XmlSchemaChoice particleChoice = (XmlSchemaChoice)p1;
993                             for (int j = 0; j < particleChoice.Items.Count; ++j) {
994                                 newChoice.Items.Add(particleChoice.Items[j]);
995                             }
996                         }
997                         else {
998                             newChoice.Items.Add(p1);
999                         }
1000                     }
1001                 }
1002                 choice = newChoice;
1003             }
1004             if (!root && choice.Items.Count == 0) {
1005                 if (choice.MinOccurs != decimal.Zero) {
1006                     SendValidationEvent(Res.Sch_EmptyChoice, oldChoice, XmlSeverityType.Warning);
1007                 }
1008                 return XmlSchemaParticle.Empty;
1009             }
1010             else if (!root && choice.Items.Count == 1 && choice.MinOccurs == decimal.One && choice.MaxOccurs == decimal.One) {
1011                 return (XmlSchemaParticle)choice.Items[0];
1012             }
1013             else {
1014                 return choice;
1015             }
1016         }
1017
1018         private XmlSchemaParticle CannonicalizeSequence(XmlSchemaSequence sequence, bool root, bool substitution) {
1019             if (sequence.Items.Count > 0) {
1020                 XmlSchemaSequence newSequence = new XmlSchemaSequence();
1021                 newSequence.MinOccurs = sequence.MinOccurs;
1022                 newSequence.MaxOccurs = sequence.MaxOccurs;
1023                 for (int i = 0; i < sequence.Items.Count; ++i) {
1024                     XmlSchemaParticle p1 = CannonicalizeParticle(( XmlSchemaParticle)sequence.Items[i], false, substitution);
1025                     if (p1 != XmlSchemaParticle.Empty) {
1026                         if (p1.MinOccurs == decimal.One && p1.MaxOccurs == decimal.One && p1 is XmlSchemaSequence) {
1027                             XmlSchemaSequence particleSequence = (XmlSchemaSequence)p1;
1028                             for (int j = 0; j < particleSequence.Items.Count; ++j) {
1029                                 newSequence.Items.Add(particleSequence.Items[j]);
1030                             }
1031                         }
1032                         else {
1033                             newSequence.Items.Add(p1);
1034                         }
1035                     }
1036                 }
1037                 sequence = newSequence;
1038             }
1039             if (sequence.Items.Count == 0) {
1040                 return XmlSchemaParticle.Empty;
1041             }
1042             else if (!root && sequence.Items.Count == 1 && sequence.MinOccurs == decimal.One && sequence.MaxOccurs == decimal.One) {
1043                 return (XmlSchemaParticle)sequence.Items[0];
1044             }
1045             else {
1046                 return sequence;
1047             }
1048         }
1049
1050         private bool IsValidRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1051             if (derivedParticle == baseParticle) {
1052                 return true;
1053             }
1054             else if (derivedParticle == null || derivedParticle == XmlSchemaParticle.Empty) {
1055                 return IsParticleEmptiable(baseParticle);
1056             }
1057             else if (baseParticle == null || baseParticle == XmlSchemaParticle.Empty) {
1058                 return false;
1059             }
1060             if (baseParticle is XmlSchemaElement) {
1061                 if (derivedParticle is XmlSchemaElement) {
1062                     return IsElementFromElement((XmlSchemaElement)derivedParticle, (XmlSchemaElement)baseParticle);
1063                 }
1064                 else {
1065                     return false;
1066                 }
1067             }
1068             else if (baseParticle is XmlSchemaAny) {
1069                 if (derivedParticle is XmlSchemaElement) {
1070                     return IsElementFromAny((XmlSchemaElement)derivedParticle, (XmlSchemaAny)baseParticle);
1071                 }
1072                 else if (derivedParticle is XmlSchemaAny) {
1073                     return IsAnyFromAny((XmlSchemaAny)derivedParticle, (XmlSchemaAny)baseParticle);
1074                 }
1075                 else {
1076                     return IsGroupBaseFromAny((XmlSchemaGroupBase)derivedParticle, (XmlSchemaAny)baseParticle);
1077                 }
1078             }
1079             else if (baseParticle is XmlSchemaAll) {
1080                 if (derivedParticle is XmlSchemaElement) {
1081                     return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1082                 }
1083                 else if (derivedParticle is XmlSchemaAll) {
1084                     return IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1085                 }
1086                 else if (derivedParticle is XmlSchemaSequence) {
1087                     return IsSequenceFromAll((XmlSchemaSequence)derivedParticle, (XmlSchemaAll)baseParticle);
1088                 }
1089             }
1090             else if (baseParticle is XmlSchemaChoice ) {
1091                 if (derivedParticle is XmlSchemaElement) {
1092                     return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle, false);
1093                 }
1094                 else if (derivedParticle is XmlSchemaChoice) {
1095                     return IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, false);
1096                 }
1097                 else if (derivedParticle is XmlSchemaSequence) {
1098                     return IsSequenceFromChoice((XmlSchemaSequence)derivedParticle, (XmlSchemaChoice)baseParticle);
1099                 }
1100             }
1101             else if (baseParticle is XmlSchemaSequence) {
1102                 if (derivedParticle is XmlSchemaElement) {
1103                     return IsElementFromGroupBase((XmlSchemaElement)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1104                 }
1105                 else if (derivedParticle is XmlSchemaSequence) {
1106                     return IsGroupBaseFromGroupBase((XmlSchemaGroupBase)derivedParticle, (XmlSchemaGroupBase)baseParticle, true);
1107                 }
1108             }
1109             else {
1110                 Debug.Assert(false);
1111             }
1112
1113             return false;
1114         }
1115
1116         private bool IsElementFromElement(XmlSchemaElement derivedElement, XmlSchemaElement baseElement) {
1117             return  (derivedElement.QualifiedName == baseElement.QualifiedName) &&
1118                     (derivedElement.IsNillable == baseElement.IsNillable) &&
1119                     IsValidOccurrenceRangeRestriction(derivedElement, baseElement) &&
1120                     (baseElement.FixedValue == null || baseElement.FixedValue == derivedElement.FixedValue) &&
1121                     ((derivedElement.BlockResolved | baseElement.BlockResolved) ==  derivedElement.BlockResolved) &&
1122                     (derivedElement.ElementSchemaType != null) && (baseElement.ElementSchemaType != null) &&
1123                     XmlSchemaType.IsDerivedFrom(derivedElement.ElementSchemaType, baseElement.ElementSchemaType, ~XmlSchemaDerivationMethod.Restriction);
1124         }
1125
1126         private bool IsElementFromAny(XmlSchemaElement derivedElement, XmlSchemaAny baseAny) {
1127             return baseAny.Allows(derivedElement.QualifiedName) &&
1128                 IsValidOccurrenceRangeRestriction(derivedElement, baseAny);
1129         }
1130
1131         private bool IsAnyFromAny(XmlSchemaAny derivedAny, XmlSchemaAny baseAny) {
1132             return IsValidOccurrenceRangeRestriction(derivedAny, baseAny) &&
1133                 NamespaceList.IsSubset(derivedAny.NamespaceList, baseAny.NamespaceList);
1134         }
1135
1136         private bool IsGroupBaseFromAny(XmlSchemaGroupBase derivedGroupBase, XmlSchemaAny baseAny) {
1137             decimal minOccurs, maxOccurs;
1138             CalculateEffectiveTotalRange(derivedGroupBase, out minOccurs, out maxOccurs);
1139             if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseAny.MinOccurs, baseAny.MaxOccurs)) {
1140                 return false;
1141             }
1142             // eliminate occurrance range check
1143             string minOccursAny = baseAny.MinOccursString;
1144             baseAny.MinOccurs = decimal.Zero;
1145
1146             for (int i = 0; i < derivedGroupBase.Items.Count; ++i) {
1147                 if (!IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[i], baseAny)) {
1148                     baseAny.MinOccursString = minOccursAny;
1149                     return false;
1150                 }
1151             }
1152             baseAny.MinOccursString = minOccursAny;
1153             return true;
1154         }
1155
1156         private bool IsElementFromGroupBase(XmlSchemaElement derivedElement, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) {
1157             bool isMatched = false;
1158             for (int i = 0; i < baseGroupBase.Items.Count; ++i) {
1159                 XmlSchemaParticle baseParticle = (XmlSchemaParticle)baseGroupBase.Items[i];
1160                 if (!isMatched) {
1161                     string minOccursElement = baseParticle.MinOccursString;
1162                     string maxOccursElement = baseParticle.MaxOccursString;
1163                     baseParticle.MinOccurs *= baseGroupBase.MinOccurs;
1164                     if ( baseParticle.MaxOccurs != decimal.MaxValue) {
1165                         if (baseGroupBase.MaxOccurs == decimal.MaxValue)
1166                              baseParticle.MaxOccurs = decimal.MaxValue;
1167                         else 
1168                              baseParticle.MaxOccurs *= baseGroupBase.MaxOccurs;
1169                     }
1170                     isMatched  = IsValidRestriction(derivedElement, baseParticle);
1171                     baseParticle.MinOccursString = minOccursElement;
1172                     baseParticle.MaxOccursString = maxOccursElement;
1173                 }
1174                 else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
1175                     return false;
1176                 }
1177             }
1178             return isMatched;
1179         }
1180
1181         private bool IsGroupBaseFromGroupBase(XmlSchemaGroupBase derivedGroupBase, XmlSchemaGroupBase baseGroupBase,  bool skipEmptableOnly) {
1182             if (!IsValidOccurrenceRangeRestriction(derivedGroupBase, baseGroupBase) || derivedGroupBase.Items.Count > baseGroupBase.Items.Count) {
1183                 return false;
1184             }
1185             int count = 0;
1186             for (int i = 0; i < baseGroupBase.Items.Count; ++i) {
1187                 XmlSchemaParticle baseParticle = (XmlSchemaParticle)baseGroupBase.Items[i];
1188                 if ((count < derivedGroupBase.Items.Count) && IsValidRestriction((XmlSchemaParticle)derivedGroupBase.Items[count], baseParticle)) {
1189                     count ++;
1190                 }
1191                 else if (skipEmptableOnly && !IsParticleEmptiable(baseParticle)) {
1192                     return false;
1193                 }
1194             }
1195             if (count < derivedGroupBase.Items.Count) {
1196                 return false;
1197             }
1198             return true;
1199         }
1200
1201         private bool IsSequenceFromAll(XmlSchemaSequence derivedSequence, XmlSchemaAll baseAll) {
1202             if (!IsValidOccurrenceRangeRestriction(derivedSequence, baseAll) || derivedSequence.Items.Count > baseAll.Items.Count) {
1203                 return false;
1204             }
1205             BitSet map = new BitSet(baseAll.Items.Count);
1206             for (int j = 0; j < derivedSequence.Items.Count; ++j) {
1207                 int i = GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[j], baseAll.Items);
1208                 if (i >= 0) {
1209                     if (map[i]) {
1210                         return false;
1211                     }
1212                     else {
1213                         map.Set(i);
1214                     }
1215                 }
1216                 else {
1217                     return false;
1218                 }
1219             }
1220             for (int i = 0; i < baseAll.Items.Count; i++) {
1221                 if (!map[i] && !IsParticleEmptiable((XmlSchemaParticle)baseAll.Items[i])) {
1222                     return false;
1223                 }
1224             }
1225             return true;
1226         }
1227
1228         private bool IsSequenceFromChoice(XmlSchemaSequence derivedSequence, XmlSchemaChoice baseChoice) {
1229             decimal minOccurs, maxOccurs;
1230             CalculateSequenceRange(derivedSequence, out minOccurs, out maxOccurs);
1231             if (!IsValidOccurrenceRangeRestriction(minOccurs, maxOccurs, baseChoice.MinOccurs, baseChoice.MaxOccurs) || derivedSequence.Items.Count > baseChoice.Items.Count) {
1232                 return false;
1233             }
1234             for (int i = 0; i < derivedSequence.Items.Count; ++i) {
1235                 if (GetMappingParticle((XmlSchemaParticle)derivedSequence.Items[i], baseChoice.Items) < 0)
1236                     return false;
1237             }
1238             return true;
1239         }
1240
1241         private void CalculateSequenceRange(XmlSchemaSequence sequence, out decimal minOccurs, out decimal maxOccurs) {
1242             minOccurs = decimal.Zero; maxOccurs = decimal.Zero;
1243             for (int i = 0; i < sequence.Items.Count; ++i) {
1244                 XmlSchemaParticle p = (XmlSchemaParticle)sequence.Items[i];
1245
1246                 minOccurs += p.MinOccurs;
1247                 if (p.MaxOccurs == decimal.MaxValue)
1248                     maxOccurs = decimal.MaxValue;
1249                 else if (maxOccurs != decimal.MaxValue)
1250                     maxOccurs += p.MaxOccurs;
1251             }
1252             minOccurs *= sequence.MinOccurs;
1253             if (sequence.MaxOccurs == decimal.MaxValue) {
1254                 maxOccurs = decimal.MaxValue;
1255             }
1256             else if (maxOccurs != decimal.MaxValue) {
1257                 maxOccurs *= sequence.MaxOccurs;
1258             }
1259         }
1260
1261         private bool IsValidOccurrenceRangeRestriction(XmlSchemaParticle derivedParticle, XmlSchemaParticle baseParticle) {
1262             return IsValidOccurrenceRangeRestriction(derivedParticle.MinOccurs, derivedParticle.MaxOccurs, baseParticle.MinOccurs, baseParticle.MaxOccurs);
1263         }
1264
1265         private bool IsValidOccurrenceRangeRestriction(decimal minOccurs, decimal maxOccurs, decimal baseMinOccurs, decimal baseMaxOccurs) {
1266             return (baseMinOccurs <= minOccurs) && (maxOccurs <= baseMaxOccurs);
1267         }
1268
1269         private int GetMappingParticle(XmlSchemaParticle particle, XmlSchemaObjectCollection collection) {
1270             for (int i = 0; i < collection.Count; i++) {
1271                 if (IsValidRestriction(particle, (XmlSchemaParticle)collection[i]))
1272                     return i;
1273             }
1274             return -1;
1275         }
1276
1277         private bool IsParticleEmptiable(XmlSchemaParticle particle) {
1278             decimal minOccurs, maxOccurs;
1279             CalculateEffectiveTotalRange(particle, out minOccurs, out maxOccurs);
1280             return minOccurs == decimal.Zero;
1281         }
1282
1283         private void CalculateEffectiveTotalRange(XmlSchemaParticle particle, out decimal minOccurs, out decimal maxOccurs) {
1284             if (particle is XmlSchemaElement || particle is XmlSchemaAny) {
1285                 minOccurs = particle.MinOccurs;
1286                 maxOccurs = particle.MaxOccurs;
1287             }
1288             else if (particle is XmlSchemaChoice) {
1289                 if (((XmlSchemaChoice)particle).Items.Count == 0) {
1290                     minOccurs = maxOccurs = decimal.Zero;
1291                 }
1292                 else {
1293                     minOccurs = decimal.MaxValue;
1294                     maxOccurs = decimal.Zero;
1295                     XmlSchemaChoice choice = (XmlSchemaChoice) particle;
1296                     for (int i = 0; i < choice.Items.Count; ++i) {
1297                         decimal min, max;
1298                         CalculateEffectiveTotalRange((XmlSchemaParticle) choice.Items[i], out min, out max);
1299                         if (min < minOccurs) {
1300                             minOccurs = min;
1301                         }
1302                         if (max > maxOccurs) {
1303                             maxOccurs = max;
1304                         }
1305                     }
1306                     minOccurs *= particle.MinOccurs;
1307                     if (maxOccurs != decimal.MaxValue) {
1308                         if (particle.MaxOccurs == decimal.MaxValue)
1309                             maxOccurs = decimal.MaxValue;
1310                         else 
1311                             maxOccurs *= particle.MaxOccurs;
1312                     }
1313                 }
1314             }
1315             else {
1316                 XmlSchemaObjectCollection collection = ((XmlSchemaGroupBase)particle).Items;
1317                 if (collection.Count == 0) {
1318                     minOccurs = maxOccurs = decimal.Zero;
1319                 }
1320                 else {
1321                     minOccurs = 0;
1322                     maxOccurs = 0;
1323                     for (int i = 0; i < collection.Count; ++i) {
1324                         decimal min, max;
1325                         CalculateEffectiveTotalRange((XmlSchemaParticle)collection[i], out min, out max);
1326                         minOccurs += min;
1327                         if (maxOccurs != decimal.MaxValue) {
1328                             if (max == decimal.MaxValue)
1329                                 maxOccurs = decimal.MaxValue;
1330                             else 
1331                                 maxOccurs += max;
1332                         }
1333                     }
1334                     minOccurs *= particle.MinOccurs;
1335                     if (maxOccurs != decimal.MaxValue) {
1336                         if (particle.MaxOccurs == decimal.MaxValue)
1337                             maxOccurs = decimal.MaxValue;
1338                         else 
1339                             maxOccurs *= particle.MaxOccurs;
1340                     }
1341                 }
1342             }
1343         }
1344
1345         private void PushComplexType(XmlSchemaComplexType complexType) {
1346             this.complexTypeStack.Push(complexType);
1347         }
1348
1349         private XmlSchemaContentType GetSchemaContentType(XmlSchemaComplexType complexType, XmlSchemaComplexContent complexContent, XmlSchemaParticle particle) {
1350             if ((complexContent != null && complexContent.IsMixed) ||
1351                 (complexContent == null && complexType.IsMixed)) {
1352                 return XmlSchemaContentType.Mixed;      
1353             }
1354             else if (particle != null && !particle.IsEmpty) {
1355                 return XmlSchemaContentType.ElementOnly;
1356             }
1357             else {                            
1358                 return XmlSchemaContentType.Empty;                            
1359             }
1360         }
1361
1362         private void CompileAttributeGroup(XmlSchemaAttributeGroup attributeGroup) {
1363             if (attributeGroup.IsProcessing) {
1364                 SendValidationEvent(Res.Sch_AttributeGroupCircularRef, attributeGroup);
1365                 return;
1366             }
1367             if (attributeGroup.AttributeUses.Count > 0) {// already checked
1368                 return;
1369             }
1370             attributeGroup.IsProcessing = true;
1371             XmlSchemaAnyAttribute anyAttribute = attributeGroup.AnyAttribute;
1372             for (int i = 0; i < attributeGroup.Attributes.Count; ++i) {
1373                 XmlSchemaAttribute attribute = attributeGroup.Attributes[i] as XmlSchemaAttribute;
1374                 if (attribute != null) {
1375                     if (attribute.Use != XmlSchemaUse.Prohibited) {
1376                         CompileAttribute(attribute);
1377                     }
1378                     if (attributeGroup.AttributeUses[attribute.QualifiedName] == null) {
1379                         attributeGroup.AttributeUses.Add(attribute.QualifiedName, attribute);
1380                     }
1381                     else  {
1382                         SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
1383                     }
1384                 }
1385                 else { // XmlSchemaAttributeGroupRef
1386                     XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)attributeGroup.Attributes[i];
1387                     XmlSchemaAttributeGroup attributeGroupResolved;
1388                     if (attributeGroup.Redefined != null && attributeGroupRef.RefName == attributeGroup.Redefined.QualifiedName) {
1389                         attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroup.Redefined;
1390                     }
1391                     else {
1392                         attributeGroupResolved = (XmlSchemaAttributeGroup)this.schema.AttributeGroups[attributeGroupRef.RefName];
1393                     }
1394                     if (attributeGroupResolved != null) {
1395                         CompileAttributeGroup(attributeGroupResolved);
1396                         foreach (XmlSchemaAttribute attributeValue in attributeGroupResolved.AttributeUses.Values) {
1397                             if (attributeGroup.AttributeUses[attributeValue.QualifiedName] == null) {
1398                                 attributeGroup.AttributeUses.Add(attributeValue.QualifiedName, attributeValue);
1399                             }
1400                             else {
1401                                 SendValidationEvent(Res.Sch_DupAttributeUse, attributeValue.QualifiedName.ToString(), attributeValue);
1402                             }
1403                         }
1404                         anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroupResolved.AttributeWildcard);
1405                     }
1406                     else {
1407                         SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
1408                     }
1409                 }
1410             }          
1411             attributeGroup.AttributeWildcard = anyAttribute;
1412             attributeGroup.IsProcessing = false;
1413
1414         }
1415
1416         private void CompileLocalAttributes(XmlSchemaComplexType baseType, XmlSchemaComplexType derivedType, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaDerivationMethod derivedBy) {
1417             XmlSchemaAnyAttribute baseAttributeWildcard = baseType != null ? baseType.AttributeWildcard : null;
1418             for (int i = 0; i < attributes.Count; ++i) {
1419                 XmlSchemaAttribute attribute = attributes[i] as XmlSchemaAttribute;
1420                 if (attribute != null) {
1421                     if (attribute.Use != XmlSchemaUse.Prohibited) {
1422                         CompileAttribute(attribute);
1423                     }
1424                     if (attribute.Use != XmlSchemaUse.Prohibited || 
1425                         (attribute.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
1426
1427                         if (derivedType.AttributeUses[attribute.QualifiedName] == null) {
1428                             derivedType.AttributeUses.Add(attribute.QualifiedName, attribute);
1429                         }
1430                         else  {
1431                             SendValidationEvent(Res.Sch_DupAttributeUse, attribute.QualifiedName.ToString(), attribute);
1432                         }
1433                     }
1434                     else {
1435                         SendValidationEvent(Res.Sch_AttributeIgnored, attribute.QualifiedName.ToString(), attribute, XmlSeverityType.Warning);
1436                     }
1437
1438                 }
1439                 else { // is XmlSchemaAttributeGroupRef
1440                     XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)attributes[i];
1441                     XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)this.schema.AttributeGroups[attributeGroupRef.RefName];
1442                     if (attributeGroup != null) {
1443                         CompileAttributeGroup(attributeGroup);
1444                         foreach (XmlSchemaAttribute attributeValue in attributeGroup.AttributeUses.Values) {
1445                           if (attributeValue.Use != XmlSchemaUse.Prohibited || 
1446                              (attributeValue.Use == XmlSchemaUse.Prohibited && derivedBy == XmlSchemaDerivationMethod.Restriction && baseType != XmlSchemaComplexType.AnyType)) {
1447                             if (derivedType.AttributeUses[attributeValue.QualifiedName] == null) {
1448                                 derivedType.AttributeUses.Add(attributeValue.QualifiedName, attributeValue);
1449                             }
1450                             else {
1451                                 SendValidationEvent(Res.Sch_DupAttributeUse, attributeValue.QualifiedName.ToString(), attributeGroupRef);
1452                             }
1453                           }
1454                           else {
1455                             SendValidationEvent(Res.Sch_AttributeIgnored, attributeValue.QualifiedName.ToString(), attributeValue, XmlSeverityType.Warning);
1456                           }
1457
1458                         }
1459                         anyAttribute = CompileAnyAttributeIntersection(anyAttribute, attributeGroup.AttributeWildcard);
1460                     }
1461                     else {
1462                         SendValidationEvent(Res.Sch_UndefAttributeGroupRef, attributeGroupRef.RefName.ToString(), attributeGroupRef);
1463                     }
1464                 }
1465             }
1466
1467             // check derivation rules
1468             if (baseType != null) {
1469                 if (derivedBy == XmlSchemaDerivationMethod.Extension) {
1470                     derivedType.SetAttributeWildcard(CompileAnyAttributeUnion(anyAttribute, baseAttributeWildcard));
1471                     foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
1472                         XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
1473                         if (attribute != null) {
1474                             Debug.Assert(attribute.Use != XmlSchemaUse.Prohibited);
1475                             if (attribute.AttributeSchemaType != attributeBase.AttributeSchemaType || attributeBase.Use == XmlSchemaUse.Prohibited) {
1476                                 SendValidationEvent(Res.Sch_InvalidAttributeExtension, attribute);
1477                             }
1478                         }
1479                         else {
1480                             derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
1481                         }
1482                     }
1483                 }
1484                 else {  // derivedBy == XmlSchemaDerivationMethod.Restriction
1485                     // Schema Component Constraint: Derivation Valid (Restriction, Complex)
1486                     if ((anyAttribute != null) && (baseAttributeWildcard == null || !XmlSchemaAnyAttribute.IsSubset(anyAttribute, baseAttributeWildcard))) {
1487                         SendValidationEvent(Res.Sch_InvalidAnyAttributeRestriction, derivedType);
1488                     }
1489                     else {
1490                         derivedType.SetAttributeWildcard(anyAttribute); //complete wildcard
1491                     }
1492
1493                     // Add form the base
1494                     foreach(XmlSchemaAttribute attributeBase in baseType.AttributeUses.Values) {
1495                         XmlSchemaAttribute attribute = (XmlSchemaAttribute)derivedType.AttributeUses[attributeBase.QualifiedName];
1496                         if (attribute == null) {
1497                             derivedType.AttributeUses.Add(attributeBase.QualifiedName, attributeBase);
1498                         } 
1499                         else {
1500                             if (attributeBase.Use == XmlSchemaUse.Prohibited && attribute.Use != XmlSchemaUse.Prohibited) {
1501 #if DEBUG
1502                                 string position = string.Empty;
1503                                 if (derivedType.SourceUri != null) {
1504                                     position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
1505                                 }
1506                                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
1507                                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
1508                                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard));
1509 #endif
1510                                 SendValidationEvent(Res.Sch_AttributeRestrictionProhibited, attribute);
1511                             } 
1512                             else if (attribute.Use == XmlSchemaUse.Prohibited) {
1513                                 continue;
1514                             } 
1515                             else if (attributeBase.AttributeSchemaType == null || attribute.AttributeSchemaType == null || !XmlSchemaType.IsDerivedFrom(attribute.AttributeSchemaType, attributeBase.AttributeSchemaType, XmlSchemaDerivationMethod.Empty)) {
1516                                 SendValidationEvent(Res.Sch_AttributeRestrictionInvalid, attribute);
1517                             }
1518                         }
1519                     }
1520
1521                     // Check additional ones are valid restriction of base's wildcard
1522                     foreach(XmlSchemaAttribute attribute in derivedType.AttributeUses.Values) {
1523                         XmlSchemaAttribute attributeBase = (XmlSchemaAttribute)baseType.AttributeUses[attribute.QualifiedName];
1524                         if (attributeBase != null) {
1525                             continue;
1526                         }
1527                         if (baseAttributeWildcard == null || !baseAttributeWildcard.Allows(attribute.QualifiedName)) {
1528 #if DEBUG
1529                             string position = string.Empty;
1530                             if (derivedType.SourceUri != null) {
1531                                 position = " in " + derivedType.SourceUri + "(" + derivedType.LineNumber + ", " + derivedType.LinePosition + ")";
1532                             }
1533                             Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "Invalid complexType attributes restriction" + position);
1534                             Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Base    " + DumpAttributes(baseType.AttributeUses, baseType.AttributeWildcard));
1535                             Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, "     Derived " + DumpAttributes(derivedType.AttributeUses, derivedType.AttributeWildcard));
1536 #endif
1537                             SendValidationEvent(Res.Sch_AttributeRestrictionInvalidFromWildcard, attribute);
1538                         }
1539                     }
1540                 }
1541             } 
1542             else {
1543                 derivedType.SetAttributeWildcard(anyAttribute);
1544             }
1545        }
1546
1547
1548 #if DEBUG
1549         private string DumpAttributes(XmlSchemaObjectTable attributeUses, XmlSchemaAnyAttribute attributeWildcard) {
1550             StringBuilder sb = new StringBuilder();
1551             sb.Append("[");
1552             bool first = true;
1553             foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1554                 if (attribute.Use != XmlSchemaUse.Prohibited) {
1555                     if (first) {
1556                         first = false;
1557                     }
1558                     else {
1559                         sb.Append(" ");
1560                     }
1561                     sb.Append(attribute.QualifiedName.Name);       
1562                     if (attribute.Use == XmlSchemaUse.Optional) {
1563                         sb.Append("?");                                                                  
1564                     }
1565                 }
1566             }
1567             if (attributeWildcard != null) {
1568                 if (attributeUses.Count != 0) {
1569                     sb.Append(" ");                                                                  
1570                 }
1571                 sb.Append("<");
1572                 sb.Append(attributeWildcard.NamespaceList.ToString());
1573                 sb.Append(">");
1574             }
1575             sb.Append("] - [");
1576             first = true;
1577             foreach (XmlSchemaAttribute attribute in attributeUses.Values) {
1578                 if (attribute.Use == XmlSchemaUse.Prohibited) {
1579                     if (first) {
1580                         first = false;
1581                     }
1582                     else {
1583                         sb.Append(" ");
1584                     }
1585                     sb.Append(attribute.QualifiedName.Name);       
1586                 }
1587             }
1588             sb.Append("]");
1589             return sb.ToString();
1590         }
1591 #endif
1592
1593         private XmlSchemaAnyAttribute CompileAnyAttributeUnion(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1594             if (a == null) {
1595                 return b;
1596             }
1597             else if (b == null) {
1598                 return a;
1599             }
1600             else {
1601                 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Union(a, b, true); //true for v1Compat
1602                 if (attribute == null) {
1603                     SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1604                 }
1605                 return attribute;
1606             }
1607
1608         }
1609
1610         private XmlSchemaAnyAttribute CompileAnyAttributeIntersection(XmlSchemaAnyAttribute a, XmlSchemaAnyAttribute b) {
1611             if (a == null) {
1612                 return b;
1613             }
1614             else if (b == null) {
1615                 return a;
1616             }
1617             else {
1618                 XmlSchemaAnyAttribute attribute = XmlSchemaAnyAttribute.Intersection(a, b, true); //true for v1Compat
1619                 if (attribute == null) {
1620                     SendValidationEvent(Res.Sch_UnexpressibleAnyAttribute, a);
1621                 }
1622                 return attribute;
1623             }
1624         }
1625
1626          private void CompileAttribute(XmlSchemaAttribute xa) {
1627             if (xa.IsProcessing) {
1628                 SendValidationEvent(Res.Sch_AttributeCircularRef, xa);
1629                 return;
1630             }
1631             if (xa.AttDef != null) { //already compiled?
1632                 return;
1633             }
1634             xa.IsProcessing = true;
1635             SchemaAttDef decl = null;
1636             try {
1637                 if (!xa.RefName.IsEmpty) {
1638                     XmlSchemaAttribute a = (XmlSchemaAttribute)this.schema.Attributes[xa.RefName];
1639                     if (a == null) {
1640                         throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, xa.RefName.ToString(), xa);
1641                     }     
1642                     CompileAttribute(a);
1643                     if (a.AttDef == null) {
1644                         throw new XmlSchemaException(Res.Sch_RefInvalidAttribute, xa.RefName.ToString(), xa);
1645                     }
1646                     decl = a.AttDef.Clone();
1647                     if(decl.Datatype != null) {
1648                         if(a.FixedValue != null) {
1649                             if(xa.DefaultValue != null) {
1650                                 throw new XmlSchemaException(Res.Sch_FixedDefaultInRef, xa.RefName.ToString(), xa);
1651                             }
1652                             else if(xa.FixedValue != null ) {
1653                                 if (xa.FixedValue != a.FixedValue) {
1654                                     throw new XmlSchemaException(Res.Sch_FixedInRef, xa.RefName.ToString(), xa);
1655                                 }
1656                             }
1657                             else {
1658                                 decl.Presence = SchemaDeclBase.Use.Fixed; 
1659                                 decl.DefaultValueRaw = decl.DefaultValueExpanded = a.FixedValue;
1660                                 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
1661                             }
1662                         }
1663                         else if (a.DefaultValue != null) {
1664                             if(xa.DefaultValue == null && xa.FixedValue == null) {
1665                                 decl.Presence = SchemaDeclBase.Use.Default; 
1666                                 decl.DefaultValueRaw = decl.DefaultValueExpanded = a.DefaultValue;
1667                                 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
1668                             }
1669                         }   
1670                     }
1671                     xa.SetAttributeType(a.AttributeSchemaType);
1672                 }
1673                 else {
1674                     decl = new SchemaAttDef(xa.QualifiedName);
1675                     if (xa.SchemaType != null) {
1676                         CompileSimpleType(xa.SchemaType);
1677                         xa.SetAttributeType(xa.SchemaType);
1678                         decl.SchemaType = xa.SchemaType;
1679                         decl.Datatype = xa.SchemaType.Datatype;
1680                     }
1681                     else if (!xa.SchemaTypeName.IsEmpty) {
1682                         XmlSchemaSimpleType simpleType = GetSimpleType(xa.SchemaTypeName);
1683                         if (simpleType != null) {
1684                             xa.SetAttributeType(simpleType);
1685                             decl.Datatype = simpleType.Datatype;
1686                             decl.SchemaType = simpleType;
1687                         }
1688                         else {
1689                             throw new XmlSchemaException(Res.Sch_UndeclaredSimpleType, xa.SchemaTypeName.ToString(), xa);   
1690                         }
1691                     }
1692                     else {
1693                         decl.SchemaType = DatatypeImplementation.AnySimpleType;
1694                         decl.Datatype = DatatypeImplementation.AnySimpleType.Datatype;
1695                         xa.SetAttributeType(DatatypeImplementation.AnySimpleType);
1696                     }
1697                 }
1698                 if (decl.Datatype != null) {
1699                     decl.Datatype.VerifySchemaValid(this.schema.Notations, xa);
1700                 }
1701                 if (xa.DefaultValue != null || xa.FixedValue != null) {
1702                     if (xa.DefaultValue != null) {
1703                         decl.Presence = SchemaDeclBase.Use.Default; 
1704                         decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.DefaultValue;
1705                     }
1706                     else {
1707                         decl.Presence = SchemaDeclBase.Use.Fixed; 
1708                         decl.DefaultValueRaw = decl.DefaultValueExpanded = xa.FixedValue;
1709                     }
1710                     if(decl.Datatype != null) {
1711                         decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xa), true);
1712                     }
1713                 }
1714                 else {
1715                     switch (xa.Use) {
1716                         case XmlSchemaUse.None: 
1717                         case XmlSchemaUse.Optional: 
1718                             decl.Presence = SchemaDeclBase.Use.Implied; 
1719                             break;
1720                         case XmlSchemaUse.Required: 
1721                             decl.Presence = SchemaDeclBase.Use.Required; 
1722                             break;
1723                         case XmlSchemaUse.Prohibited:
1724                             break;
1725                     }
1726                 }
1727                 decl.SchemaAttribute = xa; //So this is available for PSVI
1728                 xa.AttDef = decl;
1729             } 
1730             catch (XmlSchemaException e) {
1731                 if (e.SourceSchemaObject == null) {
1732                     e.SetSource(xa);
1733                 }
1734                 SendValidationEvent(e);
1735                 xa.AttDef = SchemaAttDef.Empty;
1736             } 
1737             finally {
1738                 xa.IsProcessing = false;
1739             }
1740         }
1741
1742         private void CompileIdentityConstraint (XmlSchemaIdentityConstraint xi) { 
1743             if (xi.IsProcessing) {
1744                 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;       
1745                 SendValidationEvent(Res.Sch_IdentityConstraintCircularRef, xi);
1746                 return;
1747             }
1748
1749             if (xi.CompiledConstraint != null) {
1750                 return;
1751             }
1752             
1753             xi.IsProcessing = true;
1754             CompiledIdentityConstraint compic = null;
1755             try {
1756                 SchemaNamespaceManager xnmgr = new SchemaNamespaceManager(xi);
1757                 compic = new CompiledIdentityConstraint(xi, xnmgr);
1758                 if (xi is XmlSchemaKeyref) {
1759                     XmlSchemaIdentityConstraint ic = (XmlSchemaIdentityConstraint)this.schema.IdentityConstraints[((XmlSchemaKeyref)xi).Refer];
1760                     if (ic == null) {
1761                         throw new XmlSchemaException(Res.Sch_UndeclaredIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
1762                     }     
1763                     CompileIdentityConstraint(ic);
1764                     if (ic.CompiledConstraint == null) {
1765                         throw new XmlSchemaException(Res.Sch_RefInvalidIdentityConstraint, ((XmlSchemaKeyref)xi).Refer.ToString(), xi);
1766                     }
1767                     // keyref has the different cardinality with the key it referred
1768                     if (ic.Fields.Count != xi.Fields.Count) {
1769                         throw new XmlSchemaException(Res.Sch_RefInvalidCardin, xi.QualifiedName.ToString(), xi);
1770                     }
1771                     // keyref can only refer to key/unique
1772                     if (ic.CompiledConstraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) {
1773                         throw new XmlSchemaException(Res.Sch_ReftoKeyref, xi.QualifiedName.ToString(), xi);
1774                     }
1775                 }
1776                 xi.CompiledConstraint = compic;
1777             }
1778             catch (XmlSchemaException e) {
1779                 if (e.SourceSchemaObject == null) {
1780                     e.SetSource(xi);
1781                 }
1782                 SendValidationEvent(e);
1783                 xi.CompiledConstraint = CompiledIdentityConstraint.Empty;       
1784                 // empty is better than null here, stop quickly when circle referencing
1785             } 
1786             finally {
1787                 xi.IsProcessing = false;
1788             }
1789
1790         }
1791
1792         private void CompileElement(XmlSchemaElement xe) {
1793             if (xe.IsProcessing) {
1794                 SendValidationEvent(Res.Sch_ElementCircularRef, xe);
1795                 return;
1796             }
1797             if (xe.ElementDecl != null) {
1798                 return;
1799             }
1800             xe.IsProcessing = true;
1801             SchemaElementDecl decl = null;
1802             try {
1803                 if (!xe.RefName.IsEmpty) {
1804                     XmlSchemaElement e = (XmlSchemaElement)this.schema.Elements[xe.RefName];
1805                     if (e == null) {
1806                         throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe);
1807                     }  
1808                     CompileElement(e);
1809                     if (e.ElementDecl == null) {
1810                         throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe);
1811                     }
1812                     xe.SetElementType(e.ElementSchemaType);
1813                     decl = e.ElementDecl.Clone();
1814                 }
1815                 else {
1816                     if (xe.SchemaType != null) {
1817                         xe.SetElementType(xe.SchemaType);
1818                     }
1819                     else if (!xe.SchemaTypeName.IsEmpty) {
1820                         xe.SetElementType(GetAnySchemaType(xe.SchemaTypeName));
1821                         if (xe.ElementSchemaType == null) {
1822                             throw new XmlSchemaException(Res.Sch_UndeclaredType, xe.SchemaTypeName.ToString(), xe);   
1823                         }
1824                     }
1825                     else  if (!xe.SubstitutionGroup.IsEmpty) {
1826                         XmlSchemaElement examplar = (XmlSchemaElement)this.schema.Elements[xe.SubstitutionGroup];
1827                         if (examplar == null) {
1828                             throw new XmlSchemaException(Res.Sch_UndeclaredEquivClass, xe.SubstitutionGroup.Name.ToString(CultureInfo.InvariantCulture), xe);   
1829                         }
1830                         if (examplar.IsProcessing) { //Circular subst group; already detected by now
1831                             return;
1832                         }
1833                         CompileElement(examplar);
1834                         if (examplar.ElementDecl == null) { //If head is invalid, fall back to AnyType
1835                             xe.SetElementType(XmlSchemaComplexType.AnyType);
1836                             decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
1837                         }
1838                         else {
1839                             xe.SetElementType(examplar.ElementSchemaType);
1840                             decl = examplar.ElementDecl.Clone();
1841                         }
1842                     }
1843                     else {
1844                         xe.SetElementType(XmlSchemaComplexType.AnyType);
1845                         decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
1846                     }
1847             
1848                     if (decl == null) {
1849                         Debug.Assert(xe.ElementSchemaType != null);
1850                         if (xe.ElementSchemaType is XmlSchemaComplexType) {
1851                             XmlSchemaComplexType complexType = (XmlSchemaComplexType)xe.ElementSchemaType;
1852                             CompileComplexType(complexType);
1853                             if (complexType.ElementDecl != null) {
1854                                 decl = complexType.ElementDecl.Clone();
1855 //                                decl.LocalElements = complexType.LocalElementDecls;
1856                             }
1857                         } 
1858                         else if (xe.ElementSchemaType is XmlSchemaSimpleType) {
1859                             XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)xe.ElementSchemaType;
1860                             CompileSimpleType(simpleType);
1861                             if (simpleType.ElementDecl != null) {
1862                                 decl = simpleType.ElementDecl.Clone();
1863                             }
1864                         } 
1865                     }
1866                     decl.Name = xe.QualifiedName;
1867                     decl.IsAbstract = xe.IsAbstract;
1868                     XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType;
1869                     if (ct != null) {
1870                         decl.IsAbstract |= ct.IsAbstract; 
1871                     }
1872                     decl.IsNillable = xe.IsNillable;
1873                     decl.Block |= xe.BlockResolved;
1874                 }
1875                 if (decl.Datatype != null) {
1876                     decl.Datatype.VerifySchemaValid(this.schema.Notations, xe);
1877                 }
1878
1879                 if (xe.DefaultValue != null || xe.FixedValue != null) {
1880                     if (decl.ContentValidator != null) {
1881                         if (decl.ContentValidator.ContentType == XmlSchemaContentType.TextOnly) {
1882                             if (xe.DefaultValue != null) {
1883                                 decl.Presence = SchemaDeclBase.Use.Default; 
1884                                 decl.DefaultValueRaw = xe.DefaultValue;
1885                             }
1886                             else {
1887                                 decl.Presence = SchemaDeclBase.Use.Fixed; 
1888                                 decl.DefaultValueRaw = xe.FixedValue;
1889                             }
1890                             if (decl.Datatype != null) {
1891                                 decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true);
1892                             }
1893                         }
1894                         else if (decl.ContentValidator.ContentType != XmlSchemaContentType.Mixed || !decl.ContentValidator.IsEmptiable) {
1895                             throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe);
1896                         }
1897                     }
1898                 }
1899                 if (xe.HasConstraints) {
1900                     XmlSchemaObjectCollection constraints = xe.Constraints;
1901                     CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count];
1902                     int idx = 0;
1903                     for (int i = 0; i < constraints.Count; ++i) {
1904                         XmlSchemaIdentityConstraint constraint = (XmlSchemaIdentityConstraint)constraints[i];
1905                         CompileIdentityConstraint (constraint);
1906                         compiledConstraints[idx ++] = constraint.CompiledConstraint;
1907                     }
1908                     decl.Constraints = compiledConstraints;
1909                 }
1910                 decl.SchemaElement = xe; //So this is available for PSVI
1911                 xe.ElementDecl = decl;
1912             } 
1913             catch (XmlSchemaException e) {
1914                 if (e.SourceSchemaObject == null) {
1915                     e.SetSource(xe);
1916                 }
1917                 SendValidationEvent(e);
1918                 xe.ElementDecl = SchemaElementDecl.Empty;
1919             } 
1920             finally {
1921                 xe.IsProcessing = false;
1922             }
1923         }
1924
1925         private ContentValidator CompileComplexContent(XmlSchemaComplexType complexType) {
1926             if (complexType.ContentType == XmlSchemaContentType.Empty) {
1927                 return ContentValidator.Empty;
1928             }
1929             else if (complexType.ContentType == XmlSchemaContentType.TextOnly) {
1930                 return ContentValidator.TextOnly;
1931             }
1932             XmlSchemaParticle particle = complexType.ContentTypeParticle;
1933             if (particle == null || particle == XmlSchemaParticle.Empty) {
1934                 if (complexType.ContentType == XmlSchemaContentType.ElementOnly) {
1935                     return ContentValidator.Empty;
1936                 }
1937                 else {
1938                     return ContentValidator.Mixed;
1939                 }
1940             }
1941             PushComplexType(complexType);
1942             if (particle is XmlSchemaAll) {
1943                 XmlSchemaAll all = (XmlSchemaAll)particle;
1944                 AllElementsContentValidator contentValidator = new AllElementsContentValidator(complexType.ContentType, all.Items.Count, all.MinOccurs == decimal.Zero);
1945                 for (int i = 0; i < all.Items.Count; ++i) {
1946                     XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i];
1947                     if (!contentValidator.AddElement(localElement.QualifiedName, localElement, localElement.MinOccurs == decimal.Zero)) {
1948                        SendValidationEvent(Res.Sch_DupElement, localElement.QualifiedName.ToString(), localElement);
1949                     }
1950                 }
1951                 return contentValidator;
1952             }
1953             else {
1954                 ParticleContentValidator contentValidator = new ParticleContentValidator(complexType.ContentType);
1955 #if DEBUG
1956                 string name = complexType.Name != null ? complexType.Name : string.Empty;
1957                 Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceVerbose, "CompileComplexContent: "+ name  + DumpContentModel(particle));
1958 #endif
1959                 try {
1960                     contentValidator.Start();
1961                     BuildParticleContentModel(contentValidator, particle);
1962                     return contentValidator.Finish(compileContentModel);                         
1963                 }
1964                 catch(UpaException e) {
1965                     if (e.Particle1 is XmlSchemaElement) {
1966                         if (e.Particle2 is XmlSchemaElement) {
1967                             SendValidationEvent(Res.Sch_NonDeterministic, ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaElement)e.Particle2);
1968                         }
1969                         else {
1970                             SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle2).NamespaceList.ToString(), ((XmlSchemaElement)e.Particle1).QualifiedName.ToString(), (XmlSchemaAny)e.Particle2);
1971                         }
1972                     }
1973                     else {
1974                         if (e.Particle2 is XmlSchemaElement) {
1975                             SendValidationEvent(Res.Sch_NonDeterministicAnyEx, ((XmlSchemaAny)e.Particle1).NamespaceList.ToString(), ((XmlSchemaElement)e.Particle2).QualifiedName.ToString(), (XmlSchemaAny)e.Particle1);
1976                         }
1977                         else {
1978                             SendValidationEvent(Res.Sch_NonDeterministicAnyAny, ((XmlSchemaAny)e.Particle1).NamespaceList.ToString(), ((XmlSchemaAny)e.Particle2).NamespaceList.ToString() ,(XmlSchemaAny)e.Particle1);
1979                         }
1980                     }
1981                     return XmlSchemaComplexType.AnyTypeContentValidator;
1982                 }
1983                 catch(NotSupportedException) {
1984                     SendValidationEvent(Res.Sch_ComplexContentModel, complexType, XmlSeverityType.Warning);
1985                     return XmlSchemaComplexType.AnyTypeContentValidator;
1986                 }
1987             }
1988         }
1989
1990 #if DEBUG
1991         private string DumpContentModel(XmlSchemaParticle particle) {
1992             StringBuilder sb = new StringBuilder();
1993             DumpContentModelTo(sb, particle);
1994             return sb.ToString();
1995         }
1996
1997         private void DumpContentModelTo(StringBuilder sb, XmlSchemaParticle particle) {
1998             if (particle is XmlSchemaElement) {
1999                 sb.Append(((XmlSchemaElement)particle).QualifiedName);       
2000             }
2001             else if (particle is XmlSchemaAny) {
2002                 sb.Append("<");
2003                 sb.Append(((XmlSchemaAny)particle).NamespaceList.ToString());
2004                 sb.Append(">");
2005             }
2006             else if (particle is XmlSchemaAll) {
2007                 XmlSchemaAll all = (XmlSchemaAll)particle;
2008                 sb.Append("[");       
2009                 bool first = true;
2010                 for (int i = 0; i < all.Items.Count; ++i) {
2011                     XmlSchemaElement localElement = (XmlSchemaElement)all.Items[i];
2012                     if (first) {
2013                         first = false;
2014                     }
2015                     else {
2016                         sb.Append(", ");
2017                     }
2018                     sb.Append(localElement.QualifiedName.Name);       
2019                     if (localElement.MinOccurs == decimal.Zero) {
2020                         sb.Append("?");                                                                  
2021                     }
2022                 }    
2023                 sb.Append("]");                                
2024             }
2025             else if (particle is XmlSchemaGroupBase) {
2026                 XmlSchemaGroupBase gb = (XmlSchemaGroupBase)particle;
2027                 sb.Append("(");
2028                 string delimeter = (particle is XmlSchemaChoice) ? " | " : ", ";
2029                 bool first = true;
2030                 for (int i = 0; i < gb.Items.Count; ++i) {
2031                     if (first) {
2032                         first = false;
2033                     }
2034                     else {
2035                         sb.Append(delimeter);
2036                     }
2037                     DumpContentModelTo(sb, (XmlSchemaParticle)gb.Items[i]);
2038                 }
2039                 sb.Append(")");
2040             } else {
2041                 Debug.Assert(particle == XmlSchemaParticle.Empty);
2042                 sb.Append("<>");
2043             }
2044             if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2045                 // nothing
2046             }
2047             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2048                 sb.Append("?");
2049             }
2050             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2051                 sb.Append("*");
2052             }
2053             else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2054                 sb.Append("+");
2055             }
2056             else {
2057                 sb.Append("{" + particle.MinOccurs.ToString(NumberFormatInfo.InvariantInfo) +", " + particle.MaxOccurs.ToString(NumberFormatInfo.InvariantInfo) + "}");
2058             }
2059         }
2060 #endif
2061
2062         private void BuildParticleContentModel(ParticleContentValidator contentValidator, XmlSchemaParticle particle) {
2063             if (particle is XmlSchemaElement) {
2064                 XmlSchemaElement element = (XmlSchemaElement)particle;
2065                 contentValidator.AddName(element.QualifiedName, element);       
2066             }
2067             else if (particle is XmlSchemaAny) {
2068                 XmlSchemaAny any = (XmlSchemaAny)particle;
2069                 contentValidator.AddNamespaceList(any.NamespaceList, any);
2070             }
2071             else if (particle is XmlSchemaGroupBase) {
2072                 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2073                 bool isChoice = particle is XmlSchemaChoice;
2074                 contentValidator.OpenGroup();
2075                 bool first = true;
2076                 for (int i = 0; i < particles.Count; ++i) {
2077                     XmlSchemaParticle p = (XmlSchemaParticle)particles[i];
2078                     Debug.Assert(!p.IsEmpty);
2079                     if (first) {
2080                         first = false;
2081                     }
2082                     else if (isChoice) {
2083                         contentValidator.AddChoice();  
2084                     }
2085                     else {
2086                         contentValidator.AddSequence();
2087                     }
2088                     BuildParticleContentModel(contentValidator, p);
2089                 }
2090                 contentValidator.CloseGroup();
2091             }
2092             else {
2093                 Debug.Assert(false);
2094             }
2095             if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.One) {
2096                 // nothing
2097             }
2098             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.One) {
2099                 contentValidator.AddQMark();
2100             }
2101             else if (particle.MinOccurs == decimal.Zero && particle.MaxOccurs == decimal.MaxValue) {
2102                 contentValidator.AddStar();
2103             }
2104             else if (particle.MinOccurs == decimal.One && particle.MaxOccurs == decimal.MaxValue) {
2105                 contentValidator.AddPlus();
2106             }
2107             else {
2108                 contentValidator.AddLeafRange(particle.MinOccurs, particle.MaxOccurs);
2109             }
2110         }
2111
2112         private void CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle) {
2113             if (particle is XmlSchemaElement) {
2114                 XmlSchemaElement localElement = (XmlSchemaElement)particle;
2115                 CompileElement(localElement); 
2116                 if (complexType.LocalElements[localElement.QualifiedName] == null) {
2117                     complexType.LocalElements.Add(localElement.QualifiedName, localElement);
2118                 }
2119                 else {
2120                     XmlSchemaElement element = (XmlSchemaElement)complexType.LocalElements[localElement.QualifiedName];
2121                     if (element.ElementSchemaType != localElement.ElementSchemaType) {
2122                         SendValidationEvent(Res.Sch_ElementTypeCollision, particle);
2123                     }
2124                 }                 
2125             }
2126             else if (particle is XmlSchemaGroupBase) {
2127                 XmlSchemaObjectCollection particles = ((XmlSchemaGroupBase)particle).Items;
2128                 for (int i = 0; i < particles.Count; ++i) {
2129                     CompileParticleElements(complexType, (XmlSchemaParticle)particles[i]);
2130                 }
2131             }
2132         }
2133
2134         private void CompileCompexTypeElements(XmlSchemaComplexType complexType) {
2135             if (complexType.IsProcessing) {
2136                 SendValidationEvent(Res.Sch_TypeCircularRef, complexType);
2137                 return;
2138             }
2139             complexType.IsProcessing = true;
2140             if (complexType.ContentTypeParticle != XmlSchemaParticle.Empty) {
2141                 CompileParticleElements(complexType, complexType.ContentTypeParticle);
2142             }
2143             complexType.IsProcessing = false;
2144         }
2145
2146         private XmlSchemaSimpleType GetSimpleType(XmlQualifiedName name) {
2147             XmlSchemaSimpleType type = this.schema.SchemaTypes[name] as XmlSchemaSimpleType;
2148             if (type != null) {
2149                 CompileSimpleType(type);
2150             }
2151             else {
2152                 type = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
2153                 //Re-assign datatype impl for V1Compat
2154                 if (type != null) {
2155                     if (type.TypeCode == XmlTypeCode.NormalizedString) {
2156                         type = DatatypeImplementation.GetNormalizedStringTypeV1Compat();
2157                     }
2158                     else if (type.TypeCode == XmlTypeCode.Token) {
2159                         type = DatatypeImplementation.GetTokenTypeV1Compat();
2160                     }
2161                 }
2162             }
2163             return type;
2164         }
2165
2166         private XmlSchemaComplexType GetComplexType(XmlQualifiedName name) {
2167             XmlSchemaComplexType type = this.schema.SchemaTypes[name] as XmlSchemaComplexType;
2168             if (type != null) {
2169                 CompileComplexType(type);
2170             }
2171             return type;
2172         }
2173
2174          private XmlSchemaType GetAnySchemaType(XmlQualifiedName name) {
2175                 XmlSchemaType type = (XmlSchemaType)this.schema.SchemaTypes[name];
2176                 if (type != null) {
2177                     if (type is XmlSchemaComplexType) {
2178                         CompileComplexType((XmlSchemaComplexType)type);
2179                     }
2180                     else {
2181                         CompileSimpleType((XmlSchemaSimpleType)type);  
2182                     }
2183                     return type;
2184                 }
2185                 else { //Its is a built-in simpleType
2186                     XmlSchemaSimpleType simpleType = DatatypeImplementation.GetSimpleTypeFromXsdType(name);
2187                     return simpleType;
2188                 }
2189         }
2190     };
2191
2192 } // namespace System.Xml