/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	ML 3/22/2005 UPDATING_XFUN_FROM_OPERATION									*
 *	ML 7/12/2006 REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING					*
 *	ML 7/19/2006 REMEMBERING_SETTINGS_IN_XFOPERATION_FOR_AUTO_UPDATE			*
 *	ML 12/7/2006 ADDING_INPUT_TABLE_FROM_WITHIN_XF								*
 *	ML 1/5/2007 TRANSLATING_ESCAPED_INPUT_DATA_STRINGS_XF_FOR_RESULTS_LOG		*
 *	ML 5/18/2007 XFUNCTION_CLASS_NEW_ARRANGEMENT								*
 *	CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE				*
 *	ML 9/4/2007 QA70-10332 OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS				*
 *	YuI 10/02/07 QA70-10468 CHANGE_PARAM_CANCEL_MESSES_UP_THE_DATA_MARKERS		*
 *	TD 10-05-2007 QA80-10479  OPERATION_FAILS_WHEN_XFN_MISSING_WITH_ABSTARCT_ERROR_MSG*
 *	YuI 10/10/2007 QA70-10512 CHANGE_PARAM_UNPROTECTS_OUTPUT					*
 *	CPY 11/24/07 QA70-10716 YURI_GUI_LOCALIZATION_ON_CHANGE_PARAM_CHANGE_BROKE_XF
 *	ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
 *	ML 11/12/2008 QA70-12452 MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
 *	Hong 12/25/08 QA80-12798 v8.0990e XF_CHANGE_PARAM_SHOULD_NO_SHOW_ANY_THEME_NAME_IN_THEME_COMBO
 *	ML 3/27/2009 QA70-13359 MUST_COPY_InputRangeAdditionalDataNode_FOR_XF_ON_CHANGE_PARAMS
 *	Sophy 4/1/2009 QA80-12574-S1 DISABLE_REGENERATE_REPORT_GRAPHS_IF_TOOLS_ARE_NOT_APPLICABLE
 *	Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY	*
 *	Folger 04/15/09 QA80-13453 OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
 *	Folger 07/23/09 QA80-13420-P2 XF_BASED_PLOTTING_NEEDS_GETN_TREE_AND_AUTO_UPDATE_SUPPORT
 *	Folger 07/29/09 QA80-14035 SHOW_ERROR_WHEN_CHANGE_PARAM_OF_NONE_AUTO_GETN_DIALOG_XF
 *	Folger 09/08/09 QA80-13420 XF_BASED_PLOTTING_NEEDS_GET_OUTPUT_GRAPHLAYER_IN_EVENT1
 *	Folger 10/16/09 QA81-14489-P2 OPTIONAL_VECTOR_OUTPUT_BECAME_WRONG_IN_CHANGE_PARAM
 *	Folger 03/01/10 QA81-15106-P3 OP_CHANGE_SUPPORT_CHANGE_INPUT_DATA			*
 *	Folger 04/19/10 QA81-15286 RECALCULATE_FROM_OLD_PROJECT_FAILED_TO_UPDATE_HIERARCHICAL_REPORT_CORRECTLY
 *	Folger 08/05/10 ORG-702-P1 CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
 *	Folger 08/27/2010 ORG-905-P1 OP_CHANGE_SHOULD_UPDATE_RANGES_IN_XF_GETN_TREE	*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.
#include "XFunctionEx.h"
#include <Operation.h>
#include "wksOperation.h" //---- CPY 10/14/06 SEPARATE_OUT_OPERATION_BASE_INTO_SEPARATE_HEADER

//------- CPY 10/15/07 XYZ_GRIDDING_COMPILE_FAILED_ON_START_FIRST_RUN
#ifdef _FOR_SMART_LOADING_ONLY 
#include <event_utils.h> // anytime wksOperation.h is included, event_utils is needed
#endif
//------- end XYZ_GRIDDING_COMPILE_FAILED_ON_START_FIRST_RUN

#include <xfutils.h>/// YuI 08/18/06 RANGE_TO_TREE_UPDATE_FOR_OPERATIONS

#include <okocUtils.h> /// TD 10-05-2007 QA80-10479  OPERATION_FAILS_WHEN_XFN_MISSING_WITH_ABSTARCT_ERROR_MSG

class OC_REGISTERED XFOperation	:	public	WksReportOperation
{
public:
	XFOperation();
	~XFOperation();

public:
	/// YuI 04/11/05 XFOPERATION_CHANGE_PARAM
	virtual	bool ShowDlg(TreeNode& trOperation, BOOL bChangeParams);	
	/// end XFOPERATION_CHANGE_PARAM
	
	///Sophy 4/1/2009 QA80-12574-S1 DISABLE_REGENERATE_REPORT_GRAPHS_IF_TOOLS_ARE_NOT_APPLICABLE
	//virtual
	bool	IsReplotGraphsSupported();
	///end DISABLE_REGENERATE_REPORT_GRAPHS_IF_TOOLS_ARE_NOT_APPLICABLE

	///------ Folger 04/15/09 QA80-13453 OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
	void	CheckUpdateOutputs(const Array<DataRange&>& arrOutputs, bool bCheckUpdateOutputNumber = false, XFunction* pXF = NULL);
	///------ End OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
	
	///------ Folger 03/01/10 QA81-15106-P3 OP_CHANGE_SUPPORT_CHANGE_INPUT_DATA
	virtual	void	SetTree(TreeNode& trOperation);
	///------ End OP_CHANGE_SUPPORT_CHANGE_INPUT_DATA

	///------ Folger 08/27/2010 ORG-905-P1 OP_CHANGE_SHOULD_UPDATE_RANGES_IN_XF_GETN_TREE
	virtual	BOOL	OperationtoGUI(TreeNode& trOperation, bool bInit, string* pstrSelectedTheme = NULL, bool bSetDefaultInputOnInit = true, DWORD dwExeCtrl = 0, DWORD dwParam = 0);
	///------ End OP_CHANGE_SHOULD_UPDATE_RANGES_IN_XF_GETN_TREE
	
protected:
	/// YuI 07/26/06 XFOPERATION_CHANGE_PARAM_PROBLEM
	/*
	/// YuI 04/11/05 XFOPERATION_CHANGE_PARAM
	virtual BOOL	OperationtoGUI(TreeNode& trOperation, bool bInit, string* pstrSelectedTheme = NULL, bool bSetDefaultInputOnInit = true);
	/// end XFOPERATION_CHANGE_PARAM
	virtual BOOL 	Construct(TreeNode& trOperation, int nOption = 0);

	/// YuI 08/09/05 XFUNCTION_OPERATION_CHANGE_PARAM_BUG
	/// ML 7/12/2006 REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	//BOOL			GetXFunction(TreeNode& trOp, XFunction& xf, BOOL bGUI = FALSE);
	BOOL			GetXFunction(TreeNode& trOp, XFunction& xf, BOOL bGUI = FALSE, vector<uint> *pvMapIdsToUIDs = NULL);
	/// end REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	BOOL 			GUItoOperation(TreeNode& trOperation, int nFrom);
	/// end XFUNCTION_OPERATION_CHANGE_PARAM_BUG
	*/
	
	/// YuI 11/15/06 NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
	//	BOOL			GetXFunction(TreeNode& trOp, XFunction& xf, BOOL bGUI = FALSE, vector<uint> *pvMapIdsToUIDs = NULL);
	//---- CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE
	//BOOL			GetXFunction(TreeNode& trOp, XFunction& xf, BOOL bGUI = FALSE, vector<uint> *pvMapIdsToUIDs = NULL, BOOL bUpdateFromRanges = TRUE, DWORD* pdwCntrl = NULL);
	BOOL			GetXFunction(TreeNode& trOp, XFunction& xf, DWORD dwXFcntrl, vector<uint> *pvMapIdsToUIDs = NULL, BOOL bUpdateFromRanges = TRUE, DWORD* pdwCntrl = NULL);
	//----
	/// end NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
	/// ML 9/4/2007 QA70-10332 OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
	//virtual BOOL	ChangeParam();
	virtual int		ChangeParam();
	/// end OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
	/// end XFOPERATION_CHANGE_PARAM_PROBLEM
	///------- CPY 11/24/07 QA70-10716 YURI_GUI_LOCALIZATION_ON_CHANGE_PARAM_CHANGE_BROKE_XF
	//	/// ML 3/1/2007 QA70-9421 UPDATE_TRGUI_TO_CURRENT_BEFORE_RUNNING
	//	virtual	bool	updateTreeBeforeRunning(TreeNode &trOp = NULL);  
	//	/// end UPDATE_TRGUI_TO_CURRENT_BEFORE_RUNNING
	//virtual
	bool updateTreeBeforeRunning(TreeNode &trOp = NULL, BOOL bLocalize = FALSE);

	//------- end YURI_GUI_LOCALIZATION_ON_CHANGE_PARAM_CHANGE_BROKE_XF
	/// YuI 08/18/06 RANGE_TO_TREE_UPDATE_FOR_OPERATIONS
	BOOL			UpdateTreeFromRanges(TreeNode& tr);
	void			GetOutputs(vector<int>& vOutputUIDs);
	/// end RANGE_TO_TREE_UPDATE_FOR_OPERATIONS
private:	
	virtual BOOL	executeWithRange(int nExeMode = OEXEM_ON_CREATE, DWORD dwExecCntrl = 0);
	/// ML 3/6/2006 AUTOUPDATE_MORE_WORK
	BOOL			UpdateRanges(TreeNode& trOp, XFunction& xf);
	/// end AUTOUPDATE_MORE_WORK
	
};

////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.


XFOperation::XFOperation()
{
}

XFOperation::~XFOperation()
{
}

///Sophy 4/1/2009 QA80-12574-S1 DISABLE_REGENERATE_REPORT_GRAPHS_IF_TOOLS_ARE_NOT_APPLICABLE
//virtual
bool	XFOperation::IsReplotGraphsSupported()
{
	Tree trOperation;
	GetTree(trOperation);
	TreeNode trXFname = trOperation.GetNode(STR_OP_XF_EXTERNAL_NODE);
	if ( trXFname )
	{
		vector<string> vsXFNames =	//xf names of those don't support regenerating report graphs
		{
			"sign2", "signrank1", "signrank2", "kstest2", "mwtest", "kwanova",
			"mediantest", "friedman", "NPHKSamples", "NPHPairSample", "NPHTwoSample",
			"corrcoef", "weibullfit"
		};
		string strXFname = trXFname.strVal;
		if ( vsXFNames.Find(strXFname) >= 0 )
			return false;
	}
	return WksReportOperation::IsReplotGraphsSupported();
}
///end DISABLE_REGENERATE_REPORT_GRAPHS_IF_TOOLS_ARE_NOT_APPLICABLE


/// ML 3/6/2006 AUTOUPDATE_MORE_WORK
void	XFOperation::GetOutputs(vector<int>& vOutputUIDs)
{
	/*
	DataRange dr;
	int nIndex = 0;
	while( GetOutput(dr, nIndex) )
	{
		nIndex++;
		vOutputUIDs.Add(dr.GetUID());
	}
	*/
	int nOutputCount = GetOutputCount();
	for( int ii = 0; ii < nOutputCount; ii++ )
	{
		DataRange dr;
		if( GetOutput(dr, ii) )
			vOutputUIDs.Add(dr.GetUID());
		else
			vOutputUIDs.Add(0);
	}
}

BOOL	XFOperation::UpdateRanges(TreeNode& trOp, XFunction& xf)
{
	/*
	DataRange drInput;
	GetInput(drInput);

	/// YuI 11/09/05 QA70-8279 REPORT_TREE_AND_REPORT_DATA_XVARIABLES
	//	DataRange drOutput;
	//	GetOutput(drOutput);
	//	xf.UpdateFromOperationRanges(&drInput, &drOutput);
	Array<DataRange&> arrOutputs;
	arrOutputs.SetAsOwner(TRUE);
	
	DataRange* pDr = new DataRange;
	int nIndex = 0;
	while( GetOutput(*pDr, nIndex) )
	{
		arrOutputs.Add(*pDr);
		pDr = new DataRange;
		nIndex++;
	}
	delete pDr;
	
	xf.UpdateFromOperationRanges(&drInput, &arrOutputs);
	*/
	vector<int> vOutputUIDs;
	GetOutputs(vOutputUIDs);
	xf.UpdateOutputUIDs(vOutputUIDs);
	SetTree(trOp);
	
	return TRUE;
}
/// end AUTOUPDATE_MORE_WORK
///------- CPY 11/24/07 QA70-10716 YURI_GUI_LOCALIZATION_ON_CHANGE_PARAM_CHANGE_BROKE_XF
/// ML 3/1/2007 QA70-9421 UPDATE_TRGUI_TO_CURRENT_BEFORE_RUNNING
//bool	XFOperation::updateTreeBeforeRunning(TreeNode &trOp)
bool	XFOperation::updateTreeBeforeRunning(TreeNode &trOp, BOOL bLocalize)
///-------
{
	return true;
}
/// end UPDATE_TRGUI_TO_CURRENT_BEFORE_RUNNING

/// YuI 08/18/06 RANGE_TO_TREE_UPDATE_FOR_OPERATIONS
BOOL	XFOperation::UpdateTreeFromRanges(TreeNode& tr)
{
	vector<int> vOutputUIDs;
	GetOutputs(vOutputUIDs);
	DataRange drInput;
	int nInputUID = 0;
	
	GetInput(drInput);
	if( drInput )
		nInputUID = drInput.GetUID();
	
	if( nInputUID > 0 )
		return okxf_update_tree_from_ranges(&tr, nInputUID, &vOutputUIDs);
		
	return FALSE;
}
/// end RANGE_TO_TREE_UPDATE_FOR_OPERATIONS

/// YuI 08/09/05 XFUNCTION_OPERATION_CHANGE_PARAM_BUG
/// ML 7/12/2006 REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
//BOOL	XFOperation::GetXFunction(TreeNode& trOp, XFunction& xf, BOOL bGUI)
/// YuI 11/15/06 NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
//	BOOL	XFOperation::GetXFunction(TreeNode& trOp, XFunction& xf, BOOL bGUI, vector<uint> *pvMapIdsToUIDs)
//----- CPY 2/20/2007 QA70-9335 XF_RESULTS_LOG_DUMP_GLOBAL_CONTROL_AND_XF_CONTROL, added dwCntrl
//------ CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE
//BOOL	XFOperation::GetXFunction(TreeNode& trOp, XFunction& xf, BOOL bGUI, vector<uint> *pvMapIdsToUIDs, BOOL bUpdateFromRanges, DWORD* pdwCntrl)
/// end NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
/// end REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
BOOL	XFOperation::GetXFunction(TreeNode& trOp, XFunction& xf, DWORD dwXFcntrl, vector<uint> *pvMapIdsToUIDs, BOOL bUpdateFromRanges, DWORD* pdwCntrl)
{
	TreeNode trXFname = trOp.GetNode(STR_OP_XF_EXTERNAL_NODE);
	TreeNode trXF;
	if(trXFname)
	{
		TreeNode trXFexternal;
		string strName = trXFname.strVal;
		string strOxfPath;
		//int nLocation = okutil_find_file_from_composite_name(&strOxfPath, strName, SUPPORTFILE_XF, ORIGIN_PATH_SYSTEM);
		int nLocation = okutil_find_file_from_composite_name(&strOxfPath, strName, SUPPORTFILE_XF, ORIGIN_PATH_UNDEF);
		if(ORIGIN_PATH_UNDEF  != nLocation)
		{
			/// ML 7/19/2006 REMEMBERING_SETTINGS_IN_XFOPERATION_FOR_AUTO_UPDATE
			///// ML 3/6/2006 AUTOUPDATE_MORE_WORK
			////if(xf.Load(&trXFexternal, strOxfPath, LTXF_BY_FILENAME))
			////	trXF = trXFexternal;
			//if(xf.Load(&trXFexternal, strOxfPath, LTXF_BY_FILENAME, true, false, true))
			//	trXF = trXFexternal;
			///// end AUTOUPDATE_MORE_WORK
			TreeNode trOpGetN = trOp.GetNode(STR_OP_XF_GETN_NODE);
			///------ Folger 07/23/09 QA80-13420-P2 XF_BASED_PLOTTING_NEEDS_GETN_TREE_AND_AUTO_UPDATE_SUPPORT
			#ifdef		__XF_BASED_PLOTTING_MECHANISM__
			okutil_last_evaluated_getn_access(&trOpGetN, FALSE);
			#endif		/// __XF_BASED_PLOTTING_MECHANISM__
			///------ End XF_BASED_PLOTTING_NEEDS_GETN_TREE_AND_AUTO_UPDATE_SUPPORT
			/// Hong 12/25/08 QA80-12798 v8.0990e XF_CHANGE_PARAM_SHOULD_NO_SHOW_ANY_THEME_NAME_IN_THEME_COMBO
			if ( (LTXF_CHANGE_PARAM | LTXF_SHOW_DIALOG) & dwXFcntrl )
				trOpGetN.RemoveAttribute(STR_THEME_FILE_ATTRIB);
			/// end XF_CHANGE_PARAM_SHOULD_NO_SHOW_ANY_THEME_NAME_IN_THEME_COMBO
			/// YuI 08/18/06 RANGE_TO_TREE_UPDATE_FOR_OPERATIONS
			/// YuI 11/15/06 NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
			//	UpdateTreeFromRanges(trOpGetN);
			if( bUpdateFromRanges )
				UpdateTreeFromRanges(trOpGetN);
			/// end NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
			/// end RANGE_TO_TREE_UPDATE_FOR_OPERATIONS
			
			///------ Folger 09/08/09 QA80-13420 XF_BASED_PLOTTING_NEEDS_GET_OUTPUT_GRAPHLAYER_IN_EVENT1
			#ifdef		__XF_BASED_PLOTTING_MECHANISM__
			string		strXFName;
			trOpGetN.GetAttribute(STR_XFUNCTION_NAME_ATTRIB, strXFName);
			if ( _is_xf_based_plotting_xfunction(strXFName) )
			{
				DataRange	dr;
				if ( _get_xf_based_plotting_output_range(dr, *this) )
				{
					GraphLayer	gl;
					if ( _get_xf_based_plotting_output_graph(gl, dr, strXFName) )
					{
						trOpGetN.AutoUpdate.SetAttribute(STR_XF_BASED_PLOTTING_GRAPH_UID_ATTRIB, gl.GetUID(TRUE));
					}
				}
			}
			#endif		/// __XF_BASED_PLOTTING_MECHANISM__
			///------ End XF_BASED_PLOTTING_NEEDS_GET_OUTPUT_GRAPHLAYER_IN_EVENT1
			
			//------ CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE
			//if(xf.Load(&trXFexternal, strOxfPath, LTXF_BY_FILENAME, true, false, true, trOpGetN))
			if(xf.Load(&trXFexternal, strOxfPath, dwXFcntrl | LTXF_BY_FILENAME, true, false, true, trOpGetN))
			//-----
				trXF = trXFexternal;
			/// end REMEMBERING_SETTINGS_IN_XFOPERATION_FOR_AUTO_UPDATE
			/// ML 7/12/2006 REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
			if ( pvMapIdsToUIDs )
				GetIdsToUIDsMap(*pvMapIdsToUIDs);
			/// end REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
		}
		/// TD 10-05-2007 QA80-10479  OPERATION_FAILS_WHEN_XFN_MISSING_WITH_ABSTARCT_ERROR_MSG
		else
		{
			string strError;
			ocu_load_msg_str(IDSXF_OPER_NOT_FOUND, &strError, strName);
			okoc_out_msg(strError, 'E', false);
		}
		/// end OPERATION_FAILS_WHEN_XFN_MISSING_WITH_ABSTARCT_ERROR_MSG
		if(!trXF)
			return error_report("XFOperation::GetXFunction error with external XF file");		
		/// ML 3/6/2006 AUTOUPDATE_MORE_WORK
		UpdateRanges(trOp, xf);
		/// end AUTOUPDATE_MORE_WORK
	}
	else 
	{
		//------ CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE
		//trXF = bGUI ? trOp.GUI : trOp.xf;
		trXF = (dwXFcntrl & LTXF_CHANGE_PARAM) ? trOp.GUI : trOp.xf;
		//-----
		if(!trXF)
			return error_report("XFOperation::GetXFunction found no XF tree");	
		/// Hong 12/25/08 QA80-12798 v8.0990e XF_CHANGE_PARAM_SHOULD_NO_SHOW_ANY_THEME_NAME_IN_THEME_COMBO
		if ( (LTXF_CHANGE_PARAM | LTXF_SHOW_DIALOG) & dwXFcntrl )
			trXF.RemoveAttribute(STR_THEME_FILE_ATTRIB);
		/// end XF_CHANGE_PARAM_SHOULD_NO_SHOW_ANY_THEME_NAME_IN_THEME_COMBO
		if(!xf.Create(trXF, TRUE, TRUE, TRUE))
			return error_report("XFOperation::GetXFunction error Create XF tree");
		
		/// ML 3/6/2006 AUTOUPDATE_MORE_WORK
		/*
		DataRange drInput;
		GetInput(drInput);

		/// YuI 11/09/05 QA70-8279 REPORT_TREE_AND_REPORT_DATA_XVARIABLES
		//	DataRange drOutput;
		//	GetOutput(drOutput);
		//	xf.UpdateFromOperationRanges(&drInput, &drOutput);
		Array<DataRange&> arrOutputs;
		arrOutputs.SetAsOwner(TRUE);
		
		DataRange* pDr = new DataRange;
		int nIndex = 0;
		while( GetOutput(*pDr, nIndex) )
		{
			arrOutputs.Add(*pDr);
			pDr = new DataRange;
			nIndex++;
		}
		delete pDr;
		
		xf.UpdateFromOperationRanges(&drInput, &arrOutputs);
		/// end REPORT_TREE_AND_REPORT_DATA_XVARIABLES
		
		SetTree(trOp);
		*/
		
		UpdateRanges(trOp, xf);		
		/// end AUTOUPDATE_MORE_WORK
	}
	//----- CPY 1/27/2007 QA70-9335 XF_RESULTS_LOG_OUTPUT_OPTIONS
	if(pdwCntrl)
		xf_update_results_cmd_log_output_options(trXF, *pdwCntrl);
	//-----
	return true;
}
/// end XFUNCTION_OPERATION_CHANGE_PARAM_BUG

/// YuI 02/13/07 ON_BEFORE_AFTER_EXECUTE_CLEANUP
/// YuI 11/12/08 ADDITIONAL_CLEANUP_FOR_EXECUTE_ON_CHANGE_PARAM
/*
class	OnBeforeAfterExecuteHelper
{
public:
	OnBeforeAfterExecuteHelper(OperationBase& op)
	{
		m_op = op;
		op.OnBeforeExecute();
	}
	
	~OnBeforeAfterExecuteHelper()
	{
		if( m_op )
			m_op.OnAfterExecute();			
	}
private:
	OperationBase m_op;
};
*/
/// end ADDITIONAL_CLEANUP_FOR_EXECUTE_ON_CHANGE_PARAM
/// end YuI

/// ML 11/12/2008 QA70-12452 MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
static	void	_copy_InputRangeAdditionalDataNode_from_xf_to_op(TreeNode &trOp, XFunction &xf)
{
	TreeNode		trNodeADInOp = trOp.GetNode(TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME);
	if ( trNodeADInOp.IsValid() )
	{
		TreeNode	trNodeADInXF;
		if ( xf.GetInputRangeAdditionalDataNode(trNodeADInXF) )
			trNodeADInOp.Replace(trNodeADInXF, TRUE, TRUE);
	}
}
/// end MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM

///------ Folger 04/15/09 QA80-13453 OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
void	XFOperation::CheckUpdateOutputs(const Array<DataRange&>& arrOutputs, bool bCheckUpdateOutputNumber/* = false*/, XFunction* pXF/* = NULL*/)
{
	int nOldOutputCount = 0;
	DataRange drOldOutput;
	int nNewOutputCount = arrOutputs.GetSize();
	while( GetOutput(drOldOutput, nOldOutputCount) )
	{
		if( nOldOutputCount < nNewOutputCount )
		{
			DataRange& drNewOutput = arrOutputs.GetAt(nOldOutputCount);
			if( NULL != drNewOutput && drNewOutput.IsValid() )
			{
				/// YuI 09/18/07 QA70-10331 REPORT_DATA_POLYRANGES_ARE_SCREWED_UP_AFTER_CHANGE_PARAM
				okutil_on_change_operation_output_range(&drOldOutput, &drNewOutput);
				/// end REPORT_DATA_POLYRANGES_ARE_SCREWED_UP_AFTER_CHANGE_PARAM
				
				/// YuI 10/10/2007 QA70-10512 CHANGE_PARAM_UNPROTECTS_OUTPUT
				//	drNewOutput.Clone(drOldOutput);
				
				// if we do not preserve output data will become unprotected
				drNewOutput.Clone(drOldOutput, TRUE);
				/// end CHANGE_PARAM_UNPROTECTS_OUTPUT
			}
		}
		nOldOutputCount++;
	}
	
	if ( bCheckUpdateOutputNumber )
	{
		if ( !pXF )
		{
			ASSERT(false);
			return;
		}
		
		// after loop nOutputIndex contains total number of outputs of operation
		// we need to get rid of some outputs (non-optional becoming optional)
		for( int ii = nOldOutputCount; ii > nNewOutputCount; ii-- )
		{
			DataRange drTemp;
			if( GetOutput(drTemp, ii - 1) )
				RemoveOutput(drTemp);
		}
		
		// we need to add some outputs (<optional> becoming non-optional situation)
		for( ii = nOldOutputCount; ii < nNewOutputCount; ii++ )
		{
			SetOutput(arrOutputs.GetAt(ii));
		}
		
		Tree	trOp;
		GetTree(trOp);
		UpdateRanges(trOp, *pXF);
	}
}

class	XFOperationUpdateHelper
{
public:
	XFOperationUpdateHelper(XFOperation* pOpXF, XFunction* pXF, Array<DataRange&>& arrOutputs)
	{
		m_pOpXF = NULL;
		m_parrOutputs = NULL;
		
		if ( !pXF )
			return;
		
		TreeNode	trXFVer = pXF->GetTree().version;
		TreeNode	trOpGetN = checkGetOpGetN(pOpXF);
		if ( !trXFVer || !trOpGetN )
			return;
		
		double	rXFVerInOp = 1;		/// assume default is 1
		trOpGetN.GetAttribute(STR_XF_VERSION, rXFVerInOp);
		if ( rXFVerInOp != trXFVer.dVal )
		{
			m_pOpXF = pOpXF;
			m_pXF = pXF;
			m_parrOutputs = &arrOutputs;
		}
	}
	~XFOperationUpdateHelper()
	{
		if ( m_pOpXF )
		{
			m_pOpXF->CheckUpdateOutputs(*m_parrOutputs, true, m_pXF);
			
			TreeNode	trXFVer = m_pXF->GetTree().version;
			Tree		trOp;
			TreeNode	trOpGetN = checkGetOpGetN(m_pOpXF, &trOp);
			if ( trXFVer && trOpGetN )
			{
				trOpGetN.SetAttribute(STR_XF_VERSION, trXFVer.dVal);
				m_pOpXF->SetTree(trOp);
			}
		}
	}
	
	bool	IsRangesNeedsUpdate()
	{
		return NULL != m_pOpXF;
	}
	
private:
	
	TreeNode	checkGetOpGetN(Operation* op, TreeNode* ptrOp = NULL)
	{
		TreeNode	trOp;
		Tree		trOpTemp;
				
		if ( ptrOp )
		{
			op->GetTree(*ptrOp);
			trOp = *ptrOp;
		}
		else
		{
			op->GetTree(trOpTemp);
			trOp = trOpTemp;
		}
		
		return tree_check_get_node(trOp, STR_OP_XF_GETN_NODE);		
	}
	
private:
	
	XFOperation*		m_pOpXF;
	XFunction*			m_pXF;
	Array<DataRange&>*	m_parrOutputs;
};
///------ End OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE

///------ Folger 07/23/09 QA80-13420-P2 XF_BASED_PLOTTING_NEEDS_GETN_TREE_AND_AUTO_UPDATE_SUPPORT
#ifdef		__XF_BASED_PLOTTING_MECHANISM__
static		BOOL	_is_same_type_xf_based_plotting_graph(GraphPage& gp, LPCSTR	lpcszXF)
{
	string	str = gp.Info.SYSTEM.PLOTTING.XFUNCTION$;
	return	0 == str.Find(lpcszXF);
}

///------ Folger 07/23/09 09/08/09 XF_BASED_PLOTTING_NEEDS_GET_OUTPUT_GRAPHLAYER_IN_EVENT1
static		BOOL		_is_xf_based_plotting_xfunction(LPCSTR lpcszName)
{
	string	str = lpcszName;
	return 0 == str.Find("plot_");
}

static		BOOL		_get_xf_based_plotting_output_range(DataRange& dr, XFOperation& op)
{
	int			nOutputCount = op.GetOutputCount();
	for ( int ii=0; ii<nOutputCount; ++ii )
	{
		op.GetOutput(dr, ii);
		if ( dr && dr.GetNumRanges() > 0 )
			break;
	}
	
	if ( !dr || 0 == dr.GetNumRanges() )
	{
		ASSERT(FALSE);
		return FALSE;
	}
	
	return TRUE;
}

static		BOOL		_get_xf_based_plotting_output_graph(GraphLayer& glXFPlot, DataRange& dr, LPCSTR lpcszXFName)
{
	foreach ( PageBase pg in Project.Pages )
	{
		GraphPage	gp(pg);
		if ( !gp || !_is_same_type_xf_based_plotting_graph(gp, lpcszXFName) )
			continue;
		
		foreach ( GraphLayer gl in gp.Layers )
		{
			foreach ( DataPlot dp in gl.DataPlots )
			{
				DataRange	drPlot;
				dp.GetDataRange(drPlot);
				if ( drPlot.Intersects(dr) )
				{
					glXFPlot = gl;
					break;
				}
			}
			
			if ( glXFPlot )
				break;
		}
		
		if ( glXFPlot )
			break;
	}

	return glXFPlot.IsValid();
}
///------ End XF_BASED_PLOTTING_NEEDS_GET_OUTPUT_GRAPHLAYER_IN_EVENT1

typedef BOOL	(*PLOTTING_FUNC)(GraphLayer& gl, DataRange& dr, TreeNode& trGetN, BOOL bFromUpdateUpdate);
class	XFBasedPlottingAutoUpdateHelper
{
public:
	XFBasedPlottingAutoUpdateHelper(XFOperation* pOp)
	{
		m_pOp = pOp;
	}
	
	~XFBasedPlottingAutoUpdateHelper()
	{
		Tree	trOp;
		m_pOp->GetTree(trOp);
		TreeNode	trXFname = trOp.GetNode(STR_OP_XF_EXTERNAL_NODE);
		if ( !trXFname )
			return;

		string		strFunc;
		strFunc.Format(XF_BASED_OC_PLOTTING_FUNCTION_FORMAT, trXFname.strVal);
		PLOTTING_FUNC	pfn = Project.FindCompiledFunction(strFunc)	;
		if ( pfn )
		{
			///------ Folger 09/08/09 QA80-13420 XF_BASED_PLOTTING_NEEDS_GET_OUTPUT_GRAPHLAYER_IN_EVENT1
			//DataRange	dr;
			//int			nOutputCount = m_pOp->GetOutputCount();
			//for ( int ii=0; ii<nOutputCount; ++ii )
			//{
				//m_pOp->GetOutput(dr, ii);
				//if ( dr && dr.GetNumRanges() > 0 )
					//break;
			//}
			//
			//if ( !dr || 0 == dr.GetNumRanges() )
			//{
				//ASSERT(FALSE);
				//return;
			//}
			//
			//GraphLayer		glXFPlot;
			//foreach ( PageBase pg in Project.Pages )
			//{
				//GraphPage	gp(pg);
				//if ( !gp || !_is_same_type_xf_based_plotting_graph(gp, trXFname.strVal) )
					//continue;
				//
				//foreach ( GraphLayer gl in gp.Layers )
				//{
					//foreach ( DataPlot dp in gl.DataPlots )
					//{
						//DataRange	drPlot;
						//dp.GetDataRange(drPlot);
						//if ( drPlot.Intersects(dr) )
						//{
							//glXFPlot = gl;
							//break;
						//}
					//}
					//
					//if ( glXFPlot )
						//break;
				//}
				//
				//if ( glXFPlot )
					//break;
			//}
			//if ( glXFPlot )
			DataRange		dr;
			if ( _get_xf_based_plotting_output_range(dr, *m_pOp) )
			{
				TreeNode		trGetN;
				/// trGetN can be got from m_pOp, here just use okutil_last_evaluated_getn_access to make consistent with the one called in VC (ok_xf_based_plotting_from_wks).
				okutil_last_evaluated_getn_access(&trGetN);
				int				nUID = 0;
				trGetN.AutoUpdate.GetAttribute(STR_XF_BASED_PLOTTING_GRAPH_UID_ATTRIB, nUID);
				GraphLayer		glXFPlot;
				if ( !(glXFPlot = (GraphLayer)Project.GetObject(nUID)) && !_get_xf_based_plotting_output_graph(glXFPlot, dr, trXFname.strVal) )
				{
					ASSERT(FALSE);
					return;
				}
				pfn(glXFPlot, dr, trGetN, TRUE);
			}
			///------ End XF_BASED_PLOTTING_NEEDS_GET_OUTPUT_GRAPHLAYER_IN_EVENT1
		}
	}
	
private:
	XFOperation* 	m_pOp;
};
#endif		/// __XF_BASED_PLOTTING_MECHANISM__
///------ End XF_BASED_PLOTTING_NEEDS_GETN_TREE_AND_AUTO_UPDATE_SUPPORT

BOOL	XFOperation::executeWithRange(int nExeMode, DWORD dwExecCntrl)
{
	/// YuI 08/09/05 XFUNCTION_OPERATION_CHANGE_PARAM_BUG
	/*
	TreeNode trOp;
	GetTree(trOp);
	TreeNode trXFname = trOp.GetNode(STR_OP_XF_EXTERNAL_NODE);
	TreeNode trXF;
	Tree trXFexternal;
	XFunction xf;
	if(trXFname)
	{
		string strName = trXFname.strVal;
		string strOxfPath;
		int nLocation = okutil_find_file_from_composite_name(&strOxfPath, strName, SUPPORTFILE_XF);
		if(ORIGIN_PATH_UNDEF  != nLocation)
		{
			if(xf.Load(trXFexternal, strOxfPath))
				trXF = trXFexternal;
		}
		if(!trXF)
			return error_report("XFOperation::executeWithRange error with external XF file");		
	}
	else 
	{
		trXF = trOp.GetNode(STR_OP_XF_NODE);
		if(!trXF)
			return error_report("XFOperation::executeWithRange found no XF tree");
	
		if(!xf.Create(trXF, true))
			return error_report("XFOperation::executeWithRange error Create XF tree");
		
		/// ML 3/22/2005 UPDATING_XFUN_FROM_OPERATION
		DataRange		drInput, drOutput;
		GetInput(drInput);
		GetOutput(drOutput);
		xf.UpdateFromOperationRanges(&drInput, &drOutput);
		SetTree(trOp);
		/// end UPDATING_XFUN_FROM_OPERATION
	}
	
	
	return xf.Evaluate();
	*/
//#ifndef 	 _XF_LT_CALL_IN_VC //CPY 1/27/06	

	///------ Folger 07/23/09 QA80-13420-P2 XF_BASED_PLOTTING_NEEDS_GETN_TREE_AND_AUTO_UPDATE_SUPPORT
	#ifdef		__XF_BASED_PLOTTING_MECHANISM__
	XFBasedPlottingAutoUpdateHelper	plottingHelper(this);
	#endif		/// __XF_BASED_PLOTTING_MECHANISM__
	///------ End XF_BASED_PLOTTING_NEEDS_GETN_TREE_AND_AUTO_UPDATE_SUPPORT

	/// YuI 02/13/07 ON_BEFORE_AFTER_EXECUTE_CLEANUP
	/// YuI 11/12/08 ADDITIONAL_CLEANUP_FOR_EXECUTE_ON_CHANGE_PARAM
	//	OnBeforeAfterExecuteHelper clHelper(*this);
	OnBeforeAfterExecuteHelper clHelper(*this, nExeMode);
	/// end ADDITIONAL_CLEANUP_FOR_EXECUTE_ON_CHANGE_PARAM
	/// end YuI
	
	XFunction xf;
	TreeNode trOp;
	GetTree(trOp);
	/// ML 7/12/2006 REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	//if( GetXFunction(trOp, xf) )
	//	return xf.Evaluate(NULL, NULL);
	vector<uint>		vMapIdsToUIDs;
	/// YuI 11/15/06 NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
	// shuld update XFunction only in case og autoupdate running
	// in case of ChangeParam - tree already comes from dialog, should not be updated anymore.
	//	if( GetXFunction(trOp, xf, FALSE, &vMapIdsToUIDs) )
	BOOL	bUpdateXFFromRanges = ( (OEXEM_ON_AUTOUPDATE_MANUAL == nExeMode) || (OEXEM_ON_AUTOUPDATE_TASK == nExeMode) );
	DWORD dwCntrl = 0;
	if( GetXFunction(trOp, xf, LTXF_EXEC_RECALCULATE, &vMapIdsToUIDs, bUpdateXFFromRanges, &dwCntrl) )
	/// end NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
	{
		///------ Folger 04/15/09 QA80-13453 OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
		Array<DataRange&>			arrOutputs;
		XFOperationUpdateHelper		clHelper(this, &xf, arrOutputs);
		///------ End OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
		
		/// YuI 07/26/06 XFOPERATION_CHANGE_PARAM_PROBLEM
		if( OEXEM_ON_CHANGEPARAM == nExeMode )
		{
			DataRange	drInput;
			drInput.Create();
			
			/// YuI 11/15/06 NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
			//	if( xf.Evaluate(&drInput, NULL, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | LTXF_OUT_RESULTS_LOG, &vMapIdsToUIDs) )
			//Array<DataRange&> arrOutputs;		///------ Folger 04/15/09 QA80-13453 OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
			/// ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
			///// ML 12/7/2006 ADDING_INPUT_TABLE_FROM_WITHIN_XF 
			////if( xf.Evaluate(&drInput, &arrOutputs, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | LTXF_OUT_RESULTS_LOG, &vMapIdsToUIDs) )
			///// YuI 02/05/07 can't compile due to more control over results log
			////	bool		bOK = xf.Evaluate(&drInput, &arrOutputs, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | LTXF_OUT_RESULTS_LOG, &vMapIdsToUIDs);
			//bool		bOK = xf.Evaluate(&drInput, &arrOutputs, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl, &vMapIdsToUIDs);
			///// end YuI
			double		rXFVersionLastTime = 1;		// assume that 1. is the old version for the case when STR_ATT_OP_XFVER is not available, such as when
													// running an operation from before the introduction of STR_ATT_OP_XFVER.
			BOOL		bHasXFVersionLastTime = trOp.GetAttribute(STR_ATT_OP_XFVER, rXFVersionLastTime);
			///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
			//bool		bOK = xf.Evaluate(&drInput, &arrOutputs, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl, &vMapIdsToUIDs, NULL, rXFVersionLastTime);
			///------ Folger 10/16/09 QA81-14489-P2 OPTIONAL_VECTOR_OUTPUT_BECAME_WRONG_IN_CHANGE_PARAM
			//bool		bOK = xf.Evaluate(&drInput, &arrOutputs, LTXF_SHOW_DIALOG | LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl, &vMapIdsToUIDs, NULL, rXFVersionLastTime);
			TreeNode	trOpGetN = tree_check_get_node(trOp, STR_OP_XF_GETN_NODE);
			bool		bOK = xf.Evaluate(&drInput, &arrOutputs, LTXF_SHOW_DIALOG | LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl, &vMapIdsToUIDs, &trOpGetN, rXFVersionLastTime);
			///------ End OPTIONAL_VECTOR_OUTPUT_BECAME_WRONG_IN_CHANGE_PARAM
			///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
			/// end MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
			
			/// ML 11/12/2008 QA70-12452 MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
			///// ML 5/18/2007 XFUNCTION_CLASS_NEW_ARRANGEMENT
			////xf.RemoveChild(TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME);
			//xf.RemoveInputRangeAdditionalDataNode();
			///// end XFUNCTION_CLASS_NEW_ARRANGEMENT
			/// end MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
			if (bOK)
			/// end ADDING_INPUT_TABLE_FROM_WITHIN_XF
			/// end NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
			{
				/// ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
				BOOL			bCallSetTree = FALSE;
				TreeNode		trXF = xf.GetTree();
				if ( trXF.IsValid() )
				{
					double			rXFVersion = trXF.version.dVal;
					if ( !bHasXFVersionLastTime || rXFVersionLastTime != rXFVersion )
					{
						trOp.SetAttribute(STR_ATT_OP_XFVER, rXFVersion);
						bCallSetTree = TRUE;		// I feel it is safer to call SetTree after all the output ranges have been taken care of.
					}
				}
				/// end MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
				/// ML 11/12/2008 QA70-12452 MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
				/// ML 3/27/2009 QA70-13359 MUST_COPY_InputRangeAdditionalDataNode_FOR_XF_ON_CHANGE_PARAMS
				//if ( bCallSetTree )
				// The scenario described in 13359 does change InputRangeAdditionalDataNode due to the input change, so we
				// have to do this always on Change Params:
				/// end MUST_COPY_InputRangeAdditionalDataNode_FOR_XF_ON_CHANGE_PARAMS
					_copy_InputRangeAdditionalDataNode_from_xf_to_op(trOp, xf);
				xf.RemoveInputRangeAdditionalDataNode();
				/// end MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
				// need to update operation input ranges
				DataRange drOldInput;
				GetInput(drOldInput);
				/// YuI 10/10/2007 QA70-10512 CHANGE_PARAM_UNPROTECTS_OUTPUT
				//	drInput.Clone(drOldInput);
				drInput.Clone(drOldInput, TRUE);
				/// end CHANGE_PARAM_UNPROTECTS_OUTPUT
				SetIdsToUIDsMap(vMapIdsToUIDs);	// put the updated map back into the operation
				
				/// YuI 11/15/06 NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
				// need to update outputs as well
				// some outputs that were optional before may not be that optional anymore
				// and visa versa - valid before change param become optional after change param
				
				///------ Folger 04/15/09 QA80-13453 OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
				//int nOldOutputCount = 0;
				//DataRange drOldOutput;
				//int nNewOutputCount = arrOutputs.GetSize();
				//while( GetOutput(drOldOutput, nOldOutputCount) )
				//{
					//if( nOldOutputCount < nNewOutputCount )
					//{
						//DataRange& drNewOutput = arrOutputs.GetAt(nOldOutputCount);
						//if( NULL != drNewOutput && drNewOutput.IsValid() )
						//{
							///// YuI 09/18/07 QA70-10331 REPORT_DATA_POLYRANGES_ARE_SCREWED_UP_AFTER_CHANGE_PARAM
							//okutil_on_change_operation_output_range(&drOldOutput, &drNewOutput);
							///// end REPORT_DATA_POLYRANGES_ARE_SCREWED_UP_AFTER_CHANGE_PARAM
							//
							///// YuI 10/10/2007 QA70-10512 CHANGE_PARAM_UNPROTECTS_OUTPUT
							////	drNewOutput.Clone(drOldOutput);
							//
							//// if we do not preserve output data will become unprotected
							//drNewOutput.Clone(drOldOutput, TRUE);
							///// end CHANGE_PARAM_UNPROTECTS_OUTPUT
						//}
					//}
					//nOldOutputCount++;
				//}
				///*
				//// after loop nOutputIndex contains total number of outputs of operation
				//// we need to get rid of some outputs (non-optional becoming optional)
				//for( int ii = nOldOutputCount; ii > nNewOutputCount; ii-- )
				//{
					//DataRange drTemp;
					//if( GetOutput(drTemp, ii - 1) )
						//RemoveOutput(drTemp);
				//}
				//
				//// we need to add some outputs (<optional> becoming non-optional situation)
				//for( ii = nOldOutputCount; ii < nNewOutputCount; ii++ )
				//{
					//SetOutput(arrOutputs.GetAt(ii));
				//}
				//UpdateRanges(trOp, xf);
				//*/
				CheckUpdateOutputs(arrOutputs);
				///------ End OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
				/// end NEED_TO_HANDLE_THE_SITUATION_WHEN_CHANGE_PARAM_CHANGES_OUTPUTS
				/// ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
				/// ML 3/27/2009 QA70-13359 MUST_COPY_InputRangeAdditionalDataNode_FOR_XF_ON_CHANGE_PARAMS
				//if ( bCallSetTree )
				// See the comment above under the same code marking.
				/// end MUST_COPY_InputRangeAdditionalDataNode_FOR_XF_ON_CHANGE_PARAMS
					SetTree(trOp);
				/// ML 1/9/2008 QA70-10917 MAKE_XFVERSION_USED_WHEN_XFOP_WAS_RUN_LAST_TIME_AVAILABLE_TO_ORIGINC
				/// YuI 10/02/07 QA70-10468 CHANGE_PARAM_CANCEL_MESSES_UP_THE_DATA_MARKERS
				OnAfterCalculations(trOp);
				/// end CHANGE_PARAM_CANCEL_MESSES_UP_THE_DATA_MARKERS
				return TRUE;
			}
			/// ML 11/12/2008 QA70-12452 MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
			xf.RemoveInputRangeAdditionalDataNode();
			/// end MUST_TRANSFER_IRADDITIONAL_DATA_NODE_FROM_XF_TO_OP_ON_CHANGE_PARAM
			
			return error_report("XFOperation::executeWithRange failed to create XFunction");
		}
		/// end XFOPERATION_CHANGE_PARAM_PROBLEM
		
		/// ML 1/5/2007 TRANSLATING_ESCAPED_INPUT_DATA_STRINGS_XF_FOR_RESULTS_LOG
		/// ML 12/7/2006 ADDING_INPUT_TABLE_FROM_WITHIN_XF 
		//if ( xf.Evaluate(NULL, NULL, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | LTXF_OUT_RESULTS_LOG, &vMapIdsToUIDs) )
		//bool	bOK = xf.Evaluate(NULL, NULL, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | LTXF_OUT_RESULTS_LOG, &vMapIdsToUIDs);
		DataRange		rngInput;
		GetInput(rngInput);
		TreeNode		trNodeADInOp = trOp.GetNode(TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME);
		// Must temporarily copy TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME from op to xf. 
		if ( trNodeADInOp.IsValid() )
		{
			TreeNode	trNodeADInXF;
			/// ML 5/18/2007 XFUNCTION_CLASS_NEW_ARRANGEMENT
			//octree_tree_check_get_node(&trNodeADInXF, &xf, TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME);
			xf.GetInputRangeAdditionalDataNode(trNodeADInXF, TRUE);
			/// end XFUNCTION_CLASS_NEW_ARRANGEMENT
			trNodeADInXF.Replace(trNodeADInOp);
		}
		/// YuI 02/05/07 can't compile due to more control over results log
		//	bool	bOK = xf.Evaluate(&rngInput, NULL, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | LTXF_OUT_RESULTS_LOG | LTXF_NO_UPDATE_RANGES, &vMapIdsToUIDs);
		///------ Folger 04/15/09 QA80-13453 OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
		//bool	bOK = xf.Evaluate(&rngInput, NULL, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl | LTXF_NO_UPDATE_RANGES, &vMapIdsToUIDs);
		bool	bOK = false;
		if ( clHelper.IsRangesNeedsUpdate() )
		{
			///------ Folger 04/19/10 QA81-15286 RECALCULATE_FROM_OLD_PROJECT_FAILED_TO_UPDATE_HIERARCHICAL_REPORT_CORRECTLY
			//if ( (bOK = xf.Evaluate(&rngInput, &arrOutputs, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl, &vMapIdsToUIDs)) )
			DataRange	drInput;
			drInput.Create();
			///------ Folger 08/05/10 ORG-702-P1 CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
			//if ( (bOK = xf.Evaluate(&drInput, &arrOutputs, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl, &vMapIdsToUIDs)) )
			if ( (bOK = xf.Evaluate(&drInput, &arrOutputs, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl, &vMapIdsToUIDs, NULL, DEFAULT_XFVERSION_LAST_TIME_RUN, GetUID())) )
			///------ End CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
			///------ End RECALCULATE_FROM_OLD_PROJECT_FAILED_TO_UPDATE_HIERARCHICAL_REPORT_CORRECTLY
			{
				TreeNode trOpGetN = tree_check_get_node(trOp, STR_OP_XF_GETN_NODE);
				if ( trOpGetN )
				{
					Tree		trTemp;
					TreeNode	trTempGetN;
					xf.GetGUI(trTemp, trTempGetN);
					trOpGetN.Replace(trTempGetN, true, true, true);
					///------ Folger 04/19/10 QA81-15286 RECALCULATE_FROM_OLD_PROJECT_FAILED_TO_UPDATE_HIERARCHICAL_REPORT_CORRECTLY
					_copy_InputRangeAdditionalDataNode_from_xf_to_op(trOp, xf);
					///------ End RECALCULATE_FROM_OLD_PROJECT_FAILED_TO_UPDATE_HIERARCHICAL_REPORT_CORRECTLY
					SetTree(trOp);
				}
			}
		}
		else
		{
			///------ Folger 08/05/10 ORG-702-P1 CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
			//bOK = xf.Evaluate(&rngInput, NULL, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl | LTXF_NO_UPDATE_RANGES, &vMapIdsToUIDs);		/// old code
			bOK = xf.Evaluate(&rngInput, NULL, LTXF_FROM_AUTO_UPDATE | LTXF_EXECUTE | dwCntrl | LTXF_NO_UPDATE_RANGES, &vMapIdsToUIDs, NULL, DEFAULT_XFVERSION_LAST_TIME_RUN, GetUID());
			///------ End CLEAR_OUTPUT_DATA_WITHOUT_ERROR_FOR_XF_OPERATION_RECALCULATE_IF_INPUT_IS_EMPTY
		}
		///------ End OLD_PROJECT_FAILS_TO_UPDATE_OUTPUTS_DURING_AUTO_UPDATE
		/// end YuI
		/// end TRANSLATING_ESCAPED_INPUT_DATA_STRINGS_XF_FOR_RESULTS_LOG
		/// ML 5/18/2007 XFUNCTION_CLASS_NEW_ARRANGEMENT
		//xf.RemoveChild(TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME);
		xf.RemoveInputRangeAdditionalDataNode();
		/// end XFUNCTION_CLASS_NEW_ARRANGEMENT
		if (bOK)
		/// end ADDING_INPUT_TABLE_FROM_WITHIN_XF 
		{
			/// YuI 10/02/07 QA70-10468 CHANGE_PARAM_CANCEL_MESSES_UP_THE_DATA_MARKERS
			OnAfterCalculations(trOp);
			/// end CHANGE_PARAM_CANCEL_MESSES_UP_THE_DATA_MARKERS
			SetIdsToUIDsMap(vMapIdsToUIDs);	// put the updated map back into the operation
			return TRUE;
		}

		return FALSE;
	}
	/// end REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
//#endif	
	return error_report("XFOperation::executeWithRange failed to create XFunction");
	/// end XFUNCTION_OPERATION_CHANGE_PARAM_BUG
}

/// end VECTORIAL_NUMERIC_FUNCTIONS


/// YuI 07/26/06 XFOPERATION_CHANGE_PARAM_PROBLEM
/*
/// YuI 04/11/05 XFOPERATION_CHANGE_PARAM
typedef bool (*FUNCXFD)(TreeNode &tr, UINT); 
bool 	XFOperation::ShowDlg(TreeNode& trOperation, BOOL bChangeParams)
{
	/// YuI 08/09/05 XFUNCTION_OPERATION_CHANGE_PARAM_BUG
	// we need to decide ifg to Open GetNDialog on change param
	// or bring up the general XFunction dialog
	// basicly if Getn is applicable - it must be opened
	// if shift is down - XFDialog will open instead
	TreeNode trXF = trOperation.GUI;
	if( trXF.UsageCtxt.mainmenu.Use && trXF.UsageCtxt.mainmenu.GetN.nVal && !SHIFT_DOWN )
	{
#ifndef 	 _XF_LT_CALL_IN_VC //CPY 1/27/06
		XFunction xf;
		if( GetXFunction(trOperation, xf, true) )
		{
			return open_XF_getn_dialog(trXF, xf, false, false, false);
		}
#endif
	}
	/// end XFUNCTION_OPERATION_CHANGE_PARAM_BUG

	Function fn = Project.FindFunction("OpenXFDialog", "OriginLab\\XFDialog.c");
	FUNCXFD pfn = fn;
	if(pfn)
	{
		/// YuI 08/09/05 XFUNCTION_OPERATION_CHANGE_PARAM_BUG
		//	if( pfn(trOperation.xf, GetUID() ) )
		if( pfn(trXF, GetUID() ) )
		/// end XFUNCTION_OPERATION_CHANGE_PARAM_BUG
		{
			return true;
		}
	}
	
	return false;
}

BOOL 	XFOperation::GUItoOperation(TreeNode& trOperation, int nFrom)
{
	trOperation.xf.Replace(trOperation.GUI, true, true, true);
	return true;
}

BOOL	XFOperation::OperationtoGUI(TreeNode& trOperation, bool bInit, string* pstrSelectedTheme, bool bSetDefaultInputOnInit)
{
	/// YuI 08/09/05 XFUNCTION_OPERATION_CHANGE_PARAM_BUG
	//	return TRUE;
	TreeNode trGUI = tree_check_get_node(trOperation, "GUI");
	trGUI.Replace(trOperation.xf, true, true, true);
	return TRUE;
	/// end XFUNCTION_OPERATION_CHANGE_PARAM_BUG
}
/// end XFOPERATION_CHANGE_PARAM

BOOL 	XFOperation::Construct(TreeNode& trOperation, int nOption)
{
	if( WksReportOperation::Construct(trOperation, nOption) )
	{
		return TRUE;
	}
	
	return FALSE;
}
*/

///------ Folger 07/29/09 QA80-14035 SHOW_ERROR_WHEN_CHANGE_PARAM_OF_NONE_AUTO_GETN_DIALOG_XF
#ifdef		__NOT_ALLOW_CHANGE_PARAM_FOR_NONE_AUTO_GETN_DIALOG__	
static	BOOL	_is_xf_support_getn(XFunction& xf)
{
	TreeNode	trXF = xf.GetTree();
	TreeNode	trGetN = trXF.UsageCtxt.mainmenu.GetN;
	return		trGetN ? XF_GETN_NONE != trGetN.nVal : FALSE;
}
#endif		/// __NOT_ALLOW_CHANGE_PARAM_FOR_NONE_AUTO_GETN_DIALOG__	
///------ End SHOW_ERROR_WHEN_CHANGE_PARAM_OF_NONE_AUTO_GETN_DIALOG_XF

/// ML 9/4/2007 QA70-10332 OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
//BOOL	XFOperation::ChangeParam()
int		XFOperation::ChangeParam()
/// end OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
{
	TreeNode trOp;
	GetTree(trOp);
	XFunction xf;
	//------ CPY 5/17/07 QA70-9794 XF_SEPARATE_INTO_TWO_CLASSES_AND_CACHE
	//if( GetXFunction(trOp, xf, TRUE) )
	if(GetXFunction(trOp, xf, LTXF_CHANGE_PARAM | LTXF_SHOW_DIALOG) )
	//------
	{
		///------ Folger 07/29/09 QA80-14035 SHOW_ERROR_WHEN_CHANGE_PARAM_OF_NONE_AUTO_GETN_DIALOG_XF
		#ifdef		__NOT_ALLOW_CHANGE_PARAM_FOR_NONE_AUTO_GETN_DIALOG__	
		if ( !_is_xf_support_getn(xf) )
		{
			warning_msg_box(XFERR_NO_CHANGE_PARAM_SUPPORT, false);
			return -1;
		}
		#endif		/// __NOT_ALLOW_CHANGE_PARAM_FOR_NONE_AUTO_GETN_DIALOG__	
		///------ End SHOW_ERROR_WHEN_CHANGE_PARAM_OF_NONE_AUTO_GETN_DIALOG_XF

		TreeNode trOpGetN = tree_check_get_node(trOp, STR_OP_XF_GETN_NODE);			
		if( xf.OpenGetNDialog(trOpGetN) )
		{
			SetTree(trOp);
			/// ML 9/4/2007 QA70-10332 OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
			//Execute(OEXEM_ON_CHANGEPARAM);
			//return TRUE;
			return Execute(OEXEM_ON_CHANGEPARAM) ? 1 : 0;
			/// end OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
		}
	}
	
	/// ML 9/4/2007 QA70-10332 OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
	//return FALSE;
	return -1;		// not run (Cancel)
	/// end OPERATION_STATUS_UPDATE_ON_CHANGE_PARAMS
}
/// end XFOPERATION_CHANGE_PARAM_PROBLEM

///------ Folger 03/01/10 QA81-15106-P3 OP_CHANGE_SUPPORT_CHANGE_INPUT_DATA
/// virtual
void	XFOperation::SetTree(TreeNode& trOperation)
{
	TreeNode	trOpGetN = trOperation.xfGetN;
	if ( trOpGetN )
	{
		OPERATIONINFO	opInfo;
		GetInfo(&opInfo);
		if ( OPERSTATE_VALID_DIRTY == opInfo.nState )
		{	
			DataRange	drInput;
			drInput.Create();
		
			okxf_init_input_ranges_from_tree(&drInput, &trOpGetN);
		
			DataRange	drInputOld;
			GetInput(drInputOld);
			drInput.Clone(drInputOld, TRUE);
		}
	}
	
	WksReportOperation::SetTree(trOperation);
}
///------ End OP_CHANGE_SUPPORT_CHANGE_INPUT_DATA

///------ Folger 08/27/2010 ORG-905-P1 OP_CHANGE_SHOULD_UPDATE_RANGES_IN_XF_GETN_TREE
/// virtual
BOOL	XFOperation::OperationtoGUI(TreeNode& trOperation, bool bInit, string* pstrSelectedTheme/* = NULL*/, bool bSetDefaultInputOnInit/* = true*/, DWORD dwExeCtrl/* = 0*/, DWORD dwParam/* = 0*/)
{
	TreeNode	trOpGetN = trOperation.GetNode(STR_OP_XF_GETN_NODE);
	if ( !trOpGetN )
	{
		O_A_FAIL;
		return FALSE;
	}

	return UpdateTreeFromRanges(trOpGetN);
}
///------ End OP_CHANGE_SHOULD_UPDATE_RANGES_IN_XF_GETN_TREE