/* Jazzy - a Java library for Spell Checking Copyright (C) 2001 Mindaugas Idzelis Full text of license can be found in LICENSE.txt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.swabunga.spell.event; import java.text.BreakIterator; /** * Defines common methods and behaviour for the various word finding subclasses. * * @author Anthony Roy (ajr@antroy.co.uk) */ public abstract class AbstractWordFinder implements WordFinder { // ~ Instance/static variables ............................................. protected Word currentWord; protected Word nextWord; protected boolean startsSentence; protected String text; protected BreakIterator sentenceIterator; // ~ Constructors .......................................................... /** * Creates a new AbstractWordFinder object. * * @param inText * the String to iterate through. */ public AbstractWordFinder(String inText) { text = inText; setup(); } public AbstractWordFinder() { text = ""; setup(); } // ~ Methods ............................................................... /** * This method scans the text from the end of the last word, and returns a new Word object corresponding to the next word. * * @return the next word. */ @Override public abstract Word next(); /** * Return the text being searched. May have changed since first set through calls to replace. * * @return the text being searched. */ @Override public String getText() { return text; } @Override public void setText(String newText) { text = newText; setup(); } /** * Returns the current word in the iteration . * * @return the current word. * @throws WordNotFoundException * current word has not yet been set. */ @Override public Word current() { if (currentWord == null) { throw new WordNotFoundException("No Words in current String"); } return currentWord; } /** * @return true if there are further words in the string. */ @Override public boolean hasNext() { return nextWord != null; } /** * Replace the current word in the search with a replacement string. * * @param newWord * the replacement string. * @throws WordNotFoundException * current word has not yet been set. */ @Override public void replace(String newWord) { if (currentWord == null) { throw new WordNotFoundException("No Words in current String"); } StringBuffer sb = new StringBuffer(text.substring(0, currentWord.getStart())); sb.append(newWord); sb.append(text.substring(currentWord.getEnd())); int diff = newWord.length() - currentWord.getText().length(); currentWord.setText(newWord); /* Added Conditional to ensure a NullPointerException is avoided (11 Feb 2003) */ if (nextWord != null) { nextWord.setStart(nextWord.getStart() + diff); } text = sb.toString(); sentenceIterator.setText(text); int start = currentWord.getStart(); sentenceIterator.following(start); startsSentence = sentenceIterator.current() == start; } /** * @return true if the current word starts a new sentence. * @throws WordNotFoundException * current word has not yet been set. */ @Override public boolean startsSentence() { if (currentWord == null) { throw new WordNotFoundException("No Words in current String"); } return startsSentence; } /** * Return the text being searched. May have changed since first set through calls to replace. * * @return the text being searched. */ @Override public String toString() { return text; } protected void setSentenceIterator(Word wd) { int current = sentenceIterator.current(); if (current == currentWord.getStart()) { startsSentence = true; } else { startsSentence = false; if (currentWord.getEnd() > current) { sentenceIterator.next(); } } } // Added more intelligent character recognition (11 Feb '03) protected boolean isWordChar(int posn) { boolean out = false; char curr = text.charAt(posn); if (posn == 0 || posn == text.length() - 1) { return Character.isLetterOrDigit(curr); } char prev = text.charAt(posn - 1); char next = text.charAt(posn + 1); switch (curr) { case '\'': case '@': case '.': case '_': out = Character.isLetterOrDigit(prev) && Character.isLetterOrDigit(next); break; default: out = Character.isLetterOrDigit(curr); } return out; } protected boolean isWordChar(char c) { boolean out = false; if (Character.isLetterOrDigit(c) || c == '\'') { out = true; } return out; } protected int ignore(int index, char startIgnore) { return ignore(index, new Character(startIgnore), null); } protected int ignore(int index, char startIgnore, char endIgnore) { return ignore(index, new Character(startIgnore), new Character(endIgnore)); } protected int ignore(int index, Character startIgnore, Character endIgnore) { int newIndex = index; if (newIndex < text.length()) { Character curChar = new Character(text.charAt(newIndex)); if (curChar.equals(startIgnore)) { newIndex++; while (newIndex < text.length()) { curChar = new Character(text.charAt(newIndex)); if (endIgnore != null && curChar.equals(endIgnore)) { newIndex++; break; } else if (endIgnore == null && !Character.isLetterOrDigit(curChar.charValue())) { break; } newIndex++; } } } return newIndex; } protected int ignore(int index, String startIgnore, String endIgnore) { // {{{ int newIndex = index; int len = text.length(); int slen = startIgnore.length(); int elen = endIgnore.length(); if (!(newIndex + slen >= len)) { String seg = text.substring(newIndex, newIndex + slen); // System.out.println(seg + ":" + seg.length()+ ":" + startIgnore + ":" + slen); if (seg.equals(startIgnore)) { newIndex += slen; cycle: while (true) { if (newIndex == text.length() - elen) { break cycle; } String ss = text.substring(newIndex, newIndex + elen); if (ss.equals(endIgnore)) { newIndex += elen; break cycle; } else { newIndex++; } } } } return newIndex; } // }}} protected void init() { sentenceIterator = BreakIterator.getSentenceInstance(); sentenceIterator.setText(text); } private void setup() { currentWord = new Word("", 0); nextWord = new Word("", 0); startsSentence = true; init(); try { next(); } catch (WordNotFoundException e) { currentWord = null; nextWord = null; } } }