You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@uima.apache.org by "Marshall Schor (Jira)" <de...@uima.apache.org> on 2019/12/02 20:37:00 UTC

[jira] [Commented] (UIMA-6153) select.covering should bind to AnnotationFS

    [ https://issues.apache.org/jira/browse/UIMA-6153?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16986348#comment-16986348 ] 

Marshall Schor commented on UIMA-6153:
--------------------------------------

I think we could do something like Richard suggests.  Unfortunately, you can't have two classes in Java with the same name and different generic args, so we'd have to have something like:
 * SelectFSs<T extends FeatureStructure>   (as currently exists)
 * SelectAnnotations<T extends Annotation> (new)
 * plus 2 new associated "impl" classes.

Both the CAS and JCas interfaces have 5 different methods for invoking select. 

The methods in SelectFSs which "imply" annotations (such as "at(begin, end)"), can be changed to return a new instance of SelectAnnotations.  Unfortunately, at the time of conversion (to a lower upper-generic-bound), the specific passed in bound is lost.  So if you have Token extends Annotation, and write:
{code:java}
 Token c = jcas.select(Token.class).at(2, 3).get(0);{code}
 this currently works (because the Token.class arg sets the upper bound for "T" to be Token).

But after changing "at" in SelectFSs to convert to a SelectAnnotations, returning an instance of
{code:java}
<U extends Annotation> SelectAnnotations<U>{code}
the passed-in compile-time "Token.class" upper bound of "Token" is unfortunately replaced with "Annotation".  This causes this issue (using myTokenType, so the compile time doesn't know the type)
{code:java}
Token c = jcas.selectFSs(Token.class).at(2, 3).get(0); 
    // error can't cast Annotation to Token 
Token c = jcas.selectAnnotations(myTokenType).at(2, 3).get(0); 
    // error can't cast Annotation to Token
{code}
This can be avoided by writing any of these forms
{code:java}
Token c = jcas.selectAnnotation(Token.class).at(2,3).get(0);   //or
Token c = jcas.selectFSs(Token.class).<Token>at(2,3).get(0);  
       // set the upper bound at the some point  after the impl converts to Annotation
       // or
Token c = (Token) jcas.selectFSs(Token.class).at(2,3).get(0);  // cast the result
{code}
Keeping the single selectFSs APIs as they are, and requiring the user to write a generic arg spec at the first point in the builder-chain where its needed (but it can be written earlier in the chain if wanted) seems a better solution to me.  Any of these forms do work:
{code:java}
Token c = jcas.select(Token.class).at(2, 3).get(0);   // specify by passing in the class
   // these next specify the upper bound at compile-time, at any point in the chain.
Token c = jcas.select<Token>(myTypeForTokenClass).at(2, 3).get(0); 
Token c = jcas.select(myTypeForTokenClass).<Token>at(2, 3).get(0);
Token c = jcas.select(myTypeForTokenClass).at(2, 3).<Token>get(0);{code}
I'm currently thinking the best way forward is to keep the API simple (by having only one kind of select), and "educating" with more examples etc. the use of the generic type spec where needed in the chain if it can't be inferred.

> select.covering should bind to AnnotationFS
> -------------------------------------------
>
>                 Key: UIMA-6153
>                 URL: https://issues.apache.org/jira/browse/UIMA-6153
>             Project: UIMA
>          Issue Type: Improvement
>          Components: UIMA
>    Affects Versions: 3.1.1SDK
>            Reporter: Richard Eckart de Castilho
>            Priority: Major
>
> The following code does not compile because select.covering() uses TOP instead of AnnotationFS as the generic type. Consequently, getBegin() and getEnd() are not available on the "s" used in the filter expressions. But since covering() only makes sense for annotations, binding the generic type to TOP doesn't seem to make much sense:
> {{return aCas.select(getType(aCas, Sentence.class)).covering(aBegin1, aBegin1)}}
> {{    .filter(s -> s.getBegin() <= aBegin1 && aBegin1 < s.getEnd())}}
> {{    .filter(s -> s.getBegin() <= aBegin2 && aBegin2 < s.getEnd()).findFirst()}}
> {{    .isPresent();}}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)