You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2017/03/17 17:50:12 UTC

svn commit: r1787457 - in /uima/uimafit/trunk/uimafit-core/src: main/java/org/apache/uima/fit/util/CasUtil.java main/java/org/apache/uima/fit/util/JCasUtil.java test/java/org/apache/uima/fit/util/JCasUtilTest.java

Author: rec
Date: Fri Mar 17 17:50:11 2017
New Revision: 1787457

URL: http://svn.apache.org/viewvc?rev=1787457&view=rev
Log:
[UIMA-5067] JCasUtil.selectSingleRelative returns wrong object
- Throw an IllegalArgumentException if the anchor type does not subsume the selected type and position is 0
- Added unit tests to for both cases (subsumed/not subsumed)
- Document new behavior
- Renamed arguments (cosmetic change)


Modified:
    uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
    uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java
    uima/uimafit/trunk/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java

Modified: uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
URL: http://svn.apache.org/viewvc/uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java?rev=1787457&r1=1787456&r2=1787457&view=diff
==============================================================================
--- uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java (original)
+++ uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java Fri Mar 17 17:50:11 2017
@@ -980,33 +980,38 @@ public final class CasUtil {
   }
 
   /**
-   * Return an annotation preceding or following of a given reference annotation.
+   * Return an annotation preceding or following of a given reference annotation. If the type
+   * parameter corresponds to the type or a subtype of the anchor annotation and the relative
+   * position is 0, then the anchor annotation is returned.
    * 
    * @param cas
    *          a CAS containing the annotation.
    * @param type
    *          a type.
-   * @param annotation
+   * @param aAnchor
    *          anchor annotation
-   * @param index
+   * @param aPosition
    *          relative position to access. A negative value selects a preceding annotation while a
    *          positive number selects a following annotation.
    * @return the addressed annotation.
    * @throws IndexOutOfBoundsException
-   *           if the relative index points beyond the type index bounds.
+   *           if the relative position points beyond the type index bounds.
+   * @throws IllegalArgumentException
+   *           if the relative position is {@code 0} and the anchor type does not subsume the
+   *           selected type.
    * @see <a href="package-summary.html#SortOrder">Order of selected feature structures</a>
    */
-  public static AnnotationFS selectSingleRelative(CAS cas, Type type, AnnotationFS annotation,
-          int index) {
+  public static AnnotationFS selectSingleRelative(CAS cas, Type type, AnnotationFS aAnchor,
+          int aPosition) {
     if (!cas.getTypeSystem().subsumes(cas.getAnnotationType(), type)) {
       throw new IllegalArgumentException("Type [" + type.getName() + "] is not an annotation type");
     }
 
     // move to first previous annotation
     FSIterator<AnnotationFS> itr = cas.getAnnotationIndex(type).iterator();
-    itr.moveTo(annotation);
+    itr.moveTo(aAnchor);
 
-    if (index < 0) {
+    if (aPosition < 0) {
       // If the insertion point is beyond the index, move back to the last.
       if (!itr.isValid()) {
         itr.moveToLast();
@@ -1020,11 +1025,11 @@ public final class CasUtil {
       // the same offset as the reference annotation.
 
       // make sure we're past the beginning of the reference annotation
-      while (itr.isValid() && itr.get().getEnd() > annotation.getBegin()) {
+      while (itr.isValid() && itr.get().getEnd() > aAnchor.getBegin()) {
         itr.moveToPrevious();
       }
 
-      for (int i = 0; i < (-index - 1) && itr.isValid(); ++i, itr.moveToPrevious()) {
+      for (int i = 0; i < (-aPosition - 1) && itr.isValid(); ++i, itr.moveToPrevious()) {
         // Seeking
       }
 
@@ -1033,7 +1038,7 @@ public final class CasUtil {
       } else {
         return itr.get();
       }
-    } else if (index > 0) {
+    } else if (aPosition > 0) {
       // When seeking forward, there is no need to check if the insertion point is beyond the
       // index. If it was, there would be nothing beyond it that could be found and returned.
       // The moveTo operation also does not yield an iterator being invalid because it points
@@ -1045,11 +1050,11 @@ public final class CasUtil {
       // the same offset as the reference annotation.
       
       // make sure we're past the end of the reference annotation
-      while (itr.isValid() && itr.get().getBegin() < annotation.getEnd()) {
+      while (itr.isValid() && itr.get().getBegin() < aAnchor.getEnd()) {
         itr.moveToNext();
       }
 
-      for (int i = 0; i < (index - 1) && itr.isValid(); ++i, itr.moveToPrevious()) {
+      for (int i = 0; i < (aPosition - 1) && itr.isValid(); ++i, itr.moveToPrevious()) {
         // Seeking
       }
 
@@ -1058,8 +1063,13 @@ public final class CasUtil {
       } else {
         return itr.get();
       }
-    } else {
-      return annotation;
+    } else if (cas.getTypeSystem().subsumes(aAnchor.getType(), type)) {
+      return aAnchor;
+    }
+    else {
+      throw new IllegalArgumentException(
+              "Relative position cannot be 0 if the type of the anchor annotator does not subsume "
+              + "the selected type.");
     }
   }
 

Modified: uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java
URL: http://svn.apache.org/viewvc/uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java?rev=1787457&r1=1787456&r2=1787457&view=diff
==============================================================================
--- uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java (original)
+++ uima/uimafit/trunk/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java Fri Mar 17 17:50:11 2017
@@ -67,6 +67,7 @@ public final class JCasUtil {
   public static <T extends Annotation> Iterable<T> subiterate(final JCas jCas, final Class<T> type,
           final AnnotationFS container, final boolean ambiguous, final boolean strict) {
     return new Iterable<T>() {
+      @Override
       public Iterator<T> iterator() {
         return JCasUtil.iterator(container, type, ambiguous, strict);
       }
@@ -613,29 +614,34 @@ public final class JCasUtil {
   }
 
   /**
-   * Return an annotation preceding or following of a given reference annotation.
+   * Return an annotation preceding or following of a given reference annotation. If the type
+   * parameter corresponds to the type or a subtype of the anchor annotation and the relative
+   * position is 0, then the anchor annotation is returned.
    * 
    * @param <T>
    *          the JCas type.
    * @param aJCas
    *          a JCas.
    * @param aType
-   *          a type.
-   * @param annotation
+   *          type of the annotation to be returned.
+   * @param aAnchor
    *          anchor annotation
-   * @param index
+   * @param aPosition
    *          relative position to access. A negative value selects a preceding annotation while a
    *          positive number selects a following annotation.
    * @return the addressed annotation.
    * @throws IndexOutOfBoundsException
-   *           if the relative index points beyond the type index bounds.
+   *           if the relative position points beyond the type index bounds.
+   * @throws IllegalArgumentException
+   *           if the relative position is {@code 0} and the anchor type does not subsume the
+   *           selected type.
    * @see <a href="package-summary.html#SortOrder">Order of selected feature structures</a>
    */
   @SuppressWarnings("unchecked")
   public static <T extends Annotation> T selectSingleRelative(JCas aJCas, Class<T> aType,
-          AnnotationFS annotation, int index) {
+          AnnotationFS aAnchor, int aPosition) {
     Type t = getType(aJCas, aType);
-    return (T) CasUtil.selectSingleRelative(aJCas.getCas(), t, annotation, index);
+    return (T) CasUtil.selectSingleRelative(aJCas.getCas(), t, aAnchor, aPosition);
   }
 
   /**

Modified: uima/uimafit/trunk/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java
URL: http://svn.apache.org/viewvc/uima/uimafit/trunk/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java?rev=1787457&r1=1787456&r2=1787457&view=diff
==============================================================================
--- uima/uimafit/trunk/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java (original)
+++ uima/uimafit/trunk/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java Fri Mar 17 17:50:11 2017
@@ -461,6 +461,37 @@ public class JCasUtilTest extends Compon
     assertEquals(secondToken.getBegin(), a.getBegin());
     assertEquals(secondToken.getEnd(), a.getEnd());
   }
+  
+  @Test(expected=IllegalArgumentException.class)
+  public void testSingleRelativeDifferentTypeSamePositionFail() {
+    String text = "one two three";
+    tokenBuilder.buildTokens(jCas, text);
+
+    List<Token> tokens = new ArrayList<Token>(select(jCas, Token.class));
+    
+    for (Token token : tokens) {
+      new AnalyzedText(jCas, token.getBegin(), token.getEnd()).addToIndexes();
+    }    
+    
+    Token firstToken = tokens.get(0);
+    selectSingleRelative(jCas, AnalyzedText.class, firstToken, 0);
+  }
+
+  @Test
+  public void testSingleRelativeDifferentTypeSamePositionOk() {
+    String text = "one two three";
+    tokenBuilder.buildTokens(jCas, text);
+
+    List<Token> tokens = new ArrayList<Token>(select(jCas, Token.class));
+    
+    for (Token token : tokens) {
+      new AnalyzedText(jCas, token.getBegin(), token.getEnd()).addToIndexes();
+    }    
+    
+    Token firstToken = tokens.get(0);
+    Token a = selectSingleRelative(jCas, Token.class, firstToken, 0);
+    assertEquals(firstToken, a);
+  }
 
   @Test
   public void testSelectFollowing() {