**** Merged from MCS ****
[mono-project.git] / mcs / class / Mono.Xml.Ext / Mono.Xml.XPath2 / XQueryDefaultFunctionCall.cs
blob7eb4e280563f2266ef3a41242f069cdb8ede2ab7
1 //
2 // XQueryDefaultFunctionCall.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 //
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
9 //
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:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
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 // XQuery 1.0 and XPath 2.0 Functions implementation as XPathItemExpression.
32 // See XQuery 1.0 and XPath 2.0 Functions and Operators.
34 #if NET_2_0
35 using System;
36 using System.Collections;
37 using System.Reflection;
38 using System.Xml;
39 using System.Xml.Schema;
40 using System.Xml.Query;
41 using System.Xml.XPath;
42 using System.Xml.Xsl;
44 namespace Mono.Xml.XPath2
46 internal abstract class DefaultFunctionCall : FunctionCallExprBase
48 static Hashtable qnameTable = new Hashtable ();
49 static XmlQualifiedName GetName (string name)
51 XmlQualifiedName qname = qnameTable [name] as XmlQualifiedName;
52 if (qname == null) {
53 qname = new XmlQualifiedName (name, XQueryFunction.Namespace);
54 qnameTable.Add (name, qname);
56 return qname;
59 public DefaultFunctionCall (XQueryStaticContext ctx, string name, int minArgs, int maxArgs, SequenceType type, ExprSequence args)
60 : base (GetName (name), args)
62 this.type = type;
63 this.minArgs = minArgs;
64 this.maxArgs = maxArgs;
67 SequenceType type;
68 int minArgs;
69 int maxArgs;
71 public override int MinArgs { get { return minArgs; } }
72 public override int MaxArgs { get { return maxArgs; } }
74 public override SequenceType StaticType {
75 get { return type; }
79 // Accessors
81 // 2.1 fn:node-name ($arg as node ()?) as xs:QName?
82 internal class FnNodeNameCall : DefaultFunctionCall
84 public FnNodeNameCall (XQueryStaticContext ctx, ExprSequence args)
85 : base (ctx, "node-name", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsQName, Occurence.Optional), args)
89 public override XPathSequence Evaluate (XPathSequence iter)
91 XPathSequence res = Args [0].Evaluate (iter);
92 if (!res.MoveNext ())
93 return new XPathEmptySequence (iter.Context);
94 // FIXME: what happens if context item is not a node.
95 XPathNavigator nav = res.Current as XPathNavigator;
96 if (nav == null || nav.LocalName == String.Empty)
97 return new XPathEmptySequence (iter.Context);
98 return new SingleItemIterator (new XPathAtomicValue (new XmlQualifiedName (nav.LocalName, nav.NamespaceURI), XmlSchemaSimpleType.XsQName), iter);
102 // 2.2 fn:nilled ($arg as node()) as xs:boolean?
103 internal class FnNilledCall : DefaultFunctionCall
105 public FnNilledCall (XQueryStaticContext ctx, XPathItemExpression [] args)
106 : base (ctx, "nilled", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsBoolean, Occurence.One), args)
110 public override XPathSequence Evaluate (XPathSequence iter)
112 XPathSequence res = Args [0].Evaluate (iter);
113 if (!res.MoveNext ())
114 return new XPathEmptySequence (iter.Context);
115 XPathNavigator nav = res.Current as XPathNavigator;
116 IXmlSchemaInfo info = nav.NodeType == XPathNodeType.Element ? nav.SchemaInfo : null;
117 if (info != null)
118 return new SingleItemIterator (new XPathAtomicValue (info.IsNil, null), iter);
119 else
120 return new XPathEmptySequence (iter.Context);
124 // 2.3 fn:string ($arg as item()?) as xs:string
125 internal class FnStringCall : DefaultFunctionCall
127 public FnStringCall (XQueryStaticContext ctx, XPathItemExpression [] args)
128 : base (ctx, "string", 0, 1, SequenceType.Create (XmlSchemaSimpleType.XsString, Occurence.Optional), args)
132 public override XPathSequence Evaluate (XPathSequence iter)
134 XPathItem item = null;
135 if (Args.Length == 0)
136 item = iter.Context.CurrentItem;
137 else {
138 XPathSequence res = Args [0].Evaluate (iter);
139 if (!res.MoveNext ())
140 return new XPathEmptySequence (iter.Context);
141 item = res.Current;
143 return new SingleItemIterator (new XPathAtomicValue (Core (item), null), iter);
146 private string Core (XPathItem item)
148 XPathNavigator nav = item as XPathNavigator;
150 return nav != null ? nav.Value : XQueryConvert.ItemToString (item);
154 // 2.4 fn:data ($arg as item()*) as xdt:anyAtomicType*
155 internal class FnDataCall : DefaultFunctionCall
157 public FnDataCall (XQueryStaticContext ctx, XPathItemExpression [] args)
158 : base (ctx, "data", 1, 1, SequenceType.Create (XmlSchemaComplexType.AnyType, Occurence.ZeroOrMore), args)
162 public override XPathSequence Evaluate (XPathSequence iter)
164 return new AtomizingIterator (Args [0].Evaluate (iter));
168 // 2.5 fn:base-uri ($arg as node()?) as xs:anyURI?
169 internal class FnBaseUriCall : DefaultFunctionCall
171 public FnBaseUriCall (XQueryStaticContext ctx, XPathItemExpression [] args)
172 : base (ctx, "base-uri", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsAnyUri, Occurence.Optional), args)
176 public override XPathSequence Evaluate (XPathSequence iter)
178 XPathSequence res = Args [0].Evaluate (iter);
179 if (res.MoveNext ())
180 return new XPathEmptySequence (iter.Context);
181 XPathNavigator nav = res.Current as XPathNavigator;
182 if (nav == null)
183 return new XPathEmptySequence (iter.Context);
184 else
185 return new SingleItemIterator (new XPathAtomicValue (nav.BaseURI, XmlSchemaSimpleType.XsString), iter);
189 // 2.6 fn:document-uri ($arg as node()?) as xs:anyURI?
190 internal class FnDocumentUriCall : DefaultFunctionCall
192 public FnDocumentUriCall (XQueryStaticContext ctx, XPathItemExpression [] args)
193 : base (ctx, "document-uri", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsAnyUri, Occurence.Optional), args)
197 public override XPathSequence Evaluate (XPathSequence iter)
199 XPathSequence res = Args [0].Evaluate (iter);
200 if (res.MoveNext ())
201 return new XPathEmptySequence (iter.Context);
202 XPathNavigator nav = res.Current as XPathNavigator;
203 if (nav == null)
204 return new XPathEmptySequence (iter.Context);
205 nav = nav.Clone ();
206 nav.MoveToRoot ();
207 return new SingleItemIterator (new XPathAtomicValue (nav.BaseURI, null), iter);
211 // 3 fn:error ()
212 // fn:error ($error as xs:QName)
213 // fn:error ($error as xs:QName, $description as xs:string)
214 // fn:error ($error as xs:QName, $description as xs:string, $error-object as item()*)
215 internal class FnErrorCall : DefaultFunctionCall
217 public FnErrorCall (XQueryStaticContext ctx, XPathItemExpression [] args)
218 // FIXME: return type is actually none
219 : base (ctx, "error", 0, 3, SequenceType.AnyType, args)
223 public override XPathSequence Evaluate (XPathSequence iter)
225 // error name
226 XPathSequence errorNameIter = Args.Length > 0 ? Args [0].Evaluate (iter) : null;
227 XmlQualifiedName errorType = XmlQualifiedName.Empty;
228 if (errorNameIter != null && errorNameIter.MoveNext ())
229 errorType = XQueryConvert.ItemToQName (errorNameIter.Current);
231 // description
232 string description = Args.Length > 1 ? Args [1].EvaluateAsString (iter) : String.Empty;
234 // error-object
235 XPathSequence errorObjIter = Args.Length > 2 ? Args [2].Evaluate (iter) : null;
237 // FIXME: add error-object information
238 throw new XmlQueryException (errorType + description);
242 // 4 trace ($value as item()*, $label as xs:string) as item()*
243 internal class FnTraceCall : DefaultFunctionCall
245 public FnTraceCall (XQueryStaticContext ctx, XPathItemExpression [] args)
246 : base (ctx, "trace", 2, 2, SequenceType.Create (XmlSchemaComplexType.AnyType, Occurence.ZeroOrMore), args)
250 public override XPathSequence Evaluate (XPathSequence iter)
252 return new TracingIterator (Args [0].Evaluate (iter), Args [1].EvaluateAsString (iter));
256 // 5 constructor functions
257 internal class AtomicConstructorCall : DefaultFunctionCall
259 // FIXME: use IXmlNamespaceResolver.LookupPrefix() in ctx
260 public AtomicConstructorCall (XQueryStaticContext ctx, SequenceType type, XPathItemExpression [] args)
261 : base (ctx, type.SchemaType.QualifiedName.Name, 1, 1, type, args)
265 public override XPathSequence Evaluate (XPathSequence iter)
267 return new SingleItemIterator (XQueryConvert.ItemToItem (Atomize (Args [0].Evaluate (iter)), null), iter);
271 // 6 functions on numerics (operators are not defined here)
273 // 6.4.1 fn:abs ($arg as numeric?) as numeric?
274 internal class FnAbsCall : DefaultFunctionCall
276 public FnAbsCall (XQueryStaticContext ctx, XPathItemExpression [] args)
277 : base (ctx, "abs", 1, 1, args [0].StaticType, args)
281 public override XPathSequence Evaluate (XPathSequence iter)
283 XPathSequence arg = Args [0].Evaluate (iter);
284 if (!arg.MoveNext ())
285 return new XPathEmptySequence (iter.Context);
286 XPathAtomicValue a = null;
287 // FIXME: use schema type IsDerivedFrom()
288 switch (Type.GetTypeCode (arg.Current.ValueType)) {
289 case TypeCode.Int64:
290 return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsInt64), arg.Current.XmlType), iter);
291 case TypeCode.Int32:
292 return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsInt32), arg.Current.XmlType), iter);
293 case TypeCode.Double:
294 return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsDouble), arg.Current.XmlType), iter);
295 case TypeCode.Decimal:
296 return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsDecimal), arg.Current.XmlType), iter);
297 case TypeCode.Single:
298 return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsSingle), arg.Current.XmlType), iter);
300 return new XPathEmptySequence (iter.Context);
304 // 6.4.2 fn:ceiling ($arg as numeric?) as numeric?
305 internal class FnCeilingCall : DefaultFunctionCall
307 public FnCeilingCall (XQueryStaticContext ctx, XPathItemExpression [] args)
308 : base (ctx, "ceiling", 1, 1, args [0].StaticType, args)
312 public override XPathSequence Evaluate (XPathSequence iter)
314 throw new NotImplementedException ();
318 // 6.4.3 fn:floor ($arg as numeric?) as numeric?
319 internal class FnFloorCall : DefaultFunctionCall
321 public FnFloorCall (XQueryStaticContext ctx, XPathItemExpression [] args)
322 : base (ctx, "floor", 1, 1, args [0].StaticType, args)
326 public override XPathSequence Evaluate (XPathSequence iter)
328 throw new NotImplementedException ();
332 // 6.4.4 fn:round ($arg as numeric?) as numeric?
333 internal class FnRoundCall : DefaultFunctionCall
335 public FnRoundCall (XQueryStaticContext ctx, XPathItemExpression [] args)
336 : base (ctx, "round", 1, 1, args [0].StaticType, args)
340 public override XPathSequence Evaluate (XPathSequence iter)
342 throw new NotImplementedException ();
346 // 6.4.5 fn:round-half-to-even ($arg as numeric?) as numeric?
347 internal class FnRoundHalfToEvenCall : DefaultFunctionCall
349 public FnRoundHalfToEvenCall (XQueryStaticContext ctx, XPathItemExpression [] args)
350 : base (ctx, "round-half-to-even", 1, 2, args [0].StaticType, args)
354 public override XPathSequence Evaluate (XPathSequence iter)
356 throw new NotImplementedException ();
360 // 7.2.1 fn:codepoints-to-string ($arg as xs:integer*) as xs:string
361 internal class FnCodepointsToStringCall : DefaultFunctionCall
363 public FnCodepointsToStringCall (XQueryStaticContext ctx, XPathItemExpression [] args)
364 : base (ctx, "codepoints-to-string", 1, 1, SequenceType.IntegerList, args)
368 public override XPathSequence Evaluate (XPathSequence iter)
370 throw new NotImplementedException ();
374 internal class FnStringCallToCodepointsCall : DefaultFunctionCall
376 public FnStringCallToCodepointsCall (XQueryStaticContext ctx, XPathItemExpression [] args)
377 : base (ctx, "string-to-codepoints", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsString, Occurence.Optional), args)
381 public override XPathSequence Evaluate (XPathSequence iter)
383 throw new NotImplementedException ();
387 #endif