package org.xbib.elasticsearch.index.analysis.combo;
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import java.io.IOException;
/**
* A {@link org.apache.lucene.analysis.TokenStream} wrapper that keeps track of
* the current term position of the given TokenStream,
* and defines a comparison order.
*/
public class PositionedTokenStream extends TokenFilter implements Comparable<PositionedTokenStream> {
// Attributes to track
private final OffsetAttribute offsetAttr;
private final PositionIncrementAttribute posAttr;
/**
* Position tracker.
*/
private int position;
public PositionedTokenStream(TokenStream input) {
super(input);
// Force loading/adding these attributes
// won't do much bad if they're not read/written
offsetAttr = input.addAttribute(OffsetAttribute.class);
posAttr = input.addAttribute(PositionIncrementAttribute.class);
this.position = 0;
}
/**
* Returns the tracked current token position.
*
* @return The accumulated position increment attribute values.
*/
public int getPosition() {
return position;
}
/*
* "TokenStream interface"
*/
public final boolean incrementToken() throws IOException {
boolean rtn = input.incrementToken();
if (!rtn) {
position = Integer.MAX_VALUE;
}
// Track accumulated position
position += posAttr.getPositionIncrement();
return rtn;
}
public void end() throws IOException {
input.end();
position = 0;
}
public void reset() throws IOException {
input.reset();
position = 0;
}
public void close() throws IOException {
input.close();
position = 0;
}
/**
* Permit ordering by reading order: term position, then term offsets (start, then end).
*/
@Override
public int compareTo(PositionedTokenStream that) {
// Nullity checks
if (that == null) {
return 1;
}
// Position checks
if (this.position != that.position) {
return this.position - that.position;
}
// TokenStream nullity checks
if (that.input == null) {
if (this.input == null) {
return 0;
} else {
return 1;
}
} else if (this.input == null) {
return -1;
}
// Order by reading order, using offsets
if (this.offsetAttr != null && that.offsetAttr != null) {
int a = this.offsetAttr.startOffset();
int b = that.offsetAttr.startOffset();
if (a != b) {
return a - b;
}
a = this.offsetAttr.endOffset();
b = that.offsetAttr.endOffset();
return a - b;
} else if (that.offsetAttr == null) {
if (this.offsetAttr == null) {
return 0;
}
return 1;
} else {
return -1;
}
}
}