(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaChoice.cs
blobeb3dda8bfce776e7bc6343ad6565766e3440b282
1 //
2 // System.Xml.Schema.XmlSchemaChoice.cs
3 //
4 // Author:
5 // Dwivedi, Ajay kumar Adwiv@Yahoo.com
6 // Atsushi Enomoto ginga@kit.hi-ho.ne.jp
7 //
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.
29 using System;
30 using System.Collections;
31 using System.Xml.Serialization;
32 using System.Xml;
34 namespace System.Xml.Schema
36 public class XmlSchemaChoice : XmlSchemaGroupBase
38 private XmlSchemaObjectCollection items;
39 const string xmlname = "choice";
40 private decimal minEffectiveTotalRange = -1;
42 public XmlSchemaChoice ()
44 items = new XmlSchemaObjectCollection();
47 [XmlElement("element",typeof(XmlSchemaElement),Namespace=XmlSchema.Namespace)]
48 [XmlElement("group",typeof(XmlSchemaGroupRef),Namespace=XmlSchema.Namespace)]
49 [XmlElement("choice",typeof(XmlSchemaChoice),Namespace=XmlSchema.Namespace)]
50 [XmlElement("sequence",typeof(XmlSchemaSequence),Namespace=XmlSchema.Namespace)]
51 [XmlElement("any",typeof(XmlSchemaAny),Namespace=XmlSchema.Namespace)]
52 public override XmlSchemaObjectCollection Items
54 get{ return items; }
57 internal override int Compile(ValidationEventHandler h, XmlSchema schema)
59 // If this is already compiled this time, simply skip.
60 if (this.IsComplied (schema.CompilationId))
61 return 0;
63 XmlSchemaUtil.CompileID(Id, this, schema.IDCollection, h);
64 CompileOccurence (h, schema);
66 if (Items.Count == 0)
67 this.warn (h, "Empty choice is unsatisfiable if minOccurs not equals to 0");
69 foreach(XmlSchemaObject obj in Items)
71 if(obj is XmlSchemaElement ||
72 obj is XmlSchemaGroupRef ||
73 obj is XmlSchemaChoice ||
74 obj is XmlSchemaSequence ||
75 obj is XmlSchemaAny)
77 errorCount += obj.Compile(h,schema);
79 else
80 error(h, "Invalid schema object was specified in the particles of the choice model group.");
82 this.CompilationId = schema.CompilationId;
83 return errorCount;
86 internal override XmlSchemaParticle GetOptimizedParticle (bool isTop)
88 if (OptimizedParticle != null)
89 return OptimizedParticle;
91 if (Items.Count == 0 || ValidatedMaxOccurs == 0)
92 OptimizedParticle = XmlSchemaParticle.Empty;
93 // LAMESPEC: Regardless of isTop, it should remove pointless particle. It seems ContentTypeParticle design bug.
94 else if (!isTop && Items.Count == 1 && ValidatedMinOccurs == 1 && ValidatedMaxOccurs == 1)
95 OptimizedParticle = ((XmlSchemaParticle) Items [0]).GetOptimizedParticle (false);
96 else {
97 XmlSchemaChoice c = new XmlSchemaChoice ();
98 CopyInfo (c);
99 for (int i = 0; i < Items.Count; i++) {
100 XmlSchemaParticle p = Items [i] as XmlSchemaParticle;
101 p = p.GetOptimizedParticle (false);
102 if (p == XmlSchemaParticle.Empty)
103 continue;
104 else if (p is XmlSchemaChoice && p.ValidatedMinOccurs == 1 && p.ValidatedMaxOccurs == 1) {
105 XmlSchemaChoice pc = p as XmlSchemaChoice;
106 for (int ci = 0; ci < pc.Items.Count; ci++) {
107 c.Items.Add (pc.Items [ci]);
108 c.CompiledItems.Add (pc.Items [ci]);
111 else {
112 c.Items.Add (p);
113 c.CompiledItems.Add (p);
116 if (c.Items.Count == 0)
117 OptimizedParticle = XmlSchemaParticle.Empty;
118 else
119 OptimizedParticle = c;
121 return OptimizedParticle;
124 internal override int Validate (ValidationEventHandler h, XmlSchema schema)
126 if (IsValidated (schema.CompilationId))
127 return errorCount;
129 CompiledItems.Clear ();
130 foreach (XmlSchemaParticle p in Items) {
131 errorCount += p.Validate (h, schema); // This is basically extraneous for pointless item, but needed to check validation error.
132 CompiledItems.Add (p);
135 ValidationId = schema.ValidationId;
136 return errorCount;
139 internal override bool ValidateDerivationByRestriction (XmlSchemaParticle baseParticle,
140 ValidationEventHandler h, XmlSchema schema, bool raiseError)
142 XmlSchemaAny any = baseParticle as XmlSchemaAny;
143 if (any != null) {
144 // NSRecurseCheckCardinality
145 return ValidateNSRecurseCheckCardinality (any, h, schema, raiseError);
148 XmlSchemaChoice choice = baseParticle as XmlSchemaChoice;
149 if (choice != null) {
150 // RecurseLax
151 if (!ValidateOccurenceRangeOK (choice, h, schema, raiseError))
152 return false;
154 // If it is totally optional, then ignore their contents.
155 if (choice.ValidatedMinOccurs == 0 && choice.ValidatedMaxOccurs == 0 &&
156 this.ValidatedMinOccurs == 0 && this.ValidatedMaxOccurs == 0)
157 return true;
158 // return ValidateRecurseLax (choice, h, schema, raiseError);
159 return this.ValidateSeqRecurseMapSumCommon (choice, h, schema, true, false, raiseError);
162 if (raiseError)
163 error (h, "Invalid choice derivation by restriction was found.");
164 return false;
167 private bool ValidateRecurseLax (XmlSchemaGroupBase baseGroup,
168 ValidationEventHandler h, XmlSchema schema, bool raiseError)
170 int index = 0;
171 for (int i = 0; i < baseGroup.CompiledItems.Count; i++) {
172 XmlSchemaParticle pb = (XmlSchemaParticle) baseGroup.CompiledItems [i];
173 pb = pb.GetOptimizedParticle (false);
174 if (pb == XmlSchemaParticle.Empty)
175 continue;
176 XmlSchemaParticle pd = null;
177 while (this.CompiledItems.Count > index) {
178 pd = (XmlSchemaParticle) this.CompiledItems [index];
179 pd = pd.GetOptimizedParticle (false);
180 index++;
181 if (pd != XmlSchemaParticle.Empty)
182 break;
184 if (!ValidateParticleSection (ref index, pd, pb, h, schema, raiseError))
185 continue;
187 if (this.CompiledItems.Count > 0 && index != this.CompiledItems.Count) {
188 if (raiseError)
189 error (h, "Invalid particle derivation by restriction was found. Extraneous derived particle was found.");
190 return false;
192 return true;
195 private bool ValidateParticleSection (ref int index, XmlSchemaParticle pd, XmlSchemaParticle pb, ValidationEventHandler h, XmlSchema schema, bool raiseError)
197 if (pd == pb) // they are same particle
198 return true;
200 if (pd != null) {
201 XmlSchemaElement el = pd as XmlSchemaElement;
202 XmlSchemaParticle pdx = pd;
203 // if (el != null && el.SubstitutingElements.Count > 0)
204 // pdx = el.SubstitutingChoice;
206 if (!pdx.ValidateDerivationByRestriction (pb, h, schema, false)) {
207 if (!pb.ValidateIsEmptiable ()) {
208 if (raiseError)
209 error (h, "Invalid particle derivation by restriction was found. Invalid sub-particle derivation was found.");
210 return false;
212 else {
213 index--; // try the same derived particle and next base particle.
214 return false;
217 } else if (!pb.ValidateIsEmptiable ()) {
218 if (raiseError)
219 error (h, "Invalid particle derivation by restriction was found. Base schema particle has non-emptiable sub particle that is not mapped to the derived particle.");
220 return false;
223 return true;
226 internal override decimal GetMinEffectiveTotalRange ()
228 if (minEffectiveTotalRange >= 0)
229 return minEffectiveTotalRange;
231 decimal product = 0; //this.ValidatedMinOccurs;
232 if (Items.Count == 0)
233 product = 0;
234 else {
235 foreach (XmlSchemaParticle p in this.Items) {
236 decimal got = p.GetMinEffectiveTotalRange ();
237 if (product > got)
238 product= got;
241 minEffectiveTotalRange = product;
242 return product;
245 internal override void ValidateUniqueParticleAttribution (XmlSchemaObjectTable qnames, ArrayList nsNames,
246 ValidationEventHandler h, XmlSchema schema)
248 foreach (XmlSchemaParticle p in this.Items)
249 p.ValidateUniqueParticleAttribution (qnames, nsNames, h, schema);
252 internal override void ValidateUniqueTypeAttribution (XmlSchemaObjectTable labels,
253 ValidationEventHandler h, XmlSchema schema)
255 foreach (XmlSchemaParticle p in this.Items)
256 p.ValidateUniqueTypeAttribution (labels, h, schema);
259 //<choice
260 // id = ID
261 // maxOccurs = (nonNegativeInteger | unbounded) : 1
262 // minOccurs = nonNegativeInteger : 1
263 // {any attributes with non-schema namespace . . .}>
264 // Content: (annotation?, (element | group | choice | sequence | any)*)
265 //</choice>
266 internal static XmlSchemaChoice Read(XmlSchemaReader reader, ValidationEventHandler h)
268 XmlSchemaChoice choice = new XmlSchemaChoice();
269 reader.MoveToElement();
271 if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)
273 error(h,"Should not happen :1: XmlSchemaChoice.Read, name="+reader.Name,null);
274 reader.SkipToEnd();
275 return null;
278 choice.LineNumber = reader.LineNumber;
279 choice.LinePosition = reader.LinePosition;
280 choice.SourceUri = reader.BaseURI;
282 while(reader.MoveToNextAttribute())
284 if(reader.Name == "id")
286 choice.Id = reader.Value;
288 else if(reader.Name == "maxOccurs")
292 choice.MaxOccursString = reader.Value;
294 catch(Exception e)
296 error(h,reader.Value + " is an invalid value for maxOccurs",e);
299 else if(reader.Name == "minOccurs")
303 choice.MinOccursString = reader.Value;
305 catch(Exception e)
307 error(h,reader.Value + " is an invalid value for minOccurs",e);
310 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
312 error(h,reader.Name + " is not a valid attribute for choice",null);
314 else
316 XmlSchemaUtil.ReadUnhandledAttribute(reader,choice);
320 reader.MoveToElement();
321 if(reader.IsEmptyElement)
322 return choice;
324 // Content: (annotation?, (element | group | choice | sequence | any)*)
325 int level = 1;
326 while(reader.ReadNextElement())
328 if(reader.NodeType == XmlNodeType.EndElement)
330 if(reader.LocalName != xmlname)
331 error(h,"Should not happen :2: XmlSchemaChoice.Read, name="+reader.Name,null);
332 break;
334 if(level <= 1 && reader.LocalName == "annotation")
336 level = 2; //Only one annotation
337 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
338 if(annotation != null)
339 choice.Annotation = annotation;
340 continue;
342 if(level <=2)
344 if(reader.LocalName == "element")
346 level = 2;
347 XmlSchemaElement element = XmlSchemaElement.Read(reader,h);
348 if(element != null)
349 choice.items.Add(element);
350 continue;
352 if(reader.LocalName == "group")
354 level = 2;
355 XmlSchemaGroupRef group = XmlSchemaGroupRef.Read(reader,h);
356 if(group != null)
357 choice.items.Add(group);
358 continue;
360 if(reader.LocalName == "choice")
362 level = 2;
363 XmlSchemaChoice ch = XmlSchemaChoice.Read(reader,h);
364 if(ch != null)
365 choice.items.Add(ch);
366 continue;
368 if(reader.LocalName == "sequence")
370 level = 2;
371 XmlSchemaSequence sequence = XmlSchemaSequence.Read(reader,h);
372 if(sequence != null)
373 choice.items.Add(sequence);
374 continue;
376 if(reader.LocalName == "any")
378 level = 2;
379 XmlSchemaAny any = XmlSchemaAny.Read(reader,h);
380 if(any != null)
381 choice.items.Add(any);
382 continue;
385 reader.RaiseInvalidElementError();
387 return choice;