//----------------------------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.workflow.xpdl.parser;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import org.huihoo.workflow.WorkflowException;
import org.huihoo.workflow.WorkflowUtilities;
import org.huihoo.workflow.event.CaseEventListener;
import org.huihoo.workflow.event.WorkEventListener;
import org.huihoo.workflow.xpdl.ExtendedAttribute;
import org.huihoo.workflow.xpdl.WorkflowActivity;
import org.huihoo.workflow.xpdl.WorkflowApplication;
import org.huihoo.workflow.xpdl.WorkflowCondition;
import org.huihoo.workflow.xpdl.WorkflowPackage;
import org.huihoo.workflow.xpdl.WorkflowProcess;
import org.huihoo.workflow.xpdl.WorkflowTransition;
import org.huihoo.workflow.xpdl.XPDLGlobals;
import org.huihoo.workflow.xpdl.activity.ActivityType;
import org.huihoo.workflow.xpdl.activity.Implementation;
import org.huihoo.workflow.xpdl.activity.JoinType;
import org.huihoo.workflow.xpdl.activity.NoImplementation;
import org.huihoo.workflow.xpdl.activity.PageImplementation;
import org.huihoo.workflow.xpdl.activity.PerformerMode;
import org.huihoo.workflow.xpdl.activity.PerformerType;
import org.huihoo.workflow.xpdl.activity.SubFlowImplementation;
import org.huihoo.workflow.xpdl.activity.ToolImplementation;
import org.huihoo.workflow.xpdl.activity.ToolSet;
import org.huihoo.workflow.xpdl.condition.ConditionType;
import org.huihoo.workflow.xpdl.condition.ScriptCondition;

public class XPDLParserTools
{
	public static List internalValidate(WorkflowPackage workflowPackage)
	{
		List errorList = new ArrayList();
		if (workflowPackage == null)
		{
			return errorList;
		}
		List processList = workflowPackage.getWorkflowProcesses();
		int process_size = processList.size();

		//	---------------------------------------------------------------
		//	 1. validate package main process
		//	---------------------------------------------------------------				
		{
			ExtendedAttribute attribute =
				(ExtendedAttribute) workflowPackage.findExtendedAttribute(XPDLGlobals.ID_PROCESS_MAIN);
			if (attribute != null)
			{
				String processId = attribute.getValue();
				if (processId == null || processId.length() == 0)
				{
					errorList.add(
						new WorkflowException(
							"package attribute '" + XPDLGlobals.ID_PROCESS_MAIN + "' must be set." + workflowPackage.toString()));
				}
			}
			else
			{
				errorList.add(
					new WorkflowException(
						"package attribute '" + XPDLGlobals.ID_PROCESS_MAIN + "' must be set." + workflowPackage.toString()));
			}
		}

		//	---------------------------------------------------------------
		//	 2. validate workflowapplication qualified class name
		//	---------------------------------------------------------------	
		List appList = workflowPackage.getApplications();
		int app_size = appList.size();
		for (int i = 0; i < app_size; ++i)
		{
			WorkflowApplication app = (WorkflowApplication) appList.get(i);
			ExtendedAttribute attribute = app.findExtendedAttribute(XPDLGlobals.APPLICATION_QUALIFIED_CLASS_NAME);
			if (attribute != null)
			{
				String className = (String) attribute.getValue();
				if (className == null || className.length() == 0)
				{
					errorList.add(
						new WorkflowException(
							"application attribute '"
								+ XPDLGlobals.APPLICATION_QUALIFIED_CLASS_NAME
								+ "' must be set.{"
								+ workflowPackage
								+ ",applicationUUID="
								+ app.getUUID()
								+ "}"));
				}
			}
			else
			{
				errorList.add(
					new WorkflowException(
						"application attribute '"
							+ XPDLGlobals.APPLICATION_QUALIFIED_CLASS_NAME
							+ "' must be set.{"
							+ workflowPackage
							+ ",applicationUUID="
							+ app.getUUID()
							+ "}"));
			}
		}

		//	---------------------------------------------------------------
		//	 3. validate workflowprocess beginActivity and endActivity
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			ExtendedAttribute attribute = workflowProcess.findExtendedAttribute(XPDLGlobals.ID_ACTIVITY_BEGIN);
			String activityId = null;

			if (attribute != null)
			{
				activityId = (String) attribute.getValue();
				if (activityId == null || activityId.length() == 0)
				{
					errorList.add(
						new WorkflowException(
							"process attribute '" + XPDLGlobals.ID_ACTIVITY_BEGIN + "' must be set." + workflowProcess.toString()));
				}
			}
			else
			{
				errorList.add(
					new WorkflowException(
						"process attribute '" + XPDLGlobals.ID_ACTIVITY_BEGIN + "' must be set." + workflowProcess.toString()));
			}

			attribute = (ExtendedAttribute) workflowProcess.findExtendedAttribute(XPDLGlobals.ID_ACTIVITY_END);
			if (attribute != null)
			{
				activityId = (String) attribute.getValue();
				if (activityId == null || activityId.length() == 0)
				{
					errorList.add(
						new WorkflowException(
							"process attribute '" + XPDLGlobals.ID_ACTIVITY_END + "' must be set." + workflowProcess.toString()));
				}
			}
			else
			{
				errorList.add(
					new WorkflowException(
						"process attribute '" + XPDLGlobals.ID_ACTIVITY_END + "' must be set." + workflowProcess.toString()));
			}
		}

		//	---------------------------------------------------------------
		//	 4. validate workflowActivity activity type
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			for (int j = 0; j < activitySize; ++j)
			{
				WorkflowActivity activity = (WorkflowActivity) activies.get(j);
				ExtendedAttribute attribute = activity.findExtendedAttribute(XPDLGlobals.ACTIVITY_TYPE);
				if (attribute != null)
				{
					String activity_type = (String) attribute.getValue();
					if (activity_type == null || activity_type.length() == 0)
					{
						errorList.add(
							new WorkflowException(
								"activity attribute '" + XPDLGlobals.ACTIVITY_TYPE + "' must be set." + activity.toString()));
					}
				}
				else
				{
					errorList.add(
						new WorkflowException(
							"activity attribute '" + XPDLGlobals.ACTIVITY_TYPE + "' must be set." + activity.toString()));
				}
			}
		}

		//	---------------------------------------------------------------
		//	 5. validate workflowActivity performer type
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();
			for (int j = 0; j < activitySize; ++j)
			{
				WorkflowActivity activity = (WorkflowActivity) activies.get(j);
				ExtendedAttribute attribute = activity.findExtendedAttribute(XPDLGlobals.ACTIVITY_TYPE);
				if (attribute != null)
				{
					if (!ActivityType.parse((String) attribute.getValue()).equals(ActivityType.ACTIVITY_BUSINESS))
					{
						continue;
					}
				}
				attribute = (ExtendedAttribute) activity.findExtendedAttribute(XPDLGlobals.PERFORMER_TYPE);
				if (attribute != null)
				{
					String performer_type = (String) attribute.getValue();
					if (performer_type == null || performer_type.length() == 0)
					{
						errorList.add(
							new WorkflowException(
								"activity attribute '" + XPDLGlobals.PERFORMER_TYPE + "' must be set." + activity.toString()));
					}
				}
				else
				{
					errorList.add(
						new WorkflowException(
							"activity attribute '" + XPDLGlobals.PERFORMER_TYPE + "' must be set." + activity.toString()));
				}
			}
		}

		//	---------------------------------------------------------------
		//	 6. validate workflowActivity Implementation referrence
		//	---------------------------------------------------------------			
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			WorkflowActivity activity = null;
			Implementation impl = null;
			ToolImplementation toolImpl = null;
			ToolSet toolSet = null;
			SubFlowImplementation subFlowImpl = null;

			for (int j = 0; j < activitySize; ++j)
			{
				activity = (WorkflowActivity) activies.get(j);
				impl = activity.getImplementation();

				if (impl == null)
				{
					continue;
				}

				if ((impl instanceof ToolImplementation) && ActivityType.ACTIVITY_BUSINESS.equals(activity.getActivityType()))
				{
					toolImpl = (ToolImplementation) impl;
					String appId = toolImpl.getValue();
					if ((appId == null) || (workflowPackage.findApplication(appId) == null))
					{
						errorList.add(new WorkflowException("Tool attribute 'Id'" + "' must be set." + activity.toString()));
					}
				}

				if ((impl instanceof ToolSet) && ActivityType.ACTIVITY_BUSINESS.equals(activity.getActivityType()))
				{
					toolSet = (ToolSet) impl;
					List toolImpls = toolSet.getToolKits();
					int toolImpls_size = toolImpls.size();

					for (int k = 0; k < toolImpls_size; ++k)
					{
						toolImpl = (ToolImplementation) toolImpls.get(k);
						String appId = toolImpl.getValue();
						if ((appId == null) || (workflowPackage.findApplication(appId) == null))
						{
							errorList.add(new WorkflowException("Tool attribute 'Id'" + "' must be set." + activity.toString()));
						}
					}
				}

				if ((impl instanceof SubFlowImplementation)
					&& ActivityType.ACTIVITY_SUBFLOW.equals(activity.getActivityType()))
				{
					subFlowImpl = (SubFlowImplementation) impl;
					String processId = subFlowImpl.getValue();
					if ((processId == null) || (workflowPackage.findWorkflowProcess(processId) == null))
					{
						errorList.add(new WorkflowException("SubFlow attribute 'Id' " + "must be set." + activity.toString()));
					}
				}
			}
		}

		//	---------------------------------------------------------------
		//	 7. validate WorkflowTransition formActivity & toActivity
		//	---------------------------------------------------------------			
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List trans = workflowProcess.getTransitions();
			int trans_size = trans.size();

			WorkflowTransition tran = null;

			for (int j = 0; j < trans_size; ++j)
			{
				tran = (WorkflowTransition) trans.get(j);
				if (tran.getFromActivity() == null)
				{
					errorList.add(new WorkflowException("Transition attribute 'From' " + "must be set." + tran.toString()));
				}

				if (tran.getToActivity() == null)
				{
					errorList.add(new WorkflowException("Transition attribute 'To' " + "must be set." + tran.toString()));
				}
			}
		}

		//	---------------------------------------------------------------
		//	 8. validate workflowActivity activity type match performer Type
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			for (int j = 0; j < activitySize; ++j)
			{
				WorkflowActivity activity = (WorkflowActivity) activies.get(j);
				ExtendedAttribute attribute = activity.findExtendedAttribute(XPDLGlobals.ACTIVITY_TYPE);
				if (attribute != null)
				{
					if (ActivityType.parse((String) attribute.getValue()).equals(ActivityType.ACTIVITY_BUSINESS))
					{
						continue;
					}

					attribute = (ExtendedAttribute) activity.findExtendedAttribute(XPDLGlobals.PERFORMER_TYPE);
					if (attribute != null
						&& !(PerformerType.parse(attribute.getValue()).equals(PerformerType.PERFORMER_AUTOMATION)))
					{
						errorList.add(
							new WorkflowException(
								"activity attribute '"
									+ XPDLGlobals.PERFORMER_TYPE
									+ "' and attribute '"
									+ XPDLGlobals.ACTIVITY_TYPE
									+ "' mismatched. "
									+ activity.toString()));
					}
				}
			}
		}
		return errorList;
	}

	public static List internalFormat(WorkflowPackage workflowPackage)
	{
		List errorList = new ArrayList();

		if (workflowPackage == null)
		{
			return errorList;
		}

		List processList = workflowPackage.getWorkflowProcesses();
		int process_size = processList.size();

		//	---------------------------------------------------------------
		//	 1. format transition hidden attribute
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List transitions = workflowProcess.getTransitions();
			int tran_size = transitions.size();
			WorkflowTransition transition = null;

			for (int j = 0; j < tran_size; ++j)
			{
				transition = (WorkflowTransition) transitions.get(j);
				ExtendedAttribute attribute = transition.findExtendedAttribute(XPDLGlobals.HIDDEN_BOOLEAN);
				if (attribute != null)
				{
					String value = attribute.getValue();
					if (value != null && Boolean.valueOf(value).booleanValue())
					{
						transition.setHidden(true);
					}
					transition.removeExtendedAttribute(XPDLGlobals.HIDDEN_BOOLEAN);
				}
			}
		}

		//	---------------------------------------------------------------
		//	 2. format transition condition
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List transitions = workflowProcess.getTransitions();
			int tran_size = transitions.size();
			WorkflowTransition transition = null;

			for (int j = 0; j < tran_size; ++j)
			{
				transition = (WorkflowTransition) transitions.get(j);
				WorkflowCondition condition = transition.getWorkflowCondition();
				if (condition != null && condition.getContent() != null)
				{
					ExtendedAttribute attribute = transition.findExtendedAttribute(XPDLGlobals.CONDITION_TYPE);
					if (attribute != null)
					{
						ConditionType ctype = ConditionType.parse(attribute.getValue());
						if (ConditionType.CONDITION_SCRIPT.equals(ctype))
						{
							transition.setWorkflowCondition(new ScriptCondition(condition.getContent()));
						}

						transition.removeExtendedAttribute(XPDLGlobals.CONDITION_TYPE);
					}
				}
			}
		}

		//	---------------------------------------------------------------
		//	 3. format activity incoming transitions & Outgoing transitions 
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List transitions = workflowProcess.getTransitions();
			int tran_size = transitions.size();
			WorkflowTransition transition = null;
			WorkflowActivity fromActivity = null;
			WorkflowActivity toActivity = null;
			for (int j = 0; j < tran_size; ++j)
			{
				transition = (WorkflowTransition) transitions.get(j);

				fromActivity = transition.getFromActivity();
				toActivity = transition.getToActivity();
				if (fromActivity != null)
				{
					fromActivity.addOutgoingTransition(transition);
				}

				if (toActivity != null)
				{
					toActivity.addIncomingTransition(transition);
				}

			}
		}

		//	---------------------------------------------------------------
		//	 4. format activity type
		//	---------------------------------------------------------------    
		for (int i = 0; i < processList.size(); ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);

			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			WorkflowActivity activity = null;
			Implementation impl = null;
			ExtendedAttribute attribute = null;
			for (int j = 0; j < activitySize; ++j)
			{
				activity = (WorkflowActivity) activies.get(j);
				attribute = (ExtendedAttribute) activity.findExtendedAttribute(XPDLGlobals.ACTIVITY_TYPE);
				if (attribute != null)
				{
					activity.setActivityType(ActivityType.parse(attribute.getValue()));
					activity.removeExtendedAttribute(XPDLGlobals.ACTIVITY_TYPE);
				}
			}

			//must set begin and end activity type
			activity = WorkflowUtilities.getBeginActivity(workflowProcess);
			if (activity != null)
			{
				activity.setActivityType(ActivityType.ACTIVITY_BEGIN);
			}

			activity = WorkflowUtilities.getEndActivity(workflowProcess);
			if (activity != null)
			{
				activity.setActivityType(ActivityType.ACTIVITY_END);
			}

		}

		//	---------------------------------------------------------------
		//	 5. format activity implementation
		//	---------------------------------------------------------------
		for (int i = 0; i < processList.size(); ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			WorkflowActivity activity = null;
			Implementation impl = null;
			ExtendedAttribute attribute = null;
			for (int j = 0; j < activitySize; ++j)
			{
				activity = (WorkflowActivity) activies.get(j);
				impl = activity.getImplementation();
				if (impl != null)
				{
					if (impl instanceof NoImplementation)
					{
						attribute = activity.findExtendedAttribute(XPDLGlobals.PAGE_URL);
						if (attribute != null)
						{
							activity.setImplementation(new PageImplementation(attribute.getValue()));
						}
					}
				}
			}
		}

		//	---------------------------------------------------------------
		//	 6. format performer type
		//	--------------------------------------------------------------- 
		for (int i = 0; i < processList.size(); ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			WorkflowActivity activity = null;
			Implementation impl = null;
			ExtendedAttribute attribute = null;
			for (int j = 0; j < activitySize; ++j)
			{
				activity = (WorkflowActivity) activies.get(j);
				attribute = (ExtendedAttribute) activity.findExtendedAttribute(XPDLGlobals.PERFORMER_TYPE);
				if (attribute != null)
				{
					activity.setPerformerType(PerformerType.parse(attribute.getValue()));
					activity.removeExtendedAttribute(XPDLGlobals.PERFORMER_TYPE);
				}
			}
		}

		//	---------------------------------------------------------------
		//	 7. format application QualifiedClassName
		//	---------------------------------------------------------------  
		List wfApps = workflowPackage.getApplications();
		int wfAppSize = wfApps.size();
		WorkflowApplication wfApp = null;
		for (int i = 0; i < wfAppSize; ++i)
		{
			wfApp = (WorkflowApplication) wfApps.get(i);
			ExtendedAttribute attribute = wfApp.findExtendedAttribute(XPDLGlobals.APPLICATION_QUALIFIED_CLASS_NAME);
			if (attribute != null)
			{
				wfApp.setQualifiedClassName(attribute.getValue());
				wfApp.removeExtendedAttribute(XPDLGlobals.APPLICATION_QUALIFIED_CLASS_NAME);
			}
		}

		//	---------------------------------------------------------------
		//	 8. validate workflowActivity Implementation & ActivityType
		//	---------------------------------------------------------------		
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			WorkflowActivity activity = null;
			Implementation impl = null;
			ToolImplementation toolImpl = null;
			ToolSet toolSet = null;
			SubFlowImplementation subFlowImpl = null;

			for (int j = 0; j < activitySize; ++j)
			{
				activity = (WorkflowActivity) activies.get(j);
				impl = activity.getImplementation();
				if (ActivityType.ACTIVITY_BUSINESS.equals(activity.getActivityType()))
				{
					if (impl != null && (impl instanceof SubFlowImplementation))
					{
						errorList.add(
							new WorkflowException(
								"ActivityType 'ACTIVITY_BUSINESS' Implementation can not be 'SubFlow'. " + activity.toString()));
					}
				}

				if (ActivityType.ACTIVITY_SUBFLOW.equals(activity.getActivityType()))
				{
					if (impl != null && !(impl instanceof SubFlowImplementation))
					{
						errorList.add(
							new WorkflowException(
								"ActivityType 'ACTIVITY_SUBFLOW' Implementation must be 'SubFlow'. " + activity.toString()));
					}
				}

				if (ActivityType.ACTIVITY_ROUTE.equals(activity.getActivityType()))
				{
					if (impl != null && !(impl instanceof NoImplementation))
					{
						errorList.add(
							new WorkflowException(
								"ActivityType 'ACTIVITY_ROUTE' Implementation must be 'No'. " + activity.toString()));
					}
				}

			}
		}

		//	---------------------------------------------------------------
		//	 9. format workflowProcess  listener class name
		//	---------------------------------------------------------------	
		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			ExtendedAttribute attribute = workflowProcess.findExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME);
			if (attribute != null)
			{
				workflowProcess.setListenerClassName(attribute.getValue());
				workflowProcess.removeExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME);
			}
		}

		//	---------------------------------------------------------------
		//	 10. format workflowActivity  listener class name
		//	---------------------------------------------------------------	
		for (int i = 0; i < processList.size(); ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			WorkflowActivity activity = null;
			Implementation impl = null;
			ExtendedAttribute attribute = null;
			for (int j = 0; j < activitySize; ++j)
			{
				activity = (WorkflowActivity) activies.get(j);
				attribute = (ExtendedAttribute) activity.findExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME);
				if (attribute != null)
				{
					activity.setListenerClassName(attribute.getValue());
					activity.removeExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME);
				}
			}
		}

		//	---------------------------------------------------------------
		//	 11. format performer mode
		//	--------------------------------------------------------------- 
		for (int i = 0; i < processList.size(); ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			WorkflowActivity activity = null;
			Implementation impl = null;
			ExtendedAttribute attribute = null;
			for (int j = 0; j < activitySize; ++j)
			{
				activity = (WorkflowActivity) activies.get(j);
				attribute = (ExtendedAttribute) activity.findExtendedAttribute(XPDLGlobals.PERFORMER_MODE);
				if (attribute != null)
				{
					activity.setPerformerMode(PerformerMode.parse(attribute.getValue()));
					activity.removeExtendedAttribute(XPDLGlobals.PERFORMER_MODE);
				}
			}
		}

		return errorList;
	}

	public static List externalFormat(WorkflowPackage workflowPackage)
	{
		return externalFormat(workflowPackage, XPDLParserTools.class.getClassLoader());
	}

	public static List externalFormat(WorkflowPackage workflowPackage, ClassLoader loader)
	{
		if (loader == null)
		{
			loader = XPDLParserTools.class.getClassLoader();
		}
		List errorList = new ArrayList();
		if (workflowPackage == null)
		{
			return errorList;
		}

		List processList = workflowPackage.getWorkflowProcesses();

		//---------------------------------------------------------
		// 1. format WorkflowProcess LISTENER_QUALIFIED_CLASS_NAME
		//---------------------------------------------------------
		for (int i = 0; i < processList.size(); ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);

			String className = workflowProcess.getListenerClassName();

			if (className != null && className.length() > 0)
			{
				try
				{
					Class implClass = loader.loadClass(className);
					CaseEventListener listener = (CaseEventListener) implClass.newInstance();
					workflowProcess.addCaseListener(listener);
				}
				catch (Throwable ex)
				{
					errorList.add(new WorkflowException("Can not load class :" + className, ex));
					System.err.println("Can not load class :" + className);
					System.err.println(loader);
				}
			}
		}
		//---------------------------------------------------------
		// 2. format WorkflowActivity LISTENER_QUALIFIED_CLASS_NAME
		//---------------------------------------------------------     
		for (int i = 0; i < processList.size(); ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();
			for (int j = 0; j < activitySize; ++j)
			{
				WorkflowActivity activity = (WorkflowActivity) activies.get(j);

				String className = activity.getListenerClassName();
				if (className != null && className.length() > 0)
				{
					try
					{
						Class implClass = loader.loadClass(className);
						WorkEventListener listener = (WorkEventListener) implClass.newInstance();

						activity.addWorkListener(listener);
					}
					catch (Throwable ex)
					{
						errorList.add(new WorkflowException("Can not load class :" + className, ex));
						System.err.println("Can not load class :" + className);
						System.err.println(loader);
					}
				}
			}
		}
		return errorList;
	}

	public static void dumpErrorList(List errorList, PrintStream stream)
	{
		if (errorList != null && errorList.size() > 0)
		{
			stream.println("--------------------------XPDLParserTools Error Dump  BEGIN--------------------------");
			int errSize = errorList.size();
			if (errSize > 0)
			{
				WorkflowException except;
				for (int i = 0; i < errSize; ++i)
				{
					except = (WorkflowException) errorList.get(i);
					except.printStackTrace(stream);
				}
			}
			stream.println("--------------------------XPDLParserTools Error Dump  END--------------------------");
		}
	}

	public static void dumpErrorList(List errorList, PrintWriter stream)
	{
		if (errorList != null && errorList.size() > 0)
		{
			stream.println("--------------------------XPDLParserTools Error Dump  BEGIN--------------------------");

			int errSize = errorList.size();
			if (errSize > 0)
			{
				WorkflowException except;
				for (int i = 0; i < errSize; ++i)
				{
					except = (WorkflowException) errorList.get(i);
					except.printStackTrace(stream);
				}
			}
			stream.println("--------------------------XPDLParserTools Error Dump  END--------------------------");
		}
	}

	public static boolean containsJoinActivity(WorkflowPackage workflowPackage)
	{
		List processList = workflowPackage.getWorkflowProcesses();
		int process_size = processList.size();

		for (int i = 0; i < process_size; ++i)
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) processList.get(i);
			List activies = workflowProcess.getActivities();
			int activitySize = activies.size();

			for (int j = 0; j < activitySize; ++j)
			{
				WorkflowActivity activity = (WorkflowActivity) activies.get(j);
				JoinType joinType = activity.getJoinType();

				if (joinType != null && !JoinType.JOIN_UNKNOWN.equals(joinType))
				{
					return true;
				}
			}
		}
		return false;
	}
}
