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
;
39 namespace Mono
.Xml
.XPath2
41 internal class XQueryContextManager
43 XQueryStaticContext staticContext
;
45 // Fixed dynamic context during evaluation
47 XmlResolver extDocResolver
;
49 Stack
<XQueryContext
> contextStack
= new Stack
<XQueryContext
> ();
50 XQueryContext currentContext
;
51 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
53 Stack
<XPathSequence
> contextSequenceStack
= new Stack
<XPathSequence
> ();
55 XmlWriter currentWriter
;
56 XPathItem input
; // source input item(node)
57 XPathSequence currentSequence
;
58 XmlNamespaceManager namespaceManager
;
59 Hashtable localCollationCache
= new Hashtable ();
61 internal XQueryContextManager (XQueryStaticContext ctx
, XPathItem input
, XmlWriter writer
, XmlResolver resolver
, XmlArgumentList args
)
64 this.staticContext
= ctx
;
66 currentWriter
= writer
;
67 this.extDocResolver
= resolver
;
69 namespaceManager
= new XmlNamespaceManager (ctx
.NameTable
);
70 foreach (DictionaryEntry de
in ctx
.NSResolver
.GetNamespacesInScope (XmlNamespaceScope
.ExcludeXml
))
71 namespaceManager
.AddNamespace (de
.Key
.ToString (), de
.Value
.ToString ());
72 namespaceManager
.PushScope ();
74 currentContext
= new XQueryContext (this, null, new Hashtable ());
76 currentSequence
= new SingleItemIterator (input
, currentContext
);
77 currentSequence
.MoveNext ();
79 currentContext
= new XQueryContext (this, currentSequence
, new Hashtable ());
82 public bool Initialized
{
83 get { return currentContext != null; }
86 public XmlResolver ExtDocResolver
{
87 get { return extDocResolver; }
90 public XmlArgumentList Arguments
{
94 public XmlWriter Writer
{
95 get { return currentWriter; }
96 // FIXME: might be better avoid setter as public
97 set { currentWriter = value; }
100 internal XQueryContext CurrentContext
{
101 get { return currentContext; }
104 internal XQueryStaticContext StaticContext
{
105 get { return staticContext; }
108 internal CultureInfo
GetCulture (string collation
)
110 CultureInfo ci
= staticContext
.GetCulture (collation
);
112 ci
= (CultureInfo
) localCollationCache
[collation
];
115 ci
= new CultureInfo (collation
);
116 localCollationCache
[collation
] = ci
;
120 public void PushCurrentSequence (XPathSequence sequence
)
122 if (sequence
== null)
123 throw new ArgumentNullException ();
124 // sequence = sequence.Clone ();
125 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
126 contextStack
.Push (currentContext
);
127 currentsequence
= sequence
;
128 currentContext
= new XQueryContext (this);
130 contextSequenceStack
.Push (currentSequence
);
131 currentSequence
= sequence
;
135 public void PopCurrentSequence ()
137 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
140 currentSequence
= contextSequenceStack
.Pop ();
142 if (currentSequence
== null)
143 throw new SystemException ("XQuery error: should not happen.");
146 internal void PushContext ()
148 contextStack
.Push (currentContext
);
149 currentContext
= new XQueryContext (this);
152 internal void PopContext ()
154 currentContext
= contextStack
.Pop ();
157 internal void PushVariable (XmlQualifiedName name
, object iter
)
160 CurrentContext
.SetVariable (name
, iter
);
163 internal void PopVariable ()
168 internal XmlNamespaceManager NSManager
{
169 get { return namespaceManager; }
172 internal XPathSequence CurrentSequence
{
173 get { return currentSequence; }
177 public class XQueryContext
: IXmlNamespaceResolver
179 XQueryContextManager contextManager
;
180 Hashtable currentVariables
;
181 XPathSequence currentSequence
;
183 internal XQueryContext (XQueryContextManager manager
)
185 manager
.CurrentSequence
,
186 (Hashtable
) manager
.CurrentContext
.currentVariables
.Clone ())
190 internal XQueryContext (XQueryContextManager manager
, XPathSequence currentSequence
, Hashtable currentVariables
)
192 contextManager
= manager
;
193 this.currentSequence
= currentSequence
;
195 if (manager.CurrentContext != null)
196 currentVariables = (Hashtable) manager.CurrentContext.currentVariables.Clone ();
198 currentVariables = new Hashtable ();
200 this.currentVariables
= currentVariables
;
203 internal XmlWriter Writer
{
204 get { return contextManager.Writer; }
205 // FIXME: might be better avoid public setter.
206 set { contextManager.Writer = value; }
209 internal XQueryStaticContext StaticContext
{
210 get { return contextManager.StaticContext; }
213 internal CultureInfo DefaultCollation
{
214 get { return StaticContext.DefaultCollation; }
217 internal XQueryContextManager ContextManager
{
218 get { return contextManager; }
221 public XPathItem CurrentItem
{
223 if (currentSequence
== null)
224 throw new XmlQueryException ("This XQuery dynamic context has no context item.");
225 return CurrentSequence
.Current
;
229 public XPathNavigator CurrentNode
{
230 get { return CurrentItem as XPathNavigator; }
233 public XPathSequence CurrentSequence
{
234 get { return currentSequence; }
237 internal CultureInfo
GetCulture (string collation
)
239 return contextManager
.GetCulture (collation
);
242 internal void PushVariable (XmlQualifiedName name
, object iter
)
244 contextManager
.PushVariable (name
, iter
);
247 // FIXME: Hmm... this design is annoying.
248 internal void SetVariable (XmlQualifiedName name
, object iter
)
250 currentVariables
[name
] = iter
;
253 internal void PopVariable ()
255 contextManager
.PopVariable ();
258 internal XPathSequence
ResolveVariable (XmlQualifiedName name
)
260 object obj
= currentVariables
[name
];
261 if (obj
== null && contextManager
.Arguments
!= null)
262 obj
= contextManager
.Arguments
.GetParameter (name
.Name
, name
.Namespace
);
264 return new XPathEmptySequence (this);
265 XPathSequence seq
= obj
as XPathSequence
;
268 XPathItem item
= obj
as XPathItem
;
270 item
= new XPathAtomicValue (obj
, XmlSchemaType
.GetBuiltInType (XPathAtomicValue
.XmlTypeCodeFromRuntimeType (obj
.GetType (), true)));
271 return new SingleItemIterator (item
, this);
274 internal XPathSequence
ResolveCollection (string name
)
276 // FIXME: support later.
277 return new XPathEmptySequence (currentSequence
.Context
);
280 public IXmlNamespaceResolver NSResolver
{
281 get { return contextManager.NSManager; }
284 #region IXmlNamespaceResolver implementation
285 public XmlNameTable NameTable
{
286 get { return contextManager.NSManager.NameTable; }
289 public string LookupPrefix (string ns
)
291 return contextManager
.NSManager
.LookupPrefix (ns
);
294 public string LookupPrefix (string ns
, bool atomized
)
296 return contextManager
.NSManager
.LookupPrefix (ns
, atomized
);
299 public string LookupNamespace (string prefix
)
301 return contextManager
.NSManager
.LookupNamespace (prefix
);
304 public string LookupNamespace (string prefix
, bool atomized
)
306 return contextManager
.NSManager
.LookupNamespace (prefix
, atomized
);
309 public IDictionary
GetNamespacesInScope (XmlNamespaceScope scope
)
311 return contextManager
.NSManager
.GetNamespacesInScope (scope
);