public static AnnotationFS selectSingleRelative()

in uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java [1137:1204]


  public static AnnotationFS selectSingleRelative(CAS cas, Type type, AnnotationFS aAnchor,
          int aPosition) {
    requireAnnotationType(cas, type);

    // move to first previous annotation
    FSIterator<AnnotationFS> itr = cas.getAnnotationIndex(type).iterator();
    itr.moveTo(aAnchor);

    if (aPosition < 0) {
      // If the insertion point is beyond the index, move back to the last.
      if (!itr.isValid()) {
        itr.moveToLast();
        if (!itr.isValid()) {
          throw new IndexOutOfBoundsException("Reached end of index while seeking.");
        }
      }

      // No need to do additional seeks here (as done in selectCovered) because the current method
      // does not have to worry about type priorities - it never returns annotations that have
      // the same offset as the reference annotation.

      // make sure we're past the beginning of the reference annotation
      while (itr.isValid() && itr.get().getEnd() > aAnchor.getBegin()) {
        itr.moveToPrevious();
      }

      for (int i = 0; i < (-aPosition - 1) && itr.isValid(); ++i, itr.moveToPrevious()) {
        // Seeking
      }

      if (!itr.isValid()) {
        throw new IndexOutOfBoundsException("Reached end of index while seeking.");
      } else {
        return itr.get();
      }
    } 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
      // *before the first* index entry, at max it points *to the first* index entry, so this
      // case also does not need to be handled.

      // No need to do additional seeks here (as done in selectCovered) because the current method
      // does not have to worry about type priorities - it never returns annotations that have
      // the same offset as the reference annotation.

      // make sure we're past the end of the reference annotation
      while (itr.isValid() && itr.get().getBegin() < aAnchor.getEnd()) {
        itr.moveToNext();
      }

      for (int i = 0; i < (aPosition - 1) && itr.isValid(); ++i, itr.moveToPrevious()) {
        // Seeking
      }

      if (!itr.isValid()) {
        throw new IndexOutOfBoundsException("Reached end of index while seeking.");
      } else {
        return itr.get();
      }
    } 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.");
    }
  }