Add MIT license to System.XML.DLL
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaSimpleType.cs
1 //\r
2 // System.Xml.Schema.XmlSchemaSimpleType.cs\r
3 //\r
4 // Author:\r
5 //      Dwivedi, Ajay kumar  Adwiv@Yahoo.com\r
6 //      Atsushi Enomoto  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.Xml.Serialization;\r
31 using System.Xml;\r
32 using Mono.Xml.Schema;\r
33 \r
34 namespace System.Xml.Schema\r
35 {\r
36         /// <summary>\r
37         /// Summary description for XmlSchemaSimpleType.\r
38         /// </summary>\r
39         public class XmlSchemaSimpleType : XmlSchemaType\r
40         {\r
41                 const string xmlname = "simpleType";\r
42                 private static XmlSchemaSimpleType schemaLocationType;\r
43 \r
44                 private XmlSchemaSimpleTypeContent content;\r
45                 //compilation vars\r
46                 internal bool islocal = true; // Assuming local means we have to specify islocal=false only in XmlSchema\r
47                 private bool recursed;\r
48                 private XmlSchemaDerivationMethod variety;\r
49 \r
50                 static XmlSchemaSimpleType ()\r
51                 {\r
52                         // This is not used in the meantime.\r
53                         XmlSchemaSimpleType st = new XmlSchemaSimpleType ();\r
54                         XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList ();\r
55                         list.ItemTypeName = new XmlQualifiedName ("anyURI", XmlSchema.Namespace);\r
56                         st.Content = list;\r
57                         st.BaseXmlSchemaTypeInternal = null;\r
58                         st.variety = XmlSchemaDerivationMethod.List;\r
59                         schemaLocationType = st;\r
60                 }\r
61 \r
62                 internal static XsdAnySimpleType AnySimpleType {\r
63                         get { return XsdAnySimpleType.Instance; }\r
64                 }\r
65 \r
66                 internal static XmlSchemaSimpleType SchemaLocationType {\r
67                         get { return schemaLocationType; }\r
68                 }\r
69 \r
70                 public XmlSchemaSimpleType()\r
71                 {\r
72                 }\r
73 \r
74                 [XmlElement("restriction",typeof(XmlSchemaSimpleTypeRestriction),Namespace=XmlSchema.Namespace)]\r
75                 [XmlElement("list",typeof(XmlSchemaSimpleTypeList),Namespace=XmlSchema.Namespace)]\r
76                 [XmlElement("union",typeof(XmlSchemaSimpleTypeUnion),Namespace=XmlSchema.Namespace)]\r
77                 public XmlSchemaSimpleTypeContent Content\r
78                 {\r
79                         get{ return  content; } \r
80                         set{ content = value; }\r
81                 }\r
82 \r
83                 internal XmlSchemaDerivationMethod Variety\r
84                 {\r
85                         get{ return variety; }\r
86                 }\r
87 \r
88                 /// <remarks>\r
89                 /// For a simple Type:\r
90                 ///             1. Content must be present\r
91                 ///             2. id if present, must have be a valid ID\r
92                 ///             a) If the simpletype is local\r
93                 ///                     1-      are from <xs:complexType name="simpleType"> and <xs:complexType name="localSimpleType">\r
94                 ///                     1. name  is prohibited\r
95                 ///                     2. final is prohibited\r
96                 ///             b) If the simpletype is toplevel\r
97                 ///                     1-  are from <xs:complexType name="simpleType"> and <xs:complexType name="topLevelSimpleType">\r
98                 ///                     1. name is required, type must be NCName\r
99                 ///                     2. Content is required\r
100                 ///                     3. final can have values : #all | (list | union | restriction)\r
101                 ///                     4. If final is set, finalResolved is same as final (but within the values of b.3)\r
102                 ///                     5. If final is not set, the finalDefault of the schema (ie. only #all and restriction)\r
103                 ///                     6. Base type is:\r
104                 ///                             4.1 If restriction is chosen,the base type of restriction or elements\r
105                 ///                             4.2 otherwise simple ur-type\r
106                 /// </remarks>\r
107                 internal override int Compile(ValidationEventHandler h, XmlSchema schema)\r
108                 {\r
109                         // If this is already compiled this time, simply skip.\r
110                         if (this.IsComplied (schema.CompilationId))\r
111                                 return 0;\r
112 \r
113                         errorCount = 0;\r
114 \r
115                         if(this.islocal) // a\r
116                         {\r
117                                 if(this.Name != null) // a.1\r
118                                         error(h,"Name is prohibited in a local simpletype");\r
119                                 else\r
120                                         this.QNameInternal = new XmlQualifiedName(this.Name,schema.TargetNamespace);\r
121                                 if(this.Final != XmlSchemaDerivationMethod.None) //a.2\r
122                                         error(h,"Final is prohibited in a local simpletype");\r
123                         }\r
124                         else //b\r
125                         {\r
126                                 if(this.Name == null) //b.1\r
127                                         error(h,"Name is required in top level simpletype");\r
128                                 else if(!XmlSchemaUtil.CheckNCName(this.Name)) // b.1.2\r
129                                         error(h,"name attribute of a simpleType must be NCName");\r
130                                 else\r
131                                         this.QNameInternal = new XmlQualifiedName(this.Name,schema.TargetNamespace);\r
132                                 \r
133                                 //NOTE: Although the FinalResolved can be Empty, it is not a valid value for Final\r
134                                 //DEVIATION: If an error occurs, the finaldefault is always consulted. This deviates\r
135                                 //                       from the way MS implementation works.\r
136                                 switch(this.Final) //b.3, b.4\r
137                                 {\r
138                                         case XmlSchemaDerivationMethod.All:\r
139                                                 this.finalResolved = XmlSchemaDerivationMethod.All;\r
140                                                 break;\r
141                                         case XmlSchemaDerivationMethod.List:\r
142                                         case XmlSchemaDerivationMethod.Union:\r
143                                         case XmlSchemaDerivationMethod.Restriction:\r
144                                                 this.finalResolved = Final;\r
145                                                 break;\r
146                                         default:\r
147                                                 error(h,"The value of final attribute is not valid for simpleType");\r
148                                                 goto case XmlSchemaDerivationMethod.None;\r
149                                                 // use assignment from finaldefault on schema.\r
150                                         case XmlSchemaDerivationMethod.None: // b.5\r
151                                                 XmlSchemaDerivationMethod flags = \r
152                                                         (XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.List |\r
153                                                         XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Union );\r
154                                                 switch (schema.FinalDefault) {\r
155                                                 case XmlSchemaDerivationMethod.All:\r
156                                                         finalResolved = XmlSchemaDerivationMethod.All;\r
157                                                         break;\r
158                                                 case XmlSchemaDerivationMethod.None:\r
159                                                         finalResolved = XmlSchemaDerivationMethod.Empty;\r
160                                                         break;\r
161                                                 default:\r
162                                                         finalResolved = schema.FinalDefault & flags;\r
163                                                         break;\r
164                                                 }\r
165                                                 break;\r
166                                 }\r
167                         }\r
168 \r
169                         XmlSchemaUtil.CompileID(Id,this,schema.IDCollection,h);\r
170 \r
171                         if (Content != null)\r
172                                 Content.OwnerType = this;\r
173 \r
174                         if(this.Content == null) //a.3,b.2\r
175                                 error(h,"Content is required in a simpletype");\r
176                         else if(Content is XmlSchemaSimpleTypeRestriction)\r
177                         {\r
178                                 this.resolvedDerivedBy = XmlSchemaDerivationMethod.Restriction;\r
179                                 errorCount += ((XmlSchemaSimpleTypeRestriction)Content).Compile(h,schema);\r
180                         }\r
181                         else if(Content is XmlSchemaSimpleTypeList)\r
182                         {\r
183                                 this.resolvedDerivedBy = XmlSchemaDerivationMethod.List;\r
184                                 errorCount += ((XmlSchemaSimpleTypeList)Content).Compile(h,schema);\r
185                         }\r
186                         else if(Content is XmlSchemaSimpleTypeUnion)\r
187                         {\r
188                                 this.resolvedDerivedBy = XmlSchemaDerivationMethod.Union;\r
189                                 errorCount += ((XmlSchemaSimpleTypeUnion)Content).Compile(h,schema);\r
190                         }\r
191 \r
192                         this.CompilationId = schema.CompilationId;\r
193                         return errorCount;\r
194                 }\r
195 \r
196                 internal void CollectBaseType (ValidationEventHandler h, XmlSchema schema)\r
197                 {\r
198                         if (Content is XmlSchemaSimpleTypeRestriction) {\r
199                                 object o = ((XmlSchemaSimpleTypeRestriction) Content).GetActualType (h, schema, false);\r
200                                 BaseXmlSchemaTypeInternal = o as XmlSchemaSimpleType;\r
201                                 if (BaseXmlSchemaTypeInternal != null)\r
202                                         DatatypeInternal = BaseXmlSchemaTypeInternal.Datatype;\r
203                                 else\r
204                                         DatatypeInternal = o as XmlSchemaDatatype;\r
205                         }\r
206                         // otherwise, actualBaseSchemaType is null\r
207                         else\r
208                                 DatatypeInternal = XmlSchemaSimpleType.AnySimpleType;\r
209                 }\r
210                 \r
211                 internal override int Validate(ValidationEventHandler h, XmlSchema schema)\r
212                 {\r
213                         // 3.14.6 Properties Correct.\r
214                         // \r
215                         // 1. Post Compilation Properties\r
216                         // {name}, {target namespace} => QNameInternal. Already Compile()d.\r
217                         // {base type definition} => baseSchemaTypeInternal\r
218                         // {final} => finalResolved. Already Compile()d.\r
219                         // {variety} => resolvedDerivedBy. Already Compile()d.\r
220                         //\r
221                         // 2. Should be checked by "recursed" field.\r
222 \r
223                         if(IsValidated (schema.ValidationId))\r
224                                 return errorCount;\r
225 \r
226                         if (recursed) {\r
227                                 error (h, "Circular type reference was found.");\r
228                                 return errorCount;\r
229                         }\r
230                         recursed = true;\r
231 \r
232                         CollectBaseType (h, schema);\r
233 \r
234                         if (content != null)\r
235                                 errorCount += content.Validate (h, schema);\r
236 \r
237 /*\r
238                         // BaseSchemaType property\r
239                         BaseXmlSchemaTypeInternal = content.ActualBaseSchemaType as XmlSchemaType;\r
240                         if (this.BaseXmlSchemaTypeInternal == null)\r
241                                 this.DatatypeInternal = content.ActualBaseSchemaType as XmlSchemaDatatype;\r
242 */\r
243 \r
244                         // Datatype property\r
245                         XmlSchemaSimpleType simple = BaseXmlSchemaType as XmlSchemaSimpleType;\r
246                         if (simple != null)\r
247                                 this.DatatypeInternal = simple.Datatype;\r
248 //                      else\r
249 //                              DatatypeInternal = BaseSchemaType as XmlSchemaDatatype;\r
250 \r
251                         // 3.\r
252                         XmlSchemaSimpleType baseSType = BaseXmlSchemaType as XmlSchemaSimpleType;\r
253                         if (baseSType != null) {\r
254                                 if ((baseSType.FinalResolved & this.resolvedDerivedBy) != 0)\r
255                                         error (h, "Specified derivation is prohibited by the base simple type.");\r
256                         }\r
257 \r
258                         // {variety}\r
259                         if (this.resolvedDerivedBy == XmlSchemaDerivationMethod.Restriction &&\r
260                                 baseSType != null)\r
261                                 this.variety = baseSType.Variety;\r
262                         else\r
263                                 this.variety = this.resolvedDerivedBy;\r
264 \r
265                         // 3.14.6 Derivation Valid (Restriction, Simple)\r
266                         XmlSchemaSimpleTypeRestriction r = Content as XmlSchemaSimpleTypeRestriction;\r
267                         object baseType = BaseXmlSchemaType != null ? (object) BaseXmlSchemaType : Datatype;\r
268                         if (r != null)\r
269                                 ValidateDerivationValid (baseType, r.Facets, h, schema);\r
270 \r
271                         // TODO: describe which validation term this belongs to.\r
272                         XmlSchemaSimpleTypeList l = Content as XmlSchemaSimpleTypeList;\r
273                         if (l != null) {\r
274                                 XmlSchemaSimpleType itemSimpleType = l.ValidatedListItemType as XmlSchemaSimpleType;\r
275                                 if (itemSimpleType != null && itemSimpleType.Content is XmlSchemaSimpleTypeList)\r
276                                         error (h, "List type must not be derived from another list type.");\r
277                         }\r
278 \r
279                         recursed = false;\r
280                         ValidationId = schema.ValidationId;\r
281                         return errorCount;\r
282                 }\r
283 \r
284                 // 3.14.6 Derivation Valid (RestrictionSimple)
285                 internal void ValidateDerivationValid (object baseType, XmlSchemaObjectCollection facets,
286                         ValidationEventHandler h, XmlSchema schema)
287                 {
288                         // TODO
289                         XmlSchemaSimpleType baseSimpleType = baseType as XmlSchemaSimpleType;
290                         switch (this.Variety) {
291                         // 1. atomic type
292                         case XmlSchemaDerivationMethod.Restriction:
293                                 // 1.1
294                                 if (baseSimpleType != null && baseSimpleType.resolvedDerivedBy != XmlSchemaDerivationMethod.Restriction)
295                                         error (h, "Base schema type is not either atomic type or primitive type.");
296                                 // 1.2
297                                 if (baseSimpleType != null && 
298                                         (baseSimpleType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0)
299                                         error (h, "Derivation by restriction is prohibited by the base simple type.");
300                                 // TODO: 1.3 facet restriction valid.
301                                 break;
302                         case XmlSchemaDerivationMethod.List:
303                                 XmlSchemaSimpleTypeList thisList = Content as XmlSchemaSimpleTypeList;
304                                 /*
305                                 // 2.1 item list type not allowed
306                                 if (baseSimpleType != null && baseSimpleType.resolvedDerivedBy == XmlSchemaDerivationMethod.List)
307                                         error (h, "Base list schema type is not allowed.");
308                                 XmlSchemaSimpleTypeUnion baseUnion = baseSimpleType.Content as XmlSchemaSimpleTypeUnion;
309                                 if (baseUnion != null) {
310                                         bool errorFound = false;
311                                         foreach (object memberType in baseUnion.ValidatedTypes) {
312                                                 XmlSchemaSimpleType memberST = memberType as XmlSchemaSimpleType;
313                                                 if (memberST != null && memberST.resolvedDerivedBy == XmlSchemaDerivationMethod.List)
314                                                         errorFound = true;
315                                         }
316                                         if (errorFound)
317                                                 error (h, "Base union schema type should not contain list types.");
318                                 }
319                                 */
320                                 // 2.2 facets limited
321                                 if (facets != null)
322                                         foreach (XmlSchemaFacet facet in facets) {
323                                                 if (facet is XmlSchemaLengthFacet ||
324                                                         facet is XmlSchemaMaxLengthFacet ||
325                                                         facet is XmlSchemaMinLengthFacet ||
326                                                         facet is XmlSchemaEnumerationFacet ||
327                                                         facet is XmlSchemaPatternFacet)
328                                                         continue;
329                                                 else
330                                                         error (h, "Not allowed facet was found on this simple type which derives list type.");
331                                         }
332                                 break;
333                         case XmlSchemaDerivationMethod.Union:
334                                 // 3.1
335
336                                 // 3.2
337                                 if (facets != null)
338                                         foreach (XmlSchemaFacet facet in facets) {
339                                                 if (facet is XmlSchemaEnumerationFacet ||
340                                                         facet is XmlSchemaPatternFacet)
341                                                         continue;
342                                                 else
343                                                         error (h, "Not allowed facet was found on this simple type which derives list type.");
344                                         }
345                                 break;
346                         }
347                 }
348
349                 // 3.14.6 Type Derivation OK (Simple)
350                 internal bool ValidateTypeDerivationOK (object baseType,
351                         ValidationEventHandler h, XmlSchema schema, bool raiseError)
352                 {
353                         // 1
354                         // Note that anyType should also be allowed as anySimpleType.
355                         if (this == baseType || baseType == XmlSchemaSimpleType.AnySimpleType ||
356                                 baseType == XmlSchemaComplexType.AnyType)
357                                 return true;
358
359                         // 2.1
360                         XmlSchemaSimpleType baseSimpleType = baseType as XmlSchemaSimpleType;
361                         if (baseSimpleType != null && 
362                                 (baseSimpleType.FinalResolved & resolvedDerivedBy) != 0) {
363                                 if (raiseError)
364                                         error (h, "Specified derivation is prohibited by the base type.");
365                                 return false;
366                         }
367
368                         // 2.2.1
369                         if (BaseXmlSchemaType == baseType || Datatype == baseType)
370                                 return true;
371
372                         // 2.2.2
373                         XmlSchemaSimpleType thisBaseSimpleType = BaseXmlSchemaType as XmlSchemaSimpleType;
374                         if (thisBaseSimpleType != null) {
375                                 if (thisBaseSimpleType.ValidateTypeDerivationOK (baseType, h, schema, false))
376                                         return true;
377                         }
378
379                         // 2.2.3
380                         switch (Variety) {
381                         case XmlSchemaDerivationMethod.Union:
382                         case XmlSchemaDerivationMethod.List:
383                                 if (baseType == XmlSchemaSimpleType.AnySimpleType)
384                                         return true;
385                                 break;
386                         }
387
388                         // 2.2.4 validly derived from one of the union member type.
389                         if (baseSimpleType != null && baseSimpleType.Variety == XmlSchemaDerivationMethod.Union) {
390                                 foreach (object memberType in ((XmlSchemaSimpleTypeUnion) baseSimpleType.Content).ValidatedTypes)
391                                         if (this.ValidateTypeDerivationOK (memberType, h, schema, false))
392                                                 return true;
393                         }
394
395                         if (raiseError)
396                                 error(h, "Invalid simple type derivation was found.");
397                         return false;
398                 }
399
400                 internal string Normalize (string s, XmlNameTable nt, XmlNamespaceManager nsmgr)
401                 {
402                         return Content.Normalize (s, nt, nsmgr);
403                 }
404
405                 //<simpleType \r
406                 //  final = (#all | (list | union | restriction)) \r
407                 //  id = ID \r
408                 //  name = NCName \r
409                 //  {any attributes with non-schema namespace . . .}>\r
410                 //  Content: (annotation?, (restriction | list | union))\r
411                 //</simpleType>\r
412                 internal static XmlSchemaSimpleType Read(XmlSchemaReader reader, ValidationEventHandler h)\r
413                 {\r
414                         XmlSchemaSimpleType stype = new XmlSchemaSimpleType();\r
415                         reader.MoveToElement();\r
416 \r
417                         if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)\r
418                         {\r
419                                 error(h,"Should not happen :1: XmlSchemaGroup.Read, name="+reader.Name,null);\r
420                                 reader.Skip();\r
421                                 return null;\r
422                         }\r
423 \r
424                         stype.LineNumber = reader.LineNumber;\r
425                         stype.LinePosition = reader.LinePosition;\r
426                         stype.SourceUri = reader.BaseURI;\r
427 \r
428                         while(reader.MoveToNextAttribute())\r
429                         {\r
430                                 if(reader.Name == "final")\r
431                                 {\r
432                                         Exception innerex;\r
433                                         stype.Final = XmlSchemaUtil.ReadDerivationAttribute(reader, out innerex, "final",\r
434                                                 XmlSchemaUtil.FinalAllowed);\r
435                                         if(innerex != null)\r
436                                                 error(h, "some invalid values not a valid value for final", innerex);\r
437                                 }\r
438                                 else if(reader.Name == "id")\r
439                                 {\r
440                                         stype.Id = reader.Value;\r
441                                 }\r
442                                 else if(reader.Name == "name")\r
443                                 {\r
444                                         stype.Name = reader.Value;\r
445                                 }\r
446                                 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)\r
447                                 {\r
448                                         error(h,reader.Name + " is not a valid attribute for simpleType",null);\r
449                                 }\r
450                                 else\r
451                                 {\r
452                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,stype);\r
453                                 }\r
454                         }\r
455                         \r
456                         reader.MoveToElement();\r
457                         if(reader.IsEmptyElement)\r
458                                 return stype;\r
459 \r
460                         //      Content: (annotation?, (restriction | list | union))\r
461                         int level = 1;\r
462                         while(reader.ReadNextElement())\r
463                         {\r
464                                 if(reader.NodeType == XmlNodeType.EndElement)\r
465                                 {\r
466                                         if(reader.LocalName != xmlname)\r
467                                                 error(h,"Should not happen :2: XmlSchemaSimpleType.Read, name="+reader.Name,null);\r
468                                         break;\r
469                                 }\r
470                                 if(level <= 1 && reader.LocalName == "annotation")\r
471                                 {\r
472                                         level = 2; //Only one annotation\r
473                                         XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
474                                         if(annotation != null)\r
475                                                 stype.Annotation = annotation;\r
476                                         continue;\r
477                                 }\r
478                                 if(level <= 2)\r
479                                 {\r
480                                         if(reader.LocalName == "restriction")\r
481                                         {\r
482                                                 level = 3;\r
483                                                 XmlSchemaSimpleTypeRestriction restriction = XmlSchemaSimpleTypeRestriction.Read(reader,h);\r
484                                                 if(restriction != null)\r
485                                                         stype.content = restriction;\r
486                                                 continue;\r
487                                         }\r
488                                         if(reader.LocalName == "list")\r
489                                         {\r
490                                                 level = 3;\r
491                                                 XmlSchemaSimpleTypeList list = XmlSchemaSimpleTypeList.Read(reader,h);\r
492                                                 if(list != null)\r
493                                                         stype.content = list;\r
494                                                 continue;\r
495                                         }\r
496                                         if(reader.LocalName == "union")\r
497                                         {\r
498                                                 level = 3;\r
499                                                 XmlSchemaSimpleTypeUnion union = XmlSchemaSimpleTypeUnion.Read(reader,h);\r
500                                                 if(union != null)\r
501                                                         stype.content = union;\r
502                                                 continue;\r
503                                         }\r
504                                 }\r
505                                 reader.RaiseInvalidElementError();\r
506                         }\r
507                         return stype;\r
508                 }\r
509 \r
510 \r
511         }\r
512 }\r