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

rec pushed a commit to branch 
bugfix/345-Certain-select-operations-deplete-FS-ID-pool
in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git

commit 3d35bfeb24faa0d63eed108e6c4141ddbe6737a6
Author: Richard Eckart de Castilho <r...@apache.org>
AuthorDate: Wed Sep 20 20:52:50 2023 +0200

    Issue #345: Certain select operations deplete FS ID pool
    
    - Introduce an internal flag and guard to temporarily disable ID assignment 
to annotatons while creating temporary annotations.
---
 .../java/org/apache/uima/cas/impl/CASImpl.java     |  9 +++---
 .../uima/cas/impl/FeatureStructureImplC.java       | 36 ++++++++++++++++++----
 .../org/apache/uima/cas/impl/SelectFSs_impl.java   | 16 ++--------
 .../java/org/apache/uima/cas/impl/Subiterator.java |  4 +--
 .../org/apache/uima/jcas/cas/AnnotationBase.java   | 24 ++++++++-------
 .../main/java/org/apache/uima/jcas/cas/TOP.java    | 12 +++++++-
 .../java/org/apache/uima/jcas/tcas/Annotation.java | 33 +++++++++++++++++---
 .../org/apache/uima/cas/impl/SubiteratorTest.java  |  4 +--
 8 files changed, 94 insertions(+), 44 deletions(-)

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 14d568c6e..a65b9fc2f 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 @@ public class CASImpl extends AbstractCas_ImplBase
     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 @@ public class CASImpl extends AbstractCas_ImplBase
     }
 
     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 3aa568f7a..cc91fffb3 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 @@ public class FeatureStructureImplC implements 
FeatureStructureImpl {
 
   /**
    * 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 @@ public class FeatureStructureImplC implements 
FeatureStructureImpl {
    * @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 @@ public class FeatureStructureImplC implements 
FeatureStructureImpl {
     // }
   }
 
+  /**
+   * 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 cf1a71aca..69d793e81 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.impl.Subiterator.BoundsUse;
 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.NonEmptyFSList;
 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 @@ public class SelectFSs_impl<T extends FeatureStructure> 
implements SelectFSs<T>
   // }
 
   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 bce76f870..4cb1b4f56 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 @@ public class Subiterator<T extends AnnotationFS> implements 
LowLevelIterator<T>
       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 @@ public class Subiterator<T extends AnnotationFS> implements 
LowLevelIterator<T>
    */
   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 4c5efd192..383f48d9f 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 @@ public class AnnotationBase extends TOP implements 
AnnotationBaseImpl {
   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 @@ public class AnnotationBase extends TOP implements 
AnnotationBaseImpl {
   }
 
   /**
-   * 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 60ef838c5..7dc694339 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 @@ public class TOP extends FeatureStructureImplC {
    * @param id
    *          -
    */
-  private TOP(int id) {
+  TOP(int id) {
     super(id);
   }
 
@@ -93,6 +93,16 @@ public class TOP extends FeatureStructureImplC {
     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 7f2baa3c5..47cb64ec0 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.CAS;
 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;
@@ -176,6 +177,15 @@ public class Annotation extends AnnotationBase implements 
AnnotationImpl {
     setEnd(end);
   }
 
+  /**
+   * 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 @@ public class Annotation extends AnnotationBase implements 
AnnotationImpl {
       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 class Annotation extends AnnotationBase implements 
AnnotationImpl {
    */
   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 class Annotation extends AnnotationBase implements 
AnnotationImpl {
    */
   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 class Annotation extends AnnotationBase implements 
AnnotationImpl {
    */
   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 @@ public class Annotation extends AnnotationBase implements 
AnnotationImpl {
       });
     }
   }
+
+  /**
+   * 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 7f3cd95ab..8c069b524 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 @@ public class SubiteratorTest {
               .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);
     }
   }
 

Reply via email to