Updated 7/2016

This page discusses ideas for supporting JCas customization, and multiple customizations possible due to PEAR classpath isolation with "customized" JCas cover classes.

The problem arises because with the Feature Structure data contained solely in a particular instance of a Java class, there must be an approach to have the differing contexts (different PEAR definitions of the customization of the JCas cover class) share and update this data.  An instance produced from a PEAR needs to be able to be used outside of the PEAR, and vice-versa. 

The current thinking for PEARs is to support a hierarchy of approaches, from completely general (but slower) where FSs are serialized / deserialized when crossing the PEAR boundary, to optimized approaches attempting to avoid the serialization / deserialization overhead.

A catalog of customizations observed in JCas implementations

Customizations are used for many things; here are some gleaned from some actual use cases:

(lightbulb)Starting with customization, adding any merged type features

The merged type system (including PEARs) represents the common needed JCas cover class's fields and getters and setters.  Merge this with any customization code while loading the cover class. 

Implementation ideas here in diagram form: UV3 JCasClassLoading.

Handling multiple customizations of a UIMA Cas Type

Multiple customizations can arise when two or more independently developed components both implement customized JCas classes.  This may happen in two ways:

  1. An aggregate or custom application includes two (or more) components, and the classpath is set up in such a way that each component's customizations (which would be identically named Java Classes) are in the classpath.  In this case, one of the customizations is ahead of the other in the classpath and will "win" in the class lookup.
  2. An aggregate or custom application includes two (or more) components, one (or more) of which is a PEAR, and a type with multiple customizations occurs within the PEAR and outside of the PEAR.  PEARs have their own classpath, and are intended to have their classpath override the containing aggregate's classpath.  The "effective" classpath is switched when the PEAR component is entered, and switched back upon exit.

Alternatives for handling Aggregate case (1):

Alternatives for handling PEAR case (2):

 

 

(question)A single common system-generated implementation + an augmentation mechanism for (multiple) customizations

At the high abstraction level: UIMA is providing

This idea is to separate the concepts of customizing the JCas cover classes as follows:

This may be very hard to implement. There are examples of new methods being added in a customization; these methods would need to be called from a base instance (don't know how to do that).  Also, customization may add fields.

(question)Copy some Feature Structures into / out of the PEAR

A PEAR represents a packaging and a classpath isolation.  The PEAR may (for some of the shared types) have a different definition of the JCas cover class.  If the difference is simply it has fewer features than the pipeline's fully merged definition, then it can use the main pipeline's definition (it will have extra methods, but those would just go unused).  If it has a different implementation beyond that, then a lazy (when needed) copying of the main pipeline's Feature Structure into the Pear's instantiation would be done.  Likewise, on exit from the PEAR, if the type is mentioned as being an output, and it was "copied" in, then it would be copied out.

Needs:

(question)Merge all the custom definitions into one and use that everywhere.

Do some kind of "merge" operation among all definitions of JCas cover classes including those in contained PEARs, and use that one merged definition everywhere.  

(thumbs down)Keep the system-generated code in one class, and use a different wrapping class for the customization

Split apart the system-generated (from the merged type system) JCas cover class and user customization, into different classes.  The user customization class would wrap the system-generated one, and create both; all value setting/getting would be via forwarding methods.  

Advantages: 

Disadvantages: 

Nesting: An "outermost" pipeline can nest 1 or more PEARs, which, in turn may nest one or more inner PEARs, etc.  (Type merging is applied to all the type definitions, including those in the PEAR). Each inner PEAR JCas customization would be a 1-level wrapper of the system-generated class from the outer-most pipeline (not on its container if it was a PEAR).

Naming: JCas cover classes are named to match their UIMA type name.  This enables users to write "new MyType()" where MyType is the UIMA type name.  

(thumbs down)Keep the system-generated code in one class, and do the customization in a class "extension"

Another way to split apart the system-generated from the customization: have the customization "extend" rather than wrap the system-generated one.

Advantages

Disadvantages