package org.apache.solr.request.uninverted;
import java.io.IOException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.TermEnum;
public class TermNumEnumerator extends TermEnum {
// public static Logger log = LoggerFactory.getLogger(TermNumEnumerator.class);
protected final IndexReader reader;
protected final TermIndex tindex;
protected TermEnum tenum;
protected int pos=-1;
protected Term t;
protected TermDocs termDocs;
TermNumEnumerator(IndexReader reader, TermIndex tindex) throws IOException {
this.reader = reader;
this.tindex = tindex;
}
TermNumEnumerator(IndexReader reader, TermIndex tindex, String termValue, int pos) throws IOException {
this.reader = reader;
this.tindex = tindex;
this.pos = pos;
tenum = reader.terms(tindex.createTerm(termValue));
setTerm();
}
public TermDocs getTermDocs() throws IOException {
if (termDocs==null) termDocs = reader.termDocs(t,102400);
else termDocs.seek(t);
return termDocs;
}
protected boolean setTerm() {
t = tenum.term();
if (t==null
|| t.field() != tindex.fterm.field() // intern'd compare
|| (tindex.prefix != null && !t.text().startsWith(tindex.prefix,0)) )
{
t = null;
return false;
}
return true;
}
@Override
public boolean next() throws IOException {
pos++;
boolean b = tenum.next();
if (!b) {
t = null;
return false;
}
return setTerm(); // this is extra work if we know we are in bounds...
}
@Override
public Term term() {
return t;
}
@Override
public int docFreq() {
return tenum.docFreq();
}
@Override
public void close() throws IOException {
if (tenum!=null) tenum.close();
}
public boolean skipTo(String target) throws IOException {
return skipTo(tindex.fterm.createTerm(target));
}
public boolean skipTo(Term target) throws IOException {
// already here
if (t != null && t.equals(target)) return true;
int startIdx = tindex.index.search(target.text());
if (startIdx >= 0) {
// we hit the term exactly... lucky us!
if (tenum != null) tenum.close();
tenum = reader.terms(target);
pos = startIdx << tindex.intervalBits;
return setTerm();
}
// we didn't hit the term exactly
startIdx=-startIdx-1;
if (startIdx == 0) {
// our target occurs *before* the first term
if (tenum != null) tenum.close();
tenum = reader.terms(target);
pos = 0;
return setTerm();
}
// back up to the start of the block
startIdx--;
if ((pos >> tindex.intervalBits) == startIdx && t != null && t.text().compareTo(target.text())<=0) {
// we are already in the right block and the current term is before the term we want,
// so we don't need to seek.
} else {
// seek to the right block
if (tenum != null) tenum.close();
tenum = reader.terms(target.createTerm(tindex.index.get(startIdx)));
pos = startIdx << tindex.intervalBits;
setTerm(); // should be true since it's in the index
}
while (t != null && t.text().compareTo(target.text()) < 0) {
next();
}
return t != null;
}
public boolean skipTo(int termNumber) throws IOException {
int delta = termNumber - pos;
if (delta < 0 || delta > tindex.interval || tenum==null) {
int idx = termNumber >>> tindex.intervalBits;
String base = tindex.index.get(idx);
pos = idx << tindex.intervalBits;
delta = termNumber - pos;
if (tenum != null) {tenum.close();}
tenum = reader.terms(tindex.createTerm(base));
}
while (--delta >= 0) {
boolean b = tenum.next();
if (b==false) {
t = null;
return false;
}
++pos;
}
return setTerm();
}
/** The current term number, starting at 0.
* Only valid if the previous call to next() or skipTo() returned true.
*/
public int getTermNumber() {
return pos;
}
}