2 // XQueryFunction.cs - XQuery 1.0 and XPath 2.0 Functions implementation
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 // See XQuery 1.0 and XPath 2.0 Functions and Operators.
35 using System.Collections;
36 using System.Reflection;
38 using System.Xml.Schema;
39 using System.Xml.Query;
40 using System.Xml.XPath;
44 namespace Mono.Xml.XPath2
46 // It is instantiated per function definition. (e.g. fn:string(), fn:data(), fn:contat()).
47 public abstract class XQueryFunction
49 public const string Namespace = "http://www.w3.org/2004/07/xpath-functions";
51 static XQueryFunctionTable defaultFunctions = new XQueryFunctionTable ();
53 static XQueryFunction ()
55 defaultFunctions.Add (FromName ("node-name", "FnNodeName"));
56 defaultFunctions.Add (FromName ("nilled", "FnNilled"));
57 defaultFunctions.Add (FromName ("string", "FnString"));
58 defaultFunctions.Add (FromName ("data", "FnData"));
59 defaultFunctions.Add (FromName ("base-uri", "FnBaseUri"));
60 defaultFunctions.Add (FromName ("document-uri", "FnDocumentUri"));
61 defaultFunctions.Add (FromName ("error", "FnError"));
62 defaultFunctions.Add (FromName ("trace", "FnTrace"));
63 defaultFunctions.Add (FromName ("abs", "FnAbs"));
64 defaultFunctions.Add (FromName ("ceiling", "FnCeiling"));
65 defaultFunctions.Add (FromName ("floor", "FnFloor"));
66 defaultFunctions.Add (FromName ("round", "FnRound"));
67 defaultFunctions.Add (FromName ("round-half-to-even", "FnRoundHalfToEven"));
68 defaultFunctions.Add (FromName ("codepoints-to-string", "FnCodepointsToString"));
69 defaultFunctions.Add (FromName ("string-to-codepoints", "FnStringToCodepoints"));
70 defaultFunctions.Add (FromName ("compare", "FnCompare"));
71 defaultFunctions.Add (FromName ("concat", "FnConcat"));
72 defaultFunctions.Add (FromName ("string-join", "FnStringJoin"));
73 defaultFunctions.Add (FromName ("substring", "FnSubstring"));
74 defaultFunctions.Add (FromName ("string-length", "FnStringLength"));
75 defaultFunctions.Add (FromName ("normaize-space", "FnNormalizeSpace"));
76 defaultFunctions.Add (FromName ("normalize-unicode", "FnNormalizeUnicode"));
77 defaultFunctions.Add (FromName ("uppercase", "FnUpperCase"));
78 defaultFunctions.Add (FromName ("lowercase", "FnLowerCase"));
79 defaultFunctions.Add (FromName ("translate", "FnTranslate"));
80 defaultFunctions.Add (FromName ("escape-uri", "FnEscapeUri"));
81 defaultFunctions.Add (FromName ("contains", "FnContains"));
82 defaultFunctions.Add (FromName ("starts-with", "FnStartsWith"));
83 defaultFunctions.Add (FromName ("ends-with", "FnEndsWith"));
84 defaultFunctions.Add (FromName ("substring-before", "FnSubstringBefore"));
85 defaultFunctions.Add (FromName ("substring-after", "FnSubstringAfter"));
86 defaultFunctions.Add (FromName ("matches", "FnMatches"));
87 defaultFunctions.Add (FromName ("replace", "FnReplace"));
88 defaultFunctions.Add (FromName ("tokenize", "FnTokenize"));
89 defaultFunctions.Add (FromName ("resolve-uri", "FnResolveUri"));
90 defaultFunctions.Add (FromName ("true", "FnTrue"));
91 defaultFunctions.Add (FromName ("false", "FnFalse"));
92 defaultFunctions.Add (FromName ("not", "FnNot"));
94 defaultFunctions.Add (FromName ("resolve-qname", "FnResolveQName"));
95 defaultFunctions.Add (FromName ("expand-qname", "FnExpandQName"));
96 defaultFunctions.Add (FromName ("namespace-uri-for-prefix", "FnNamespaceUriForPrefix"));
97 defaultFunctions.Add (FromName ("in-scope-prefixes", "FnInScopePrefixes"));
98 defaultFunctions.Add (FromName ("name", "FnName"));
99 defaultFunctions.Add (FromName ("local-name", "FnLocalName"));
100 defaultFunctions.Add (FromName ("namespace-uri", "FnNamespaceUri"));
101 defaultFunctions.Add (FromName ("number", "FnNumber"));
102 defaultFunctions.Add (FromName ("lang", "FnLang"));
103 defaultFunctions.Add (FromName ("root", "FnRoot"));
104 defaultFunctions.Add (FromName ("boolean", "FnBoolean"));
105 defaultFunctions.Add (FromName ("indexof", "FnIndexOf"));
106 defaultFunctions.Add (FromName ("empty", "FnEmpty"));
107 defaultFunctions.Add (FromName ("exists", "FnExists"));
108 defaultFunctions.Add (FromName ("distinct-values", "FnDistinctValues"));
109 defaultFunctions.Add (FromName ("insert-before", "FnInsertBefore"));
110 defaultFunctions.Add (FromName ("remove", "FnRemove"));
111 defaultFunctions.Add (FromName ("reverse", "FnReverse"));
112 defaultFunctions.Add (FromName ("subsequence", "FnSubsequence"));
113 defaultFunctions.Add (FromName ("unordered", "FnUnordered"));
114 defaultFunctions.Add (FromName ("zero-or-one", "FnZeroOrOne"));
115 defaultFunctions.Add (FromName ("one-or-more", "FnOneOrMore"));
116 defaultFunctions.Add (FromName ("exactly-one", "FnExactlyOne"));
117 defaultFunctions.Add (FromName ("deep-equal", "FnDeepEqual"));
118 defaultFunctions.Add (FromName ("count", "FnCount"));
119 defaultFunctions.Add (FromName ("avg", "FnAvg"));
120 defaultFunctions.Add (FromName ("max", "FnMax"));
121 defaultFunctions.Add (FromName ("min", "FnMin"));
122 defaultFunctions.Add (FromName ("sum", "FnSum"));
123 defaultFunctions.Add (FromName ("id", "FnId"));
124 defaultFunctions.Add (FromName ("idref", "FnIdRef"));
125 defaultFunctions.Add (FromName ("doc", "FnDoc"));
126 defaultFunctions.Add (FromName ("collection", "FnCollection"));
127 defaultFunctions.Add (FromName ("position", "FnPosition"));
128 defaultFunctions.Add (FromName ("last", "FnLast"));
129 defaultFunctions.Add (FromName ("current-datetime", "FnCurrentDateTime"));
130 defaultFunctions.Add (FromName ("current-date", "FnCurrentDate"));
131 defaultFunctions.Add (FromName ("current-time", "FnCurrentTime"));
132 defaultFunctions.Add (FromName ("default-collation", "FnDefaultCollation"));
133 defaultFunctions.Add (FromName ("implicit-timezone", "FnImplicitTimeZone"));
134 // defaultFunctions.Add (FromName ("years-from-duration", "FnYearsFromDuration"));
137 fnYearsFromDuration, fnMonthsFromDuration,
138 fnDaysFromDuration, fnHoursFromDuration,
139 fnMinutesFromDuration, fnSecondsFromDuration,
140 fnYearFromDateTime, fnMonthFromDateTime,
141 fnDayFromDateTime, fnHoursFromDateTime,
142 fnMinutesFromDateTime, fnSecondsFromDateTime,
143 fnTimeZoneFromDateTime, fnYearFromDate, fnMonthFromDate,
144 fnDayFromDate, fnTimeZoneFromDate, fnHoursFromTime,
145 fnMinutesFromTime, fnSecondsFromTime,
146 fnTimeZoneFromTime, fnAdjustDateTimeToTimeZone,
147 fnAdjustDateToTimeZone, fnAdjustTimeToTimeZone,
148 fnSubtractDateTimesYieldingYearMonthDuration,
149 fnSubtractDateTimesYieldingDayTimeDuration,
150 fnSubtractDatesYieldingYearMonthDuration,
151 fnSubtractDatesYieldingDayTimeDuration,
156 private static XQueryCliFunction FromName (string xname, string cliname)
158 return XQueryCliFunction.CreateFromMethodInfo (
159 new XmlQualifiedName (xname, XQueryFunction.Namespace),
160 FindNamedMethods (typeof (XQueryFunctionCliImpl), cliname)
164 internal static XQueryCliFunction FromQName (XmlQualifiedName qname)
166 return XQueryCliFunction.CreateFromMethodInfo (
167 qname, FindNamedMethods (Type.GetType (qname.Namespace), qname.Name));
170 private static bool FilterImpl (MemberInfo m, object filterCriteria)
172 return m.Name == filterCriteria.ToString ();
175 private static MemberFilter memberFilter = new MemberFilter (FilterImpl);
177 private static MethodInfo [] FindNamedMethods (Type type, string name)
179 ArrayList al = new ArrayList (
182 BindingFlags.Default | BindingFlags.Public | BindingFlags.Static,
183 // FIXME: wait for anonymous method support
184 // delegate (MemberInfo m, object filterCriteria) {
185 // return m.Name == filterCriteria.ToString ();
189 return al.ToArray (typeof (MethodInfo)) as MethodInfo [];
192 internal static XQueryFunction FindKnownFunction (
193 XmlQualifiedName name)
195 switch (name.Namespace) {
196 case XQueryFunction.Namespace:
197 return defaultFunctions [name];
198 case InternalPool.XdtNamespace:
199 case XmlSchema.Namespace:
200 XmlSchemaType type = XmlSchemaType.GetBuiltInSimpleType (name);
202 return null; // FIXME: atomic constructor
203 type = XmlSchemaType.GetBuiltInComplexType (name);
205 return null; // FIXME: atomic constructor?
214 internal XQueryFunction (XmlQualifiedName name, XQueryFunctionArgument [] args, SequenceType returnType)
218 this.returnType = returnType;
223 XmlQualifiedName name;
224 XQueryFunctionArgument [] args;
225 SequenceType returnType;
229 public XmlQualifiedName Name {
233 public abstract int MinArgs { get; }
234 public abstract int MaxArgs { get; }
236 public XQueryFunctionArgument [] Args {
240 public SequenceType ReturnType {
241 get { return returnType; }
244 public abstract object Invoke (XPathSequence current, object [] args);
246 public virtual XPathSequence Evaluate (XPathSequence iter, ExprSequence args)
248 object [] instParams = new object [args.Count];
249 for (int i = 0; i < args.Count; i++) {
250 XPathSequence val = args [i].Evaluate (iter);
251 instParams [i] = Args [i].Type.ToRuntimeType (val);
253 object o = Invoke (iter, instParams);
255 return new XPathEmptySequence (iter.Context);
256 if (o is XPathSequence)
257 return (XPathSequence) o;
258 XPathItem item = o as XPathItem;
260 item = new XPathAtomicValue (o, ReturnType.SchemaType);
261 return new SingleItemIterator (item, iter.Context);
265 public class XQueryFunctionArgument
267 public XQueryFunctionArgument (XmlQualifiedName name, SequenceType type)
273 XmlQualifiedName name;
276 public XmlQualifiedName Name {
280 public SequenceType Type {
285 public class XQueryUserFunction : XQueryFunction
289 internal XQueryUserFunction (XmlQualifiedName name,
290 XQueryFunctionArgument [] parameters,
292 SequenceType returnType)
293 : base (name, parameters, returnType)
298 public override int MinArgs {
299 get { return Args.Length; }
302 public override int MaxArgs {
303 get { return Args.Length; }
306 public override object Invoke (XPathSequence current, object [] args)
308 throw new SystemException ("XQuery internal error: should not happen.");
311 public override XPathSequence Evaluate (XPathSequence iter, ExprSequence args)
313 for (int i = 0; i < Args.Length; i++)
314 iter.Context.PushVariable (Args [i].Name, args [i].Evaluate (iter));
315 XPathSequence seq = new ExprSequenceIterator (iter, expr);
316 for (int i = 0; i < Args.Length; i++)
317 iter.Context.PopVariable ();