2003-08-18 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                                 //TODO: which outputter should be used here?
50                                 Outputter outputter = new XmlOutputter(w, p.CompiledStyle.Style.Outputs);
51                                 p.PushOutput (outputter);
52                                 content.Evaluate (p);
53                                 p.PopOutput ();
54                                 return w.Document.CreateNavigator ().SelectChildren (XPathNodeType.All);
55                         } else {
56                                 return "";
57                         }
58                 }
59                 
60                 public QName Name { get { return name; }}
61         }
62         
63         public abstract class XslGeneralVariable : XslCompiledElement, IXsltContextVariable {
64                 protected XslVariableInformation var;   
65                 
66                 public XslGeneralVariable (Compiler c) : base (c) {}
67                 
68                 protected override void Compile (Compiler c)
69                 {
70                         this.var = new XslVariableInformation (c);
71                 }
72                 
73                 public override abstract void Evaluate (XslTransformProcessor p);
74                 protected abstract object GetValue (XslTransformProcessor p);
75                 
76                 
77                 public object Evaluate (XsltContext xsltContext)
78                 {       
79                         object value = GetValue (((XsltCompiledContext)xsltContext).Processor);
80                         
81                         if (value is XPathNodeIterator)                 
82                                 return ((XPathNodeIterator)value).Clone ();
83                         
84                         return value;
85                 }
86
87                 public QName Name {get {return  var.Name;}}
88                 public XPathResultType VariableType { get {return XPathResultType.Any;}}
89                 public abstract bool IsLocal { get; }
90                 public abstract bool IsParam { get; }
91         }
92         
93         public class XslGlobalVariable : XslGeneralVariable {
94                 public XslGlobalVariable (Compiler c) : base (c) {}
95                 static object busyObject = new Object ();
96                 
97                         
98                 public override void Evaluate (XslTransformProcessor p)
99                 {
100                         Hashtable varInfo = p.globalVariableTable;
101                         
102                         if (varInfo.Contains (this)) {
103                                 if (varInfo [this] == busyObject)
104                                         throw new Exception ("Circular Dependency");
105                                 return;
106                         }
107                         
108                         varInfo [this] = busyObject;
109                         varInfo [this] = var.Evaluate (p);
110                         
111                 }
112                 
113                 protected override object GetValue (XslTransformProcessor p)
114                 {
115                         Evaluate (p);
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 bool IsEvaluated (XslTransformProcessor p)
158                 {
159                         return p.GetStackItem (slot) != null;
160                 }
161                 
162                 public override bool IsLocal { get { return true; }}
163                 public override bool IsParam { get { return false; }}
164         }
165         
166         public class XslLocalParam : XslLocalVariable {
167                 bool overriden;
168                 object paramVal;
169                 
170                 public XslLocalParam (Compiler c) : base (c) {}
171                 
172                 public override void Evaluate (XslTransformProcessor p)
173                 {               
174                         if (p.GetStackItem (slot) != null) return; // evaluated already
175                                 
176                         base.Evaluate (p);
177                 }
178                 
179                 public void Override (XslTransformProcessor p, object paramVal)
180                 {
181                         p.SetStackItem (slot, paramVal);
182                 }
183                 
184                 public override bool IsParam { get { return true; }}
185         }
186 }