2004-12-16 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / Mono.Xml.Schema / XsdParticleValidationState.cs
1 //
2 // Mono.Xml.Schema.XsdParticleValidationState.cs
3 //
4 // Author:
5 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
6 //
7 //      (C)2003 Atsushi Enomoto
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 using System;
31 using System.Collections;
32 using System.Xml;
33 using System.Xml.Schema;
34 using Mono.Xml;
35
36 namespace Mono.Xml.Schema
37 {
38         internal class XsdParticleStateManager
39         {
40                 Hashtable table;
41                 XmlSchemaContentProcessing processContents;
42
43                 public XsdParticleStateManager ()
44                 {
45                         table = new Hashtable ();
46                         processContents = XmlSchemaContentProcessing.Strict; // not Lax
47                 }
48
49                 public XmlSchemaElement CurrentElement;
50
51                 public Stack ContextStack = new Stack ();
52
53                 public XsdValidationContext Context
54                         = new XsdValidationContext ();
55
56                 public XmlSchemaContentProcessing ProcessContents {
57                         get { return processContents; }
58                 }
59
60                 public void PushContext ()
61                 {
62                         ContextStack.Push (Context.Clone ());
63                 }
64
65                 public void PopContext ()
66                 {
67                         Context = (XsdValidationContext) ContextStack.Pop ();
68                 }
69
70                 internal void SetProcessContents (XmlSchemaContentProcessing value)
71                 {
72                         this.processContents = value;
73                 }
74
75                 public XsdValidationState Get (XmlSchemaParticle xsobj)
76                 {
77                         XsdValidationState got = table [xsobj] as XsdValidationState;
78                         if (got == null)
79                                 got = Create (xsobj);
80                         return got;
81                 }
82
83                 public XsdValidationState Create (XmlSchemaObject xsobj)
84                 {
85                         string typeName = xsobj.GetType ().Name;
86                         switch (typeName) {
87                         case "XmlSchemaElement":
88                                 return AddElement ((XmlSchemaElement) xsobj);
89                         case "XmlSchemaSequence":
90                                 return AddSequence ((XmlSchemaSequence) xsobj);
91                         case "XmlSchemaChoice":
92                                 return AddChoice ((XmlSchemaChoice) xsobj);
93                         case "XmlSchemaAll":
94                                 return AddAll ((XmlSchemaAll) xsobj);
95                         case "XmlSchemaAny":
96                                 return AddAny ((XmlSchemaAny) xsobj);
97                         case "EmptyParticle":
98                                 return AddEmpty ();
99                         default:
100                                 // GroupRef should not appear
101                                 throw new InvalidOperationException ("Should not occur.");
102                         }
103                 }
104
105                 internal XsdValidationState MakeSequence (XsdValidationState head, XsdValidationState rest)
106                 {
107                         if (head is XsdEmptyValidationState)
108                                 return rest;
109                         else
110                                 return new XsdAppendedValidationState (this, head, rest);
111                 }
112
113                 private XsdElementValidationState AddElement (XmlSchemaElement element)
114                 {
115                         XsdElementValidationState got = new XsdElementValidationState (element, this);
116                         return got;
117                 }
118
119                 private XsdSequenceValidationState AddSequence (XmlSchemaSequence sequence)
120                 {
121                         XsdSequenceValidationState got = new XsdSequenceValidationState (sequence, this);
122                         return got;
123                 }
124
125                 private XsdChoiceValidationState AddChoice (XmlSchemaChoice choice)
126                 {
127                         XsdChoiceValidationState got = new XsdChoiceValidationState (choice, this);
128                         return got;
129                 }
130
131                 private XsdAllValidationState AddAll (XmlSchemaAll all)
132                 {
133                         XsdAllValidationState got = new XsdAllValidationState (all, this);
134                         return got;
135                 }
136
137                 private XsdAnyValidationState AddAny (XmlSchemaAny any)
138                 {
139                         XsdAnyValidationState got = new XsdAnyValidationState (any, this);
140                         return got;
141                 }
142
143                 private XsdEmptyValidationState AddEmpty ()
144                 {
145                         return new XsdEmptyValidationState (this);
146                 }
147         }
148
149         internal abstract class XsdValidationState
150         {
151                 // Static members
152
153                 static XsdInvalidValidationState invalid;
154
155                 static XsdValidationState ()
156                 {
157                         invalid = new XsdInvalidValidationState (null);
158                 }
159
160                 public static XsdInvalidValidationState Invalid {
161                         get { return invalid; }
162                 }
163
164                 // Dynamic members
165
166                 int occured;
167                 readonly XsdParticleStateManager manager;
168
169                 public XsdValidationState (XsdParticleStateManager manager)
170                 {
171                         this.manager = manager;
172                 }
173
174                 // Normally checks Max Occurs boundary
175                 public abstract XsdValidationState EvaluateStartElement (string localName, string ns);
176
177                 // Normally checks Min Occurs boundary
178                 public abstract bool EvaluateEndElement ();
179
180                 internal abstract bool EvaluateIsEmptiable ();
181
182                 public abstract void GetExpectedParticles (ArrayList al);
183
184                 public XsdParticleStateManager Manager {
185                         get { return manager; }
186                 }
187
188                 public int Occured {
189                         get { return occured; }
190                 }
191
192                 internal int OccuredInternal {
193                         get { return occured; }
194                         set { occured = value; }
195                 }
196         }
197
198         internal class XsdElementValidationState : XsdValidationState
199         {
200                 public XsdElementValidationState (XmlSchemaElement element, XsdParticleStateManager manager)
201                         : base (manager)
202                 {
203                         this.element = element;
204                 }
205
206                 // final fields
207                 readonly XmlSchemaElement element;
208
209                 string Name {
210                         get { return element.QualifiedName.Name; }
211                 }
212
213                 string NS {
214                         get { return element.QualifiedName.Namespace; }
215                 }
216
217                 // Methods
218                 public override void GetExpectedParticles (ArrayList al)
219                 {
220                         XmlSchemaElement copy = (XmlSchemaElement) MemberwiseClone ();
221                         decimal mo = element.ValidatedMinOccurs - Occured;
222                         copy.MinOccurs = mo > 0 ? mo : 0;
223                         if (element.ValidatedMaxOccurs == decimal.MaxValue)
224                                 copy.MaxOccursString = "unbounded";
225                         else
226                                 copy.MaxOccurs = element.ValidatedMaxOccurs - Occured;
227                         al.Add (copy);
228                 }
229
230                 public override XsdValidationState EvaluateStartElement (string name, string ns)
231                 {
232                         if (this.Name == name && this.NS == ns && !element.IsAbstract) {
233                                 return this.CheckOccurence (element);
234                         } else {
235                                 for (int i = 0; i < element.SubstitutingElements.Count; i++) {
236                                         XmlSchemaElement subst = (XmlSchemaElement) element.SubstitutingElements [i];
237                                         if (subst.QualifiedName.Name == name &&
238                                                 subst.QualifiedName.Namespace == ns) {
239                                                 return this.CheckOccurence (subst);
240                                         }
241                                 }
242                                 return XsdValidationState.Invalid;
243                         }
244                 }
245
246                 private XsdValidationState CheckOccurence (XmlSchemaElement maybeSubstituted)
247                 {
248                         OccuredInternal++;
249                         Manager.CurrentElement = maybeSubstituted;
250                         if (Occured > element.ValidatedMaxOccurs) {
251                                 return XsdValidationState.Invalid;
252                         } else if (Occured == element.ValidatedMaxOccurs) {
253                                 return Manager.Create (XmlSchemaParticle.Empty);
254                         } else {
255                                 return this;
256                         }
257                 }
258
259                 public override bool EvaluateEndElement ()
260                 {
261                         return EvaluateIsEmptiable ();
262                 }
263
264                 internal override bool EvaluateIsEmptiable ()
265                 {
266                         return (element.ValidatedMinOccurs <= Occured &&
267                                 element.ValidatedMaxOccurs >= Occured);
268                 }
269         }
270
271         internal class XsdSequenceValidationState : XsdValidationState
272         {
273                 readonly XmlSchemaSequence seq;
274                 int current;
275                 XsdValidationState currentAutomata;
276                 bool emptiable;
277
278                 public XsdSequenceValidationState (XmlSchemaSequence sequence, XsdParticleStateManager manager)
279                         : base (manager)
280                 {
281                         seq = sequence;
282                         this.current = -1;
283                 }
284
285                 public override void GetExpectedParticles (ArrayList al)
286                 {
287                         // if not started, then just collect all items from seq.
288                         if (currentAutomata == null) {
289                                 foreach (XmlSchemaParticle p in seq.CompiledItems) {
290                                         al.Add (p);
291                                         if (!p.ValidateIsEmptiable ())
292                                                 break;
293                                 }
294                                 return;
295                         }
296
297                         // automata for ongoing iteration
298                         if (currentAutomata != null) {
299                                 currentAutomata.GetExpectedParticles (al);
300                                 if (!currentAutomata.EvaluateIsEmptiable ())
301                                         return;
302
303                                 // remaining items after currentAutomata
304                                 for (int i = current + 1; i < seq.CompiledItems.Count; i++) {
305                                         XmlSchemaParticle p = seq.CompiledItems [i] as XmlSchemaParticle;
306                                         al.Add (p);
307                                         if (!p.ValidateIsEmptiable ())
308                                                 break;
309                                 }
310                         }
311
312                         // itself
313                         if (Occured + 1 == seq.ValidatedMaxOccurs)
314                                 return;
315
316                         {
317                                 for (int i = 0; i <= current; i++)
318                                         al.Add (seq.CompiledItems [i]);
319                         }
320                 }
321
322                 public override XsdValidationState EvaluateStartElement (string name, string ns)
323                 {
324                         if (seq.CompiledItems.Count == 0)
325                                 return XsdValidationState.Invalid;
326
327                         int idx = current < 0 ? 0 : current;
328                         XsdValidationState xa = currentAutomata;
329                         // If it is true and when matching particle was found, then
330                         // it will increment occurence.
331                         bool increment = false;
332
333                         while (true) {
334 //                              if (current < 0 || current == seq.CompiledItems.Count) {
335 //                                      idx = current = 0;
336 //                                      increment = true;
337 //                              }
338                                 if (xa == null) {       // This code runs in case of a newiteration.
339                                         xa = Manager.Create (seq.CompiledItems [idx] as XmlSchemaParticle);
340                                         increment = true;
341                                 }
342                                 if (xa is XsdEmptyValidationState &&
343                                                 seq.CompiledItems.Count == idx + 1 &&
344                                                 Occured == seq.ValidatedMaxOccurs) {
345                                         return XsdValidationState.Invalid;
346                                 } else {
347                                         XsdValidationState result = xa.EvaluateStartElement (name, ns);
348                                         if (result == XsdValidationState.Invalid) {
349                                                 if (!xa.EvaluateIsEmptiable ()) {
350                                                         emptiable = false;
351                                                         return XsdValidationState.Invalid;
352                                                 }
353                                         } else {
354                                                 current = idx;
355                                                 currentAutomata = result;
356                                                 if (increment) {
357                                                         OccuredInternal++;
358                                                         if (Occured > seq.ValidatedMaxOccurs)
359                                                                 return XsdValidationState.Invalid;
360                                                 }
361 //                                              current++;
362 //                                              return Manager.MakeSequence (result, this);
363                                                 return this;
364                                         // skip in other cases.
365                                         }
366                                 }
367                                 idx++;
368                                 if (idx > current && increment && current >= 0) {
369                                         return XsdValidationState.Invalid;
370                                 }
371                                 if (seq.CompiledItems.Count > idx) {
372                                         xa = Manager.Create (seq.CompiledItems [idx] as XmlSchemaParticle);
373                                 }
374                                 else if (current < 0) { // started from top
375                                         return XsdValidationState.Invalid;
376                                 }
377                                 else {          // started from middle
378                                         idx = 0;
379                                         xa = null;
380                                 }
381                         }
382                 }
383
384                 public override bool EvaluateEndElement ()
385                 {
386                         if (seq.ValidatedMinOccurs > Occured + 1)
387                                 return false;
388                         if (seq.CompiledItems.Count == 0)
389                                 return true;
390                         if (currentAutomata == null && seq.ValidatedMinOccurs <= Occured)
391                                 return true;
392
393                         int idx = current < 0 ? 0 : current;
394                         XsdValidationState xa = currentAutomata;
395                         if (xa == null)
396                                 xa = Manager.Create (seq.CompiledItems [idx] as XmlSchemaParticle);
397                         while (xa != null) {
398                                 if (!xa.EvaluateEndElement ())
399                                         if (!xa.EvaluateIsEmptiable ())
400                                                 return false;   // cannot omit following items.
401                                 idx++;
402                                 if (seq.CompiledItems.Count > idx)
403                                         xa = Manager.Create (seq.CompiledItems [idx] as XmlSchemaParticle);
404                                 else
405                                         xa = null;
406                         }
407                         if (current < 0)
408                                 OccuredInternal++;
409
410                         return seq.ValidatedMinOccurs <= Occured && seq.ValidatedMaxOccurs >= Occured;
411                 }
412
413                 internal override bool EvaluateIsEmptiable ()\r
414                 {\r
415                         if (seq.ValidatedMinOccurs > Occured + 1)\r
416                                 return false;\r
417                         if (seq.ValidatedMinOccurs == 0 && currentAutomata == null)\r
418                                 return true;\r
419 \r
420                         if (emptiable)\r
421                                 return true;\r
422                         if (seq.CompiledItems.Count == 0)\r
423                                 return true;\r
424 \r
425                         int idx = current < 0 ? 0 : current;
426                         XsdValidationState xa = currentAutomata;\r
427                         if (xa == null)
428                                 xa = Manager.Create (seq.CompiledItems [idx] as XmlSchemaParticle);
429                         while (xa != null) {
430                                 if (!xa.EvaluateIsEmptiable ())
431                                         return false;
432                                 idx++;
433                                 if (seq.CompiledItems.Count > idx)
434                                         xa = Manager.Create (seq.CompiledItems [idx] as XmlSchemaParticle);
435                                 else
436                                         xa = null;
437                         }
438                         emptiable = true;
439                         return true;
440                 }\r
441
442         }
443
444         internal class XsdChoiceValidationState : XsdValidationState
445         {
446                 readonly XmlSchemaChoice choice;
447                 bool emptiable;
448                 bool emptiableComputed;
449
450                 public XsdChoiceValidationState (XmlSchemaChoice choice, XsdParticleStateManager manager)
451                         : base (manager)
452                 {
453                         this.choice = choice;
454                 }
455
456                 public override void GetExpectedParticles (ArrayList al)
457                 {
458                         if (Occured < choice.ValidatedMaxOccurs)
459                                 foreach (XmlSchemaParticle p in choice.CompiledItems)
460                                         al.Add (p);
461                 }
462
463                 public override XsdValidationState EvaluateStartElement (string localName, string ns)
464                 {
465                         emptiableComputed = false;
466
467                         for (int i = 0; i < choice.CompiledItems.Count; i++) {
468                                 XmlSchemaParticle xsobj = (XmlSchemaParticle) choice.CompiledItems [i];
469                                 XsdValidationState xa = Manager.Create (xsobj);
470                                 XsdValidationState result = xa.EvaluateStartElement (localName, ns);
471                                 if (result != XsdValidationState.Invalid) {
472                                         OccuredInternal++;
473                                         if (Occured > choice.ValidatedMaxOccurs)
474                                                 return XsdValidationState.Invalid;
475                                         else if (Occured == choice.ValidatedMaxOccurs)
476                                                 return result;
477                                         else
478                                                 return Manager.MakeSequence (result, this);
479                                 }
480                         }
481                         emptiable = choice.ValidatedMinOccurs <= Occured;
482                         emptiableComputed = true;
483                         return XsdValidationState.Invalid;
484                 }
485
486                 public override bool EvaluateEndElement ()
487                 {
488                         emptiableComputed = false;
489
490                         if (choice.ValidatedMinOccurs > Occured + 1)
491                                 return false;
492
493                         else if (choice.ValidatedMinOccurs <= Occured)
494                                 return true;
495
496                         for (int i = 0; i < choice.CompiledItems.Count; i++) {
497                                 XmlSchemaParticle p = (XmlSchemaParticle) choice.CompiledItems [i];
498                                 if (Manager.Create (p).EvaluateIsEmptiable ())
499                                         return true;
500                         }
501                         return false;
502                 }
503
504                 internal override bool EvaluateIsEmptiable ()\r
505                 {\r
506                         if (emptiableComputed)
507                                 return emptiable;
508 \r
509                         if (choice.ValidatedMaxOccurs < Occured)\r
510                                 return false;\r
511                         else if (choice.ValidatedMinOccurs > Occured + 1)\r
512                                 return false;\r
513 \r
514                         for (int i = Occured; i < choice.ValidatedMinOccurs; i++) {\r
515                                 bool next = false;\r
516                                 for (int pi = 0; pi < choice.CompiledItems.Count; pi++) {
517                                         XmlSchemaParticle p = (XmlSchemaParticle) choice.CompiledItems [pi];\r
518                                         if (Manager.Create (p).EvaluateIsEmptiable ()) {
519                                                 next = true;
520                                                 break;
521                                         }
522                                 }\r
523                                 if (!next)\r
524                                         return false;\r
525                         }\r
526                         return true;\r
527                 }\r
528         }
529
530         internal class XsdAllValidationState : XsdValidationState
531         {
532                 readonly XmlSchemaAll all;
533                 ArrayList consumed = new ArrayList ();
534
535                 public XsdAllValidationState (XmlSchemaAll all, XsdParticleStateManager manager)
536                         : base (manager)
537                 {
538                         this.all = all;
539                 }
540
541                 public override void GetExpectedParticles (ArrayList al)
542                 {
543                         foreach (XmlSchemaParticle p in all.CompiledItems)
544                                 if (!consumed.Contains (p))
545                                         al.Add (p);
546                 }
547
548                 public override XsdValidationState EvaluateStartElement (string localName, string ns)
549                 {
550                         if (all.CompiledItems.Count == 0)
551                                 return XsdValidationState.Invalid;
552
553                         // We don't have to keep element validation state, since 
554                         // it must occur only 0 or 1.
555                         for (int i = 0; i < all.CompiledItems.Count; i++) {
556                                 XmlSchemaElement xsElem = (XmlSchemaElement) all.CompiledItems [i];
557                                 if (xsElem.QualifiedName.Name == localName &&
558                                         xsElem.QualifiedName.Namespace == ns) {
559                                         if (consumed.Contains (xsElem))
560                                                 return XsdValidationState.Invalid;
561                                         consumed.Add (xsElem);
562                                         Manager.CurrentElement = xsElem;
563                                         OccuredInternal = 1;    // xs:all also occurs 0 or 1 always.
564                                         return this;
565                                 }
566                         }
567                         return XsdValidationState.Invalid;
568                 }
569
570                 public override bool EvaluateEndElement ()
571                 {
572                         if (all.Emptiable || all.ValidatedMinOccurs == 0)
573                                 return true;
574                         if (all.ValidatedMinOccurs > 0 && consumed.Count == 0)
575                                 return false;
576                         if (all.CompiledItems.Count == consumed.Count)
577                                 return true;
578                         for (int i = 0; i < all.CompiledItems.Count; i++) {
579                                 XmlSchemaElement el = (XmlSchemaElement) all.CompiledItems [i];
580                                 if (el.ValidatedMinOccurs > 0 && !consumed.Contains (el))
581                                         return false;
582                         }
583                         return true;
584                 }
585
586                 internal override bool EvaluateIsEmptiable ()\r
587                 {\r
588                         if (all.Emptiable || all.ValidatedMinOccurs == 0)
589                                 return true;
590                         for (int i = 0; i < all.CompiledItems.Count; i++) {
591                                 XmlSchemaElement el = (XmlSchemaElement) all.CompiledItems [i];
592                                 if (el.ValidatedMinOccurs > 0 && !consumed.Contains (el))
593                                         return false;
594                         }
595                         return true;
596                 }\r
597         }
598
599         internal class XsdAnyValidationState : XsdValidationState
600         {
601                 readonly XmlSchemaAny any;
602
603                 public XsdAnyValidationState (XmlSchemaAny any, XsdParticleStateManager manager)
604                         : base (manager)
605                 {
606                         this.any = any;
607                 }
608
609                 // Methods
610                 public override void GetExpectedParticles (ArrayList al)
611                 {
612                         al.Add (any);
613                 }
614
615                 public override XsdValidationState EvaluateStartElement (string name, string ns)
616                 {
617                         if (!MatchesNamespace (ns))
618                                 return XsdValidationState.Invalid;
619
620                         OccuredInternal++;
621                         Manager.SetProcessContents (any.ResolvedProcessContents);
622                         if (Occured > any.ValidatedMaxOccurs)
623                                 return XsdValidationState.Invalid;
624                         else if (Occured == any.ValidatedMaxOccurs)
625                                 return Manager.Create (XmlSchemaParticle.Empty);
626                         else
627                                 return this;
628                 }
629
630                 private bool MatchesNamespace (string ns)
631                 {
632                         if (any.HasValueAny)
633                                 return true;
634                         if (any.HasValueLocal && ns == String.Empty)
635                                 return true;
636                         if (any.HasValueOther && (any.TargetNamespace == "" || any.TargetNamespace != ns))
637                                 return true;
638                         if (any.HasValueTargetNamespace && any.TargetNamespace == ns)
639                                 return true;
640                         for (int i = 0; i < any.ResolvedNamespaces.Count; i++)
641                                 if (any.ResolvedNamespaces [i] == ns)
642                                         return true;
643                         return false;
644                 }
645
646                 public override bool EvaluateEndElement ()
647                 {
648                         return EvaluateIsEmptiable ();
649                 }
650
651                 internal override bool EvaluateIsEmptiable ()\r
652                 {\r
653                         return any.ValidatedMinOccurs <= Occured &&
654                                 any.ValidatedMaxOccurs >= Occured;
655                 }\r
656         }
657
658         internal class XsdAppendedValidationState : XsdValidationState
659         {
660                 public XsdAppendedValidationState (XsdParticleStateManager manager,
661                         XsdValidationState head, XsdValidationState rest)
662                         : base (manager)
663                 {
664                         this.head = head;
665                         this.rest = rest;
666                 }
667
668                 XsdValidationState head;
669                 XsdValidationState rest;
670
671                 // Methods
672                 public override void GetExpectedParticles (ArrayList al)
673                 {
674                         head.GetExpectedParticles (al);
675                         rest.GetExpectedParticles (al);
676                 }
677
678                 public override XsdValidationState EvaluateStartElement (string name, string ns)
679                 {
680                         XsdValidationState afterHead = head.EvaluateStartElement (name, ns);
681                         if (afterHead != XsdValidationState.Invalid) {
682                                 head = afterHead;
683                                 return afterHead is XsdEmptyValidationState ? rest : this;
684                         } else if (!head.EvaluateIsEmptiable ()) {
685                                 return XsdValidationState.Invalid;
686                         }
687
688                         return rest.EvaluateStartElement (name, ns);
689                 }
690
691                 public override bool EvaluateEndElement ()
692                 {
693                         if (head.EvaluateEndElement ())
694 //                              return true;
695                                 return rest.EvaluateIsEmptiable ();
696                         if (!head.EvaluateIsEmptiable ())
697                                 return false;
698                         return rest.EvaluateEndElement ();
699                 }
700
701                 internal override bool EvaluateIsEmptiable ()\r
702                 {\r
703                         if (head.EvaluateIsEmptiable ())\r
704                                 return rest.EvaluateIsEmptiable ();\r
705                         else\r
706                                 return false;\r
707                 }\r
708         }
709
710         internal class XsdEmptyValidationState : XsdValidationState
711         {
712                 public XsdEmptyValidationState (XsdParticleStateManager manager)
713                         : base (manager)
714                 {
715                 }
716
717                 // Methods
718
719                 public override void GetExpectedParticles (ArrayList al)
720                 {
721                         // do nothing
722                 }
723
724                 public override XsdValidationState EvaluateStartElement (string name, string ns)
725                 {
726                         return XsdValidationState.Invalid;
727                 }
728
729                 public override bool EvaluateEndElement ()
730                 {
731                         return true;
732                 }
733
734                 internal override bool EvaluateIsEmptiable ()\r
735                 {\r
736                         return true;\r
737                 }\r
738 \r
739         }
740
741         internal class XsdInvalidValidationState : XsdValidationState
742         {
743                 internal XsdInvalidValidationState (XsdParticleStateManager manager)
744                         : base (manager)
745                 {
746                 }
747
748                 // Methods
749
750                 public override void GetExpectedParticles (ArrayList al)
751                 {
752                         // do nothing
753                 }
754
755                 public override XsdValidationState EvaluateStartElement (string name, string ns)
756                 {
757                         return this;
758                 }
759
760                 public override bool EvaluateEndElement ()
761                 {
762                         return false;
763                 }
764
765                 internal override bool EvaluateIsEmptiable ()\r
766                 {\r
767                         return false;\r
768                 }\r
769 \r
770         }
771 }