//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010  huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/willow
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : willow@lists.sourceforge.net 
 */
//----------------------------END  LICENSE-----------------------------
package org.huihoo.willow.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.huihoo.commons.jdbc.Store;
import org.huihoo.willow.Context;
import org.huihoo.willow.ContextDeployer;
import org.huihoo.willow.Globals;
import org.huihoo.willow.deploy.PluginRepository;
import org.huihoo.willow.util.StringManager;
import org.huihoo.workflow.SchemaContext;
import org.huihoo.workflow.WorkflowGlobals;
import org.huihoo.workflow.WorkflowException;
import org.huihoo.workflow.server.WorkflowXPDL;
import org.huihoo.workflow.server.WorkflowXPDLRepository;
import org.huihoo.workflow.store.FactoryManager;
import org.huihoo.workflow.store.WorkflowTemplate;
import org.huihoo.workflow.xpdl.WorkflowPackage;
import org.huihoo.workflow.xpdl.parser.XPDLParser;
import org.huihoo.workflow.xpdl.parser.XPDLParserFactory;
import org.huihoo.workflow.xpdl.parser.XPDLParserTools;

public class StandardContextDeployer implements ContextDeployer
{
	private static Log log = LogFactory.getLog(StandardContextDeployer.class);

	/**
	 * The string manager for this package.
	 */
	protected static StringManager sm = StringManager.getManager(Constants.PACKAGE);

	/**
	 * The names of applications that we have auto-deployed (to avoid
	 * double deployment attempts).
	 */
	private HashMap deployed = new HashMap();

	//----------------------------------------------------------- Constructors
	public StandardContextDeployer()
	{
	}
	/**
	 * Create a new StandardContextDeployer associated with the specified
	 * StandardContext.
	 *
	 * @param engine The StandardContext we are associated with
	 */
	public StandardContextDeployer(StandardContext context)
	{
		super();
		this.context = context;
	}
	/**
	 * The <code>StandardContext</code> instance we are associated with.
	 */
	protected StandardContext context = null;

	public Context getContext()
	{
		return context;
	}
	public void setContext(Context context)
	{
		this.context = (StandardContext) context;
	}
	/**
	 * Return the name of the Container with which this EngineDeployer is associated.
	 */
	public String getName()
	{
		return (context.getName());
	}
	public void install(String procName, URL procURL) throws WorkflowException
	{
		log.info(sm.getString("standardContext.installing", procName, procURL));

		//	--------------------------------------------------------------
		//
		//	--------------------------------------------------------------		
		Hashtable env = new Hashtable();
		XPDLParserFactory factory = XPDLParserFactory.newInstance(env);

		String value = context.findInitParameter(Globals.PARSER_XML_VALIDATING);
		if (value != null)
		{
			factory.setValidating(Boolean.valueOf(value).booleanValue());
		}

		value = context.findInitParameter(Globals.PARSER_XML_NAMESPACEAWARE);
		if (value != null)
		{
			factory.setNamespaceAware(Boolean.valueOf(value).booleanValue());
		}

		value = context.findInitParameter(Globals.PARSER_XPDL_VALIDATING);
		if (value != null)
		{
			factory.setXPDLValidating(Boolean.valueOf(value).booleanValue());
		}

		XPDLParser parser = factory.newXPDLParser();

		//--------------------------------------------------------------
		//
		//--------------------------------------------------------------
		WorkflowPackage workflowPackage = null;
		InputStream istream = null;
		try
		{
			istream = procURL.openStream();
			workflowPackage = parser.parse(istream);
		}
		catch (IOException e)
		{
			if (istream != null)
			{
				try
				{
					istream.close();
				}
				catch (Throwable t)
				{
				}
			}

			WorkflowException ne = new WorkflowException("can not parse XPDL document");
			ne.setRootCause(e);
			throw ne;
		}

		//------------------------------------------------------------
		//  VERY IMPORTANT CODE SECTION  BY ZOSATAPO 2005-12-24
		//
		//  TO Initialize WorkflowProcess and WorkflowActivity Listeners
		//------------------------------------------------------------		
		XPDLParserTools.externalFormat(workflowPackage, context.getLoader().getClassLoader());

		Store caseSTORE = PluginRepository.getInstance().findStore(WorkflowGlobals.CASEDATABASE_STORE_KEY);
		Store userSTORE = PluginRepository.getInstance().findStore(WorkflowGlobals.USERDATABASE_STORE_KEY);		
		SchemaContext schemaCONTEXT = PluginRepository.getInstance().getSchemaContext();
		
		WorkflowTemplate workflowTemplate = FactoryManager.getWorkflowTemplate(caseSTORE,userSTORE,schemaCONTEXT);
		
		StandardXPDL standardXPDL = new StandardXPDL(workflowPackage, workflowTemplate);
		ApplicationConfig config = new ApplicationConfig(context.getWorkflowContext());
    standardXPDL.setName(workflowPackage.getUUID());
    standardXPDL.setWorkflowConfig(config);
    standardXPDL.setRouteEvalutor(context.getRouteEvalutor());
		
		context.addChild(standardXPDL);
		deployed.put(procName, standardXPDL);
		WorkflowXPDLRepository.getInstance().addWorkflowXPDL(standardXPDL);		
	}
	public void remove(String procName) throws WorkflowException
	{
		if (deployed.containsKey(procName))
		{
			WorkflowXPDL workflowRuntime = findWorkflowXPDL(procName);		
			WorkflowXPDLRepository.getInstance().removeWorkflowXPDL(workflowRuntime);		
			deployed.remove(procName);
			context.removeChild((StandardXPDL) workflowRuntime);
		}
	}

	public WorkflowXPDL findWorkflowXPDL(String procName)
	{
		if (deployed.containsKey(procName))
		{
			return (WorkflowXPDL) deployed.get(procName);
		}
		return null;
	}

	public String[] findWorkflowXPDLs()
	{
		synchronized (deployed)
		{
			String results[] = new String[deployed.size()];
			return ((String[]) deployed.keySet().toArray(results));
		}
	}
}
