blob: ce50b2f79562805d335d0882826fe1246c585ed2 [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.CAS;
public class LLUnambiguousIteratorImpl implements LowLevelIterator {
private final int[] annots;
private int pos = 0;
private final int size;
// We only need those for copy.
private final LowLevelIterator theIterator;
private final LowLevelCAS theCas;
public LLUnambiguousIteratorImpl(LowLevelIterator it, LowLevelCAS cas) {
super();
this.theCas = cas;
this.theIterator = it;
this.annots = new int[it.ll_indexSize()];
final LowLevelTypeSystem ts = cas.ll_getTypeSystem();
final int annotType = ts.ll_getCodeForTypeName(CAS.TYPE_NAME_ANNOTATION);
final int startFeat = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_BEGIN);
final int endFeat = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_END);
int lastSeenEnd = 0;
int curRef;
int curType;
it.moveToFirst();
int i = 0;
// Iterate over the input iterator.
while (it.isValid()) {
// Get current ref and its type.
curRef = it.ll_get();
curType = cas.ll_getFSRefType(curRef);
if (ts.ll_subsumes(annotType, curType)) {
// Found an annotation.
if (i == 0 || (cas.ll_getIntValue(curRef, startFeat) >= lastSeenEnd)) {
// Either first annotation, or non-overlapping continuation.
this.annots[i] = curRef;
lastSeenEnd = cas.ll_getIntValue(curRef, endFeat);
++i;
}
}
it.moveToNext();
}
// The current value of i is the size of the index view provided by
// this iterator.
this.size = i;
}
public void moveToFirst() {
this.pos = 0;
}
public void moveToLast() {
this.pos = this.size - 1;
}
public boolean isValid() {
return (this.pos >= 0) && (this.pos < this.size);
}
public int ll_get() throws NoSuchElementException {
if (!this.isValid()) {
throw new NoSuchElementException();
}
return this.annots[this.pos];
}
public void moveToNext() {
++this.pos;
}
public void moveToPrevious() {
--this.pos;
}
public void moveTo(int fsRef) {
final int position = binarySearch(this.annots, fsRef, 0, this.size);
if (position >= 0) {
this.pos = position;
} else {
this.pos = -(position + 1);
}
}
public Object copy() {
LLUnambiguousIteratorImpl copy = new LLUnambiguousIteratorImpl(this.theIterator, this.theCas);
copy.pos = this.pos;
return copy;
}
public int ll_indexSize() {
return this.size;
}
public LowLevelIndex ll_getIndex() {
return this.theIterator.ll_getIndex();
}
// 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 = this.ll_getIndex().ll_compare(ele, array[i]);
if (comp == 0) {
return i;
}
if (start == end) {
if (comp < 0) {
return (-i) - 1;
}
// 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;
}
}