/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (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.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Community System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.htmlcheck.dict;

import com.silverwrist.venice.htmlcheck.ModSpellingDictionary;

public class TreeLexicon implements ModSpellingDictionary
{
  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private DictNode root;    // root node of the trie that contains our data
  private int count;        // number of words in the lexicon

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  public TreeLexicon()
  {
    root = new DictNode();
    count = 0;

  } // end constructor

  /*--------------------------------------------------------------------------------
   * Internal functions
   *--------------------------------------------------------------------------------
   */

  private boolean checkSimple(String word)
  {
    DictNode cur = root;
    for (int i=0; i<word.length(); i++)
    { // loop through the characters and move down the trie
      char ch = word.charAt(i);
      if (((ch<'a') || (ch>'z')) && (ch!='-') && (ch!='\''))
	return false;
      cur = cur.getRef(ch);
      if (cur==null)
	return false;

    } // end for

    return cur.isTerminal();

  } // end checkSimple

  private boolean checkHyphenates(String word)
  {
    if (word.indexOf('-')<0)
      return false;  // non-hyphenated

    int st = 0;
    int p;
    boolean ok = true;
    do
    { // break the word up into hyphenated compounds
      p = word.indexOf('-',st);
      String frag;
      if (p>=0)
      { // get the middle fragment of the word
	frag = word.substring(st,p);
	st = p + 1;

      } // end if
      else  // get it from the end
	frag = word.substring(st);

      // check this fragment...
      if (frag.length()<=1)
	ok = true;   // fragments of length 0 or 1 are always OK
      else  // anything else goes through checkSimple
	ok = checkSimple(frag);

    } while (ok && (p>=0));

    return ok;

  } // end checkHyphenates

  /*--------------------------------------------------------------------------------
   * Implementations from interface SpellingDictionary
   *--------------------------------------------------------------------------------
   */

  public synchronized int size()
  {
    return count;

  } // end size

  public synchronized boolean checkWord(String word)
  {
    if (word.length()<=1)
      return true;  // words of length 1 get a free pass
    String real_word = word.toLowerCase();
    if (checkSimple(real_word))
      return true;  // word is in lexicon - we're OK to go

    if ((real_word.indexOf('\'')==(real_word.length()-2)) && (real_word.charAt(real_word.length()-1)=='s'))
    { // drop the apostrophe-s from the end of the word and retry
      String base = real_word.substring(0,real_word.length()-2);
      if (checkSimple(base))
	return true;
      return checkHyphenates(base);

    } // end if
    else // try hyphenated forms
      return checkHyphenates(real_word);

  } // end checkWord

  /*--------------------------------------------------------------------------------
   * Implementations from interface ModSpellingDictionary
   *--------------------------------------------------------------------------------
   */

  public synchronized void addWord(String word)
  {
    String real_word = word.toLowerCase();
    DictNode cur = root;
    for (int i=0; i<real_word.length(); i++)
    { // move through the word - bail out if bogus chars
      char ch = real_word.charAt(i);
      if (((ch<'a') || (ch>'z')) && (ch!='-') && (ch!='\''))
	return;

      // advance down through trie
      DictNode next = cur.getRef(ch);
      if (next==null)
      { // strike out into a new DictNode
	next = new DictNode();
	cur.setRef(ch,next);

      } // end if

      cur = next;

    } // end for

    cur.setTerminal();
    count++;

  } // end addWord

  public void delWord(String word)
  { // not implemented for this lexicon type
  } // end delWord

  public synchronized void clear()
  {
    root = new DictNode();
    count = 0;

  } // end clear

} // end class TreeLexicon


