Changes

Jump to navigation Jump to search
237 bytes added ,  14:00, 27 February 2020
no edit summary
|- 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