/**
 * Title:
 * @version:    $Id: XMLConfigHolder.java,v 1.1 2004/11/15 13:47:50 rob Exp $
 * Copyright:   Copyright (C) 2003 Ian Ibbotson
 * @author:     Ian Ibbotson
 * Company:
 * Description:
 */

package com.k_int.AdminApp.config;

import java.net.*;
import java.util.*;
import org.apache.commons.digester.*;
import org.apache.commons.digester.xmlrules.*;
import com.k_int.QueryDescriptor.*;
import javax.naming.*;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.Configuration;
import com.k_int.AdminApp.auth.iface.AuthenticationMethod;
import java.util.logging.*;
import java.util.HashMap;

public class XMLConfigHolder implements ConfigHolder
{
    private static Logger cat = Logger.getLogger("com.k_int.AdminApp.config.XMLCOnfigHolder");
  private Context ctx;
  private Hashtable descriptors;
  private Hashtable session_factories;
  private Hashtable default_layouts;
  private Hashtable view_register;
  private ActionCategory root_category = new ActionCategory("Root");
  private Hashtable app_properties;
  private Hashtable auth_methods;
  private Vector default_workspace_components = new Vector();
  private Hashtable role_specific_views;

  public XMLConfigHolder(String config_resource_path) throws javax.naming.NamingException
  {
    Hashtable env = new Hashtable();
    env.put( Context.INITIAL_CONTEXT_FACTORY, "tyrex.naming.MemoryContextFactory" );
    env.put( Context.PROVIDER_URL, "XDAdmin" );
    ctx = new InitialContext( env );
    descriptors = new Hashtable();
    session_factories = new Hashtable();
    default_layouts = new Hashtable();
    view_register = new Hashtable();
    app_properties = new Hashtable();
    auth_methods = new Hashtable();
    role_specific_views = new Hashtable();
    ctx.rebind("SearchDescriptors", descriptors);
    ctx.rebind("SessionFactories", session_factories);
    ctx.rebind("DefaultLayouts",default_layouts);
    ctx.rebind("ViewRegister",view_register);
    ctx.rebind("RootCategory",root_category);
    ctx.rebind("Configuration",this);
    loadConfigFile(config_resource_path);
  }


  // config_resource will look for the identified resource on the classpath. For example, the
  // testing config uses "com/k_int/AdminApp/config/config.xml" but using just "config.xml" will
  // Search the root of all components in the classpath for a resource called config.xml
  private void loadConfigFile(String config_resource_path)
  {
    try
    {
      URL rules = ClassLoader.getSystemResource("com/k_int/AdminApp/config/XDAdminDigesterRules.xml");
      URL config = ClassLoader.getSystemResource(config_resource_path);
      Digester digester = DigesterLoader.createDigester(rules);
      digester.push(this); // Push this object onto stack so we can add objects to it :)
      Object result = digester.parse(config.openStream() );

      cat.finest("config load complete");
    }
    catch ( Exception e )
    {
      cat.log(Level.SEVERE,"Error",e);
      System.exit(-1);
    }
  }

  public void addCategory(ActionCategory c)
  {
    cat.finest("Add category "+c);
    root_category.add(c);
  }

  public void registerQueryDescriptor(QueryDescriptor qd)
  {
    cat.finest("Register query descriptor "+qd.getId());
    descriptors.put(qd.getId(), qd);
  }

  public void registerSessionFactory(String id, 
                                     String resource, 
                                     Boolean update,
                                     String connection_url,
                                     String connection_username,
                                     String connection_password,
                                     String connection_driver,
                                     String dialect,
                                     String pool_size)
  {
    try
    {
      cat.finest("registerSessionFactory "+id+","+resource);
      // Configuration c = new Configuration().configure(resource).buildSessionFactory();
      Configuration c = new Configuration().configure(resource);

    
      c.setProperty("hibernate.connection.url",connection_url);
      c.setProperty("hibernate.connection.username",connection_username);
      c.setProperty("hibernate.connection.password",connection_password);
      c.setProperty("hibernate.connection.driver_class",connection_driver);
      c.setProperty("hibernate.dialect",dialect);
      c.setProperty("hibernate.connection.pool_size",pool_size);

      // This command with synchronize the database with our definitions
      if ( ( update != null ) && ( update.equals(Boolean.TRUE) ) )
      {
        cat.finest("Synchronizing database and persistence definition");
        new net.sf.hibernate.tool.hbm2ddl.SchemaUpdate(c).execute(false);
      }

      cat.finest("build session factory");

      SessionFactory sf = c.buildSessionFactory();
      session_factories.put(id, sf);
      cat.finest("Done registering session factory");
    }
    catch ( net.sf.hibernate.HibernateException he )
    {
        cat.log(Level.SEVERE,"Error",he);
     
        System.exit(-1);
    }
  }

  public void registerDefaultLayout(String classname, String layoutid)
  {
    cat.finest("registerDefaultLayout "+classname+"="+layoutid);

    default_layouts.put(classname, layoutid);
  }

  public void registerView(String id, String type, String resource)
  {
    cat.finest("registerView("+id+","+type+","+resource+")");
    view_register.put(id, resource);
  }
  
  
  public void registerRoleSpecificLayout(String classname, String layoutid, String role)
  {
      cat.finest("registerRoleSpecific layout("+classname+","+layoutid+","+role+")");
      
      // at this stage need to set up the defaults
      // based on the current role
      HashMap view_map;
      if(role_specific_views.get(role)==null)
      {
          view_map=new HashMap();
          role_specific_views.put(role, view_map);
      }
      else
            view_map=(HashMap) role_specific_views.get(role);
       
        view_map.put(classname, layoutid);
   
  }
  
  
  public void allocateRoleSpecificViews(String role)
  {
      HashMap role_view_map = (HashMap) role_specific_views.get(role);
      
      if(role_view_map==null)
        return;
        
     cat.finest("Allocating role specific views for "+role);
        
     Iterator i = role_view_map.keySet().iterator();
     
     while(i.hasNext())
     {
         String classname = (String) i.next();
         String layout_id = (String) role_view_map.get(classname);
         registerDefaultLayout(classname,layout_id);
     }       
  }
  




  public ActionCategory getRootCategory()
  {
    return root_category;
  }

  public String lookupViewResource(String view_id)
  {
    cat.finest("lookupViewResource("+view_id+")="+view_register.get(view_id));
    return (String) view_register.get(view_id);
  }

  public SessionFactory getSessionFactory(String id)
  {
    return (SessionFactory)session_factories.get(id);
  }

  public String lookupDefaultView(String class_name)
  {
    return (String)default_layouts.get(class_name);
  }
  
  public void setViewsForRole(String role)
  {
      
  }

  public void setAppProperty(String name, Object value)
  {
    app_properties.put(name, value);
  }

  public Object getAppProperty(String name)
  {
    return app_properties.get(name);
  }

  public void registerAuthenticationMethod(AuthenticationMethod method)
  {
    method.setConfig(this);
    cat.finest("Registering authentication method with ID "+method.getMethodId());
    auth_methods.put(method.getMethodId(), method);
  }

  public Object[] getAuthMethods()
  {
    return auth_methods.values().toArray();
  }

  public void addWorkspaceComponent(ActionComponent component)
  {
    cat.finest("addWorkspaceComponent");
    default_workspace_components.add(component);
  }

  public Vector getDefaultWorkspaceComponents()
  {
    cat.finest("getDefaultWorkspaceComponents");
    return default_workspace_components;
  }

}
