blob: 122bfeac550b0c442e9ac3741264914e95165600 [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.impl;
import java.util.NoSuchElementException;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.admin.FSIndexComparator;
import org.apache.uima.internal.util.ComparableIntPointerIterator;
import org.apache.uima.internal.util.IntComparator;
import org.apache.uima.internal.util.IntPointerIterator;
import org.apache.uima.internal.util.IntVector;
public class FSBagIndex extends FSLeafIndexImpl {
private class IntVectorIterator implements ComparableIntPointerIterator, LowLevelIterator {
private int itPos;
private IntComparator comp;
private int modificationSnapshot; // to catch illegal modifications
private int[] detectIllegalIndexUpdates; // shared copy with Index Repository
private int typeCode;
public boolean isConcurrentModification() {
return this.modificationSnapshot != this.detectIllegalIndexUpdates[this.typeCode];
}
public void resetConcurrentModification() {
this.modificationSnapshot = this.detectIllegalIndexUpdates[this.typeCode];
}
private IntVectorIterator() {
super();
this.itPos = 0;
}
private IntVectorIterator(IntComparator comp) {
this();
this.comp = comp;
}
public boolean isValid() {
return ((this.itPos >= 0) && (this.itPos < FSBagIndex.this.index.size()));
}
public void moveToFirst() {
this.itPos = 0;
}
public void moveToLast() {
this.itPos = FSBagIndex.this.index.size() - 1;
}
public void moveToNext() {
++this.itPos;
}
public void moveToPrevious() {
--this.itPos;
}
public int ll_get() {
if (!isValid()) {
throw new NoSuchElementException();
}
return FSBagIndex.this.index.get(this.itPos);
}
/**
* @see org.apache.uima.internal.util.IntPointerIterator#copy()
*/
public Object copy() {
IntVectorIterator copy = new IntVectorIterator(this.comp);
copy.itPos = this.itPos;
return copy;
}
/**
* @see java.lang.Comparable#compareTo(Object)
*/
public int compareTo(Object o) throws NoSuchElementException {
return this.comp.compare(get(), ((IntVectorIterator) o).get());
}
/**
* @see org.apache.uima.internal.util.IntPointerIterator#moveTo(int)
*/
public void moveTo(int i) {
final int position = find(i);
if (position >= 0) {
this.itPos = position;
} else {
this.itPos = -(position + 1);
}
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelIterator#ll_get()
*/
public int get() throws NoSuchElementException {
return ll_get();
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelIterator#moveToNext()
*/
public void inc() {
moveToNext();
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelIterator#moveToPrevious()
*/
public void dec() {
moveToPrevious();
}
public int ll_indexSize() {
return FSBagIndex.this.size();
}
public LowLevelIndex ll_getIndex() {
return FSBagIndex.this;
}
}
// The index, a vector of FS references.
private IntVector index;
private int initialSize;
FSBagIndex(CASImpl cas, Type type, int initialSize, int indexType) {
super(cas, type, indexType);
this.initialSize = initialSize;
this.index = new IntVector(initialSize);
}
/**
* @see org.apache.uima.cas.impl.FSLeafIndexImpl#init(org.apache.uima.cas.admin.FSIndexComparator)
*/
boolean init(FSIndexComparator comp) {
// The comparator for a bag index must be empty, except for the type. If
// it
// isn't, we create an empty one.
FSIndexComparator newComp;
if (comp.getNumberOfKeys() > 0) {
newComp = new FSIndexComparatorImpl(this.lowLevelCAS);
newComp.setType(comp.getType());
} else {
newComp = comp;
}
return super.init(newComp);
}
IntVector getVector() {
return this.index;
}
public void flush() {
this.index = new IntVector(this.initialSize);
}
public final boolean insert(int fs) {
this.index.add(fs);
return true;
}
/*
* public final boolean insert(int fs) { // First, check if we can insert at the end. final int []
* indexArray = this.index.getArray(); final int length = this.index.size(); if (length == 0) {
* this.index.add(fs); return true; } final int last = indexArray[length - 1]; if (compare(last,
* fs) < 0) { index.add(fs); return true; } final int pos = this.binarySearch(indexArray, fs, 0,
* length); if (pos >= 0) { return false; } index.add(-(pos+1), fs); return true; } // public
* IntIteratorStl iterator() { // return new IntVectorIterator(); // }
*/
// private final int find(int ele) {
// return this.index.indexOf(ele);
// // return binarySearch(this.index.getArray(), ele, 0, this.index.size());
// }
private final int find(int ele) {
final int[] array = this.index.getArray();
final int max = this.index.size();
for (int i = 0; i < max; i++) {
if (compare(ele, array[i]) == 0) {
return i;
}
}
return -1;
}
public int compare(int fs1, int fs2) {
if (fs1 < fs2) {
return -1;
} else if (fs1 > fs2) {
return 1;
} else {
return 0;
}
}
/*
* // Do binary search on index. private final int binarySearch(int [] array, int ele, int start,
* int end) { --end; // Make end a legal value. int i; // Current position int comp; // Compare
* value while (start <= end) { i = (start + end) / 2; comp = compare(ele, array[i]); if (comp ==
* 0) { return i; } if (start == end) { if (comp < 0) { return (-i)-1; } else { // comp > 0 return
* (-i)-2; // (-(i+1))-1 } } if (comp < 0) { end = i-1; } else { // comp > 0 start = i+1; } } //
* This means that the input span is empty. return (-start)-1; }
*/
public ComparableIntPointerIterator pointerIterator(IntComparator comp,
int[] detectIllegalIndexUpdates, int typeCode) {
IntVectorIterator ivi = new IntVectorIterator(comp);
ivi.modificationSnapshot = detectIllegalIndexUpdates[typeCode];
ivi.detectIllegalIndexUpdates = detectIllegalIndexUpdates;
ivi.typeCode = typeCode;
return ivi;
}
/**
* @see org.apache.uima.cas.impl.FSLeafIndexImpl#refIterator()
*/
protected IntPointerIterator refIterator() {
return new IntVectorIterator();
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelIndex#ll_iterator()
*/
public LowLevelIterator ll_iterator() {
return new IntVectorIterator();
}
/**
* @see org.apache.uima.cas.impl.FSLeafIndexImpl#refIterator(int)
*/
protected IntPointerIterator refIterator(int fsCode) {
IntVectorIterator it = new IntVectorIterator();
final int pos = find(fsCode);
if (pos >= 0) {
it.itPos = pos;
} else {
it.itPos = -(pos + 1);
}
return it;
}
/**
* @see org.apache.uima.cas.FSIndex#contains(FeatureStructure)
*/
public boolean contains(FeatureStructure fs) {
return (find(((FeatureStructureImpl) fs).getAddress()) >= 0);
}
public FeatureStructure find(FeatureStructure fs) {
// Cast to implementation.
FeatureStructureImpl fsi = (FeatureStructureImpl) fs;
// Use internal find method.
final int resultAddr = find(fsi.getAddress());
// If found, create new FS to return.
if (resultAddr > 0) {
return fsi.getCASImpl().createFS(this.index.get(resultAddr));
}
// Not found.
return null;
}
/**
* @see org.apache.uima.cas.FSIndex#size()
*/
public int size() {
return this.index.size();
}
/**
* @see org.apache.uima.cas.impl.FSLeafIndexImpl#deleteFS(org.apache.uima.cas.FeatureStructure)
*/
public void deleteFS(FeatureStructure fs) {
final int addr = ((FeatureStructureImpl) fs).getAddress();
final int pos = this.index.indexOf(addr);
if (pos >= 0) {
this.index.remove(pos);
}
}
public void remove(int fsRef) {
final int pos = this.index.indexOf(fsRef);
if (pos >= 0) {
this.index.remove(pos);
}
}
public int hashCode() {
throw new UnsupportedOperationException();
}
}