/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch 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.elasticsearch.search.lookup; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; import org.apache.lucene.util.IntsRefBuilder; import java.io.IOException; import java.util.Iterator; /* * Can iterate over the positions of a term an arbitrary number of times. * */ public class CachedPositionIterator extends PositionIterator { public CachedPositionIterator(IndexFieldTerm indexFieldTerm) { super(indexFieldTerm); } // all payloads of the term in the current document in one bytes array. // payloadStarts and payloadLength mark the start and end of one payload. final BytesRefBuilder payloads = new BytesRefBuilder(); final IntsRefBuilder payloadsLengths = new IntsRefBuilder(); final IntsRefBuilder payloadsStarts = new IntsRefBuilder(); final IntsRefBuilder positions = new IntsRefBuilder(); final IntsRefBuilder startOffsets = new IntsRefBuilder(); final IntsRefBuilder endOffsets = new IntsRefBuilder(); final BytesRef payload = new BytesRef(); @Override public Iterator<TermPosition> reset() { return new Iterator<TermPosition>() { private int pos = 0; private final TermPosition termPosition = new TermPosition(); @Override public boolean hasNext() { return pos < freq; } @Override public TermPosition next() { termPosition.position = positions.intAt(pos); termPosition.startOffset = startOffsets.intAt(pos); termPosition.endOffset = endOffsets.intAt(pos); termPosition.payload = payload; payload.bytes = payloads.bytes(); payload.offset = payloadsStarts.intAt(pos); payload.length = payloadsLengths.intAt(pos); pos++; return termPosition; } @Override public void remove() { } }; } private void record() throws IOException { TermPosition termPosition; for (int i = 0; i < freq; i++) { termPosition = super.next(); positions.setIntAt(i, termPosition.position); addPayload(i, termPosition.payload); startOffsets.setIntAt(i, termPosition.startOffset); endOffsets.setIntAt(i, termPosition.endOffset); } } private void ensureSize(int freq) { if (freq == 0) { return; } startOffsets.grow(freq); endOffsets.grow(freq); positions.grow(freq); payloadsLengths.grow(freq); payloadsStarts.grow(freq); payloads.grow(freq * 8);// this is just a guess.... } private void addPayload(int i, BytesRef currPayload) { if (currPayload != null) { payloadsLengths.setIntAt(i, currPayload.length); payloadsStarts.setIntAt(i, i == 0 ? 0 : payloadsStarts.intAt(i - 1) + payloadsLengths.intAt(i - 1)); payloads.grow(payloadsStarts.intAt(i) + currPayload.length); System.arraycopy(currPayload.bytes, currPayload.offset, payloads.bytes(), payloadsStarts.intAt(i), currPayload.length); } else { payloadsLengths.setIntAt(i, 0); payloadsStarts.setIntAt(i, i == 0 ? 0 : payloadsStarts.intAt(i - 1) + payloadsLengths.intAt(i - 1)); } } @Override public void nextDoc() throws IOException { super.nextDoc(); ensureSize(freq); record(); } @Override public TermPosition next() { throw new UnsupportedOperationException(); } }