Ofer Bronstein created UIMA-3724:
------------------------------------

             Summary: Adding (J)CasUtil.selectCoveredSingle()
                 Key: UIMA-3724
                 URL: https://issues.apache.org/jira/browse/UIMA-3724
             Project: UIMA
          Issue Type: Improvement
          Components: uimaFIT
            Reporter: Ofer Bronstein
            Priority: Minor


JCasUtil (and its equivalent CASUtil) have two very useful methods:

- {{selectSingle(JCas jCas, Class<T> type)}}, retrieving all T type annotations 
from the CAS, making sure only one exists, and returning it
- {{selectCovered(JCas jCas, final Class<T> type, AnnotationFS 
coveringAnnotation)}}, retrieving all T type annotations from the CAS, that 
exist in the span defined by the covering annotation.

My request is to add a {{selectCoveredSingle}} method (I already implemented 
and tested, written below). It would retrieve all T type annotation in the span 
of the covering annotation, make sure there is only one, and return it.
The uses for such a method would be really common, as this assists in 
performing something very basic in UIMA - once you have some annotation, you 
want to retrieve other information on it, and if it is a small unit, then you 
know in advance that many types of information should only appear once for that 
annotation. Otherwise, it's an error.
For instance, say I have linguistically annotated text, and I hold some 
intersting annotation of a Token. Then I want to find out what is its Part Of 
Speech. Then I would simply call: {{selectCoveredSingle(jcas, 
PartOfSpeech.class, token)}}, and get exactly one PartOfSpeech annotation as I 
expected. If there is none or more then one, an exception is thrown.

One could also use a method like {{selectCoveredSingleOptional}} (not 
implemented yet), that does exactly the same, but returns null when no such 
annotation exists, instead of throwing an exception. This makes sense when a 
token can have some optional attribute. In linguistics, it could be when a 
Token may be a NamedEntity, but not necessarily.

the implementation is made out of two methods - the first should be in 
JCasUtil, the second should be in CASUtil.
===
Implementation:
===

        /**
         * Get the annotation of the given annotation type constrained by a 
'covering' annotation.
         * Iterates over all annotations of the given type to find the covered 
annotations.
         * Does not use subiterators.
         *
         * @param <T>
         *            the JCas type.
         * @param jCas
         *            a JCas containing the annotation.
         * @param type
         *            a UIMA type.
         * @param coveringAnnotation
         *            the covering annotation.
         * @return the single instance of the given type.
         * @throws IllegalArgumentException if not exactly one instance if the 
given type is present
         *                 under the covering annotation.
         * @see Subiterator
         * 
         * @author Ofer Bronstein
         * @since April 2014
         */
        @SuppressWarnings("unchecked")
        public static <T extends Annotation> T selectCoveredSingle(JCas jCas, 
final Class<T> type,
                        AnnotationFS coveringAnnotation) {
                return (T) selectCoveredSingle(jCas.getCas(), 
JCasUtil.getType(jCas, type),
                                coveringAnnotation);
        }

        /**
         * Get the annotation of the given annotation type constrained by a 
'covering' annotation.
         * Iterates over all annotations of the given type to find the covered 
annotations.
         * Does not use subiterators.
         *
         * @param cas
         *            a cas containing the annotation.
         * @param type
         *            a UIMA type.
         * @param coveringAnnotation
         *            the covering annotation.
         * @return the single instance of the given type.
         * @throws IllegalArgumentException if not exactly one instance if the 
given type is present
         *                 under the covering annotation.
         * @see Subiterator
         * 
         * @author Ofer Bronstein
         * @since April 2014
         */
        public static AnnotationFS selectCoveredSingle(CAS cas, Type type,
                        AnnotationFS coveringAnnotation) {
                List<AnnotationFS> annotations = CasUtil.selectCovered(cas, 
type, coveringAnnotation);
                
                if (annotations.isEmpty()) {
                        throw new IllegalArgumentException("CAS does not 
contain any [" + type.getName() + "]");
                }
                if (annotations.size() > 1)  {
                        throw new IllegalArgumentException("CAS contains more 
than one [" + type.getName()
                                        + "]");
                }
                
                return annotations.get(0);
        }





--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to