Merge branch 'main' into merge/update-main-to-3.4.x
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 77ff9bb..d059c60 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
@@ -56,6 +56,7 @@
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;
@@ -1018,6 +1019,10 @@
// }
private Annotation makePosAnnot(int begin, int end) {
+ return makePosAnnot(jcas, begin, end);
+ }
+
+ static Annotation makePosAnnot(JCas jcas, int begin, int end) {
if (end < begin) {
throw new IllegalArgumentException("End value must be >= Begin value");
}
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 63c5567..613b30c 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 = new Annotation(jcas, begin, Integer.MAX_VALUE);
+ coveringStartPos = SelectFSs_impl.makePosAnnot(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(new Annotation(jcas, begin, end));
+ it.moveToNoReinit(SelectFSs_impl.makePosAnnot(jcas, begin, end));
if (!it.isValid()) {
it.moveToLastNoReinit();
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
new file mode 100644
index 0000000..7f3cd95
--- /dev/null
+++ b/uimaj-core/src/test/java/org/apache/uima/cas/impl/SubiteratorTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.cas.impl;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.contentOf;
+
+import java.io.File;
+
+import org.apache.uima.UIMAFramework;
+import org.apache.uima.analysis_engine.AnalysisEngine;
+import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.FSIterator;
+import org.apache.uima.cas.test.Sentence;
+import org.apache.uima.cas.test.Token;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.resource.ResourceSpecifier;
+import org.apache.uima.test.junit_extension.JUnitExtension;
+import org.apache.uima.util.XMLInputSource;
+import org.apache.uima.util.XMLParser;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+//@formatter:off
+/**
+ * The setup:
+ * Token (super = Annotation)
+ * Sentence (super = Annotation)
+ *
+ * Annotator: (in descr) SubIteratorAnnotator
+ */
+//@formatter:on
+public class SubiteratorTest {
+
+ private static AnalysisEngine segmenter = null;
+
+ private JCas jcas;
+
+ @BeforeAll
+ static void setupClass() throws Exception {
+ File descriptorFile = JUnitExtension.getFile("CASTests/desc/TokensAndSentences.xml");
+
+ assertThat(descriptorFile).exists();
+
+ XMLParser parser = UIMAFramework.getXMLParser();
+ ResourceSpecifier spec = (ResourceSpecifier) parser.parse(new XMLInputSource(descriptorFile));
+ segmenter = UIMAFramework.produceAnalysisEngine(spec);
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ String text = contentOf(getClass().getResource("/CASTests/verjuice.txt"), UTF_8);
+
+ jcas = segmenter.newJCas();
+ jcas.setDocumentText(text);
+
+ segmenter.process(jcas);
+ }
+
+ @Test
+ public void testAnnotator() throws Exception {
+ iterateAndCheck(jcas);
+
+ iterateAndCheck(jcas);
+ }
+
+ @Test
+ public void thatTemporaryAnnotationsAreNotRetained() throws Exception {
+ var casImpl = ((CASImpl) jcas.getCas());
+ try (var ctx = casImpl.ll_forceEnableV2IdRefs(true)) {
+ var fsesBefore = new AllFSs(casImpl).getAllFSsAllViews_sofas_reachable().getAllFSsSorted();
+ var maxId = fsesBefore.stream().mapToInt(fs -> fs._id).max().getAsInt();
+
+ // This select creates a temporary annotation used to constrain the operation
+ jcas.select(Token.class).covering(0, 10).asList();
+
+ var fsesAfter = new AllFSs(casImpl).getAllFSsAllViews_sofas_reachable().getAllFSsSorted();
+ assertThat(fsesAfter) //
+ .extracting(fs -> fs.getType().getName())//
+ .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.
+ var t = new Token(jcas);
+ assertThat(t._id).isEqualTo(maxId + 2 + 1);
+ }
+ }
+
+ private void iterateAndCheck(JCas aJCas) {
+ var tokenIndex = aJCas.getAnnotationIndex(Token.class);
+ var firstSentence = aJCas.getAnnotationIndex(Sentence.class).iterator().next();
+ var tokenIterator = tokenIndex.subiterator(firstSentence);
+ var firstToken = tokenIndex.iterator().next();
+ tokenIterator.moveTo(firstToken);
+
+ // check unambiguous iterator creation
+ FSIterator<Token> it = tokenIndex.iterator(false);
+ it.moveTo(firstToken);
+ }
+}
diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/test/SubiteratorTest.java b/uimaj-core/src/test/java/org/apache/uima/cas/test/SubiteratorTest.java
deleted file mode 100644
index dbdefca..0000000
--- a/uimaj-core/src/test/java/org/apache/uima/cas/test/SubiteratorTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.cas.test;
-
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.uima.UIMAFramework;
-import org.apache.uima.analysis_engine.AnalysisEngine;
-import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
-import org.apache.uima.cas.FSIterator;
-import org.apache.uima.cas.text.AnnotationIndex;
-import org.apache.uima.jcas.JCas;
-import org.apache.uima.jcas.tcas.Annotation;
-import org.apache.uima.resource.ResourceInitializationException;
-import org.apache.uima.resource.ResourceSpecifier;
-import org.apache.uima.test.junit_extension.JUnitExtension;
-import org.apache.uima.util.FileUtils;
-import org.apache.uima.util.InvalidXMLException;
-import org.apache.uima.util.XMLInputSource;
-import org.apache.uima.util.XMLParser;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-//@formatter:off
-/**
- * The setup:
- * Token (super = Annotation)
- * Sentence (super = Annotation)
- *
- * Annotator: (in descr) SubIteratorAnnotator
- */
-//@formatter:on
-public class SubiteratorTest {
-
- private AnalysisEngine ae = null;
-
- @BeforeEach
- public void setUp() {
- File descriptorFile = JUnitExtension.getFile("CASTests/desc/TokensAndSentences.xml");
- assertTrue("Descriptor must exist: " + descriptorFile.getAbsolutePath(),
- descriptorFile.exists());
-
- try {
- XMLParser parser = UIMAFramework.getXMLParser();
- ResourceSpecifier spec = (ResourceSpecifier) parser.parse(new XMLInputSource(descriptorFile));
- this.ae = UIMAFramework.produceAnalysisEngine(spec);
- } catch (IOException e) {
- e.printStackTrace();
- assertTrue(false);
- } catch (InvalidXMLException e) {
- e.printStackTrace();
- assertTrue(false);
- } catch (ResourceInitializationException e) {
- e.printStackTrace();
- assertTrue(false);
- }
-
- }
-
- @AfterEach
- public void tearDown() {
- if (this.ae != null) {
- this.ae.destroy();
- this.ae = null;
- }
- }
-
- @Test
- public void testAnnotator() {
- File textFile = JUnitExtension.getFile("CASTests/verjuice.txt");
- String text = null;
- try {
- text = FileUtils.file2String(textFile, "utf-8");
- } catch (IOException e) {
- e.printStackTrace();
- assertTrue(false);
- }
- JCas jcas = null;
- try {
- jcas = this.ae.newJCas();
- } catch (ResourceInitializationException e) {
- e.printStackTrace();
- assertTrue(false);
- }
- jcas.setDocumentText(text);
- try {
- this.ae.process(jcas);
-
- iterateAndcheck(jcas);
-
- iterateAndcheck(jcas);
- } catch (AnalysisEngineProcessException e) {
- e.printStackTrace();
- assertTrue(false);
- } catch (ClassCastException e) {
- // UIMA-464: Subiterator.moveTo() throws ClassCastException.
- assertTrue(false);
- }
- }
-
- private void iterateAndcheck(JCas jcas) {
- AnnotationIndex<Token> tokenIndex = jcas.getAnnotationIndex(Token.class);
- Annotation sentence = jcas.getAnnotationIndex(Sentence.class).iterator().next();
- FSIterator<Token> tokenIterator = tokenIndex.subiterator(sentence);
- Annotation token = tokenIndex.iterator().next();
- // debug token.toString();
- tokenIterator.moveTo(token); // throws ClassCastException
-
- // check unambiguous iterator creation
-
- FSIterator<Token> it = tokenIndex.iterator(false);
- it.moveTo(token);
- }
-}