Project

Profile

Help

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

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

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
        /// <summary>
548
        /// Default constructor to create a wrapped Java StandardCollectionFinder
549
        /// </summary>
550
        public StandardCollectionFinder() {
551
            collectionFinder = new JStandardCollectionFinder();
552
        }
553

    
554
        internal StandardCollectionFinder(JCollectionFinder cf)
555
        {
556
            collectionFinder = (JStandardCollectionFinder)cf;
557
        }
558

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

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

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

    
587
            collectionFinder.registerCollection(collectionURI, new ResourceCollectionWrapper(collection));
588

    
589
        }
590

    
591
    }
592

    
593

    
594
    internal class ResourceCollectionWrapper : JResourceCollection
595
    {
596

    
597
        IResourceCollection resourceCollection;
598

    
599
        public ResourceCollectionWrapper(IResourceCollection rc) {
600
            resourceCollection = rc;
601
        }
602

    
603
        public string getCollectionURI()
604
        {
605
            return resourceCollection.CollectionURI();
606
        }
607

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

    
617
            return iter.iterator();
618

    
619
        }
620

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

    
630
            return iter.iterator();
631
        }
632

    
633
        public bool isStable(JXPathContext xpc)
634
        {
635
           return false;
636
        }
637

    
638
        public bool stripWhitespace(net.sf.saxon.om.SpaceStrippingRule ssr)
639
        {
640
            return false;
641
        }
642
    }
643

    
644

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

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

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

    
679
	/// <summary>
680
	/// ResourceCollection class implements the IResourcecollection interface.
681
    /// This class is used to map the URI of collection into a sequence of Resource objects.
682
    /// It is usedto support the fn:collection() and fn:uri-collection() functions.
683
	/// </summary>
684
    public class ResourceCollection : IResourceCollection
685
    {
686
		protected JResourceCollection resourceCollection;
687

    
688
        internal ResourceCollection()
689
        {
690
        }
691

    
692

    
693
		internal ResourceCollection(JResourceCollection rc) {
694
            resourceCollection = rc;
695
        }
696

    
697
        /// <summary>
698
        /// Get the URI of the collection
699
        /// </summary>
700
        /// <returns>The URI as passed to the fn:collection() or fn:uri-collection() function, resolved if it is relative
701
        /// against the static base URI. If the collection() or uri-collection() function was called with no argument (to get the 
702
        /// 'default collection') this will be the URI of the default collection registered with the Configuration</returns>
703
        public string CollectionURI()
704
        {
705
            return resourceCollection.getCollectionURI();
706
        }
707

    
708
        /// <summary>
709
        /// Get the URIs of the resources in the collection.  It is
710
        /// not required that all collections expose a list of URIs in this way, or that the URIs bear any particular
711
        /// relationship to the resources returned by the getResources() method for the same collection URI.
712
        /// </summary>
713
        /// <param name="context">the XPath evaluation context</param>
714
        /// <returns>List over the URIs of the resources in the collection. The URIs are represented as strings.
715
        /// They should preferably be absolute URIs.</returns>
716
        public List<string> GetResourceURIs(DynamicContext context)
717
        {
718
            List<string> list = new List<string>();
719
            var jIter = resourceCollection.getResourceURIs(context.context);
720
            while(jIter.hasNext()) {
721

    
722
                string uri = (string)jIter.next();
723
                list.Add(uri);
724
            }
725
            return list;
726
        }
727

    
728
        /// <summary>
729
        /// Get the resources in the collection. This supports the fn:collection() function. It is not
730
        /// required that all collections expose a set of resources in this way, or that the resources
731
        /// returned bear any particular relationship to the URIs returned by the getResourceURIs() method
732
        /// for the same collection URI.
733
        /// </summary>
734
        /// <param name="context">context the XPath evaluation context</param>
735
        /// <returns>a list over the resources in the collection. This returns objects of implementations of the interface <code>IResource</code></returns>
736
        public List<IResource> GetResources(DynamicContext context)
737
        {
738
            List<IResource> list = new List<IResource>();
739
            var jIter = resourceCollection.getResources(context.context);
740
            while (jIter.hasNext())
741
            {
742

    
743
                JResource jresource = (JResource)jIter.next();
744
                list.Add(new Resource(jresource));
745
            }
746
            return list;
747
        }
748

    
749
        public bool IsStable(DynamicContext context)
750
        {
751
            return resourceCollection.isStable(context.context);
752
        }
753

    
754

    
755
    }
756

    
757
    /// <summary>
758
    /// A ResourceFactory is used for constructing a particular type of resource
759
    /// </summary>
760
    public interface IResourceFactory {
761

    
762

    
763
        /// <summary>
764
        /// Create a Resource with given content
765
        /// </summary>
766
        /// <param name="proc">the Saxon Processor</param>
767
        /// <returns>the resource</returns>
768
		/**public**/ IResource MakeResource(Processor proc);
769

    
770
    }
771

    
772
    internal class ResourceFactoryWrapper : JResourceFactory
773
    {
774
        private IResourceFactory resourceFactory;
775
        private Processor proc;
776

    
777
        internal ResourceFactoryWrapper(IResourceFactory factory, Processor proc) {
778
            this.resourceFactory = factory;
779
        }
780

    
781
        public JResource makeResource(JConfiguration c, AbstractResourceCollection.InputDetails details)
782
        {
783
            return new ResourceWrapper(resourceFactory.MakeResource(proc));
784
        }
785
    }
786

    
787
    /// <summary>
788
    /// Resource Wrapper class for a Java Resource object
789
    /// </summary>
790
    public class Resource : IResource
791
    {
792
        internal JResource resource = null;
793

    
794
        //Default constructor
795
        public Resource() 
796
		{ 
797
			resource = null; 
798
		}
799

    
800
        /// <summary>
801
        /// Constructor to  wrap a Java Resource
802
        /// </summary>
803
        /// <param name="rc">Java Resource object</param>
804
        public Resource(JResource rc) 
805
		{
806
            resource = rc;
807
        }
808

    
809
        /// <summary>
810
        /// Get the media type (MIME type) of the resource if known
811
        /// </summary>
812
        /// <returns>the media type if known; otherwise null</returns>
813
        public string GetContentType()
814
        {
815
            return resource.getContentType();
816
        }
817

    
818
        /// <summary>
819
        /// Get a URI that identifies this resource
820
        /// </summary>
821
        /// <returns>a URI identifying this resource</returns>
822
        public string GetResourceURI()
823
        {
824
            return resource.getResourceURI();
825
        }
826

    
827
        public XdmItem GetXdmItem(DynamicContext context)
828
        {
829
            return XdmItem.FromGroundedValue(resource.getItem(context.context).materialize()).ItemAt(0);
830
        }
831
    }
832

    
833
	/// <summary>
834
	/// BinaryResource
835
	/// </summary>
836
    public class BinaryResource : Resource {
837

    
838

    
839
        public BinaryResource(String href, String contentType, byte[] content) {
840
            resource = new net.sf.saxon.resource.BinaryResource(href, contentType, content); 
841
        }
842

    
843

    
844
    }
845

    
846

    
847
    internal class ResourceWrapper : JResource
848
    {
849

    
850
        IResource resource;
851

    
852
        public ResourceWrapper(IResource resource) {
853
            this.resource = resource;
854
        }
855
        public string getContentType()
856
        {
857
            return resource.GetContentType();
858
        }
859

    
860
        public JItem getItem(JXPathContext xpc)
861
        {
862
            return (JItem) resource.GetXdmItem(new DynamicContext(xpc)).Unwrap();
863
        }
864

    
865
        public string getResourceURI()
866
        {
867
            return resource.GetResourceURI();
868
        }
869
    }
870
    
871

    
872
    internal class CollectionFinderWrapper : JCollectionFinder
873
    {
874

    
875
        ICollectionFinder collectionFinder;
876

    
877
        public CollectionFinderWrapper(ICollectionFinder cf) {
878
            collectionFinder = cf;
879
        }
880

    
881
        public JResourceCollection findCollection(JXPathContext xpc, string str)
882
        {
883
            IResourceCollection rcollection = collectionFinder.FindCollection(new DynamicContext(xpc), str);
884

    
885
            return new ResourceCollectionWrapper(rcollection);
886
        }
887
    }
888

    
889
    /// <summary>
890
    /// This is an interface for simple external/extension functions.
891
    /// Users can implement this interface and register the implementation with the <see cref="Saxon.Api.Processor"/>;
892
    /// the function will then be available for calling from all queries, stylesheets, and XPath expressions compiled
893
    /// under this Processor.
894
    /// </summary>
895
    /// <remarks>
896
    /// <para>Extension functions implemented using this interface are expected to be free of side-effects,
897
    /// and to have no dependencies on the static or dynamic context. A richer interface for extension
898
    /// functions is provided via the <see cref="Saxon.Api.ExtensionFunctionDefinition"/> class.</para>
899
    /// </remarks>
900

    
901
    public interface ExtensionFunction
902
    {
903

    
904
        /// <summary>
905
        /// Return the name of the external function
906
        /// </summary>
907
        /// <returns>the name of the function, as a <c>QName</c></returns>
908

    
909
		/**public**/ 
910
		QName GetName();
911

    
912

    
913
        /// <summary>
914
        /// Declare the result type of the external function
915
        /// </summary>
916
        /// <returns>the result type of the external function</returns>
917

    
918
		/**public**/ 
919
		XdmSequenceType GetResultType();
920

    
921
        /// <summary>
922
        /// Declare the type of the arguments
923
        /// </summary>
924
        /// <returns>an array of <c>XdmSequenceType</c> objects, one for each argument to the function,
925
        /// representing the expected types of the arguments</returns>
926

    
927
		/**public**/ 
928
		XdmSequenceType[] GetArgumentTypes();
929

    
930

    
931
        /// <summary>
932
        /// Method called at run time to evaluate the function.
933
        /// </summary>
934
        /// <param name="arguments">The values of the arguments supplied in the XPath function call.</param>
935
        /// <returns>An <c>XdmValue</c>, representing the result of the extension function. 
936
        /// (Note: in many cases it will be convenient to return an <c>XdmAtomicValue</c> or <c>XdmNode</c>, 
937
        /// both of which are instances of <c>XdmValue</c>).</returns>
938

    
939
		/**public**/ 
940
		XdmValue Call(XdmValue[] arguments);
941
    }
942

    
943

    
944

    
945
    internal class WrappedExtensionFunction : JExtensionFunction
946
    {
947
        ExtensionFunction definition;
948

    
949
        public WrappedExtensionFunction(ExtensionFunction definition)
950
        {
951
            this.definition = definition;
952
        }
953

    
954
        public net.sf.saxon.s9api.XdmValue call(net.sf.saxon.s9api.XdmValue[] xvarr)
955
        {
956
            XdmValue[] values = new XdmValue[xvarr.Length];
957
            int len = xvarr.Length;
958
            for (int i = 0; i < len; i++) {
959
                values[i] = XdmValue.Wrap(xvarr[i].getUnderlyingValue());
960
            }
961
            try {
962
                XdmValue result = definition.Call(values);
963
                return XdmValue.FromGroundedValueToJXdmValue(result.value);
964
            }
965
            catch (Exception ex) {
966
                throw new DynamicError(ex.Message);
967
            }
968
            
969
            }
970

    
971
        public JXdmSequenceType[] getArgumentTypes()
972
        {
973
            XdmSequenceType [] types = definition.GetArgumentTypes();
974
            JXdmSequenceType[] results = new JXdmSequenceType[types.Length];
975
            for (int i = 0; i < types.Length; i++) {
976
                results[i] = types[i].ToJXdmSequenceType();
977
            }
978
            return results;
979
        }
980

    
981
        public net.sf.saxon.s9api.QName getName()
982
        {
983
            return definition.GetName().UnderlyingQName();
984
        }
985

    
986
        public JXdmSequenceType getResultType()
987
        {
988
            JXdmSequenceType declaredResult = definition.GetResultType().ToJXdmSequenceType();
989
            return declaredResult;
990
        }
991
    }
992

    
993
        internal class WrappedExtensionFunctionDefinition : JExtensionFunctionDefinition
994
    {
995
        ExtensionFunctionDefinition definition;
996

    
997
        public WrappedExtensionFunctionDefinition(ExtensionFunctionDefinition definition)
998
        {
999
            this.definition = definition;
1000
        }
1001

    
1002
        public override JStructuredQName getFunctionQName()
1003
        {
1004
            return definition.FunctionName.ToStructuredQName();
1005
        }
1006

    
1007
        public override int getMinimumNumberOfArguments()
1008
        {
1009
            return definition.MinimumNumberOfArguments;
1010
        }
1011

    
1012
        public override int getMaximumNumberOfArguments()
1013
        {
1014
            return definition.MaximumNumberOfArguments;
1015
        }
1016

    
1017
        public override JSequenceType[] getArgumentTypes()
1018
        {
1019
            XdmSequenceType[] dt = definition.ArgumentTypes;
1020
            JSequenceType[] jt = new JSequenceType[dt.Length];
1021
            for (int i = 0; i < dt.Length; i++)
1022
            {
1023
                jt[i] = dt[i].ToSequenceType();
1024
            }
1025
            return jt;
1026
        }
1027

    
1028
        public override JSequenceType getResultType(JSequenceType[] argumentTypes)
1029
        {
1030
            XdmSequenceType[] dt = new XdmSequenceType[argumentTypes.Length];
1031
            for (int i = 0; i < dt.Length; i++)
1032
            {
1033
                dt[i] = XdmSequenceType.FromSequenceType(argumentTypes[i]);
1034
            }
1035

    
1036
            XdmSequenceType rt = definition.ResultType(dt);
1037
            return rt.ToSequenceType();
1038
        }
1039

    
1040
        public override Boolean trustResultType()
1041
        {
1042
            return definition.TrustResultType;
1043
        }
1044

    
1045
        public override Boolean dependsOnFocus()
1046
        {
1047
            return definition.DependsOnFocus;
1048
        }
1049

    
1050
        public override Boolean hasSideEffects()
1051
        {
1052
            return definition.HasSideEffects;
1053
        }
1054

    
1055
        public override JExtensionFunctionCall makeCallExpression()
1056
        {
1057
            return new WrappedExtensionFunctionCall(definition.MakeFunctionCall());
1058
        }
1059

    
1060
    }
1061

    
1062
    internal class Mapper : net.sf.saxon.dotnet.DotNetIterator.Mapper
1063
    {
1064
        public object convert(object obj)
1065
        {
1066
            XdmItem i = (XdmItem)obj;
1067
            return (JItem)i.Unwrap();
1068
        }
1069
    }
1070

    
1071
    internal class WrappedExtensionFunctionCall : JExtensionFunctionCall {
1072

    
1073
        ExtensionFunctionCall functionCall;
1074

    
1075
        public WrappedExtensionFunctionCall(ExtensionFunctionCall call)
1076
        {
1077
            this.functionCall = call;
1078
        }
1079
        
1080
        public override void supplyStaticContext(JStaticContext context, int locationId, JExpression[] arguments)
1081
        {
1082
            StaticContext sc = new StaticContext(context);
1083
            functionCall.SupplyStaticContext(sc);
1084
        }
1085

    
1086
        public override void copyLocalData(JExtensionFunctionCall destination)
1087
        {
1088
            functionCall.CopyLocalData(((WrappedExtensionFunctionCall)destination).functionCall);
1089
        }
1090

    
1091
        public override JSequence call(JXPathContext context, JSequence [] argument)
1092
        {
1093
            SequenceEnumerator<XdmItem>[] na = new SequenceEnumerator<XdmItem>[argument.Length];
1094
            for (int i = 0; i < na.Length; i++)
1095
            {
1096
                na[i] = new SequenceEnumerator<XdmItem>((JXdmSequenceIterator)XdmValue.FromGroundedValueToJXdmValue(argument[i].materialize()).iterator());
1097
            }
1098
            DynamicContext dc = new DynamicContext(context);
1099
            IEnumerator<XdmItem> result = functionCall.Call(na, dc);
1100
            return new net.sf.saxon.om.LazySequence(new net.sf.saxon.om.IteratorWrapper(new net.sf.saxon.dotnet.DotNetIterator(result, new Mapper())));
1101
        }
1102
    }
1103
}
1104

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