{'fraction_non_alphanumeric': 0.030551089022072795, 'fraction_numerical': 0.00847829264727379, 'mean_word_length': 4.945538818076478, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 0, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Customisable Handling of Java References in Prolog Programs

Integration techniques for combining programs written in distinct language paradigms facilitate the implementation of specialised modules in the best language for their task. In the case of Java-Prolog integration, a known problem is the proper representation of references to Java objects on the Prolog side. To solve it adequately, multiple dimensions should be considered, including reference representation, opacity of the representation, identity preservation, reference life span, and scope of the inter-language conversion policies. This paper presents an approach that addresses all these dimensions, generalising and building on existing representation patterns of foreign references in Prolog, and taking inspiration from similar inter-language representation techniques found in other domains. Our approach maximises portability by making few assumptions about the Prolog engine interacting with Java (e.g., embedded or executed as an external process). We validate our work by extending JPC, an open-source integration library, with features supporting our approach. Our JPC library is currently compatible with three different open source Prolog engines (SWI, YAP} and XSB) by means of drivers. To appear in Theory and Practice of Logic Programming (TPLP).


Introduction
Writing program modules in the language best suited for their task can greatly facilitate their implementation (Mernik et al. 2005). However, integrating modules written in different languages is not trivial when such languages belong to different paradigms (Gybels 2003). This is especially the case for Prolog programs integrated with an object-oriented language such as Java (Denti et al. 2005). One of the main problems of this integration is the proper representation of foreign language artefacts in the logic language, such that they can be conveniently manipulated and interpreted (Gybels 2003).
The scope of this work concerns a portable approach to simplify the management and representation of Java object references in Prolog. Studying existing solutions to this problem in Prolog, similar logic languages (e.g., Soul (Roover et al. 2011)) and even inter-language conversion libraries in other domains (e.g., Google's Gson library (Google Inc. 2012)), we have identified the following dimensions to be tackled: 1) reference representation; 2) opacity of the representation; 3) identity preservation; 4) reference life span and 5) scope of the inter-language conversion policies. To maximise portability, our approach does not make any simplifying assumption regarding the architecture of the Prolog engine (e.g., such as it being embedded in the JVM). We validate our work by extending our Java Prolog Connectivity (JPC) 1 integration library (Castro et al. 2013) with customisable support for managing Java references in Prolog.
This paper is structured as follows. Section 2 discusses the main Java reference representation issues in Prolog. Section 3 presents an overview of JPC's architecture. JPC's approach for custom management of Java references in Prolog is discussed in section 4. Section 5 discusses related work. Section 6 summarizes our conclusions and future work.

The Problem of Representing Java References in Prolog
In this section, we identify the different dimensions to be taken into consideration when looking at the problem of representing Java references in Prolog (figure 1). These dimensions have been extracted and generalised from existing solutions to this problem both in Prolog and other inter-language representation domains.

Reference Representation
A first important dimension is how Java objects are represented on the logic side. Several integration libraries allow to reify Java objects in Prolog using a symbolic term representation (Singleton et al. 2004;Carlsson et al. 1995;Calejo 2004). As show in figure 1, such approach has the advantage of not relying on any specific Prolog engine architecture. Alternatively, Prolog implementations running in the JVM may support the storage of direct object references (e.g., Jinni (Tarau 2004) and LeanProlog (Tarau 2011)). An advantage of this representation scheme is that there are no performance penalties associated to the marshalling/unmarshalling of Java objects to/from the Prolog engine.

Opacity of the Representation
A second important dimension is the degree of opacity of the representation (i.e., the degree of data exposed). For symbolic term representations (A), frequently a fine-grained reification of the internal object structure (i.e., a white box representation) is desired. For example, JTransformer (Kniesel et al. 2007) allows to reason over the structure of terms reifying objects modelling a Java abstract syntax tree. However, if inspecting the object's structure on the Prolog side is not required, having an opaque reference (i.e., a black box representation) to the corresponding Java object is preferable (e.g., an opaque reference to a GUI component on the Java side). In those cases, an automatic mechanism to generate opaque term representations of Java objects is desirable.
When the Prolog engine is embedded in a JVM, a more direct kind of reference to Java objects can be established (B). In the simplest case, the object reference can be considered and unified as a special constant term. In spite of the more direct mapping (no automated mapping to generate the reference is required; the term wraps the object 'as is'), this case is conceptually equivalent to mapping the object reference to an opaque term representation. But we may want to combine the best of both worlds and have direct references to the actual Java objects, while still allowing Prolog programs to reason over the internal structure of such objects. Approaches such as Soul (Roover et al. 2011) have achieved this through the mechanism of open unification (Brichau et al. 2007). This approach consists in allowing the programmer to customise not the term representation of an object, but rather its unification mechanism. In a nutshell, the unification mechanism is opened up so that Java objects are not regarded as constants but can be unified with structured logic terms of the right form.

Object Identity Preservation
For logic engines running in the JVM (D) object references are preserved automatically since the term wraps the object 'as is'. For engines not embedded in the JVM, a programmer needs to decide if an object reified as a term should preserve its identity when the term is translated back to a Java object (C). In many situations, it is not important to preserve such identity (e.g., instances of String) and a different reference, considered equivalent to the original object (e.g., by means of the equals method), is acceptable. However, in certain cases, keeping track of the original reference is required to guarantee the expected behaviour of the program (e.g., if the reference points to a GUI component). Furthermore, passing around symbolic representations of object references is often more efficient than marshalling and unmarshalling large Java objects. Note that the need for preserving the original object identity is orthogonal to the required opacity of the representation. I.e., independently if the reference should be preserved or not, the programmer should still be able to decide on the best representation of the object on the Prolog side.

Reference Life Span
A fourth dimension is the life span of Prolog references to Java objects. For a symbolic term representation, a programmer should decide on a mechanism for delimiting the life span of a mapping between a Java reference and a Prolog term (E). This mechanism can be explicit (e.g., an API allowing to request to 'forget' a mapping) or rely on JVM garbage collection mechanisms. An explicit mechanism enables a fine-grained control over the life span of a reference. For example, a symbolic term representation of an object that is not explicitly referenced in a program (i.e., normally to be scheduled for garbage collection) can still remain valid until explicitly discarded. Alternatively, a reference life span may be automatically delimited by the JVM garbage-collection mechanism (e.g., a reference to the application main window). For an object reference representation (F), the programmer may want to keep the reference alive as long as it is present in the Prolog database (i.e., a strong reference). However, in certain scenarios a Java reference stored in Prolog should not prevent it from being garbage collected (e.g., the reference points to a disposed GUI component). In that case, the reference should be invalidated when it is reclaimed by the garbage collector. A programmer may also want to define customisable cleaning tasks to be automatically executed when a reference is garbage collected. For example, clauses containing dead references may be automatically retracted from the Prolog database to avoid unexpected behaviours (e.g., null pointer exceptions). Furthermore, references that may be reclaimed by the garbage collector should be classified according to the Java (garbage-collected) reference types: Weak for eagerly collected references (discarded at the next garbage collection cycle) and Soft for references not aggressively reclaimed (only collected when the memory is tight). 2

Scope of the Inter-Language Conversion Policies
We claim that it is useful for a programmer to be able to choose different reference management policies in different parts of the program. To achieve that, it is needed a simple mechanism for scoping and encapsulating the best reference handling policy for certain objects. Besides greater flexibility, this facilitates performance tuning and testing (e.g., generating mocking representations of references). Next, we will introduce the architecture of a library that supports a customisable management of all these dimensions.

Architecture
JPC is an integration library supporting the development of hybrid Java-Prolog programs. It provides different levels of abstractions, simplifying the implementation of common inter-operability tasks. To set the ground for discussing the JPC features for Java reference management in Prolog, this section overviews its main components (figure 2).

Prolog VM Abstraction
Several integration libraries rely on the notion of a Prolog engine as a convenient abstraction for interacting with a Prolog virtual machine from Java (Tarau 2004;Rho et al. 2004;Calejo 2004). In JPC, a programmer interacts with a Prolog engine abstraction that communicates with concrete Prolog engines using drivers. With portability in mind, when modelling such an abstract Prolog engine we tried to find a compromise between (1) offering convenient features facilitating the interaction from Java programs and (2) not assuming a specific implementation architecture of the underlying Prolog engine. Our Prolog engine abstraction provides a general purpose API for interacting with Prolog. However, as illustrated in section 4, JPC also supplies a higher level API that simplifies certain tasks (e.g., inter-language conversions). JPC defines a set of classes reifying Prolog data types: Term, Atom, Compound, IntegerTerm, FloatTerm, Var, JRef (a Java reference term; a special kind of term wrapping a Java reference).

Embedded Prolog Database
JPC uses an embedded Prolog database running on the JVM and supporting the storage of Java object references in addition to standard Prolog terms. Several JPC interoper-

Symbolic Representation
To illustrate the properties of symbolic references (identified by the first row of figure 1), we start by defining a Person class (listing 1) declaring name as its only instance variable. The PersonConverter class (listing 2) defines how instances of class Person are translated to a Prolog compound term (lines 5-7) and back (lines 8-10). According to our classification in section 2.2, the term reification of a person, according to this converter, corresponds to a white box representation since it exposes its internal data.  (1)).getName()); 10 } 11 } Listing 2. The PersonConverter class Listing 3 illustrates a white box term representation of a Java object, without object identity preservation (the first three lines are common to most examples; we will not repeat them). A central artefact in our approach is a conversion context, instantiated in line 4 using a builder class and configured with the PersonConverter converter. With this context we obtain the conversion of a person in line 5 (person(mary)). Next, we assert the fact student(person(mary)) (line 6). A student(A) goal is instantiated in line 7 passing the context defined before. A person is queried in line 8 using a deterministic query. The selectObject() method adapts each solution to the query as an object whose term reification is given as a string. This adaptation corresponds to the conversion as a Java object of the term that has been bound to the Person variable in the solution. Lines 9 and 10 verify that the queried and the original persons are equal, although with different identities.

Listing 3. White Box without Identity Preservation
Listing 4 illustrates the mapping of a reference to a term representation (line 2) in the scope of a context. The newRefTerm() method associates a person reference (first argument) to an arbitrary (compound) term representation (second argument). In this example, the term corresponds to the term conversion of the reference according to a given conversion context (obtained by the toTerm() method of the context instance). We verify that this time the queried person corresponds to the original person reference in line 6.

Listing 4. White Box and Identity Preservation
An example of a black box representation is shown in listing 5. Here, we assert a term of the form student(serialisation), where the compound argument corresponds to the term representation of the serialisation of a Person instance. No converter is passed to the query in line 2. This is because the default conversion context (employed by the query if no context is explicitly passed) includes a converter able to deserialize a Java object from the term representation of its serialisation. Finally, we verify that our queried person is equal to the original person (line 4) although having different identities (line 5).

Listing 5. Black Box without Identity Preservation
A programmer can also associate an automatically generated term to a reference. An example is given in listing 6. This time we invoke the method newRefTerm() passing as only argument the reference to reify as a term (line 2). A (black box) term representation is generated behind the curtains. Our library guarantees that such generated term representations are identical for the same object even across different contexts.

Listing 6. Black Box and Identity Preservation
As discussed in section 2.4, a programmer should also be able to control the life span of term-reference mappings. Listing 7 shows an example. We use the newRefTerm() method (line 2) to associate a reference to its (context dependent) term reification. But afterwards we delete this association using the forgetRefTerm() method (line 5). Thus, although the queried person is equal to the original person (line 7) since the term is translated according to the conversion context (line 1), they do not have the same identity (line 8) as the association between the term and the original reference was eliminated.

Listing 7. Explicit Management of Associations Life Span
A programmer can also rely on the Java garbage collection mechanism for delimiting the life span of an association as shown in listing 8. The newWeakRefTerm() method (line 2) is equivalent to the newRefTerm() method discussed earlier. But in this case the association between a term and a reference persists as long as the reference is not reclaimed in the next garbage collection cycle. To prove it, we assign null to the only variable keeping a reference to the person (line 4) and give a hint to the garbage collector to start a cycle (line 5). Note that the query is not instantiated with a conversion context (line 7). Thus, an exception is raised when we try to convert the term (bound to the variable Person) to an object as no converter is found and no reference is associated to such term. Our framework also provides the newSoftRefTerm() method with similar semantics than newWeakRefTerm(), with the only difference that an association between a term and a reference may persist some time after a garbage collection cycle, and will be deleted only if the memory gets tight.

Object Reference Representation
This section focuses on the properties of object references (identified by the second row of figure 1). Although our library currently only has drivers for non-embedded Prolog engines, as a proof of concept we implement the examples in this section using the JPC embedded Prolog database described in section 3.1. With the exception of open unification, all the other properties are supported by our implementation.
We start with an example of constant unification of references in listing 9. As mentioned in section 3.1, a JPCJRef term wrapps an object reference. In our current version, they are unified as constants (i.e., unifying tow JRef terms succeeds if their referred objects are equal). In line 1 we assert that mary (wrapped in a JRef term) is a student. In line 2 we query if a different person object with the same name is a student, which succeeds.
Listing 9. Constant Unification of JRef terms Thanks to our embedded Prolog database, the identity of a reference is trivially preserved. To illustrate this, we execute a deterministic query (line 3) with goal student(X). We verify that the obtained referent has the same identity as mary in line 5.
Listing 10 shows how to create JRef instances that may be garbage collected. We first create two objects equal to mary and assert them, using two kind of references: strong (line 3) and weak (line 4). When we query for students unifying with mary (line 5) using a strong reference, we get two results instead of one. This is because the unification semantics of JRef terms evaluates the referents, not the actual JRef term wrapper. Afterwards we assign to null the variable person2 (line 6) and give a hint to the garbage collector to execute a cycle (line 7). Since the referent of the JRef term asserted in line 4 has been invalidated, the number of students unifying with mary is now only 1 (line 8). Note that weak or soft references should be used with care: they may require non-monotonic reasoning as the referent of a JRef term may be invalidated during the query execution.

Related Work
Most related work has already been overviewed in sections 2 and 3.1 so we do not repeat it here. InterProlog inspired the serialisation mechanism illustrated in listing 5. It provides a more structured representation of a serialised object on the Prolog side using a definite clause grammar. Currently we represent serialised bytes as an atom using a raw base-64 encoding. InterProlog has limited support, however, for customising the reification as a term of arbitrary Java objects (even not serialisable ones) as in our approach. Concerning our mechanisms for custom two-way conversions between interlanguage artefacts, this was inspired by Google's Gson library, which aims to provide a high-level tool for conversions between Java objects and their JSON representation.

Conclusions and Future Work
This work discusses different dimensions that should be taken into consideration when dealing with Java references in Prolog programs. These dimensions have been extracted from many sources, including our own experience, a study of existing approaches, and even existing solutions in other domains. At the moment, JPC does not implement a mechanism for interacting with Java from the Prolog side. In line with our portability goal, we plan to implement our Prolog side API using Logtalk (Moura 2003), a portable object-oriented layer for Prolog. As in the current Java side API, we expect to prototype a first version by reusing existing bridge libraries. We will also continue improving our embedded Prolog database so that it can be released as a stand-alone embedded Prolog engine. We hope that our work will benefit not only implementors of Java-Prolog integration libraries, but also integrators of similar object-oriented and logic languages.