/*
 * 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 Communities 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) 2003 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.dynamo.dict;

import java.util.*;
import org.apache.log4j.Logger;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.Namespaces;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;

public class DictionarySubsystem
    implements NamedObject, ComponentInitialize, ComponentShutdown, HTMLCheckerConfigurator
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static Logger logger = Logger.getLogger(DictionarySubsystem.class);

  private static final String DEFAULT_BEGIN_ERROR = "<span class=\"spellingerror\">";
  private static final String DEFAULT_END_ERROR = "</span>";

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private String m_name;                       // name of this object
  private LinkedList m_shutdown_list;          // object shutdown list
  private Hashtable m_dictionaries;            // current dictionaries
  private Hashtable m_modifiable_dictionaries; // current modifiable dictionaries
  private ComponentShutdown m_htmlchecker;     // HTML checker configurator

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

  public DictionarySubsystem()
  {
    m_shutdown_list = new LinkedList();
    m_dictionaries = new Hashtable();
    m_modifiable_dictionaries = new Hashtable();

  } // end constructor

  /*--------------------------------------------------------------------------------
   * Implementations from interface NamedObject
   *--------------------------------------------------------------------------------
   */

  public String getName()
  {
    return m_name;

  } // end getName

  /*--------------------------------------------------------------------------------
   * Implementations from interface ComponentInitialize
   *--------------------------------------------------------------------------------
   */

  /**
   * Initialize the component.
   *
   * @param config_root Pointer to the section of the Dynamo XML configuration file that configures this
   *                    particular component.  This is to be considered "read-only" by the component.
   * @param services An implementation of {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider}
   *                 which provides initialization services to the component.  This will include an implementation
   *                 of {@link com.silverwrist.dynamo.iface.ObjectProvider ObjectProvider} which may be used to
   *                 get information about other objects previously initialized by the application.
   * @exception com.silverwrist.dynamo.except.ConfigException If an error is encountered in the component
   *            configuration.
   */
  public void initialize(Element config_root, ServiceProvider services) throws ConfigException
  {
    logger.info("DictionarySubsystem initializing");
    XMLLoader loader = XMLLoader.get();
    List subobjects = null;

    try
    { // verify the right node name
      loader.verifyNodeName(config_root,"object");

      // get the object's name
      m_name = loader.getAttribute(config_root,"name");

      // get the subobject nodes to load
      subobjects = loader.getMatchingSubElements(config_root,"dictionary");

    } // end try
    catch (XMLLoadException e)
    { // error loading XML config data
      throw new ConfigException(e);

    } // end catch

    // load and initialize the dictionary subobjects
    Iterator it = subobjects.iterator();
    while (it.hasNext())
    { // initialize all the dictionary subobjects
      Element droot = (Element)(it.next());
      DynamoDictionary dict = (DynamoDictionary)(LoaderUtils.loadObject(droot,services,DynamoDictionary.class));
      ComponentShutdown cs = (ComponentShutdown)(LoaderUtils.query(ComponentShutdown.class,dict));
      if (cs!=null)
	m_shutdown_list.addFirst(cs);
      String dictname = ((NamedObject)dict).getName();
      m_dictionaries.put(dictname,dict);
      if (dict instanceof DynamoModifiableDictionary)
	m_modifiable_dictionaries.put(dictname,dict);

    } // end while

    // Link us into the HTML Checker's configurators list.
    HTMLCheckerConfigRegister creg =
        (HTMLCheckerConfigRegister)(services.queryService(HTMLCheckerConfigRegister.class));
    m_htmlchecker = creg.registerConfigurator(this);

  } // end initialize

  /*--------------------------------------------------------------------------------
   * Implementations from interface ComponentShutdown
   *--------------------------------------------------------------------------------
   */

  public void shutdown()
  {
    m_htmlchecker.shutdown();
    m_htmlchecker = null;
    m_dictionaries.clear();
    m_modifiable_dictionaries.clear();
    while (m_shutdown_list.size()>0)
    { // shut down all the components
      ComponentShutdown cs = (ComponentShutdown)(m_shutdown_list.removeFirst());
      cs.shutdown();

    } // end while

  } // end shutdown

  /*--------------------------------------------------------------------------------
   * Implementations from interface HTMLCheckerConfigurator
   *--------------------------------------------------------------------------------
   */

  public void configure(HTMLCheckerProfile profile)
  {
    boolean enable =
        ((Boolean)(PropertyUtils.getPropertyDefault(profile,Namespaces.SPELLCHECKER_PROPERTIES_NAMESPACE,
						    "enable",Boolean.FALSE))).booleanValue();
    if (enable)
    { // get the list of dictionaries
      String dictnames = PropertyUtils.getPropertyDefault(profile,Namespaces.SPELLCHECKER_PROPERTIES_NAMESPACE,
							  "dictionaries","").toString();
      String[] dictname_list = StringUtils.split1(dictnames,',');
      ArrayList dict_list = new ArrayList();
      for (int i=0; i<dictname_list.length; i++)
      { // locate the dictionaries and plug them in
	DynamoDictionary d = (DynamoDictionary)(m_dictionaries.get(dictname_list[i].trim()));
	if (d!=null)
	  dict_list.add(d);

      } // end for

      DynamoDictionary[] dicts = new DynamoDictionary[dict_list.size()];
      dict_list.toArray(dicts);

      // get the begin error and end error sequences
      String begin_error = PropertyUtils.getPropertyDefault(profile,Namespaces.SPELLCHECKER_PROPERTIES_NAMESPACE,
							    "begin.error",DEFAULT_BEGIN_ERROR).toString();
      String end_error = PropertyUtils.getPropertyDefault(profile,Namespaces.SPELLCHECKER_PROPERTIES_NAMESPACE,
							  "end.error",DEFAULT_END_ERROR).toString();

      // load a spellchucker, ready to go!
      profile.addWordRewriter(new Spellchecker(dicts,begin_error,end_error));

    } // end if

  } // end configure

} // end class DictionarySubsystem
