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 2021/02/15 18:17:36 UTC

[uima-uimafit] 01/01: [UIMA-6314] Align preceding/following with predicate in UIMA core

This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch bugfix/UIMA-6314-Align-preceding-following-with-predicate-in-UIMA-core
in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git

commit 1c98562dcb6810e2804cac994d38f7db5de1f602
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Mon Feb 15 19:17:23 2021 +0100

    [UIMA-6314] Align preceding/following with predicate in UIMA core
    
    - Copy the test data for the predicates over from UIMA core
    - Align selectPreceding/selectFollowing with the respective predicates from UIMA core
---
 .../java/org/apache/uima/fit/util/CasUtil.java     |  65 +++++++---
 .../uima/fit/util/AnnotationPredicateTestData.java | 137 +++++++++++++++++++++
 .../java/org/apache/uima/fit/util/CasUtilTest.java |  14 +--
 .../org/apache/uima/fit/util/SelectionAssert.java  | 106 +---------------
 4 files changed, 191 insertions(+), 131 deletions(-)

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 50b0dfc..77dfa6f 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
@@ -203,7 +203,7 @@ public final class CasUtil {
   public static List<AnnotationFS> select(ArrayFS array, Type type) {
     final CAS cas = array.getCAS();
     requireAnnotationType(cas, type);
-    return (List) FSCollectionFactory.create(array, type);
+    return FSCollectionFactory.create(array, type);
   }
 
   /**
@@ -260,7 +260,7 @@ public final class CasUtil {
   @SuppressWarnings({ "unchecked", "rawtypes" })
   public static Collection<AnnotationFS> select(final CAS cas, final Type type) {
     requireAnnotationType(cas, type);
-    return (Collection) cas.getAnnotationIndex(type).select().asList();
+    return cas.getAnnotationIndex(type).select().asList();
   }
   
   /**
@@ -1208,11 +1208,18 @@ public final class CasUtil {
     }
     
     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.
+    // Zero-width annotations are in the index *after* the wider annotations starting at the same
+    // location, but we would consider a zero-width annotation at the beginning of a larger
+    // reference annotation to be preceding the larger one. So we need to seek right
+    // for any relevant zero-with annotations.
+    while (itr.isValid() && itr.get().getBegin() == anchorBegin) {
+      itr.moveToNext();
+      if (!itr.isValid()) {
+        itr.moveToLast();
+        break;
+      }
+    }
     
     // make sure we're past the beginning of the reference annotation
     while (itr.isValid() && itr.get().getEnd() > anchorBegin) {
@@ -1226,9 +1233,8 @@ public final class CasUtil {
       int curEnd = cur.getEnd();
 
       if (
-              curEnd <= anchorBegin && 
-              (cur.getBegin() != curEnd || anchorBegin != curEnd) &&
-              (anchorBegin != anchorEnd || curEnd != anchorBegin)
+              curEnd <= anchorBegin ||
+              (cur.getBegin() == curEnd && curEnd == anchorBegin)
       ) {
         precedingAnnotations.add(itr.get());
         i++;
@@ -1262,6 +1268,10 @@ public final class CasUtil {
     // withSnapshotIterators() not needed here since we copy the FSes to a list anyway    
     FSIterator<AnnotationFS> itr = cas.getAnnotationIndex(type).iterator();
     itr.moveTo(annotation);
+    
+    int anchorBegin = annotation.getBegin();
+    int anchorEnd = annotation.getBegin();
+
 
     // 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.
@@ -1273,24 +1283,41 @@ public final class CasUtil {
     // does not have to worry about type priorities - it never returns annotations that have
     // the same offset as the reference annotation.
 
+    if (annotation.getBegin() == annotation.getEnd()) {
+      // zero-width annotations appear *after* larger annotations with the same start position in
+      // the index but the larger annotations are considered to be *following* the zero-width, so we
+      // have to look to the left for larger annotations...
+      if (itr.isValid()) {
+        itr.moveToPrevious();
+        while (itr.isValid() && itr.getNvc().getBegin() == annotation.getBegin()) {
+          itr.moveToPrevious();
+        }
+        
+        if (!itr.isValid()) {
+          itr.moveToFirst();
+        }
+        else {
+          itr.moveToNext();
+        }
+      }
+      else {
+        itr.moveToFirst();
+      }
+    }
+    
     // make sure we're past the end of the reference annotation
     while (itr.isValid() && itr.get().getBegin() < annotation.getEnd()) {
       itr.moveToNext();
     }
 
     // add annotations from the iterator into the result list
-    int refEnd = annotation.getEnd();
     List<AnnotationFS> followingAnnotations = new ArrayList<AnnotationFS>();
-    for (int i = 0; i < count && itr.isValid(); i++, itr.moveToNext()) {
-      AnnotationFS fs = itr.get();
-      int begin = fs.getBegin();
-      int end = fs.getEnd();
-      if (begin == end && refEnd == begin) {
-        // Skip zero-width annotation at the end of the reference annotation. These are considered
-        // to be "coveredBy" instead of following
-        continue;
+    for (int i = 0; i < count && itr.isValid(); itr.moveToNext()) {
+      AnnotationFS a = itr.get();
+      if (a.getBegin() >= annotation.getEnd()) {
+        followingAnnotations.add(itr.get());
+        i ++;
       }
-      followingAnnotations.add(itr.get());
     }
     
     return followingAnnotations;
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/util/AnnotationPredicateTestData.java b/uimafit-core/src/test/java/org/apache/uima/fit/util/AnnotationPredicateTestData.java
new file mode 100644
index 0000000..12dd85e
--- /dev/null
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/util/AnnotationPredicateTestData.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.uima.fit.util;
+
+import static java.lang.Integer.MAX_VALUE;
+import static java.util.Arrays.asList;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.BEGINNING_WITH;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.COLOCATED;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.COVERED_BY;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.COVERING;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.ENDING_WITH;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.FOLLOWING;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.OVERLAPPING;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.OVERLAPPING_AT_BEGIN;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.OVERLAPPING_AT_END;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.PRECEDING;
+
+import java.util.List;
+
+import org.apache.uima.fit.util.SelectionAssert.TestCase;
+
+public class AnnotationPredicateTestData {
+  public static enum RelativePosition {
+    COLOCATED,
+    OVERLAPPING,
+    OVERLAPPING_AT_BEGIN,
+    OVERLAPPING_AT_END,
+    COVERING,
+    COVERED_BY,
+    PRECEDING,
+    FOLLOWING,
+    BEGINNING_WITH,
+    ENDING_WITH
+  }
+  
+  // Used as fixed references for the annotation relation cases.
+  private static final int BEGIN = 10;
+  private static final int END = 20;
+  private static final int Z_POS = 10;
+
+  public static final TestCase T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13;
+  
+  public static final List<TestCase> NON_ZERO_WIDTH_TEST_CASES = asList(
+      T1 = new TestCase("1) Y begins and ends after X (### [---])", 
+          p -> p.apply(BEGIN, END, END + 1, MAX_VALUE),
+          asList(PRECEDING)),
+      T2 = new TestCase("2) Y begins at X's end and ends after X (###[---])", 
+          p -> p.apply(BEGIN, END, END, MAX_VALUE),
+          asList(PRECEDING)),
+      T3 = new TestCase("3) Y begins within and ends after X (##[#--])", 
+          p -> p.apply(BEGIN, END, END - 1 , MAX_VALUE),
+          asList(OVERLAPPING, OVERLAPPING_AT_BEGIN)),
+      T4 = new TestCase("4) Y begins and ends at X's boundries ([###])", 
+          p -> p.apply(BEGIN, END, BEGIN, END),
+          asList(OVERLAPPING, COLOCATED, COVERED_BY, COVERING, BEGINNING_WITH, ENDING_WITH)),
+      T5 = new TestCase("5) Y begins and ends within X (#[#]#)", 
+          p -> p.apply(BEGIN, END, BEGIN + 1, END - 1),
+          asList(OVERLAPPING, COVERING)),
+      T6 = new TestCase("6) Y begins at and ends before X's boundries ([##]#)", 
+          p -> p.apply(BEGIN, END, BEGIN, END - 1),
+          asList(OVERLAPPING, COVERING, BEGINNING_WITH, OVERLAPPING_AT_END)),
+      T7 = new TestCase("7) Y begins after and ends at X's boundries (#[##])", 
+          p -> p.apply(BEGIN, END, BEGIN + 1, END),
+          asList(OVERLAPPING, COVERING, ENDING_WITH, OVERLAPPING_AT_BEGIN)),
+      T8 = new TestCase("8) Y begins before and ends after X's boundries ([-###-])", 
+          p -> p.apply(BEGIN, END, BEGIN - 1, END + 1),
+          asList(OVERLAPPING, COVERED_BY)),
+      T9 = new TestCase("9) X starts where Y begins and ends within Y ([##-])", 
+          p -> p.apply(BEGIN, END, BEGIN, END + 1),
+          asList(OVERLAPPING, COVERED_BY, BEGINNING_WITH)),
+      T10 = new TestCase("10) X starts within Y and ends where Y ends ([-##])", 
+          p -> p.apply(BEGIN, END, BEGIN - 1, END),
+          asList(OVERLAPPING, COVERED_BY, ENDING_WITH)),
+      T11 = new TestCase("11) Y begins before and ends within X ([--#]##)", 
+          p -> p.apply(BEGIN, END, 0, BEGIN + 1),
+          asList(OVERLAPPING, OVERLAPPING_AT_END)),
+      T12 = new TestCase("12) Y begins before and ends where X begins ([---]###)", 
+          p -> p.apply(BEGIN, END, 0, BEGIN),
+          asList(FOLLOWING)),
+      T13 = new TestCase("13) Y begins and ends before X begins ([---] ###)", 
+          p -> p.apply(BEGIN, END, 0, BEGIN - 1),
+          asList(FOLLOWING)));
+
+  public static final TestCase TZ1, TZ2, TZ3, TZ4, TZ5, TZ6, TZ7, TZ8, TZ9, TZ10, TZ11;
+
+  public static final List<TestCase> ZERO_WIDTH_TEST_CASES = asList(
+      TZ1 = new TestCase("Z1) Zero-width X before Y start (# [---])", 
+          p -> p.apply(Z_POS, Z_POS, Z_POS + 10, Z_POS + 20),
+          asList(PRECEDING)),
+      TZ2 = new TestCase("Z2) Zero-width Y after X's end (### |)", 
+          p -> p.apply(BEGIN, END, END + 1, END + 1),
+          asList(PRECEDING)),
+      TZ3 = new TestCase("Z3) Zero-width X at Y's start (#---])", 
+          p -> p.apply(Z_POS, Z_POS, Z_POS, Z_POS + 10),
+          asList(PRECEDING, OVERLAPPING, COVERED_BY, BEGINNING_WITH)),
+      TZ4 = new TestCase("Z4) Zero-width X at Y's end ([---#)", 
+          p -> p.apply(Z_POS, Z_POS, Z_POS-10, Z_POS),
+          asList(FOLLOWING, OVERLAPPING, COVERED_BY, ENDING_WITH)),
+      TZ5 = new TestCase("Z5) Zero-width Y where X begins (|###)", 
+          p -> p.apply(BEGIN, END, BEGIN, BEGIN),
+          asList(FOLLOWING, OVERLAPPING, COVERING, BEGINNING_WITH)),
+      TZ6 = new TestCase("Z6) Zero-width Y within X (#|#)", 
+          p -> p.apply(BEGIN, END, BEGIN + 1, BEGIN + 1),
+          asList(OVERLAPPING, COVERING)),
+      TZ7 = new TestCase("Z7) Zero-width Y at X's end (###|)", 
+          p -> p.apply(BEGIN, END, END, END),
+          asList(PRECEDING, OVERLAPPING, COVERING, ENDING_WITH)),
+      TZ8 = new TestCase("Z8) Zero-width X with Y (-|-)", 
+          p -> p.apply(Z_POS, Z_POS, Z_POS - 5, Z_POS + 5),
+          asList(OVERLAPPING, COVERED_BY)),
+      TZ9 = new TestCase("Z9) Zero-width X after Y's end ([---] #)", 
+          p -> p.apply(Z_POS, Z_POS, Z_POS - 10, Z_POS - 5),
+          asList(FOLLOWING)),
+      TZ10 = new TestCase("Z10) Zero-width Y before X begins (| ###)", 
+          p -> p.apply(BEGIN, END, BEGIN - 1, BEGIN - 1),
+          asList(FOLLOWING)),
+      TZ11 = new TestCase("Z11) Zero-width X matches zero-width Y start/end (#)", 
+          p -> p.apply(Z_POS, Z_POS, Z_POS, Z_POS),
+          asList(FOLLOWING, PRECEDING, OVERLAPPING, COVERED_BY, COVERING, COLOCATED, BEGINNING_WITH, 
+              ENDING_WITH)));
+}
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/util/CasUtilTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/util/CasUtilTest.java
index 7ccf685..711de6d 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/util/CasUtilTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/util/CasUtilTest.java
@@ -27,6 +27,13 @@ import static org.apache.uima.cas.text.AnnotationPredicates.covering;
 import static org.apache.uima.cas.text.AnnotationPredicates.following;
 import static org.apache.uima.cas.text.AnnotationPredicates.preceding;
 import static org.apache.uima.fit.factory.TypeSystemDescriptionFactory.createTypeSystemDescription;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.NON_ZERO_WIDTH_TEST_CASES;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.ZERO_WIDTH_TEST_CASES;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.COLOCATED;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.COVERED_BY;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.COVERING;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.FOLLOWING;
+import static org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition.PRECEDING;
 import static org.apache.uima.fit.util.CasUtil.exists;
 import static org.apache.uima.fit.util.CasUtil.getAnnotationType;
 import static org.apache.uima.fit.util.CasUtil.getType;
@@ -41,15 +48,8 @@ import static org.apache.uima.fit.util.CasUtil.selectFS;
 import static org.apache.uima.fit.util.CasUtil.selectFollowing;
 import static org.apache.uima.fit.util.CasUtil.selectPreceding;
 import static org.apache.uima.fit.util.CasUtil.toText;
-import static org.apache.uima.fit.util.SelectionAssert.NON_ZERO_WIDTH_TEST_CASES;
-import static org.apache.uima.fit.util.SelectionAssert.ZERO_WIDTH_TEST_CASES;
 import static org.apache.uima.fit.util.SelectionAssert.assertSelection;
 import static org.apache.uima.fit.util.SelectionAssert.assertSelectionIsEqualOnRandomData;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.COLOCATED;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.COVERED_BY;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.COVERING;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.FOLLOWING;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.PRECEDING;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/util/SelectionAssert.java b/uimafit-core/src/test/java/org/apache/uima/fit/util/SelectionAssert.java
index 2bf7b0e..f3b6697 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/util/SelectionAssert.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/util/SelectionAssert.java
@@ -18,18 +18,7 @@
  */
 package org.apache.uima.fit.util;
 
-import static java.lang.Integer.MAX_VALUE;
 import static java.util.Arrays.asList;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.BEGINNING_WITH;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.COLOCATED;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.COVERED_BY;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.COVERING;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.ENDING_WITH;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.FOLLOWING;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.OVERLAPPING;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.OVERLAPPING_AT_BEGIN;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.OVERLAPPING_AT_END;
-import static org.apache.uima.fit.util.SelectionAssert.RelativePosition.PRECEDING;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.util.ArrayList;
@@ -44,106 +33,13 @@ import org.apache.uima.UIMAFramework;
 import org.apache.uima.cas.CAS;
 import org.apache.uima.cas.Type;
 import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition;
 import org.apache.uima.jcas.tcas.Annotation;
 import org.apache.uima.resource.metadata.TypeSystemDescription;
 import org.apache.uima.util.CasCreationUtils;
 import org.assertj.core.api.AutoCloseableSoftAssertions;
 
 public class SelectionAssert {
-  public static enum RelativePosition {
-    COLOCATED,
-    OVERLAPPING,
-    OVERLAPPING_AT_BEGIN,
-    OVERLAPPING_AT_END,
-    COVERING,
-    COVERED_BY,
-    PRECEDING,
-    FOLLOWING,
-    BEGINNING_WITH,
-    ENDING_WITH
-  }
-  
-  // Used as fixed references for the annotation relation cases.
-  private static final int BEGIN = 10;
-  private static final int END = 20;
-  private static final int Z_POS = 10;
-
-  public static final List<TestCase> NON_ZERO_WIDTH_TEST_CASES = asList(
-      new TestCase("1) Y begins and ends after X (### [---])", 
-          p -> p.apply(BEGIN, END, END + 1, MAX_VALUE),
-          asList(PRECEDING)),
-      new TestCase("2) Y begins at X's end and ends after X (###[---])", 
-          p -> p.apply(BEGIN, END, END, MAX_VALUE),
-          asList(PRECEDING)),
-      new TestCase("3) Y begins within and ends after X (##[#--])", 
-          p -> p.apply(BEGIN, END, END - 1 , MAX_VALUE),
-          asList(OVERLAPPING, OVERLAPPING_AT_BEGIN)),
-      new TestCase("4) Y begins and ends at X's boundries ([###])", 
-          p -> p.apply(BEGIN, END, BEGIN, END),
-          asList(OVERLAPPING, COLOCATED, COVERED_BY, COVERING, BEGINNING_WITH, ENDING_WITH)),
-      new TestCase("5) Y begins and ends within X (#[#]#)", 
-          p -> p.apply(BEGIN, END, BEGIN + 1, END - 1),
-          asList(OVERLAPPING, COVERING)),
-      new TestCase("6) Y begins at and ends before X's boundries ([##]#)", 
-          p -> p.apply(BEGIN, END, BEGIN, END - 1),
-          asList(OVERLAPPING, COVERING, BEGINNING_WITH)),
-      new TestCase("7) Y begins after and ends at X's boundries (#[##])", 
-          p -> p.apply(BEGIN, END, BEGIN + 1, END),
-          asList(OVERLAPPING, COVERING, ENDING_WITH)),
-      new TestCase("8) Y begins before and ends after X's boundries ([-###-])", 
-          p -> p.apply(BEGIN, END, BEGIN - 1, END + 1),
-          asList(OVERLAPPING, COVERED_BY)),
-      new TestCase("9) X starts where Y begins and ends within Y ([##-])", 
-          p -> p.apply(BEGIN, END, BEGIN, END + 1),
-          asList(OVERLAPPING, COVERED_BY, BEGINNING_WITH)),
-      new TestCase("10) X starts within Y and ends where Y ends ([-##])", 
-          p -> p.apply(BEGIN, END, BEGIN - 1, END),
-          asList(OVERLAPPING, COVERED_BY, ENDING_WITH)),
-      new TestCase("11) Y begins before and ends within X ([--#]##)", 
-          p -> p.apply(BEGIN, END, 0, BEGIN + 1),
-          asList(OVERLAPPING, OVERLAPPING_AT_END)),
-      new TestCase("12) Y begins before and ends where X begins ([---]###)", 
-          p -> p.apply(BEGIN, END, 0, BEGIN),
-          asList(FOLLOWING)),
-      new TestCase("13) Y begins and ends before X begins ([---] ###)", 
-          p -> p.apply(BEGIN, END, 0, BEGIN - 1),
-          asList(FOLLOWING)));
-
-  public static final List<TestCase> ZERO_WIDTH_TEST_CASES = asList(
-      new TestCase("Z1) Zero-width X before Y start (# [---])", 
-          p -> p.apply(Z_POS, Z_POS, Z_POS + 10, Z_POS + 20),
-          asList(PRECEDING)),
-      new TestCase("Z2) Zero-width Y after X's end (### |)", 
-          p -> p.apply(BEGIN, END, END + 1, END + 1),
-          asList(PRECEDING)),
-      new TestCase("Z3) Zero-width X at Y's start (#---])", 
-          p -> p.apply(Z_POS, Z_POS, Z_POS, Z_POS + 10),
-          asList(OVERLAPPING, COVERED_BY, BEGINNING_WITH)),
-      new TestCase("Z4) Zero-width X at Y's end ([---#)", 
-          p -> p.apply(Z_POS, Z_POS, Z_POS-10, Z_POS),
-          asList(OVERLAPPING, COVERED_BY, ENDING_WITH)),
-      new TestCase("Z5) Zero-width Y where X begins (|###)", 
-          p -> p.apply(BEGIN, END, BEGIN, BEGIN),
-          asList(OVERLAPPING, COVERING, BEGINNING_WITH)),
-      new TestCase("Z6) Zero-width Y within X (#|#)", 
-          p -> p.apply(BEGIN, END, BEGIN + 1, BEGIN + 1),
-          asList(OVERLAPPING, COVERING)),
-      new TestCase("Z7) Zero-width Y at X's end (###|)", 
-          p -> p.apply(BEGIN, END, END, END),
-          asList(OVERLAPPING, COVERING, ENDING_WITH)),
-      new TestCase("Z8) Zero-width X with Y (-|-)", 
-          p -> p.apply(Z_POS, Z_POS, Z_POS - 5, Z_POS + 5),
-          asList(OVERLAPPING, COVERED_BY)),
-      new TestCase("Z9) Zero-width X after Y's end ([---] #)", 
-          p -> p.apply(Z_POS, Z_POS, Z_POS - 10, Z_POS - 5),
-          asList(FOLLOWING)),
-      new TestCase("Z10) Zero-width Y before X begins (| ###)", 
-          p -> p.apply(BEGIN, END, BEGIN - 1, BEGIN - 1),
-          asList(FOLLOWING)),
-      new TestCase("Z11) Zero-width X matches zero-width Y start/end (#)", 
-          p -> p.apply(Z_POS, Z_POS, Z_POS, Z_POS),
-          asList(OVERLAPPING, COVERED_BY, COVERING, COLOCATED, BEGINNING_WITH, ENDING_WITH)));
-  
   public static void assertSelection(RelativePosition aCondition, RelativeAnnotationPredicate aPredicate, 
       List<TestCase> aTestCases)
       throws Exception {