//----------------------------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.coreImpl.xpdl.serializer;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.huihoo.commons.jdbc.JDBCFactory;
import org.huihoo.commons.jdbc.JDBCUtilities;
import org.huihoo.commons.jdbc.Store;
import org.huihoo.workflow.WorkflowComplexComponent;
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.WorkflowPackageHeader;
import org.huihoo.workflow.xpdl.WorkflowParameter;
import org.huihoo.workflow.xpdl.WorkflowProcess;
import org.huihoo.workflow.xpdl.WorkflowProcessHeader;
import org.huihoo.workflow.xpdl.WorkflowScript;
import org.huihoo.workflow.xpdl.WorkflowTransition;
import org.huihoo.workflow.xpdl.XPDLGlobals;
import org.huihoo.workflow.xpdl.XPDLSchema;
import org.huihoo.workflow.xpdl.XPDLScope;
import org.huihoo.workflow.xpdl.activity.ActivityType;
import org.huihoo.workflow.xpdl.activity.Implementation;
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.parameter.ActualParameter;
import org.huihoo.workflow.xpdl.parameter.FormalParameter;
import org.huihoo.workflow.xpdl.serializer.XPDLSerializeException;
import org.huihoo.workflow.xpdl.util.DateTools;
import org.huihoo.workflow.xpdl.util.DurationUnit;
import org.huihoo.workflow.xpdl.util.TypeDefinition;

public class XPDLSerializerJDBC
{
	public static void cleanup(WorkflowPackage pkg, Store store) throws SQLException
	{
		if (pkg == null)
		{
			return;
		}

		Connection conn = JDBCFactory.getConnection(store);
		PreparedStatement pstmt = null;

		try
		{
			conn.setAutoCommit(false);

			String strSQL = "DELETE  " + XPDLSchema.SCHEMA_PACKAGE + " WHERE vc_uuid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_PACKAGEHEADER + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_DATAFIELD + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_APPLICATION + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_SCRIPT + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_PROCESS + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_PROCESSHEADER + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_ACTIVITY + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_TRANSITION + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_EXTENDEDATTRIBUTE + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_FORMALPARAMETER + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;	
			
			strSQL = "DELETE  " + XPDLSchema.SCHEMA_ACTUALPARAMETER + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;			

			strSQL = "DELETE  " + XPDLSchema.SCHEMA_TOOL + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;		

			strSQL = "DELETE  " + XPDLSchema.SCHEMA_SUBFLOW + " WHERE vc_packageid=?";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.execute();
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;
			
			conn.commit();
		}
		catch (SQLException ex)
		{
			try
			{
				conn.rollback();
			}
			catch (SQLException e)
			{
			}
			throw ex;
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
			JDBCUtilities.cleanupNoThrow(conn);
		}

	}

	public static void serialize(WorkflowPackage pkg, Store store) throws XPDLSerializeException, SQLException
	{
		if (pkg == null)
		{
			return;
		}

		Connection conn = JDBCFactory.getConnection(store);

		try
		{
			conn.setAutoCommit(false);

			PreparedStatement pstmt = null;
			try
			{
				String strSQL = "INSERT INTO " + XPDLSchema.SCHEMA_PACKAGE + "(vc_uuid,vc_name) VALUES(?,?)";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, pkg.getUUID());
				pstmt.setString(2, pkg.getName());
				pstmt.execute();
			}
			finally
			{
				JDBCUtilities.cleanupNoThrow(pstmt);
			}

			serialize(pkg, pkg.getPackageHeader(), conn);
			serializeDataFields(pkg, conn);

			serializeExtendedAttributes(pkg, pkg, conn);

			serializeApplications(pkg, conn);
			serialize(pkg, pkg.getScript(), conn);

			List procList = pkg.getWorkflowProcesses();
			int size = procList.size();
			for (int i = 0; i < size; ++i)
			{
				serialize(pkg, (WorkflowProcess) procList.get(i), conn);
			}

			conn.commit();
		}
		catch (SQLException ex)
		{
			try
			{
				conn.rollback();
			}
			catch (SQLException e)
			{
			}
			throw ex;
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(conn);
		}
	}

	protected static void serialize(WorkflowPackage pkg, WorkflowPackageHeader header, Connection conn)
		throws XPDLSerializeException, SQLException
	{
		if (header == null)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO "
					+ XPDLSchema.SCHEMA_PACKAGEHEADER
					+ "(vc_packageid,vc_xpdlversion,vc_vendor,dat_created,vc_description) VALUES(?,?,?,?,?)";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.setString(2, header.getXPDLVersion());
			pstmt.setString(3, header.getVendor());
			pstmt.setDate(4, DateTools.toSqlDate(header.getCreationTime()));
			pstmt.setString(5, header.getDescription());
			pstmt.execute();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serializeDataFields(WorkflowPackage pkg, Connection conn)
		throws XPDLSerializeException, SQLException
	{
		List paramList = pkg.getDataFields();
		int size = paramList.size();
		if (size <= 0)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO "
					+ XPDLSchema.SCHEMA_DATAFIELD
					+ "(vc_packageid,vc_uuid,vc_name,vc_type,vc_value,vc_description) VALUES(?,?,?,?,?,?)";
			pstmt = conn.prepareStatement(strSQL);

			for (int i = 0; i < size; ++i)
			{
				WorkflowParameter param = (WorkflowParameter) paramList.get(i);
				pstmt.setString(1, pkg.getUUID());
				pstmt.setString(2, param.getUUID());
				pstmt.setString(3, param.getName());
				pstmt.setString(4, TypeDefinition.javaToXPDL(param.getType()));
				pstmt.setString(5, param.getValue().toString());
				pstmt.setString(6, param.getDescription());
				pstmt.addBatch();

				serializeExtendedAttributes(pkg, param, conn);
			}

			pstmt.executeBatch();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serializeApplications(WorkflowPackage pkg, Connection conn)
		throws XPDLSerializeException, SQLException
	{
		List appList = pkg.getApplications();
		int size = appList.size();
		if (size <= 0)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO " + XPDLSchema.SCHEMA_APPLICATION + "(vc_packageid,vc_uuid,vc_name,vc_description) VALUES(?,?,?)";
			pstmt = conn.prepareStatement(strSQL);

			for (int i = 0; i < size; ++i)
			{
				WorkflowApplication app = (WorkflowApplication) appList.get(i);
				pstmt.setString(1, pkg.getUUID());
				pstmt.setString(2, app.getUUID());
				pstmt.setString(3, app.getName());
				pstmt.setString(4, app.getDescription());
				pstmt.addBatch();

				serializeFormalParameters(pkg, app, app.getFormalParameters(), conn);

				String qClassName = app.getQualifiedClassName();
				if (qClassName != null)
				{
					app.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.APPLICATION_QUALIFIED_CLASS_NAME, qClassName));
				}
				serializeExtendedAttributes(pkg, app, conn);
			}

			pstmt.executeBatch();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serialize(WorkflowPackage pkg, WorkflowScript script, Connection conn)
		throws XPDLSerializeException, SQLException
	{
		if (script == null)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO " + XPDLSchema.SCHEMA_SCRIPT + "(vc_packageid,vc_type,vc_version,vc_grammar) VALUES(?,?,?,?)";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.setString(2, script.getType());
			pstmt.setString(3, script.getVersion());
			pstmt.setString(4, script.getGrammar());
			pstmt.execute();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serialize(WorkflowPackage pkg, WorkflowProcess proc, Connection conn)
		throws XPDLSerializeException, SQLException
	{
		PreparedStatement pstmt = null;
		try
		{
			String strSQL = "INSERT INTO " + XPDLSchema.SCHEMA_PROCESS + "(vc_packageId,vc_uuid,vc_name) VALUES(?,?,?)";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.setString(2, proc.getUUID());
			pstmt.setString(3, proc.getName());
			pstmt.execute();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		serialize(pkg, proc, proc.getProcessHeader(), conn);
		serializeActivities(pkg, proc, conn);
		serializeTransitions(pkg, proc, conn);

		String listenerClassName = proc.getListenerClassName();
		if (listenerClassName != null)
		{
			proc.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME, listenerClassName));
		}
		serializeExtendedAttributes(pkg, proc, conn);
	}

	protected static void serialize(
		WorkflowPackage pkg,
		WorkflowProcess proc,
		WorkflowProcessHeader header,
		Connection conn)
		throws XPDLSerializeException, SQLException
	{
		if (header == null)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO "
					+ XPDLSchema.SCHEMA_PROCESSHEADER
					+ "(vc_packageid,vc_processid,dat_created,dat_validfrom,dat_validto,int_limit,vc_durationunit,vc_description) VALUES(?,?,?,?,?,?,?,?)";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, pkg.getUUID());
			pstmt.setString(2, proc.getUUID());
			pstmt.setDate(3, DateTools.toSqlDate(header.getCreationTime()));

			pstmt.setDate(4, DateTools.toSqlDate(header.getValidFrom()));
			pstmt.setDate(5, DateTools.toSqlDate(header.getValidTo()));

			if (header.getLimit() != null)
			{
				pstmt.setInt(6, header.getLimit().getValue());
				pstmt.setString(7, DurationUnit.typeToString(header.getLimit().getUnit()));
			}
			else
			{
				pstmt.setInt(6, -1);
				pstmt.setString(7, null);
			}

			pstmt.setString(8, header.getDescription());
			pstmt.execute();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serializeActivities(WorkflowPackage pkg, WorkflowProcess proc, Connection conn)
		throws XPDLSerializeException, SQLException
	{
		List actList = proc.getActivities();
		int size = actList.size();
		if (size <= 0)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{

			String strSQL =
				"INSERT INTO "
					+ XPDLSchema.SCHEMA_ACTIVITY
					+ "(vc_packageid,vc_processid,vc_uuid,vc_name,int_limit,vc_durationunit,vc_impltype,vc_implid,vc_performer,vc_jointype,vc_splittype,vc_description) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)";
			pstmt = conn.prepareStatement(strSQL);

			for (int i = 0; i < size; ++i)
			{
				WorkflowActivity act = (WorkflowActivity) actList.get(i);
				List pfs = act.getPerformers();
				int sizej = pfs.size();
				StringBuffer performers = new StringBuffer();
				for (int j = 0; j < sizej; ++i)
				{
					if (j == (sizej - 1))
					{
						performers.append(pfs.get(j).toString());
					}
					else
					{
						performers.append(pfs.get(j).toString() + XPDLGlobals.PERFORMER_SEPARATOR);
					}

				}

				String implType = XPDLSchema.IMPLEMENTATION_NO;
				String implID = null;
				Implementation impl = act.getImplementation();
				if (impl instanceof ToolImplementation)
				{
					implType = XPDLSchema.IMPLEMENTATION_TOOL;
					implID = ((ToolImplementation) impl).getValue();
				}
				else if (impl instanceof ToolSet)
				{
					ToolImplementation toolImpl = (ToolImplementation) ((ToolSet) impl).getToolKits().get(0);

					implType = XPDLSchema.IMPLEMENTATION_TOOL;
					implID = toolImpl.getUUID();
					serializeToolImplementation(conn, pkg, toolImpl);
				}
				else if (impl instanceof SubFlowImplementation)
				{
					SubFlowImplementation subflowImpl = (SubFlowImplementation) impl;
					implType = XPDLSchema.IMPLEMENTATION_SUBFLOW;
					implID = ((SubFlowImplementation) impl).getUUID();
					serializeSubFlowImplementation(conn, pkg, subflowImpl);
				}

				pstmt.setString(1, pkg.getUUID());
				pstmt.setString(2, proc.getUUID());
				pstmt.setString(3, act.getUUID());
				pstmt.setString(4, act.getName());

				if (act.getDuration() != null)
				{
					pstmt.setInt(5, act.getDuration().getValue());
					pstmt.setString(6, DurationUnit.typeToString(act.getDuration().getUnit()));
				}
				else
				{
					pstmt.setInt(5, -1);
					pstmt.setString(6, null);
				}
				pstmt.setString(7, implType);
				pstmt.setString(8, implID);

				pstmt.setString(9, performers.toString());
				pstmt.setString(10, act.getJoinType().getType());
				pstmt.setString(11, act.getSplitType().getType());
				pstmt.setString(12, act.getDescription());
				pstmt.addBatch();

				ActivityType act_type = act.getActivityType();
				if (act_type != null)
				{
					act.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.ACTIVITY_TYPE, act_type.getType()));
				}

				PerformerType pf_type = act.getPerformerType();
				if (pf_type != null)
				{
					act.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.PERFORMER_TYPE, pf_type.getType()));
				}

				PerformerMode pf_mode = act.getPerformerMode();
				if (pf_mode != null)
				{
					act.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.PERFORMER_MODE, pf_mode.getMode()));
				}

				String listenerClassName = act.getListenerClassName();
				if (listenerClassName != null)
				{
					act.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME, listenerClassName));
				}
				serializeExtendedAttributes(pkg, act, conn);
			}

			pstmt.executeBatch();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

	}

	protected static void serializeTransitions(WorkflowPackage pkg, WorkflowProcess proc, Connection conn)
		throws XPDLSerializeException, SQLException
	{
		List tranList = proc.getTransitions();
		int size = tranList.size();
		if (size <= 0)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO "
					+ XPDLSchema.SCHEMA_TRANSITION
					+ "(vc_packageid,vc_processid,vc_uuid,vc_name,vc_from,vc_to,vc_condition,vc_description) VALUES(?,?,?,?,?,?,?,?)";
			pstmt = conn.prepareStatement(strSQL);

			for (int i = 0; i < size; ++i)
			{
				WorkflowTransition trans = (WorkflowTransition) tranList.get(i);
				pstmt.setString(1, pkg.getUUID());
				pstmt.setString(2, proc.getUUID());
				pstmt.setString(3, trans.getUUID());
				pstmt.setString(4, trans.getName());

				pstmt.setString(5, trans.getFromActivity().getUUID());
				pstmt.setString(6, trans.getToActivity().getUUID());

				WorkflowCondition condition = trans.getWorkflowCondition();
				if (condition != null && condition.getContent() != null)
				{
					pstmt.setString(7, trans.getWorkflowCondition().getContent());
					trans.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.CONDITION_TYPE, condition.getType().getType()));
				}
				else
				{
					pstmt.setString(7, null);
				}

				pstmt.setString(8, trans.getDescription());
				pstmt.addBatch();

				serializeExtendedAttributes(pkg, trans, conn);
			}

			pstmt.executeBatch();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serializeExtendedAttributes(
		WorkflowPackage pkg,
		WorkflowComplexComponent comp,
		Connection conn)
		throws XPDLSerializeException, SQLException
	{
		Map attrMap = comp.getExtendedAttributes();
		if (attrMap.size() <= 0)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO  "
					+ XPDLSchema.SCHEMA_EXTENDEDATTRIBUTE
					+ "(vc_scope,vc_packageid,vc_compid,vc_name,vc_value) "
					+ "VALUES('"
					+ XPDLScope.extractScope(comp)
					+ "','"
					+ pkg.getUUID()
					+ "','"
					+ comp.getUUID()
					+ "',?,?)";
			pstmt = conn.prepareStatement(strSQL);

			Iterator iterator = attrMap.values().iterator();
			while (iterator.hasNext())
			{
				ExtendedAttribute attr = (ExtendedAttribute) iterator.next();
				pstmt.setString(1, attr.getName());
				pstmt.setString(2, attr.getValue());
				pstmt.addBatch();
			}

			pstmt.executeBatch();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serializeFormalParameters(
		WorkflowPackage pkg,
		WorkflowComplexComponent comp,
		List fpList,
		Connection conn)
		throws XPDLSerializeException, SQLException
	{
		int size = fpList.size();
		if (size <= 0)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO "
					+ XPDLSchema.SCHEMA_FORMALPARAMETER
					+ "(vc_scope,vc_packageid,vc_compid,vc_uuid,int_index,vc_mode,vc_type,vc_description) "
					+ "VALUES('"
					+ XPDLScope.extractScope(comp)
					+ "','"
					+ pkg.getUUID()
					+ "','"
					+ comp.getUUID()
					+ "',?,?,?,?,?)";
			pstmt = conn.prepareStatement(strSQL);

			for (int i = 0; i < size; ++i)
			{
				FormalParameter fp = (FormalParameter) fpList.get(i);
				pstmt.setString(1, fp.getUUID());
				pstmt.setInt(2, fp.getIndex());
				pstmt.setString(3, fp.getMode().getMode());
				pstmt.setString(4, TypeDefinition.javaToXPDL(fp.getType()));
				pstmt.setString(5, fp.getDescription());

				pstmt.addBatch();
			}

			pstmt.executeBatch();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serializeActualParameters(
		WorkflowPackage pkg,
		WorkflowComplexComponent comp,
		List acpList,
		Connection conn)
		throws XPDLSerializeException, SQLException
	{
		int size = acpList.size();
		if (size <= 0)
		{
			return;
		}

		PreparedStatement pstmt = null;
		try
		{
			String strSQL =
				"INSERT INTO "
					+ XPDLSchema.SCHEMA_ACTUALPARAMETER
					+ "(vc_scope,vc_packageid,vc_compid,int_index,vc_name) "
					+ "VALUES('"
					+ XPDLScope.extractScope(comp)
					+ "','"
					+ pkg.getUUID()
					+ "','"
					+ comp.getUUID()
					+ "',?,?)";
			pstmt = conn.prepareStatement(strSQL);

			for (int i = 0; i < size; ++i)
			{
				ActualParameter acp = (ActualParameter) acpList.get(i);
				pstmt.setInt(1, i);
				pstmt.setString(2, acp.getValue());

				pstmt.addBatch();
			}

			pstmt.executeBatch();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
	}

	protected static void serializeToolImplementation(
		Connection conn,
		WorkflowPackage workflowPackage,
		ToolImplementation toolImpl)
		throws XPDLSerializeException, SQLException
	{
		String strSQL =
			"INSERT INTO  "
				+ XPDLSchema.SCHEMA_TOOL
				+ "(vc_package,vc_uuid,vc_description,vc_appid) "
				+ "VALUES('"
				+ workflowPackage.getUUID()
				+ "',?,?,?)";
		PreparedStatement pstmt = null;
		try
		{
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, toolImpl.getUUID());
			pstmt.setString(2, toolImpl.getDescription());
			pstmt.setString(3, toolImpl.getValue());
			pstmt.execute();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}
		serializeActualParameters(workflowPackage, toolImpl, toolImpl.getActualParameters(), conn);
		serializeExtendedAttributes(workflowPackage, toolImpl, conn);
	}

	protected static void serializeSubFlowImplementation(
		Connection conn,
		WorkflowPackage workflowPackage,
		SubFlowImplementation subflowImpl)
		throws XPDLSerializeException, SQLException
	{
		String strSQL =
			"INSERT INTO  "
				+ XPDLSchema.SCHEMA_SUBFLOW
				+ "(vc_package,vc_uuid,vc_description,vc_processid) "
				+ "VALUES('"
				+ workflowPackage.getUUID()
				+ "',?,?,?)";
		PreparedStatement pstmt = null;
		try
		{
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, subflowImpl.getUUID());
			pstmt.setString(2, subflowImpl.getDescription());
			pstmt.setString(3, subflowImpl.getValue());
			pstmt.execute();
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		serializeExtendedAttributes(workflowPackage, subflowImpl, conn);
	}
}
