[UIMA-6286] select following finds zero-width annotation at reference end position
- Added fix and unit test
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java b/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
index eaa0e5c..03c88ac 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
@@ -1088,14 +1088,14 @@
* a CAS.
* @param type
* a UIMA type.
- * @param annotation
+ * @param anchor
* anchor annotation
* @param count
* number of annotations to collect
* @return List of aType annotations preceding anchor annotation
* @see <a href="package-summary.html#SortOrder">Order of selected feature structures</a>
*/
- public static List<AnnotationFS> selectPreceding(CAS cas, Type type, AnnotationFS annotation,
+ public static List<AnnotationFS> selectPreceding(CAS cas, Type type, AnnotationFS anchor,
int count) {
if (!cas.getTypeSystem().subsumes(cas.getAnnotationType(), type)) {
throw new IllegalArgumentException("Type [" + type.getName() + "] is not an annotation type");
@@ -1106,7 +1106,7 @@
// Seek annotation in index
// withSnapshotIterators() not needed here since we copy the FSes to a list anyway
FSIterator<AnnotationFS> itr = cas.getAnnotationIndex(type).iterator();
- itr.moveTo(annotation);
+ itr.moveTo(anchor);
// If the insertion point is beyond the index, move back to the last.
if (!itr.isValid()) {
@@ -1115,20 +1115,30 @@
return precedingAnnotations;
}
}
+
+ int anchorBegin = anchor.getBegin();
+ int anchorEnd = anchor.getEnd();
// 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() > annotation.getBegin()) {
+ while (itr.isValid() && itr.get().getEnd() > anchorBegin) {
itr.moveToPrevious();
}
// add annotations from the iterator into the result list
for (int i = 0; i < count && itr.isValid(); itr.moveToPrevious()) {
AnnotationFS cur = itr.get();
- if (cur.getEnd() <= annotation.getBegin()) {
+
+ int curEnd = cur.getEnd();
+
+ if (
+ curEnd <= anchorBegin &&
+ (cur.getBegin() != curEnd || anchorBegin != curEnd) &&
+ (anchorBegin != anchorEnd || curEnd != anchorBegin)
+ ) {
precedingAnnotations.add(itr.get());
i++;
}
@@ -1193,6 +1203,7 @@
}
followingAnnotations.add(itr.get());
}
+
return followingAnnotations;
}
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java
index afdbb52..7094af4 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java
@@ -694,7 +694,21 @@
assertThat(selection)
.isEmpty();
}
+
+ @Test
+ public void thatSelectPrecedingOnZeroWidthDoesNotFindAnnotationEndingAtSameLocation()
+ {
+ Annotation a1 = new Annotation(jCas, 10, 20);
+ Annotation a2 = new Annotation(jCas, 20, 20);
+ asList(a1, a2).forEach(a -> a.addToIndexes());
+
+ List<Annotation> selection = selectPreceding(Annotation.class, a2, MAX_VALUE);
+
+ assertThat(selection)
+ .isEmpty();
+ }
+
@Test
public void testExists() throws UIMAException {
JCas jcas = CasCreationUtils.createCas(createTypeSystemDescription(), null, null).getJCas();