2006-08-26 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaAll.cs
1 //\r
2 // System.Xml.Schema.XmlSchemaAll.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.Collections;\r
31 using System.Xml;\r
32 using System.Xml.Serialization;\r
33 \r
34 namespace System.Xml.Schema\r
35 {\r
36         /// <summary>\r
37         /// Summary description for XmlSchemaAll.\r
38         /// </summary>\r
39         public class XmlSchemaAll : XmlSchemaGroupBase\r
40         {\r
41                 private XmlSchema schema;\r
42                 private XmlSchemaObjectCollection items;\r
43                 const string xmlname = "all";\r
44                 private bool emptiable;\r
45 \r
46                 public XmlSchemaAll()\r
47                 {\r
48                         items = new XmlSchemaObjectCollection();\r
49                 }\r
50 \r
51                 [XmlElement("element",typeof(XmlSchemaElement))]\r
52                 public override XmlSchemaObjectCollection Items \r
53                 {\r
54                         get{ return items; }\r
55                 }\r
56 \r
57                 internal bool Emptiable\r
58                 {\r
59                         get { return emptiable; }\r
60                 }\r
61 \r
62 \r
63                 /// <remarks>\r
64                 /// 1. MaxOccurs must be one. (default is also one)\r
65                 /// 2. MinOccurs must be zero or one.\r
66                 /// </remarks>\r
67                 internal override int Compile(ValidationEventHandler h, XmlSchema schema)\r
68                 {\r
69                         // If this is already compiled this time, simply skip.\r
70                         if (CompilationId == schema.CompilationId)\r
71                                 return 0;\r
72 \r
73                         this.schema = schema;\r
74 \r
75                         if(MaxOccurs != Decimal.One)\r
76                                 error(h,"maxOccurs must be 1");\r
77                         if(MinOccurs != Decimal.One && MinOccurs != Decimal.Zero)\r
78                                 error(h,"minOccurs must be 0 or 1");\r
79 \r
80                         XmlSchemaUtil.CompileID(Id, this, schema.IDCollection, h);\r
81                         CompileOccurence (h, schema);\r
82 \r
83                         foreach(XmlSchemaObject obj in Items)\r
84                         {\r
85 #if NET_2_0\r
86                                 obj.Parent = this;\r
87 #endif\r
88 \r
89                                 XmlSchemaElement elem = obj as XmlSchemaElement;\r
90                                 if(elem != null)\r
91                                 {\r
92                                         if(elem.ValidatedMaxOccurs != Decimal.One && elem.ValidatedMaxOccurs != Decimal.Zero)\r
93                                         {\r
94                                                 elem.error (h,"The {max occurs} of all the elements of 'all' must be 0 or 1. ");\r
95                                         }\r
96                                         errorCount += elem.Compile(h, schema);\r
97                                 }\r
98                                 else\r
99                                 {\r
100                                         error(h,"XmlSchemaAll can only contain Items of type Element");\r
101                                 }\r
102                         }\r
103 \r
104                         this.CompilationId = schema.CompilationId;\r
105                         return errorCount;\r
106                 }\r
107 \r
108                 internal override XmlSchemaParticle GetOptimizedParticle (bool isTop)\r
109                 {\r
110                         if (OptimizedParticle != null)\r
111                                 return OptimizedParticle;\r
112                         if (Items.Count == 0 || ValidatedMaxOccurs == 0) {\r
113                                 OptimizedParticle = XmlSchemaParticle.Empty;\r
114                                 return OptimizedParticle;\r
115                         }\r
116                         else if (Items.Count == 1) {\r
117                                 if (ValidatedMinOccurs == 1 && ValidatedMaxOccurs == 1) {\r
118                                         XmlSchemaSequence seq = new XmlSchemaSequence ();\r
119                                         this.CopyInfo (seq);\r
120                                         XmlSchemaParticle p = (XmlSchemaParticle) Items [0];\r
121                                         p = p.GetOptimizedParticle (false);\r
122                                         if (p == XmlSchemaParticle.Empty)\r
123                                                 OptimizedParticle = p;\r
124                                         else {\r
125                                                 seq.Items.Add (p);\r
126                                                 seq.CompiledItems.Add (p);\r
127                                                 seq.Compile (null, schema);\r
128                                                 OptimizedParticle = seq;\r
129                                         }\r
130                                         return OptimizedParticle;\r
131                                 }\r
132                         }\r
133 \r
134                         XmlSchemaAll all = new XmlSchemaAll ();\r
135                         CopyInfo (all);\r
136                         CopyOptimizedItems (all);\r
137                         OptimizedParticle = all;\r
138                         all.ComputeEmptiable ();\r
139 \r
140                         return OptimizedParticle;\r
141                 }\r
142 \r
143                 internal override int Validate(ValidationEventHandler h, XmlSchema schema)\r
144                 {\r
145                         if (IsValidated (schema.CompilationId))\r
146                                 return errorCount;\r
147 \r
148                         // 3.8.6 All Group Limited :: 1.\r
149                         // Beware that this section was corrected: E1-26 of http://www.w3.org/2001/05/xmlschema-errata#Errata1\r
150                         if (!this.parentIsGroupDefinition && ValidatedMaxOccurs != 1)\r
151                                 error (h, "-all- group is limited to be content of a model group, or that of a complex type with maxOccurs to be 1.");\r
152 \r
153                         CompiledItems.Clear ();\r
154                         foreach (XmlSchemaParticle obj in Items) {\r
155                                 errorCount += obj.Validate (h, schema);\r
156                                 if (obj.ValidatedMaxOccurs != 0 &&\r
157                                         obj.ValidatedMaxOccurs != 1)\r
158                                         error (h, "MaxOccurs of a particle inside -all- compositor must be either 0 or 1.");\r
159                                 CompiledItems.Add (obj);\r
160                         }\r
161                         ComputeEmptiable ();\r
162 \r
163                         ValidationId = schema.ValidationId;\r
164                         return errorCount;\r
165                 }\r
166 \r
167                 private void ComputeEmptiable ()\r
168                 {\r
169                         emptiable = true;\r
170                         for (int i = 0; i < Items.Count; i++) {\r
171                                 if (((XmlSchemaParticle) Items [i]).ValidatedMinOccurs > 0) {\r
172                                         emptiable = false;\r
173                                         break;\r
174                                 }\r
175                         }\r
176                 }\r
177 \r
178                 internal override bool ValidateDerivationByRestriction (XmlSchemaParticle baseParticle,\r
179                         ValidationEventHandler h, XmlSchema schema, bool raiseError)\r
180                 {\r
181                         XmlSchemaAny any = baseParticle as XmlSchemaAny;\r
182                         XmlSchemaAll derivedAll = baseParticle as XmlSchemaAll;\r
183                         if (any != null) {\r
184                                 // NSRecurseCheckCardinality\r
185                                 return ValidateNSRecurseCheckCardinality (any, h, schema, raiseError);\r
186                         } else if (derivedAll != null) {\r
187                                 // Recurse\r
188                                 if (!ValidateOccurenceRangeOK (derivedAll, h, schema, raiseError))\r
189                                         return false;\r
190                                 return ValidateRecurse (derivedAll, h, schema, raiseError);\r
191                         }\r
192                         else {\r
193                                 if (raiseError)\r
194                                         error (h, "Invalid -all- particle derivation was found.");\r
195                                 return false;\r
196                         }\r
197                 }\r
198 \r
199                 internal override decimal GetMinEffectiveTotalRange ()\r
200                 {\r
201                         return GetMinEffectiveTotalRangeAllAndSequence ();\r
202                 }\r
203 \r
204                 internal override void ValidateUniqueParticleAttribution (XmlSchemaObjectTable qnames, ArrayList nsNames,\r
205                         ValidationEventHandler h, XmlSchema schema)\r
206                 {\r
207                         foreach (XmlSchemaElement el in this.Items)\r
208                                 el.ValidateUniqueParticleAttribution (qnames, nsNames, h, schema);\r
209                 }\r
210 \r
211                 internal override void ValidateUniqueTypeAttribution (XmlSchemaObjectTable labels,\r
212                         ValidationEventHandler h, XmlSchema schema)\r
213                 {\r
214                         foreach (XmlSchemaElement el in this.Items)\r
215                                 el.ValidateUniqueTypeAttribution (labels, h, schema);\r
216                 }\r
217 \r
218 \r
219                 //<all\r
220                 //  id = ID\r
221                 //  maxOccurs = 1 : 1\r
222                 //  minOccurs = (0 | 1) : 1\r
223                 //  {any attributes with non-schema namespace . . .}>\r
224                 //  Content: (annotation?, element*)\r
225                 //</all>\r
226                 internal static XmlSchemaAll Read(XmlSchemaReader reader, ValidationEventHandler h)\r
227                 {\r
228                         XmlSchemaAll all = new XmlSchemaAll();\r
229                         reader.MoveToElement();\r
230 \r
231                         if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)\r
232                         {\r
233                                 error(h,"Should not happen :1: XmlSchemaAll.Read, name="+reader.Name,null);\r
234                                 reader.SkipToEnd();\r
235                                 return null;\r
236                         }\r
237                         \r
238                         all.LineNumber = reader.LineNumber;\r
239                         all.LinePosition = reader.LinePosition;\r
240                         all.SourceUri = reader.BaseURI;\r
241 \r
242                         //Read Attributes\r
243                         while(reader.MoveToNextAttribute())\r
244                         {\r
245                                 if(reader.Name == "id")\r
246                                 {\r
247                                         all.Id = reader.Value;\r
248                                 }\r
249                                 else if(reader.Name == "maxOccurs")\r
250                                 {\r
251                                         try\r
252                                         {\r
253                                                 all.MaxOccursString = reader.Value;\r
254                                         }\r
255                                         catch(Exception e)\r
256                                         {\r
257                                                 error(h,reader.Value + " is an invalid value for maxOccurs",e);\r
258                                         }\r
259                                 }\r
260                                 else if(reader.Name == "minOccurs")\r
261                                 {\r
262                                         try\r
263                                         {\r
264                                                 all.MinOccursString = reader.Value;\r
265                                         }\r
266                                         catch(Exception e)\r
267                                         {\r
268                                                 error(h,reader.Value + " is an invalid value for minOccurs",e);\r
269                                         }\r
270                                 }\r
271                                 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)\r
272                                 {\r
273                                         error(h,reader.Name + " is not a valid attribute for all",null);\r
274                                 }\r
275                                 else\r
276                                 {\r
277                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,all);\r
278                                 }\r
279                         }\r
280                         \r
281                         reader.MoveToElement();\r
282                         if(reader.IsEmptyElement)\r
283                                 return all;\r
284 \r
285                         //Content: (annotation?, element*)\r
286                         int level = 1;\r
287                         while(reader.ReadNextElement())\r
288                         {\r
289                                 if(reader.NodeType == XmlNodeType.EndElement)\r
290                                 {\r
291                                         if(reader.LocalName != xmlname)\r
292                                                 error(h,"Should not happen :2: XmlSchemaAll.Read, name="+reader.Name,null);\r
293                                         break;\r
294                                 }\r
295                                 if(level <= 1 && reader.LocalName == "annotation")\r
296                                 {\r
297                                         level = 2;      //Only one annotation\r
298                                         XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
299                                         if(annotation != null)\r
300                                                 all.Annotation = annotation;\r
301                                         continue;\r
302                                 }\r
303                                 if(level <=2 && reader.LocalName == "element")\r
304                                 {\r
305                                         level = 2;\r
306                                         XmlSchemaElement element = XmlSchemaElement.Read(reader,h);\r
307                                         if(element != null)\r
308                                                 all.items.Add(element);\r
309                                         continue;\r
310                                 }\r
311                                 reader.RaiseInvalidElementError();\r
312                         }\r
313                         return all;\r
314                 }\r
315         }\r
316 }\r