/*------------------------------------------------------------------------------*
 * File Name: Data.h															*
 * Creation: Sophy 2/24/2009													*
 * Purpose: Origin C header file for Origin basic Data types					*
 * Copyright (c) OriginLab Corp.	2000 - 2010									*
 * All Rights Reserved															*
 * Modifications:																*
 *	Sophy 7/7/2009 v8.1058 FAIL_TO_GET_ALL_DATA_IN_RECORD_WHEN_DATATYPE_IS_CHAR	*
 *	Sophy 8/10/2009 QA80-13988-P2 FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA 
 *	Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER				*
 *	Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
 *	Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE	*
 *	Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE			*
 *------------------------------------------------------------------------------*/


#ifndef	_CDF_MANAGER_H_
#define	_CDF_MANAGER_H_

#include "cdf.h"

#define	STR_VAR_TREE_R			"CDFVarsR"
#define	STR_VAR_TREE_Z			"CDFVarsZ"
///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
#define	STR_CDF_ATT_TREE		"CDFAtts"	
#define	STR_CDF_ATTS			"CDF Attributes"
#define	STR_GLOBAL_ATTS			"Global Attributes"
#define	STR_VARIABLE_ATTS		"Variable Attributes"
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
#define	STR_ATT_TREE_V			"CDFAttsV" //variable scope
#define	STR_ATT_TREE_G			"CDFAttsG" //global scope

#define	STR_VAR_TYPE			"Type"
#define	STR_VAR_REC_NUM			"Recs" 		//number of records allocated for this variable
#define	STR_VAR_WRITTEN_RECS	"WrittenRecs" //number of records initialized in this variable
#define	STR_VAR_MAX_REC_NUM		"MaxRecNum" //the max record number of all the initialzed records in this variable
#define	STR_VAR_REC_SIZE		"RecSize" //buffer needed to stored one record
#define	STR_VAR_UNITS			"Units"
#define	STR_VAR_DIM_NUM			"Dims" //number of dims and each dim's value
#define	STR_VAR_DIM_VARY		"DimVariance"	//dim variances
#define	STR_VAR_COMMENTS		"Comments"
#define	STR_VAR_DESCRIPT		"Description"


//variable attributes
#define	STR_VAR_TYPE_ATTRIB		"TypeValue"
#define	STR_VAR_LONGNAME_ATTRIB	"long_name"
#define	STR_VAR_VAR_TYPE		"VarType" //rVariable or zVariable
#define	STR_VAR_R_VARIABLE		"rVariable"
#define	STR_VAR_Z_VARIABLE		"zVariable"

#define	STR_VAR_REC_LABEL_FMT	"%s_Record%d"	

///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
//#define	STR_IMP_TREENODE_1D		"Var1D"	
//#define	STR_IMP_TREENODE_2D		"Var2D"
//#define	STR_IMP_TREENODE_3D		"Var3D"
//#define	STR_IMP_TREENODE_4D		"Var4D"
#define	MAX_SUPPORT_RANK			4
#define	STR_VAR_X_D					"Var%dD"
#define	STR_X_D_VARS				"%dD Variables"
#define	STR_ENTRY_X					"Entry%d"

#define	STR_MAX_REC_NUM_LABEL		"Max Record Number"
#define	STR_WRITTEN_RECS_LABEL		"Number of Written Records"
#define	STR_VAR_DIM_SIZE			"Dimension Size"
#define	STR_DIM_VARIANCE			"Dimension Variance"

#define	STR_DATA_TYPE				"Data Type"
#define	STR_VAR_TYPE_LABEL			"Variable Type"
#define	STR_VAR_INFO				"Variable Information"
#define	STR_VARY					"VARY"
#define	STR_NOVARY					"NOVARY"

#define	STR_DIMS_SEP				", "

#define	SET_LABEL(_NODE, _LABEL)	_NODE.SetAttribute(STR_LABEL_ATTRIB, _LABEL)

///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
#define	STR_ENTRY_ATTRIB			"Entry"
#define	ATTRIB_ENTRY_G				1
#define	ATTRIB_ENTRY_R				2
#define	ATTRIB_ENTRY_Z				3
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

//define compatible FSI_ type
#define	FSI_DATE	(FSI_COMPLEX + 1)
#define	FSI_DATE2	(FSI_DATE + 1)

class CDF
{
public:
	CDF(){}
	~CDF(){}
	CDFstatus	Open(LPCSTR lpcszFileName);
	CDFstatus	Close();
	//Import Data
	CDFstatus	ImportOneCol(LPCSTR lpcszVar, Worksheet& wks, int iCol);
	CDFstatus	ImportOneVarRecord(LPCSTR lpcszVar, const int& iRecNum, MatrixLayer& ml);
	CDFstatus	ImportOneVarRecord(LPCSTR lpcszVar, const int& iRecNum, Worksheet& wks);	///Sophy 9/6/2010 ORG-1000 IMPORT_MULTI_DIMS_TEXT_DATA_INTO_WORKSHEET_COLUMN

	//Access variable information
	CDFstatus	GetVarsInfo(TreeNode& trVarsInfo);
	CDFstatus	GetOneVarInfo(LPCSTR lpcszVar, vector<uint>& vnDims, int* pnDataType = NULL, int* pnNumRecs = NULL, int* pnMaxRecNum = NULL, string* pstrUnits = NULL, string* pstrLongName = NULL, string* strComment = NULL);
	
	CDFstatus	UpdateFileInfo(Page& pg);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
private:
	CDFstatus	constructVarTree();
	CDFstatus	constructRVarTree();
	CDFstatus	constructZVarTree();
	CDFstatus	constructAttbsTree();	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
	CDFstatus	addOneAttribEntry(long lAttrNum, long lEntryNum, int nEntryType, TreeNode& trParent);	///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	CDFstatus	addOneVarInfo(const long nVarID, TreeNode& trParent, bool bZVar = true);
	
	CDFstatus	addOneAttrib(const long& attNum, int nVarID, TreeNode& trVar, bool bZVar = true);
	CDFstatus	getOneVector(LPSTR lpcszVar, Column& col, const int& nocType);
	CDFstatus	getOneMatrix(LPSTR lpcszVar, const int& iRecNum, MatrixLayer& ml, const int nMatObjIndex, const vector<uint>& vnRef, const int& nocType);
	CDFstatus	getVarsInfoOneType(TreeNode& trVarsInfo, bool bZVar);
	TreeNode	getOneVar(LPCSTR lpcszVar, bool& bZVar);
	bool		checkIsOneD(vector<uint>& vnDims);
	void		filterOneVar(TreeNode& trVar);
	void		filterAttribsTree(TreeNode& trAttribs);	///Sophy 9/11/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	
	int			calRecordSize(const vector<long>& vDims, const long& lDataType);
	int			getTypeSize(long lType);
	int			getOCType(long lType);
	LPCSTR		getTypeName(long lType);
	
	bool		updateUserTree(OriginObject& obj, LPCSTR lpcszVar, LPCSTR lpcszLabel);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	
	
private:
	CDFid	m_cdfID;
	Tree	m_trInfo;
	long	m_lNumRVars;
	long	m_lNumDimsR;
	long	m_lNumZVars;
	long	m_lNumAttribs;
	
	long	m_lOldMajority; //reset Majority as ROW_MAJOR(for simpler handling) when open and restore on close
};

//---------------- Implementation --------------------//

CDFstatus	CDF::Open(LPCSTR lpcszFileName)
{
	//Init begin
	CDFstatus status = CDFopen(lpcszFileName, &m_cdfID);
	if ( status != CDF_OK )
		return status;
	//reset Majority
	status = CDFgetMajority(m_cdfID, &m_lOldMajority);
	if ( status != CDF_OK )
		return status;
	
	status = CDFgetNumVars(m_cdfID, 0, &m_lNumRVars);//CDFgetNumrVars(m_cdfID, &m_lNumRVars);
	if ( status != CDF_OK )
		return status;
	
	status = CDFgetNumVars(m_cdfID, 1, &m_lNumZVars);//CDFgetNumzVars(m_cdfID, &m_lNumZVars);
	if ( status != CDF_OK )
		return status;
	
	status = CDFgetNumAttributes(m_cdfID, &m_lNumAttribs);
	if ( status != CDF_OK )
		return status;
	//Init end
	status = constructVarTree();
	if ( status != CDF_OK )
		return status;
	
	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	status = constructAttbsTree();
	if ( status != CDF_OK )
		return status;
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	
	return status;
}

CDFstatus	CDF::Close()
{
	CDFstatus status;
	status = CDFsetMajority(m_cdfID, m_lOldMajority);
	if ( status != CDF_OK )
		return status;
	
	return CDFclose(m_cdfID);
}

CDFstatus	CDF::constructVarTree()
{
	CDFstatus status = constructRVarTree();
	if ( status != CDF_OK )
		return status;
	
	status = constructZVarTree();
	return status;
}

CDFstatus	CDF::constructRVarTree()
{
	CDFstatus	status = CDF_OK;
	TreeNode	trRVars = tree_check_get_node(m_trInfo, STR_VAR_TREE_R);
	for ( int nID = 0; nID < m_lNumRVars; nID++ )
	{
		if ( (status = addOneVarInfo(nID, trRVars, false)) != CDF_OK )
			return status;
	}
	return status;
}

CDFstatus	CDF::GetVarsInfo(TreeNode& trVarsInfo)
{
	if ( !trVarsInfo )
		return CDF_WARN;
	
	getVarsInfoOneType(trVarsInfo, false); //get rVariables
	getVarsInfoOneType(trVarsInfo, true); //get zVariables
	
	return CDF_OK;
}

CDFstatus	CDF::getVarsInfoOneType(TreeNode& trVarsInfo, bool bZVar)
{
	if ( !trVarsInfo )
		return CDF_WARN;
	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
	//TreeNode	tr1D, tr2D, tr3D, tr4D;
	TreeNode	trXD;
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	vector<uint>	vnDims;
	int				nRealDims;
	
	string	strVars = bZVar ? STR_VAR_TREE_Z : STR_VAR_TREE_R;
	TreeNode	trVars = m_trInfo.GetNode(strVars);
	ASSERT(trVars);
	foreach ( TreeNode trOneVar in trVars.Children )
	{
		vnDims = trOneVar.Dims.nVals;
		nRealDims = vnDims.GetSize();
		if ( checkIsOneD(vnDims) )
			nRealDims = 1;
		
		TreeNode trVar = trOneVar.Clone(true);
		filterOneVar(trVar); //remove idle nodes
		///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
		//switch(nRealDims)
		//{
		//case 0:
		//case 1:
			//if ( !tr1D.IsValid() )
				//tr1D = trVarsInfo.AddNode(STR_IMP_TREENODE_1D);
			//tr1D.AddNode(trVar);
			//break;
			//
		//case 2:
			//if ( !tr2D.IsValid() )
				//tr2D = trVarsInfo.AddNode(STR_IMP_TREENODE_2D);
			//tr2D.AddNode(trVar);
			//break;
			//
		//case 3:
			//if ( !tr3D.IsValid() )
				//tr3D = trVarsInfo.AddNode(STR_IMP_TREENODE_3D);
			//tr3D.AddNode(trVar);
			//break;
			//
		//case 4:
			//if ( !tr4D.IsValid() )
				//tr4D = trVarsInfo.AddNode(STR_IMP_TREENODE_4D);
			//tr4D.AddNode(trVar);
			//break;
			//
		//default:
			//ASSERT(false); //should never come here.
			//break;
		//}	
		if ( nRealDims <= MAX_SUPPORT_RANK )
		{
			string strXD;
			strXD.Format(STR_VAR_X_D, nRealDims);
			trXD = tree_check_get_node(trVarsInfo, strXD);
			
			strXD.Format(STR_X_D_VARS, nRealDims);
			SET_LABEL(trXD, strXD);
			trXD.AddNode(trVar);
		}
		else
			ASSERT(FALSE); //should never come here
		///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	}
	return CDF_OK;
}

CDFstatus	CDF::GetOneVarInfo(LPCSTR lpcszVar, vector<uint>& vnDims, int* pnDataType, int* pnNumRecs , int* pnMaxRecNum, string* pstrUnits, string* pstrLongName, string* pstrComments) //NULL, NULL, NULL, NULL, NULL, NULL
{
	bool		bZVar;
	TreeNode	trVar = getOneVar(lpcszVar, bZVar);
	if ( !trVar ) //can not find the variable
		return NO_SUCH_VAR;
	
	if ( pnDataType )
	{
		int cdfType = -1;
		if ( trVar.Type )
			trVar.Type.GetAttribute(STR_VAR_TYPE_ATTRIB, cdfType);
		*pnDataType = getOCType(cdfType);
	}
	
	TreeNode	trDims = trVar.GetNode(STR_VAR_DIM_NUM);
	vnDims = trDims.nVals;
	
	if ( pnNumRecs )
		*pnNumRecs = trVar.WrittenRecs.nVal;
	
	if ( pnMaxRecNum )
		*pnMaxRecNum = trVar.MaxRecNum.nVal;
	
	if ( pstrUnits )
	{
		///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
		//TreeNode	trUnits = trVar.GetNode(STR_VAR_UNITS);
		//if ( trUnits )
			//*pstrUnits = trUnits.strVal;
		TreeNode trUnits = trVar.GetNode(STR_VAR_UNITS, false);
		if ( trUnits )
			*pstrUnits = trUnits.FirstNode ? trUnits.FirstNode.strVal : trUnits.strVal;
		///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	}
	
	if ( pstrLongName )
	{
		TreeNode	trLongName = trVar.GetNode(STR_VAR_LONGNAME_ATTRIB);
		if ( trLongName )
			///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
			//*pstrLongName = trLongName.strVal;
			*pstrLongName = trLongName.FirstNode ? trLongName.FirstNode.strVal : trLongName.strVal;
			///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
		
		if ( pstrLongName->IsEmpty() )
			*pstrLongName = trVar.tagName;
	}
	
	if ( pstrComments )
	{
		TreeNode	trComments = trVar.GetNode(STR_VAR_COMMENTS);
		if ( trComments )
			*pstrComments = trComments.strVal;
	}
	return CDF_OK;
}

///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
CDFstatus	CDF::UpdateFileInfo(Page& pg)
{
	CDFstatus status = CDF_WARN;
	TreeNode trAttrs = m_trInfo.GetNode(STR_CDF_ATT_TREE);
	if ( trAttrs )
	{
		filterAttribsTree(trAttrs);	///Sophy 9/11/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
		string strInfoName = trAttrs.tagName;
		if ( set_user_info(pg, strInfoName, trAttrs) )
			status = CDF_OK;
	}
	return status;
}
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
CDFstatus	CDF::ImportOneCol(LPCSTR lpcszVar, Worksheet& wks, int iCol)
{
	if ( !wks )
		return CDF_WARN;
	
	CDFstatus	status;
	vector<uint>	vnDims;
	int				nocType;
	int				nWrittenRecs;
	int				nMaxRecNum;
	string			strUnits, strLongName, strComments;
	status = GetOneVarInfo(lpcszVar, vnDims, &nocType, &nWrittenRecs, &nMaxRecNum, &strUnits, &strLongName, &strComments);
	if ( status != CDF_OK )
		return CDF_WARN;
	
	if ( !checkIsOneD(vnDims) )
		return CDF_WARN; //not supported
	
	if ( iCol >= wks.GetNumCols() )
		wks.SetSize(-1, iCol + 1);
	
	Column	col(wks, iCol);
	///Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
	if ( nocType != FSI_DATE && nocType != FSI_DATE2 && nocType != FSI_CHAR ) //FSI_DATE & FSI_DATE2 are local defined type, FSI_CHAR will update independently, so need to set internal data type here
	{
		col.SetFormat(OKCOLTYPE_NUMERIC);
		col.SetInternalDataType(nocType);
	}
	///end UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
	//import data
	status = getOneVector((LPSTR)lpcszVar, col, nocType); //testing...
	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
	updateUserTree(col, lpcszVar, STR_VAR_INFO);
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	col.SetUnits(strUnits);
	col.SetLongName(strLongName);
	col.SetComments(strComments);
	
	return status;
}

CDFstatus	CDF::ImportOneVarRecord(LPCSTR lpcszVar, const int& iRecNum, MatrixLayer& ml)
{
	if ( !ml )
		return CDF_WARN;
	
	bool		bZVar;
	int			nocType;
	CDFstatus	status;
	vector<uint>	vnDims;
	
	status = GetOneVarInfo(lpcszVar, vnDims, &nocType);
	if ( status != CDF_OK )
		return status;

	
	if ( checkIsOneD(vnDims) )
		return CDF_WARN; //should be imported to worksheet.
	
	int	nDims = vnDims.GetSize();
	if ( nDims > 4 )
	{
		printf("Dimensions more than 4 are not supported!");
		ASSERT(FALSE);
		return CDF_WARN;
	}
	
	if ( !ml.SetInternalDataType(nocType) )
		return CDF_WARN;
	
	vector<uint>	vnRef(0);
	switch(nDims)
	{
	case 2:
		ml.SetSize(1, vnDims[0], vnDims[1]);
		status = getOneMatrix((LPSTR)lpcszVar, iRecNum, ml, 0, vnRef, nocType);
		if ( status != CDF_OK )
			return status;
		break;
		
	case 3:
		vnRef.SetSize(1);
		ml.SetSize(vnDims[0], vnDims[1], vnDims[2]);
		for ( int ii = 0; ii < vnDims[0]; ii++ )
		{
			vnRef[0] = ii;
			status = getOneMatrix((LPSTR)lpcszVar, iRecNum, ml, ii, vnRef, nocType);
			ASSERT(status == CDF_OK);
			if ( status != CDF_OK )
				return status;
		}
		break;
		
	case 4:
		vnRef.SetSize(2);
		ml.SetSize(vnDims[0] * vnDims[1], vnDims[2], vnDims[3]);
		for ( int ii = 0; ii < vnDims[0]; ii++ )
		{
			vnRef[0] = ii;
			for ( int jj = 0; jj < vnDims[1]; jj++ )
			{
				vnRef[1] = jj;
				status = getOneMatrix((LPSTR)lpcszVar, iRecNum, ml, (ii * vnDims[1] + jj), vnRef, nocType);
				ASSERT(status == CDF_OK);
				if ( status != CDF_OK )
					return status;
			}
		}
		break;
		
	default:
		ASSERT(FALSE);
	}
	
	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
	updateUserTree(ml, lpcszVar, STR_VAR_INFO);
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

	return status;
}

///Sophy 9/6/2010 ORG-1000 IMPORT_MULTI_DIMS_TEXT_DATA_INTO_WORKSHEET_COLUMN
CDFstatus	CDF::ImportOneVarRecord(LPCSTR lpcszVar, const int& iRecNum, Worksheet& wks)
{
	if ( !wks )
		return CDF_WARN;
	
	CDFstatus status = CDF_OK;
	vector<uint>	vnDims;
	string			strUnits, strLongName, strComments;
	status = GetOneVarInfo(lpcszVar, vnDims, NULL, NULL, NULL, &strUnits, &strLongName, &strComments);
	if ( status != CDF_OK )
		return CDF_WARN;

	
	long lFactor = 1;
	vector<long> lModes(vnDims.GetSize());
	for ( int iMod = vnDims.GetSize() - 1; iMod >= 0; iMod-- )
	{
		lModes[iMod] = lFactor;
		lFactor *= vnDims[iMod];
	}
	int nNumData = lFactor;
	
	bool		bZVar;
	TreeNode	trVar = getOneVar(lpcszVar, bZVar);
	int			nVarType = bZVar ? 1 : 0; //rVariable or zVariable
	
	long varNum = CDFgetVarNum(m_cdfID, (LPSTR)lpcszVar);
	vector<string> vsData(0);
	int	nNumEles = 0;
	CDFgetVarNumElements(m_cdfID, nVarType, varNum, &nNumEles); //number of charaters in each data value

	vector<long> lIndices(vnDims.GetSize());
	for ( int iData = 0; iData < nNumData; iData++ )
	{
		long lMode = iData;
		for ( int iMod = 0; iMod < vnDims.GetSize(); iMod++ )
		{
			lIndices[iMod] = lMode / lModes[iMod];
			lMode = lMode % lModes[iMod];
		}
		
		string strData;
		LPSTR lpBuffer = strData.GetBuffer(nNumEles);
		status = CDFgetVarData(m_cdfID, nVarType, varNum, iRecNum, (long*)lIndices, lpBuffer);
		strData.ReleaseBuffer();
		if ( status == CDF_OK )
			vsData.Add(strData);

	}
	Column	col(wks, iRecNum);
	col.PutStringArray(vsData);
	updateUserTree(col, lpcszVar, STR_VAR_INFO);
	col.SetUnits(strUnits);
	col.SetLongName(strLongName);
	col.SetComments(strComments);
	return status;
}
///end IMPORT_MULTI_DIMS_TEXT_DATA_INTO_WORKSHEET_COLUMN
bool		CDF::checkIsOneD(vector<uint>& vnDims)
{
	for ( int ii = vnDims.GetSize() - 2; ii >= 0; ii-- ) //check all dim sizes except the last one
	{
		if ( vnDims[ii] != 1 )
			return false;
	}
	return true; //0 dims or one dims or can be converted as one dim array.
}

void		CDF::filterOneVar(TreeNode& trVar)
{
	vector<string>	vsUsefulNode = {
									STR_VAR_TYPE,
									STR_VAR_VAR_TYPE,
									STR_VAR_DESCRIPT,
									///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
									STR_VAR_LONGNAME_ATTRIB,
									STR_VAR_UNITS,
									///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
									STR_VAR_DIM_NUM,
									STR_VAR_DIM_VARY,
									STR_VAR_WRITTEN_RECS, 
									STR_VAR_MAX_REC_NUM
								   };
	if ( !trVar )
		return;
	
	foreach ( TreeNode trNode in trVar.Children )
	{
		string strName = trNode.tagName;
		if ( vsUsefulNode.Find(strName, 0, true) < 0 )
			trNode.Remove();
		///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
		else if ( strName.CompareNoCase(STR_VAR_LONGNAME_ATTRIB) == 0 )
		{
			string strLongName = trNode.FirstNode ? trNode.FirstNode.strVal : trNode.strVal;
			trNode.RemoveChildrenWithPrefix();
			trNode.strVal = strLongName;
			
		}
		else if ( strName.CompareNoCase(STR_VAR_UNITS) == 0 )
		{
			string strUnits = trNode.FirstNode ? trNode.FirstNode.strVal : trNode.strVal;
			trNode.RemoveChildrenWithPrefix();
			trNode.strVal = strUnits;
		}
		///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
		else if ( strName.CompareNoCase(STR_VAR_DIM_NUM) == 0 )
		{
			vector<int> vnDims;
			vnDims = trNode.nVals;
			vector<string> vsDims;
			convert_int_vector_to_string_vector(vnDims, vsDims);
			trNode.Reset();
			trNode.strVal = get_display_string(vsDims, vsDims.GetSize(), STR_DIMS_SEP);
			SET_LABEL(trNode, STR_VAR_DIM_SIZE);
		}
		else if ( strName.CompareNoCase(STR_VAR_DIM_VARY) == 0 )
		{
			vector<int> vnDims;
			vnDims = trNode.nVals;
			vector<string> vsDims(vnDims.GetSize());
			for ( int ii = 0; ii < vnDims.GetSize(); ii++ )
			{
				if ( vnDims[ii] == 0 )
					vsDims[ii] = STR_NOVARY;
				else
					vsDims[ii] = STR_VARY;
			}
			trNode.Reset();
			trNode.strVal = get_display_string(vsDims, vsDims.GetSize(), STR_DIMS_SEP);
			SET_LABEL(trNode, STR_DIM_VARIANCE);
		}
	}
	return;
}

///Sophy 9/11/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
void		CDF::filterAttribsTree(TreeNode& trAttribs)
{
	if ( !trAttribs )
		return;
	foreach(TreeNode trAttsGV in trAttribs.Children) //global and variable attribute tree
	{
		foreach(TreeNode trAttrib in trAttsGV.Children) //each attribute
		{
			foreach(TreeNode trEntry in trAttrib.Children) //each attribute entry
			{
				int nOCType;
				trEntry.GetAttribute(STR_VAR_TYPE, nOCType);
				switch(nOCType)
				{
				case FSI_CHAR:
				case FSI_DATE:
				case FSI_DATE2:
					break; //no need to update display issue
					
				case FSI_BYTE:
					vector<byte> vbVals;
					vbVals = trEntry.bVals;
					vector<string> vsVals;
					convert_byte_vector_to_string_vector(vbVals, vsVals);
					trEntry.Reset();
					trEntry.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
					break;
					
				case FSI_SHORT:
					vector<short> vVals;
					vVals = trEntry.sVals;
					vector<int>	vnVals;
					vnVals = vVals;
					vector<string> vsVals;
					convert_int_vector_to_string_vector(vnVals, vsVals);
					trEntry.Reset();
					trEntry.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
					break;
					
				case FSI_USHORT:
					vector<short> vVals;
					vVals = trEntry.sVals;
					vector<uint>	vnVals;
					vnVals = vVals;
					vector<string> vsVals;
					convert_uint_vector_to_string_vector(vnVals, vsVals);
					trEntry.Reset();
					trEntry.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
					break;
					
				case FSI_LONG:
					vector<int>	vnVals;
					vnVals = trEntry.nVals;
					vector<string> vsVals;
					convert_int_vector_to_string_vector(vnVals, vsVals);
					trEntry.Reset();
					trEntry.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
					break;
					
				case FSI_ULONG:
					vector<uint>	vnVals;
					vnVals = trEntry.nVals;
					vector<string> vsVals;
					convert_uint_vector_to_string_vector(vnVals, vsVals);
					trEntry.Reset();
					trEntry.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
					break;
					
				case FSI_REAL:
					vector<float> vfVals;
					vfVals = trEntry.fVals;
					vector<double> vdVals;
					vdVals = vfVals;
					vector<string> vsVals;
					convert_double_vector_to_string_vector(vdVals, vsVals, vdVals.GetSize());
					trEntry.Reset();
					trEntry.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
					break;
					
				case FSI_DOUBLE:
					vector<double> vdVals;
					vdVals = trEntry.dVals;
					vector<string> vsVals;
					convert_double_vector_to_string_vector(vdVals, vsVals, vdVals.GetSize());
					trEntry.Reset();
					trEntry.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
					break;
					
				default:
					ASSERT(FALSE);
					break;
				}
			}
		}
	}
}
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

TreeNode	CDF::getOneVar(LPCSTR lpcszVar, bool& bZVar)
{
	TreeNode	trVar;
	TreeNode	trRVars = m_trInfo.GetNode(STR_VAR_TREE_R);
	bZVar = false;
	if ( trRVars )
		trVar = trRVars.GetNode(lpcszVar);
	if ( !trVar ) //try to get from zVariable tree
	{
		TreeNode	trZVars = m_trInfo.GetNode(STR_VAR_TREE_Z);
		if ( trZVars )
		{
			trVar = trZVars.GetNode(lpcszVar);
			bZVar = true; //if trVar not empty, it is zVariable
		}
	}
	
	return trVar;
}

CDFstatus	CDF::constructZVarTree()
{
	CDFstatus	status = CDF_OK;
	TreeNode	trZVars = tree_check_get_node(m_trInfo, STR_VAR_TREE_Z);
	for ( int nID = 0; nID < m_lNumZVars; nID++ )
	{
		if ( (status = addOneVarInfo(nID, trZVars, true)) != CDF_OK )
			return status;
	}
	return status;
}

///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
CDFstatus	CDF::constructAttbsTree()
{
	CDFstatus status = CDF_OK;
	TreeNode trAtts = tree_check_get_node(m_trInfo, STR_CDF_ATT_TREE);
	SET_LABEL(trAtts, STR_CDF_ATTS);
	TreeNode trAttVG, trOneAttrib;
	char attName[CDF_ATTR_NAME_LEN256 + 1];
	long lAttribScope = 0, lMaxgEntry, lMaxrEntry, lMaxzEntry, lDataType, lNumElements;
	for ( int nAttN; nAttN < m_lNumAttribs; nAttN++ )
	{
		status = CDFinquireAttr(m_cdfID, nAttN, attName, &lAttribScope, &lMaxgEntry, &lMaxrEntry, &lMaxzEntry);
		
		string strAttName(attName);
		strAttName.MakeValidCName();
		if ( GLOBAL_SCOPE == lAttribScope )
		{
			trAttVG = tree_check_get_node(trAtts, STR_ATT_TREE_G);
			SET_LABEL(trAttVG, STR_GLOBAL_ATTS);
			
			trOneAttrib = tree_check_get_node(trAttVG, strAttName);
			SET_LABEL(trOneAttrib, attName);
			
			for ( long igEntry = 0; igEntry <= lMaxgEntry; igEntry++ )
			{
				status = addOneAttribEntry(nAttN, igEntry, ATTRIB_ENTRY_G, trOneAttrib);
			}
		}
		else //VARIABLE_SCOPE
		{
			trAttVG = tree_check_get_node(trAtts, STR_ATT_TREE_V);
			SET_LABEL(trAttVG, STR_VARIABLE_ATTS);
			
			trOneAttrib = tree_check_get_node(trAttVG, strAttName);
			SET_LABEL(trOneAttrib, attName);
			
			for ( long irEntry = 0; irEntry <= lMaxrEntry; irEntry++ )
			{
				status = addOneAttribEntry(nAttN, irEntry, ATTRIB_ENTRY_R, trOneAttrib);
			}
			
			for ( long izEntry = 0; izEntry <= lMaxzEntry; izEntry++ )
			{
				status = addOneAttribEntry(nAttN, izEntry, ATTRIB_ENTRY_Z, trOneAttrib);
			}
		}
		
	}
	return status;
}
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
CDFstatus	CDF::addOneAttribEntry(long lAttrNum, long lEntryNum, int nEntryType, TreeNode& trParent)
{
	CDFstatus status = CDF_WARN;
	if ( !trParent )
		return status;
	
	long lDataType, lNumElements;
	status = CDFinquireAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, &lDataType, &lNumElements);
	if ( status == CDF_OK )
	{
		string strEntry;
		strEntry.Format(STR_ENTRY_X, lEntryNum);
		TreeNode trEntry = tree_check_get_node(trParent, strEntry);
		
		int nOCType = getOCType(lDataType);
		trEntry.SetAttribute(STR_VAR_TYPE, nOCType);
		trEntry.SetAttribute(STR_ENTRY_ATTRIB, lEntryNum);
		switch(nOCType)
		{
		case FSI_CHAR:
			
			string strVal;
			LPSTR lpBuffer = strVal.GetBuffer(lNumElements);
			
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, lpBuffer);
				
			strVal.ReleaseBuffer();
			if ( status == CDF_OK )
				trEntry.strVal = strVal;
			
			break;
			
		case FSI_BYTE:
			
			vector<byte> vbVals(lNumElements);
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, vbVals);
			if ( status == CDF_OK )
				trEntry.bVals = vbVals;
			
			break;
			
		case FSI_SHORT:
		case FSI_USHORT:
			
			vector<short> vsVals(lNumElements);
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, vsVals);
			if ( status == CDF_OK )
				trEntry.sVals = vsVals;
			
			break;
			
		case FSI_LONG:
		case FSI_ULONG:
			
			vector<int> vnVals(lNumElements);
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, vnVals);
			if ( status == CDF_OK )
				trEntry.nVals = vnVals;
			
			break;
			
		case FSI_REAL:
			vector<float> vfVals(lNumElements);
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, vfVals);
			if ( status == CDF_OK )
				trEntry.fVals = vfVals;
			
			break;
			
		case FSI_DOUBLE:
			
			vector<double> vdVals(lNumElements);
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, vdVals);
			if ( status == CDF_OK )
				trEntry.dVals = vdVals;
			
			break;
			
		case FSI_DATE:
			
			vector<string> vsVals(lNumElements);
			vector<double> vDouble(lNumElements);
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, vDouble);
			if ( status == CDF_OK )
			{
				for ( int ii = 0; ii < lNumElements; ii++ )
				{
					char epString[EPOCH_STRING_LEN + 1];
					encodeEPOCHx(vDouble[ii], "<yr.02><mm.02><dom.02> <hour.02>:<min.02>:<sec.02>", epString);
					
					string strData(epString);
					vsVals[ii] = strData;
				}
				trEntry.strVals = vsVals;
			}
			break;
			
		case FSI_DATE2:
			
			vector<string> vsVals(lNumElements);
			vector<double> vDouble(lNumElements * 2);
			status = CDFgetAttrEntry(m_cdfID, nEntryType, lAttrNum, lEntryNum, vDouble);
			if ( status == CDF_OK )
			{
				for ( int ii = 0; ii < lNumElements; ii++ )
				{
					char epString[EPOCH_STRING_LEN + 1];
					
					encodeEPOCH16_x(&vDouble[ii * 2], "<yr.02><mm.02><dom.02> <hour.02>:<min.02>:<sec.02>", epString);
					
					string strData(epString);
					vsVals[ii] = strData;
				}
				trEntry.strVals = vsVals;
			}
			break;
			
		default:
			ASSERT(FALSE);
			break; //need to add more support
		}
	}
	return status;
}
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

CDFstatus	CDF::addOneVarInfo(const long nVarID, TreeNode& trParent, bool bZVar) //true
{
	char	varName[CDF_VAR_NAME_LEN256 + 1];
	long	lDataType;
	long	lNumElements; //number of elements of datatype
	long	lRecVary;
	long	lNumDims;
	long	vlDimSizes[CDF_MAX_DIMS];
	long	vlDimVarys[CDF_MAX_DIMS];
	CDFstatus	status;
	int		nVarType = bZVar ? 1 : 0; //rVariable or zVariable;
	status = CDFinquireVar(m_cdfID, nVarType, nVarID, varName, &lDataType, &lNumElements, &lNumDims, vlDimSizes, &lRecVary, vlDimVarys);
	
	TreeNode	trVar = tree_check_get_node(trParent, varName);
	TreeNode	trType = tree_check_get_node(trVar, STR_VAR_TYPE);
	SET_LABEL(trType, STR_DATA_TYPE);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	trType.strVal = getTypeName(lDataType);
	trType.SetAttribute(STR_VAR_TYPE_ATTRIB, lDataType);
	
	TreeNode	trVarType = tree_check_get_node(trVar, STR_VAR_VAR_TYPE);
	SET_LABEL(trVarType, STR_VAR_TYPE_LABEL);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	trVarType.strVal = bZVar ? STR_VAR_Z_VARIABLE : STR_VAR_R_VARIABLE;
	
	vector<long>	vnDimSizes;
	vector<long>	vnDimVariances;
	
	vnDimSizes.SetSize(lNumDims);
	vnDimVariances.SetSize(lNumDims);
	for ( int ii = 0; ii < lNumDims; ii++ )
	{
		vnDimSizes[ii] = vlDimSizes[ii];
		vnDimVariances[ii] = vlDimVarys[ii];
	}
	
	TreeNode	trDimNum = tree_check_get_node(trVar, STR_VAR_DIM_NUM);
	SET_LABEL(trDimNum, STR_VAR_DIM_SIZE);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	trDimNum.nVals = vnDimSizes;
	
	TreeNode	trDimVary = tree_check_get_node(trVar, STR_VAR_DIM_VARY);
	SET_LABEL(trDimVary, STR_DIM_VARIANCE);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	trDimVary.nVals = vnDimVariances;
	
	//get number of records
	long		lNumRecAllocated;
	status = CDFgetVarAllocRecords(m_cdfID, nVarType, nVarID, &lNumRecAllocated);
	TreeNode	trAllocatedRecs = tree_check_get_node(trVar, STR_VAR_REC_NUM);
	trAllocatedRecs.nVal = lNumRecAllocated;
	
	long		lNumRec;
	status = CDFgetVarNumRecsWritten(m_cdfID, nVarType, nVarID, &lNumRec);//CDFgetzVarNumRecsWritten(m_cdfID, nVarID, &lNumRec);
	TreeNode	trWrittenRecs = tree_check_get_node(trVar, STR_VAR_WRITTEN_RECS);
	SET_LABEL(trWrittenRecs, STR_WRITTEN_RECS_LABEL);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	trWrittenRecs.nVal = lNumRec;
	
	long		lMaxRecNum;
	status = CDFgetVarMaxWrittenRecNum(m_cdfID, nVarType, nVarID, &lMaxRecNum);
	TreeNode	trMaxRecNum = tree_check_get_node(trVar, STR_VAR_MAX_REC_NUM);
	SET_LABEL(trMaxRecNum, STR_MAX_REC_NUM_LABEL);	///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
	trMaxRecNum.nVal = lMaxRecNum;
	
	//get one record's size
	TreeNode	trRecSize = tree_check_get_node(trVar, STR_VAR_REC_SIZE);
	trRecSize.nVal = calRecordSize(vnDimSizes, lDataType);
	//try to get attrib, so ignore return value in case attr not exists
	for ( int attNum = 0; attNum < m_lNumAttribs; attNum++ )
	{
		addOneAttrib(attNum, nVarID, trVar, bZVar);
	}
	
	TreeNode	trDescript = tree_check_get_node(trVar, STR_VAR_DESCRIPT);
	///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	//if ( trVar.long_name )
		//trDescript.strVal = trVar.long_name.strVal;
	//else
		//trDescript.strVal = trVar.tagName;
	string strDesc = "";
	if ( strDesc.IsEmpty() && trVar.description )
		strDesc = trVar.description.FirstNode ? trVar.description.FirstNode.strVal : trVar.description.strVal;		
	if ( strDesc.IsEmpty() && trVar.long_name )
		strDesc = trVar.long_name.FirstNode ? trVar.long_name.FirstNode.strVal : trVar.long_name.strVal;
	if ( strDesc.IsEmpty() )
		strDesc = trVar.tagName;

	if ( trDescript.FirstNode )
		trDescript.FirstNode.strVal = strDesc;
	else
		trDescript.strVal = strDesc;
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	
	return status;
}

CDFstatus	CDF::addOneAttrib(const long& attNum, int nVarID, TreeNode& trVar, bool bZVar) //true
{
	long	lDataType;
	long	lNumElements;
	CDFstatus status = CDF_OK;
	///Sophy 9/9/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	//string	strName;
	//LPSTR	lpName = strName.GetBuffer(CDF_ATTR_NAME_LEN256 + 1);
	//if ( attNum >= CDF_OK ) //exist
	//{
		//
		//if ( bZVar )
			//status = CDFinquireAttrzEntry(m_cdfID, attNum, nVarID, &lDataType, &lNumElements);
		//else
			//status = CDFinquireAttrrEntry(m_cdfID, attNum, nVarID, &lDataType, &lNumElements);
		//
		//if ( status == CDF_OK && lDataType == CDF_CHAR )
		//{
			//string strVal;
			//LPSTR lpBuffer = strVal.GetBuffer(lNumElements + 1);
			//
			//if ( bZVar )
				//status = CDFgetAttrzEntry(m_cdfID, attNum, nVarID, lpBuffer);
			//else
				//status = CDFgetAttrrEntry(m_cdfID, attNum, nVarID, lpBuffer);
				//
			//strVal.ReleaseBuffer();
			//TreeNode trAttrib = tree_check_get_node(trVar, lpName);
			//trAttrib.strVal = strVal;
		//}
	//}
	//strName.ReleaseBuffer();
	char attrName[CDF_ATTR_NAME_LEN256 + 1];
	long lEntryScope, lMaxgEntry, lMaxrEntry, lMaxzEntry;
	status = CDFinquireAttr(m_cdfID, attNum, attrName, &lEntryScope, &lMaxgEntry, &lMaxrEntry, &lMaxzEntry);
	if ( VARIABLE_SCOPE == lEntryScope && (lMaxrEntry >= 0 && !bZVar || lMaxzEntry >= 0 && bZVar) )
	{
		string strAttrName(attrName);
		strAttrName.MakeValidCName();
		
		TreeNode trOneAttrib = tree_check_get_node(trVar, strAttrName);
		SET_LABEL(trOneAttrib, attrName);
		
		int nEntryType = bZVar ? ATTRIB_ENTRY_Z : ATTRIB_ENTRY_R;
		status = addOneAttribEntry(attNum, nVarID, nEntryType, trOneAttrib);
	}
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	return status;
}

CDFstatus	CDF::getOneVector(LPSTR lpcszVar, Column& col, const int& nocType)
{
	bool		bZVar;
	TreeNode	trVar = getOneVar(lpcszVar, bZVar);
	int			nVarType = bZVar ? 1 : 0; //rVariable or zVariable
	if ( !trVar || nocType < 0 )
		return NO_SUCH_VAR;
	int			varNum = CDFgetVarNum(m_cdfID, lpcszVar);
	int			nRecs = trVar.Recs.nVal;
	int			nMaxRecNum = trVar.MaxRecNum.nVal;
	int			nWrittenRecs = trVar.WrittenRecs.nVal;
	int			nNumRecRead = 0;
	int			nRecSize = trVar.RecSize.nVal;
	int			iRec;
	CDFstatus	status = CDF_OK;
	vectorbase&	vInternal = col.GetDataObject();
	
	
	TreeNode	trDimVary = trVar.GetNode(STR_VAR_DIM_VARY);
	vector<long>	vlDimVary(0);
	if ( trDimVary )
		vlDimVary = trDimVary.nVals;
	
	long		lDimVary = vlDimVary.GetSize() > 0 ? vlDimVary[0] : VARY; //since lpcszVar is 1D variable. for 0D variable, always should be VARY
	
	switch(nocType)
	{
	case FSI_CHAR:
		vector<string> vsData(0);
		int	nNumEles = 0;
		CDFgetVarNumElements(m_cdfID, nVarType, varNum, &nNumEles); //number of charaters in each data value
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			///Sophy 7/7/2009 v8.1058 FAIL_TO_GET_ALL_DATA_IN_RECORD_WHEN_DATATYPE_IS_CHAR
			/*
			string			strChars;
			LPSTR			lpBuffer = strChars.GetBuffer(nNumEles * nRecSize / sizeof(char));
			status = CDFgetVarRecordData(m_cdfID,nVarType, varNum, iRec, lpBuffer);
			strChars.ReleaseBuffer();
			if ( status == CDF_OK )
			{
				vector<string>	vsTokens;
				int	nTokens = strChars.GetTokens(vsTokens);
				ASSERT(nTokens == nRecSize);

				vsData.Append(vsTokens);
				nNumRecRead++;
			}
			*/
			//when it is string type, CDFgetVarRecordData can only get the first item's value in a record, so use CDFgetVarData to retrieve data item by item.
			//nRecSize is equal to the number of string in one record of a variable
			long lIndex[1];
			for ( int iValue = 0; iValue < nRecSize; iValue++ )
			{
				lIndex[0] = iValue;
				string	strChars;
				LPSTR	lpBuffer = strChars.GetBuffer(nNumEles/sizeof(char));
				status = CDFgetVarData(m_cdfID, nVarType, varNum, iRec, lIndex, lpBuffer);
				strChars.ReleaseBuffer();
				if ( status == CDF_OK )
					vsData.Add(strChars);
			}
			nNumRecRead++;
			///end FAIL_TO_GET_ALL_DATA_IN_RECORD_WHEN_DATATYPE_IS_CHAR
		}
		///Sophy 8/10/2009 QA80-13988-P2 FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA should set column format before set data
		//Dataset ds;
		//ds.Attach(col);
		//ds.PutStringArray(vsData);
		
		//col.SetFormat(OKCOLTYPE_TEXT);	//set column as Text format
		col.SetFormat(OKCOLTYPE_TEXT);
		col.PutStringArray(vsData);
		///end FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA		
		break;
		
	case FSI_BYTE:
		vector<byte> vbData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<byte>	vByte(nRecSize/sizeof(byte));
			vByte = -33;
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vByte);
			if ( status == CDF_OK )
			{
				if ( lDimVary == NOVARY )
				{
					//vByte = vByte[0]; this statement can cause runtime error!!
					byte bTmp = vByte[0];
					vByte = bTmp;
				}
				
				vbData.Append(vByte);
				nNumRecRead++;
			}
		}
		vInternal = vbData;

		break;
		
	case FSI_SHORT:
		vector<short>	vshData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<short>	vShort(nRecSize/sizeof(short));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vShort);
			if ( status == CDF_OK )
			{
				if ( lDimVary == NOVARY )
				{
					//vShort = vShort[0];
					short sTmp = vShort[0];
					vShort = sTmp;
				}
				
				vshData.Append(vShort);
				nNumRecRead++;
			}
		}
		vInternal = vshData;
		break;
		
	case FSI_USHORT:
		vector<ushort>	vushData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<unsigned short> vUShort(nRecSize/sizeof(ushort));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vUShort);
			if ( status == CDF_OK )
			{
				if ( lDimVary == NOVARY )
				{
					//vUShort = vUShort[0];
					ushort uTmp = vUShort[0];
					vUShort = uTmp;
				}
					
				vushData.Append(vUShort);
				nNumRecRead++;
			}
		}
		vInternal = vushData;
		break;
		
	case FSI_LONG:
		vector<int>		vnData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<int>	vInt(nRecSize/sizeof(int));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vInt);
			if ( status == CDF_OK )
			{
				if ( lDimVary == NOVARY )
				{
					//vInt = vInt[0];
					int nTmp = vInt[0];
					vInt = nTmp;
				}
				
				vnData.Append(vInt);
				nNumRecRead++;
			}
		}
		vInternal = vnData;
		break;
		
	case FSI_ULONG:
		vector<uint>	vunData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<uint>	vUInt(nRecSize/sizeof(uint));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vUInt);
			if ( status == CDF_OK )
			{
				if ( lDimVary == NOVARY )
				{
					//vUInt = vUInt[0];
					uint uTmp = vUInt[0];
					vUInt = uTmp;
				}
				
				vunData.Append(vUInt);
				nNumRecRead++;
			}
		}
		vInternal = vunData;
		break;
		
	case FSI_REAL:
		vector<float>	vfData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<float>	vFloat(nRecSize/sizeof(float));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vFloat);
			if ( status == CDF_OK )
			{
				if ( lDimVary == NOVARY )
				{
					//vFloat = vFloat[0];
					float fTmp = vFloat[0];
					vFloat = fTmp;
				}
				
				vfData.Append(vFloat);
				nNumRecRead++;
			}
		}
		vInternal = vfData;
		break;
		
	case FSI_DOUBLE:
		vector<double>	vData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<double>	vDouble(nRecSize/sizeof(double));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vDouble);
			if ( status == CDF_OK )
			{
				if ( lDimVary == NOVARY )
				{
					//vDouble = vDouble[0];
					double dTmp = vDouble[0];
					vDouble = dTmp;
				}
				
				vData.Append(vDouble);
				nNumRecRead++;
			}
		}
		vInternal = vData;
		break;
	
	///Sophy 7/27/2009 QA80-13988-P2 SUPPORT_IMPORTING_DATE_TIME_DATA_WITH_EPOCH_TYPE
	case FSI_DATE:
		vector<string>	vsData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<double>	vDouble(nRecSize/sizeof(double));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vDouble);
			if ( status == CDF_OK )
			{
				for ( int ii = 0; ii < vDouble.GetSize(); ii++ )
				{
					char epString[EPOCH_STRING_LEN + 1];
					///Sophy 8/10/2009 QA80-13988-P2 FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
					//encodeEPOCH3(vDouble[ii], epString);
					encodeEPOCHx(vDouble[ii], "<yr.02><mm.02><dom.02> <hour.02>:<min.02>:<sec.02>", epString);
					///end FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
					
					string strData(epString);
					vsData.Add(strData);
				}
				
				if ( lDimVary == NOVARY )
				{
					for ( int jj = 1; jj < vsData.GetSize(); jj++ )
						vsData[jj] = vsData[0];
				}
				
				nNumRecRead++;
			}
		}
		///Sophy 8/10/2009 QA80-13988-P2 FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
		//Dataset ds;
		//ds.Attach(col);
		//ds.PutStringArray(vsData);
		
		//col.SetFormat(OKCOLTYPE_DATE);
		col.SetFormat(OKCOLTYPE_DATE);
		col.SetSubFormat(LDF_YYMMDD_AND_HHMMSS_SEPARCOLON); //yyMMdd HH:mm:ss
		col.PutStringArray(vsData);
		///end FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
		
		break;
		
	case FSI_DATE2:
		
		vector<string>	vsData(0);
		for ( iRec = 0; iRec <= nMaxRecNum; iRec++ )
		{
			vector<double>	vDouble(nRecSize/sizeof(double));
			status = CDFgetVarRecordData(m_cdfID, nVarType, varNum, iRec, vDouble);
			if ( status == CDF_OK )
			{
				for ( int ii = 0; ii < vDouble.GetSize(); ii+=2 ) //every EPOCH16 data consists of 16 bytes(two double)
				{
					char epString[EPOCH16_STRING_LEN + 1];
					double *pDouble = &vDouble[ii];
					//since Origin doesn't support format like yyyy-mm-dd HH:MM:SS.Msec.Usec.Nsec.Psec.fos, here treat it like EPOCH type
					///Sophy 8/10/2009 QA80-13988-P2 FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
					//encodeEPOCH16_x(pDouble, "<year>-<month>-<dom> <hour>:<min>:<sec>.<msec>", epString);
					encodeEPOCH16_x(pDouble, "<yr.02><mm.02><dom.02> <hour.02>:<min.02>:<sec.02>", epString);
					///end FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
					
					string strData(epString);
					vsData.Add(strData);
				}
				
				if ( lDimVary == NOVARY )
				{
					for ( int jj = 1; jj < vsData.GetSize(); jj++ )
						vsData[jj] = vsData[0];
				}
				
				nNumRecRead++;
			}
		}
		///Sophy 8/10/2009 QA80-13988-P2 FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
		//Dataset ds;
		//ds.Attach(col);
		//ds.PutStringArray(vsData);
		//
		//col.SetFormat(OKCOLTYPE_DATE);
		col.SetFormat(OKCOLTYPE_DATE);
		col.SetSubFormat(LDF_YYMMDD_AND_HHMMSS_SEPARCOLON); //yyMMdd HH:mm:ss
		col.PutStringArray(vsData);
		///end FIX_TEXT_AND_DATETIME_DATA_DISPLAY_LIKE_NUMERIC_DATA
		break;
	///end SUPPORT_IMPORTING_DATE_TIME_DATA_WITH_EPOCH_TYPE	
	default:
		ASSERT(FALSE);
		return BAD_DATA_TYPE;
	}
	ASSERT(nWrittenRecs == nNumRecRead); //ASSERT(nNumRecRead == nRecs);
	return status;
}

CDFstatus	CDF::getOneMatrix(LPSTR lpcszVar, const int& iRecNum, MatrixLayer& ml, const int nMatObjIndex, const vector<uint>& vnRef, const int& nocType)
{
	CDFstatus status = CDF_OK;
	bool		bZVar;
	TreeNode	trVar = getOneVar(lpcszVar, bZVar);
	int			nVarType = bZVar ? 1 : 0;
	long		lVarNum = CDFgetVarNum(m_cdfID, lpcszVar);
	if ( !trVar || lVarNum < CDF_OK )
		return NO_SUCH_VAR;
	
	vector<uint>	vnDims;
	vnDims = trVar.Dims.nVals;
	if ( vnRef.GetSize() != vnDims.GetSize() - 2 )
		return BAD_DIM_SIZE; //2D matrix dimension check

	long		vlStart[CDF_MAX_DIMS]; //start record indices.
	long		vlCount[CDF_MAX_DIMS]; //count of each dimension
	long		vlIntervals[CDF_MAX_DIMS]; //intervals of each dimension
	int			ii;
	for ( ii = 0; ii < vnRef.GetSize(); ii++ )
	{
		vlStart[ii] = vnRef[ii];
		vlCount[ii] = 1;
		vlIntervals[ii] = 1;
	}
	for ( ; ii < vnDims.GetSize(); ii++ )
	{
		vlStart[ii] = 0;
		vlCount[ii] = vnDims[ii];
		vlIntervals[ii] = 1;
	}
	switch(nocType)
	{
	case FSI_CHAR:
		break; ///Sophy 9/6/2010 ORG-1000 IMPORT_MULTI_DIMS_TEXT_DATA_INTO_WORKSHEET_COLUMN matrix can not be used to put text data.
		Matrix<char> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (char*)mo);
		break;
		
	case FSI_BYTE:
		Matrix<byte> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (byte*)mo);
		break;
		
	case FSI_SHORT:
		Matrix<short> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (short*)mo);
		break;
		
	case FSI_USHORT:
		Matrix<ushort> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (ushort*)mo);
		break;
		
	case FSI_LONG:
		Matrix<int> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (int*)mo);
		break;
		
	case FSI_ULONG:
		Matrix<uint> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (uint*)mo);
		break;
		
	case FSI_REAL:
		Matrix<float> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (float*)mo);
		break;
		
	case FSI_DOUBLE:
		Matrix<double> mo(ml, nMatObjIndex);
		status = CDFhyperGetVarData(m_cdfID, nVarType, lVarNum, iRecNum, 1, 1, vlStart, vlCount, vlIntervals, (double*)mo);
		break;
		
	default:
		ASSERT(FALSE); //should never come here
		status = CDF_WARN;
	}
	//Sophy, need to continue...
	
	return status;
}

int			CDF::calRecordSize(const vector<long>& vDims, const long& lDataType)
{
	int nDims = vDims.GetSize();
	if ( nDims == 0 )
		return getTypeSize(lDataType);

	int	nBufferSize = getTypeSize(lDataType);
	for ( int iDim = 0; iDim < nDims; iDim++ )
	{
		nBufferSize *= vDims[iDim];
	}
	return nBufferSize;
}
	
int			CDF::getTypeSize(long lType)
{
	switch(lType)
	{
	case CDF_INT1:
	case CDF_CHAR:
	case CDF_UCHAR:
	case CDF_BYTE:
	case CDF_UINT1:
		return 1;
		
	case CDF_INT2:
	case CDF_UINT2:
		return 2;
		
	case CDF_INT4:
	case CDF_UINT4:
	case CDF_REAL4:
	case CDF_FLOAT:
		return 4;
		
	case CDF_REAL8:
	case CDF_DOUBLE:
	case CDF_EPOCH:
		return 8;
		
	case CDF_EPOCH16:
		return 16;
		
	default:
		ASSERT(false); //should not come here
	}
	return 0;
}

int			CDF::getOCType(long lType)
{
	switch(lType)
	{
	case CDF_CHAR:
	case CDF_UCHAR:
		return FSI_CHAR;
		
	case CDF_INT1:
	case CDF_BYTE:
	case CDF_UINT1:
		return FSI_BYTE;
		
	case CDF_INT2:
		return FSI_SHORT;
		
	case CDF_UINT2:
		return FSI_USHORT;
		
	case CDF_INT4:
		return FSI_LONG;
		
	case CDF_UINT4:
		return FSI_ULONG;
		
	case CDF_REAL4:
	case CDF_FLOAT:
		return FSI_REAL;
		
	case CDF_REAL8:
	case CDF_DOUBLE:
		return FSI_DOUBLE;
	///Sophy 7/27/2009 QA80-13988-P2 SUPPORT_IMPORTING_DATE_TIME_DATA_WITH_EPOCH_TYPE	
	case CDF_EPOCH:
		return FSI_DATE; //self defined
		
	case CDF_EPOCH16:
		return FSI_DATE2; //self defined
	///end SUPPORT_IMPORTING_DATE_TIME_DATA_WITH_EPOCH_TYPE
	default:
		ASSERT(false); //should not come here
	}
	return -1;
}

LPCSTR		CDF::getTypeName(long lType)
{
	switch(lType)
	{
	case CDF_CHAR:
	case CDF_UCHAR:
		return "char";
		
	case CDF_INT1:
	case CDF_UINT1:
	case CDF_BYTE:
		return "byte";
		
	case CDF_INT2:
		return "short";
	case CDF_UINT2:
		return "unshort";
		
	case CDF_INT4:
		return "int";
		
	case CDF_UINT4:
		return "uint"
		
	case CDF_REAL4:
	case CDF_FLOAT:
		return "float";
		
	case CDF_REAL8:
	case CDF_DOUBLE:
		return "double";
	
	///Sophy 7/27/2009 QA80-13988-P2 SUPPORT_IMPORTING_DATE_TIME_DATA_WITH_EPOCH_TYPE
	case CDF_EPOCH:
		return "epoch"
		
	case CDF_EPOCH16:
		return "epoch16";
	///end SUPPORT_IMPORTING_DATE_TIME_DATA_WITH_EPOCH_TYPE	
	default:
		ASSERT(false); //need to check more type
	}
	return "Unknown";
}

///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
bool		CDF::updateUserTree(OriginObject& obj, LPCSTR lpcszVar, LPCSTR lpcszLabel)
{
	bool bZVar;
	TreeNode trVar = getOneVar(lpcszVar, bZVar);
	if ( !obj || !trVar )
		return false;
	
	TreeNode trVarCopy = trVar.Clone(true);
	filterOneVar(trVarCopy);
	SET_LABEL(trVarCopy, lpcszLabel);
	
	string strInfo(lpcszLabel);
	
	///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
	//return set_user_info(obj, strInfo, trVarCopy);
	///---Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	//trVarCopy.Show = 0;
	//bool bRet = set_user_info(obj, strInfo, trVarCopy);
	bool bRet = fu_set_import_file_info(obj, trVarCopy, strInfo, IMPORT_INFO_TO_USER_TREE);
	///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	///---Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	// roll back move column info out of user tree, as CP said
	//trVarCopy.Show = 1;
	//strInfo = lpcszLabel;
	//strInfo.Insert(0, "CDF ");
	//SET_LABEL(trVarCopy, strInfo);
	//bRet &= set_import_file_info(obj, trVarCopy, strInfo);
	///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
	
	return bRet;
	///---END QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
}
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

#endif	//_CDF_MANAGER_H_
