/*
* Freeplane - mind map editor
* Copyright (C) 2010 dimitry
*
* This file author is dimitry
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.inet.jortho;
import java.text.BreakIterator;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
/**
* @author Dimitry Polivaev
* Aug 14, 2010
*/
class LetterBasedBreakIterator {
private CharacterIterator text;
public LetterBasedBreakIterator() {
}
/**
* Set a new text string to be scanned. The current scan
* position is reset to first().
* @param newText new text to scan.
*/
public void setText(String newText)
{
setText(new StringCharacterIterator(newText));
}
/**
* Set a new text for scanning. The current scan
* position is reset to first().
* @param newText new text to scan.
*/
public void setText(CharacterIterator text){
this.text = text;
}
/**
* Returns the first boundary. The iterator's current position is set
* to the first text boundary.
* @return The character index of the first text boundary.
*/
public int first() {
return nextBoundary(text.first(), false);
}
private int nextBoundary(char c, boolean wasLetter) {
for(;;){
if(c == CharacterIterator.DONE){
return BreakIterator.DONE;
}
if(wasLetter != isLetter(c)){
return text.getIndex();
}
c = text.next();
}
}
/**
* Returns the first boundary following the specified character offset. If the
* specified offset equals to the last text boundary, it returns
* <code>BreakIterator.DONE</code> and the iterator's current position is unchanged.
* Otherwise, the iterator's current position is set to the returned boundary.
* The value returned is always greater than the offset or the value
* <code>BreakIterator.DONE</code>.
* @param offset the character offset to begin scanning.
* @return The first boundary after the specified offset or
* <code>BreakIterator.DONE</code> if the last text boundary is passed in
* as the offset.
* @exception IllegalArgumentException if the specified offset is less than
* the first text boundary or greater than the last text boundary.
*/
public int following(int wordOffset) {
if(wordOffset <= text.getBeginIndex()){
return first();
}
if(wordOffset >= text.getEndIndex()){
return BreakIterator.DONE;
}
int lastIndex = text.getIndex();
text.setIndex(wordOffset);
boolean wasLetter = isLetter(text.current());
int nextBoundary = nextBoundary(text.next(), wasLetter);
if(nextBoundary == BreakIterator.DONE){
text.setIndex(lastIndex);
}
return nextBoundary;
}
/**
* Returns the boundary following the current boundary. If the current boundary
* is the last text boundary, it returns <code>BreakIterator.DONE</code> and
* the iterator's current position is unchanged. Otherwise, the iterator's
* current position is set to the boundary following the current boundary.
* @return The character index of the next text boundary or
* <code>BreakIterator.DONE</code> if the current boundary is the last text
* boundary.
* Equivalent to next(1).
* @see #next(int)
*/
public int next() {
boolean wasLetter = isLetter(text.current());
return nextBoundary(text.next(), wasLetter);
}
private boolean isLetter(char current) {
return Character.isDigit(current) || Character.isLetter(current);
}
}