Expression Pattern Language (eXPL)

Persistence

Client-side persistence with eXPL requires writing a resource provider with database connectivity and the ability to perform basic read and write operations. The following examples illustrate resource provider design for interacting with Object-Relational Mapping (ORM) implementations, where database tables are mapped to annotated entity classes. Obviously this section is about Java programming, not eXPL per se. A resource provider has the following requirements:

  1. Identify one or more resources by name, each one representing a particular table or view
  2. For each resource, implement one or both of the axiom collection import/export provider methods
  3. For each import/export implemtation, map an entity class to an axiom archetype*
  4. An import method must execute a database query and marshall the result as an axiom collection
  5. An export method must unmarshall each axiom received to an entity object and write it to the database
  6. The provider may need to throttle data traffic to prevent the application appearing to go unresponsive

* An axiom archetype contains metadata about an axiom collection: term names, term sequence order and term types. Resource providers are passed archetypes in order to marshall an unmarshall axioms.

Application Stack

Persistence examples shown here are from the Classy eXPL project - see eXPL Extensions. Each application has a resource provider sitting on top of a framework which creates and populates a test database. The provider is dependent on the framework, so some understanding of the framework is needed to make sense of the code. Note that most of the code is open-source.

Each application consists of a small number of classes which perform persistence operations by calling to the Classy Data library, which in turn calls to the Ormlite Object Relational Mapping (ORM) library which in turns calls to a database driver which ultimately makes native calls to the operating system on which the application is running. Here is a brief description of the application stack on which the resource providers sit:

  1. eXPL Extensions- A package containing helper classes to which common tasks are delegated
  2. Classy Data - A lighweight JPA persistence framework.
  3. Ormlite ORM - An Object-Relational Mapping package, is popular with Android developers and has many supported databases.
  4. Database Driver - Currently only drivers SQLite and H2 are supported by Classy Data
  5. Java Runtime - Java can be installed on all popular operating systems. Java SE Version 7 is the minimum requirement

Persistence Examples

All examples are located in the main java directory of the classy_xpl project tutorial-extensions module. There are 3 tutorial packages numbered 1 to 3:

  1. Application HighCitiesSorted2, given a resource provider to access a database table containing cities with their elevations, selects and sorts cities which are at 5,000 feet or higher.
  2. Application IncreasedAgriculture2, exports to a "Agri20Year" database table a selection of countries which increased the area under agriculture over a 20-year period. In this case, AgriResourceProvider extends EntityResourceProvider in order to implement an export method
  3. Application IncreasedAgriculture3 builds on the 2nd tutorial by importing the agricultural information from an "AgriAreaPercent" database table. In this case, EntityResourceProvider is overriden to use a custom import method - see below for details.

Import

The ResourceProvider interface for importing an axiom collection:

Iterator<Axiom> iterator(AxiomArchetype archetype);

The collection is accessed by an iterator, which allows the resource provider to fetch database rows in batches. The archetype defines term names and positions so entity class fields can be mapped correctly to axiom terms. All resource providers in these examples use eXPL Extensions helper class JpaEntityCollector to delegate required interactions with the underlying JPA framework. It can create a "select all" query for the entity class and provides support for batching.

The resource provider is required to create a NameMap list at the time the import to facilitate mapping of entity class fields to axiom fields. The NameMap list has another, optional role which can be seen in the IncreasedAgriculture3 example. The eXPL program has an empty axiom header in it's resource declaration:

resource agri_area_percent axiom() = "agriculture";

This is a provision where the number of terms may be large and/or possibly unknown, and the resource provider configures the empty archetype. The NameMap list in this case is used to configure the archetype.

Export

The ResourceProvider interface for exporting an axiom returns a listener which the eXPL runtime calls back to every time an axiom is produced as a solution:

AxiomListener getAxiomListener(String axiomName);

The AxiomListener interface:

/** * Handle next axiom loaded by processor
* @param qname Qualified name of axiom
* @param axiom Axiom object
*/
void onNextAxiom(QualifiedName qname, Axiom axiom);

Axiom method getArchetype() is called to get the archetype.