Sophie

Sophie

distrib > Mageia > 7 > aarch64 > by-pkgid > b3bdfe6d859a3d6920ff2c44b38e9a6f > files > 276

saxon-manual-9.4.0.9-2.mga7.noarch.rpm

<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet href="../../make-menu.xsl" type="text/xsl"?><html>
   <head>
      <this-is section="extensibility" page="integratedfunctions" subpage="ext-full-J"/>
      <!--
           Generated at 2011-12-09T20:47:22.916Z--><title>Saxonica: XSLT and XQuery Processing: Java extension functions: full interface</title>
      <meta name="coverage" content="Worldwide"/>
      <meta name="copyright" content="Copyright Saxonica Ltd"/>
      <meta name="title"
            content="Saxonica: XSLT and XQuery Processing: Java extension functions: full interface"/>
      <meta name="robots" content="noindex,nofollow"/>
      <link rel="stylesheet" href="../../saxondocs.css" type="text/css"/>
   </head>
   <body class="main">
      <h1>Java extension functions: full interface</h1>
      <p>With this approach, each extension function is implemented
         as a pair of Java classes. The first class, the <a class="bodylink"
            href="../../javadoc/net/sf/saxon/lib/ExtensionFunctionDefinition.html"><code>ExtensionFunctionDefinition</code></a>,
         provides general static information about the extension function (including its name, arity, and the
         types of its arguments and result). The second class, an <a class="bodylink"
            href="../../javadoc/net/sf/saxon/lib/ExtensionFunctionCall.html"><code>ExtensionFunctionCall</code></a>, represents
         a specific call on the extension function, and includes the <code>call()</code> method that Saxon invokes
         to evaluate the function.</p>
      <div class="boxed"
           style="border: solid thin; background-color: #B1CCC7; padding: 2px">When a stylesheet or query uses integrated extension functions and is run from the command line,
the classes that implement these extension functions must be registered with the <a class="bodylink" href="../../javadoc/net/sf/saxon/Configuration.html">
            <code>Configuration</code>
         </a>.
 On Saxon-PE and Saxon-EE this can conveniently be done by declaring them in a <a class="bodylink" href="../../configuration/configuration-file.xml">configuration file</a>.
It can also
be achieved (on all editions including Saxon-HE) by subclassing <a class="bodylink" href="../../javadoc/net/sf/saxon/Transform.html">
            <code>net.sf.saxon.Transform</code>
         </a> or <a class="bodylink" href="../../javadoc/net/sf/saxon/Query.html">
            <code>net.sf.saxon.Query</code>
         </a>,
overriding the method <code>applyLocalOptions()</code> so that it makes the appropriate calls on
<code>config.registerExtensionFunction()</code>; or it can be done in a user-defined
class that implements the interface <a class="bodylink" href="../../javadoc/net/sf/saxon/lib/Initializer.html">
            <code>net.sf.saxon.Initializer</code>
         </a>, and that is nominated
on the command line using the <code>-init</code> option.</div>
      <p>The arguments passed in a call to an integrated extension function are type-checked against the declared
types in the same way as for any other XPath function call, including the standard conversions such as
atomization and numeric promotion. The return value is checked against the declared return type but is not
converted: it is the responsibility of the function implementation to return a value of the correct type.</p>
      <p>Here is an example extension written to the Java version of this interface. It takes two integer arguments and performs a "shift left"
    operation, shifting the first argument by the number of bit-positions indicated in the second argument:</p>
      <div class="codeblock"
           style="border: solid thin; background-color: #B1CCC7; padding: 2px">
         <pre>
            <code>
private static class ShiftLeft extends ExtensionFunctionDefinition {
        @Override
        public StructuredQName getFunctionQName() {
            return new StructuredQName("eg", "http://example.com/saxon-extension", "shift-left");
        }

        @Override
        public SequenceType[] getArgumentTypes() {
            return new SequenceType[] {SequenceType.SINGLE_INTEGER, SequenceType.SINGLE_INTEGER};
        }

        @Override
        public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
            return SequenceType.SINGLE_INTEGER;
        }

        @Override
        public ExtensionFunctionCall makeCallExpression() {
            return new ExtensionFunctionCall() {
                public SequenceIterator call(SequenceIterator[] arguments, XPathContext context) throws XPathException {
                    long v0 = ((IntegerValue)arguments[0].next()).longValue();
                    long v1 = ((IntegerValue)arguments[1].next()).longValue();
                    long result = v0&lt;&lt;v1;
                    return Value.asIterator(Int64Value.makeIntegerValue(result));
                }
            };
        }
    }</code>
         </pre>
      </div>
      <p>The extension must be registered with the configuration:</p>
      <div class="codeblock"
           style="border: solid thin; background-color: #B1CCC7; padding: 2px">
         <pre>
            <code>configuration.registerExtensionFunction(new ShiftLeft())</code>
         </pre>
      </div>
      <p>and it can then be called like this:</p>
      <div class="codeblock"
           style="border: solid thin; background-color: #B1CCC7; padding: 2px">
         <pre>
            <code>declare namespace eg="http://example.com/saxon-extension";
          for $i in 1 to 10 return eg:shift-left(2, $i)"</code>
         </pre>
      </div>
      <p>The methods that must be implemented (or that may be implemented) by an integrated extension function
are listed in the table below. Further details are in the Javadoc.</p>
      <p>First, the <a class="bodylink"
            href="../../javadoc/net/sf/saxon/lib/ExtensionFunctionDefinition.html"><code>ExtensionFunctionDefinition</code></a> class:</p>
      <table>
         <tr>
            <td content="para">
               <p>
               <b>Method</b>
            </p>
            </td>
            <td content="para">
               <p>
               <b>Effect</b>
            </p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>getFunctionQName</p>
            </td>
            <td content="para">
               <p>Returns the name of the function, as a QName (represented by the Saxon class <code>StructuredQName</code>). Like all other functions,
integrated extension functions must be in a namespace. The prefix part of the QName is immaterial.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>getMinumumNumberOfArguments</p>
            </td>
            <td content="para">
               <p>Indicates the minimum number of arguments that must be supplied in a call to the function. A call
with fewer arguments than this will be rejected as a static error.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>getMaximumNumberOfArguments</p>
            </td>
            <td content="para">
               <p>Indicates the maximum number of arguments that must be supplied in a call to the function. A call
with more arguments than this will be rejected as a static error.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>getArgumentTypes</p>
            </td>
            <td content="para">
               <p>Returns the static type of each argument to the function, as an array
with one member per argument. The type is returned as an instance of the Saxon class <code>net.sf.saxon.type.SequenceType</code>.
Some of the more commonly-used types are represented by static constants in the <code>SequenceType</code> class.
If there are fewer members in the array than there are arguments in the function call, Saxon assumes that all
arguments have the same type as the last one that is explicitly declared; this allows for function with a variable
number of arguments, such as <code>concat()</code>.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>getResultType</p>
            </td>
            <td content="para">
               <p>Returns the static type of the result of the function. The actual
result returned at runtime will be checked against this declared type, but no conversion takes place. Like
the argument types, the result type is returned as an instance of <code>net.sf.saxon.type.SequenceType</code>.When Saxon calls this method, it supplies an array containing the inferred static types of the actual arguments
to the function call. The implementation can use this information to return a more precise result, for example in cases
where the value returned by the function is of the same type as the value supplied in the first argument.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>trustResultType</p>
            </td>
            <td content="para">
               <p>This method normally returns <code>false</code>. It can return
<code>true</code> if the implementor of the extension function is confident that no run-time checking of the function
result is needed; that is, if the method is guaranteed to return a value of the declared result type.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>dependsOnFocus</p>
            </td>
            <td content="para">
               <p>This method must return true if the implementation of the function
accesses the context item, context position, or context size from the dynamic evaluation context. The method
does not need to be implemented otherwise, as its default value is false.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>hasSideEffects</p>
            </td>
            <td content="para">
               <p>This method should be implemented, and return true, if the function
has side-effects of any kind, including constructing new nodes if the identity of the nodes is signficant. When
this method returns true, Saxon will try to avoid moving the function call out of loops or otherwise rearranging
the sequence of calls. However, functions with side-effects are still discouraged, because the optimizer cannot
always detect their presence if they are deeply nested within other calls.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>makeCallExpression</p>
            </td>
            <td content="para">
               <p>This method must be implemented; it is called at
 compile time when a call to this extension function is identified, to create an instance of the relevant
 <code>ExtensionFunctionCall</code> object to hold details of the function call expression.</p>
            </td>
         </tr>
      </table>
      <p>The methods defined on the second object, the <a class="bodylink"
            href="../../javadoc/net/sf/saxon/lib/ExtensionFunctionCall.html"><code>ExtensionFunctionCall</code></a>, are:</p>
      <table>
         <tr>
            <td content="para">
               <p>
               <b>Method</b>
            </p>
            </td>
            <td content="para">
               <p>
               <b>Effect</b>
            </p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>supplyStaticContext</p>
            </td>
            <td content="para">
               <p>Saxon calls this method fairly early on during the compilation
process to supply details of the static context in which the function call appears. The method may in some
circumstances be called more than once; it will always be called at least once. As well as the static context
information itself, the expressions supplied as arguments are also made available. If evaluation of the function
depends on information in the static context, this information should be copied into private variables for
use at run-time.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>rewrite</p>
            </td>
            <td content="para">
               <p>Saxon calls this method at a fairly late stage during compilation to
give the implementation the opportunity to optimize itself, for example by performing partial evaluation of
intermediate results, or if all the arguments are compile-time constants (instances of <code>net.sf.saxon.expr.Literal</code>)
even by early evaluation of the entire function call. The method can return any <code>Expression</code> (which includes the
option of returning a <code>Literal</code> to represent the final result); the returned expression will then be
evaluated at run-time in place of the original. It is entirely the responsibility of the implementation to
ensure that the substitute expression is equivalent in every way, including the type of its result.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>copyLocalData</p>
            </td>
            <td content="para">
               <p>Saxon occasionally needs to make a copy of an expression tree. When
it copies an integrated function call it will invoke this method, which is responsible for ensuring that any
local data maintained within the function call objects is correctly copied.</p>
            </td>
         </tr>
         <tr>
            <td content="para">
               <p>call</p>
            </td>
            <td content="para">
               <p>Saxon calls this method at run-time to evaluate the function.The value of each
argument is supplied in the form of a <code>SequenceIterator</code>, that is, an iterator over the items in the
sequence that make up the value of the argument. This may use lazy evaluation, which means that a dynamic error
can occur when reading the next item from the SequenceIterator; it also means that if the implementation
does not require all the items from the value of one of the arguments, they will not necessarily be evaluated
at all (it is good practice to call the close() method on the iterator if it is not read to completion.) The implementation delivers the result also in the form of a <code>SequenceIterator</code>, which in turn
means that the result may be subject to delayed evaluation: the calling code will only access items in the result
as they are required, and may not always read the result to completion. To return a singleton result, 
use the class <code>net.sf.saxon.om.SingletonIterator</code>; to return an empty sequence, return the
unique instance of <code>net.sf.saxon.om.EmptyIterator</code>.</p>
            </td>
         </tr>
      </table>
      <p>Having written an integrated extension function, it must be registered with Saxon so that calls on the
function are recognized by the parser. This is done using the <code>registerExtensionFunction</code> method
available on the <a class="bodylink" href="../../javadoc/net/sf/saxon/Configuration.html"><code>Configuration</code></a> class, and also on the s9api 
         <a class="bodylink" href="../../javadoc/net/sf/saxon/s9api/Processor.html"><code>Processor</code></a> class. It can also
 be registered via an entry in the configuration file. The function can be given any name, although names in 
 the <code>fn:</code>, <code>xs:</code>, and <code>saxon:</code> namespaces are strongly discouraged and may not work.</p>
      <p>It is also possible to register integrated extension functions under XQJ: this is done by locating the
        <code>Configuration</code> that underpins the <code>XQDataSource</code> or <code>XQConnection</code> by casting it to
        the Saxon implementation class (<code>SaxonXQDataSource</code> or <code>SaxonXQConnection</code>)
        and calling <code>getConfiguration()</code>.</p>
      <table width="100%">
         <tr>
            <td>
               <p align="right"><a class="nav" href="ext-fns-N.xml">Next</a></p>
            </td>
         </tr>
      </table>
   </body>
</html>