2003-07-30 Ben Maurer <bmaurer@users.sourceforge.net>
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl.Operations / XslVariable.cs
1 //
2 // XslVariable.cs
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
7 //      
8 // (C) 2003 Ben Maurer
9 // (C) 2003 Atsushi Enomoto
10 //
11
12 using System;
13 using System.Collections;
14 using System.Xml;
15 using System.Xml.XPath;
16 using System.Xml.Xsl;
17
18 using QName = System.Xml.XmlQualifiedName;
19
20 namespace Mono.Xml.Xsl.Operations {
21         
22         public class XslVariableInformation
23         {
24                 QName name;
25                 XPathExpression select;
26                 XslOperation content;
27                 
28                 public XslVariableInformation (Compiler c)
29                 {
30                         c.AssertAttribute ("name");
31                         name = c.ParseQNameAttribute ("name");
32                         
33                         string sel = c.GetAttribute ("select");
34                         if (sel != null && sel != "" ) {
35                                 select = c.CompileExpression (c.GetAttribute ("select"));
36                                 // TODO assert empty
37                         } else  if (c.Input.MoveToFirstChild ()) {
38                                 content = c.CompileTemplateContent ();
39                                 c.Input.MoveToParent ();
40                         }
41                 }
42                 
43                 public object Evaluate (XslTransformProcessor p)
44                 {
45                         if (select != null) {
46                                 return p.Evaluate (select);
47                         } else if (content != null) {
48                                 XmlNodeWriter w = new XmlNodeWriter ();
49                                 p.PushOutput (w);
50                                 content.Evaluate (p);
51                                 p.PopOutput ();
52                                 return w.Document.CreateNavigator ().SelectChildren (XPathNodeType.All);
53                         } else {
54                                 return "";
55                         }
56                 }
57                 
58                 public QName Name { get { return name; }}
59         }
60         
61         public abstract class XslGeneralVariable : XslCompiledElement, IXsltContextVariable {
62                 protected XslVariableInformation var;   
63                 
64                 public XslGeneralVariable (Compiler c) : base (c) {}
65                 
66                 protected override void Compile (Compiler c)
67                 {
68                         this.var = new XslVariableInformation (c);
69                 }
70                 
71                 public override abstract void Evaluate (XslTransformProcessor p);
72                 protected abstract object GetValue (XslTransformProcessor p);
73                 
74                 
75                 public object Evaluate (XsltContext xsltContext)
76                 {
77                         XslTransformProcessor p = ((XsltCompiledContext)xsltContext).Processor;
78                         Evaluate (p);
79                         
80                         object value = GetValue (p);
81                         
82                         if (value is XPathNodeIterator)                 
83                                 return ((XPathNodeIterator)value).Clone ();
84                         
85                         return value;
86                 }
87
88                 public QName Name {get {return  var.Name;}}
89                 public XPathResultType VariableType { get {return XPathResultType.Any;}}
90                 public abstract bool IsLocal { get; }
91                 public abstract bool IsParam { get; }
92         }
93         
94         public class XslGlobalVariable : XslGeneralVariable {
95                 public XslGlobalVariable (Compiler c) : base (c) {}
96                 static object busyObject = new Object ();
97                 
98                         
99                 public override void Evaluate (XslTransformProcessor p)
100                 {
101                         Hashtable varInfo = p.globalVariableTable;
102                         
103                         if (varInfo.Contains (this)) {
104                                 if (varInfo [this] == busyObject)
105                                         throw new Exception ("Circular Dependency");
106                                 return;
107                         }
108                         
109                         varInfo [this] = busyObject;
110                         varInfo [this] = var.Evaluate (p);
111                         
112                 }
113                 
114                 protected override object GetValue (XslTransformProcessor p)
115                 {
116                         return p.globalVariableTable [this];
117                 }
118                         
119                 public override bool IsLocal { get { return false; }}
120                 public override bool IsParam { get { return false; }}
121         }
122         
123         public class XslGlobalParam : XslGlobalVariable {
124                 bool overriden;
125                 object paramVal;
126                 
127                 public XslGlobalParam (Compiler c) : base (c) {}
128                         
129                 public void Override (XslTransformProcessor p, object paramVal)
130                 {
131                         Debug.Assert (!p.globalVariableTable.Contains (this), "Shouldn't have been evaluated by this point");
132                         
133                         p.globalVariableTable [this] = paramVal;
134                 }
135                 
136                 public override bool IsParam { get { return true; }}
137         }
138         
139         public class XslLocalVariable : XslGeneralVariable {
140                 protected int slot;
141                                 
142                 public XslLocalVariable (Compiler c) : base (c)
143                 {
144                         slot = c.AddVariable (this);
145                 }
146                 
147                 public override void Evaluate (XslTransformProcessor p)
148                 {       
149                         p.SetStackItem (slot, var.Evaluate (p));
150                 }
151                 
152                 protected override object GetValue (XslTransformProcessor p)
153                 {
154                         return p.GetStackItem (slot);
155                 }
156                 
157                 public override bool IsLocal { get { return true; }}
158                 public override bool IsParam { get { return false; }}
159         }
160         
161         public class XslLocalParam : XslLocalVariable {
162                 bool overriden;
163                 object paramVal;
164                 
165                 public XslLocalParam (Compiler c) : base (c) {}
166                 
167                 public override void Evaluate (XslTransformProcessor p)
168                 {               
169                         if (p.GetStackItem (slot) != null) return; // evaluated already
170                                 
171                         base.Evaluate (p);
172                 }
173                 
174                 public void Override (XslTransformProcessor p, object paramVal)
175                 {
176                         p.SetStackItem (slot, paramVal);
177                 }
178                 
179                 public override bool IsParam { get { return true; }}
180         }
181 }