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