2 // XQueryDefaultFunctionCall.cs
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 // XQuery 1.0 and XPath 2.0 Functions implementation as XPathItemExpression.
32 // See XQuery 1.0 and XPath 2.0 Functions and Operators.
36 using System
.Collections
;
37 using System
.Reflection
;
39 using System
.Xml
.Schema
;
40 using System
.Xml
.Query
;
41 using System
.Xml
.XPath
;
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
;
53 qname
= new XmlQualifiedName (name
, XQueryFunction
.Namespace
);
54 qnameTable
.Add (name
, qname
);
59 public DefaultFunctionCall (XQueryStaticContext ctx
, string name
, int minArgs
, int maxArgs
, SequenceType type
, ExprSequence args
)
60 : base (GetName (name
), args
)
63 this.minArgs
= minArgs
;
64 this.maxArgs
= maxArgs
;
71 public override int MinArgs { get { return minArgs; }
}
72 public override int MaxArgs { get { return maxArgs; }
}
74 public override SequenceType StaticType
{
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
);
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;
118 return new SingleItemIterator (new XPathAtomicValue (info
.IsNil
, null), iter
);
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
;
138 XPathSequence res
= Args
[0].Evaluate (iter
);
139 if (!res
.MoveNext ())
140 return new XPathEmptySequence (iter
.Context
);
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
);
180 return new XPathEmptySequence (iter
.Context
);
181 XPathNavigator nav
= res
.Current
as XPathNavigator
;
183 return new XPathEmptySequence (iter
.Context
);
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
);
201 return new XPathEmptySequence (iter
.Context
);
202 XPathNavigator nav
= res
.Current
as XPathNavigator
;
204 return new XPathEmptySequence (iter
.Context
);
207 return new SingleItemIterator (new XPathAtomicValue (nav
.BaseURI
, null), iter
);
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
)
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
);
232 string description
= Args
.Length
> 1 ? Args
[1].EvaluateAsString (iter
) : String
.Empty
;
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
)) {
290 return new SingleItemIterator (new XPathAtomicValue (System
.Math
.Abs (arg
.Current
.ValueAsInt64
), arg
.Current
.XmlType
), iter
);
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 ();