2010-03-12 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaComplexType.cs
1 //
2 // System.Xml.Schema.XmlSchemaComplexType.cs
3 //
4 // Authors:
5 //      Dwivedi, Ajay kumar  Adwiv@Yahoo.com
6 //      Enomoto, Atsushi     ginga@kit.hi-ho.ne.jp
7 //
8
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 using System;
30 using System.Collections;
31 using System.Xml;
32 using System.ComponentModel;
33 using System.Xml.Serialization;
34
35 namespace System.Xml.Schema
36 {
37         /// <summary>
38         /// Summary description for XmlSchemaComplexType.
39         /// </summary>
40         public class XmlSchemaComplexType : XmlSchemaType
41         {
42                 private XmlSchemaAnyAttribute anyAttribute;
43                 private XmlSchemaObjectCollection attributes;
44                 private XmlSchemaObjectTable attributeUses;
45                 private XmlSchemaAnyAttribute attributeWildcard;
46                 private XmlSchemaDerivationMethod block;
47                 private XmlSchemaDerivationMethod blockResolved;
48                 private XmlSchemaContentModel contentModel;
49                 private XmlSchemaParticle validatableParticle;
50                 private XmlSchemaParticle contentTypeParticle;
51                 private bool isAbstract;
52                 private bool isMixed;
53                 private XmlSchemaParticle particle;
54                 private XmlSchemaContentType resolvedContentType;
55
56                 internal bool ValidatedIsAbstract;
57                 internal bool ParentIsSchema {
58                         get { return Parent is XmlSchema; }
59                 }
60
61                 const string xmlname = "complexType";
62
63                 private static XmlSchemaComplexType anyType;
64
65                 internal static XmlSchemaComplexType AnyType {
66                         get {
67                                 if (anyType == null) {
68                                         anyType = new XmlSchemaComplexType ();
69                                         anyType.Name = "anyType";
70                                         anyType.QNameInternal = new XmlQualifiedName ("anyType", XmlSchema.Namespace);
71                                         if (XmlSchemaUtil.StrictMsCompliant)
72                                                 anyType.validatableParticle = XmlSchemaParticle.Empty; // This code makes validator handles these schemas incorrectly: particlesIb001, mgM013, mgH014, ctE004, ctD004
73                                         else
74                                                 anyType.validatableParticle = XmlSchemaAny.AnyTypeContent;
75
76                                         anyType.contentTypeParticle = anyType.validatableParticle;
77                                         anyType.DatatypeInternal = XmlSchemaSimpleType.AnySimpleType;
78                                         anyType.isMixed = true;
79                                         anyType.resolvedContentType = XmlSchemaContentType.Mixed;
80                                 }
81                                 return anyType;
82                         }
83                 }
84
85                 internal static readonly XmlQualifiedName AnyTypeName = new XmlQualifiedName ("anyType", XmlSchema.Namespace);
86
87                 public XmlSchemaComplexType ()
88                 {
89                         attributes = new XmlSchemaObjectCollection();
90                         block = XmlSchemaDerivationMethod.None;
91                         attributeUses = new XmlSchemaObjectTable();
92                         validatableParticle = XmlSchemaParticle.Empty;
93                         contentTypeParticle = validatableParticle;
94                 }
95
96                 #region Attributes
97
98                 [DefaultValue(false)]
99                 [System.Xml.Serialization.XmlAttribute("abstract")]
100                 public bool IsAbstract 
101                 {
102                         get{ return  isAbstract; }
103                         set{ isAbstract = value; }
104                 }
105                 [DefaultValue(XmlSchemaDerivationMethod.None)]
106                 [System.Xml.Serialization.XmlAttribute("block")]
107                 public XmlSchemaDerivationMethod Block
108                 {
109                         get{ return  block; }
110                         set{ block = value; }
111                 }
112                 [DefaultValue(false)]
113                 [System.Xml.Serialization.XmlAttribute("mixed")]
114                 public override bool IsMixed
115                 {
116                         get{ return  isMixed; }
117                         set{ isMixed = value; }
118                 }
119                 
120                 #endregion
121                 
122                 #region Elements
123                                 
124                 [XmlElement("simpleContent",typeof(XmlSchemaSimpleContent))]
125                 [XmlElement("complexContent",typeof(XmlSchemaComplexContent))]
126                 public XmlSchemaContentModel ContentModel 
127                 {
128                         get{ return  contentModel; } 
129                         set{ contentModel = value; }
130                 }
131
132                 //LAMESPEC: The default value for particle in Schema is of Type EmptyParticle (internal?)
133                 [XmlElement("group",typeof(XmlSchemaGroupRef))]
134                 [XmlElement("all",typeof(XmlSchemaAll))]
135                 [XmlElement("choice",typeof(XmlSchemaChoice))]
136                 [XmlElement("sequence",typeof(XmlSchemaSequence))]
137                 public XmlSchemaParticle Particle 
138                 {
139                         get{ return  particle; } 
140                         set{ particle = value; }
141                 }
142
143                 [XmlElement("attribute",typeof(XmlSchemaAttribute))]
144                 [XmlElement("attributeGroup",typeof(XmlSchemaAttributeGroupRef))]
145                 public XmlSchemaObjectCollection Attributes 
146                 {
147                         get{ return attributes; }
148                 }
149
150                 [XmlElement("anyAttribute")]
151                 public XmlSchemaAnyAttribute AnyAttribute 
152                 {
153                         get{ return  anyAttribute; }
154                         set{ anyAttribute = value; }
155                 }
156                 #endregion
157
158                 #region XmlIgnore
159                 [XmlIgnore]
160                 public XmlSchemaContentType ContentType 
161                 {
162                         get{ return resolvedContentType; }
163                 }
164                 [XmlIgnore]
165                 public XmlSchemaParticle ContentTypeParticle 
166                 {
167                         get{ return contentTypeParticle; }
168                 }
169                 [XmlIgnore]
170                 public XmlSchemaDerivationMethod BlockResolved 
171                 {
172                         get{ return blockResolved; }
173                 }
174                 [XmlIgnore]
175                 public XmlSchemaObjectTable AttributeUses 
176                 {
177                         get{ return attributeUses; }
178                 }
179                 [XmlIgnore]
180                 public XmlSchemaAnyAttribute AttributeWildcard 
181                 {
182                         get{ return attributeWildcard; }
183                 }
184
185                 #endregion
186
187                 internal XmlSchemaParticle ValidatableParticle 
188                 {
189                         get{ return contentTypeParticle; }
190                 }
191
192                 internal override void SetParent (XmlSchemaObject parent)
193                 {
194                         base.SetParent (parent);
195                         if (ContentModel != null)
196                                 ContentModel.SetParent (this);
197                         if (Particle != null)
198                                 Particle.SetParent (this);
199                         if (AnyAttribute != null)
200                                 AnyAttribute.SetParent (this);
201                         foreach (XmlSchemaObject obj in Attributes)
202                                 obj.SetParent (this);
203                 }
204
205                 /// <remarks>
206                 /// 1. If ContentModel is present, neither particle nor Attributes nor AnyAttribute can be present.
207                 /// 2. If particle is present, 
208                 /// a. For a topLevelComplexType
209                 ///             1. name must be present and type NCName
210                 ///             2. if block is #all, blockdefault is #all, else List of (extension | restriction)
211                 ///             3. if final is #all, finaldefault is #all, else List of (extension | restriction)
212                 ///     b. For a local Complex type 
213                 ///             1. abstract must be false
214                 ///             2. Name must be absent
215                 ///             3. final must be absent
216                 ///             4. block must be absent
217                 ///             
218                 /// </remarks>
219                 internal override int Compile (ValidationEventHandler h, XmlSchema schema)
220                 {
221                         // If this is already compiled this time, simply skip.
222                         if (CompilationId == schema.CompilationId)
223                                 return errorCount;
224
225                         ValidatedIsAbstract = isAbstract;
226                         attributeUses.Clear();
227
228                         if (isRedefinedComponent) {
229                                 if (Annotation != null)
230                                         Annotation.isRedefinedComponent = true;
231                                 if (AnyAttribute != null)
232                                         AnyAttribute.isRedefinedComponent = true;
233                                 foreach (XmlSchemaObject obj in Attributes)
234                                         obj.isRedefinedComponent = true;
235                                 if (ContentModel != null)
236                                         ContentModel.isRedefinedComponent = true;
237                                 if (Particle != null)
238                                         Particle.isRedefinedComponent = true;
239                         }
240
241                         // block/final resolution
242                         if(ParentIsSchema || isRedefineChild)
243                         {
244                                 if(this.Name == null || this.Name == string.Empty)
245                                         error(h,"name must be present in a top level complex type");
246                                 else if(!XmlSchemaUtil.CheckNCName(Name))
247                                         error(h,"name must be a NCName");
248                                 else
249                                         this.QNameInternal = new XmlQualifiedName(Name, AncestorSchema.TargetNamespace);
250                                 
251                                 if(Block != XmlSchemaDerivationMethod.None)
252                                 {
253                                         if(Block == XmlSchemaDerivationMethod.All)
254                                         {
255                                                 blockResolved = XmlSchemaDerivationMethod.All;
256                                         }
257                                         else
258                                         {
259                                                 if ((Block & XmlSchemaUtil.ComplexTypeBlockAllowed) != Block)
260                                                         error (h, "Invalid block specification.");
261                                                 blockResolved = Block & XmlSchemaUtil.ComplexTypeBlockAllowed;
262                                         }
263                                 }
264                                 else
265                                 {
266                                         switch (schema.BlockDefault) {
267                                         case XmlSchemaDerivationMethod.All:
268                                                 blockResolved = XmlSchemaDerivationMethod.All;
269                                                 break;
270                                         case XmlSchemaDerivationMethod.None:
271                                                 blockResolved = XmlSchemaDerivationMethod.Empty;
272                                                 break;
273                                         default:
274                                                 blockResolved = schema.BlockDefault & XmlSchemaUtil.ComplexTypeBlockAllowed;
275                                                 break;
276                                         }
277                                 }
278
279                                 if(Final != XmlSchemaDerivationMethod.None)
280                                 {
281                                         if(Final == XmlSchemaDerivationMethod.All)
282                                                 finalResolved = XmlSchemaDerivationMethod.All;
283                                         else if ((Final & XmlSchemaUtil.FinalAllowed) != Final)
284                                                 error (h, "Invalid final specification.");
285                                         else
286                                                 finalResolved = Final;
287                                 }
288                                 else
289                                 {
290                                         switch (schema.FinalDefault) {
291                                         case XmlSchemaDerivationMethod.All:
292                                                 finalResolved = XmlSchemaDerivationMethod.All;
293                                                 break;
294                                         case XmlSchemaDerivationMethod.None:
295                                                 finalResolved = XmlSchemaDerivationMethod.Empty;
296                                                 break;
297                                         default:
298                                                 finalResolved = schema.FinalDefault & XmlSchemaUtil.FinalAllowed;
299                                                 break;
300                                         }
301                                 }
302                         }
303                         else // Not Top Level
304                         {
305                                 if(isAbstract)
306                                         error(h,"abstract must be false in a local complex type");
307                                 if(Name != null)
308                                         error(h,"name must be absent in a local complex type");
309                                 if(Final != XmlSchemaDerivationMethod.None)
310                                         error(h,"final must be absent in a local complex type");
311                                 if(block != XmlSchemaDerivationMethod.None)
312                                         error(h,"block must be absent in a local complex type");
313                         }
314
315                         // Process contents and BaseSchemaType
316                         if(contentModel != null)
317                         {
318                                 if(anyAttribute != null || Attributes.Count != 0 || Particle != null)
319                                         error(h,"attributes, particles or anyattribute is not allowed if ContentModel is present");
320                                 errorCount += contentModel.Compile (h, schema);
321
322                                 XmlSchemaSimpleContent smodel = ContentModel as XmlSchemaSimpleContent;
323                                 if(smodel != null)
324                                 {
325                                         XmlSchemaSimpleContentExtension sscx = smodel.Content as XmlSchemaSimpleContentExtension;
326                                         if (sscx == null) {
327                                                 XmlSchemaSimpleContentRestriction sscr = smodel.Content as XmlSchemaSimpleContentRestriction;
328                                                 if (sscr != null) {
329                                                         if (sscr.BaseType != null) {
330                                                                 sscr.BaseType.Compile (h, schema);
331                                                                 BaseXmlSchemaTypeInternal = sscr.BaseType;
332                                                         }
333                                                 }
334                                         }
335                                 }
336                         }
337                         else
338                         {
339                                 if (Particle != null)
340                                         errorCount += Particle.Compile (h, schema);
341
342                                 if(this.anyAttribute != null)
343                                 {
344                                         AnyAttribute.Compile(h,schema);
345                                 }
346                                 foreach(XmlSchemaObject obj in Attributes)
347                                 {
348                                         if(obj is XmlSchemaAttribute)
349                                         {
350                                                 XmlSchemaAttribute attr = (XmlSchemaAttribute) obj;
351                                                 errorCount += attr.Compile(h,schema);
352                                         }
353                                         else if(obj is XmlSchemaAttributeGroupRef)
354                                         {
355                                                 XmlSchemaAttributeGroupRef atgrp = (XmlSchemaAttributeGroupRef) obj;
356                                                 errorCount += atgrp.Compile(h,schema);
357                                         }
358                                         else
359                                                 error(h,obj.GetType() +" is not valid in this place::ComplexType");
360                                 }
361                         }
362
363                         XmlSchemaUtil.CompileID(Id, this, schema.IDCollection, h);
364                         this.CompilationId = schema.CompilationId;
365                         return errorCount;
366                 }
367
368                 Guid CollectProcessId;
369
370                 private void CollectSchemaComponent (ValidationEventHandler h, XmlSchema schema)
371                 {
372                         if (CollectProcessId == schema.CompilationId)
373                                 return;
374                         // Below are already contributed by Compile():
375                         // {name}, {namespace} => QualifiedName, QNameInternal
376                         // {abstract} => ValidatedIsAbstract
377                         // {prohibited substitutions} => BlockResolved
378                         // {final} => FinalResolved
379                         // {annotations} => Annotation (XmlSchemaAnnotated)
380
381                         // Below are different properties depending on simpleContent | complexContent.
382                         // {base type definition}
383                         // {derivation method}
384                         // {attribute uses} => AttributeUses (later)
385                         // {attribute wildcard} => AttributeWildcard (later)
386                         // {content type}
387
388
389                         // {base type definition} => baseSchemaTypeInternal (later)
390                         if (contentModel != null) {
391                                 BaseSchemaTypeName = contentModel.Content != null ? contentModel.Content.GetBaseTypeName () : XmlQualifiedName.Empty;
392
393                                 BaseXmlSchemaTypeInternal = schema.FindSchemaType(BaseSchemaTypeName);
394                         }
395                         // Resolve redefine.
396                         if (this.isRedefineChild && BaseXmlSchemaType != null && this.QualifiedName == BaseSchemaTypeName) {
397                                 XmlSchemaType redType = (XmlSchemaType) redefinedObject;
398                                 if (redType == null)
399                                         error (h, "Redefinition base type was not found.");
400                                 else
401                                         BaseXmlSchemaTypeInternal = redType;
402                         }
403
404                         // {derivation method} => resolvedDerivedBy
405                         if (contentModel != null && contentModel.Content != null) {
406                                 resolvedDerivedBy =
407                                         contentModel.Content.IsExtension ?
408                                         XmlSchemaDerivationMethod.Extension :
409                                         XmlSchemaDerivationMethod.Restriction;
410                         }
411                         else
412                                 resolvedDerivedBy = XmlSchemaDerivationMethod.Empty;
413                 }
414
415                 void FillContentTypeParticle (ValidationEventHandler h, XmlSchema schema)
416                 {
417                         // {content type} => ContentType and ContentTypeParticle (later)
418                         if (ContentModel != null) {
419                                 CollectContentTypeFromContentModel (h, schema);
420                         } else
421                                 CollectContentTypeFromImmediateContent ();
422
423                         contentTypeParticle = validatableParticle.GetOptimizedParticle (true);
424                         if (contentTypeParticle == XmlSchemaParticle.Empty && resolvedContentType == XmlSchemaContentType.ElementOnly)
425                                 resolvedContentType = XmlSchemaContentType.Empty;
426
427                         CollectProcessId = schema.CompilationId;
428                 }
429
430                 #region {content type}
431                 private void CollectContentTypeFromImmediateContent ()
432                 {
433                         // leave resolvedDerivedBy as Empty
434                         if (Particle != null)
435                                 validatableParticle = Particle;
436                         if (this == AnyType) {
437                                 resolvedContentType = XmlSchemaContentType.Mixed;
438                                 return;
439                         }
440
441                         if (validatableParticle == XmlSchemaParticle.Empty) {
442                                 // note that this covers "Particle == null" case
443                                 if (this.IsMixed)
444                                         resolvedContentType = XmlSchemaContentType.TextOnly;
445                                 else
446                                         resolvedContentType = XmlSchemaContentType.Empty;
447                         } else {
448                                 if (this.IsMixed)
449                                         resolvedContentType = XmlSchemaContentType.Mixed;
450                                 else
451                                         resolvedContentType = XmlSchemaContentType.ElementOnly;
452                         }
453                         if (this != AnyType)
454                                 BaseXmlSchemaTypeInternal = XmlSchemaComplexType.AnyType;
455                 }
456
457                 private void CollectContentTypeFromContentModel (ValidationEventHandler h, XmlSchema schema)
458                 {
459                         if (ContentModel.Content == null) {
460                                 // basically it is error. Recover by specifying empty content.
461                                 validatableParticle = XmlSchemaParticle.Empty;
462                                 resolvedContentType = XmlSchemaContentType.Empty;
463                                 return;
464                         }
465
466                         if (ContentModel.Content is XmlSchemaComplexContentExtension)
467                                 CollectContentTypeFromComplexExtension (h, schema);
468                         if (ContentModel.Content is XmlSchemaComplexContentRestriction)
469                                 CollectContentTypeFromComplexRestriction ();
470                 }
471
472                 private void CollectContentTypeFromComplexExtension (ValidationEventHandler h, XmlSchema schema)
473                 {
474                         XmlSchemaComplexContentExtension cce = (XmlSchemaComplexContentExtension) ContentModel.Content;
475                         XmlSchemaComplexType baseComplexType = this.BaseXmlSchemaType as XmlSchemaComplexType;
476                         if (baseComplexType != null)
477                                 baseComplexType.CollectSchemaComponent (h ,schema);
478
479                         // It must exist, but consider validation error case.
480                         if (BaseSchemaTypeName == XmlSchemaComplexType.AnyTypeName)
481                                 baseComplexType = XmlSchemaComplexType.AnyType;
482
483                         // On error case, it simple reject any contents
484                         if (baseComplexType == null) {
485                                 validatableParticle = XmlSchemaParticle.Empty;
486                                 resolvedContentType = XmlSchemaContentType.Empty;
487                                 return;
488                         }
489
490                         // 3.4.2 complex content {content type}
491                         if (cce.Particle == null || cce.Particle == XmlSchemaParticle.Empty) {
492                                 // - 2.1
493                                 if (baseComplexType == null) {
494                                         // Basically it is an error. Considering ValidationEventHandler.
495                                         validatableParticle = XmlSchemaParticle.Empty;
496                                         resolvedContentType = XmlSchemaContentType.Empty;
497                                 } else {
498                                         validatableParticle = baseComplexType.ValidatableParticle;
499                                         resolvedContentType = baseComplexType.resolvedContentType;
500                                         // Bug #501814
501                                         if (resolvedContentType == XmlSchemaContentType.Empty)
502                                                 resolvedContentType = GetComplexContentType (contentModel);
503                                 }
504                         } else if (baseComplexType.validatableParticle == XmlSchemaParticle.Empty
505                                 || baseComplexType == XmlSchemaComplexType.AnyType) {
506                                 // - 2.2
507                                 validatableParticle = cce.Particle;
508                                 resolvedContentType = GetComplexContentType (contentModel);
509                         } else {
510                                 // - 2.3 : create a new sequences that merges both contents.
511                                 XmlSchemaSequence seq = new XmlSchemaSequence ();
512                                 this.CopyInfo (seq);
513                                 seq.Items.Add (baseComplexType.validatableParticle);
514                                 seq.Items.Add (cce.Particle);
515                                 seq.Compile (h, schema);
516                                 seq.Validate (h, schema);
517                                 validatableParticle = seq;
518                                 resolvedContentType = GetComplexContentType (contentModel);
519                         }
520                         if (validatableParticle == null)
521                                 validatableParticle = XmlSchemaParticle.Empty;
522                 }
523
524                 private void CollectContentTypeFromComplexRestriction ()
525                 {
526                         XmlSchemaComplexContentRestriction ccr = (XmlSchemaComplexContentRestriction) ContentModel.Content;
527                         // 3.4.2 complex content schema component {content type}
528                         // - 1.1.1
529                         bool isEmptyParticle = false;
530                         if (ccr.Particle == null) 
531                                 isEmptyParticle = true;
532                         else {
533                                 XmlSchemaGroupBase gb = ccr.Particle as XmlSchemaGroupBase;
534                                 if (gb != null) {
535                                         // - 1.1.2
536                                         if (!(gb is XmlSchemaChoice) && gb.Items.Count == 0)
537                                                 isEmptyParticle = true;
538                                         // - 1.1.3
539                                         else if (gb is XmlSchemaChoice && gb.Items.Count == 0 && gb.ValidatedMinOccurs == 0)
540                                                 isEmptyParticle = true;
541                                 }
542                         }
543                         if (isEmptyParticle) {
544                                 resolvedContentType = XmlSchemaContentType.Empty;
545                                 validatableParticle = XmlSchemaParticle.Empty;
546                         } else {
547                                 // - 1.2.1
548                                 resolvedContentType = GetComplexContentType (contentModel);
549                                 // - 1.2.2
550                                 validatableParticle = ccr.Particle;
551                         }
552                 }
553
554                 // 3.4.2 Complex Content Schema Component {content type} 1.2.1
555                 private XmlSchemaContentType GetComplexContentType (XmlSchemaContentModel content)
556                 {
557                         if (this.IsMixed || ((XmlSchemaComplexContent) content).IsMixed)
558                                 return XmlSchemaContentType.Mixed;
559                         else
560                                 return XmlSchemaContentType.ElementOnly;
561                 }
562                 #endregion
563
564                 //
565                 // We have to validate:
566                 //
567                 //      - 3.4.3 Complex Type Definition Representation OK
568                 //      - 3.4.6 Type Definition Properties Correct
569                 //      - 3.4.6 Derivation Valid (Extension)
570                 //      - 3.4.6 Derivation Valid (Restriction, Complex)
571                 //
572                 // There are many schema errata:
573                 // http://www.w3.org/2001/05/xmlschema-errata#Errata1
574                 //
575                 // E1-43 Derivation Valid (Restriction, Complex) 5.
576                 // E1-21 Derivation Valid (Restriction, Complex) 4.3.
577                 // E1-17 Type Derivation OK (Complex) 2.1.
578                 //
579                 // And E1-38, E1-37, E1-30, E1-27
580                 //
581                 internal override int Validate (ValidationEventHandler h, XmlSchema schema)
582                 {
583                         if (IsValidated (schema.ValidationId))
584                                 return errorCount;
585                         // FIXME: omitting it causes StackOverflowException
586                         // among the compilation of element and types, but
587                         // it may result in insufficient results.
588                         ValidationId = schema.ValidationId;
589
590                         CollectSchemaComponent (h, schema);
591
592                         ValidateBaseXmlSchemaType (h, schema);
593                         
594                         ValidateParticle (h, schema);
595                         
596                         FillContentTypeParticle (h, schema);
597
598                         // 3.4.6: Properties Correct
599                         // Term. 1 => 3.4.1 already done by CollectSchemaComponent()
600                         //            except for {attribute uses} and {attribute wildcard}
601                         // Term. 2, 3 and 4 goes to ValidateContentModel().
602                         // Term. 5 follows in this method.
603                         //
604                         if (ContentModel != null)
605                                 ValidateContentModel (h, schema);
606                         else
607                                 ValidateImmediateAttributes (h, schema);
608
609                         // Additional support for 3.8.6 All Group Limited
610                         if (ContentTypeParticle != null) {
611                                 XmlSchemaAll termAll = contentTypeParticle.GetOptimizedParticle (true) as XmlSchemaAll;
612                                 if (termAll != null && (termAll.ValidatedMaxOccurs != 1 || contentTypeParticle.ValidatedMaxOccurs != 1)) // here contentTypeParticle is used to check occurence.
613                                         error (h, "Particle whose term is -all- and consists of complex type content particle must have maxOccurs = 1.");
614                         }
615
616 #if NET_2_0
617                         if (schema.Schemas.CompilationSettings != null &&
618                                 schema.Schemas.CompilationSettings.EnableUpaCheck)
619 #endif
620                         // This check is optional only after 2.0
621                         contentTypeParticle.ValidateUniqueParticleAttribution (new XmlSchemaObjectTable (),
622                                 new ArrayList (), h, schema);
623                         contentTypeParticle.ValidateUniqueTypeAttribution (
624                                 new XmlSchemaObjectTable (), h, schema);
625
626                         // 3.4.6 Properties Correct :: 5 (Two distinct ID attributes)
627                         XmlSchemaAttribute idAttr = null;
628                         foreach (DictionaryEntry entry in attributeUses) {
629                                 XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
630                                 XmlSchemaDatatype dt = attr.AttributeType as XmlSchemaDatatype;
631                                 if (dt != null && dt.TokenizedType != XmlTokenizedType.ID)
632                                         continue;
633                                 if (dt == null)
634                                         dt = ((XmlSchemaSimpleType) attr.AttributeType).Datatype;
635                                 if (dt != null && dt.TokenizedType == XmlTokenizedType.ID) {
636                                         if (idAttr != null)
637                                                 error (h, "Two or more ID typed attribute declarations in a complex type are found.");
638                                         else
639                                                 idAttr = attr;
640                                 }
641                         }
642
643                         ValidationId = schema.ValidationId;
644                         return errorCount;
645                 }
646
647                 private void ValidateImmediateAttributes (ValidationEventHandler h, XmlSchema schema)
648                 {
649                         // {attribute uses}
650                         // also checks 3.4.6 Properties Correct :: 4 (Distinct attributes)
651                         attributeUses = new XmlSchemaObjectTable ();
652                         XmlSchemaUtil.ValidateAttributesResolved (attributeUses,
653                                 h, schema, attributes, anyAttribute, ref attributeWildcard, null, false);
654                 }
655                 
656                 private void ValidateBaseXmlSchemaType (ValidationEventHandler h, XmlSchema schema)
657                 {
658                         if (ContentModel != null && BaseXmlSchemaTypeInternal != null)
659                                 errorCount += BaseXmlSchemaTypeInternal.Validate (h, schema);
660                 }
661
662                 private void ValidateParticle (ValidationEventHandler h, XmlSchema schema)
663                 {       
664                         if (ContentModel == null && Particle != null) {
665                                 errorCount += particle.Validate (h, schema);
666                                 XmlSchemaGroupRef pgrp = Particle as XmlSchemaGroupRef;
667                                 if (pgrp != null) {
668                                         if (pgrp.TargetGroup != null)
669                                                 errorCount += pgrp.TargetGroup.Validate (h,schema);
670                                         // otherwise, it might be missing sub components.
671                                         else if (!schema.IsNamespaceAbsent (pgrp.RefName.Namespace))
672                                                 error (h, "Referenced group " + pgrp.RefName + " was not found in the corresponding schema.");
673                                 }
674                         }
675                 }
676
677                 private void ValidateContentModel (ValidationEventHandler h, XmlSchema schema)
678                 {
679                         errorCount += contentModel.Validate (h, schema);
680                         
681                         XmlSchemaType baseType = BaseXmlSchemaTypeInternal;
682
683                         // Here we check 3.4.6 Properties Correct :: 2. and 3.
684                         XmlSchemaComplexContentExtension cce = contentModel.Content as XmlSchemaComplexContentExtension;
685                         XmlSchemaComplexContentRestriction ccr = contentModel.Content as XmlSchemaComplexContentRestriction;
686                         XmlSchemaSimpleContentExtension sce = contentModel.Content as XmlSchemaSimpleContentExtension;
687                         XmlSchemaSimpleContentRestriction scr = contentModel.Content as XmlSchemaSimpleContentRestriction;
688
689                         XmlSchemaAnyAttribute localAnyAttribute = null;
690                         XmlSchemaAnyAttribute baseAnyAttribute = null;
691
692                         // 3.4.6 Properties Correct :: 3. Circular definition prohibited.
693                         if (ValidateRecursionCheck ())
694                                 error (h, "Circular definition of schema types was found.");
695                         if (baseType != null) {
696                                 // Fill "Datatype" property.
697                                 this.DatatypeInternal = baseType.Datatype;
698                         } else if (BaseSchemaTypeName == XmlSchemaComplexType.AnyTypeName)
699                                 DatatypeInternal = XmlSchemaSimpleType.AnySimpleType;
700                         else if (XmlSchemaUtil.IsBuiltInDatatypeName (BaseSchemaTypeName)) {
701                                 DatatypeInternal = XmlSchemaDatatype.FromName (BaseSchemaTypeName);
702                         }
703
704                         XmlSchemaComplexType baseComplexType = baseType as XmlSchemaComplexType;
705                         XmlSchemaSimpleType baseSimpleType = baseType as XmlSchemaSimpleType;
706
707                         // 3.4.6 Derivation Valid (common to Extension and Restriction, Complex) :: 1.
708                         if (baseType != null && (baseType.FinalResolved & resolvedDerivedBy) != 0)
709                                         error (h, "Specified derivation is specified as final by derived schema type.");
710
711                         // 3.4.6 Properties Correct :: 2.
712                         // Simple {base type definition} and restriction {derivation method} not allowed.
713                         if (baseSimpleType != null && resolvedDerivedBy == XmlSchemaDerivationMethod.Restriction)
714                                 error (h, "If the base schema type is a simple type, then this type must be extension.");
715
716                         // Common to complexContent
717                         if (cce != null || ccr != null) {
718                                 // 3.4.3 Complex Type Definition Representation OK :: 1.
719                                 // base
720                                 if (BaseSchemaTypeName == XmlSchemaComplexType.AnyTypeName)
721                                         baseComplexType = XmlSchemaComplexType.AnyType;
722                                 else if (XmlSchemaUtil.IsBuiltInDatatypeName (BaseSchemaTypeName))
723                                         error (h, "Referenced base schema type is XML Schema datatype.");
724                                 else if (baseComplexType == null && !schema.IsNamespaceAbsent (BaseSchemaTypeName.Namespace))
725                                         error (h, "Referenced base schema type " + BaseSchemaTypeName + " was not complex type or not found in the corresponding schema.");
726                         }
727                         // Common to simpleContent 
728                         else {
729                                 // ContentType of {content type}
730                                 resolvedContentType = XmlSchemaContentType.TextOnly;
731
732                                 // 3.4.3 Complex Type Definition Representation OK :: 1.
733                                 // base
734                                 if (BaseSchemaTypeName == XmlSchemaComplexType.AnyTypeName)
735                                         baseComplexType = XmlSchemaComplexType.AnyType;
736
737                                 if (baseComplexType != null && baseComplexType.ContentType != XmlSchemaContentType.TextOnly) {
738                                         error (h, "Base schema complex type of a simple content must be simple content type. Base type is " + BaseSchemaTypeName);
739                                 } else if (sce == null && (baseSimpleType != null && BaseSchemaTypeName.Namespace != XmlSchema.Namespace)) {
740                                         error (h, "If a simple content is not an extension, base schema type must be complex type. Base type is " + BaseSchemaTypeName);
741                                 } else if (XmlSchemaUtil.IsBuiltInDatatypeName (BaseSchemaTypeName)) {
742                                         // do nothing for particle.
743                                 }
744                                 // otherwise, it might be missing sub components.
745                                 else if (baseType == null && !schema.IsNamespaceAbsent (BaseSchemaTypeName.Namespace))
746                                         error (h, "Referenced base schema type " + BaseSchemaTypeName + " was not found in the corresponding schema.");
747
748                                 // 3.4.3 Complex Type Definition Representation OK :: 2.
749                                 // Note that baseSimpleType is also allowed as to Errata E1-27 (http://www.w3.org/2001/05/xmlschema-errata)
750                                 if (baseComplexType != null) {
751                                         if (baseComplexType.ContentType == XmlSchemaContentType.TextOnly) {
752                                                 // 2.1.1
753                                         // Here "baseComplexType.Particle != null" is required for error-ignorant case
754                                         } else if (scr != null && baseComplexType.ContentType == XmlSchemaContentType.Mixed && baseComplexType.Particle != null && baseComplexType.Particle.ValidateIsEmptiable () && scr.BaseType != null) {
755                                                 // 2.1.2 && 2.2: OK
756                                         }
757                                         else
758                                                 error (h, "Base complex type of a simple content restriction must be text only.");
759                                 } else {
760                                         if (sce != null && baseComplexType == null) {
761                                                 // 2.1.3 : OK
762                                         }
763                                         else
764                                                 error (h, "Not allowed base type of a simple content restriction.");
765                                 }
766                         }
767
768                         // complexType/complexContent/extension
769                         if (cce != null) {
770                                 // I don't think 3.4.6 Derivation Valid (Extension) :: 1.2
771                                 // is constraining anything here, since 3.4.2 {attribute uses}
772                                 // defines as to include base type's attribute uses.
773                                 localAnyAttribute = cce.AnyAttribute;
774                                 if (baseComplexType != null) {
775                                         foreach (DictionaryEntry entry in baseComplexType.AttributeUses) {
776                                                 XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
777                                                 XmlSchemaUtil.AddToTable (attributeUses, attr, attr.QualifiedName, h);
778                                         }
779                                         baseAnyAttribute = baseComplexType.AttributeWildcard;
780                                 }
781                                 // attributes
782                                 errorCount += XmlSchemaUtil.ValidateAttributesResolved (
783                                         this.attributeUses, h, schema, cce.Attributes, 
784                                         cce.AnyAttribute , ref attributeWildcard, null, true);
785
786                                 // After adding them, test extension validity.
787                                 if (baseComplexType != null)
788                                         this.ValidateComplexBaseDerivationValidExtension (baseComplexType, h, schema);
789                                 else if (baseSimpleType != null)
790                                         this.ValidateSimpleBaseDerivationValidExtension (baseSimpleType, h, schema);
791                         }
792                         // complexType/complexContent/restriction
793                         if (ccr != null) {
794                                 // For ValidationEventHandler.
795                                 if (baseComplexType == null)
796                                         baseComplexType = XmlSchemaComplexType.AnyType;
797
798                                 // attributes
799                                 localAnyAttribute = ccr.AnyAttribute;
800                                 this.attributeWildcard = localAnyAttribute;
801                                 if (baseComplexType != null)
802                                         baseAnyAttribute = baseComplexType.AttributeWildcard;
803                                 if (baseAnyAttribute != null && localAnyAttribute != null)
804                                         // 1.3 attribute wildcard subset. (=> 3.10.6)
805                                         localAnyAttribute.ValidateWildcardSubset (baseAnyAttribute, h, schema);
806
807                                 // 3.4.2 Complex Type Definition with complex content Schema Component
808                                 // and its {attribute uses} and {attribute wildcard} are done here (descendantly)
809                                 errorCount += XmlSchemaUtil.ValidateAttributesResolved (
810                                         this.attributeUses, h, schema, ccr.Attributes, 
811                                         ccr.AnyAttribute, ref attributeWildcard, null, false);
812                                 foreach (DictionaryEntry entry in baseComplexType.AttributeUses) {
813                                         XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
814                                         if (attributeUses [attr.QualifiedName] == null)
815                                                 XmlSchemaUtil.AddToTable (attributeUses, attr, attr.QualifiedName, h);
816                                 }
817
818                                 // Derivation Valid (Restriction, Complex) :: 5.
819                                 // Also see E1-15 of http://www.w3.org/2001/05/xmlschema-errata#Errata1
820                                 // 5.1 shouled be in scr (XmlSchemaSimpleContentRestriction)
821                                 this.ValidateDerivationValidRestriction (baseComplexType, h, schema);
822                         }
823                         // complexType/simpleContent/extension
824                         if (sce != null) {
825                                 errorCount += XmlSchemaUtil.ValidateAttributesResolved (
826                                         this.attributeUses, h, schema, sce.Attributes, 
827                                         sce.AnyAttribute, ref attributeWildcard, null, true);
828
829                                 // Attributes
830                                 // I don't think 3.4.6 Derivation Valid (Extension) :: 1.2
831                                 // is constraining anything here, since 3.4.2 {attribute uses}
832                                 // defines as to include base type's attribute uses.
833                                 localAnyAttribute = sce.AnyAttribute;
834
835                                 if (baseComplexType != null) {
836                                         baseAnyAttribute = baseComplexType.AttributeWildcard;
837
838                                         foreach (DictionaryEntry entry in baseComplexType.AttributeUses) {
839                                                 XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
840 #if BUGGY_MS_COMPLIANT
841                                                 if (attr.Use != XmlSchemaUse.Prohibited)
842                                                         XmlSchemaUtil.AddToTable (attributeUses, attr, attr.QualifiedName, h);
843 #endif
844                                                 XmlSchemaUtil.AddToTable (attributeUses, attr, attr.QualifiedName, h);
845                                         }
846                                 }
847                                 if (baseAnyAttribute != null && localAnyAttribute != null)
848                                         // 1.3 attribute wildcard subset. (=> 3.10.6)
849                                         localAnyAttribute.ValidateWildcardSubset (baseAnyAttribute, h, schema);
850                         }
851                         // complexType/simpleContent/restriction
852                         if (scr != null) {
853                                 // Attributes
854                                 baseAnyAttribute = baseComplexType != null ? baseComplexType.AttributeWildcard : null;
855
856                                 localAnyAttribute = scr.AnyAttribute;
857                                 if (localAnyAttribute != null && baseAnyAttribute != null)
858                                         // 1.3 attribute wildcard subset. (=> 3.10.6)
859                                         localAnyAttribute.ValidateWildcardSubset (baseAnyAttribute, h, schema);
860                                 // 3.4.6 :: 5.1. Beware that There is an errata for 5.1!!
861                                 // http://www.w3.org/2001/05/xmlschema-errata#Errata1
862
863                                 // 3.4.2 Complex Type Definition with simple content Schema Component
864                                 // and its {attribute uses} and {attribute wildcard} are done here (descendantly)
865                                 errorCount += XmlSchemaUtil.ValidateAttributesResolved (
866                                         this.attributeUses, h, schema, scr.Attributes, 
867                                         scr.AnyAttribute, ref attributeWildcard, null, false);
868                         }
869
870                         // Common process of AttributeWildcard.
871                         if (localAnyAttribute != null) {
872                                 this.attributeWildcard = localAnyAttribute;
873                         }
874                         else
875                                 this.attributeWildcard = baseAnyAttribute;
876                 }
877
878                 // 3.4.6 Type Derivation OK (Complex)
879                 internal void ValidateTypeDerivationOK (object b, ValidationEventHandler h, XmlSchema schema)
880                 {
881                         // AnyType derives from AnyType itself.
882                         if (this == XmlSchemaComplexType.AnyType && BaseXmlSchemaType == this)
883                                 return;
884
885                         XmlSchemaType bst = b as XmlSchemaType;
886                         if (b == this)  // 1 and 2.1
887                                 return;
888                         if (bst != null && (resolvedDerivedBy & bst.FinalResolved) != 0) // 1.
889                                 error (h, "Derivation type " + resolvedDerivedBy + " is prohibited by the base type.");
890                         // FIXME: here BaseSchemaType should be 
891                         // BaseXmlSchemaType, however for some case it 
892                         // seems not working.
893                         if (BaseSchemaType == b) // 2.2
894                                 return;
895                         if (BaseSchemaType == null || BaseXmlSchemaType == XmlSchemaComplexType.AnyType) { // 2.3.1
896                                 error (h, "Derived type's base schema type is anyType.");
897                                 return;
898                         }
899                         // 2.3.2.1
900                         XmlSchemaComplexType dbct = BaseXmlSchemaType as XmlSchemaComplexType;
901                         if (dbct != null) {
902                                 dbct.ValidateTypeDerivationOK (b, h, schema);
903                                 return;
904                         }
905                         // 2.3.2.2
906                         XmlSchemaSimpleType dbst = BaseXmlSchemaType as XmlSchemaSimpleType;
907                         if (dbst != null) {
908                                 dbst.ValidateTypeDerivationOK (b, h, schema, true);
909                                 return;
910                         }
911                 }
912
913                 // 3.4.6 Derivation Valid (Extension) - Term. 1 (Complex Type)
914                 internal void ValidateComplexBaseDerivationValidExtension (XmlSchemaComplexType baseComplexType,
915                         ValidationEventHandler h, XmlSchema schema)
916                 {
917                         // 1.1
918                         if ((baseComplexType.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0)
919                                 error (h, "Derivation by extension is prohibited.");
920                         // 1.2
921                         foreach (DictionaryEntry entry in baseComplexType.AttributeUses) {
922                                 XmlSchemaAttribute ba = (XmlSchemaAttribute) entry.Value;
923                                 XmlSchemaAttribute da = AttributeUses [ba.QualifiedName] as XmlSchemaAttribute;
924                                 if (da == null)
925                                         error (h, "Invalid complex type derivation by extension was found. Missing attribute was found: " + ba.QualifiedName + " .");
926                         }
927                         // 1.3 -> 3.10.6 Wildcard Subset.
928                         if (AnyAttribute != null) {
929                                 if (baseComplexType.AnyAttribute == null)
930                                         error (h, "Invalid complex type derivation by extension was found. Base complex type does not have an attribute wildcard.");
931                                 else
932                                         baseComplexType.AnyAttribute.ValidateWildcardSubset (AnyAttribute, h, schema);
933                         }
934
935                         // 1.4 => 1.4.2 (1.4.1 would be included in SimpleContentExtention).
936                         // 1.4.2.1
937 //                      if (contentTypeParticle == null)
938 //                              error (h, "Extended complex type's content type must not be empty.");
939                         // 1.4.2.2.1
940                         if (baseComplexType.ContentType != XmlSchemaContentType.Empty) {
941                                 // 1.4.2.2.2.1
942                                 if (this.ContentType != baseComplexType.ContentType)
943 //                              if (this.GetContentType (false) != baseComplexType.GetContentType (false))
944                                         error (h, "Base complex type has different content type " + baseComplexType.ContentType + ".");
945                                 // 1.4.2.2.2.2 => 3.9.6 Particle Valid (Extension)
946                                 else if (this.contentTypeParticle == null ||
947                                         !this.contentTypeParticle.ParticleEquals (baseComplexType.ContentTypeParticle)) {
948                                         XmlSchemaSequence seq = contentTypeParticle as XmlSchemaSequence;
949                                         if (contentTypeParticle != XmlSchemaParticle.Empty && (seq == null || contentTypeParticle.ValidatedMinOccurs != 1 || contentTypeParticle.ValidatedMaxOccurs != 1))
950                                                 error (h, "Invalid complex content extension was found.");
951                                         else {
952                                                 // Identical sequence item should be checked, but
953                                                 // I think it is naturally achieved as coded above.
954                                         }
955                                 }
956                         }
957                 }
958
959                 // 3.4.6 Derivation Valid (Extension) - Term. 2 (Simple Type)
960                 internal void ValidateSimpleBaseDerivationValidExtension (object baseType,
961                         ValidationEventHandler h, XmlSchema schema)
962                 {
963                         XmlSchemaSimpleType st = baseType as XmlSchemaSimpleType;
964                         if (st != null && (st.FinalResolved & XmlSchemaDerivationMethod.Extension) != 0)
965                                 error (h, "Extension is prohibited by the base type.");
966
967                         XmlSchemaDatatype dt = baseType as XmlSchemaDatatype;
968                         if (dt == null)
969                                 dt = st.Datatype;
970                         if (dt != this.Datatype)
971                                 error (h, "To extend simple type, a complex type must have the same content type as the base type.");
972                 }
973
974                 internal void ValidateDerivationValidRestriction (XmlSchemaComplexType baseType,
975                         ValidationEventHandler h, XmlSchema schema)
976                 {
977                         // 1.
978                         if (baseType == null) {
979                                 error (h, "Base schema type is not a complex type.");
980                                 return;
981                         }
982                         if ((baseType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0) {
983                                 error (h, "Prohibited derivation by restriction by base schema type.");
984                                 return;
985                         }
986
987                         // 2.
988                         foreach (DictionaryEntry entry in this.AttributeUses) {
989                                 XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
990                                 XmlSchemaAttribute baseAttr = baseType.AttributeUses [attr.QualifiedName] as XmlSchemaAttribute;
991                                 if (baseAttr != null) {
992                                         // 2.1
993                                         // 2.1.1
994                                         if (baseAttr.ValidatedUse != XmlSchemaUse.Optional && attr.ValidatedUse != XmlSchemaUse.Required)
995                                                 error (h, "Invalid attribute derivation by restriction was found for " + attr.QualifiedName + " .");
996                                         // 2.1.2
997                                         XmlSchemaSimpleType attrSimpleType = attr.AttributeType as XmlSchemaSimpleType;
998                                         XmlSchemaSimpleType baseAttrSimpleType = baseAttr.AttributeType as XmlSchemaSimpleType;
999                                         bool typeError = false;
1000                                         if (attrSimpleType != null)
1001                                                 attrSimpleType.ValidateDerivationValid (baseAttrSimpleType, null, h, schema);
1002                                         else if (attrSimpleType == null && baseAttrSimpleType != null)
1003                                                 typeError = true;
1004                                         else {
1005                                                 Type t1 = attr.AttributeType.GetType ();
1006                                                 Type t2 = baseAttr.AttributeType.GetType ();
1007                                                 if (t1 != t2 && t1.IsSubclassOf (t2))
1008                                                         typeError = true;
1009                                         }
1010                                         if (typeError)
1011                                                 error (h, "Invalid attribute derivation by restriction because of its type: " + attr.QualifiedName + " .");
1012                                         // 2.1.3
1013                                         if (baseAttr.ValidatedFixedValue != null && attr.ValidatedFixedValue != baseAttr.ValidatedFixedValue)
1014                                                 error (h, "Invalid attribute derivation by restriction because of its fixed value constraint: " + attr.QualifiedName + " .");
1015                                 } else {
1016                                         // 2.2
1017                                         if (baseType.AttributeWildcard != null)
1018                                                 if (!baseType.AttributeWildcard.ValidateWildcardAllowsNamespaceName (
1019                                                         attr.QualifiedName.Namespace, schema) &&
1020                                                         !schema.IsNamespaceAbsent (attr.QualifiedName.Namespace))
1021                                                         error (h, "Invalid attribute derivation by restriction was found for " + attr.QualifiedName + " .");
1022                                 }
1023                         }
1024                         // I think 3. is considered in 2.
1025                         // 4.
1026                         if (this.AttributeWildcard != null && baseType != XmlSchemaComplexType.AnyType) {
1027                                 if (baseType.AttributeWildcard == null)
1028                                         error (h, "Invalid attribute derivation by restriction because of attribute wildcard.");
1029                                 else
1030                                         AttributeWildcard.ValidateWildcardSubset (baseType.AttributeWildcard, h, schema);
1031                         }
1032
1033                         // 5.
1034                         if (this == AnyType)
1035                                 return;
1036                         if (contentTypeParticle == XmlSchemaParticle.Empty) {
1037                                 // 5.1
1038                                 if (ContentType != XmlSchemaContentType.Empty) {
1039                                         // TODO: 5.1.1
1040 //                                      XmlSchemaSimpleType baseST = baseType as XmlSchemaSimpleType;
1041                                         // 5.1.2
1042                                         if (baseType.ContentType == XmlSchemaContentType.Mixed && !baseType.ContentTypeParticle.ValidateIsEmptiable ())
1043                                                 error (h, "Invalid content type derivation.");
1044
1045                                 } else {
1046                                         // 5.2
1047                                         if (baseType.ContentTypeParticle != XmlSchemaParticle.Empty &&
1048                                                 !baseType.ContentTypeParticle.ValidateIsEmptiable ())
1049                                                 error (h, "Invalid content type derivation.");
1050                                 }
1051                         } else {
1052                                 // 5.3 => 3.9.6 Particle Valid (Restriction)
1053                                 if (baseType.ContentTypeParticle != null) {
1054                                         // 3.9.6 - 1 : same particle.
1055                                         // 3.9.6 - 2 is covered by using ActualParticle.
1056                                         if (!contentTypeParticle.ParticleEquals (baseType.ContentTypeParticle))
1057                                                 contentTypeParticle.ValidateDerivationByRestriction (baseType.ContentTypeParticle, h, schema, true);
1058                                 }
1059                         }
1060                 }
1061
1062 #region Read
1063                 //<complexType
1064                 //  abstract = boolean : false
1065                 //  block = (#all | List of (extension | restriction)) 
1066                 //  final = (#all | List of (extension | restriction)) 
1067                 //  id = ID
1068                 //  mixed = boolean : false
1069                 //  name = NCName
1070                 //  {any attributes with non-schema namespace . . .}>
1071                 //  Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
1072                 //</complexType>
1073                 internal static XmlSchemaComplexType Read(XmlSchemaReader reader, ValidationEventHandler h)
1074                 {
1075                         XmlSchemaComplexType ctype = new XmlSchemaComplexType();
1076                         reader.MoveToElement();
1077                         Exception innerex;
1078
1079                         if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)
1080                         {
1081                                 error(h,"Should not happen :1: XmlSchemaComplexType.Read, name="+reader.Name,null);
1082                                 reader.SkipToEnd();
1083                                 return null;
1084                         }
1085
1086                         ctype.LineNumber = reader.LineNumber;
1087                         ctype.LinePosition = reader.LinePosition;
1088                         ctype.SourceUri = reader.BaseURI;
1089
1090                         while(reader.MoveToNextAttribute())
1091                         {
1092                                 if(reader.Name == "abstract")
1093                                 {
1094                                         ctype.IsAbstract = XmlSchemaUtil.ReadBoolAttribute(reader,out innerex);
1095                                         if(innerex != null)
1096                                                 error(h,reader.Value + " is invalid value for abstract",innerex);
1097                                 }
1098                                 else if(reader.Name == "block")
1099                                 {
1100                                         ctype.block = XmlSchemaUtil.ReadDerivationAttribute(reader,out innerex, "block",
1101                                                 XmlSchemaUtil.ComplexTypeBlockAllowed);
1102                                         if(innerex != null)
1103                                                 error (h,"some invalid values for block attribute were found",innerex);
1104                                 }
1105                                 else if(reader.Name == "final")
1106                                 {
1107                                         ctype.Final = XmlSchemaUtil.ReadDerivationAttribute(reader,out innerex, "final",
1108                                                 XmlSchemaUtil.FinalAllowed);
1109                                         if(innerex != null)
1110                                                 error (h,"some invalid values for final attribute were found",innerex);
1111                                 }
1112                                 else if(reader.Name == "id")
1113                                 {
1114                                         ctype.Id = reader.Value;
1115                                 }
1116                                 else if(reader.Name == "mixed")
1117                                 {
1118                                         ctype.isMixed = XmlSchemaUtil.ReadBoolAttribute(reader,out innerex);
1119                                         if(innerex != null)
1120                                                 error(h,reader.Value + " is invalid value for mixed",innerex);
1121                                 }
1122                                 else if(reader.Name == "name")
1123                                 {
1124                                         ctype.Name = reader.Value;
1125                                 }
1126                                 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
1127                                 {
1128                                         error(h,reader.Name + " is not a valid attribute for complexType",null);
1129                                 }
1130                                 else
1131                                 {
1132                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,ctype);
1133                                 }
1134                         }
1135                         
1136                         reader.MoveToElement();
1137                         if(reader.IsEmptyElement)
1138                                 return ctype;
1139
1140                         //Content: 1. annotation?, 
1141                         //                 2. simpleContent | 2. complexContent | 
1142                         //                      (3.(group | all | choice | sequence)?, (4.(attribute | attributeGroup)*, 5.anyAttribute?)))
1143                         int level = 1;
1144                         while(reader.ReadNextElement())
1145                         {
1146                                 if(reader.NodeType == XmlNodeType.EndElement)
1147                                 {
1148                                         if(reader.LocalName != xmlname)
1149                                                 error(h,"Should not happen :2: XmlSchemaComplexType.Read, name="+reader.Name,null);
1150                                         break;
1151                                 }
1152                                 if(level <= 1 && reader.LocalName == "annotation")
1153                                 {
1154                                         level = 2; //Only one annotation
1155                                         XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
1156                                         if(annotation != null)
1157                                                 ctype.Annotation = annotation;
1158                                         continue;
1159                                 }
1160                                 if(level <=2)
1161                                 {
1162                                         if(reader.LocalName == "simpleContent")
1163                                         {
1164                                                 level = 6;
1165                                                 XmlSchemaSimpleContent simple = XmlSchemaSimpleContent.Read(reader,h);
1166                                                 if(simple != null)
1167                                                         ctype.ContentModel = simple;
1168                                                 continue;
1169                                         }
1170                                         if(reader.LocalName == "complexContent")
1171                                         {
1172                                                 level = 6;
1173                                                 XmlSchemaComplexContent complex = XmlSchemaComplexContent.Read(reader,h);
1174                                                 if(complex != null)
1175                                                         ctype.contentModel = complex;
1176                                                 continue;
1177                                         }
1178                                 }
1179                                 if(level <= 3)
1180                                 {
1181                                         if(reader.LocalName == "group")
1182                                         {
1183                                                 level = 4;
1184                                                 XmlSchemaGroupRef group = XmlSchemaGroupRef.Read(reader,h);
1185                                                 if(group != null)
1186                                                         ctype.particle = group;
1187                                                 continue;
1188                                         }
1189                                         if(reader.LocalName == "all")
1190                                         {
1191                                                 level = 4;
1192                                                 XmlSchemaAll all = XmlSchemaAll.Read(reader,h);
1193                                                 if(all != null)
1194                                                         ctype.particle = all;
1195                                                 continue;
1196                                         }
1197                                         if(reader.LocalName == "choice")
1198                                         {
1199                                                 level = 4;
1200                                                 XmlSchemaChoice choice = XmlSchemaChoice.Read(reader,h);
1201                                                 if(choice != null)
1202                                                         ctype.particle = choice;
1203                                                 continue;
1204                                         }
1205                                         if(reader.LocalName == "sequence")
1206                                         {
1207                                                 level = 4;
1208                                                 XmlSchemaSequence sequence = XmlSchemaSequence.Read(reader,h);
1209                                                 if(sequence != null)
1210                                                         ctype.particle = sequence;
1211                                                 continue;
1212                                         }
1213                                 }
1214                                 if(level <= 4)
1215                                 {
1216                                         if(reader.LocalName == "attribute")
1217                                         {
1218                                                 level = 4;
1219                                                 XmlSchemaAttribute attr = XmlSchemaAttribute.Read(reader,h);
1220                                                 if(attr != null)
1221                                                         ctype.Attributes.Add(attr);
1222                                                 continue;
1223                                         }
1224                                         if(reader.LocalName == "attributeGroup")
1225                                         {
1226                                                 level = 4;
1227                                                 XmlSchemaAttributeGroupRef attr = XmlSchemaAttributeGroupRef.Read(reader,h);
1228                                                 if(attr != null)
1229                                                         ctype.attributes.Add(attr);
1230                                                 continue;
1231                                         }
1232                                 }
1233                                 if(level <= 5 && reader.LocalName == "anyAttribute")
1234                                 {
1235                                         level = 6;
1236                                         XmlSchemaAnyAttribute anyattr = XmlSchemaAnyAttribute.Read(reader,h);
1237                                         if(anyattr != null)
1238                                                 ctype.AnyAttribute = anyattr;
1239                                         continue;
1240                                 }
1241                                 reader.RaiseInvalidElementError();
1242                         }
1243                         return ctype;
1244                 }
1245 #endregion
1246         }
1247 }