2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.XML / Mono.Xml.Schema / XsdParticleValidationState.cs
index 38a1929510d63bb1862bd7be013f39b98d2733c9..ef7fb08e4c6a1be44cd97620c0f1ba9647eedbbe 100644 (file)
@@ -35,38 +35,36 @@ using Mono.Xml;
 
 namespace Mono.Xml.Schema
 {
-       internal enum XsdParticleEvaluationResult
-       {
-               Matched = 1,    // Matched one of its components.
-               Passed = 2,     // Did not match, but it successfully passed the whole components.
-               InvalidIncomplete = 3,  // It had incomplete validation state, and in fact it failed to pass.
-               Mismatched = 4  // Dis not match, 
-       }
-
-       internal class XsdValidationStateManager
+       internal class XsdParticleStateManager
        {
                Hashtable table;
-               XmlSchemaElement currentElement;
                XmlSchemaContentProcessing processContents;
 
-               public XsdValidationStateManager ()
+               public XsdParticleStateManager ()
                {
                        table = new Hashtable ();
                        processContents = XmlSchemaContentProcessing.Strict; // not Lax
                }
 
-               public XmlSchemaElement CurrentElement {
-                       get { return currentElement; }
-                       set { currentElement = value; }
+               public XmlSchemaElement CurrentElement;
+
+               public Stack ContextStack = new Stack ();
+
+               public XsdValidationContext Context
+                       = new XsdValidationContext ();
+
+               public XmlSchemaContentProcessing ProcessContents {
+                       get { return processContents; }
                }
 
-               internal void SetCurrentElement (XmlSchemaElement elt)
+               public void PushContext ()
                {
-                       this.currentElement = elt;
+                       ContextStack.Push (Context.Clone ());
                }
 
-               public XmlSchemaContentProcessing ProcessContents {
-                       get { return processContents; }
+               public void PopContext ()
+               {
+                       Context = (XsdValidationContext) ContextStack.Pop ();
                }
 
                internal void SetProcessContents (XmlSchemaContentProcessing value)
@@ -166,10 +164,9 @@ namespace Mono.Xml.Schema
                // Dynamic members
 
                int occured;
-               string message;
-               XsdValidationStateManager manager;
+               readonly XsdParticleStateManager manager;
 
-               public XsdValidationState (XsdValidationStateManager manager)
+               public XsdValidationState (XsdParticleStateManager manager)
                {
                        this.manager = manager;
                }
@@ -182,17 +179,10 @@ namespace Mono.Xml.Schema
 
                internal abstract bool EvaluateIsEmptiable ();
 
-               public XsdValidationStateManager Manager {
-                       get { return manager; }
-               }
-
-               public string Message {
-                       get { return message; }
-               }
+               public abstract void GetExpectedParticles (ArrayList al);
 
-               public string MessageInternal {
-                       get { return message; }
-                       set { message = value; }
+               public XsdParticleStateManager Manager {
+                       get { return manager; }
                }
 
                public int Occured {
@@ -207,24 +197,39 @@ namespace Mono.Xml.Schema
 
        internal class XsdElementValidationState : XsdValidationState
        {
-               public XsdElementValidationState (XmlSchemaElement element, XsdValidationStateManager manager)
+               public XsdElementValidationState (XmlSchemaElement element, XsdParticleStateManager manager)
                        : base (manager)
                {
                        this.element = element;
-                       name = element.QualifiedName.Name;
-                       ns = element.QualifiedName.Namespace;
                }
 
                // final fields
-               XmlSchemaElement element;
-               string name;
-               string ns;
+               readonly XmlSchemaElement element;
+
+               string Name {
+                       get { return element.QualifiedName.Name; }
+               }
+
+               string NS {
+                       get { return element.QualifiedName.Namespace; }
+               }
 
                // Methods
-               
+               public override void GetExpectedParticles (ArrayList al)
+               {
+                       XmlSchemaElement copy = (XmlSchemaElement) MemberwiseClone ();
+                       decimal mo = element.ValidatedMinOccurs - Occured;
+                       copy.MinOccurs = mo > 0 ? mo : 0;
+                       if (element.ValidatedMaxOccurs == decimal.MaxValue)
+                               copy.MaxOccursString = "unbounded";
+                       else
+                               copy.MaxOccurs = element.ValidatedMaxOccurs - Occured;
+                       al.Add (copy);
+               }
+
                public override XsdValidationState EvaluateStartElement (string name, string ns)
                {
-                       if (this.name == name && this.ns == ns && !element.IsAbstract) {
+                       if (this.Name == name && this.NS == ns && !element.IsAbstract) {
                                return this.CheckOccurence (element);
                        } else {
                                for (int i = 0; i < element.SubstitutingElements.Count; i++) {
@@ -241,9 +246,8 @@ namespace Mono.Xml.Schema
                private XsdValidationState CheckOccurence (XmlSchemaElement maybeSubstituted)
                {
                        OccuredInternal++;
-                       Manager.SetCurrentElement (maybeSubstituted);
+                       Manager.CurrentElement = maybeSubstituted;
                        if (Occured > element.ValidatedMaxOccurs) {
-                               MessageInternal = "Element occurence excess.";
                                return XsdValidationState.Invalid;
                        } else if (Occured == element.ValidatedMaxOccurs) {
                                return Manager.Create (XmlSchemaParticle.Empty);
@@ -266,26 +270,53 @@ namespace Mono.Xml.Schema
 
        internal class XsdSequenceValidationState : XsdValidationState
        {
-               XmlSchemaSequence seq;
+               readonly XmlSchemaSequence seq;
                int current;
                XsdValidationState currentAutomata;
                bool emptiable;
-               decimal minOccurs;
-               decimal maxOccurs;
 
-               public XsdSequenceValidationState (XmlSchemaSequence sequence, XsdValidationStateManager manager)
-                       : this (sequence, manager, sequence.ValidatedMinOccurs, sequence.ValidatedMaxOccurs, -1)
+               public XsdSequenceValidationState (XmlSchemaSequence sequence, XsdParticleStateManager manager)
+                       : base (manager)
                {
+                       seq = sequence;
+                       this.current = -1;
                }
 
-               public XsdSequenceValidationState (XmlSchemaSequence sequence, XsdValidationStateManager manager,
-                       decimal minOccurs, decimal maxOccurs, int current)
-                       : base (manager)
+               public override void GetExpectedParticles (ArrayList al)
                {
-                       seq = sequence;
-                       this.minOccurs = minOccurs;
-                       this.maxOccurs = maxOccurs;
-                       this.current = current;
+                       // if not started, then just collect all items from seq.
+                       if (currentAutomata == null) {
+                               foreach (XmlSchemaParticle p in seq.CompiledItems) {
+                                       al.Add (p);
+                                       if (!p.ValidateIsEmptiable ())
+                                               break;
+                               }
+                               return;
+                       }
+
+                       // automata for ongoing iteration
+                       if (currentAutomata != null) {
+                               currentAutomata.GetExpectedParticles (al);
+                               if (!currentAutomata.EvaluateIsEmptiable ())
+                                       return;
+
+                               // remaining items after currentAutomata
+                               for (int i = current + 1; i < seq.CompiledItems.Count; i++) {
+                                       XmlSchemaParticle p = seq.CompiledItems [i] as XmlSchemaParticle;
+                                       al.Add (p);
+                                       if (!p.ValidateIsEmptiable ())
+                                               break;
+                               }
+                       }
+
+                       // itself
+                       if (Occured + 1 == seq.ValidatedMaxOccurs)
+                               return;
+
+                       {
+                               for (int i = 0; i <= current; i++)
+                                       al.Add (seq.CompiledItems [i]);
+                       }
                }
 
                public override XsdValidationState EvaluateStartElement (string name, string ns)
@@ -310,7 +341,7 @@ namespace Mono.Xml.Schema
                                }
                                if (xa is XsdEmptyValidationState &&
                                                seq.CompiledItems.Count == idx + 1 &&
-                                               Occured == maxOccurs) {
+                                               Occured == seq.ValidatedMaxOccurs) {
                                        return XsdValidationState.Invalid;
                                } else {
                                        XsdValidationState result = xa.EvaluateStartElement (name, ns);
@@ -324,7 +355,7 @@ namespace Mono.Xml.Schema
                                                currentAutomata = result;
                                                if (increment) {
                                                        OccuredInternal++;
-                                                       if (Occured > maxOccurs)
+                                                       if (Occured > seq.ValidatedMaxOccurs)
                                                                return XsdValidationState.Invalid;
                                                }
 //                                             current++;
@@ -352,11 +383,11 @@ namespace Mono.Xml.Schema
 
                public override bool EvaluateEndElement ()
                {
-                       if (minOccurs > Occured + 1)
+                       if (seq.ValidatedMinOccurs > Occured + 1)
                                return false;
                        if (seq.CompiledItems.Count == 0)
                                return true;
-                       if (currentAutomata == null && minOccurs <= Occured)
+                       if (currentAutomata == null && seq.ValidatedMinOccurs <= Occured)
                                return true;
 
                        int idx = current < 0 ? 0 : current;
@@ -376,14 +407,14 @@ namespace Mono.Xml.Schema
                        if (current < 0)
                                OccuredInternal++;
 
-                       return minOccurs <= Occured && maxOccurs >= Occured;
+                       return seq.ValidatedMinOccurs <= Occured && seq.ValidatedMaxOccurs >= Occured;
                }
 
                internal override bool EvaluateIsEmptiable ()\r
                {\r
-                       if (minOccurs > Occured + 1)\r
+                       if (seq.ValidatedMinOccurs > Occured + 1)\r
                                return false;\r
-                       if (minOccurs == 0 && currentAutomata == null)\r
+                       if (seq.ValidatedMinOccurs == 0 && currentAutomata == null)\r
                                return true;\r
 \r
                        if (emptiable)\r
@@ -412,16 +443,23 @@ namespace Mono.Xml.Schema
 
        internal class XsdChoiceValidationState : XsdValidationState
        {
-               XmlSchemaChoice choice;
+               readonly XmlSchemaChoice choice;
                bool emptiable;
                bool emptiableComputed;
 
-               public XsdChoiceValidationState (XmlSchemaChoice choice, XsdValidationStateManager manager)
+               public XsdChoiceValidationState (XmlSchemaChoice choice, XsdParticleStateManager manager)
                        : base (manager)
                {
                        this.choice = choice;
                }
 
+               public override void GetExpectedParticles (ArrayList al)
+               {
+                       if (Occured < choice.ValidatedMaxOccurs)
+                               foreach (XmlSchemaParticle p in choice.CompiledItems)
+                                       al.Add (p);
+               }
+
                public override XsdValidationState EvaluateStartElement (string localName, string ns)
                {
                        emptiableComputed = false;
@@ -491,15 +529,22 @@ namespace Mono.Xml.Schema
 
        internal class XsdAllValidationState : XsdValidationState
        {
-               XmlSchemaAll all;
+               readonly XmlSchemaAll all;
                ArrayList consumed = new ArrayList ();
 
-               public XsdAllValidationState (XmlSchemaAll all, XsdValidationStateManager manager)
+               public XsdAllValidationState (XmlSchemaAll all, XsdParticleStateManager manager)
                        : base (manager)
                {
                        this.all = all;
                }
 
+               public override void GetExpectedParticles (ArrayList al)
+               {
+                       foreach (XmlSchemaParticle p in all.CompiledItems)
+                               if (!consumed.Contains (p))
+                                       al.Add (p);
+               }
+
                public override XsdValidationState EvaluateStartElement (string localName, string ns)
                {
                        if (all.CompiledItems.Count == 0)
@@ -514,7 +559,7 @@ namespace Mono.Xml.Schema
                                        if (consumed.Contains (xsElem))
                                                return XsdValidationState.Invalid;
                                        consumed.Add (xsElem);
-                                       Manager.SetCurrentElement (xsElem);
+                                       Manager.CurrentElement = xsElem;
                                        OccuredInternal = 1;    // xs:all also occurs 0 or 1 always.
                                        return this;
                                }
@@ -553,15 +598,20 @@ namespace Mono.Xml.Schema
 
        internal class XsdAnyValidationState : XsdValidationState
        {
-               XmlSchemaAny any;
+               readonly XmlSchemaAny any;
 
-               public XsdAnyValidationState (XmlSchemaAny any, XsdValidationStateManager manager)
+               public XsdAnyValidationState (XmlSchemaAny any, XsdParticleStateManager manager)
                        : base (manager)
                {
                        this.any = any;
                }
 
                // Methods
+               public override void GetExpectedParticles (ArrayList al)
+               {
+                       al.Add (any);
+               }
+
                public override XsdValidationState EvaluateStartElement (string name, string ns)
                {
                        if (!MatchesNamespace (ns))
@@ -607,7 +657,7 @@ namespace Mono.Xml.Schema
 
        internal class XsdAppendedValidationState : XsdValidationState
        {
-               public XsdAppendedValidationState (XsdValidationStateManager manager,
+               public XsdAppendedValidationState (XsdParticleStateManager manager,
                        XsdValidationState head, XsdValidationState rest)
                        : base (manager)
                {
@@ -619,6 +669,12 @@ namespace Mono.Xml.Schema
                XsdValidationState rest;
 
                // Methods
+               public override void GetExpectedParticles (ArrayList al)
+               {
+                       head.GetExpectedParticles (al);
+                       rest.GetExpectedParticles (al);
+               }
+
                public override XsdValidationState EvaluateStartElement (string name, string ns)
                {
                        XsdValidationState afterHead = head.EvaluateStartElement (name, ns);
@@ -653,12 +709,18 @@ namespace Mono.Xml.Schema
 
        internal class XsdEmptyValidationState : XsdValidationState
        {
-               public XsdEmptyValidationState (XsdValidationStateManager manager)
+               public XsdEmptyValidationState (XsdParticleStateManager manager)
                        : base (manager)
                {
                }
 
                // Methods
+
+               public override void GetExpectedParticles (ArrayList al)
+               {
+                       // do nothing
+               }
+
                public override XsdValidationState EvaluateStartElement (string name, string ns)
                {
                        return XsdValidationState.Invalid;
@@ -678,12 +740,18 @@ namespace Mono.Xml.Schema
 
        internal class XsdInvalidValidationState : XsdValidationState
        {
-               internal XsdInvalidValidationState (XsdValidationStateManager manager)
+               internal XsdInvalidValidationState (XsdParticleStateManager manager)
                        : base (manager)
                {
                }
 
                // Methods
+
+               public override void GetExpectedParticles (ArrayList al)
+               {
+                       // do nothing
+               }
+
                public override XsdValidationState EvaluateStartElement (string name, string ns)
                {
                        return this;