Project

Profile

Help

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

he / src / main / csharp / api / Saxon.Api / Extensibility.cs @ c7deb2a9

1
using System;
2

    
3
using JConfiguration = net.sf.saxon.Configuration;
4
using JStaticContext = net.sf.saxon.expr.StaticContext;
5
using JXPathException = net.sf.saxon.trans.XPathException;
6
using JXPathContext = net.sf.saxon.expr.XPathContext;
7
using JExtensionFunctionDefinition = net.sf.saxon.lib.ExtensionFunctionDefinition;
8
using JExtensionFunction = net.sf.saxon.s9api.ExtensionFunction;
9
using JExtensionFunctionCall = net.sf.saxon.lib.ExtensionFunctionCall;
10
using JStructuredQName = net.sf.saxon.om.StructuredQName;
11
using JXdmSequenceIterator = net.sf.saxon.s9api.XdmSequenceIterator;
12
using JSequenceType = net.sf.saxon.value.SequenceType;
13
using JSequence = net.sf.saxon.om.Sequence;
14
using JExpression = net.sf.saxon.expr.Expression;
15
using JXdmSequenceType = net.sf.saxon.s9api.SequenceType;
16
using JItem = net.sf.saxon.om.Item;
17
using JResource = net.sf.saxon.lib.Resource;
18
using JResourceCollection = net.sf.saxon.lib.ResourceCollection;
19
using JResourceFactory = net.sf.saxon.lib.ResourceFactory;
20
using JStandardCollectionFinder = net.sf.saxon.resource.StandardCollectionFinder;
21
using JCollectionFinder = net.sf.saxon.lib.CollectionFinder;
22
using System.Collections.Generic;
23
using net.sf.saxon.om;
24
using java.util;
25
using net.sf.saxon;
26
using net.sf.saxon.resource;
27

    
28
namespace Saxon.Api
29
{
30

    
31
    /// <summary>
32
    /// The class <c>StaticContext</c> provides information about the static context of an expression
33
    /// </summary>
34

    
35
    public class StaticContext {
36

    
37
        private JStaticContext env;
38

    
39
        internal StaticContext(JStaticContext jsc) {
40
            env = jsc;
41
        }
42

    
43

    
44
        /// <summary>
45
        /// The URI of the module where an expression appears, suitable for use in diagnostics
46
        /// </summary>
47

    
48
        public Uri ModuleUri {
49
            get {
50
                return new Uri(env.getSystemId());
51
            }
52
        }
53

    
54

    
55
        /// <summary>
56
        /// The static base URI of the expression. Often the same as the URI of the containing module,
57
        /// but not necessarily so, for example in a stylesheet that uses external XML entities or the
58
        /// <c>xml:base</c> attribute
59
        /// </summary>
60

    
61
        public Uri BaseUri {
62
            get {
63
                return new Uri(env.getStaticBaseURI());
64
            }
65
        }
66

    
67
        /// <summary>
68
        /// Resolve an in-scope namespace prefix to obtain the corresponding namespace URI. If the prefix
69
        /// is a zero-length string, the default namespace for elements and types is returned.
70
        /// </summary>
71
        /// <param name="Prefix">The namespace prefix</param>
72
        /// <returns>The corresponding namespace URI if there is one, or null otherwise</returns>
73

    
74
        public String GetNamespaceForPrefix(string Prefix) {
75
            if (Prefix == "") {
76
                return env.getDefaultElementNamespace();
77
            }
78
            try {
79
                return env.getNamespaceResolver().getURIForPrefix(Prefix, false);
80
            } catch (JXPathException) {
81
                return null;
82
            }
83
        }
84

    
85
        /// <summary>
86
        /// The <c>Processor</c> that was used to create the query or stylesheet from which this extension
87
        /// function was invoked.
88
        /// </summary>
89
        /// <remarks>
90
        /// <para>This property is useful if the extension function wishes to create new nodes (the <code>Processor</code>
91
        /// can be used to obtain a <code>DocumentBuilder</code>), or to execute XPath expressions or queries.</para>
92
        /// <para>There may be circumstances in which the <c>Processor</c> is not available, in which case this method
93
        /// may return null, or may return a different <c>Processor</c>. This will happen only if low-level interfaces
94
        /// have been used to cause a <c>Configuration</c> to be shared between several <c>Processor</c> instances,
95
        /// or between a <c>Processor</c> and other applications.</para>
96
        /// </remarks>
97

    
98
        public Processor Processor
99
        {
100
            get
101
            {
102
                JConfiguration config = env.getConfiguration();
103
                Object p = config.getProcessor();
104
                if (p is Processor)
105
                {
106
                    return (Processor)p;
107
                }
108
                else
109
                {
110
                    return null;
111
                }
112

    
113
            }
114
        }
115

    
116
        /// <summary>
117
        /// The underlying object in the Saxon implementation, an instance of class
118
		/// <code>net.sf.saxon.expr.StaticContext</code>
119
        /// </summary>
120
        /// <remarks>
121
        /// <para>This property provides access to internal methods in the Saxon engine that are
122
        /// not specifically exposed in the .NET API. In general these methods should be
123
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
124
        /// <para>The internal methods follow
125
        /// Java naming conventions rather than .NET conventions.</para>
126
        /// <para>Information about the returned object (and the objects it provides access to)
127
		/// is included in the Saxon JavaDoc documentation, see <see cref="net.sf.saxon.expr.StaticContext"/>.
128
        /// </para>
129
        /// </remarks>
130

    
131
        public JStaticContext Implementation
132
        {
133
            get { return env; }
134
        }
135
    }
136

    
137
    /// <summary>
138
    /// The class <c>DynamicContext</c> provides information about the dynamic context of an expression
139
    /// </summary>
140

    
141
    public class DynamicContext {
142

    
143
        internal JXPathContext context;
144

    
145
        internal DynamicContext(JXPathContext context) {
146
            this.context = context;
147
        }
148

    
149
        /// <summary>
150
        /// The context item. May be null if no context item is defined
151
        /// </summary>
152

    
153
        public XdmItem ContextItem {
154
            get {
155
                return context.getContextItem() == null ? null : (XdmItem)XdmItem.Wrap(context.getContextItem());
156
            }
157
        }
158

    
159
        /// <summary>
160
        /// The context position (equivalent to the XPath <c>position()</c> function).
161
        /// </summary>
162
        /// <remarks>Calling this method throws an exception if the context item is undefined.</remarks>
163

    
164
        public int ContextPosition {
165
            get {
166
                return context.getCurrentIterator().position();
167
            }
168
        }
169

    
170
        /// <summary>
171
        /// The context size (equivalent to the XPath <c>last()</c> function).
172
        /// </summary>
173
        /// <remarks>Calling this method throws an exception if the context item is undefined.</remarks>
174

    
175
        public int ContextSize {
176
            get {
177
                return context.getLast();
178
            }
179
        }
180

    
181
        /// <summary>
182
        /// The underlying object in the Saxon implementation, an instance of class
183
		/// <code>net.sf.saxon.expr.XPathContext</code>
184
        /// </summary>
185
        /// <remarks>
186
        /// <para>This property provides access to internal methods in the Saxon engine that are
187
        /// not specifically exposed in the .NET API. In general these methods should be
188
        /// considered to be less stable than the classes in the Saxon.Api namespace.</para> 
189
        /// <para>The internal methods follow
190
        /// Java naming conventions rather than .NET conventions.</para>
191
        /// <para>Information about the returned object (and the objects it provides access to)
192
		/// is included in the Saxon JavaDoc documentation, see <see cref="net.sf.saxon.expr.XPathContext"/>
193
        /// </para>
194
        /// </remarks>
195

    
196
        public JXPathContext Implementation
197
        {
198
            get { return context; }
199
        }
200

    
201
    }
202

    
203
    /// <summary>
204
    /// <para>Abstract superclass for user-written extension functions. An extension function may be implemented as a subclass
205
    /// of this class, with appropriate implementations of the defined methods.</para>
206
    /// <para>More precisely, a subclass of <c>ExtensionFunctionDefinition</c> identifies a family of extension functions
207
    /// with the same (namespace-qualified) name but potentially having different arity (number of arguments).</para>
208
    /// </summary>
209
    /// <remarks>
210
    /// <para>A user-defined extension function is typically implemented using a pair of classes: a class that extends 
211
    /// <code>ExtensionFunctionDefinition</code>, whose purpose is to define the properties of the extension function
212
    /// (in particular, its signature -- the types of its arguments and result); and a class that extends
213
    /// <code>ExtensionFunctionCall</code>, whose purpose is to perform the actual evaluation.</para> 
214
    /// <para>The <code>ExtensionFunctionDefinition</code> is immutable and will normally have a singleton instance
215
    /// for each subclass; this singleton instance is registered with the <code>Processor</code> to associate the
216
    /// name of the extension function with its definition.</para>
217
    /// <para>The <code>ExtensionFunctionCall</code> has one instance for each call on the extension function appearing
218
    /// in the source code of a stylesheet or query; this instance is created when Saxon calls the method <code>MakeFunctionCall</code>
219
    /// provided by the <code>ExtensionFunctionDefinition</code> object. The instance of <code>ExtensionFunctionCall</code>
220
    /// holds information about the static context of the function call, and its <code>Call</code> method is called
221
    /// (by Saxon) to evaluate the extension function at run-time.</para>
222
    /// </remarks>
223

    
224
    public abstract class ExtensionFunctionDefinition
225
    {
226
        /// <summary>
227
		/// Read-only property returning the name of the extension function, as a <c>QName</c>.
228
        /// </summary>
229
        /// <remarks>
230
        /// A getter for this property must be implemented in every subclass.
231
        /// </remarks>
232

    
233
        public abstract QName FunctionName { get; }
234

    
235
        /// <summary>
236
        /// Read-only property giving the minimum number of arguments in a call to this extension function.
237
        /// </summary>
238
        /// <remarks>
239
        /// A getter for this property must be implemented in every subclass.
240
        /// </remarks>
241

    
242
        public abstract int MinimumNumberOfArguments { get; }
243

    
244
        /// <summary>
245
        /// Read-only property giving the maximum number of arguments in a call to this extension function.
246
        /// </summary>
247
        /// <remarks>
248
        /// A getter for this property must be implemented in every subclass.
249
        /// </remarks>
250

    
251
        public abstract int MaximumNumberOfArguments { get; }
252

    
253
        /// <summary>
254
        /// Read-only property giving the required types of the arguments to this extension function. 
255
        /// If the number of items in the array is less than the maximum number of arguments, 
256
		/// then the last entry in the returned <c>ArgumentTypes</c> is assumed to apply to all the rest; 
257
        /// if the returned array is empty, then all arguments are assumed to be of type <c>item()*</c>
258
        /// </summary>
259
        /// <remarks>
260
        /// A getter for this property must be implemented in every subclass.
261
		/// </remarks>
262
		/// <returns>
263
		/// An array of <c>XdmSequenceType</c> objects representing the required types of the arguments 
264
		/// to the extension function.
265
		/// </returns>
266

    
267
        public abstract XdmSequenceType[] ArgumentTypes { get; }
268

    
269
        /// <summary>
270
        /// Method returning the declared type of the return value from the function. The type of the return
271
        /// value may be known more precisely if the types of the arguments are known (for example, some functions
272
		/// return a value that is the same type as the first argument). The method is therefore called supplying the
273
        /// static types of the actual arguments present in the call.
274
        /// </summary>
275
        /// <remarks>
276
        /// This method must be implemented in every subclass.
277
        /// </remarks>
278
        /// <param name="ArgumentTypes">
279
        /// The static types of the arguments present in the function call
280
        /// </param>
281
        /// <returns>
282
        /// An <c>XdmSequenceType</c> representing the declared return type of the extension function
283
        /// </returns>
284

    
285
        public abstract XdmSequenceType ResultType(XdmSequenceType[] ArgumentTypes);
286

    
287
        /// <summary>
288
        /// This property may return true for a subclass if it guarantees that the returned result of the function
289
        /// will always be of the declared return type: setting this to true by-passes the run-time checking of the type
290
        /// of the value, together with code that would otherwise perform atomization, numeric type promotion, and similar
291
        /// conversions. If the value is set to true and the value is not of the correct type, the effect is unpredictable
292
        /// and probably disastrous.
293
        /// </summary>
294
        /// <remarks>
295
        /// The default value of this property is <c>false</c>. A getter for this property may be implemented in a subclass
296
        /// to return a different value.
297
        /// </remarks>
298

    
299
        public virtual Boolean TrustResultType {
300
            get { return false; }
301
        }
302

    
303
        /// <summary>
304
        /// This property must return true for a subclass if the evaluation of the function makes use of the context
305
        /// item, position, or size from the dynamic context. It should also return true (despite the property name)
306
        /// if the function makes use of parts of the static context that vary from one part of the query or stylesheet
307
        /// to another. Setting the property to true inhibits certain Saxon optimizations, such as extracting the call
308
        /// from a loop, or moving it into a global variable.
309
        /// </summary>
310
        /// <remarks>
311
        /// The default value of this property is <c>false</c>. A getter for this property may be implemented in a subclass
312
        /// to return a different value.
313
        /// </remarks>
314

    
315
        public virtual Boolean DependsOnFocus {
316
            get { return false; }
317
        }
318

    
319
        /// <summary>
320
        /// This property should return true for a subclass if the evaluation of the function has side-effects.
321
        /// Saxon never guarantees the result of calling functions with side-effects, but if this property is set,
322
        /// then certain aggressive optimizations will be avoided, making it more likely that the function behaves
323
        /// as expected.
324
        /// </summary>
325
        /// <remarks>
326
        /// The default value of this property is <c>false</c>. A getter for this property may be implemented in a subclass
327
        /// to return a different value.
328
        /// </remarks>
329

    
330
        public virtual Boolean HasSideEffects {
331
            get { return false; }
332
        }
333

    
334
        /// <summary>
335
        /// Factory method to create an <c>ExtensionFunctionCall</c> object, representing a specific function call in the XSLT or XQuery
336
        /// source code. Saxon will call this method once it has identified that a specific call relates to this extension
337
        /// function.
338
        /// </summary>
339
        /// <remarks>
340
        /// This method must be implemented in every subclass. The implementation should normally instantiate the relevant subclass
341
        /// of <code>ExtensionFunctionCall</code>, and return the new instance.
342
        /// </remarks>
343
        /// <returns>
344
        /// An instance of the appropriate implementation of <code>ExtensionFunctionCall</code>
345
        /// </returns>
346

    
347
        public abstract ExtensionFunctionCall MakeFunctionCall();
348
    }
349

    
350
    /// <summary>
351
    /// An instance of this class will be created by the compiler for each function call to this extension function
352
    /// that is found in the source code. The class is always instantiated by calling the method <c>MakeFunctionCall()</c>
353
    /// of the corresponding <c>ExtensionFunctionDefinition</c>. 
354
    /// The implementation may therefore retain information about the static context of the
355
    /// call. Once compiled, however, the instance object must be immutable.
356
    /// </summary>
357

    
358
    public abstract class ExtensionFunctionCall
359
    {
360

    
361
        /// <summary>
362
        /// Method called by the compiler (at compile time) to provide information about the static context of the
363
        /// function call. The implementation may retain this information for use at run-time, if the result of the
364
        /// function depends on information in the static context.
365
        /// </summary>
366
        /// <remarks>
367
        /// For efficiency, the implementation should only retain copies of the information that it actually needs. It
368
        /// is not a good idea to hold a reference to the static context itself, since that can result in a great deal of
369
        /// compile-time information being locked into memory during run-time execution.
370
        /// </remarks>
371
        /// <param name="context">Information about the static context in which the function is called</param>
372

    
373
        public virtual void SupplyStaticContext(StaticContext context)
374
        {
375
            // default: no action
376
        }
377

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

    
387
        public virtual void CopyLocalData(ExtensionFunctionCall destination) { }
388

    
389
        /// <summary>
390
        /// Method called at run time to evaluate the function.
391
        /// </summary>
392
        /// <param name="arguments">The values of the arguments to the function, supplied as iterators over XPath
393
        /// sequence values.</param>
394
        /// <param name="context">The dynamic context for evaluation of the function. This provides access
395
        /// to the context item, position, and size, and if required to internal data maintained by the Saxon
396
        /// engine.</param>
397
        /// <returns>An iterator over a sequence, representing the result of the extension function.
398
        /// Note that Saxon does not guarantee to read this sequence to completion, so calls on the iterator
399
        /// must have no side-effects. In rare circumstances (for example, when <code>last()</code> is
400
        /// used) Saxon may clone the returned iterator by calling its <c>GetAnother()</c> method, 
401
        /// allowing the function results to be read more than once.</returns>
402

    
403
        public abstract IEnumerator<XdmItem> Call(IEnumerator<XdmItem>[] arguments, DynamicContext context);
404
    }
405

    
406

    
407

    
408
    /// <summary>
409
    ///  An instance of CollectionFinder can be registered with the Saxon configuration; it is called in response
410
    ///  to calls on the fn:collection() and fn:uri-collection() functions.
411
    ///  When these functions are called, the <c>FindCollection(XPathContext, String)</c> method is
412
    ///  called to get a <c>ResourceCollection</c>
413
    ///  object representing the collection of resources identified by the supplied collection URI.
414
    /// </summary>
415
    public interface ICollectionFinder
416
    {
417

    
418

    
419
        /// <summary>
420
        /// Locate the collection of resources corresponding to a collection URI.
421
        /// </summary>
422
        /// <param name="context">The XPath dynamic evaluation context</param>
423
        /// <param name="collectionURI">The collection URI: an absolute URI, formed by resolving the argument
424
        /// supplied to the fn:collection or fn:uri-collection against the staticbase URI</param>
425
        /// <returns>a ResourceCollection object representing the resources in the collection identified
426
        ///  by this collection URI. Result should not be null.</returns>
427
		/**public**/ IResourceCollection FindCollection(DynamicContext context, String collectionURI);
428

    
429

    
430
    }
431

    
432

    
433
    /// <summary>
434
    /// This interface defines a ResourceCollection. This class
435
    /// is used to map the URI of collection into a sequence of Resource objects.
436
    /// It is used to support the fn:collection() and fn:uri-collection() functions.
437
    /// </summary>
438
    public interface IResourceCollection
439
    {
440
        /// <summary>
441
        /// Get the URI of the collection
442
        /// </summary>
443
        /// <returns> The URI as passed to the fn:collection() or fn:uri-collection()
444
        /// function, resolved if it is relative against the static base URI.
445
        /// If the collection() or uri-collection() function
446
        /// was called with no arguments(to get the "default collection") this
447
        /// will be the URI of the default collection registered with the Configuration.</returns>
448
		/**public**/ String CollectionURI();
449

    
450
        /// <summary>
451
        /// Get the URIs of the resources in the collection. This supports the fn:uri-collection()
452
        /// function.It is not required that all collections expose a list of URIs in this way, or
453
        /// that the URIs bear any particular relationship to the resources returned by the
454
        /// getResources() method for the same collection URI.The URIs that are returned should be
455
        /// suitable for passing to the registered URIResolver (in the case of XML resources),
456
        /// or the { @link UnparsedTextURIResolver }
457
        /// (in the case of unparsed text and JSON resources), etc.
458
        /// </summary>
459
        /// <param name="context">context the XPath evaluation context</param>
460
        /// <returns>an iterator over the URIs of the resources in the collection. The URIs are represented
461
        /// as Strings.They should preferably be absolute URIs.</returns>
462
		/**public**/ List<String> GetResourceURIs(DynamicContext context);
463

    
464
        /// <summary>
465
        /// Get the resources in the collection. This supports the fn:collection() function. It is not
466
        /// required that all collections expose a set of resources in this way, or that the resources
467
        /// returned bear any particular relationship to the URIs returned by the getResourceURIs() method
468
        /// for the same collection URI.
469
        /// </summary>
470
        /// <param name="context">the XPath evaluation context</param>
471
        /// <returns>a List over the resources in the collection. This returns objects of class
472
        /// <c>Riesource</c>.</returns>
473
		/**public**/ List<IResource> GetResources(DynamicContext context);
474

    
475

    
476
    }
477

    
478

    
479
    /// <summary>
480
    /// This class represents a resource collection containing all, or selected, files within a filestore directory
481
    /// </summary>
482
    public class DirectoryCollection : ResourceCollection
483
    {
484
       
485
        /// <summary>
486
        /// Create a directory collection
487
        /// </summary>
488
        /// <param name="proc">Processor object for configuration properties</param>
489
        /// <param name="collectionURI">the collection URI</param>
490
        /// <param name="directoryName">the directory containing the files</param>
491
        /// <param name="parameters">query parameter supplied as part of the URI</param>
492
        public DirectoryCollection(Processor proc, String collectionURI, String directoryName, URIQueryParameters parameters)
493
        {
494
            resourceCollection = new net.sf.saxon.resource.DirectoryCollection(proc.Implementation, collectionURI, new  java.io.File(directoryName), parameters.Implementation());
495
            
496
        }
497

    
498
     
499
    }
500

    
501
    /// <summary>
502
    /// A JarCollection represents a collection of resources held in a JAR or ZIP archive, accessess typically
503
    /// using a URI using the "jar" URI scheme, or simply a "file" URI where the target file is a JAR or ZIP file.
504
    /// </summary>
505
    public class JarCollection : ResourceCollection
506
    {
507

    
508
		/// <summary>
509
		/// Create a JarCollection
510
		/// </summary>
511
		/// <param name="context">The XPath dynamic context</param>
512
		/// <param name="collectionURI">the collection URI used to identify this collection 
513
		/// (typically but not necessarily the location of the JAR file)</param>
514
		/// <param name="parameters">URI query parameters appearing on the collection URI</param>
515
        public JarCollection(DynamicContext context, String collectionURI, URIQueryParameters parameters)
516
        {
517
            resourceCollection = new net.sf.saxon.resource.JarCollection(context.context, collectionURI, parameters.Implementation());
518

    
519
        }
520

    
521
    }
522

    
523
	/// <summary>
524
	/// CatalogCollection
525
	/// </summary>
526
    public class CatalogCollection : ResourceCollection
527
    {
528

    
529
        public CatalogCollection(Processor proc, String collectionURI)
530
        {
531
            resourceCollection = new net.sf.saxon.resource.CatalogCollection(proc.Implementation, collectionURI);
532

    
533
        }
534

    
535

    
536
    }
537

    
538

    
539
    /// <summary>
540
    /// Default implementation of the CollectionFinder interface. 
541
    /// </summary>
542
    public class StandardCollectionFinder : ICollectionFinder
543
    {
544

    
545
        JStandardCollectionFinder collectionFinder;
546

    
547
        public StandardCollectionFinder() {
548
            collectionFinder = new JStandardCollectionFinder();
549
        }
550

    
551
        internal StandardCollectionFinder(JCollectionFinder cf)
552
        {
553
            collectionFinder = (JStandardCollectionFinder)cf;
554
        }
555

    
556
        /// <summary>
557
        /// Locate the collection of  resources corresponding to a collection URI
558
        /// </summary>
559
        /// <param name="context">The XPath dynamic evaluation context</param>
560
        /// <param name="collectionURI">The collection URI: an absolute URI, formed by resolving the argument
561
        /// supplied to the fn:collection or fn:uri-collection against the static base URI</param>
562
        /// <returns>a ResourceCollection object representing resources in the collection identified by this collection URI</returns>
563
        public IResourceCollection FindCollection(DynamicContext context, string collectionURI)
564
        {
565
            return new ResourceCollection(collectionFinder.findCollection(context.context, collectionURI));
566
        }
567

    
568
        /// <summary>
569
        /// The underlying java CollectionFinder object
570
        /// </summary>
571
        public JCollectionFinder Implementation {
572
            get {
573
                return collectionFinder;
574
            }
575
        }
576

    
577
        /// <summary>
578
        /// Register a specific URI and bind it to a specific ResourceCollection
579
        /// </summary>
580
        /// <param name="collectionURI">collectionURI the collection URI to be registered. Must not be null.</param>
581
        /// <param name="collection">collection the ResourceCollection to be associated with this URI. Must not be null.</param>
582
        public void RegisterCollection(String collectionURI, IResourceCollection collection) {
583

    
584
            collectionFinder.registerCollection(collectionURI, new ResourceCollectionWrapper(collection));
585

    
586
        }
587

    
588
    }
589

    
590

    
591
    internal class ResourceCollectionWrapper : JResourceCollection
592
    {
593

    
594
        IResourceCollection resourceCollection;
595

    
596
        public ResourceCollectionWrapper(IResourceCollection rc) {
597
            resourceCollection = rc;
598
        }
599

    
600
        public string getCollectionURI()
601
        {
602
            return resourceCollection.CollectionURI();
603
        }
604

    
605
        public Iterator getResources(JXPathContext xpc)
606
        {
607
            java.util.List iter = new java.util.ArrayList();
608
            List<IResource> list = resourceCollection.GetResources(new DynamicContext(xpc));
609
            foreach (IResource src in list)
610
            {
611
                iter.add(new ResourceWrapper(src));
612
            }
613

    
614
            return iter.iterator();
615

    
616
        }
617

    
618
        public Iterator getResourceURIs(JXPathContext xpc)
619
        {
620
            java.util.List iter = new java.util.ArrayList();
621
            List<string> list = resourceCollection.GetResourceURIs(new DynamicContext(xpc));
622
            foreach (string src in list)
623
            {
624
                iter.add(src);
625
            }
626

    
627
            return iter.iterator();
628
        }
629

    
630
        public bool isStable(JXPathContext xpc)
631
        {
632
           return false;
633
        }
634

    
635
        public bool stripWhitespace(net.sf.saxon.om.SpaceStrippingRule ssr)
636
        {
637
            return false;
638
        }
639
    }
640

    
641

    
642
    /// <summary>
643
    /// This interface defines a Resource. The Resource objects belong to a collection.
644
    /// It is used to support the fn:collection() and fn:uri-collection() functions.
645
    /// <para>It is recommended (but is not universally the case) that fetching (and where necessary parsing)
646
    /// the content of a Resource should be delayed until the <c>getItem</c> method is called. This means
647
    /// that errors in fetching the resource or parsing its contents may go undetected until the resource
648
    /// is materialized in this way.</para>
649
    /// </summary>
650
    public interface IResource
651
    {
652
        /// <summary>
653
        /// Get a URI that identifies this resource
654
        /// </summary>
655
        /// <returns>a URI identifying the resource</returns>
656
		/**public**/ String GetResourceURI();
657

    
658
        /// <summary>
659
        /// Get an XDM Item holding the contents of this resource.
660
        /// </summary>
661
        /// <param name="context">the XPath evaluation context</param>
662
        /// <returns>an item holding the contents of the resource. The type of item will
663
        /// reflect the type of the resource: a document node for XML resources, a string
664
        /// for text resources, a map or array for JSON resources, a base64Binary value
665
        /// for binary resource.May also return null if the resource cannot be materialized
666
        /// and this is not to be treated as an error.</returns>
667
		/**public**/ XdmItem GetXdmItem(DynamicContext context);
668

    
669
        /// <summary> 
670
        /// Get the media type (MIME type) of the resource if known
671
        /// </summary>
672
        /// <returns>the media type if known; otherwise null</returns>
673
		/**public**/ String GetContentType();
674
    }
675

    
676
	/// <summary>
677
	/// ResourceCollection
678
	/// </summary>
679
    public class ResourceCollection : IResourceCollection
680
    {
681
		protected JResourceCollection resourceCollection;
682

    
683
        internal ResourceCollection()
684
        {
685
        }
686

    
687

    
688
		internal ResourceCollection(JResourceCollection rc) {
689
            resourceCollection = rc;
690
        }
691

    
692
        public string CollectionURI()
693
        {
694
            return resourceCollection.getCollectionURI();
695
        }
696

    
697
        public List<string> GetResourceURIs(DynamicContext context)
698
        {
699
            List<string> list = new List<string>();
700
            var jIter = resourceCollection.getResourceURIs(context.context);
701
            while(jIter.hasNext()) {
702

    
703
                string uri = (string)jIter.next();
704
                list.Add(uri);
705
            }
706
            return list;
707
        }
708

    
709
        public List<IResource> GetResources(DynamicContext context)
710
        {
711
            List<IResource> list = new List<IResource>();
712
            var jIter = resourceCollection.getResources(context.context);
713
            while (jIter.hasNext())
714
            {
715

    
716
                JResource jresource = (JResource)jIter.next();
717
                list.Add(new Resource(jresource));
718
            }
719
            return list;
720
        }
721

    
722
        public bool IsStable(DynamicContext context)
723
        {
724
            return resourceCollection.isStable(context.context);
725
        }
726

    
727

    
728
    }
729

    
730
    /// <summary>
731
    /// A ResourceFactory is used for constructing a particular type of resource
732
    /// </summary>
733
    public interface IResourceFactory {
734

    
735

    
736
        /// <summary>
737
        /// Create a Resource with given content
738
        /// </summary>
739
        /// <param name="proc">the Saxon Processor</param>
740
        /// <returns>the resource</returns>
741
		/**public**/ IResource MakeResource(Processor proc);
742

    
743
    }
744

    
745
    internal class ResourceFactoryWrapper : JResourceFactory
746
    {
747
        private IResourceFactory resourceFactory;
748
        private Processor proc;
749

    
750
        internal ResourceFactoryWrapper(IResourceFactory factory, Processor proc) {
751
            this.resourceFactory = factory;
752
        }
753

    
754
        public JResource makeResource(JConfiguration c, AbstractResourceCollection.InputDetails details)
755
        {
756
            return new ResourceWrapper(resourceFactory.MakeResource(proc));
757
        }
758
    }
759

    
760
    /// <summary>
761
    /// Resource Wrapper class for a Java Resource object
762
    /// </summary>
763
    public class Resource : IResource
764
    {
765
        internal JResource resource = null;
766

    
767
        public Resource() 
768
		{ 
769
			resource = null; 
770
		}
771

    
772
        public Resource(JResource rc) 
773
		{
774
            resource = rc;
775
        }
776

    
777
        public string GetContentType()
778
        {
779
            return resource.getContentType();
780
        }
781

    
782
        public string GetResourceURI()
783
        {
784
            return resource.getResourceURI();
785
        }
786

    
787
        public XdmItem GetXdmItem(DynamicContext context)
788
        {
789
            return XdmItem.FromGroundedValue(resource.getItem(context.context).materialize()).ItemAt(0);
790
        }
791
    }
792

    
793
	/// <summary>
794
	/// BinaryResource
795
	/// </summary>
796
    public class BinaryResource : Resource {
797

    
798

    
799
        public BinaryResource(String href, String contentType, byte[] content) {
800
            resource = new net.sf.saxon.resource.BinaryResource(href, contentType, content); 
801
        }
802

    
803

    
804
    }
805

    
806

    
807
    internal class ResourceWrapper : JResource
808
    {
809

    
810
        IResource resource;
811

    
812
        public ResourceWrapper(IResource resource) {
813
            this.resource = resource;
814
        }
815
        public string getContentType()
816
        {
817
            return resource.GetContentType();
818
        }
819

    
820
        public JItem getItem(JXPathContext xpc)
821
        {
822
            return (JItem) resource.GetXdmItem(new DynamicContext(xpc)).Unwrap();
823
        }
824

    
825
        public string getResourceURI()
826
        {
827
            return resource.GetResourceURI();
828
        }
829
    }
830
    
831

    
832
    internal class CollectionFinderWrapper : JCollectionFinder
833
    {
834

    
835
        ICollectionFinder collectionFinder;
836

    
837
        public CollectionFinderWrapper(ICollectionFinder cf) {
838
            collectionFinder = cf;
839
        }
840

    
841
        public JResourceCollection findCollection(JXPathContext xpc, string str)
842
        {
843
            IResourceCollection rcollection = collectionFinder.FindCollection(new DynamicContext(xpc), str);
844

    
845
            return new ResourceCollectionWrapper(rcollection);
846
        }
847
    }
848

    
849
    /// <summary>
850
    /// This is an interface for simple external/extension functions.
851
    /// Users can implement this interface and register the implementation with the <see cref="Saxon.Api.Processor"/>;
852
    /// the function will then be available for calling from all queries, stylesheets, and XPath expressions compiled
853
    /// under this Processor.
854
    /// </summary>
855
    /// <remarks>
856
    /// <para>Extension functions implemented using this interface are expected to be free of side-effects,
857
    /// and to have no dependencies on the static or dynamic context. A richer interface for extension
858
    /// functions is provided via the <see cref="Saxon.Api.ExtensionFunctionDefinition"/> class.</para>
859
    /// </remarks>
860

    
861
    public interface ExtensionFunction
862
    {
863

    
864
        /// <summary>
865
        /// Return the name of the external function
866
        /// </summary>
867
        /// <returns>the name of the function, as a <c>QName</c></returns>
868

    
869
		/**public**/ 
870
		QName GetName();
871

    
872

    
873
        /// <summary>
874
        /// Declare the result type of the external function
875
        /// </summary>
876
        /// <returns>the result type of the external function</returns>
877

    
878
		/**public**/ 
879
		XdmSequenceType GetResultType();
880

    
881
        /// <summary>
882
        /// Declare the type of the arguments
883
        /// </summary>
884
        /// <returns>an array of <c>XdmSequenceType</c> objects, one for each argument to the function,
885
        /// representing the expected types of the arguments</returns>
886

    
887
		/**public**/ 
888
		XdmSequenceType[] GetArgumentTypes();
889

    
890

    
891
        /// <summary>
892
        /// Method called at run time to evaluate the function.
893
        /// </summary>
894
        /// <param name="arguments">The values of the arguments supplied in the XPath function call.</param>
895
        /// <returns>An <c>XdmValue</c>, representing the result of the extension function. 
896
        /// (Note: in many cases it will be convenient to return an <c>XdmAtomicValue</c> or <c>XdmNode</c>, 
897
        /// both of which are instances of <c>XdmValue</c>).</returns>
898

    
899
		/**public**/ 
900
		XdmValue Call(XdmValue[] arguments);
901
    }
902

    
903

    
904

    
905
    internal class WrappedExtensionFunction : JExtensionFunction
906
    {
907
        ExtensionFunction definition;
908

    
909
        public WrappedExtensionFunction(ExtensionFunction definition)
910
        {
911
            this.definition = definition;
912
        }
913

    
914
        public net.sf.saxon.s9api.XdmValue call(net.sf.saxon.s9api.XdmValue[] xvarr)
915
        {
916
            XdmValue[] values = new XdmValue[xvarr.Length];
917
            int len = xvarr.Length;
918
            for (int i = 0; i < len; i++) {
919
                values[i] = XdmValue.Wrap(xvarr[i].getUnderlyingValue());
920
            }
921
            try {
922
                XdmValue result = definition.Call(values);
923
                return XdmValue.FromGroundedValueToJXdmValue(result.value);
924
            }
925
            catch (Exception ex) {
926
                throw new DynamicError(ex.Message);
927
            }
928
            
929
            }
930

    
931
        public JXdmSequenceType[] getArgumentTypes()
932
        {
933
            XdmSequenceType [] types = definition.GetArgumentTypes();
934
            JXdmSequenceType[] results = new JXdmSequenceType[types.Length];
935
            for (int i = 0; i < types.Length; i++) {
936
                results[i] = types[i].ToJXdmSequenceType();
937
            }
938
            return results;
939
        }
940

    
941
        public net.sf.saxon.s9api.QName getName()
942
        {
943
            return definition.GetName().UnderlyingQName();
944
        }
945

    
946
        public JXdmSequenceType getResultType()
947
        {
948
            JXdmSequenceType declaredResult = definition.GetResultType().ToJXdmSequenceType();
949
            return declaredResult;
950
        }
951
    }
952

    
953
        internal class WrappedExtensionFunctionDefinition : JExtensionFunctionDefinition
954
    {
955
        ExtensionFunctionDefinition definition;
956

    
957
        public WrappedExtensionFunctionDefinition(ExtensionFunctionDefinition definition)
958
        {
959
            this.definition = definition;
960
        }
961

    
962
        public override JStructuredQName getFunctionQName()
963
        {
964
            return definition.FunctionName.ToStructuredQName();
965
        }
966

    
967
        public override int getMinimumNumberOfArguments()
968
        {
969
            return definition.MinimumNumberOfArguments;
970
        }
971

    
972
        public override int getMaximumNumberOfArguments()
973
        {
974
            return definition.MaximumNumberOfArguments;
975
        }
976

    
977
        public override JSequenceType[] getArgumentTypes()
978
        {
979
            XdmSequenceType[] dt = definition.ArgumentTypes;
980
            JSequenceType[] jt = new JSequenceType[dt.Length];
981
            for (int i = 0; i < dt.Length; i++)
982
            {
983
                jt[i] = dt[i].ToSequenceType();
984
            }
985
            return jt;
986
        }
987

    
988
        public override JSequenceType getResultType(JSequenceType[] argumentTypes)
989
        {
990
            XdmSequenceType[] dt = new XdmSequenceType[argumentTypes.Length];
991
            for (int i = 0; i < dt.Length; i++)
992
            {
993
                dt[i] = XdmSequenceType.FromSequenceType(argumentTypes[i]);
994
            }
995

    
996
            XdmSequenceType rt = definition.ResultType(dt);
997
            return rt.ToSequenceType();
998
        }
999

    
1000
        public override Boolean trustResultType()
1001
        {
1002
            return definition.TrustResultType;
1003
        }
1004

    
1005
        public override Boolean dependsOnFocus()
1006
        {
1007
            return definition.DependsOnFocus;
1008
        }
1009

    
1010
        public override Boolean hasSideEffects()
1011
        {
1012
            return definition.HasSideEffects;
1013
        }
1014

    
1015
        public override JExtensionFunctionCall makeCallExpression()
1016
        {
1017
            return new WrappedExtensionFunctionCall(definition.MakeFunctionCall());
1018
        }
1019

    
1020
    }
1021

    
1022
    internal class Mapper : net.sf.saxon.dotnet.DotNetIterator.Mapper
1023
    {
1024
        public object convert(object obj)
1025
        {
1026
            XdmItem i = (XdmItem)obj;
1027
            return (JItem)i.Unwrap();
1028
        }
1029
    }
1030

    
1031
    internal class WrappedExtensionFunctionCall : JExtensionFunctionCall {
1032

    
1033
        ExtensionFunctionCall functionCall;
1034

    
1035
        public WrappedExtensionFunctionCall(ExtensionFunctionCall call)
1036
        {
1037
            this.functionCall = call;
1038
        }
1039
        
1040
        public override void supplyStaticContext(JStaticContext context, int locationId, JExpression[] arguments)
1041
        {
1042
            StaticContext sc = new StaticContext(context);
1043
            functionCall.SupplyStaticContext(sc);
1044
        }
1045

    
1046
        public override void copyLocalData(JExtensionFunctionCall destination)
1047
        {
1048
            functionCall.CopyLocalData(((WrappedExtensionFunctionCall)destination).functionCall);
1049
        }
1050

    
1051
        public override JSequence call(JXPathContext context, JSequence [] argument)
1052
        {
1053
            SequenceEnumerator<XdmItem>[] na = new SequenceEnumerator<XdmItem>[argument.Length];
1054
            for (int i = 0; i < na.Length; i++)
1055
            {
1056
                na[i] = new SequenceEnumerator<XdmItem>((JXdmSequenceIterator)XdmValue.FromGroundedValueToJXdmValue(argument[i].materialize()).iterator());
1057
            }
1058
            DynamicContext dc = new DynamicContext(context);
1059
            IEnumerator<XdmItem> result = functionCall.Call(na, dc);
1060
            return new net.sf.saxon.om.LazySequence(new net.sf.saxon.om.IteratorWrapper(new net.sf.saxon.dotnet.DotNetIterator(result, new Mapper())));
1061
        }
1062
    }
1063
}
1064

    
1065
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1066
// Copyright (c) 2020 Saxonica Limited.
1067
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
1068
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
1069
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
1070
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
(4-4/11)