//----------------------------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/god4j
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : god4j@lists.sourceforge.net 
 */
//----------------------------END  LICENSE-----------------------------
package org.huihoo.god4j.editor.elements;
import java.util.List;

import org.huihoo.god4j.editor.XPDLAttribute;
import org.huihoo.god4j.editor.XPDLCollection;
import org.huihoo.god4j.editor.XPDLCollectionComponent;
import org.huihoo.god4j.editor.XPDLComplexChoice;
import org.huihoo.god4j.editor.XPDLComponent;
import org.huihoo.god4j.editor.elements.atoms.XPDLDescription;
import org.huihoo.god4j.editor.elements.atoms.XPDLJoin;
import org.huihoo.god4j.editor.elements.atoms.XPDLLimit;
import org.huihoo.god4j.editor.elements.atoms.XPDLPerformer;
import org.huihoo.god4j.editor.elements.atoms.XPDLSplit;
import org.huihoo.god4j.editor.elements.set.XPDLActivities;
import org.huihoo.god4j.editor.elements.set.XPDLExtendedAttributes;
import org.huihoo.god4j.editor.elements.set.XPDLTools;
import org.huihoo.god4j.editor.elements.set.XPDLTransitions;
import org.huihoo.god4j.editor.panels.JavaComboxPanel;
import org.huihoo.god4j.editor.panels.JavaGroupPanel;
import org.huihoo.god4j.editor.panels.JavaListChoicePanel;
import org.huihoo.god4j.editor.panels.JavaPanel;
import org.huihoo.god4j.editor.panels.JavaTabbedPanel;
import org.huihoo.workflow.WorkflowComponent;
import org.huihoo.workflow.impl.xpdl.WorkflowActivityImpl;
import org.huihoo.workflow.xpdl.WorkflowActivity;
import org.huihoo.workflow.xpdl.WorkflowTransition;
import org.huihoo.workflow.xpdl.activity.ActivityType;
/**
* Represents a WfMC DTD element that has the similar name.
* An object of this class is attribute of class
* org.webdocwf.util.jawe.graph.Activity, which
* is visual representation of this class.
*/
public class XPDLActivity extends XPDLCollectionComponent
{
	//====================================================================
	public final static int IMPLEMENTATION_NO = 0;
	public final static int IMPLEMENTATION_TOOLS = 1;
	public final static int IMPLEMENTATION_SUBFLOW = 2;

	//====================================================================
	private XPDLAttribute attrName = null;
	private XPDLDescription refDescription = null; // min=0
	private XPDLLimit refLimit = null; // min=0
	// can be Route or Implementation
	private XPDLComplexChoice refType; // must be defined
	private XPDLPerformer refPerformer = null; // min=0

	private XPDLSplit refSplit = null;
	private XPDLJoin refJoin = null;

	private XPDLExtendedAttributes refExtendedAttributes = null; // min=0

	private XPDLAttribute attrListenerClassName = null; //only for willow

	//====================================================================
	private XPDLImplementation impl = null;
	private XPDLComponent implComp;

	/** Enables canceling of changes to the tool collection. */
	private XPDLTools clonedTools;
	/** Enables canceling of changes to the extended attributes collection. */
	private XPDLExtendedAttributes clonedEAs;
	/** Enables canceling of changes to the Deadline collection. */
	/** Enables canceling of changes to the TransitionRefs collection. */
	private XPDLCollection clonedHP;

	/** Used to show so called preconditions */
	private transient XPDLSplit helperJoin;
	/** Used to show so called postconditions */
	private transient XPDLJoin helperSplit;
	/** Used to show so called postconditions */
	private transient XPDLCollection helperPostcondition;

	public XPDLActivity(XPDLCollection parent, WorkflowActivity activity)
	{
		super(parent, "Activity");
		setWorkflowComponent(activity);
	}

	//*****************************************************************
	/**
	* Returns an activity act_int_type.
	*
	* @return   The integer value that represents the act_int_type of activity.
	*/
	public int getType()
	{
		if (implComp instanceof XPDLTools)
		{
			return IMPLEMENTATION_TOOLS;
		}

		if (implComp instanceof XPDLSubFlow)
		{
			return IMPLEMENTATION_SUBFLOW;
		}

		return IMPLEMENTATION_NO;
	}

	/** Sets the act_int_type of activity. */
	public void setType(int ptype)
	{
		XPDLComplexChoice t = (XPDLComplexChoice) impl.get("Type");
		implComp = (XPDLComponent) t.getChoices()[ptype];

		t.setValue(implComp);
	}

	public XPDLComponent getImplementation()
	{
		return implComp;
	}
	/**
	* Prepares the tabbed panel to show editable fields of Activity.
	* Panel consists of six tabs that logically comprises the
	* Activity elements to be edited.
	*
	* @return XPDLPanel to be shown.
	*/
	public JavaPanel getJavaPanel()
	{
		recreatePostcondition();

		WorkflowComponent simple_component = getWorkflowComponent();

		// just to display act_int_type of activity
		XPDLAttribute tp = new XPDLAttribute(this, "ImplementationType");
		tp.initComponent();
		tp.structComponent();
		tp.setValue(implComp.getLabel());
		tp.setReadOnly(true);

		// just to display act_int_type of activity
		XPDLAttribute actp = new XPDLAttribute(this, "ActivityType");
		actp.initComponent();
		actp.structComponent();

		if (simple_component != null && (simple_component instanceof WorkflowActivity))
		{
			WorkflowActivity wf_act = (WorkflowActivity) simple_component;
			ActivityType actType = wf_act.getActivityType();
			actp.setValue(actType.getType());
		}

		actp.setReadOnly(true);

		JavaPanel p1 = null;
		JavaPanel p2 = null;
		if (getType() == IMPLEMENTATION_TOOLS)
		{
			p1 =
				new JavaGroupPanel(
					this,
					new XPDLComponent[] { attrId, attrName, actp, tp, refLimit, refDescription },
					sm.getString("GeneralKey"));

			clonedTools = (XPDLTools) implComp.clone();
			p2 = clonedTools.getJavaPanel();
		}
		else
		{
			p1 =
				new JavaGroupPanel(
					this,
					new XPDLComponent[] { attrId, attrName, actp, tp, refDescription },
					sm.getString("GeneralKey"));

			p2 = implComp.getJavaPanel();
		}
		
		JavaPanel p3 = new JavaGroupPanel(this, new Object[] { refJoin.getJavaPanel()}, sm.getString("PreconditionKey"));

		clonedHP = createPostcondition();
		clonedHP.toCollection().addAll(helperPostcondition.toCollection());
		
		JavaPanel p4 = null;
		WorkflowActivity activity = (WorkflowActivity) getWorkflowComponent();
		if (activity.getOutgoingTransitions().size() > 1)
		{
			if (refSplit.get("Type").toString().trim().length() == 0)
			{
				refSplit.set("Type", sm.getString("XORKey"));
			}
			JavaPanel hsp = refSplit.getJavaPanel();
			
			if (hsp instanceof JavaComboxPanel)
			{
				((JavaComboxPanel) hsp).getComboBox().removeItemAt(0);
			}
			p4 = new JavaGroupPanel(this, new JavaPanel[] { hsp, clonedHP.getJavaPanel()}, sm.getString("PostconditionKey"));
		}
		else
		{
			if (refSplit.get("Type").toString().trim().length() > 0)
			{
				refSplit.set("Type", "");
			}
			refSplit.setReadOnly(true);
			p4 =
				new JavaGroupPanel(
					this,
					new JavaPanel[] { refSplit.getJavaPanel(), clonedHP.getJavaPanel()},
					sm.getString("PostconditionKey"));
			if (!isReadOnly)
			{
				refSplit.setReadOnly(false);
			}
		}
		
		clonedEAs = (XPDLExtendedAttributes) refExtendedAttributes.clone();
		JavaPanel p5 = clonedEAs.getJavaPanel();

		JavaPanel p6 = null;
		if (getType() == IMPLEMENTATION_TOOLS)
		{
			p6 =
				new JavaGroupPanel(
					this,
					new XPDLComponent[] { attrListenerClassName, refPerformer },
					sm.getString("AdvancedKey"));
		}
		else
		{
			p6 = new JavaGroupPanel(this, new XPDLComponent[] { attrListenerClassName }, sm.getString("AdvancedKey"));
		}

		JavaTabbedPanel p;

		if (simple_component != null && (simple_component instanceof WorkflowActivity))
		{
			WorkflowActivity wf_act = (WorkflowActivity) simple_component;
			ActivityType actType = wf_act.getActivityType();
			if (ActivityType.ACTIVITY_BEGIN.equals(actType) || ActivityType.ACTIVITY_END.equals(actType))
			{
				p = new JavaTabbedPanel(this, new JavaPanel[] { p1 });
			}
			else
			{
				if (getType() == IMPLEMENTATION_NO)
				{
					p = new JavaTabbedPanel(this, new JavaPanel[] { p1, p3, p4, p5, p6 });
				}
				else
				{
					p = new JavaTabbedPanel(this, new JavaPanel[] { p1, p2, p3, p4, p5, p6 });
				}
			}
		}
		else
		{
			if (getType() == IMPLEMENTATION_NO)
			{
				p = new JavaTabbedPanel(this, new JavaPanel[] { p1, p3, p4, p5, p6 });
			}
			else
			{
				p = new JavaTabbedPanel(this, new JavaPanel[] { p1, p2, p3, p4, p5, p6 });
			}
		}

		return p;
	}
	/**
	* Overrides <code>toString</code> method to return the
	* name of Activity. This string is used to visually
	* display the activity name onto it's graph object.
	*
	* @return The activity <tt>name</tt> attribute.
	*/
	public String toString()
	{
		String disp = attrName.toString();
		if (disp.trim().length() == 0)
		{
			disp = attrId.toString();
		}
		return disp;
	}

	/**
	* Used when copying activities of Application(Tools) and Route act_int_type.
	* The newly created activity will have all properties same as the
	* copied one, except that it will have diferent ID.
	*
	* @return The newly created Activity object.
	*/
	public Object clone()
	{
		XPDLActivity a = (XPDLActivity) super.clone();

		a.attrName = (XPDLAttribute) this.attrName.clone();
		a.refDescription = (XPDLDescription) this.refDescription.clone();
		a.refLimit = (XPDLLimit) this.refLimit.clone();
		a.refType = (XPDLComplexChoice) this.refType.clone();
		a.refPerformer = (XPDLPerformer) this.refPerformer.clone();
		a.refSplit = (XPDLSplit) this.refSplit.clone();
		a.refJoin = (XPDLJoin) this.refJoin.clone();
		a.refExtendedAttributes = (XPDLExtendedAttributes) this.refExtendedAttributes.clone();

		a.setType(getType());
		a.helperPostcondition = a.createPostcondition();
		a.clonedTools = null;
		a.clonedEAs = null;
		a.clonedHP = null;

		a.structComponent();
		return a;
	}

	public boolean isInputValid(JavaPanel p)
	{
		if (getType() == IMPLEMENTATION_SUBFLOW)
		{
			XPDLComplexChoice t = (XPDLComplexChoice) impl.get("Type");
			XPDLSubFlow subflow = (XPDLSubFlow) t.getChoices()[IMPLEMENTATION_SUBFLOW];
			if (!subflow.isInputValid(((JavaTabbedPanel) p).getTabbedPanel(1)))
			{
				return false;
			}
		}

		if ((getType() == IMPLEMENTATION_TOOLS) && (clonedTools != null))
		{
			XPDLComplexChoice t = (XPDLComplexChoice) impl.get("Type");
			t.getChoices()[IMPLEMENTATION_TOOLS] = clonedTools;
			t.setValue(clonedTools);
		}

		if (clonedEAs != null)
		{
			complexChildren.remove(refExtendedAttributes);

			refExtendedAttributes = clonedEAs;
			complexChildren.add(8, refExtendedAttributes);
		}

		if (clonedHP != null)
		{
			helperPostcondition = clonedHP;
		}
		return true;
	}
	private XPDLCollection createPostcondition()
	{
		XPDLCollection pConds = new XPDLCollection(this)
		{
			public JavaPanel getJavaPanel()
			{
				return new JavaListChoicePanel(
					this,
					sm.getString("SelectTargetActivityKey"),
					JavaPanel.BOX_LAYOUT,
					true,
					false);
			}
		};
		pConds.initComponent();
		pConds.loadComponent();
		pConds.setReadOnly(isReadOnly);
		return pConds;
	}

	private void recreatePostcondition()
	{
		if (helperPostcondition == null)
		{
			helperPostcondition = createPostcondition();
		}

		helperPostcondition.clear();

		XPDLActivities xpActs = (XPDLActivities) getOwnerCollection();
		XPDLProcess xpProcess = (XPDLProcess) xpActs.getParentComponent();
		XPDLTransitions ts = (XPDLTransitions) xpProcess.get("Transitions");

		WorkflowComponent workflow_component = (WorkflowComponent) getWorkflowComponent();
		if (workflow_component != null && (workflow_component instanceof WorkflowActivity))
		{
			WorkflowActivity simple_component = (WorkflowActivity) workflow_component;

			List out_list = simple_component.getOutgoingTransitions();
			int out_size = out_list.size();
			for (int i = 0; i < out_size; ++i)
			{
				WorkflowTransition tran = (WorkflowTransition) out_list.get(i);
				helperPostcondition.addComponent(ts.findComponent(tran.getUUID()));
			}
		}
	}

	//==================================================================
	public void initComponent()
	{
		//	-----------------------------------------------
		super.initComponent();
		//	-----------------------------------------------	
		attrName = new XPDLAttribute(this, "Name");
		attrName.initComponent();

		attrListenerClassName = new XPDLAttribute(this, "ListenerClassName");
		attrListenerClassName.initComponent();

		refDescription = new XPDLDescription(this); // min=0
		refDescription.initComponent();

		refLimit = new XPDLLimit(this);

		impl = new XPDLImplementation(this);
		refType = new XPDLComplexChoice(this, "Type", new XPDLComponent[] { impl }, 0, false, false, false, true, true);
		refType.initComponent();
		//refType.setValue(impl);

		refPerformer = new XPDLPerformer(this); // min=0
		refPerformer.initComponent();

		refSplit = new XPDLSplit(this);
		refSplit.initComponent();

		refJoin = new XPDLJoin(this);
		refJoin.initComponent();

		refExtendedAttributes = new XPDLExtendedAttributes(this); // min=0
		refExtendedAttributes.initComponent();
	}

	public void structComponent()
	{
		//	-----------------------------------------------
		super.structComponent();
		//	-----------------------------------------------
		attrName.structComponent();
		attrListenerClassName.structComponent();

		refDescription.structComponent();
		refLimit.structComponent();
		refType.structComponent();
		refPerformer.structComponent();
		refSplit.structComponent();
		refJoin.structComponent();
		refExtendedAttributes.structComponent();

		complexChildren.add(attrName);
		complexChildren.add(refDescription);
		complexChildren.add(refLimit);
		complexChildren.add(refType);
		complexChildren.add(refPerformer);
		complexChildren.add(refSplit);
		complexChildren.add(refJoin);
		complexChildren.add(refExtendedAttributes);
		complexChildren.add(attrListenerClassName);

		attributes.add(attrName);
		attributes.add(attrListenerClassName);
	}

	/**
	* Supposed to be overriden by derived classes to implement
	* element specific reading from an XPDL Model. This implementation
	* satisfies only "simple" elements.
	*/
	public void loadComponent()
	{
		//	-----------------------------------------------
		super.loadComponent();
		//	-----------------------------------------------
		attrName.loadComponent();
		attrListenerClassName.loadComponent();

		refDescription.loadComponent();
		refLimit.loadComponent();
		refType.loadComponent();
		refPerformer.loadComponent();
		refSplit.loadComponent();
		refJoin.loadComponent();
		refExtendedAttributes.loadComponent();

		//	-----------------------------------------------
		//special loadComponent();
		//	-----------------------------------------------	
		WorkflowComponent workflow_component = getWorkflowComponent();
		if (workflow_component != null && (workflow_component instanceof WorkflowActivityImpl))
		{
			WorkflowActivityImpl simple_component = (WorkflowActivityImpl) workflow_component;
			attrId.setValue(simple_component.getUUID());
			attrName.setValue(simple_component.getName());
			attrListenerClassName.setValue(simple_component.getListenerClassName());

			if (ActivityType.ACTIVITY_SUBFLOW.equals(simple_component.getActivityType()))
			{
				setType(IMPLEMENTATION_SUBFLOW);
			}
			else if (ActivityType.ACTIVITY_BUSINESS.equals(simple_component.getActivityType()))
			{
				setType(IMPLEMENTATION_TOOLS);
			}
			else
			{
				setType(IMPLEMENTATION_NO);
			}
		}
		else
		{
			setType(IMPLEMENTATION_TOOLS);
		}
	}

	/**
	* Supposed to be overriden by derived classes to implement
	* element specific writting to an XPDL Model.
	*
	*/
	public void saveComponent()
	{
		if (isReadOnly())
		{
			return;
		}

		//	-----------------------------------------------
		super.saveComponent();
		//	-----------------------------------------------
		attrName.saveComponent();
		attrListenerClassName.saveComponent();

		refDescription.saveComponent();
		refLimit.saveComponent();
		refType.saveComponent();
		refPerformer.saveComponent();
		refSplit.saveComponent();
		refJoin.saveComponent();
		refExtendedAttributes.saveComponent();

		//	-----------------------------------------------
		//special saveComponent();
		//	-----------------------------------------------	
		WorkflowComponent workflow_component = getWorkflowComponent();
		if (workflow_component != null && (workflow_component instanceof WorkflowActivityImpl))
		{
			WorkflowActivityImpl simple_component = (WorkflowActivityImpl) workflow_component;
			simple_component.setUUID(attrId.toString());
			simple_component.setName(attrName.toString());
			simple_component.setListenerClassName(attrListenerClassName.toString());
		}
	}

	/**
	* Supposed to be overriden by derived classes to implement
	* element specific writting to an XPDL Model.
	*
	*/
	public void saveComponent(WorkflowComponent workflow_component)
	{
		//	-----------------------------------------------
		super.saveComponent(workflow_component);
		//	-----------------------------------------------
		attrName.saveComponent(workflow_component);
		attrListenerClassName.saveComponent(workflow_component);

		refDescription.saveComponent(workflow_component);
		refLimit.saveComponent(workflow_component);
		refType.saveComponent(workflow_component);
		refPerformer.saveComponent(workflow_component);
		refSplit.saveComponent(workflow_component);
		refJoin.saveComponent(workflow_component);
		refExtendedAttributes.saveComponent(workflow_component);

		//	-----------------------------------------------
		//special saveComponent();
		//	-----------------------------------------------	
		if (workflow_component != null && (workflow_component instanceof WorkflowActivityImpl))
		{
			WorkflowActivityImpl simple_component = (WorkflowActivityImpl) workflow_component;
			simple_component.setUUID(attrId.toString());
			simple_component.setName(attrName.toString());
			simple_component.setListenerClassName(attrListenerClassName.toString());
		}
	}
	//==================================================================
}
