Project

Profile

Help

How to connect?
Download (14.2 KB) Statistics
| Branch: | Tag: | Revision:

he / latest9.2 / hen / csource / api / Saxon.Api / Extensibility.cs @ 79987d15

1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4

    
5
using JStaticContext = net.sf.saxon.expr.StaticContext;
6
using JXPathException = net.sf.saxon.trans.XPathException;
7
using JXPathContext = net.sf.saxon.expr.XPathContext;
8
using JExtensionFunctionDefinition = net.sf.saxon.functions.ExtensionFunctionDefinition;
9
using JExtensionFunctionCall = net.sf.saxon.functions.ExtensionFunctionCall;
10
using JStructuredQName = net.sf.saxon.om.StructuredQName;
11
using JSequenceIterator = net.sf.saxon.om.SequenceIterator;
12
using JSequenceType = net.sf.saxon.value.SequenceType;
13

    
14
namespace Saxon.Api
15
{
16

    
17
    /// <summary>
18
    /// The class <c>StaticContext</c> provides information about the static context of an expression
19
    /// </summary>
20

    
21
    public class StaticContext {
22

    
23
        private JStaticContext env;
24

    
25
        internal StaticContext(JStaticContext jsc) {
26
            env = jsc;
27
        }
28

    
29

    
30
        /// <summary>
31
        /// The URI of the module where an expression appears, suitable for use in diagnostics
32
        /// </summary>
33
        /// 
34
        public Uri ModuleUri {
35
            get {
36
                return new Uri(env.getSystemId());
37
            }
38
        }
39

    
40
        /// <summary>
41
        /// The line number within a module where an expression appears, suitable for use in diagnostics
42
        /// </summary>
43
        /// 
44
        public int LineNumber {
45
            get {
46
                return env.getLineNumber();
47
            }
48
        }
49

    
50

    
51
        /// <summary>
52
        /// The static base URI of the expression. Often the same as the URI of the containing module,
53
        /// but not necessarily so, for example in a stylesheet that uses external XML entities or the
54
        /// xml:base attribute
55
        /// </summary>
56
        /// 
57
        public Uri BaseUri {
58
            get {
59
                return new Uri(env.getBaseURI());
60
            }
61
        }
62

    
63
        /// <summary>
64
        /// Resolve an in-scope namespace prefix to obtain the corresponding namespace URI. If the prefix
65
        /// is a zero-length string, the default namespace for elements and types is returned.
66
        /// </summary>
67
        /// <param name="Prefix">The namespace prefix</param>
68
        /// <returns>The corresponding namespace URI if there is one, or null otherwise</returns>
69
        /// 
70
        public String GetNamespaceForPrefix(string Prefix) {
71
            if (Prefix == "") {
72
                return env.getDefaultElementNamespace();
73
            }
74
            try {
75
                return env.getURIForPrefix(Prefix);
76
            } catch (JXPathException) {
77
                return null;
78
            }
79
        }
80
    }
81

    
82
    /// <summary>
83
    /// The class <c>DynamicContext</c> provides information about the dynamic context of an expression
84
    /// </summary>
85
    /// 
86
    public class DynamicContext {
87

    
88
        internal JXPathContext context;
89

    
90
        internal DynamicContext(JXPathContext context) {
91
            this.context = context;
92
        }
93

    
94
        /// <summary>
95
        /// The context item. May be null if no context item is defined
96
        /// </summary>
97
        /// 
98
        public XdmItem ContextItem {
99
            get {
100
                return (XdmItem)XdmItem.Wrap(context.getContextItem());
101
            }
102
        }
103

    
104
        /// <summary>
105
        /// The context position (equivalent to the XPath position() function).
106
        /// </summary>
107
        /// <remarks>Calling this method throws an exception if the context item is undefined.</remarks>
108
        /// 
109
        public int ContextPosition {
110
            get {
111
                return context.getContextPosition();
112
            }
113
        }
114

    
115
        /// <summary>
116
        /// The context size (equivalent to the XPath last() function).
117
        /// </summary>
118
        /// <remarks>Calling this method throws an exception if the context item is undefined.</remarks>
119
        /// 
120
        public int ContextSize {
121
            get {
122
                return context.getLast();
123
            }
124
        }
125
        
126
    }
127

    
128
    /// <summary>
129
    /// <para>Abstract superclass for user-written extension functions. An extension function may be implemented as a subclass
130
    /// of this class, with appropriate implementations of the defined methods.</para>
131
    /// <para>More precisely, a subclass of <c>ExtensionFunctionDefinition</c> identifies a family of extension functions
132
    /// with the same (namespace-qualified) name but potentially having different arity (number of arguments).</para>
133
    /// </summary>
134
    /// 
135

    
136
    public abstract class ExtensionFunctionDefinition
137
    {
138
        /// <summary>
139
        /// Read-only property returning the name of the extension function, as a QName.
140
        /// </summary>
141

    
142
        public abstract QName FunctionName {get;}
143

    
144
        /// <summary>
145
        /// Read-only property giving the minimum number of arguments in a call to this extension function.
146
        /// </summary>
147

    
148
        public abstract int MinimumNumberOfArguments {get;}
149

    
150
        /// <summary>
151
        /// Read-only property giving the maximum number of arguments in a call to this extension function.
152
        /// </summary>
153

    
154
        public abstract int MaximumNumberOfArguments {get;}
155

    
156
        /// <summary>
157
        /// Read-only property giving the required types of the arguments to this extension function. 
158
        /// If the number of items in the array is less than the maximum number of arguments, 
159
        /// then the last entry in the returned ArgumentTypes is assumed to apply to all the rest; 
160
        /// if the returned array is empty, then all arguments are assumed to be of type <c>item()*</c>
161
        /// </summary>
162

    
163
        public abstract XdmSequenceType[] ArgumentTypes {get;}
164

    
165
        /// <summary>
166
        /// Method returning the declared type of the return value from the function. The type of the return
167
        /// value may be known more precisely if the types of the arguments are known (for example, some functions
168
        /// return a value that is the same type as the first argument. The method is therefore called supplying the
169
        /// static types of the actual arguments present in the call.
170
        /// </summary>
171
        /// <param name="ArgumentTypes">
172
        /// The static types of the arguments present in the function call
173
        /// </param>
174
        /// <returns>
175
        /// An <c>XdmSequenceType</c> representing the declared return type of the extension function
176
        /// </returns>
177

    
178
        public abstract XdmSequenceType ResultType(XdmSequenceType[] ArgumentTypes);
179

    
180
        /// <summary>
181
        /// This property may be set to true in a subclass if it guarantees that the returned result of the function
182
        /// will always be of the declared return type: setting this to true by-passes the run-time checking of the type
183
        /// of the value, together with code that would otherwise perform atomization, numeric type promotion, and similar
184
        /// conversions. If the value is set to true and the value is not of the correct type, the effect is unpredictable
185
        /// and probably disastrous.
186
        /// </summary>
187

    
188
        public virtual Boolean TrustResultType {
189
            get{return false;}
190
        }
191

    
192
        /// <summary>
193
        /// This property must be set to true in a subclass if the evaluation of the function makes use of the context
194
        /// item, position, or size from the dynamic context. This inhibits certain Saxon optimizations.
195
        /// </summary>
196

    
197
        public virtual Boolean DependsOnFocus {
198
            get{return false;}
199
        }
200

    
201
        /// <summary>
202
        /// This property should be set to true in a subclass if the evaluation of the function has side-effects.
203
        /// Saxon never guarantees the result of calling functions with side-effects, but if this property is set,
204
        /// then certain aggressive optimizations will be avoided, making it more likely that the function behaves
205
        /// as expected.
206
        /// </summary>
207

    
208
        public virtual Boolean HasSideEffects {
209
            get{return false;}
210
        }
211

    
212
        /// <summary>
213
        /// Factory method to create an ExtensionFunctionCall object, representing a specific function call in the XSLT or XQuery
214
        /// source code. Saxon will call this method once it has identified that a specific call relates to this extension
215
        /// function.
216
        /// </summary>
217
        /// <returns>
218
        /// An instance of the appropriate implementation of <code>ExtensionFunctionCall</code>
219
        /// </returns>
220

    
221
        public abstract ExtensionFunctionCall MakeFunctionCall();
222
    }
223

    
224
    /// <summary>
225
    /// <para>An instance of this class will be created by the compiler for each function call to this extension function
226
    /// that is found in the source code. The implementation may therefore retain information about the static context of the
227
    /// call. Once compiled, however, the instance object must be immutable.</para>
228
    /// </summary>
229

    
230
    public abstract class ExtensionFunctionCall {
231

    
232
        /// <summary>
233
        /// Method called by the compiler (at compile time) to provide information about the static context of the
234
        /// function call. The implementation may retain this information for use at run-time, if the result of the
235
        /// function depends on information in the static context.
236
        /// </summary>
237
        /// <remarks>
238
        /// For efficiency, the implementation should only retain copies of the information that it actually needs. It
239
        /// is not a good idea to hold a reference to the static context itself, since that can result in a great deal of
240
        /// compile-time information being locked into memory during run-time execution.
241
        /// </remarks>
242
        /// <param name="context">Information about the static context in which the function is called</param>
243

    
244
        public virtual void SupplyStaticContext(StaticContext context)
245
        {
246
            // default: no action
247
        }
248

    
249
        /// <summary>
250
        /// A subclass must implement this method if it retains any local data at the instance level. On some occasions
251
        /// (for example, when XSLT or XQuery code is inlined), Saxon will make a copy of an <c>ExtensionFunction</c> object.
252
        /// It will then call this method on the old object, supplying the new object as the value of the argument, and the
253
        /// method must copy all local data items from the old object to the new.
254
        /// </summary>
255
        /// <param name="destination">The new extension function object. This will always be an instance of the same
256
        /// class as the existing object.</param>
257

    
258
        public virtual void CopyLocalData(ExtensionFunctionCall destination) { }
259

    
260
        /// <summary>
261
        /// Method called at run time to evaluate the function.
262
        /// </summary>
263
        /// <param name="arguments">The values of the arguments to the function, supplied as iterators over XPath
264
        /// sequence values.</param>
265
        /// <param name="context"></param>
266
        /// <returns></returns>
267

    
268
        public abstract IXdmEnumerator Call(IXdmEnumerator[] arguments, DynamicContext context);
269
    }
270

    
271
    internal class WrappedExtensionFunctionDefinition : JExtensionFunctionDefinition
272
    {
273
        ExtensionFunctionDefinition definition;
274

    
275
        public WrappedExtensionFunctionDefinition(ExtensionFunctionDefinition definition)
276
        {
277
            this.definition = definition;
278
        }
279

    
280
        public override JStructuredQName getFunctionQName()
281
        {
282
            return definition.FunctionName.ToStructuredQName();
283
        }
284

    
285
        public override int getMinimumNumberOfArguments()
286
        {
287
            return definition.MinimumNumberOfArguments;
288
        }
289

    
290
        public override int getMaximumNumberOfArguments()
291
        {
292
            return definition.MaximumNumberOfArguments;
293
        }
294

    
295
        public override JSequenceType[] getArgumentTypes()
296
        {
297
            XdmSequenceType[] dt = definition.ArgumentTypes;
298
            JSequenceType[] jt = new JSequenceType[dt.Length];
299
            for (int i = 0; i < dt.Length; i++)
300
            {
301
                jt[i] = dt[i].ToSequenceType();
302
            }
303
            return jt;
304
        }
305

    
306
        public override JSequenceType getResultType(JSequenceType[] argumentTypes)
307
        {
308
            XdmSequenceType[] dt = new XdmSequenceType[argumentTypes.Length];
309
            for (int i = 0; i < dt.Length; i++)
310
            {
311
                dt[i] = XdmSequenceType.FromSequenceType(argumentTypes[i]);
312
            }
313

    
314
            XdmSequenceType rt = definition.ResultType(dt);
315
            return rt.ToSequenceType();
316
        }
317

    
318
        public override Boolean trustResultType()
319
        {
320
            return definition.TrustResultType;
321
        }
322

    
323
        public override Boolean dependsOnFocus()
324
        {
325
            return definition.DependsOnFocus;
326
        }
327

    
328
        public override Boolean hasSideEffects()
329
        {
330
            return definition.HasSideEffects;
331
        }
332

    
333
        public override JExtensionFunctionCall makeCallExpression()
334
        {
335
            return new WrappedExtensionFunctionCall(definition.MakeFunctionCall());
336
        }
337

    
338
    }
339

    
340
    internal class WrappedExtensionFunctionCall : JExtensionFunctionCall {
341

    
342
        ExtensionFunctionCall functionCall;
343

    
344
        public WrappedExtensionFunctionCall(ExtensionFunctionCall call)
345
        {
346
            this.functionCall = call;
347
        }
348

    
349
        public override void copyLocalData(JExtensionFunctionCall destination)
350
        {
351
            functionCall.CopyLocalData(((WrappedExtensionFunctionCall)destination).functionCall);
352
        }
353

    
354
        public override JSequenceIterator call(JSequenceIterator[] arguments, JXPathContext context)
355
        {
356
            SequenceEnumerator[] na = new SequenceEnumerator[arguments.Length];
357
            for (int i = 0; i < na.Length; i++)
358
            {
359
                na[i] = new SequenceEnumerator(arguments[i]);
360
            }
361
            DynamicContext dc = new DynamicContext(context);
362
            IXdmEnumerator result = functionCall.Call(na, dc);
363
            return new DotNetSequenceIterator(result);
364
        }
365
    }
366
}
(4-4/10)