Merge branch 'main' into bugfix/345-Certain-select-operations-deplete-FS-ID-pool
diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java
index 14d568c..a65b9fc 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java
@@ -1250,8 +1250,7 @@
     mySofaRef = (Sofa) aSofa;
 
     // get the indexRepository for this Sofa
-    indexRepository = (mySofaRef == null)
-            ? (FSIndexRepositoryImpl) cas.getSofaIndexRepository(1)
+    indexRepository = (mySofaRef == null) ? (FSIndexRepositoryImpl) cas.getSofaIndexRepository(1)
             : (FSIndexRepositoryImpl) cas.getSofaIndexRepository(aSofa);
     if (null == indexRepository) {
       // create the indexRepository for this CAS
@@ -1703,9 +1702,9 @@
     }
 
     Sofa sofa = new Sofa(getTypeSystemImpl().sofaType, getBaseCAS(), // view for a sofa is the
-                                                                          // base cas to correspond
-                                                                          // to where it gets
-                                                                          // indexed
+                                                                     // base cas to correspond
+                                                                     // to where it gets
+                                                                     // indexed
             sofaNum, sofaName, mimeType);
 
     getBaseIndexRepository().addFS(sofa);
diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureStructureImplC.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureStructureImplC.java
index 3aa568f..cc91fff 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureStructureImplC.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureStructureImplC.java
@@ -187,15 +187,11 @@
 
   /**
    * For non-JCas use, Internal Use Only, called by cas.createFS via generators
-   * 
-   * @param casView
-   *          -
-   * @param type
-   *          -
    */
   protected FeatureStructureImplC(TypeImpl type, CASImpl casView) {
     _casView = casView;
     _typeImpl = type;
+
     _id = casView.getNextFsId((TOP) this);
 
     if (_casView.maybeMakeBaseVersionForPear(this, _typeImpl)) {
@@ -226,7 +222,6 @@
    * @param jcasImpl
    *          - the view this is being created in
    */
-
   protected FeatureStructureImplC(JCasImpl jcasImpl) {
     _casView = jcasImpl.getCasImpl();
     _typeImpl = _casView.getTypeSystemImpl().getJCasRegisteredType(getTypeIndexID());
@@ -264,6 +259,35 @@
     // }
   }
 
+  /**
+   * For temporary marker annotations. Does not assign an ID from the CAS ID generator and never
+   * retains the annotation. We also do not trace this annotation.
+   */
+  protected FeatureStructureImplC(JCasImpl jcasImpl, int aId) {
+    _casView = jcasImpl.getCasImpl();
+    _typeImpl = _casView.getTypeSystemImpl().getJCasRegisteredType(getTypeIndexID());
+    _id = aId;
+
+    if (null == _typeImpl) {
+      throw new CASRuntimeException(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS,
+              this.getClass().getName());
+    }
+
+    if (_casView.maybeMakeBaseVersionForPear(this, _typeImpl)) {
+      _setPearTrampoline();
+    }
+
+    FeatureStructureImplC baseFs = _casView.pearBaseFs;
+    if (null != baseFs) {
+      _intData = baseFs._intData;
+      _refData = baseFs._refData;
+      _casView.pearBaseFs = null;
+    } else {
+      _intData = _allocIntData();
+      _refData = _allocRefData();
+    }
+  }
+
   private int[] _allocIntData() {
     final int c = _typeImpl.nbrOfUsedIntDataSlots;
     if (c != 0) {
diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java
index cf1a71a..69d793e 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java
@@ -19,6 +19,7 @@
 package org.apache.uima.cas.impl;
 
 import static org.apache.uima.cas.impl.Subiterator.BoundsUse.notBounded;
+import static org.apache.uima.jcas.tcas.Annotation._createMarkerAnnotation;
 
 import java.lang.reflect.Array;
 import java.util.ArrayList;
@@ -56,7 +57,6 @@
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.cas.text.AnnotationIndex;
 import org.apache.uima.cas.text.AnnotationPredicates;
-import org.apache.uima.jcas.JCas;
 import org.apache.uima.jcas.cas.EmptyFSList;
 import org.apache.uima.jcas.cas.FSArray;
 import org.apache.uima.jcas.cas.FSList;
@@ -64,7 +64,6 @@
 import org.apache.uima.jcas.cas.TOP;
 import org.apache.uima.jcas.impl.JCasImpl;
 import org.apache.uima.jcas.tcas.Annotation;
-import org.apache.uima.util.AutoCloseableNoException;
 
 // @formatter:off
 /**
@@ -1019,19 +1018,10 @@
   // }
 
   private Annotation makePosAnnot(int begin, int end) {
-    return makePosAnnot(jcas, begin, end);
+    return _createMarkerAnnotation(jcas, begin, end);
   }
 
-  static Annotation makePosAnnot(JCas jcas, int begin, int end) {
-    if (end < begin) {
-      throw new IllegalArgumentException("End value must be >= Begin value");
-    }
-    try (AutoCloseableNoException c = ((CASImpl) jcas.getCas()).ll_forceEnableV2IdRefs(false)) {
-      return new Annotation(jcas, begin, end);
-    }
-  }
-
-//@formatter:off
+  //@formatter:off
   /**
    * Iterator respects backwards
    * 
diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/Subiterator.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/Subiterator.java
index bce76f8..4cb1b4f 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/Subiterator.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/Subiterator.java
@@ -365,7 +365,7 @@
       if (begin < 0) {
         begin = 0;
       }
-      coveringStartPos = SelectFSs_impl.makePosAnnot(jcas, begin, Integer.MAX_VALUE);
+      coveringStartPos = Annotation._createMarkerAnnotation(jcas, begin, Integer.MAX_VALUE);
     } else {
       coveringStartPos = null;
     }
@@ -759,7 +759,7 @@
    */
   private void moveToJustPastBoundsAndBackup(int begin, int end,
           Predicate<Annotation> continue_going_backwards) {
-    it.moveToNoReinit(SelectFSs_impl.makePosAnnot(jcas, begin, end));
+    it.moveToNoReinit(Annotation._createMarkerAnnotation(jcas, begin, end));
 
     if (!it.isValid()) {
       it.moveToLastNoReinit();
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java
index 4c5efd1..383f48d 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java
@@ -82,11 +82,6 @@
   protected AnnotationBase() {
   }
 
-  // /* Internal - Constructor used by generator */
-  // public AnnotationBase(int addr, TOP_Type type) {
-  // super(addr, type);
-  // }
-
   public AnnotationBase(JCas jcas) {
     super(jcas);
     if (_casView.isBaseCas()) {
@@ -98,14 +93,21 @@
   }
 
   /**
-   * used by generator Make a new AnnotationBase
-   * 
-   * @param c
-   *          -
-   * @param t
-   *          -
+   * Used to create temporary marker annotations.
    */
+  protected AnnotationBase(JCas jcas, int aId) {
+    super(jcas, 0);
+    if (_casView.isBaseCas()) {
+      throw new CASRuntimeException(CASRuntimeException.DISALLOW_CREATE_ANNOTATION_IN_BASE_CAS,
+              this.getClass().getName());
+    }
+    // no journaling, no index corruption checking
+    _setRefValueCommon(wrapGetIntCatchException(_FH_sofa), _casView.getSofaRef());
+  }
 
+  /**
+   * used by generator Make a new AnnotationBase
+   */
   public AnnotationBase(TypeImpl t, CASImpl c) {
     super(t, c);
     if (_casView.isBaseCas()) {
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/TOP.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/TOP.java
index 60ef838..7dc6943 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/TOP.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/TOP.java
@@ -66,7 +66,7 @@
    * @param id
    *          -
    */
-  private TOP(int id) {
+  TOP(int id) {
     super(id);
   }
 
@@ -93,6 +93,16 @@
     super((JCasImpl) jcas);
   }
 
+  /**
+   * Internal. Used to create marker annotations.
+   * 
+   * @param jcas
+   *          -
+   */
+  TOP(JCas jcas, int aId) {
+    super((JCasImpl) jcas, aId);
+  }
+
   public static TOP _createSearchKey(int id) {
     return new TOP(id); // special super class, does nothing except create this TOP instance
   }
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java b/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java
index 7f2baa3..47cb64e 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java
@@ -27,6 +27,7 @@
 import org.apache.uima.cas.admin.LinearTypeOrder;
 import org.apache.uima.cas.impl.AnnotationImpl;
 import org.apache.uima.cas.impl.CASImpl;
+import org.apache.uima.cas.impl.SelectFSs_impl;
 import org.apache.uima.cas.impl.TypeImpl;
 import org.apache.uima.cas.impl.TypeSystemImpl;
 import org.apache.uima.jcas.JCas;
@@ -177,6 +178,15 @@
   }
 
   /**
+   * Used to create temporary marker annotations.
+   */
+  private Annotation(JCas jcas, int begin, int end, int aId) {
+    super(jcas, aId); // forward to constructor
+    setBegin(begin);
+    setEnd(end);
+  }
+
+  /**
    * @see org.apache.uima.cas.text.AnnotationFS#getCoveredText()
    * @return -
    */
@@ -212,8 +222,9 @@
       int result = Integer.compare(_getIntValueNc(b), other._getIntValueNc(b));
       // int result = Integer.compare(_getIntValueNc(BEGIN_OFFSET),
       // other._getIntValueNc(BEGIN_OFFSET));
-      if (result != 0)
+      if (result != 0) {
         return result;
+      }
 
       final int e = (int) _FH_end.invokeExact();
       result = Integer.compare(_getIntValueNc(e), other._getIntValueNc(e));
@@ -235,8 +246,9 @@
    */
   public final int compareAnnotation(Annotation other, LinearTypeOrder lto) {
     int result = compareAnnotation(other);
-    if (result != 0)
+    if (result != 0) {
       return result;
+    }
 
     return lto.compare(this, other);
   }
@@ -250,8 +262,9 @@
    */
   public final int compareAnnotationWithId(Annotation other) {
     int result = compareAnnotation(other);
-    if (result != 0)
+    if (result != 0) {
       return result;
+    }
     return Integer.compare(_id, other._id);
   }
 
@@ -266,8 +279,9 @@
    */
   public final int compareAnnotationWithId(Annotation other, LinearTypeOrder lto) {
     int result = compareAnnotation(other, lto);
-    if (result != 0)
+    if (result != 0) {
       return result;
+    }
     return Integer.compare(_id, other._id);
   }
 
@@ -309,4 +323,15 @@
       });
     }
   }
+
+  /**
+   * For internal use by {@link SelectFSs_impl}
+   */
+  public static Annotation _createMarkerAnnotation(JCas aJCas, int aBegin, int aEnd) {
+    if (aEnd < aBegin) {
+      throw new IllegalArgumentException("End value must be >= Begin value");
+    }
+
+    return new Annotation(aJCas, aBegin, aEnd, 0);
+  }
 }
diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/impl/SubiteratorTest.java b/uimaj-core/src/test/java/org/apache/uima/cas/impl/SubiteratorTest.java
index 7f3cd95..8c069b5 100644
--- a/uimaj-core/src/test/java/org/apache/uima/cas/impl/SubiteratorTest.java
+++ b/uimaj-core/src/test/java/org/apache/uima/cas/impl/SubiteratorTest.java
@@ -99,9 +99,9 @@
               .containsOnly(CAS.TYPE_NAME_SOFA, CAS.TYPE_NAME_DOCUMENT_ANNOTATION,
                       Sentence._TypeName, Token._TypeName);
 
-      // The +1 here accounts for the temporary Annotation that was created.
+      // The temporary annotation should not have been assigned an ID
       var t = new Token(jcas);
-      assertThat(t._id).isEqualTo(maxId + 2 + 1);
+      assertThat(t._id).isEqualTo(maxId + 1);
     }
   }