blob: 30fc01feb0ef99b7d41a9926758c2ff32e1ef6db [file] [log] [blame]
/*
* 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 java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import junit.framework.TestCase;
import org.apache.uima.UIMAFramework;
import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CASRuntimeException;
import org.apache.uima.cas.FSIndex;
import org.apache.uima.cas.FSIndexRepository;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.Feature;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.impl.CASImpl;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.internal.util.IntVector;
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.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
import org.apache.uima.util.XMLParser;
/**
* Class comment for IteratorTest.java goes here.
*
*/
public class IteratorTest extends TestCase {
private CASImpl cas;
private TypeSystem ts;
private Type annotationType;
private Type stringType;
private Type tokenType;
private Type intType;
private Type tokenTypeType;
private Type wordType;
private Feature tokenTypeFeat;
private Feature lemmaFeat;
private Feature sentLenFeat;
private Feature tokenFloatFeat;
private Feature startFeature;
private Type sentenceType;
/**
* Constructor for FilteredIteratorTest.
*
* @param arg0
*/
public IteratorTest(String arg0) {
super(arg0);
}
public void setUp() {
// try {
// this.cas = (CASImpl) CASInitializer.initCas(new CASTestSetup());
// assertTrue(this.cas != null);
// this.ts = this.cas.getTypeSystem();
// assertTrue(this.ts != null);
// } catch (Exception e) {
// e.printStackTrace();
// assertTrue(false);
// }
File descriptorFile = JUnitExtension.getFile("CASTests/desc/casTestCaseDescriptor.xml");
assertTrue("Descriptor must exist: " + descriptorFile.getAbsolutePath(), descriptorFile.exists());
try {
XMLParser parser = UIMAFramework.getXMLParser();
ResourceSpecifier spec = (ResourceSpecifier) parser.parse(new XMLInputSource(descriptorFile));
AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(spec);
this.cas = (CASImpl) ae.newCAS();
assertTrue(this.cas != null);
this.ts = this.cas.getTypeSystem();
assertTrue(this.ts != null);
} catch (IOException e) {
e.printStackTrace();
assertTrue(false);
} catch (InvalidXMLException e) {
e.printStackTrace();
assertTrue(false);
} catch (ResourceInitializationException e) {
e.printStackTrace();
assertTrue(false);
}
this.stringType = this.ts.getType(CAS.TYPE_NAME_STRING);
assertTrue(this.stringType != null);
this.tokenType = this.ts.getType(CASTestSetup.TOKEN_TYPE);
assertTrue(this.stringType != null);
this.intType = this.ts.getType(CAS.TYPE_NAME_INTEGER);
assertTrue(this.intType != null);
this.tokenTypeType = this.ts.getType(CASTestSetup.TOKEN_TYPE_TYPE);
assertTrue(this.tokenTypeType != null);
this.wordType = this.ts.getType(CASTestSetup.WORD_TYPE);
assertTrue(this.wordType != null);
this.tokenTypeFeat = this.ts.getFeatureByFullName(CASTestSetup.TOKEN_TYPE_FEAT_Q);
assertTrue(this.tokenTypeFeat != null);
this.lemmaFeat = this.ts.getFeatureByFullName(CASTestSetup.LEMMA_FEAT_Q);
assertTrue(this.lemmaFeat != null);
this.sentLenFeat = this.ts.getFeatureByFullName(CASTestSetup.SENT_LEN_FEAT_Q);
assertTrue(this.sentLenFeat != null);
this.tokenFloatFeat = this.ts.getFeatureByFullName(CASTestSetup.TOKEN_FLOAT_FEAT_Q);
assertTrue(this.tokenFloatFeat != null);
this.startFeature = this.ts.getFeatureByFullName(CAS.FEATURE_FULL_NAME_BEGIN);
assertTrue(this.startFeature != null);
this.sentenceType = this.ts.getType(CASTestSetup.SENT_TYPE);
assertTrue(this.sentenceType != null);
this.annotationType = this.ts.getType(CAS.TYPE_NAME_ANNOTATION);
assertTrue(this.annotationType != null);
}
public void tearDown() {
this.cas = null;
this.ts = null;
this.stringType = null;
this.tokenType = null;
this.intType = null;
this.tokenTypeType = null;
this.wordType = null;
this.tokenTypeFeat = null;
this.lemmaFeat = null;
this.sentLenFeat = null;
this.tokenFloatFeat = null;
this.startFeature = null;
this.sentenceType = null;
this.annotationType = null;
}
public void testGetIndexes() {
Iterator it = this.cas.getIndexRepository().getIndexes();
while (it.hasNext()) {
assertTrue(it.next() instanceof FSIndex);
}
}
public void testIterator() {
for (int i = 0; i < 10; i++) {
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.annotationType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.sentenceType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.tokenType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.tokenType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.tokenType, i * 2, (i * 2) + 1));
}
for (int i = 19; i >= 10; i--) {
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.annotationType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.sentenceType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.tokenType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.tokenType, i * 2, (i * 2) + 1));
this.cas.getIndexRepository().addFS(
this.cas.createAnnotation(this.tokenType, i * 2, (i * 2) + 1));
}
// /////////////////////////////////////////////////////////////////////////
// Create a reverse iterator for the set index and check that the result
// is the same as for forward iteration.
IntVector v = new IntVector();
FSIndex bagIndex = this.cas.getIndexRepository().getIndex(CASTestSetup.ANNOT_BAG_INDEX);
FSIndex setIndex = this.cas.getIndexRepository().getIndex(CASTestSetup.ANNOT_SET_INDEX);
FSIndex sortedIndex = this.cas.getIndexRepository().getIndex(CASTestSetup.ANNOT_SORT_INDEX);
FSIterator it = setIndex.iterator();
AnnotationFS a, b = null;
while (it.isValid()) {
a = (AnnotationFS) it.get();
if (b != null) {
assertTrue(setIndex.compare(b, a) <= 0);
}
b = a;
// System.out.println(
// a.getType().getName() + " - " + a.getStart() + " - " +
// a.getEnd());
v.add(it.get().hashCode());
it.moveToNext();
}
// System.out.println("Number of annotations: " + v.size());
assertTrue(v.size() == ((10 * 3) + (10 * 3)));
it = setIndex.iterator();
it.moveToLast();
int current = v.size() - 1;
while (it.isValid() && (current >= 0)) {
// System.out.println("Current: " + current);
a = (AnnotationFS) it.get();
// System.out.println(
// a.getType().getName() + " - " + a.getStart() + " - " +
// a.getEnd());
assertTrue(it.get().hashCode() == v.get(current));
it.moveToPrevious();
--current;
}
assertTrue(current == -1);
assertFalse(it.isValid());
// /////////////////////////////////////////////////////////////////////////
// Use an iterator to move forwards and backwards and make sure the
// sequence
// remains constant.
it = setIndex.iterator();
it.moveToFirst(); // This is redundant.
current = 1;
// System.out.println("Codes: " + v);
while (current < (v.size() - 1)) {
it.moveToNext();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current));
it.moveToNext();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current + 1));
it.moveToPrevious();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current));
++current;
}
// also test Java-style iteration
Iterator javaIt = setIndex.iterator();
current = 0;
while (javaIt.hasNext()) {
assertEquals(javaIt.next().hashCode(), v.get(current++));
}
// /////////////////////////////////////////////////////////////////////////
// Test fast fail.
it = bagIndex.iterator(); // use bag index, remove add last one
// (preserves order for other tests).
it.moveToLast();
a = (AnnotationFS) it.get();
it = setIndex.iterator(); // back to set iterator to do testing
this.cas.getIndexRepository().removeFS(a);
this.cas.getIndexRepository().addFS(a);
boolean ok = false;
try {
it.next(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
ok = false;
try {
it.next(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
it.moveTo(a);
ok = false;
try {
it.next(); // should not throw
ok = true;
} catch (ConcurrentModificationException e) {
// checking this with the ok variable
}
assertTrue(ok);
// /////////////////////////////////////////////////////////////////////////
// Test sorted index.
// FSIndex sortedIndex = cas.getAnnotationIndex(); // using different
// typeOrder
// System.out.println("Number of annotations: " + sortedIndex.size());
// for (it = sortedIndex.iterator(); it.hasNext(); it.next()) {
// System.out.println(it.get());
// }
assertTrue(sortedIndex.size() == 100);
v = new IntVector();
it = sortedIndex.iterator();
it.moveToFirst();
b = null;
while (it.isValid()) {
a = (AnnotationFS) it.get();
// System.out.println(a);
assertTrue(a != null);
if (b != null) {
// System.out.println("b = " + b);
assertTrue(sortedIndex.compare(b, a) <= 0);
}
b = a;
v.add(a.hashCode());
it.moveToNext();
}
assertTrue(sortedIndex.size() == v.size());
// Test moveTo()
ArrayList list = new ArrayList();
it = this.cas.getAnnotationIndex().iterator();
for (it.moveToFirst(); it.isValid(); it.moveToNext()) {
list.add(it.get());
}
// AnnotationFS an;
for (int i = 0; i < list.size(); i++) {
// System.out.println("Iteration: " + i);
it.moveToFirst();
it.moveTo((FeatureStructure) list.get(i));
assertTrue(((AnnotationFS) it.get()).getBegin() == ((AnnotationFS) list.get(i)).getBegin());
assertTrue(((AnnotationFS) it.get()).getEnd() == ((AnnotationFS) list.get(i)).getEnd());
}
// Check that reverse iterator produces reverse sequence.
// Note: this test is not valid. It is by no means guaranteed that reverse iteration of a
// sorted index will produce the reverse result of forward iteration. I no two annotations
// are equal wrt the sort order, this works of course. However, if some FSs are equal wrt
// the sort order, those may be returned in any order.
// it.moveToLast();
// System.out.println(it.get());
// for (int i = v.size() - 1; i >= 0; i--) {
// assertTrue(it.isValid());
// assertTrue(it.get().hashCode() == v.get(i));
// it.moveToPrevious();
// }
// /////////////////////////////////////////////////////////////////////////
// Use an iterator to move forwards and backwards and make sure the
// sequence
// remains constant.
it = sortedIndex.iterator();
it.moveToFirst(); // This is redundant.
current = 1;
// System.out.println("Codes: " + v);
while (current < (v.size() - 1)) {
it.moveToNext();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current));
it.moveToNext();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current + 1));
it.moveToPrevious();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current));
++current;
}
// also test Java-style iteration
javaIt = sortedIndex.iterator();
current = 0;
while (javaIt.hasNext()) {
assertEquals(javaIt.next().hashCode(), v.get(current++));
}
// /////////////////////////////////////////////////////////////////////////
// Test fast fail.
it = bagIndex.iterator(); // use bag index, remove add last one
// (preserves order for other tests).
it.moveToLast();
a = (AnnotationFS) it.get();
// for (it = sortedIndex.iterator(); it.hasNext(); it.next()) {
// System.out.println(it.get());
// }
it = sortedIndex.iterator();
it.next();
it.next();
this.cas.getIndexRepository().removeFS(a);
this.cas.getIndexRepository().addFS(a);
ok = false;
try {
it.get(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
ok = false;
try {
it.next(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
ok = false;
try {
it.moveToNext(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
it.moveTo(a);
ok = false;
try {
it.next(); // should not throw
ok = true;
} catch (ConcurrentModificationException e) {
// checking with boolean "ok"
}
assertTrue(ok);
sortedIndex = null;
// /////////////////////////////////////////////////////////////////////////
// Test bag index.
// System.out.println("Number of annotations: " + sortedIndex.size());
assertTrue(bagIndex.size() == 100);
v = new IntVector();
it = bagIndex.iterator();
b = null;
while (it.isValid()) {
a = (AnnotationFS) it.get();
assertTrue(a != null);
if (b != null) {
assertTrue(bagIndex.compare(b, a) <= 0);
}
b = a;
v.add(a.hashCode());
it.moveToNext();
}
assertTrue(bagIndex.size() == v.size());
// Check that reverse iterator produces reverse sequence.
it.moveToLast();
for (int i = v.size() - 1; i >= 0; i--) {
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(i));
it.moveToPrevious();
}
// /////////////////////////////////////////////////////////////////////////
// Use an iterator to move forwards and backwards and make sure the
// sequence
// remains constant.
it = bagIndex.iterator();
it.moveToFirst(); // This is redundant.
current = 1;
// System.out.println("Codes: " + v);
while (current < (v.size() - 1)) {
it.moveToNext();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current));
it.moveToNext();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current + 1));
it.moveToPrevious();
assertTrue(it.isValid());
assertTrue(it.get().hashCode() == v.get(current));
++current;
}
// also test Java-style iteration
javaIt = bagIndex.iterator();
current = 0;
while (javaIt.hasNext()) {
assertEquals(javaIt.next().hashCode(), v.get(current++));
}
// Test iterator copy.
FSIterator source, copy;
source = this.cas.getAnnotationIndex().iterator();
// Count items.
int count = 0;
for (source.moveToFirst(); source.isValid(); source.moveToNext()) {
++count;
}
final int max = count;
count = 0;
source.moveToFirst();
copy = source.copy();
copy.moveToFirst();
// System.out.println("Max: " + max);
while (count < max) {
// System.out.println("Count: " + count);
assertTrue(source.isValid());
assertTrue(copy.isValid());
String out = source.get().toString() + copy.get().toString();
assertTrue(out, source.get().equals(copy.get()));
source.moveToNext();
copy.moveToNext();
++count;
}
// /////////////////////////////////////////////////////////////////////////
// Test fast fail.
it = bagIndex.iterator(); // use bag index, remove add last one
// (preserves order for other tests).
it.moveToLast();
a = (AnnotationFS) it.get();
this.cas.getIndexRepository().removeFS(a);
this.cas.getIndexRepository().addFS(a);
ok = false;
try {
it.get(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
it.moveToLast();
it.moveToPrevious();
it.moveToPrevious();
it.moveToPrevious();
it.moveToNext();
this.cas.getIndexRepository().removeFS(a);
this.cas.getIndexRepository().addFS(a);
ok = false;
try {
it.moveToNext(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
ok = false;
try {
it.moveToPrevious(); // should throw
} catch (ConcurrentModificationException e) {
ok = true;
}
assertTrue(ok);
it.moveTo(a);
ok = false;
try {
it.next(); // should not throw
ok = true;
} catch (ConcurrentModificationException e) {
// checking with boolean "ok"
}
assertTrue(ok);
}
/**
* Test deleting FSs from indexes.
*/
public void testDelete() {
// Create a bunch of FSs.
FeatureStructure[] fsArray = new FeatureStructure[100];
FSIndexRepository ir = this.cas.getIndexRepository();
for (int i = 0; i < fsArray.length; i++) {
fsArray[i] = this.cas.createAnnotation(this.tokenType, i * 5, (i * 5) + 4);
ir.addFS(fsArray[i]);
}
FSIndex setIndex = this.cas.getIndexRepository().getIndex(CASTestSetup.ANNOT_SET_INDEX,
this.tokenType);
FSIterator setIt = setIndex.iterator();
FSIndex sortedIndex = this.cas.getAnnotationIndex(this.tokenType);
FSIterator sortedIt = sortedIndex.iterator();
FSIndex bagIndex = ir.getIndex(CASTestSetup.ANNOT_BAG_INDEX, this.tokenType);
FSIterator bagIt = bagIndex.iterator();
// For each index, check that the FSs are actually in the index.
for (int i = 0; i < fsArray.length; i++) {
setIt.moveTo(fsArray[i]);
assertTrue(setIt.isValid());
assertTrue(setIt.get().equals(fsArray[i]));
bagIt.moveTo(fsArray[i]);
assertTrue(bagIt.isValid());
assertTrue(bagIt.get().equals(fsArray[i]));
sortedIt.moveTo(fsArray[i]);
assertTrue(sortedIt.isValid());
assertTrue(sortedIt.get().equals(fsArray[i]));
}
// Remove an annotation, then add it again. Try setting the iterators to
// that FS. The iterator should either be invalid, or point to a
// different FS.
for (int i = 0; i < fsArray.length; i++) {
ir.removeFS(fsArray[i]);
setIt.moveTo(fsArray[i]);
if (setIt.isValid()) {
int oldRef = this.cas.ll_getFSRef(fsArray[i]);
int newRef = this.cas.ll_getFSRef(setIt.get());
assertTrue(oldRef != newRef);
assertTrue(!setIt.get().equals(fsArray[i]));
}
bagIt.moveTo(fsArray[i]);
if (bagIt.isValid()) {
assertTrue(!bagIt.get().equals(fsArray[i]));
}
sortedIt.moveTo(fsArray[i]);
if (sortedIt.isValid()) {
assertTrue(!sortedIt.get().equals(fsArray[i]));
}
ir.addFS(fsArray[i]);
}
// Remove all annotations.
for (int i = 0; i < fsArray.length; i++) {
ir.removeFS(fsArray[i]);
}
// All iterators should be invalidated when being reset.
bagIt.moveToFirst();
assertFalse(bagIt.isValid());
setIt.moveToFirst();
assertFalse(setIt.isValid());
sortedIt.moveToFirst();
assertFalse(sortedIt.isValid());
}
public void testInvalidIndexRequest() {
boolean exc = false;
try {
this.cas.getIndexRepository().getIndex(CASTestSetup.ANNOT_BAG_INDEX, this.stringType);
} catch (CASRuntimeException e) {
exc = true;
}
assertTrue(exc);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(IteratorTest.class);
}
}