Changes

Jump to navigation Jump to search
236 bytes added ,  14:00, 27 February 2020
no edit summary
* The namespace of the function name identifies the Java class.
* The local part of the name, which is rewritten to camel case, identifies a variable or function of that class.
* The middle dot character <code>·</code> ([http://www.fileformat.info/info/unicode/char/b7/index.htm ·]</code> (&amp;#xB7;]), a valid character in XQuery names, but not in Java) can be used to append exact Java parameter types to the function name. Class types must be referenced by their full path.
{| class="wikitable"
|- valign="top"
| Function
| <code>Q{java.lang.Object}hash-code($object)</code>
| <code>[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode() object.hashCode()]</code>
|- valign="top"
| Function with types
| <code>Q{java.lang.String}split·java.lang.String·int($string, ';', xs:int(3))</code>
| <code>[https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-int- string.split(";", 3)]</code>
|}
In the following example, Java’s {{Code|Math}} class is referenced. When executed, the query returns the cosine of an angle by calling the static method {{Code|cos()}}, and the value of π by addressing the static variable via {{Code|PI()}}:
<pre classsyntaxhighlight lang="brush:xquery">
declare namespace math = "java:java.lang.Math";
math:cos(xs:double(0)), math:PI()
</presyntaxhighlight>
With the [[XQuery 3.0#Expanded QNames|Expanded QName]] notation of XQuery 3.0,
the namespace can directly be embedded in the function call:
<pre classsyntaxhighlight lang="brush:xquery">
Q{java:java.lang.Math}cos(xs:double(0))
</presyntaxhighlight>
The constructor of a class can be invoked by calling the virtual function {{Code|new()}}. Instance methods can then called by passing on the resulting Java object as first argument. In the following example, 256 bytes are written to the file {{Code|output.txt}}. First, a new {{Code|FileWriter}} instance is created, and its {{Code|write()}} function is called in the next step:
<pre classsyntaxhighlight lang="brush:xquery">declare namespace fw = "java.io.FileWriter";
let $file := fw:new('output.txt')
return (
fw:close($file)
)
</presyntaxhighlight>
If the result of a Java call contains invalid XML characters, it will be rejected. The validity check can be disabled by setting the [[Options#CHECKSTRINGS{{Option|CHECKSTRINGS]] option }} to false. In the example below, a file with a single {{Code|00}} byte is written, and this file will then be accessed by via Java functions:
<pre classsyntaxhighlight lang="brush:xquery">
declare namespace br = 'java.io.BufferedReader';
declare namespace fr = 'java.io.FileReader';
file:write-binary('00.bin', xs:hexBinary('00')),
br:new(fr:new('00.bin')) ! (br:readLine(.), br:close(.))
</presyntaxhighlight>
Note that Java code cannot be pre-compiled, and will as such be evaluated slower than optimized XQuery code.
In the (side-effecting) example below, the size of a Java hash set is returned. The boolean values that are returned by {{Code|set:add()}} are swallowed:
<pre classsyntaxhighlight lang="brush:xquery">
import module namespace set = "java:java.util.HashSet";
prof:void(
),
set:size()
</presyntaxhighlight>
The execution of imported classes is more efficient than the execution of instances that are created at runtime via {{Code|new()}}. A drawback is that no arguments can be passed on to the class constructor. As a consequence, the import fails if the addressed class has no default constructor, but at least one constructor with arguments.
If a class inherits the abstract [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/QueryModule.java QueryModule] class, the two variables [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/QueryContext.java queryContext] and [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/StaticContext.java staticContext] get available, which provide access to the global and static context of a query.
The [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/QueryResource.java QueryResource] interface can be implemented to enforce finalizing operations, such as the closing of opened connections or resources in a module. Its {{Code|close()}} method will be called after a query the XQuery expression has been fully evaluated.
==Annotations==
In the following code, information from the static query context is returned by the first function, and a query exception is raised by the second function:
<pre classsyntaxhighlight lang="brush:xquery">
import module namespace context = 'org.basex.examples.query.ContextModule';
element error { $err:description }
}
</presyntaxhighlight>
The imported Java class is shown below:
<pre classsyntaxhighlight lang="brush:java">
package org.basex.examples.query;
/**
* Returns the name of the logged in user.
* @return userstring
*/
@Requires(Permission.NONE)
/**
* Converts the specified string to an integer.
* @param value string representationto be converted * @return resulting integer
* @throws QueryException query exception
*/
@Override
public void close() {
// see description abovedefined in QueryResource interface, will be called after query evaluation
}
}
</presyntaxhighlight>
The result will look as follows:
<pre classsyntaxhighlight lang="brush:xml">
<user>admin</admin>
<error>Integer conversion failed: abc</error>
</presyntaxhighlight>
Please visit the XQuery 3.0 specification if you want to get more insight into
By default, a Java function will be executed in parallel with other code. However, if a Java function performs sensitive write operations, it is advisable to explicitly lock the code. This can be realized via locking annotations:
<pre classsyntaxhighlight lang="brush:java">
@Lock(write = { "HEAVYIO" })
public void write() {
// ...
}
</presyntaxhighlight>
If an XQuery expression is run which calls the Java {{Code|write()}} function, every other query that calls {{Code|write()}} or {{Code|read()}} needs to wait for the query to be finished. If a query calls the {{Code|read()}} function, only those queries are queued that call {{Code|write()}}, because this function is only annotated with a {{Code|read}} lock. More details on parallel query execution can be found in the article on [[Transaction Management]].
Bureaucrats, editor, reviewer, Administrators
13,550

edits

Navigation menu