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)