package org.apache.lucene.search.uhighlight;
import java.text.BreakIterator;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
public class SplittingBreakIterator extends BreakIterator {
private final BreakIterator baseIter;
private final char sliceChar;
private String text;
private int sliceStartIdx;
private int sliceEndIdx;
private int current;
public SplittingBreakIterator(BreakIterator baseIter, char sliceChar) {
this.baseIter = baseIter;
this.sliceChar = sliceChar;
}
@Override
public void setText(CharacterIterator newText) {
throw new UnsupportedOperationException("unexpected");
}
@Override
public void setText(String newText) {
this.text = newText;
first();
}
@Override
public CharacterIterator getText() {
StringCharacterIterator charIter = new StringCharacterIterator(text);
charIter.setIndex(current());
return charIter;
}
@Override
public int current() {
assert current != DONE;
return current;
}
@Override
public int first() {
sliceStartIdx = 0;
sliceEndIdx = text.indexOf(sliceChar);
if (sliceEndIdx == -1) {
sliceEndIdx = text.length();
}
if (sliceStartIdx == sliceEndIdx) {
return current = sliceStartIdx;
}
baseIter.setText(text.substring(sliceStartIdx, sliceEndIdx));
return current = sliceStartIdx + baseIter.current();
}
@Override
public int last() {
sliceEndIdx = text.length();
sliceStartIdx = text.lastIndexOf(sliceChar);
if (sliceStartIdx == -1) {
sliceStartIdx = 0;
} else {
sliceStartIdx++;
}
if (sliceEndIdx == sliceStartIdx) {
return current = sliceEndIdx;
}
baseIter.setText(text.substring(sliceStartIdx, sliceEndIdx));
return current = sliceStartIdx + baseIter.last();
}
@Override
public int next() {
int prevCurrent = current;
current = sliceStartIdx == sliceEndIdx ? DONE : baseIter.next();
if (current != DONE) {
return current = current + sliceStartIdx;
}
if (sliceEndIdx >= text.length()) {
current = prevCurrent;
return DONE;
}
sliceStartIdx = sliceEndIdx + 1;
sliceEndIdx = text.indexOf(sliceChar, sliceStartIdx);
if (sliceEndIdx == -1) {
sliceEndIdx = text.length();
}
if (sliceStartIdx == sliceEndIdx) {
return current = sliceStartIdx;
}
baseIter.setText(text.substring(sliceStartIdx, sliceEndIdx));
return current = sliceStartIdx + baseIter.current();
}
@Override
public int previous() {
int prevCurrent = current;
current = sliceStartIdx == sliceEndIdx ? DONE : baseIter.previous();
if (current != DONE) {
return current = current + sliceStartIdx;
}
if (sliceStartIdx == 0) {
current = prevCurrent;
return DONE;
}
sliceEndIdx = sliceStartIdx - 1;
sliceStartIdx = text.lastIndexOf(sliceChar, sliceEndIdx - 1);
if (sliceStartIdx == -1) {
sliceStartIdx = 0;
} else {
sliceStartIdx++;
}
if (sliceStartIdx == sliceEndIdx) {
return current = sliceStartIdx;
}
baseIter.setText(text.substring(sliceStartIdx, sliceEndIdx));
return current = sliceStartIdx + baseIter.last();
}
@Override
public int following(int offset) {
if (offset + 1 < sliceStartIdx || offset + 1 > sliceEndIdx) {
if (offset == text.length()) {
last();
return DONE;
}
sliceStartIdx = text.lastIndexOf(sliceChar, offset);
if (sliceStartIdx == -1) {
sliceStartIdx = 0;
} else {
sliceStartIdx++;
}
sliceEndIdx = text.indexOf(sliceChar, Math.max(offset + 1, sliceStartIdx));
if (sliceEndIdx == -1) {
sliceEndIdx = text.length();
}
if (sliceStartIdx != sliceEndIdx) {
baseIter.setText(text.substring(sliceStartIdx, sliceEndIdx));
}
}
if (sliceStartIdx == sliceEndIdx) {
return current = offset + 1;
} else {
if (offset == sliceStartIdx - 1) {
return current = sliceStartIdx + baseIter.first();
} else {
return current = sliceStartIdx + baseIter.following(offset - sliceStartIdx);
}
}
}
@Override
public int preceding(int offset) {
if (offset - 1 < sliceStartIdx || offset - 1 > sliceEndIdx) {
if (offset == 0) {
first();
return DONE;
}
sliceEndIdx = text.indexOf(sliceChar, offset);
if (sliceEndIdx == -1) {
sliceEndIdx = text.length();
}
sliceStartIdx = text.lastIndexOf(sliceChar, offset - 1);
if (sliceStartIdx == -1) {
sliceStartIdx = 0;
} else {
sliceStartIdx = Math.min(sliceStartIdx + 1, sliceEndIdx);
}
if (sliceStartIdx != sliceEndIdx) {
baseIter.setText(text.substring(sliceStartIdx, sliceEndIdx));
}
}
if (sliceStartIdx == sliceEndIdx) {
return current = offset - 1;
} else {
if (offset == sliceEndIdx + 1) {
return current = sliceStartIdx + baseIter.last();
} else {
return current = sliceStartIdx + baseIter.preceding(offset - sliceStartIdx);
}
}
}
@Override
public int next(int n) {
if (n < 0) {
for (int i = 0; i < -n; i++) {
if (previous() == DONE) {
return DONE;
}
}
} else {
for (int i = 0; i < n; i++) {
if (next() == DONE) {
return DONE;
}
}
}
return current();
}
}