blob: 74360c02f360f09ff88c7741ed71b13b7a27f959 [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.AbstractCollection;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
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.CopyOnWriteOrderedFsSet_array;
import org.apache.uima.internal.util.OrderedFsSet_array;
import org.apache.uima.jcas.cas.TOP;
import org.apache.uima.jcas.tcas.Annotation;
/**
* Common index impl for set and sorted indexes.
*
* Differences:
* - Number of "equal" (but not identical) FSs: Set: 1, Sorted, N
* - Iterators: Set: unordered, Sorted: ordered
*
* This is an index over just one type (excluding subtypes)
*
* Uses key augmented by a least-significant additional key: the _id field of the FS itself,
* to allow multiple otherwise equal (but not ==) FSs to be in the index.
*
* @param <T> the Java class type for this index
*/
final public class FsIndex_set_sorted<T extends FeatureStructure> extends FsIndex_singletype<T> {
// /**h
// * This impl of sorted set interface allows using the bulk add operation implemented in Java's
// * TreeSet - that tests if the argument being passed in is an instance of SortedSet and does a fast insert.
// */
// The index, a custom high-performance array impl
final private OrderedFsSet_array<T> indexedFSs;
// only an optimization used for select.covering for AnnotationIndexes
private int maxAnnotSpan = -1;
FsIndex_set_sorted(CASImpl cas, Type type, int indexType, FSIndexComparator comparatorForIndexSpecs) {
super(cas, type, indexType, comparatorForIndexSpecs);
this.indexedFSs = new OrderedFsSet_array<T>(comparatorNoTypeWithID, comparatorNoTypeWithoutID);
}
@Override
public void flush() {
super.flush();
this.indexedFSs.clear();
}
/**
* @see org.apache.uima.cas.FSIndex#contains(FeatureStructure)
* @param templateKey the feature structure
* @return true if the fs is contained
*/
@Override
public boolean contains(FeatureStructure templateKey) {
T r = find(templateKey);
return r != null;
}
/* (non-Javadoc)
* @see org.apache.uima.cas.impl.FsIndex_singletype#insert(org.apache.uima.cas.FeatureStructure)
*/
@Override
void insert(T fs) {
// past the initial load, or item is not > previous largest item to be added
maybeCopy();
if (isAnnotIdx) {
int span = ((Annotation)fs).getEnd() - ((Annotation)fs).getBegin();
if (span > maxAnnotSpan) {
maxAnnotSpan = span;
}
}
indexedFSs.add(fs, isSorted()
? comparatorNoTypeWithID
: comparatorNoTypeWithoutID);
}
/**
* find any arbitrary matching FS
* two comparators: cp, and cpx (has extra id comparing)
*
* First find an FS in the index that's the smallest that's GE to key using cpx
* - if none found, then all of the entries in the index are LessThan the key (using cpx);
* but one might be equal using cp
* -- if one or more would be equal using cp, it would be because
* the only reason for the inequality using cpx was due to the _id miscompare.
* Therefore we only need to check the last of the previous ones to see if it is cp equal
* - if we find one that is GE using cpx,
* -- if it is equal then return it (any equal one is ok)
* -- if it is GT, then the ones preceding it are LessThan (using cpx) the key.
* Do the same check as above to see if the last of the preceding ones is equal using cp.
*
* @param templateKey the matching fs template
* @return an arbitrary fs that matches
*/
@Override
public T find(FeatureStructure templateKey) {
int pos = this.indexedFSs.findWithoutID((TOP)templateKey);
return (pos >= 0)
? this.indexedFSs.getAtPos(pos)
: null;
}
// @Override
// public T find(FeatureStructure templateKey) {
// if (null == templateKey || this.indexedFSs.isEmpty()) {
// return null;
// }
// TOP found;
// TOP templateKeyTop = (TOP) templateKey;
// TOP fs1GEfs = this.indexedFSs.ceiling(templateKeyTop);
//
// if (fs1GEfs == null) { // then all elements are less-that the templateKey
// found = indexedFSs.lower(templateKeyTop); //highest of elements less-than the template key
// return (found == null)
// ? null
// : (comparatorWithoutID.compare(found, templateKeyTop) == 0)
// ? (T)found
// : null;
// }
//
// // fs1GEfs is the least element that is greater-than-or-equal to the template key, using the fine-grained comparator
// if (0 == comparatorWithoutID.compare(fs1GEfs, templateKeyTop)) {
// return (T) fs1GEfs;
// }
//
// // fs1GEfs not null, GreaterThan the templateKey using comparatorWithoutID
// // Therefore, the ones preceding it are LE using comparatorWithoutID
// found = indexedFSs.lower(templateKeyTop); // the greatest element in this set strictly less than the templateKey
// return (found == null)
// ? null
// : (comparatorWithoutID.compare(found, templateKeyTop) == 0)
// ? (T)found
// : null;
// }
//
// public T findLeftmost(TOP templateKey) {
// // descending iterator over elements LessThan templateKey
// // iterator is over TOP, not T, to make compare easier
// Iterator<TOP> it = indexedFSs.headSet(templateKey, false).descendingIterator();
//
// TOP elementBefore = null;
// TOP lastEqual = null;
// // move to left until run out or have element not equal using compareWihtoutID to templateKey
// while (it.hasNext()) {
// if (0 != comparatorWithoutID.compare(elementBefore = it.next(), templateKey)) {
// break;
// }
// lastEqual = elementBefore;
// }
//
// if (!it.hasNext()) { // moved past beginning
// return (T) elementBefore; // might return null to indicate not found
// }
// return (T) lastEqual;
// }
/**
* @see org.apache.uima.cas.FSIndex#size()
*/
@Override
public int size() {
return this.indexedFSs.size()/* + itemsToBeAdded.size()*/;
}
/**
* This code is written to remove (if it exists)
* the exact FS, not just one which matches in the sort comparator.
*
* @see org.apache.uima.cas.impl.FSLeafIndexImpl#deleteFS(org.apache.uima.cas.FeatureStructure)
* @param fs the feature structure to remove
* @return true if it was in the index previously
*/
/**
*
*/
@Override
public boolean deleteFS(T fs) {
if (((TOP)fs)._getTypeImpl() != this.type) {
throw new IllegalArgumentException(
String.format("Wrong type %s passed to deleteFS of index over type %s",
((TOP)fs)._getTypeImpl().getName(), this.type.getName()));
}
// maybeProcessBulkAdds(); // moved to OrderedFsSet_array class
maybeCopy();
return this.indexedFSs.remove(fs);
}
@Override
protected void bulkAddTo(List<T> v) {
Collection<T> coll = new AbstractCollection<T>() {
@Override
public Iterator<T> iterator() { return null; }
@Override
public int size() { return FsIndex_set_sorted.this.size(); }
/* (non-Javadoc)
* @see java.util.AbstractCollection#toArray()
*/
@Override
public T[] toArray() {
return (T[]) indexedFSs.toArray();
}
};
v.addAll(coll);
}
@Override
public LowLevelIterator<T> iterator() {
return iterator(IS_ORDERED, IS_TYPE_ORDER);
}
/* (non-Javadoc)
* @see org.apache.uima.cas.impl.FsIndex_singletype#iterator(boolean, boolean)
* orderNotNeeded - ignored, because for a single index type, order always used
*/
@Override
public LowLevelIterator<T> iterator(boolean orderNotNeeded, boolean ignoreType) {
CopyOnWriteIndexPart cow_wrapper = getNonNullCow();
// if index is empty, return never-the-less a real iterator,
// not an empty one, because it may become non-empty
Comparator<TOP> comparatorMaybeNoTypeWithoutID = ignoreType ? comparatorNoTypeWithoutID : comparatorWithoutID;
return casImpl.inPearContext()
? new FsIterator_set_sorted_pear<T>(this, cow_wrapper, comparatorMaybeNoTypeWithoutID)
: new FsIterator_set_sorted2<T>(this, cow_wrapper, comparatorMaybeNoTypeWithoutID); }
@Override
protected CopyOnWriteIndexPart createCopyOnWriteIndexPart() {
if (CASImpl.traceCow) {
this.casImpl.traceCowCopy(this);
}
return new CopyOnWriteOrderedFsSet_array(indexedFSs);
}
@Override
public int ll_maxAnnotSpan() {
return maxAnnotSpan;
}
/* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@Override
public int compare(FeatureStructure o1, FeatureStructure o2) {
return comparatorWithoutID.compare((TOP)o1, (TOP)o2);
}
}