Call-out Employees Table

We further give an example where Java will be non-deterministically called from the Prolog interpreter. We want to define a Java foreign predicate that returns some employees. We approach the problem by first defining a vector with the employees. We use a static variable and a static initialization method as follows:

    static Vector<String> employees = new Vector<String>();

static {
  employees.addElement("bundy");
  employees.addElement("canby");
  employees.addElement("ozias");
  employees.addElement("watson");
}

The vector field will be used to enumerate the employees. We want the Java foreign predicate to become a predicate employee/1. We will use the same name for the Java method. The method will have a String return type. We will also see a call-out argument, since the Java for-eign predicate will be non-deterministic:

    public static String employee(CallOut co) {

We now proceed in designing our Java foreign predicate. Since the Java foreign predicate will be non-deterministic it will also need a choice point. We can define our own data structure for the choice point. We can use the getFirst() method from the call-out object to check whether our Java method was called for the first time.

If the Java method is called for the first time we have to create the choice point. We do so in that we derive an enumeration from the vector field. And we can further use the methods setData() and getData() to set and retrieve the choice point. When the Java method was not called for the first time we will reuse the existing choice point:

        Enumeration<String> elements;
if (co.getFirst()) {
elements = employees.elements();
co.setData(elements);
} else {
elements = (Enumeration<String>) co.getData();
}

Whenever there are more elements our Java method should succeed with the next element. We can simply return the element itself to indicate success. But since the predicate is non-deterministic we cannot only return the element. We must also set the retry flag so as to inform the interpreter that our Java method should be retried.

        if (elements.hasMoreElements()) {
co.setRetry(true);
return elements.nextElement();

There is no need to announce a special barrier handling. The default barrier handling is sufficient. It will automatically undo the unification upon redo. Our code does also not temporarily create some variables or perform some unification. Therefore we also don’t need some manual mark or release. Now if there are no more elements our Java method should fail. We can return null to indicate failure:

        } else {
return null;
]
}

Assume this time that the method is part of a Java class OutTable. We proceed again by pro-grammatically registering the Java foreign predicate and placing the corresponding code in the main method of the Java class OutTable itself. Note that the extra argument CallOut is neces-sary to deal with our non-deterministic Java foreign predicate:

    Object foreignGoal = inter.parseTerm("foreign(employee/1, " +
"'example03.OutTable', employee('CallOut'))");
inter.iterator(foreignGoal).next().close();

The method signature does not show the return type. This type is inquired by the interpreter at runtime from the resolved Java method. After we have registered the Java foreign predicate, we can invoke it as we already did for the predicate of the second example. The corresponding code looks as follows:

    TermVar employeeVar = new TermVar();
TermCompound employeeGoal = new TermCompound("employee", employeeVar);

Writer wr = (Writer)
inter.getProperty(ToolkitLibrary.PROP_SYS_CUR_OUTPUT);
CallIn callin = inter.iterator(employeeGoal);
while (callin.hasNext()) {
callin.next();
wr.write(inter.unparseTerm(0, employeeVar));
wr.write('\n');
wr.flush();
}

We can also run this example similar as we have done in the first example by an appropriate command line. The following line will be displayed on the standard output as a result:

bundy
canby
ozias
watson

Also here we can use the development environment instead of the runtime library to execute the example. For this purpose we put again the Java foreign predicate registration and the Java foreign predicate invocation into a Prolog text. It will be stored in the file ‘outtable.p’:

:- foreign(employee/1, ''example03.OutTable', employee('CallOut')).

:- employee(X), write(X), nl, fail; true.

After having configured the path or library of the Java class OutTable we can run the following query from the development environment:

?- consult('tableout.p').

We will receive the following result:

bundy
canby
ozias
watson
Yes

Kommentare