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

import org.w3c.dom.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.security.SecurityReferenceMonitor;
import com.silverwrist.dynamo.util.*;

public class GlobalDataManagerObject
    implements NamedObject, ComponentInitialize, ComponentShutdown, ServiceProvider
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static final int DEFAULT_HARD_LIMIT = 5;
  private static final int DEFAULT_SOFT_LIMIT = 20;

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

  private String m_name;                                // object name
  private DBConnectionPool m_pool;                      // database connection pool
  private NamespaceCache m_ns_cache;                    // namespace cache object
  private SecurityReferenceMonitor m_srm;               // security reference monitor
  private PostDynamicUpdate m_post;                     // dynamic update poster
  private GlobalPropertiesObject m_properties;          // global properties object
  private GlobalBlocksObject m_blocks;                  // global blocks object

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

  public GlobalDataManagerObject()
  { // do nothing
  } // end constructor

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

  public String getName()
  {
    return m_name;

  } // end getName

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

  public void initialize(Element config_root, ServiceProvider services) throws ConfigException
  {
    String conn_name = null;
    String nscache_name = null;
    String srm_name = null;
    int hard_limit = DEFAULT_HARD_LIMIT;
    int soft_limit = DEFAULT_SOFT_LIMIT;
    XMLLoader loader = XMLLoader.get();
    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 database configuration connection
      DOMElementHelper config_root_h = new DOMElementHelper(config_root);
      Element elt = loader.getSubElement(config_root_h,"database");
      conn_name = loader.getAttribute(elt,"connection");
      nscache_name = loader.getAttribute(elt,"namespaces");

      // get the security reference monitor reference
      elt = loader.getSubElement(config_root_h,"security");
      srm_name = loader.getAttribute(elt,"object");

      // get the block cache information
      elt = config_root_h.getSubElement("block-cache");
      if (elt!=null)
      { // get the cache limits
	hard_limit = loader.getAttributeInt(elt,"hardlimit",DEFAULT_HARD_LIMIT);
	soft_limit = loader.getAttributeInt(elt,"softlimit",DEFAULT_SOFT_LIMIT);

      } // end if

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

    } // end catch

    // Get the database connection pool and the namespace cache.
    m_pool = GetObjectUtils.getDatabaseConnection(services,conn_name);
    m_ns_cache =
        (NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name));
    m_srm =
        (SecurityReferenceMonitor)(GetObjectUtils.getDynamoComponent(services,SecurityReferenceMonitor.class,
								     srm_name));
    m_post = (PostDynamicUpdate)(services.queryService(PostDynamicUpdate.class));

    // Create the subobjects.
    m_properties = new GlobalPropertiesObject(m_pool,m_ns_cache,m_srm,m_post);
    m_blocks = new GlobalBlocksObject(m_pool,m_ns_cache,m_srm,m_post,hard_limit,soft_limit);

  } // end initialize

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

  public void shutdown()
  {
    m_pool = null;
    m_ns_cache = null;
    m_srm = null;
    m_post = null;

  } // end shutdown

  /*--------------------------------------------------------------------------------
   * Implementations from interface ServiceProvider
   *--------------------------------------------------------------------------------
   */

  /**
   * Queries this object for a specified service.
   *
   * @param klass The class of the object that should be returned as a service.
   * @return A service object.  The service object is guaranteed to be of the class
   *         specified by <CODE>klass</CODE>; that is, if <CODE>queryService(klass)</CODE>
   *         yields some object <CODE>x</CODE>, then the expression <CODE>klass.isInstance(x)</CODE>
   *         is true.
   * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in
   *            the specified class.
   */
  public Object queryService(Class klass)
  {
    if ((klass==SecureObjectStore.class) || (klass==ObjectProvider.class))
      return (SecureObjectStore)m_properties;
    throw new NoSuchServiceException("GlobalDataManagerObject",klass);

  } // end queryService

  /**
   * Queries this object for a specified service.
   *
   * @param klass The class of the object that should be returned as a service.
   * @param serviceid ID for the service to be requested, to further discriminate between requests.
   * @return A service object.  The service object is guaranteed to be of the class
   *         specified by <CODE>klass</CODE>; that is, if <CODE>queryService(klass)</CODE>
   *         yields some object <CODE>x</CODE>, then the expression <CODE>klass.isInstance(x)</CODE>
   *         is true.
   * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in
   *            the specified class.
   */
  public Object queryService(Class klass, String serviceid)
  {
    if ((klass==SecureObjectStore.class) || (klass==ObjectProvider.class))
    { // return service
      if ((serviceid==null) || serviceid.equals("properties"))
	return (SecureObjectStore)m_properties;
      if (serviceid.equals("blocks"))
	return (SecureObjectStore)m_blocks;
      throw new NoSuchServiceException("GlobalDataManagerObject",klass,serviceid);

    } // end if

    try
    { // look for the class without a service ID
      return this.queryService(klass);

    } // end try
    catch (NoSuchServiceException e)
    { // transform exception for return
      throw new NoSuchServiceException(e.getContext(),klass,serviceid,e);

    } // end catch

  } // end queryService

} // end class GlobalDataManagerObject
