Fork me on GitHub

Bidirectional Interface

Install

Java Prolog Interface API is distributed with implementation adapter and concrete prolog driver library until it is possible according to related libraries licenses. The distributions are named normally such that prolobjectlink-jpi-jpl7-swi7-x.y.z-dist.zip meaning that this distribution is a JPI implementation over JPL version 7 or above and SWI-Prolog version 7 or above. The x.y.z is the distribution version. The distribution can be downloaded in zip or tar.gz compresses format. To install you need perform the following steps: •Install Java Runtime Environment (JRE) 1.8 or above. •Install Native Prolog Engine compatible to Operating System and your architecture. If the Prolog Engine to use is Java-based this step is omitted. •Configure System Path with Prolog Engine routes. If the Prolog Engine to use is Java-based this step is omitted. •Download Java Prolog Interface compatible to related prolog engine and unzip the distribution over Operating File System. •Configure System Path with JPI unzip folder route. •Open a new System console and type pllink –i to see the product information. For the JPI beginners we recommended start with a Pure Java-Prolog Engine because have less configuration aspects and native engine are more difficult to link.

Getting started Java to Prolog

After installation and architecture compression you can use the hello world sample for test the system integration. This hello world sample show how interacts with JPI from Java programming language with Abstracted Prolog Engine. For the first experience we suggesting use a Java-based Prolog engine like tuProlog because have less configuration aspects.

Create in your preferred development environment an empty project. Set in the project build path the JPI downloaded libraries located at lib folder. Create a Main Java class that look like below code:

       public class Main {
                public static void main(String[] args) {
                PrologProvider provider = Prolog.getProvider();
                PrologEngine engine = provider.newEngine();
                engine.asserta("sample('hello wolrd')");
                PrologQuery query=engine.query("sample(X)");
                System.out.println(query.one());
                }
        }

Architecture

JPI use a layered architecture pattern where every layer represents a component. The multi-engine Java Prolog connectors provide different levels of abstraction to simplify the implementations of common inter-operability task JPC. Java Prolog Connectors architectures describe three fundamentals layers, High-level API layer, Engine Adapter layer and Concrete Engine layer. High-level API layer define all services to be used by the users in the Java Prolog Application that is the final architecture layer on the architecture stack. High-level API provide the common implementation of Engine Abstraction, Data Type and Inter-Language conversion. The adapter layer adapts before mentioned features to communicate with the concrete Engine Layer, being the last responsible of execute the request services.

All existing Java Prolog Connectors implementation only bring support for Native Prolog Engines that have JVM bindings driver. JPI project is more inclusive and find connect all Prolog Engines Categories, Native and Java Based implementations. Some particular Java Based implementations in the future can be implement in strike forward mode the JPI interface. This particulars implementations reduce the impedance mismatch by remove the adapter layer. Therefore, JPI reference implementations will be faster than other that use adapter layer.

In JPI architecture stack in the bottom layer we have the Operating System. The Operating System can be Windows, Linux or Mac OS. Over Operating System, we have the native implementation of JVM and Prolog Engines like SWI, SWI7 and others. Over JVM and Prolog Engines we have Java Based Prolog Engines implementations and JVM bindings driver that share the runtime environment with JVM and native Prolog Engines. Over Java Based Prolog Engines implementations and JVM bindings drivers we have the JPI correspondent adapters. The adapters artifacts are the JPI implementations for each Prolog Engines. Over each adapter we have the JPI application provider interface and at the top stack we the final user application. The user application only interacts with the JPI providing single sourcing and transparency.

Prolog Provider

Prolog Provider is the mechanism to interact with all Prolog components. Provider classes implementations allow create Prolog Terms, Prolog Engine, Java Prolog Converter, Prolog Parsers and system logger. Using io.github.prolobjectlink.prolog.Prolog bootstrap class the Prolog Providers are created specifying the provider class in getProvider(Class?) method. This is the workflow start for JPI. When the Prolog Provider is created the next workflow step is the Prolog Terms creation using Java primitive types or using string with Prolog syntax. Provider allow create/parsing all Prolog Terms (Atoms, Numbers, Variables and Compounds). After term creation/parsing the next step is create an engine instance with newEngine() method. Using previous term creation and engine instance Prolog Queries can be formulated. This is possible because the engine class have multiples queries creation methods like a query factory. After query creation the Query interface present many methods to retrieve the query results. The result methods are based on result quantities, result terms, result object types, etc… This is the final step in the workflow. In the table 10 is resumed all Prolog Provider Interface methods.

Prolog Terms

All Java Prolog connector libraries provide data type abstraction. Prolog data type abstraction have like ancestor the Term class. Prolog term is coding like abstract class and other Prolog terms are derived classes. In PrologTerm is defined the common term operation for all term hierarchy (functor, arity, compare, unify, arguments). The derived classes implement the correct behavior for each before mentioned operations. All Prolog data types PrologAtom, PrologNumber, PrologList, PrologStructure and PrologVariable are derived from this class. All before mentioned classes extends from this class the commons responsibilities. PrologTerm extends from Comparable interface to compare the current term with another term based on Standard Order.

PrologAtom represent the Prolog atom data type. Prolog atoms are can be of two kinds simple or complex. Simple atoms are defined like a single alpha numeric word that begin like initial lower case character. The complex atom is defining like any character sequence that begin and end with simple quotes. The string passed to build a simple atom should be match with {a-z}{A-Za-z0-9_}* regular expression. If the string passed to build an atom don't match with the before mentioned regular expression the atom constructor can be capable of create a complex atom automatically. For complex atom the string value can have the quotes or just can be absent. The printed string representation of the complex atom implementation set the quotes if they are needed.

    PrologTerm pam = provider.newAtom("pam");
         PrologTerm bob = provider.newAtom("bob");

PrologDouble represent a double precision floating point number. Extends from PrologNumber who contains an immutable Double instance. The Prolog Provider is the mechanism to create a new Prolog double invoking PrologProvider.newDouble(Number). PrologFloat represent a single precision floating point number. Extends from PrologNumber who contains an immutable Float instance. The Prolog Provider is the mechanism to create a new Prolog float invoking PrologProvider.newFloat(Number). PrologInteger represent an integer number. Extends from PrologNumber who contains an immutable Integer instance. The Prolog Provider is the mechanism to create a new Prolog integer invoking PrologProvider.newInteger(Number). Prolog term that represent a long integer number. Extends from PrologNumber who contains an immutable Long instance. The Prolog Provider is the mechanism to create a new Prolog long integer invoking PrologProvider.newLong(Number).

        PrologTerm pi = provider.newDouble(Math.PI);
        PrologTerm euler = provider.newFloat(Math.E);
        PrologTerm i = provider.newInteger(10);
        PrologTerm l = provider.newLong(10);

PrologVariable is created using PrologProvider.newVariable(int) for anonymous variables and PrologProvider.newVariable(String, int) for named variables. The Prolog variables can be used and reused because they remain in java heap. You can instantiate a prolog variable and used it any times in the same clause because refer to same variable every time. The integer parameter represents the declaration variable order in the Prolog clause starting with zero.

         PrologTerm x = provider.newVariable("X", 0);
         PrologTerm y = provider.newVariable("Y", 1);
         PrologTerm z = provider.newVariable("Z", 2);
         
         engine.assertz(
                provider.newStructure(grandparent, x, z),
                provider.newStructure(parent, x, y),
                        provider.newStructure(parent, y, z)
                        );

PrologReference term is inspired on JPL JRef. This term is like a structure compound term that have like argument the object identification atom. The functor is the @ character and the arity is 1. An example of this prolog term is e.g. @(J#00000000000000425). To access to the referenced object, is necessary use PrologTerm.getObject().

PrologList are a special compound term that have like functor a dot (.) and arity equals 2. Prolog list are recursively defined. The first item in the list is referred like list head and the second item list tail. The list tail can be another list that contains head and tail. A special list case is the empty list denoted by no items brackets ([]). The arity for this empty list is zero. The Prolog Provider is the mechanism to create a new PrologList is invoking PrologProvider.newList() for empty list or PrologProvider.newList(PrologTerm) for one item list or PrologProvider.newList(PrologTerm[]) for many items.

         PrologTerm empty = provider.newList();
         PrologTerm one = provider.newInteger(1);
         PrologTerm two = provider.newInteger(2);
         PrologTerm three = provider.newInteger(3);
         PrologTerm list = provider.newList(
                                new PrologTerm[] { one, two, three}
                        );              
         for (PrologTerm prologTerm : list) {
                System.out.println(prologTerm);
         }

PrologList implement Iterable interface to be used in for each sentence iterating over every element present in the list.

        Iterator<PrologTerm> i = list.iterator();
         while (i.hasNext()) {
                PrologTerm prologTerm = i.next();
                System.out.println(prologTerm);
         }
         for (Iterator<PrologTerm> i = list.iterator(); i.hasNext();) {
                PrologTerm prologTerm = i.next();
                System.out.println(prologTerm);
         }

Prolog structures consist in a relation the functor (structure name) and arguments enclosed between parenthesis. The Prolog Provider is the mechanism to create a new Prolog structures invoking PrologProvider.newStructure(String, PrologTerm...). Two structures are equals if and only if are structure and have equals functor and arguments. Structures terms unify only with same functor and arguments structures, with free variable or with with structures where your arguments unify if they have the same functor and arity. Structures have a special property named arity that means the number of arguments present in the structure. There are two special structures term. They are expressions (Two arguments structure term with operator functor) and atoms (functor with zero arguments). For the first special case must be used PrologProvider.newStructure(PrologTerm, String, PrologTerm) specifying operands like arguments and operator like functor.

        PrologTerm pam = provider.newAtom("pam");
        PrologTerm bob = provider.newAtom("bob");
        PrologTerm parent = provider.newStructure("parent", pam, bob);

Prolog Engine

Prolog Engine provide a general propose application interface to interact with Prolog Programing Language. Is a convenient abstraction for interacting with Prolog Virtual Machine from Java. In Java Prolog Engine connectors libraries, the abstract engine is able to answer queries using the abstract term representation before mentioned. There are several implementation engines and in this project we try connect from top level engine to more concrete or specific Prolog Engine. Based on JPC we have a top level engine that communicate with more concretes engines. Over this concretes engines we offer several services to interact with the concrete engines with low coupling and platform independency.

Prolog Query

Prolog query is the mechanism to query the prolog database loaded in prolog engine. The way to create a new prolog query is invoking query() method in the Prolog Engine. When this method is called the prolog query is open an only dispose() in PrologQuery object close the current query and release all internal resources. Prolog query have several methods to manipulate the result objects. The main difference is in return types and result quantities. The result types enough depending of desire data type. Maps of variables name key and Prolog terms as value, Maps of variables name key and Java objects as value, List of before mentioned maps, Prolog terms array, Prolog terms matrix, list of Java Objects and list of list of Java Objects. Respect to result quantities Prolog query offer one, n-th or all possible solutions. This is an important feature because the Prolog engine is forced to retrieve the necessary solution quantities. Prolog query implement Iterable and Iterator. This implementation helps to obtain successive solutions present in the query.

        public class Main {
        public static void main(String[] args) {
                PrologProvider provider = Prolog.getProvider();
                PrologEngine engine = provider.newEngine("zoo.pl");
                 PrologVariable x = provider.newVariable("X", 0);
                 PrologQuery query =                    engine.query(provider.newStructure("dark", x));
                 while (query.hasNext()) {
                        PrologTerm value =                                      query.nextVariablesSolution().get("X");
                        System.out.println(value);
                 }
                 query.dispose();
                 engine.dispose();
                }
        }
        public class Main {
                public static void main(String[] args) {
                        PrologProvider provider = Prolog.getProvider();
                         PrologEngine engine = provider.newEngine("zoo.pl");
                         PrologVariable x = provider.newVariable("X", 0);
                         PrologQuery query =                            engine.query(provider.newStructure("dark", x));
                         for (Collection<PrologTerm> col : query) {
                                for (PrologTerm prologTerm : col) {
                                        System.out.println(prologTerm);
                                }
                         }
                         query.dispose();
                         engine.dispose();
                }
        }

Prolog Query Builder

Prolog query builder to create prolog queries. The mechanism to create a new query builder is using PrologEngine.newQueryBuilder(). The query builder emulates the query creation process. After define all participant terms with the begin(PrologTerm) method, we specify the first term in the query. If the query has more terms, they are created using comma(PrologTerm) for everyone. Clause builder have a getQueryString() for string representation of the clause in progress. After clause definition this builder have query() method that create the final query instance ready to be used. The follow code show how create a Prolog query ?- big(X), dark(X). using PrologQueryBuilder interface.

        PrologVariable x = provider.newVariable("X", 0);
        PrologStructure big = provider.newStructure("big", x);
        PrologStructure dark = provider.newStructure("dark", x);
        PrologQueryBuilder builder = engine.newQueryBuilder();
        PrologQuery query = builder.begin(dark).comma(big).query();

Prolog Clause

Prolog clause is composed by two prolog terms that define a prolog clause, the head and the body. This representation considers the prolog clause body like a single term. If the body is a conjunctive set of terms, the body is a structure with functor/arity (, /2) and the first argument is the first element in the conjunction and the rest is a recursive functor/arity (, /2). The functor and arity for the clause is given from head term functor and arity. This class define some properties for commons prolog clause implementations. They are boolean flags that indicate if the prolog clause is dynamic multi-file and discontiguos. This class have several methods to access to the clause components and retrieve some clause properties and information about it. Additionally, this class contains a prolog provider reference for build terms in some operations.

Prolog Clause Builder

Prolog clause builder to create prolog clauses. The mechanism to create a new clause builder is using PrologEngine.newClauseBuilder(). The clause builder emulates the clause creation process. After define all participant terms with the begin(PrologTerm) method, we specify the head of the clause. If the clause is a rule, after head definition, the clause body is created with neck(PrologTerm) for the first term in the clause body. If the clause body have more terms, they are created using comma(PrologTerm) for everyone. Clause builder have a getClauseString() for string representation of the clause in progress. After clause definition this builder have asserta(), assertz(),clause(),retract() that use the wrapped engine invoking the correspondent methods for check, insert or remove clause respectively.

        PrologTerm z = provider.newVariable("Z", 0);
        PrologTerm darkZ = provider.newStructure("dark", z);
        PrologTerm blackZ = provider.newStructure("black", z);
        PrologTerm brownZ = provider.newStructure("brown", z);
        PrologClauseBuilder builder = engine.newClauseBuilder();
        builder.begin(darkZ).neck(blackZ).assertz();
        builder.begin(darkZ).neck(brownZ).assertz();

The Prolog result in database is showed in the follow code. The table 19 show the Prolog clause builder interface methods.

        dark(Z): - 
                black(Z).
         dark(Z): - 
                brown(Z).

Prolog Scripting in Java

Java 6 added scripting support to the Java platform that lets a Java application execute scripts written in scripting languages such as Rhino JavaScript, Groovy, Jython, JRuby, Nashorn JavaScript, etc. All classes and interfaces in the Java Scripting API are in the javax.script package. Using a scripting language in a Java application provides several advantages, dynamic type, simple way to write programs, user customization, easy way to develop and provide domain-specific features that are not available in Java. For achieve this propose Java Scripting API introduce a scripting engine component. A script engine is a software component that executes programs written in a particular scripting language. Typically, but not necessarily, a script engine is an implementation of an interpreter for a scripting language. To run a script in Java is necessary perform the following three steps, create a script engine manager, get an instance of a script engine from the script engine manager and Call the eval() method of the script engine to execute a script.

        public class Main {
                public static void main(String[] args) {
                        ScriptEngineManager manager = new ScriptEngineManager();
                        ScriptEngine engine = manager.getEngineByName("prolog");
                        Boolean result = engine.eval("?- X is 5+3.");
                        Integer solution = engine.get("X");
                        System.out.println(solution);
                }
        }

Using script engine, it possible read Prolog source file. Read Prolog source file allow coding all prolog source in separate mode respect to Java program.

        public class Main {
                public static void main(String[] args) {
                        ScriptEngineManager manager = new ScriptEngineManager();
                        ScriptEngine engine = manager.getEngineByName("prolog");
                        Boolean read = engine.eval(new FileReader("family.pl"));
                        Boolean eval = engine.eval("?- parent( Parent, Child)");
                        Object parent = engine.get("Parent");
                        Object child = engine.get("Child");
                        System.out.println(parent);
                        System.out.println(child);
                }
        }

Getting started Prolog to Java

This is an overview of an interface which allows SWI-Prolog programs to dynamically create and manipulate Java objects.

JPL types (Java types, as seen by Prolog)

All Java values and object references which are passed between Prolog engines and Java VMs via JPL's Prolog API are seen as instances of types within this simplified JPL type system:

a datum (this term is introduced, out of necessity, to refer jointly to values and refs)

is a value (values are copied between Prolog and the JVM)

is a boolean

or a char

or a long, int, short or byte

or a double or float

or a string (an instance of java.lang.String)

or a void (an artificial value returned by calls to Java void methods)

or a ref

is null

or an object (held within the JVM, and represented in Prolog by a canonical reference)

is an array

or a class instance (other than of java.lang.String)

Representation of Java values and references within Prolog

Instances of JPL types are represented within Prolog as follows:

boolean has two values, represented by @(true) and @(false)

char values are represented by corresponding Prolog integers

int, short and byte values are represented by corresponding Prolog integers

long values are represented as Prolog integers if possible (32-bit in current SWI-Prolog), else as jlong(Hi,Lo) where Hi is an integer corresponding to the top32 bits of the long, and Lo similarly represents the lower 32 bits

double and float values are represented as Prolog floats (which are equivalent to Java doubles) (there may be minor rounding, normalisation or loss-of-precision issues when a Java float is widened to a Prolog float then narrowed back again, but what the heck)

string values (immutable instances of java.lang.String) are represented as Prolog atoms (in UTF-8 encoding)

null has only one value, represented as @(null)

void has only one value, represented as @(void)

array and class instance references are currently represented as @(Tag), where Tag ia an atom whose name encodes a JNI global reference value; this may change, but won't affect Prolog programs which respect the opacity of references

Representation of Java types within Prolog (1): structured notation

The JPL Prolog API allows Prolog applications to inspect, manipulate, and reason about the types of Java values, references, methods etc., and this section describes how these types themselves (as opposed to instances thereof) are represented. Predicates which pass these type representations include jpl_class_to_type/2, jpl_classname_to_type/2, jpl_datum_to_type/2, jpl_is_object_type/1, jpl_is_type/1, jpl_object_to_type/2, jpl_primitive_type/1, jpl_ref_to_type/2, jpl_type_to_class/2. jpl_type_to_classname/2.

void is represented as void

null is represented as null

the primitive types are represented as boolean, char, byte, short, int, long, float, double

classes are represented as class(package_parts,classname_parts)

e.g. class([java,util],['Date'])

array types are represented as array(type)

e.g. array(boolean)

e.g. array(class([java,lang],['String'])

This structured notation for Java types is designed to be convenient for composition and decomposition by matching (unification).

Predicates

Creating instances of Java classes

To create an instance of a Java class from within Prolog, call jpl_new(+Class,+Params,-Ref) with a classname, a list of actual parameters for the constructor, and a variable to be bound to the new reference, e.g.

    jpl_new( 'javax.swing.JFrame', ['frame with dialog'], F)

which binds F to a new object reference, e.g.

     @('J#0008272420')

(not that the details of this structure are of any necessary concern to the Prolog programmer or to the applications she writes). NB for convenience, this predicate is overloaded: Class can also be a class type in structured notation, e.g. array(boolean).

Calling methods of Java objects or classes

The object reference generated by the jpl_new/3 call (above) can be passed to other JPL API predicates such as

    jpl_call( +Ref, +Method, +Params, -Result)

e.g.

    jpl_call( F, setVisible, [@(true)], _)

which calls the setVisible method of the object to which F refers, effectively passing it the Java value true.

(This call should display the new JFrame in the top left corner of the desktop.)

Note the anonymous variable passed as the fourth argument to jsp_call/4. A variable in this position receives the result of the method call: either a value or a reference. Since SetVisible() is a void method, the call returns the (artificial) reference @(void).

Some may prefer to code this call thus:

    jpl_call( F, setVisible, [@true], @void)

which documents the programmer's understanding that this is a void method (and fails if it isn't :-).

If the +Ref argument represents a class, then the named static method of that class is called.

Fetching field values of Java objects or classes

The jpl_get/3 API predicate can retrieve the value of an instance field or a static field, e.g.

    jpl_get( 'java.awt.Color', pink, Pink)

which binds the Prolog variable Pink to a reference to the predefined java.awt.Color "constant" which is held in the static final .pink field of the java.awt.Color class.

More generally, jpl_get/3 has the following interface:

    jpl_get( +Class_or_Object, +Field, -Datum)

If the first argument represents a class, then a static field of that class with FieldName is accessed.

Setting field values of Java objects or classes

Object and class fields can be set (i.e. have values or references assigned to them) by the jpl_set/3 API procedure, which has the following interface:

    jpl_set( +Class_or_Object, +Field, +Datum)

where Datum must be a value or reference of a type suitable for assignment to the named field of the class or object.

A slightly longer example

This code fragment

    findall(
        Ar,
        (   current_prolog_flag( N, V),
            term_to_atom( V, Va),
            jpl_new( '[Ljava.lang.String;', [N,Va], Ar)
        ),
        Ars
    ),
    jpl_new( '[[Ljava.lang.String;', Ars, Ac),
    jpl_datums_to_array( [name,value], Ah),
    jpl_new( 'javax.swing.JFrame', ['current_prolog_flag'], F),
    jpl_call( F, getContentPane, [], CP),
    jpl_new( 'javax.swing.JTable', [Ac,Ah], T),
    jpl_new( 'javax.swing.JScrollPane', [T], SP),
    jpl_call( CP, add, [SP,'Center'], _),
    jpl_call( F, setSize, [600,400], _),

builds an array of arrays of strings containing the names and values of the current SWI-Prolog "flags", and displays it in a JTable within a ScrollPane within a JFrame:

In addition to JPL API calls, this code calls jpl_datums_to_array/2, a utility which converts any list of valid representations of Java values (or objects) into a new Java array, whose base type is the most specialised type of which all list members are instances, and which is defined thus:

    jpl_datums_to_array( Ds, A) :-
        ground( Ds),
        jpl_datums_to_most_specific_common_ancestor_type( Ds, T),
        jpl_new( array(T), Ds, A).

Having found the "most specific common ancestor type" (my phrase :-), a new array of this type is created, whose elements are initialised to the successive members of the list of datums.

This illustrates another mode of operation of jpl_new/3:

    jpl_new( +ArrayType, +InitialValues, -ArrayRef)

Don't forget the possibility of writing and manipulating new Java classes to serve your Prolog applications: this interface is not designed to make Java programming redundant :-)

 jpl_new( +X, +Argz, -V) :-

X can be:

a suitable type i.e. any class(_,_), array(_) or primitive type (e.g. byte but not void) an atomic classname e.g. 'java.lang.String' e.g. 'Ljava.lang.String;' (a redundant but legitimate form) an atomic descriptor e.g. '[I' a class object i.e. an object whose type is class([java,lang],['Class'])

if X denotes a primitive type and Argz is castable to a value of that type, then V is that value (a pointless mode of operation, but somehow complete...)

if X denotes an array type and Argz is a non-negative integer, then V is a new array of that many elements, initialised to the appropriate default value

if X denotes an array type and Argz is a list of datums, each of which is (independently) castable to the array element type, then V is a new array of as many elements as Argz has members, initialised to the results of casting the respective members of Argz

if X denotes a non-array object type and Argz is a list of datums, then V is the result of an invocation of that type's most specifically-typed constructor to whose respective parameters the members of Argz are assignable

 jpl_call( +X, +Method, +Args, -R) :-

X can be:

a type, class object or classname (for static methods of the denoted class, or for static or instance methods of java.lang.Class)

a class instance or array (for static or instance methods)

Method can be:

an atomic method name (if this name is ambiguous, as a result of method overloading, then it will be resolved by considering the types of Args, as far as they can be inferred)

an integral method index (untested: for static overload resolution)

a methodID/1 structure (ditto)

Args must be

a proper list (possibly empty) of ground arguments

Finally, an attempt will be made to unify R with the returned result.

 jpl_set( +X, +Field, +V) :-

basically, sets the Fspec-th field of object X to value V

X can be:

a class object, a classname, or an (object or array) type (for static fields, or java.lang.Class fields)

a class instance (for non-static fields)

an array (for indexed element or subrange assignment)

but not a string (no fields to retrieve)

Field can be:

an atomic field name (overloading will be resolved dynamically, by considering the inferred type of V)

an integral field index (static resolution: not tried yet)

a fieldID/1 (static resolution: not tried yet)

a variable (field names, or array indices, are generated)(?!)

an array index I (X must be an array object: X[I] is assigned V)

a pair I-J of integers (J can be a variable) (X must be an array object, V must be a list of values: X[I-J] will be assigned V)

V must be ground (although one day we may pass variables to JPL?!)

 jpl_get( +X, +Field, -V) :-

X can be:

a class object, a classname, or an (object or array) type (for static fields, or java.lang.Class fields)

a class instance (for non-static fields)

an array (for the 'length' pseudo field, or for indexed element retrieval)

but not a String (clashes with classname; anyway, java.lang.String has no fields to retrieve)

Field can be

an atomic field name

or an integral field index (these are a secret :-)

or a fieldID/1 (not for general consumption :-)

or an integral array index (high-bound checking is done by JVM, maybe throwing an exception)

or a variable (field names, or array indices, are generated)

or a pair I-J of integers or variables (array subranges are generated) (relational or what?!)

Immediately before jpl_get/4 returns, an attempt will be made to unify V with the internally computed result.

Exceptions thrown by Java

Uncaught exceptions thrown by the JVM in the course of handling a JPL 3.x Prolog API call are mapped onto Standard Prolog exceptions, e.g.

    jpl_new( 'java.util.Date', [yesterday], D)
Raises the Prolog exception
    java_exception('java.lang.IllegalArgumentException', @'J#0008408972')

because, as the exception suggests, yesterday is not a valid constructor argument.

Java exceptions are always returned as Prolog exceptions with this structure:

    java_exception( classname, reference_to_exception_object)