JavaLibrary

This document contains the executable specification of JavaLibrary features: its predicates and functors are tested by following the definitions contained in the official tuProlog's guide.

1. java_object/3

java_object(ClassName, ArgList, ObjId) is true iff ClassName is the full class name of a Java class available on the local file system, ArgList is a list of arguments that can be meaningfully used to instantiate an object of the class, and ObjId can be used to reference such an object; as a side effect, the Java object is created and the reference to it is unified with ObjId. It is worth noting that ObjId can be a Prolog variable (that will be bound to a ground term) as well as a ground term (not a number).

Templates and modes for the predicate are as follows:

java_object(+full_class_name, +list, ?obj_id)

1.1 Example tests

Let's start with some simple tests verifying success or failure of single goals.

alice.tuprolog.SimpleGoalFixture
goalsuccess()
java_object('non.existant.Class', [], _). false
java_object('java.lang.Integer', [], _). false
java_object('java.lang.String', [X], _). false
java_object('java.lang.Integer', [0], Z), java_object('java.lang.Integer', [1], Z). false
java_object('java.lang.Integer', [0], zero), java_object('java.lang.Integer', [0], expected), zero <- equals(expected) returns true. true

Now we run some tests also verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Then, ask the engine to solve a query, and check variable bindings.

fit.ActionFixture
enter query java_object('java.lang.Object', [], X1), java_object('java.lang.Object', [], X2).
check hasSolution true
enter variable X1
check binding '$obj_0'
enter variable X2
check binding '$obj_1'
enter query java_object('java.lang.Object', [], X), atom_chars(X, L).
check hasSolution true
enter variable L
check binding ['$', 'o', 'b', 'j', '_', '2']
enter query java_object('java.lang.Integer[]', [0], A), A <- getClass returns C, C <- getName returns N.
check hasSolution true
enter variable N
check binding '[Ljava.lang.Integer;'
enter query java_object('java.lang.Integer', [0], Zero), java_object('java.lang.Integer', [0], Expected), Zero <- equals(Expected) returns Result.
check hasSolution true
enter variable Result
check binding true

2. <-/2 and returns/2

'<-'(ObjId, MethodInfo) is true iff ObjId is a ground term currently referencing a Java object, which provides a method whose name is the functor name of the term MethodInfo and possible arguments the arguments of MethodInfo as a compound. As a side effect the method is called on the Java object referenced by the ObjId.

return('<-'(ObjId, MethodInfo), ObjIdResult) is true iff ObjId is a ground term currently referencing a Java object, which provides a method whose name is the functor name of the term MethodInfo and possible arguments the arguments of MethodInfo as a compound, and ObjIdResult can be used as a meaningful reference for the Java object that the method possibly returns. As a side effect the method is called on the Java object referenced by the ObjId and the object possibly returned by the method invocation is referenced by the ObjIdResult term.

The anonymous variable used as argument in the MethodInfo structure is interpreted as the Java null value.

It is worth noting that this predicate is equivalent to the java_call/3 predicate.

Templates and modes for the predicate are as follows:

'<-'(@obj_id, @method_signature)
return('<-'(@obj_id, @method_signature), ?obj_id)

2.1 Example tests

Let's start with some simple tests verifying success or failure of single goals.

alice.tuprolog.SimpleGoalFixture
goalsuccess()
java_object('java.util.ArrayList', [], L), L <- clear returns X. true
java_object('java.util.ArrayList', [], L), L <- clear(10). false
java_object('java.util.ArrayList', [], L), L <- size. true
java_object('java.lang.Object', [], Obj), Obj <- nonExistantMethod. false
java_object('java.lang.Integer', [0], Z), Z <- compareTo(X). false
java_object('java.lang.Integer', [0], Z), Z <- compareTo('ciao'). false
java_object('java.util.ArrayList', [], L), L <- isEmpty returns true. true
java_object('java.lang.String', ['hello'], S), S <- toUpperCase returns 'HELLO'. true
class('java.lang.System') <- gc returns X. true
class('java.lang.Integer') <- parseInt('15') returns 15. true
class('java.lang.Integer') <- parseInt(10) returns N. false
class('java.lang.Integer') <- parseInt(X) returns N. false
class('java.lang.System') <- currentTimeMillis. true
class('java.lang.System') <- currentTimeMillis(10). false
class('non.existant.Class') <- nonExistantMethod. false
class('java.lang.Integer') <- nonExistantMethod. false

Now we run some tests also verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Then, ask the engine to solve a query, and check variable bindings.

fit.ActionFixture
enter query java_object('java.lang.Integer', [5], N), N <- intValue returns V.
check hasSolution true
enter variable V
check binding 5
enter query java_object('java.util.ArrayList', [], X), X <- toArray returns A, atom_chars(A, L).
check hasSolution true
enter variable L
check binding ['$', 'o', 'b', 'j', '_', '2']

3. as and '.'

The as infix operator is used to explicitly specify (i.e. cast) method argument types: ObjectRef as ClassName. By writing so, the object represented by ObjectRef is considered to belong to class Classname: both ObjectRef and Classname have the usual meaning explained above.

The operator works also with primitive Java types, specified as Classname (for instance, myNumber as int). The purpose of this predicate is both to provide methods with the exact Java types required, and to solve possible overloading conflicts a-priori.

The '.' infix operator is used, in conjunction with the set and get pseudo-method pair, to access the public fields of a Java object. The syntax is based on the following constructs: ObjectRef . Field <- set(GroundTerm) and ObjectRef . Field <- get(Term). As usual, ObjectRef is the Prolog identifier for a Java object.

The first construct set the public field Field to the specified GroundTerm, which may be either a value of a primitive data type, or a reference to an existing object: if GroundTerm is not ground, the infix predicate fails. The second construct retrieves the value of the public field Field, where Term is handled once again as ObjectRef in the case of java_object/3.

As for methods, static fields of classes can be accessed using the compound term class(ClassName) in the place of ObjectRef.

No templates are available, since as and '.' are infix operands, not predicates.

3.1 Example tests

Let's start with some simple tests verifying success or failure of single goals.

alice.tuprolog.SimpleGoalFixture
goalsuccess()
java_object('java.lang.Integer', [5], I), class('java.lang.Integer') <- toString(I as int) returns '5'. false
java_object('java.lang.String', ['hello'], S1), java_object('java.lang.String', ['world'], S2), S2 <- compareTo(S1 as 'java.lang.Object') returns X, X > 0. true
java_object('java.lang.String', ['hello'], S1), java_object('java.lang.String', ['world'], S2), S2 <- compareTo(S1 as 'non.existant.Class') returns X. false
java_object('java.util.ArrayList', [], L), java_object('java.lang.String', ['hello'], S), S <- compareToIgnoreCase(L as 'java.util.List') returns X. false
java_object('java.lang.String', ['hello'], S), java_object('java.lang.Integer', [2], I), S <- indexOf(I as 'java.util.List') returns N. false
class('java.lang.Integer').MAX_VALUE <- get(V). false
class('java.lang.Integer').'MAX_VALUE' <- get(V), V > 0. true
class('java.lang.Integer').'NON_EXISTANT_FIELD' <- get(X). false
java_object('java.awt.Point', [], P), P.nonExistantField <- get(X). false
java_object('java.awt.Point', [], P), P.nonExistantField <- set(0). false
java_object('java.awt.Point', [], P), P.y <- set(X). false
java_object('java.awt.GridBagConstraints', [], C), java_object('java.awt.Insets', [1,1,1,1], I1), C.insets <- set(I1), C.insets <- get(I2), I1 == I2. true

Now we run some tests also verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Then, ask the engine to solve a query, and check variable bindings.

fit.ActionFixture
enter query java_object('java.awt.Point', [], P), P.x <- get(X).
check hasSolution true
enter variable X
check binding 0
enter query java_object('java.awt.Point', [], P), P.y <- set(5), P.y <- get(Y).
check hasSolution true
enter variable Y
check binding 5

4. java_array_set/3, java_array_get/3 and java_array_length/2

java_array_set(ObjArrayId, Index, ObjId) is true iff ObjArrayId is a ground term currently referencing a Java array object, Index is a valid index for the array and ObjId is a ground term currently referencing a Java object that could inserted as an element of the array (according to Java type rules). As side effect, the object referenced by \bt{ObjId} is set in the array referenced by ObjArrayId in the position (starting from 0, following the Java convention) specified by Index. This predicate can be used for arrays of Java objects: for arrays whose elements are Java primitive types (such as int, float, etc.) predicates can be used, with an underscore and the type following the name of the predicate, such as in java_array_set_int/3, with the same semantics but specifying directly the term to be set as a Prolog term.

java_array_get(ObjArrayId, Index, ObjIdResult) is true iff ObjArrayId is a ground term currently referencing a Java array object, Index is a valid index for the array, and ObjIdResult can be used as a meaningful reference for a Java object contained in the array. As a side effect, ObjIdResult is unified with the reference to the Java object of the array referenced by ObjArrayId in the Index position. This predicate can be used for arrays of Java objects: for arrays whose elements are Java primitive types (such as int, float, etc.) predicates can be used, with an underscore and the type following the name of the predicate, such as in java_array_get_int/3, with the same semantics but specifying directly the term to be set as a Prolog term.

java_array_length(ObjArrayId, ArrayLength) is true iff ArrayLength is the length of the Java array referenced by the term ObjArrayId.

The anonymous variable used as ObjId is interpreted as the Java null value.

Templates and modes for the predicate are as follows:

java_array_set(@obj_id, @positive_integer, +obj_id)
java_array_get(@obj_id, @positive_integer, ?obj_id)
java_array_length(@term, ?integer)

4.1 Example tests

Let's start with some simple tests verifying success or failure of single goals.

alice.tuprolog.SimpleGoalFixture
goalsuccess()
java_object('java.lang.Integer[]', [3], A), java_array_get(A, 4, Obj). false
java_object('java.awt.Polygon', [], P), P.xpoints <- get(XP), java_array_get_boolean(XP, 2, V). false
java_object('java.lang.String[]', [5], A), java_array_set(A, 2, X). false
java_object('java.lang.Integer[]', [5], A), java_array_set(A, 2, zero). false
java_object('java.awt.Polygon', [], P), P.xpoints <- get(XP), java_array_set_boolean(XP, 3, 2). false
java_object('java.lang.Object', [], Obj), java_array_length(Obj, Size). false
java_object('java.lang.Object', [], Obj), java_array_get(Obj, 0, X). false
java_object('java.lang.Object', [], Obj), java_array_get_int(Obj, 0, X). false
java_object('java.lang.Integer', [0], I), java_array_set(I, 0, 5). false
java_object('java.lang.Integer', [0], I), java_array_set_int(I, 0, 5). false
java_object('java.lang.Object[]', [3], A), java_object('java.lang.Object', [], Obj), java_array_set(A, 2, Obj), java_array_get(A, 2, X), X == Obj. true

Now we run some tests also verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Then, ask the engine to solve a query, and check variable bindings.

fit.ActionFixture
enter query java_object('java.lang.Integer[]', [3], A), java_array_length(A, Size).
check hasSolution true
enter variable Size
check binding 3
enter query java_object('java.lang.Integer[]', [3], A), java_array_get(A, 0, I), I <- intValue returns V.
check hasSolution true
enter variable V
check binding _
enter query java_object('java.awt.Polygon', [], P), P.xpoints <- get(XP), java_array_get_int(XP, 3, V).
check hasSolution true
enter variable V
check binding 0
enter query java_object('java.awt.Polygon', [], P), P.xpoints <- get(XP), java_array_get_float(XP, 3, V).
check hasSolution true
enter variable V
check binding 0.0
enter query java_object('java.lang.Integer[]', [3], A), java_object('java.lang.Integer', [2], Two), java_array_set(A, 2, Two), java_array_get(A, 2, X).
check hasSolution true
enter variable X
check binding 2
enter query java_object('java.awt.Polygon', [], P), P.xpoints <- get(XP), java_array_set_int(XP, 3, 2), java_array_get_int(XP, 3, V).
check hasSolution true
enter variable V
check binding 2
enter query java_object('java.awt.Polygon', [], P), P.xpoints <- get(XP), java_array_set_float(XP, 3, 2), java_array_get_int(XP, 3, V).
check hasSolution true
enter variable V
check binding 2.0

Run the tests!


The results of the tests for JavaLibrary are as follows:

fit.Summary