//----------------------------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 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.XPDLUtils;
import org.huihoo.god4j.editor.elements.atoms.XPDLDescription;
import org.huihoo.god4j.editor.elements.set.XPDLActivities;
import org.huihoo.god4j.editor.elements.set.XPDLActualParameters;
import org.huihoo.god4j.editor.elements.set.XPDLApplications;
import org.huihoo.god4j.editor.elements.set.XPDLExtendedAttributes;
import org.huihoo.god4j.editor.elements.set.XPDLFormalParameters;
import org.huihoo.god4j.editor.elements.set.XPDLProcesses;
import org.huihoo.god4j.editor.elements.set.XPDLTools;
import org.huihoo.god4j.editor.panels.JavaComboxButtonPanel;
import org.huihoo.god4j.editor.panels.JavaGroupPanel;
import org.huihoo.god4j.editor.panels.JavaPanel;
import org.huihoo.god4j.editor.panels.JavaTabbedPanel;
import org.huihoo.workflow.WorkflowComponent;
import org.huihoo.workflow.xpdl.activity.ToolImplementation;
/**
* Represents a WfMC DTD element that has the similar name.
*/
public class XPDLTool extends XPDLCollectionComponent
{
	private XPDLActualParameters refActualParameters; // min=0
	private XPDLDescription refDescription = null; // min=0
	private XPDLExtendedAttributes refExtendedAttributes = null; // min=0

	//---------------------------------------------------------	
	/** Holds reference to choosen application for Tool instance. */
	private XPDLComplexChoice refAppChoices;
	/** Enables canceling of changes to the actual param. collection. */
	private XPDLActualParameters clonedAPs;
	/** Enables canceling of changes to the extended attributes collection. */
	private XPDLExtendedAttributes clonedEAs;

	/**
	* Defined application at the workflow process level
	* where instance of object where this instance of
	* element belongs. Applications defined at the Package
	* level are also included.
	*/
	private transient XPDLApplications definedApplications = null;
	//---------------------------------------------------------	
	/**
	* Creates a new instance of the class.
	*
	* @param tls The reference to collection of tools where
	*            this instance will be put into.
	
	* @param wp  The workflow process that holds activity which
	*            member is this class instance.
	*/
	public XPDLTool(XPDLCollection myCollection, ToolImplementation toolImpl)
	{
		super(myCollection);
		setWorkflowComponent(toolImpl);
	}
	
	public XPDLApplication  getChoosenApplication()
	{
		return (XPDLApplication) refAppChoices.getChoosen();
	}
	
	/**
	* Uses a trick to set the cloned instance of actual parameters to
	* be edited, so that canceling of changes to the actual parameter
	* collection can be handled - the real instance of actual parameters
	* is set to the cloned instance within the isValidData method.
	*/
	public JavaPanel getJavaPanel()
	{
		clonedAPs = (XPDLActualParameters) refActualParameters.clone();
		JavaPanel p1 =
			new JavaGroupPanel(
				this,
				new XPDLComponent[] {refAppChoices, clonedAPs, refDescription },
				sm.getString("GeneralKey"));

		clonedEAs = (XPDLExtendedAttributes) refExtendedAttributes.clone();
		JavaPanel p2 = clonedEAs.getJavaPanel();

		return new JavaTabbedPanel(this, new JavaPanel[] { p1, p2});
	}
	/**
	* Used to create exact copy of instance of this class.
	* The newly created instance will have all the properties
	* same as the copied one.
	*
	* @return The newly created instance of this class.
	*/
	public Object clone()
	{
		XPDLTool a = (XPDLTool) super.clone();

		a.refActualParameters = (XPDLActualParameters) this.refActualParameters.clone();
		a.refDescription = (XPDLDescription) this.refDescription.clone();
		a.refExtendedAttributes = (XPDLExtendedAttributes) this.refExtendedAttributes.clone();
		a.definedApplications = this.definedApplications;

		a.refAppChoices = new XPDLComplexChoice(this, "Application", null, 0)
		{
			public JavaPanel getJavaPanel()
			{
				if (definedApplications != null)
				{
					choices = definedApplications.getComboxComponents().toArray();
				}
				else
				{
					choices = null;
				}
				return new JavaComboxButtonPanel(this, definedApplications);
			}
		};
		a.refAppChoices.initComponent();
		a.refAppChoices.setValue(refAppChoices.getChoosen());
		a.refAppChoices.setRequired(true);

		a.clonedAPs = null;
		a.clonedEAs = null;

		a.structComponent();

		return a;
	}

	public boolean isInputValid(JavaPanel groupPanel)
	{
		boolean isValidEnter = super.isInputValid(groupPanel);
		
		JavaPanel cbp_tab = ((JavaTabbedPanel) groupPanel).getTabbedPanel(0);
		JavaComboxButtonPanel cbp=(JavaComboxButtonPanel) ((JavaGroupPanel) cbp_tab).getPanel(0);
		XPDLApplication app = (XPDLApplication) cbp.getSelectedItem();
		
		String message = sm.getString("ErrorFormalAndActualParameterTypesMustMatch");
		String dialogTitle = sm.getString("DialogFormalAndActualParameterTypesDoNotMatch");
		String elementTitle = getLabel() + ": ";
		
		if (((XPDLComplexChoice) app.get("Choice")).getChoosen() instanceof XPDLFormalParameters)
		{
			XPDLFormalParameters fps = (XPDLFormalParameters) ((XPDLComplexChoice) app.get("Choice")).getChoices()[0];
			int am = XPDLUtils.checkParameterMatching(fps, clonedAPs);
			if (am == 1)
			{
				message = sm.getString("ErrorFormalAndActualParameterNoMustMatch");
				dialogTitle = sm.getString("DialogFormalAndActualParameterNoDoNotMatch");
				isValidEnter = false;
			}
			else if (am == 2)
			{
				isValidEnter = false;
			}
		}
		if (!isValidEnter)
		{
			JavaPanel.errorMessage(groupPanel.getDialog(), dialogTitle, elementTitle, message);
		}
		else
		{
			// if the check is passed, replace actual parameters with the one entered
			if (clonedAPs != null)
			{
				complexChildren.remove(refActualParameters);
				refActualParameters = clonedAPs;
				complexChildren.add(2, refActualParameters);
			}
			if (clonedEAs != null)
			{
				complexChildren.remove(refExtendedAttributes);
				refExtendedAttributes = clonedEAs;
				complexChildren.add(4, refExtendedAttributes);
			}
		}
		return isValidEnter;
	}
	//==================================================================
	/**
	* The classes that are derived from this class has to give its
	* definition for this method. It is used to insert all members
	* of those classes that are derived from XPDLComp
	* class (or classes that are derived from that class) into
	* one list, and the members that are derived from
	* XPDLAttribute class also to insert into other list.
	* Many methods of this class uses those lists:
	* <code>toXPDL</code> method uses them to properly write an element
	* tag to the XPDL file,
	* <code>fromXPDL</code> method uses them to properly read an element
	* tag from the XPDL file,
	* <code>getPanel</code> method uses them to properly display members
	* of this class,
	* <code>get</code> and <code>set</code> uses them to properly
	* retrieve/set the elements from list, ... and so on
	* <p>NOTE: The order of inserted elements is relevant for XPDL to be
	*          valid (members of classes derived from this class must be
	*          inserted into first mentioned list in the same order that
	*          they are within a corresponding tag for those classes
	*          within WfMC XPDL).
	*/
	public void initComponent()
	{
		//	-----------------------------------------------
		super.initComponent();
		//	-----------------------------------------------		
		refDescription = new XPDLDescription(this); // min=0
		refDescription.initComponent();

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

//------------------------------------------------------------------------
		XPDLTools xpTools = (XPDLTools) getOwnerCollection();

		XPDLImplementation xpdlImpl = (XPDLImplementation) xpTools.getParentComponent();
		XPDLActivity xpAct = (XPDLActivity) xpdlImpl.getParentComponent();
		XPDLActivities xpActs = (XPDLActivities) xpAct.getOwnerCollection();

		XPDLProcess xpProcess = (XPDLProcess) xpActs.getParentComponent();
		XPDLProcesses xpProcesses = (XPDLProcesses) xpProcess.getOwnerCollection();
		XPDLPackage xpPackage = (XPDLPackage) xpProcesses.getParentComponent();

		definedApplications = (XPDLApplications) xpPackage.get("Applications");

		refAppChoices = new XPDLComplexChoice(this, "Application", null, 0)
		{
			public JavaPanel getJavaPanel()
			{
				if (definedApplications != null)
				{
					choices = definedApplications.getComboxComponents().toArray();
				}
				else
				{
					choices = null;
				}
				return new JavaComboxButtonPanel(this, definedApplications);
			}
		};
		refAppChoices.initComponent();
		refAppChoices.setRequired(true);
//-------------------------------------------------------------------
		refActualParameters = new XPDLActualParameters(this); // min=0
		refActualParameters.initComponent();
	}

	public void structComponent()
	{
		//	-----------------------------------------------
		super.structComponent();
		//	-----------------------------------------------
		refAppChoices.structComponent();
		refActualParameters.structComponent();
		refDescription.structComponent();
		refExtendedAttributes.structComponent();

		complexChildren.add(refAppChoices);
		complexChildren.add(refActualParameters);
		complexChildren.add(refDescription);
		complexChildren.add(refExtendedAttributes);

	}

	/**
	* 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();
		//	-----------------------------------------------
		refAppChoices.loadComponent();
		refActualParameters.loadComponent();
		refDescription.loadComponent();
		refExtendedAttributes.loadComponent();

		WorkflowComponent workflow_component = getWorkflowComponent();

		if (workflow_component == null || !(workflow_component instanceof ToolImplementation))
		{
			return;
		}
		ToolImplementation toolImpl = (ToolImplementation) workflow_component;

		if (toolImpl != null)
		{
			attrId.setValue(toolImpl.getApplicationID());
			XPDLApplication xpApp = (XPDLApplication) definedApplications.getXPDLApplication(toolImpl.getApplicationID());
			refAppChoices.setValue(xpApp);
		}
	}

	public void saveComponent()
	{
    if(isReadOnly())
    {
      return;
    }
    
		//	-----------------------------------------------
		super.saveComponent();
		//	-----------------------------------------------		
		refAppChoices.saveComponent();
		refActualParameters.saveComponent();
		refDescription.saveComponent();
		refExtendedAttributes.saveComponent();

		XPDLApplication xpApp = (XPDLApplication) refAppChoices.getChoosen();
		if (xpApp != null)
		{
			attrId.setValue(xpApp.getUUID());
		}

	}

	public void saveComponent(WorkflowComponent workflow_component)
	{
		//	-----------------------------------------------
		super.saveComponent(workflow_component);
		//	-----------------------------------------------
		refAppChoices.saveComponent();
		refActualParameters.saveComponent(workflow_component);
		refDescription.saveComponent(workflow_component);
		refExtendedAttributes.saveComponent(workflow_component);

		XPDLApplication xpApp = (XPDLApplication) refAppChoices.getChoosen();
		if (xpApp != null)
		{
			attrId.setValue(xpApp.getUUID());
		}

		if (workflow_component != null && (workflow_component instanceof ToolImplementation))
		{
			ToolImplementation simple_component = (ToolImplementation) workflow_component;
			simple_component.setApplicationID(attrId.toString());
		}

	}
	//==================================================================
}
