/* * Copyright (C) 2014 Indeed Inc. * * Licensed 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 com.indeed.flamdex.lucene; import com.indeed.flamdex.fieldcache.UnsortedIntTermDocIterator; import org.apache.log4j.Logger; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; import org.apache.lucene.index.TermEnum; import java.io.IOException; /** * @author jsgroth */ final class LuceneUnsortedIntTermDocIterator implements UnsortedIntTermDocIterator { private static final Logger log = Logger.getLogger(LuceneUnsortedIntTermDocIterator.class); private final String field; private final TermEnum terms; private final TermDocs termDocs; private long currentTerm; private boolean first = true; LuceneUnsortedIntTermDocIterator(String field, TermEnum terms, TermDocs termDocs) { this.field = field.intern(); this.terms = terms; this.termDocs = termDocs; } static LuceneUnsortedIntTermDocIterator create(final IndexReader r, final String field) throws IOException { final TermEnum terms = r.terms(new Term(field, "")); final TermDocs termDocs; try { termDocs = r.termDocs(); } catch (IOException e) { try { terms.close(); } catch (IOException e1) { log.error("error closing TermEnum", e1); } throw e; } return new LuceneUnsortedIntTermDocIterator(field, terms, termDocs); } @Override public boolean nextTerm() { try { return innerNextTerm(); } catch (IOException e) { throw new RuntimeException(e); } } @SuppressWarnings({"StringEquality"}) private boolean innerNextTerm() throws IOException { // loop instead of calling itself recursively to avoid potential stack overflow while (true) { if (!first) { if (!terms.next()) return false; } else { first = false; } final Term term = terms.term(); if (term == null || term.field() != field) return false; try { currentTerm = Long.parseLong(term.text()); } catch (NumberFormatException e) { continue; } termDocs.seek(terms); return true; } } @Override public long term() { return currentTerm; } @Override public int nextDocs(int[] docIdBuffer) { try { return innerNextDocs(docIdBuffer); } catch (IOException e) { throw new RuntimeException(e); } } private int innerNextDocs(int[] docIdBuffer) throws IOException { int i = 0; while (i < docIdBuffer.length && termDocs.next()) { docIdBuffer[i++] = termDocs.doc(); } return i; } @Override public void close() { try { terms.close(); } catch (IOException e) { log.error("error closing TermEnum", e); } try { termDocs.close(); } catch (IOException e) { log.error("error closing TermDocs", e); } } }