//----------------------------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.io.IOException;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.huihoo.workflow.WorkflowComplexComponent;
import org.huihoo.workflow.resources.XMLConstants;
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.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.SplitType;
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.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 XPDLSerializerIO
{
	public static void serialize(WorkflowPackage pkg, Writer out) throws XPDLSerializeException, IOException
	{
		if (pkg == null)
		{
			return;
		}
		String nsPrefix = "";
		String nsURI = "xmlns=\"" + XMLConstants.XPDL_NS_URI + "\"";
//
//		if (XMLConstants.XPDL_NS_PREFIX != null && XMLConstants.XPDL_NS_PREFIX.trim().length() > 0)
//		{
//			nsPrefix = XMLConstants.XPDL_NS_PREFIX + ":";
//			nsURI = "xmlns:" + XMLConstants.XPDL_NS_PREFIX + "=\"" + XMLConstants.XPDL_NS_URI + "\"";
//		}

		xmlDecl(out);
		out.write("<" + nsPrefix + "Package ");
		stdAttributes(pkg, out);
		out.write(" " + nsURI);
		out.write(">");
		newLine(out);
		newLine(out);

		//Package Header
		serialize(pkg.getPackageHeader(), out, nsPrefix, 1);
		newLine(out);

		//DataFields
		List initParams = pkg.getDataFields();
		if (initParams.size() > 0)
		{
			pushIdent(out, 1);
			out.write("<" + nsPrefix + "DataFields>");
			newLine(out);
			for (int i = 0; i < initParams.size(); ++i)
			{
				serialize((WorkflowParameter) initParams.get(i), out, nsPrefix, 2);
			}
			pushIdent(out, 1);
			out.write("</" + nsPrefix + "DataFields>");
			newLine(out);
		}
		newLine(out);

		//ExtendedAttributes
		extendedAttriutes(pkg, out, nsPrefix, 1);
		newLine(out);

		//WorkflowScript
		serialize(pkg.getScript(), out, nsPrefix, 1);
		newLine(out);

		//Applications
		List apps = pkg.getApplications();
		if (apps.size() > 0)
		{
			pushIdent(out, 1);
			out.write("<" + nsPrefix + "Applications>");
			newLine(out);
			for (int i = 0; i < apps.size(); ++i)
			{
				serialize((WorkflowApplication) apps.get(i), out, nsPrefix, 2);
			}
			pushIdent(out, 1);
			out.write("</" + nsPrefix + "Applications>");
			newLine(out);
		}
		newLine(out);

		//WorkflowProcesses
		List processes = pkg.getWorkflowProcesses();
		if (processes.size() > 0)
		{
			pushIdent(out, 1);
			out.write("<" + nsPrefix + "WorkflowProcesses>");
			newLine(out);
			newLine(out);
			for (int i = 0; i < processes.size(); ++i)
			{
				serialize((WorkflowProcess) processes.get(i), out, nsPrefix, 2);
				newLine(out);
			}
			pushIdent(out, 1);
			out.write("</" + nsPrefix + "WorkflowProcesses>");
			newLine(out);
		}
		out.write("</" + nsPrefix + "Package> ");
	}
	protected static void xmlDecl(Writer out) throws XPDLSerializeException, IOException
	{
		out.write(Constants.XPDL_XML_DECL);
		newLine(out);
	}
	protected static void serialize(WorkflowPackageHeader pkgHeader, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (pkgHeader == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "PackageHeader>");
		newLine(out);
		if (pkgHeader.getXPDLVersion() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "XPDLVersion>");
			out.write(pkgHeader.getXPDLVersion());
			out.write("</" + nsPrefix + "XPDLVersion>");
			newLine(out);
		}
		if (pkgHeader.getVendor() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Vendor>");
			out.write(pkgHeader.getVendor());
			out.write("</" + nsPrefix + "Vendor>");
			newLine(out);
		}
		if (pkgHeader.getCreationTime() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Created>");
			out.write(DateTools.toString(pkgHeader.getCreationTime()));
			out.write("</" + nsPrefix + "Created>");
			newLine(out);
		}
		if (pkgHeader.getDescription() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Description>");
			out.write(pkgHeader.getDescription());
			out.write("</" + nsPrefix + "Description>");
			newLine(out);
		}
		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "PackageHeader>");
		newLine(out);
	}
	protected static void serialize(WorkflowApplication application, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (application == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "Application");
		minAttributes(application, out);
		out.write(">");
		newLine(out);
		if (application.getDescription() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Description>");
			out.write(application.getDescription());
			out.write("</" + nsPrefix + "Description>");
			newLine(out);
		}
		List formals = application.getFormalParameters();
		if (formals.size() > 0)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "FormalParameters>");
			newLine(out);
			for (int i = 0; i < formals.size(); ++i)
			{
				formalParameter((FormalParameter) formals.get(i), out, nsPrefix, ident_unit + 2);
			}
			pushIdent(out, ident_unit + 1);
			out.write("</" + nsPrefix + "FormalParameters>");
			newLine(out);
		}

		String qClassName = application.getQualifiedClassName();
		if (qClassName != null)
		{
			application.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.APPLICATION_QUALIFIED_CLASS_NAME, qClassName));
		}
		extendedAttriutes(application, out, nsPrefix, ident_unit + 1);
		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "Application>");
		newLine(out);
	}
	protected static void serialize(WorkflowParameter parameter, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (parameter == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "DataField");
		minAttributes(parameter, out);
		out.write(">");
		newLine(out);

		if (parameter.getDescription() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Description>");
			out.write(parameter.getDescription());
			out.write("</" + nsPrefix + "Description>");
			newLine(out);
		}
		pushIdent(out, ident_unit + 1);
		out.write("<" + nsPrefix + "DataType>");
		newLine(out);

		if (parameter.getType().isPrimitive() || parameter.getType().getName().equals(String.class.getName()))
		{
			pushIdent(out, ident_unit + 2);
			out.write("<" + nsPrefix + "BasicType Type=\"" + TypeDefinition.javaToXPDL(parameter.getType()) + "\"/>");
			newLine(out);
		}
		else
		{
			//noop
		}

		pushIdent(out, ident_unit + 1);
		out.write("</" + nsPrefix + "DataType>");
		newLine(out);

		pushIdent(out, ident_unit + 1);
		if (parameter.getValue() != null)
		{
			out.write("<" + nsPrefix + "InitialValue>");
			out.write(parameter.getValue().toString());
			out.write("</" + nsPrefix + "InitialValue>");
			newLine(out);
		}

		extendedAttriutes(parameter, out, nsPrefix, ident_unit + 1);

		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "DataField>");
		newLine(out);
	}
	protected static void serialize(WorkflowScript script, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (script == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "Script ");
		if (script.getType() != null)
		{
			out.write(" Type=\"" + script.getType() + "\"");
		}
		if (script.getVersion() != null)
		{
			out.write(" Version=\"" + script.getVersion() + "\"");
		}
		if (script.getGrammar() != null)
		{
			out.write(" Grammar=\"" + script.getGrammar() + "\"");
		}
		out.write("/>");
		newLine(out);
	}
	protected static void serialize(WorkflowProcess process, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (process == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "WorkflowProcess");
		minAttributes(process, out);
		out.write(">");
		newLine(out);

		serialize(process.getProcessHeader(), out, nsPrefix, ident_unit + 1);
		newLine(out);
		List ativities = process.getActivities();
		if (ativities.size() > 0)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Activities>");
			newLine(out);
			for (int i = 0; i < ativities.size(); ++i)
			{
				serialize((WorkflowActivity) ativities.get(i), out, nsPrefix, ident_unit + 2);
				newLine(out);
			}
			pushIdent(out, ident_unit + 1);
			out.write("</" + nsPrefix + "Activities>");
			newLine(out);
			newLine(out);
		}
		List trans = process.getTransitions();
		if (trans.size() > 0)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Transitions>");
			newLine(out);
			for (int i = 0; i < trans.size(); ++i)
			{
				serialize((WorkflowTransition) trans.get(i), out, nsPrefix, ident_unit + 2);
				if (i < (trans.size() - 1))
				{
					newLine(out);
				}
			}
			pushIdent(out, ident_unit + 1);
			out.write("</" + nsPrefix + "Transitions>");
			newLine(out);
			newLine(out);
		}

		String listenerClassName = process.getListenerClassName();
		if (listenerClassName != null && !listenerClassName.equals(""))
		{
			process.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME, listenerClassName));
		}
		extendedAttriutes(process, out, nsPrefix, ident_unit + 1);

		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "WorkflowProcess>");
		newLine(out);
	}
	protected static void serialize(WorkflowProcessHeader processHeader, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (processHeader == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "ProcessHeader ");
		if (processHeader.getDurationUnit() != null)
		{
			out.write(" DurationUnit=\"" + DurationUnit.typeToString(processHeader.getDurationUnit()) + "\"");
		}
		out.write(">");
		newLine(out);
		if (processHeader.getCreationTime() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Created>");
			out.write(DateTools.toString(processHeader.getCreationTime()));
			out.write("</" + nsPrefix + "Created>");
			newLine(out);
		}
		if (processHeader.getDescription() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Description>");
			out.write(processHeader.getDescription());
			out.write("</" + nsPrefix + "Description>");
			newLine(out);
		}
		if (processHeader.getLimit() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Limit>");
			out.write(processHeader.getLimit().toString());
			out.write("</" + nsPrefix + "Limit>");
			newLine(out);
		}
		if (processHeader.getValidFrom() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "ValidFrom>");
			out.write(DateTools.toString(processHeader.getValidFrom()));
			out.write("</" + nsPrefix + "ValidFrom>");
			newLine(out);
		}
		if (processHeader.getValidTo() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "ValidTo>");
			out.write(DateTools.toString(processHeader.getValidTo()));
			out.write("</" + nsPrefix + "ValidTo>");
			newLine(out);
		}
		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "ProcessHeader>");
		newLine(out);
	}
	protected static void serialize(WorkflowActivity activity, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (activity == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "Activity");
		minAttributes(activity, out);
		out.write(">");
		newLine(out);
		if (activity.getDescription() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Description>");
			out.write(activity.getDescription());
			out.write("</" + nsPrefix + "Description>");
			newLine(out);
		}
		if (activity.getDuration() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Limit>");
			out.write(activity.getDuration().toString());
			out.write("</" + nsPrefix + "Limit>");
			newLine(out);
		}

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

		}
		pushIdent(out, ident_unit + 1);

		if (performers.length() > 0)
		{
			out.write("<" + nsPrefix + "Performer>");
			out.write(performers.toString());
			out.write("</" + nsPrefix + "Performer>");
		}
		else
		{
			//out.write("<" + nsPrefix + "Performer/>");		
		}

		newLine(out);
		serialize(activity.getImplementation(), out, nsPrefix, ident_unit + 1);
		serializeTransitionRestrictions(activity, out, nsPrefix, ident_unit + 1);

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

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

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

		String listenerClassName = activity.getListenerClassName();
		if (listenerClassName != null && !listenerClassName.equals(""))
		{
			activity.addExtendedAttribute(
				new ExtendedAttribute(XPDLGlobals.LISTENER_QUALIFIED_CLASS_NAME, listenerClassName));
		}
		extendedAttriutes(activity, out, nsPrefix, ident_unit + 1);

		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "Activity>");
		newLine(out);
	}
	protected static void serialize(WorkflowTransition transition, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (transition == null)
		{
			return;
		}
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "Transition");
		minAttributes(transition, out);
		if (transition.getFromActivity() != null)
		{
			out.write(" From=\"" + transition.getFromActivity().getUUID() + "\"");
		}
		if (transition.getToActivity() != null)
		{
			out.write(" To=\"" + transition.getToActivity().getUUID() + "\"");
		}
		out.write(">");
		newLine(out);
		if (transition.getDescription() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Description>");
			out.write(transition.getDescription());
			out.write("</" + nsPrefix + "Description>");
			newLine(out);
		}
		serializeCondition(transition, out, nsPrefix, ident_unit + 1);
		
		if(transition.isHidden())
		{
			transition.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.HIDDEN_BOOLEAN, "true"));
		}
		extendedAttriutes(transition, out, nsPrefix, ident_unit + 1);
		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "Transition>");
		newLine(out);
	}
	protected static void serialize(Implementation impl, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "Implementation>");
		newLine(out);
		if (impl == null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "No/>");
			newLine(out);
		}
		else
		{
			if ((impl instanceof NoImplementation) || (impl instanceof PageImplementation))
			{
				pushIdent(out, ident_unit + 1);
				out.write("<" + nsPrefix + "No/>");
				newLine(out);
			}
			else if (impl instanceof SubFlowImplementation)
			{
				pushIdent(out, ident_unit + 1);
				out.write("<" + nsPrefix + "SubFlow");
				SubFlowImplementation subflow = (SubFlowImplementation) impl;
				if (subflow.getValue() != null)
				{
					out.write(" Id=\"" + subflow.getValue() + "\"");
				}
				out.write(">");
				newLine(out);
				pushIdent(out, ident_unit + 1);
				extendedAttriutes_impl(subflow.getExtendedAttributes(), out, nsPrefix, ident_unit + 1);
				out.write("</" + nsPrefix + "SubFlow>");
				newLine(out);
			}
			else if (impl instanceof ToolImplementation)
			{
				serializeTool((ToolImplementation) impl, out, nsPrefix, ident_unit + 1);
			}
			else if (impl instanceof ToolSet)
			{
				ToolSet toolSet = (ToolSet) impl;
				List tools = toolSet.getToolKits();
				for (int i = 0; i < tools.size(); ++i)
				{
					serializeTool((ToolImplementation) tools.get(i), out, nsPrefix, ident_unit + 1);
				}
			}
		}
		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "Implementation>");
		newLine(out);
	}
	protected static void serializeTool(ToolImplementation impl, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (impl == null)
		{
			return;
		}

		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "Tool ");
		if (impl.getValue() != null)
		{
			out.write(" Id=\"" + impl.getValue() + "\"");
		}
		out.write(">");

		newLine(out);
		List actuals = impl.getActualParameters();
		//System.err.println("XPDLIO : getActualParameters || "+impl.getActualParameters());
		if (actuals.size() > 0)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "ActualParameters>");
			newLine(out);
			for (int i = 0; i < actuals.size(); ++i)
			{
				actualParameter((ActualParameter) actuals.get(i), out, nsPrefix, ident_unit + 2);
			}
			pushIdent(out, ident_unit + 1);
			out.write("</" + nsPrefix + "ActualParameters>");
			newLine(out);
		}
		extendedAttriutes_impl(impl.getExtendedAttributes(), out, nsPrefix, ident_unit + 1);
		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "Tool>");
		newLine(out);
	}
	protected static void serializeTransitionRestrictions(
		WorkflowActivity activity,
		Writer out,
		String nsPrefix,
		int ident_unit)
		throws XPDLSerializeException, IOException
	{
		JoinType joinType = activity.getJoinType();
		SplitType splitType = activity.getSplitType();

		if ((joinType != null && !(JoinType.JOIN_UNKNOWN.equals(joinType)))
			|| (splitType != null && !(SplitType.SPLIT_UNKNOWN.equals(splitType))))
		{
			pushIdent(out, ident_unit);
			out.write("<" + nsPrefix + "TransitionRestrictions>");
			newLine(out);
			if (joinType != null && !(JoinType.JOIN_UNKNOWN.equals(joinType)))
			{
				pushIdent(out, ident_unit + 1);
				out.write("<" + nsPrefix + "TransitionRestriction>");
				newLine(out);
				pushIdent(out, ident_unit + 2);
				out.write("<" + nsPrefix + "Join Type=\"" + activity.getJoinType().getType() + "\"/>");
				newLine(out);
				pushIdent(out, ident_unit + 1);
				out.write("</" + nsPrefix + "TransitionRestriction>");
				newLine(out);
			}
			if (splitType != null && !(SplitType.SPLIT_UNKNOWN.equals(splitType)))
			{
				pushIdent(out, ident_unit + 1);
				out.write("<" + nsPrefix + "TransitionRestriction>");
				newLine(out);
				pushIdent(out, ident_unit + 2);
				out.write("<" + nsPrefix + "Split Type=\"" + activity.getSplitType().getType() + "\"/>");
				newLine(out);
				pushIdent(out, ident_unit + 1);
				out.write("</" + nsPrefix + "TransitionRestriction>");
				newLine(out);
			}
			pushIdent(out, ident_unit);
			out.write("</" + nsPrefix + "TransitionRestrictions>");
			newLine(out);
		}
	}
	protected static void serializeCondition(WorkflowTransition transition, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		WorkflowCondition condition = transition.getWorkflowCondition();
		transition.removeExtendedAttribute(XPDLGlobals.CONDITION_TYPE);

		if (condition != null && condition.getContent() != null)
		{
			transition.addExtendedAttribute(new ExtendedAttribute(XPDLGlobals.CONDITION_TYPE, condition.getType().getType()));

			if (ConditionType.CONDITION_SCRIPT.equals(condition.getType()))
			{
				pushIdent(out, ident_unit);
				out.write("<" + nsPrefix + "Condition>");
				out.write(condition.getContent());
				out.write("</" + nsPrefix + "Condition>");
				newLine(out);
			}
			else
			{
				pushIdent(out, ident_unit);
				out.write("<" + nsPrefix + "Condition>");
				out.write("<![CDATA[");
				out.write(condition.getContent());
				out.write("]]>");
				out.write("</" + nsPrefix + "Condition>");
				newLine(out);
			}
		}
	}
	protected static void minAttributes(WorkflowComplexComponent elem, Writer out)
		throws XPDLSerializeException, IOException
	{
		if (elem.getUUID() == null)
		{
			throw new XPDLSerializeException("Id required {" + elem + "}");
		}
		out.write(" Id=\"" + elem.getUUID() + "\"");
		if (elem.getName() != null)
		{
			out.write(" Name=\"" + elem.getName() + "\"");
		}
	}
	protected static void stdAttributes(WorkflowComplexComponent elem, Writer out)
		throws XPDLSerializeException, IOException
	{
		if (elem.getUUID() == null)
		{
			throw new XPDLSerializeException("Id reqired {" + elem + "}");
		}
		out.write(" Id=\"" + elem.getUUID() + "\"");
		if (elem.getName() != null)
		{
			out.write(" Name=\"" + elem.getName() + "\"");
		}
		if (elem.getDescription() != null)
		{
			out.write(" Description=\"" + elem.getDescription() + "\"");
		}
	}
	protected static void extendedAttriutes(WorkflowComplexComponent elem, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		extendedAttriutes_impl(elem.getExtendedAttributes(), out, nsPrefix, ident_unit);
	}

	protected static void extendedAttriutes_impl(Map elemAttributes, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		if (elemAttributes == null || elemAttributes.size() == 0)
		{
			return;
		}
		Iterator iterator = elemAttributes.keySet().iterator();
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "ExtendedAttributes>");
		newLine(out);
		while (iterator.hasNext())
		{
			Object name = iterator.next();
			Object value = elemAttributes.get(name);
			if (value instanceof ExtendedAttribute)
			{
				ExtendedAttribute attribute = (ExtendedAttribute) value;
				pushIdent(out, ident_unit + 1);
				out.write("<" + nsPrefix + "ExtendedAttribute");
				String attrname = (String) attribute.getName();
				if (attrname != null && attrname.length() > 0)
				{
					out.write(" Name=\"" + attrname + "\"");
					if (attribute.getValue() != null)
					{
						out.write(" Value=\"" + attribute.getValue() + "\"");
					}
				}
			}
			else
			{
				//				pushIdent(out, ident_unit + 1);
				//				out.write("<" + nsPrefix + "ExtendedAttribute");
				//
				//				out.write(" Name=\"" + name.toString() + "\"");
				//				if (value != null)
				//				{
				//					out.write(" Value=\"" + value.toString() + "\"");
				//				}
				System.err.println(
					"XPDLSerializerIO Error : NOT an ExtendedAttribute {" + value.getClass() + "," + value + "}");
			}

			out.write("/>");
			newLine(out);
		}
		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "ExtendedAttributes>");
		newLine(out);
	}
	protected static void formalParameter(FormalParameter param, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "FormalParameter");
		if (param.getUUID() != null)
		{
			out.write(" Id=\"" + param.getUUID() + "\"");
		}
		out.write(" Index=\"" + param.getIndex() + "\"");
		out.write(" Mode=\"" + param.getMode().getMode() + "\"");
		out.write(">");
		newLine(out);
		if (param.getDescription() != null)
		{
			pushIdent(out, ident_unit + 1);
			out.write("<" + nsPrefix + "Description>");
			out.write(param.getDescription());
			out.write("</" + nsPrefix + "Description>");
			newLine(out);
		}
		pushIdent(out, ident_unit + 1);
		out.write("<" + nsPrefix + "DataType>");
		newLine(out);

		if (param.getType().isPrimitive() || param.getType().getName().equals("".getClass().getName()))
		{
			pushIdent(out, ident_unit + 2);
			out.write("<" + nsPrefix + "BasicType Type=\"" + TypeDefinition.javaToXPDL(param.getType()) + "\"/>");
			newLine(out);
		}
		else
		{
			//noop
		}
		pushIdent(out, ident_unit + 1);
		out.write("</" + nsPrefix + "DataType>");
		newLine(out);

		pushIdent(out, ident_unit);
		out.write("</" + nsPrefix + "FormalParameter>");
		newLine(out);
	}
	protected static void actualParameter(ActualParameter param, Writer out, String nsPrefix, int ident_unit)
		throws XPDLSerializeException, IOException
	{
		pushIdent(out, ident_unit);
		out.write("<" + nsPrefix + "ActualParameter>");
		out.write(param.getValue());
		out.write("</" + nsPrefix + "ActualParameter>");
		newLine(out);
	}
	protected static void newLine(Writer out) throws XPDLSerializeException, IOException
	{
		out.write(System.getProperty("line.separator"));
	}
	protected static void pushIdent(Writer out, int ident_unit) throws XPDLSerializeException, IOException
	{
		for (int i = 0; i < ident_unit; ++i)
		{
			out.write("  ");
		}
	}
}
