Adam Lally wrote:
On 1/4/07, Thilo Goetz <[EMAIL PROTECTED]> wrote:
I would propose the following changes:

- Leave createFeaturePath() and friends at the CAS.  These methods
require/return CAS-specific data structures and don't need to be
accessible anywhere else.


Marshall had already moved these to CommonCas, so he must have thought
they were usable from JCas?  I'll let him comment on that, it's
orthogonal to the CAS/view interface split I think.

The reason they were put into the CommonCas is because I thought users of
either the CAS or JCas interfaces might want to use createFeaturePath. These are used for filtered iterators, I think. Here's an example, from a parser that produces various kinds of "nodes", done in JCas; it uses the older APIs, so has to get a
CAS ref at the start:

CAS cas = jcas.getCas(); // filter the iterator to only return top parse frames // Top parse frames have Sgc.POS.incomplete or Sgc.POS.Top as slot-filled type

       //    Start by getting the constraint factory from the CAS.
       ConstraintFactory cf = cas.getConstraintFactory();
       // Create empty path.
       FeaturePath path = cas.createFeaturePath();

       // Add XsgParse slotName feature to path, creating one-element path.
       path.addFeature(
((XsgParse_Type) jcas.getType(XsgParse.typeIndexID)).casFeat_slotName);

       FSStringConstraint slotIsTop = cf.createStringConstraint();
       FSStringConstraint slotIsIncomplete = cf.createStringConstraint();

       slotIsTop.equals(Sgc.POS.top.toString());
       slotIsIncomplete.equals(Sgc.POS.incomplete.toString());

       FSMatchConstraint embeddedTop = cf.embedConstraint(path, slotIsTop);
FSMatchConstraint embeddedInc = cf.embedConstraint(path, slotIsIncomplete);

       FSMatchConstraint topOrInc = cf.or(embeddedTop, embeddedInc);

       // Create a filtered iterator from some annotation iterator.
       return cas
           .createFilteredIterator(
               jcas.getJFSIndexRepository()
                   .getAnnotationIndex(XsgParse.type)
                   .iterator(),
               topOrInc);

There is one kludgy part - getting the "Feature" value from the JCas structures.



- On CasView, remove getJCasView() and getLowLevelCasView().  Those
should be accessed from the JCas and LowLevelCas, respectively.

- Similarly, on JCasView, remove getCasView() and getLowLevelCasView().


OK, I think I agree that might be cleaner.  If we do this then we
really have to add getView APIs to LowLevelCas, otherwise there would
be no way at all to access a low-level interface to a view.


- On the JCas interface, can we remove some of the APIs and just make
them available on the impl object?  I'm thinking of things like
putJfsFromCaddr(int, FeatureStructure) and getType(int).


I think these may be called from JCas cover-classes, in which case I
think they need to be on the interface.  Marshall?

The "putJfsFromCaddr" is called from the JCas cover-classes.  It could
be in impl, though - we could change JCasGen and the migration tool.

The getType(int) is used by users - should remain in the API.  This method
gives JCas users efficient access to the Type object corresponding to a
JCas cover class:  getType(MyJCasCoverClass.type);
the Type object is needed by some APIs.



Another open issue is the createFS method and variants.  I have left
them off of the view API for now in deference to Thilo's "no
convenience methods" suggestion, but I'm still a little unsure.
Basically the situation now is if a user has a view handle and wants
to create an FS they need to do view.getCAS().createFS(...);

The upside is that it helps make it clear that FS are owned by the
CAS, not the view.  The downside is that it may annoy users to have to
put in the getCAS call all the time.  Also is it inconsistent that
view.createAnnotation(...) *is* on the view API?  This was done so
that users can create annotations that refer to the Sofa for the view
they're operating on.

What do others think?

Users have already complained about this kind of thing.  They have said
they don't want to have to follow dereferencing chains to reach an object that finally has a method they need - they want the framework to do that for them.

I don't think we have compelling enough reasons to require users to
a) getViews from CASes, and also then b) dereference from the View back to CASes to do
the real work of creating / accessing / updating Feature Structures.

I think that the APIs for users should focus on what the users need to get done, with an eye toward
economizing on the verbose-ness of the resulting code (sorry - I mean to
say, the user's code should be very "readable" - and having dereferencing chains makes
it less readable, I think).

-Marshall

Reply via email to