2 // XQueryContext.cs - XQuery/XPath2 dynamic context
5 // Atsushi Enomoto <atsushi@ximian.com>
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
31 using System
.Collections
;
32 using System
.Collections
.Generic
;
33 using System
.Globalization
;
35 using System
.Xml
.Schema
;
36 using System
.Xml
.XPath
;
37 using System
.Xml
.Query
;
40 namespace Mono
.Xml
.XPath2
42 internal class XQueryContextManager
44 XQueryStaticContext staticContext
;
46 // Fixed dynamic context during evaluation
48 XmlResolver extDocResolver
;
50 Stack
<XQueryContext
> contextStack
= new Stack
<XQueryContext
> ();
51 XQueryContext currentContext
;
52 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
54 Stack
<XPathSequence
> contextSequenceStack
= new Stack
<XPathSequence
> ();
56 XmlWriter currentWriter
;
57 XPathItem input
; // source input item(node)
58 XPathSequence currentSequence
;
59 XmlNamespaceManager namespaceManager
;
60 Hashtable localCollationCache
= new Hashtable ();
62 internal XQueryContextManager (XQueryStaticContext ctx
, XPathItem input
, XmlWriter writer
, XmlResolver resolver
, XmlArgumentList args
)
65 this.staticContext
= ctx
;
67 currentWriter
= writer
;
68 this.extDocResolver
= resolver
;
70 namespaceManager
= new XmlNamespaceManager (ctx
.NameTable
);
71 foreach (DictionaryEntry de
in ctx
.NSResolver
.GetNamespacesInScope (XmlNamespaceScope
.ExcludeXml
))
72 namespaceManager
.AddNamespace (de
.Key
.ToString (), de
.Value
.ToString ());
73 namespaceManager
.PushScope ();
75 currentContext
= new XQueryContext (this, null, new Hashtable ());
77 currentSequence
= new SingleItemIterator (input
, currentContext
);
78 currentSequence
.MoveNext ();
80 currentContext
= new XQueryContext (this, currentSequence
, new Hashtable ());
83 public bool Initialized
{
84 get { return currentContext != null; }
87 public XmlResolver ExtDocResolver
{
88 get { return extDocResolver; }
91 public XmlArgumentList Arguments
{
95 public XmlWriter Writer
{
96 get { return currentWriter; }
97 // FIXME: might be better avoid setter as public
98 set { currentWriter = value; }
101 internal XQueryContext CurrentContext
{
102 get { return currentContext; }
105 internal XQueryStaticContext StaticContext
{
106 get { return staticContext; }
109 internal CultureInfo
GetCulture (string collation
)
111 CultureInfo ci
= staticContext
.GetCulture (collation
);
113 ci
= (CultureInfo
) localCollationCache
[collation
];
116 ci
= new CultureInfo (collation
);
117 localCollationCache
[collation
] = ci
;
121 public void PushCurrentSequence (XPathSequence sequence
)
123 if (sequence
== null)
124 throw new ArgumentNullException ();
125 // sequence = sequence.Clone ();
126 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
127 contextStack
.Push (currentContext
);
128 currentsequence
= sequence
;
129 currentContext
= new XQueryContext (this);
131 contextSequenceStack
.Push (currentSequence
);
132 currentSequence
= sequence
;
136 public void PopCurrentSequence ()
138 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
141 currentSequence
= contextSequenceStack
.Pop ();
143 if (currentSequence
== null)
144 throw new SystemException ("XQuery error: should not happen.");
147 internal void PushContext ()
149 contextStack
.Push (currentContext
);
150 currentContext
= new XQueryContext (this);
153 internal void PopContext ()
155 currentContext
= contextStack
.Pop ();
158 internal void PushVariable (XmlQualifiedName name
, object iter
)
161 CurrentContext
.SetVariable (name
, iter
);
164 internal void PopVariable ()
169 internal XmlNamespaceManager NSManager
{
170 get { return namespaceManager; }
173 internal XPathSequence CurrentSequence
{
174 get { return currentSequence; }
178 public class XQueryContext
: IXmlNamespaceResolver
180 XQueryContextManager contextManager
;
181 Hashtable currentVariables
;
182 XPathSequence currentSequence
;
184 internal XQueryContext (XQueryContextManager manager
)
186 manager
.CurrentSequence
,
187 (Hashtable
) manager
.CurrentContext
.currentVariables
.Clone ())
191 internal XQueryContext (XQueryContextManager manager
, XPathSequence currentSequence
, Hashtable currentVariables
)
193 contextManager
= manager
;
194 this.currentSequence
= currentSequence
;
196 if (manager.CurrentContext != null)
197 currentVariables = (Hashtable) manager.CurrentContext.currentVariables.Clone ();
199 currentVariables = new Hashtable ();
201 this.currentVariables
= currentVariables
;
204 internal XmlWriter Writer
{
205 get { return contextManager.Writer; }
206 // FIXME: might be better avoid public setter.
207 set { contextManager.Writer = value; }
210 internal XQueryStaticContext StaticContext
{
211 get { return contextManager.StaticContext; }
214 internal CultureInfo DefaultCollation
{
215 get { return StaticContext.DefaultCollation; }
218 internal XQueryContextManager ContextManager
{
219 get { return contextManager; }
222 public XPathItem CurrentItem
{
224 if (currentSequence
== null)
225 throw new XmlQueryException ("This XQuery dynamic context has no context item.");
226 return CurrentSequence
.Current
;
230 public XPathNavigator CurrentNode
{
231 get { return CurrentItem as XPathNavigator; }
234 public XPathSequence CurrentSequence
{
235 get { return currentSequence; }
238 internal CultureInfo
GetCulture (string collation
)
240 return contextManager
.GetCulture (collation
);
243 internal void PushVariable (XmlQualifiedName name
, object iter
)
245 contextManager
.PushVariable (name
, iter
);
248 // FIXME: Hmm... this design is annoying.
249 internal void SetVariable (XmlQualifiedName name
, object iter
)
251 currentVariables
[name
] = iter
;
254 internal void PopVariable ()
256 contextManager
.PopVariable ();
259 internal XPathSequence
ResolveVariable (XmlQualifiedName name
)
261 object obj
= currentVariables
[name
];
262 if (obj
== null && contextManager
.Arguments
!= null)
263 obj
= contextManager
.Arguments
.GetParameter (name
.Name
, name
.Namespace
);
265 return new XPathEmptySequence (this);
266 XPathSequence seq
= obj
as XPathSequence
;
269 XPathItem item
= obj
as XPathItem
;
271 item
= new XPathAtomicValue (obj
, InternalPool
.GetBuiltInType (InternalPool
.XmlTypeCodeFromRuntimeType (obj
.GetType (), true)));
272 return new SingleItemIterator (item
, this);
275 internal XPathSequence
ResolveCollection (string name
)
277 // FIXME: support later.
278 return new XPathEmptySequence (currentSequence
.Context
);
281 public IXmlNamespaceResolver NSResolver
{
282 get { return contextManager.NSManager; }
285 #region IXmlNamespaceResolver implementation
286 public XmlNameTable NameTable
{
287 get { return contextManager.NSManager.NameTable; }
290 public string LookupPrefix (string ns
)
292 return contextManager
.NSManager
.LookupPrefix (ns
);
295 public string LookupPrefix (string ns
, bool atomized
)
297 return contextManager
.NSManager
.LookupPrefix (ns
, atomized
);
300 public string LookupNamespace (string prefix
)
302 return contextManager
.NSManager
.LookupNamespace (prefix
);
305 public string LookupNamespace (string prefix
, bool atomized
)
307 return contextManager
.NSManager
.LookupNamespace (prefix
, atomized
);
310 public IDictionary
GetNamespacesInScope (XmlNamespaceScope scope
)
312 return contextManager
.NSManager
.GetNamespacesInScope (scope
);