Merge branch 'master' into bugfix/UIMA-6288-selectPreceding-using-zero-width-anchor-returns-covering-annotation

* master: (134 commits)
  [UIMA-6275] InitializableFactory is not smart enough to find a suitable classloader
  No issue: ASF Jenkins Windows nodes seem to have trouble ('nohup' not found) - excluding Windows build nodes for the moment.
  [UIMA-6270] Add selectOverlapping to (J)CasUtil
  [UIMA-6270] Add selectOverlapping to (J)CasUtil
  [UIMA-6263] CAS validation support
  [UIMA-6264] Switch from DocBook to Asciidoc
  [UIMA-6257] Jenkinsfile for uimaFIT
  [UIMA-6257] Jenkinsfile for uimaFIT
  [UIMA-6257] Jenkinsfile for uimaFIT
  [UIMA-6257] Jenkinsfile for uimaFIT
  [maven-release-plugin] prepare for next development iteration
  [maven-release-plugin] prepare release uimafit-3.1.0
  [maven-release-plugin] prepare for next development iteration
  [maven-release-plugin] prepare release uimafit-3.1.0
  [NO JIRA] Adjust UIMA version in the NOTICE file of the binary distribution
  [maven-release-plugin] prepare for next development iteration
  [maven-release-plugin] prepare release uimafit-3.1.0
  [NO JIRA] Update documentation to changed API in ExternalResourceFactory and removed a spurious character
  [NO JIRA] Adjusted comparison version for API change report
  [NO JIRA] Updated README file for release.
  ...
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 3e96190..1aaca7c 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
@@ -1166,14 +1166,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) {
     requireAnnotationType(cas, type);
 
@@ -1182,7 +1182,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()) {
@@ -1191,20 +1191,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++;
       }
@@ -1267,6 +1277,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 1932ecd..c3817a0 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
@@ -958,7 +958,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();