/*------------------------------------------------------------------------------*
 * File Name:	HDF5Manager.h			 										*
 * Creation: 																	*
 * Purpose: OriginC Header file													*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER				*
 *	Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
 *	Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
 *	Sophy 9/28/2009 QA80-14370 FAIL_TO_IMPORT_HDF5_FILE_IN_VISTA_WHEN_FREE_CAUSE_INTERNAL_EXCEPTION
 *	Sophy 11/16/2009 QA80-13130-P9 WRONG_COLUMN_FORMAT_CAUSE_DATA_LOST_WHEN_SAVE_OR_APPEND_NEW_COLUMNS
 *	Sophy 11/16/2009 QA80-13130-P8 MORE_WORK_ON_HANDLE_HDF5_TYPES
 *	Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST*
 *	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			*
 *	Sophy 2/10/2010 SHOULD_NOT_LIMIT_STRING_DISPLAY_LENGTH_ON_DISPLAY_ATTRIBUTES*
 *------------------------------------------------------------------------------*/
#include "OCHDF5.h"

#define	STR_GROUP				"Group"
#define	STR_DATASET				"Dataset"
///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
#define	STR_LINK_OBJ_NAME		"LinkObjName"
#define	STR_LINK_OBJ_TYPE		"LinkObjType"
#define	STR_LINK				"Link"
#define	STR_DATATYPE			"DataType"
#define	STR_SIZE				"Size"
#define	STR_TYPE_CLASS			"Class"
///end IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
#define	STR_ENUM_NAMES			"EnumNames"
#define	STR_ENUM_VALUES			"EnumValues"
#define	STR_TAG_ATTRIB			"Tag"
#define	STR_NAME				"Name"
#define	STR_TYPE				"Type"
#define	STR_OC_TYPE				"OCType"
#define	STR_TAGNAME_FORMAT		"%s%d"
//group attribute
#define	STR_SUB_GROUPS			"SubGroups"
#define	STR_SUB_DATASETS		"SubDatasets"
//dataset attribute
#define	STR_DATASET_MEMBERS		"Members"	//for compound dataset
#define	STR_DATASET_SCOPE		"Columns"	//number of columns needed to put an element of a compound type
#define	STR_DATASET_MEMBER_FMT	"Member%d"
#define	STR_OBJ_ATTTRIBS		"ObjAttribs"
#define	STR_DESCRIPTION			"HDF4_SDS_DESC_0"
#define	STR_DATASET_DIMS		"Dims"
#define	STR_UINTS				"Units"
#define	STR_LONGNAME			"Long_Name"

#define	STR_VL_STR				"VL_String" //attribute to indicate whether a dataset is VL string type
#define	VL_STRING_TYPE			0x0001	//bits to indicate it is VL string

#define	STR_IMAGECLASS			"IMAGE"	///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
#define	STR_PALETTECLASS		"PALETTE" ///Sophy 9/24/2009 IMPORT_PALETTE_INTO_WORKSHEET
//OC type
#define	STR_OCTYPE_CHAR			"char"
#define	STR_OCTYPE_STRING		"string"
#define	STR_OCTYPE_SHORT		"short"
#define	STR_OCTYPE_INT			"int"
#define	STR_OCTYPE_LONG			"long"
#define	STR_OCTYPE_FLOAT		"float"
#define	STR_OCTYPE_DOUBLE		"double"
#define	STR_OCTYPE_STRUCT		"struct"
#define	STR_OCTYPE_ARRAY		"array"
#define	STR_OCTYPE_VLEN			"vlen"
#define	STR_OCTYPE_ENUM			"enum"
#define	STR_OCTYPE_BITFIELD		"biffield"
#define	STR_OCTYPE_OPAQUE		"opaque"
#define	STR_OCTYPE_REFER		"reference"
#define	STR_OCTYPE_UNKNOWN		"unknown"

//GUI tree relative
//#define	STR_DATASET_1D			"Data1D"
//#define	STR_DATASET_2D			"Data2D"
//#define	STR_DATASET_3D			"Data3D"
//#define	STR_DATASET_4D			"Data4D"
#define	STR_FIELD_CMT_FMT			"Member of \"%s\""
#define	STR_DATASET_XD_FORMAT		"Data%dD"
#define	STR_XD_DATASETS				"%dD Datasets"
#define	STR_DATASET_IMAGES			"Images"	///Sophy 7/24/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
#define	_SUPPORT_NESTED_STRUCT_					///Sophy 7/31/2009 SUPPORT_ONE_LEVEL_NESTED_COMPOUND_DATATYPE
///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
#define	STR_DIMS_SEP				", "
///Sophy 10/23/2009 IMPROVE_VALUE_SEP_FOR_DISPLAY_IN_GOS		
//#define	CHAR_VALUE_SEP				','
#define	CHAR_VALUE_SEP				( (NF_IS_EUROPEAN == okutil_get_numeric_format()) ? '.' : ',')
///end IMPROVE_VALUE_SEP_FOR_DISPLAY_IN_GOS
#define	STR_DIMS_INFO				"Dimension Size"
#define	STR_DATASET_DATATYPE		"Data Type"
#define	STR_IMAGE_INFO				"Image Information"
#define	STR_ARRAY_INFO				"Array Information"
#define	STR_DATASET_INFO			"Dataset Information"
#define	STR_ATTRIBUTES				"Attributes"
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

enum HDFstatus {
	HDF_FAIL = -1,
	HDF_SUCCESS = 0,
};

//ext FSI_
enum {
	FSI_EXT_BEGIN = FSI_COMPLEX + 1,
	FSI_BIT_8,
	FSI_BIT_16,
	FSI_BIT_32,
	FSI_BIT_64,
	FSI_INT64,
	FSI_ENUM,
	FSI_OPAQUE,
	FSI_REFERENCE,
	FSI_VLEN,
	FSI_ARRAY,
};

#define	SET_LABEL(_Node, _Label)	(_Node.SetAttribute(STR_LABEL_ATTRIB, _Label))
#define	GET_LABEL(_Node, _Label)	(_Node.GetAttribute(STR_LABEL_ATTRIB, _Label))
#define	SET_SIZE(_Node, _Size)		(_Node.SetAttribute(STR_SIZE, _Size))
#define	GET_SIZE(_Node, _Size)		(_Node.GetAttribute(STR_SIZE, _Size))
#define	AUTO_DATAID(_Node)			(_Node.DataID = m_nNodeID++)
#define	SET_NODEID(_Node, _ID)		(_Node.ID = _ID)	//for insert information variable, stands for datatype
///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
#define	CHAR_DATASET_PATH_SEP		'/'
enum {
	IMP_USE_SOURCE_CATEGORY_INFO = 0x0001,
};
///end IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
///Sophy 9/24/2009 IMPORT_VL_STRING_INTO_NOTE_WINDOW
#define	STR_TEMP_VL_STR_FILENAME	(GetAppPath(TRUE) + "ORIGIN_HDF5_TEMP_VLSTR.txt")
///end IMPORT_VL_STRING_INTO_NOTE_WINDOW
///Sophy 8/20/2009 IMPORT_IMAGE_DATA_INTO_MATRIXOBJECT
#define	STR_TEMP_BITMAP_FILENAME	(GetAppPath(TRUE) + "ORIGIN_HDF5_TEMP_BITMAP.bmp")
#pragma pack(push, 1)

//for image
//bitmap file info data
//bitmap file header
typedef struct tagBMPHEADER {
 	WORD	wFlags;	//"BM" //0x4D42
 	DWORD	dwFileSize;	//file size;
 	WORD	wReserved1;	//0
 	WORD	wReserved2;	//0
 	DWORD	dwDataOffset;	//the dataoffset
}BITMAPHEADER, *pBITMAPHEADER;

//bitmap info header
typedef struct tagBMPINFOHEADER {
 	DWORD	dwInfoSize;	//when is 40
 	LONG	nWidth;		//image width
 	LONG	nHeight;	//image height
 	WORD	nPlanes;	//number of planes, must be 1
 	WORD	nBitPerPixel;	//1, 2, 4, 8, 24
 	DWORD	dwCompression;	//compression type 0-3
 	DWORD	dwDataSize;		//data size of the image
 	LONG	nXPixelPerMeter; //0
 	LONG	nYPixelPerMeter; //0
 	DWORD	dwColorsUsed;	//number of colors used, 0 for 24 bits bitmap, or 2^nBitPerPixel
 	DWORD	dwColorsImportant; //when system color number < dwColorsUsed
}BMPINFO, *pBMPINFO;

#pragma pack(pop)
///end IMPORT_IMAGE_DATA_INTO_MATRIXOBJECT

//this method is used to free memory allocated outside Origin.
static void _safe_free(void* lpBuffer)
{
	try
	{
		free(lpBuffer);
	}
	catch(int nErr)
	{
		//ignore any exception when free memory allocated outside Origin.
	}
}
static string _get_dataset_name(LPCSTR lpcszFullPath)
{
	string strDatasetName(lpcszFullPath);
	vector<string> vsPath;
	strDatasetName.GetTokens(vsPath, CHAR_DATASET_PATH_SEP);
	return vsPath[vsPath.GetSize() - 1];
}
//Sophy, this two util can only be used in hdf5 class, usually they are used in pair
//it is a walk-around when converting between __int64 and int, should be cleaned when vector<__int64> supported
static void _hdf_convert_double_to_uint(double& dVal, uint& nVal)
{
	uint value[2];
	memcpy(value, &dVal, sizeof(double));
	nVal = value[0]; //only retrieve the low dword
}
static void _hdf_convert_uint_to_double(uint& nVal, double& dVal)
{
	uint value[2];
	value[1] = 0; //set high dword as zero
	value[0] = nVal;
	memcpy(&dVal, value, sizeof(double));
}

static void _hdf_convert_double_to_int(double& dVal, int& nVal)
{
	int value[2];
	memcpy(value, &dVal, sizeof(double));
	nVal = value[0];
}

static void _hdf_int64_vector_to_string_vector(double* pBuffer, int nSize, vector<string>& vs)
{
	vs.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
	{
		int nVal;
		_hdf_convert_double_to_int(pBuffer[ii], nVal);
		vs[ii] = nVal;
	}
}

static void _hdf_convert_dvec_to_ivec(vector<double>& vec, vector<uint>& vn)
{
	int nSize = vec.GetSize();
	vn.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
		_hdf_convert_double_to_uint(vec[ii], vn[ii]);
}

static void _hdf_convert_ivec_to_dvec(vector<uint>& vn, vector<double>& vec)
{
	int nSize = vn.GetSize();
	vec.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
		_hdf_convert_uint_to_double(vn[ii], vec[ii]);
}

static void _convert_byte_vector_to_string_vector(vector<byte>& vb, vector<string>& vs, bool bHex = true)
{
	LPCSTR lp = "%d";
	if ( bHex )
		lp = "0x%02X";
	
	char cBuffer[10];
	int nSize = vb.GetSize();
	vs.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
	{
		sprintf(cBuffer, lp, vb[ii]);
		vs[ii] = cBuffer;
	}
	return;
}

static void _convert_short_vector_to_string_vector(vector<short>& vst, vector<string>& vs, bool bHex = true)
{
	LPCSTR lp = "%d";
	if ( bHex )
		lp = "0x%04X";
	
	char cBuffer[10];
	int nSize = vst.GetSize();
	vs.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
	{
		sprintf(cBuffer, lp, vst[ii]);
		vs[ii] = cBuffer;
	}
}

static void _convert_int_vector_to_string_vector(vector<int>& vn, vector<string>& vs, bool bHex = true)
{
	LPCSTR lp = "%d";
	if ( bHex )
		lp = "0x%08X";
	
	char cBuffer[12];
	int nSize = vn.GetSize();
	vs.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
	{
		sprintf(cBuffer, lp, vn[ii]);
		vs[ii] = cBuffer;
	}
}

static void _convert_float_vector_to_string_vector(vector<float>& vf, vector<string>& vs, LPCSTR lpFMT = "%.2lf")
{
	int nSize = vf.GetSize();
	vs.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
	{
		vs[ii] = ftoa(vf[ii], lpFMT);
	}
}
static void _convert_int64_vector_to_string_vector(vector<double>& vint64, vector<string>& vs, bool bHex = true)
{
	LPCSTR lp = "%ld";
	if ( bHex )
		lp = "0x%16X";
	
	char cBuffer[20];
	int nSize = vint64.GetSize();
	vs.SetSize(nSize);
	for ( int ii = 0; ii < nSize; ii++ )
	{
		sprintf(cBuffer, lp, vint64[ii]);
		vs[ii] = cBuffer;
	}
}

static bool _is_numeric_column(int nType)
{
	if ( nType == FSI_SHORT || nType == FSI_LONG || nType == FSI_REAL || nType == FSI_DOUBLE )
		return true;
	return false;
}

static int _convert_BE_LE(void* pVal, int nSize)
{
	vector<byte> vbBuffer(sizeof(int));
	memcpy(vbBuffer, pVal, sizeof(int));
	
	int nHalf = nSize / 2;
	byte bt;
	for ( int ii = 0; ii < nHalf; ii++ )
	{
	   bt = vbBuffer[ii];
	   vbBuffer[ii] = vbBuffer[nSize - 1 - ii];
	   vbBuffer[nSize - 1 - ii] = bt;
	}
	int nRet;
	memcpy(&nRet, vbBuffer, nSize);
	return nRet;
}
//recursively get compound type info, return column scope, minus for error.
#define	AUTO_INCRE_ID(_Node)	(_Node.ID = nStartID++)
static int _construct_compound_type_info(hid_t hSpace, hid_t hDataType, TreeNode& trParent, int& nStartID)
{
	if ( !trParent || hDataType <= 0 )
		return -1;
	
	H5T_class_t tClass = H5Tget_class(hDataType);
	TreeNode trOCType = tree_check_get_node(trParent, STR_OC_TYPE);
	size_t nTypeSize = H5Tget_size(hDataType);
	SET_SIZE(trOCType, nTypeSize);
	SET_LABEL(trOCType, STR_DATASET_DATATYPE);
	AUTO_INCRE_ID(trOCType);
	
	int nColumns = 0; //to calculate how many columns needed to put a element of the compound type, say {int, double, double[4], short} will need 1 + 1 + 4 + 1 = 7 columns
	
	if ( H5T_INTEGER == tClass )
	{
		trOCType.strVal = STR_OCTYPE_INT;
		nColumns = 1;
	}
	else if ( H5T_FLOAT == tClass )
	{
		hid_t hNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
		if ( H5Tequal(hNativeType, H5T_NATIVE_FLOAT) )
			trOCType.strVal = STR_OCTYPE_FLOAT;
		else if ( H5Tequal(hNativeType, H5T_NATIVE_DOUBLE) )
			trOCType.strVal = STR_OCTYPE_DOUBLE;
		else if ( H5Tequal(hNativeType, H5T_NATIVE_LDOUBLE) )
			trOCType.strVal = "long double"; //not supported
		else
			ASSERT(FALSE); //sophy, need to add more cases.
		
		nColumns = 1;
		H5Tclose(hNativeType);
	}
	else if ( H5T_STRING == tClass )
	{
		trOCType.strVal = STR_OCTYPE_STRING;
		nColumns = 1;
		if ( H5Tis_variable_str(hSpace) )
			trParent.SetAttribute(STR_VL_STR, VL_STRING_TYPE);
	}
	else if ( H5T_ARRAY == tClass )
	{
		hid_t hSuper = H5Tget_super(hDataType);
		string strType;
		if ( H5Tequal(hSuper, H5T_NATIVE_INT) )
			strType = STR_OCTYPE_INT;
		else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
			strType = STR_OCTYPE_FLOAT;
		else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
			strType = STR_OCTYPE_DOUBLE;
		else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
			strType = STR_OCTYPE_SHORT;
		else if ( H5Tequal(hSuper, H5T_NATIVE_LONG) )
			strType = STR_OCTYPE_LONG;
		else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
			strType = STR_OCTYPE_CHAR;
		else
			ASSERT(FALSE); //need to add more cases if come here
		
		H5Tclose(hSuper);
		trOCType.SetAttribute(STR_OC_TYPE, strType);
		trOCType.strVal = STR_OCTYPE_ARRAY;
		
		int nDims = H5Tget_array_ndims(hDataType);
		vector<hsize_t> vshDims(nDims);
		H5Tget_array_dims2(hDataType, vshDims);
		vector<uint> vnDims;
		_hdf_convert_dvec_to_ivec(vshDims, vnDims);
		TreeNode trDims = tree_check_get_node(trParent, STR_DATASET_DIMS);
		AUTO_INCRE_ID(trDims);
		SET_LABEL(trDims, STR_DIMS_INFO);
		trDims.nVals = vnDims;

		nColumns = 1; //put in single column
	}
	else if ( H5T_BITFIELD == tClass )
	{
		string strType = STR_OCTYPE_BITFIELD;
		int nFSIType = FSI_LONG;
		if ( nTypeSize == 1 )
		{
			strType = STR_OCTYPE_CHAR;
			nFSIType = FSI_BYTE;
		}
		else if ( nTypeSize == 2 )
		{
			strType = STR_OCTYPE_SHORT;
			nFSIType = FSI_SHORT;
		}
		else if ( nTypeSize == 4 )
		{
			strType = STR_OCTYPE_INT;
			nFSIType = FSI_LONG;
		}
		else if ( nTypeSize == 8 )
		{
			strType = STR_OCTYPE_DOUBLE;
			nFSIType = FSI_DOUBLE;
		}
		else
		{
			ASSERT(FALSE);
		}
		trOCType.SetAttribute(STR_OC_TYPE, STR_OCTYPE_BITFIELD);
		trOCType.SetAttribute(STR_TYPE, nFSIType);
		trOCType.strVal = strType;
		nColumns = 1;
	}
	else if ( H5T_ENUM == tClass )
	{
		trOCType.strVal = STR_OCTYPE_ENUM;
		nColumns = 1;
	}
	else if ( H5T_OPAQUE == tClass )
	{
		trOCType.strVal = STR_OCTYPE_OPAQUE;
		nColumns = 1;
	}
	else if ( H5T_REFERENCE == tClass )
	{
		trOCType.strVal = STR_OCTYPE_REFER;
		nColumns = 1;
	}
	else if ( H5T_VLEN == tClass )
	{
		trOCType.strVal = STR_OCTYPE_VLEN;
		nColumns = 1;
	}
	else if ( H5T_COMPOUND == tClass )
	{
		trOCType.strVal = STR_OCTYPE_STRUCT;
		TreeNode trMembers = tree_check_get_node(trParent, STR_DATASET_MEMBERS);
		trMembers.SetAttribute(STR_OC_TYPE, STR_OCTYPE_STRUCT);
		AUTO_INCRE_ID(trMembers);
		
		int nMems = H5Tget_nmembers(hDataType);
		trParent.SetAttribute(STR_DATASET_MEMBERS, nMems);
		for ( uint iM = 0; iM < nMems; iM++ )
		{
			string strOneMem;
			strOneMem.Format(STR_DATASET_MEMBER_FMT, iM);
			TreeNode trMem = tree_check_get_node(trMembers, strOneMem);
			AUTO_INCRE_ID(trMem);
			
			char* name = H5Tget_member_name(hDataType, iM);
			string strMemName(name);
			SET_LABEL(trMem, strMemName);

			_safe_free(name);
			
			TreeNode trType = tree_check_get_node(trMem, STR_OC_TYPE);
			SET_LABEL(trType, STR_DATASET_DATATYPE);
			AUTO_INCRE_ID(trType);
			
			hid_t memType = H5Tget_member_type(hDataType, iM);
			size_t nMemTypeSize = H5Tget_size(memType);
			SET_SIZE(trType, nMemTypeSize);
			tClass = H5Tget_class(memType);
			string strType = "";
			if ( H5T_ARRAY == tClass )
			{
				hid_t hSuper = H5Tget_super(memType);
				if ( H5Tequal(hSuper, H5T_NATIVE_INT) )
					strType = STR_OCTYPE_INT;
				else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
					strType = STR_OCTYPE_FLOAT;
				else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
					strType = STR_OCTYPE_DOUBLE;
				else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
					strType = STR_OCTYPE_SHORT;
				else if ( H5Tequal(hSuper, H5T_NATIVE_LONG) )
					strType = STR_OCTYPE_LONG;
				else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
					strType = STR_OCTYPE_CHAR;
				else
					ASSERT(FALSE); //need to add more cases if come here
				
				H5Tclose(hSuper);
				trType.SetAttribute(STR_OC_TYPE, strType);
				strType = STR_OCTYPE_ARRAY;
				
				int nDims = H5Tget_array_ndims(memType);
				vector<hsize_t> vshDims(nDims);
				H5Tget_array_dims2(memType, vshDims);
				vector<uint> vnDims;
				_hdf_convert_dvec_to_ivec(vshDims, vnDims);
				TreeNode trDims = tree_check_get_node(trMem, STR_DATASET_DIMS);
				AUTO_INCRE_ID(trDims);
				SET_LABEL(trDims, STR_DIMS_INFO);
				trDims.nVals = vnDims;
				

				nColumns++; //put array in compound type in one column
				
			}
			else if ( H5T_COMPOUND == tClass )
			{
				strType = STR_OCTYPE_STRUCT;
				trMem.SetAttribute(STR_OC_TYPE, STR_OCTYPE_STRUCT);
				int nCols = _construct_compound_type_info(hSpace, memType, trMem, nStartID);
				if ( nCols > 0 )
					nColumns += nCols;
			}
			else
			{
				hid_t hNative = H5Tget_native_type(memType, H5T_DIR_DEFAULT);
				if ( H5Tequal(hNative, H5T_NATIVE_INT) )
					strType = STR_OCTYPE_INT;
				else if ( H5Tequal(hNative, H5T_NATIVE_FLOAT) )
					strType = STR_OCTYPE_FLOAT;
				else if ( H5Tequal(hNative, H5T_NATIVE_DOUBLE) )
					strType = STR_OCTYPE_DOUBLE;
				else if ( H5Tequal(hNative, H5T_NATIVE_LONG) )
					strType = STR_OCTYPE_LONG;
				else if ( H5Tequal(hNative, H5T_NATIVE_SHORT) )
					strType = STR_OCTYPE_SHORT;
				else if ( H5Tequal(hNative, H5T_STRING) )
					strType = STR_OCTYPE_CHAR;
				else
					ASSERT(FALSE); //need to add more cases.
				
				nColumns++; //atom type
				H5Tclose(hNative);
			}
			trType.strVal = strType;
			H5Tclose(memType);
		}
	}

	else
		ASSERT(FALSE); //sophy, need to add more cases.
	
	trParent.SetAttribute(STR_DATASET_SCOPE, nColumns);
	
	return nColumns;

}
class HDF5
{
public:
	HDF5(){}
	~HDF5(){ if ( m_hdfID ) Close(); }
	
	HDFstatus	Open(LPCSTR lpcszFileName);
	HDFstatus	Close();
	
	HDFstatus	GetDatasetsInfo(TreeNode& trInfo); //retrieve all datasets info, for GUI
	HDFstatus	GetOneDatasetInfo(LPCSTR lpcszDataName, vector<uint>& vnDims, int* pnDataType = NULL, string* pstrUnits = NULL, string* pstrLongName = NULL, string* pstrComments = NULL, int* pnAux = NULL); //maybe need to add more params
	
	//import data to Workbook/Matrixbook
	HDFstatus	ImportOneDCol(LPCSTR lpcszDataName, Worksheet& wks, int iCol); //import 1D dataset
	HDFstatus	ImportXDMat(LPCSTR lpcszDataName, MatrixLayer& ml); //import 2D dataset or dataset that can be converted to 2D data
	HDFstatus	ImportImage(LPCSTR lpcszDataName, MatrixLayer& ml); ///Sophy 7/24/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	HDFstatus	ImportPalette(LPCSTR lpcszDataName, Worksheet& wks); ///Sophy 9/24/2009 IMPORT_PALETTE_INTO_WORKSHEET
	///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
	HDFstatus	ImportOneFile(const TreeNode& trGUISetting, DWORD dwOption = IMP_USE_SOURCE_CATEGORY_INFO);
	HDFstatus	GetFileStruct(TreeNode& trFileStruct);
	///end IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY

	///Sophy 8/20/2009 IMPORT_IMAGE_DATA_INTO_MATRIXOBJECT
protected:
	HDFstatus	SaveAs(LPCSTR lpcszFile, LONG nWidth, LONG nHeight, byte* pRGB, int nBufferSize, DWORD dwCtrl = 0);
	///end IMPORT_IMAGE_DATA_INTO_MATRIXOBJECT
private:
	HDFstatus	constructDatasetFromGroup(hid_t groupID, TreeNode& trParent, int nSubIndex); //recursively get dataset infos from file
	HDFstatus	addOneDataset(hid_t DatasetID, TreeNode& trParent, int nSubIndex); //add one dataset to treenode
	///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
	HDFstatus	addOneDataType(hid_t groupID, TreeNode& trParent, LPCSTR lpcszTypeName, int nSubIndex);
	HDFstatus	addOneLink(hid_t groupID, TreeNode& trParent, LPCSTR lpcszLinkName, int nSubIndex);
	///end IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
	HDFstatus	addDimInfo(hid_t DatasetID, TreeNode& trDataset);
	HDFstatus	addTypeInfo(hid_t DatasetID, TreeNode& trDataset);
	HDFstatus	addOneAttrib(int nAttIndex, hid_t DatasetID, TreeNode& trParent); //add attributes to the treenode
	bool		checkValidFile(LPCSTR lpcszFileName);
	bool		checkIsOneD(const vector<uint>& vnDims);
	bool		filterDataset(TreeNode& trDataset, bool bRemoveAttribs =  true, bool bRemoveMembers = true); //trim useless nodes
	///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	bool		filterGroup(TreeNode& trGroup);
	bool		filterFileStruct(TreeNode& trFileStruct);
	bool		filterAttribs(TreeNode& trAttribs);
	TreeNode	getDatasetInfo(const TreeNode& trDataset); 
	bool		updateUserTree(OriginObject& obj, LPCSTR lpcszDatasetName, LPCSTR lpcszLabel);
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	bool		isImageType(LPCSTR lpcszDataset);///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	bool		isPaletteType(LPCSTR lpcszDataset); ///Sophy 9/24/2009 IMPORT_PALETTE_INTO_WORKSHEET
	bool		checkClassName(LPCSTR lpcszDataset, LPCSTR lpcszClass); //just centralize code
	herr_t		findAttribute(hid_t DatasetID, LPCSTR lpcszAttName);
	herr_t		findPalette(hid_t DatasetID);

	///Sophy 7/24/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	HDFstatus	getImageInfo(LPCSTR lpcszDataName, uint& nWidth, uint& nHeight, uint& nPlanes, char* interlace, uint& nPals);
	///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	//import one dataset's data into a column
	HDFstatus	getOneVector(LPCSTR lpcszDataName, Column& col);
	//import one compound type into multi-columns
	HDFstatus	getXDMultiVector(LPCSTR lpcszDataName, Worksheet& wks, int iStartCol, const vector<uint>& vnDims, vector<uint>& vnRef, int nDepth);
	HDFstatus	getMultiVector(LPCSTR lpcszDataName, Worksheet& wks, int iStartCol, const vector<uint>& vnDims, vector<uint>& vnRef);
	//recursively break XD data into multiple 2D matrix, when vnRef is ready(with nDepth = vnRef.GetSize() - 1), call getOneMatrix
	HDFstatus	getXDMatrixes(LPCSTR lpcszDataName, MatrixLayer& ml, const vector<uint>& vnDims, vector<uint>& vnRef, int nDepth);
	//fill a 2D matrix with specified data from a dataset
	HDFstatus	getOneMatrix(LPCSTR lpcszDataName, MatrixLayer& ml, int iMatObj, const vector<uint>& vnRef);
	///Sophy 9/24/2009 IMPORT_VL_STRING_INTO_NOTE_WINDOW
	HDFstatus	getOneNote(LPCSTR lpcszDataName); //VL string should put in notes window, like HDFView
	///end IMPORT_VL_STRING_INTO_NOTE_WINDOW
	//get a 2D matrix from multi-dimension array with offset and interval settings
	HDFstatus	getOneRegion(const vector<uint>& vnDims, const vector<uint>& vnRef, vector<hsize_t>& vStart, vector<hsize_t>& vStride, vector<hsize_t>& vCount, vector<hsize_t>& vBlock);
	HDFstatus	getDatasetsOneGroup(TreeNode& trGroup, TreeNode& trInfo); //clone datasets in trGroup to trInfo
	int			getDatasetDims(TreeNode& trDataset); //get number of dims
	int			getDataType(TreeNode& trDataset); //get internal datatype, int, double...
	int			getDataType(LPCSTR lpcszTypeName); //from string to enum
	
private:
	hid_t	m_hdfID;
	Tree	m_trInfo;
	string	m_strFileName;	///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
	int		m_nNodeID;
};

HDFstatus	HDF5::Open(LPCSTR lpcszFileName)
{
	if ( !checkValidFile(lpcszFileName) )
		return HDF_FAIL;

	Close(); //in case already open some file, close it first.
	
	m_hdfID = H5Fopen(lpcszFileName, H5F_ACC_RDONLY, H5P_DEFAULT);
	if ( m_hdfID < 0 )
		return HDF_FAIL;
	
	m_strFileName = lpcszFileName;	///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
	m_nNodeID = 2008;

	hid_t hRoot = H5Gopen1(m_hdfID, "/");
	HDFstatus status = constructDatasetFromGroup(hRoot, m_trInfo, -1);
	H5Gclose(hRoot);
	return status;
}

HDFstatus	HDF5::Close()
{
	//delete temporary files
	DeleteFile(STR_TEMP_VL_STR_FILENAME);
	DeleteFile(STR_TEMP_BITMAP_FILENAME);
	if ( H5Fclose(m_hdfID) < 0 )
		return HDF_FAIL;
	
	m_hdfID = 0; //reset
	return HDF_SUCCESS;
}

HDFstatus	HDF5::GetDatasetsInfo(TreeNode& trInfo)
{
	if ( !trInfo )
		return HDF_FAIL;
	
	TreeNode trGroup = m_trInfo.GetNode(STR_GROUP);//get from the root and recursively visit all nodes
	return getDatasetsOneGroup(trGroup, trInfo);
}

HDFstatus	HDF5::GetOneDatasetInfo(LPCSTR lpcszDataName, vector<uint>& vnDims, int* pnDataType, string* pstrUnits, string* pstrLongName, string* pstrComments, int* pnAux) //NULL, NULL, NULL, NULL
{
	TreeNode trDataset = m_trInfo.FindNodeByAttribute(STR_NAME, lpcszDataName, true); //recursively search
	if ( !trDataset )
		return HDF_FAIL;
	
	TreeNode trDims = trDataset.GetNode(STR_DATASET_DIMS, false);
	if ( !trDims )
		return HDF_FAIL;
	
	vnDims = trDims.nVals;
	if ( pnDataType )
		*pnDataType = getDataType(trDataset);
	
	if ( pstrUnits && trDataset.units )
		*pstrUnits = trDataset.units.strVal;
	
	if ( pstrLongName && trDataset.long_name )
		*pstrLongName = trDataset.long_name.strVal;
	
	if ( pstrComments )
	{
		TreeNode trDescript = trDataset.GetNode(STR_DESCRIPTION, false);
		if ( trDescript )
			*pstrComments = trDescript.strVal;
		else
		{
			*pstrComments = lpcszDataName;
		}
	}
	
	if ( pnAux )
	{
		int nVLType = 0;
		trDataset.GetAttribute(STR_VL_STR, nVLType);
		*pnAux = nVLType;
	}
	
	return HDF_SUCCESS;
}

HDFstatus	HDF5::ImportOneDCol(LPCSTR lpcszDataName, Worksheet& wks, int iCol)
{
	if ( !wks )
		return HDF_FAIL;
	
	int nType;
	vector<uint>	vnDims;
	string strUnits, strLongName, strComments;
	HDFstatus status = GetOneDatasetInfo(lpcszDataName, vnDims, &nType, &strUnits, &strLongName, &strComments);
	if ( !checkIsOneD(vnDims) && nType != FSI_MIXED ) //if not 1D data or multi-D of struct type, return error
		return HDF_FAIL; //can't import data into column with dimension more than 1.
	
	if ( FSI_MIXED == nType ) //compound type, create new worksheet and import to multi-columns
	{
		int nWksIndex =  wks.GetPage().AddLayer();
		ASSERT(nWksIndex >= 0);
		if ( nWksIndex < 0 )
			return HDF_FAIL;
		
		Worksheet wksNew = wks.GetPage().Layers(nWksIndex);
		vector<uint> vnRef(vnDims.GetSize());
		status = getXDMultiVector(lpcszDataName, wksNew, 0, vnDims, vnRef, 0); //from first column
		if ( status == HDF_SUCCESS )
			wksNew.SetName(lpcszDataName)
	}
	else
	{
		if ( wks.GetNumCols() <= iCol )
			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 ( FSI_CHAR != nType && FSI_ENUM != nType ) //not struct and not string and not enum
		{
			col.SetFormat(OKCOLTYPE_NUMERIC);
			col.SetInternalDataType(nType);
		}
		///end UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
		status = getOneVector(lpcszDataName, col);
		
		col.SetUnits(strUnits);
		col.SetLongName(strLongName);
		col.SetComments(strComments);//make dataset name as comments.
	}
	return status;
}

HDFstatus	HDF5::ImportXDMat(LPCSTR lpcszDataName, MatrixLayer& ml)
{
	if ( !lpcszDataName || *lpcszDataName == '\0' || !ml )
		return HDF_FAIL;
	
	///Sophy 7/24/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	if ( isImageType(lpcszDataName) ) //if is image, keep its integrity
	{
		if ( ImportImage(lpcszDataName, ml)  == HDF_SUCCESS ) //if fail, continue to import data as normal matrixes
			return HDF_SUCCESS;
	}
	///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	vector<uint>	vnDims;
	HDFstatus status = GetOneDatasetInfo(lpcszDataName, vnDims);
	if ( status != HDF_SUCCESS || checkIsOneD(vnDims) )
	{
		printf("Can not find dataset or it's 1D and should import it into worksheet!");
		return HDF_FAIL;
	}
	
	int nDims = vnDims.GetSize();
	vector<uint> vnRef;
	int nRefSize = nDims - 2;
	vnRef.SetSize(nRefSize);
	
	int nMatObjs = 1; //calculate the number of matrix objects needed.
	for ( int ii = 0; ii < nRefSize; ii++ )
		nMatObjs *= vnDims[ii];
	
	ml.SetSize(nMatObjs, vnDims[nDims - 2], vnDims[nDims - 1]);
	status = getXDMatrixes(lpcszDataName, ml, vnDims, vnRef, 0);
	
	updateUserTree(ml, lpcszDataName, STR_ARRAY_INFO);	///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER

	return status;
}

///Sophy 7/24/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
HDFstatus	HDF5::ImportImage(LPCSTR lpcszDataName, MatrixLayer& ml)
{
	if ( !ml )
		return HDF_FAIL;
	
	HDFstatus status = HDF_FAIL;
	uint nWidth = 0, nHeight = 0, nPlanes = 0, nPals = 0;
	char interlace[100];
	status = getImageInfo(lpcszDataName, nWidth, nHeight, nPlanes, interlace, nPals);
	//to do...
	ml.SetInternalDataType(FSI_LONG);
	hid_t dsID = H5Dopen1(m_hdfID, lpcszDataName);
	
	vector<byte> vnImageData; //buffer to store 24bits image data
	int nJunks = 0;
	while ( ( nJunks + nWidth * 3) % 4 != 0 )
		nJunks++;
	vnImageData.SetSize(nHeight * (nJunks + nWidth * 3));

	if ( nPals != 0 ) //indexed image
	{
		//read palette data
		hid_t attID = H5Aopen(dsID, "PALETTE", H5P_DEFAULT);
		hid_t attSID = H5Aget_space(attID);
		hid_t attTID = H5Aget_type(attID);
		
		
		int nDims = H5Sget_simple_extent_ndims(attSID);
		vector<hsize_t> vshAttDims(nDims);
		H5Sget_simple_extent_dims(attSID, vshAttDims, NULL);
		vector<uint> vnDims(nDims);
		_hdf_convert_dvec_to_ivec(vshAttDims, vnDims);
		uint nPts = 1;
		for ( int ii = 0; ii < nDims; ii++ )
			nPts *= vnDims[ii];
		
		hobj_ref_t* refbuf = (hobj_ref_t*)malloc(sizeof(hobj_ref_t) * nPts);
		H5Aread(attID, attTID, refbuf);
		
		hid_t palID = H5Rdereference(dsID, H5R_OBJECT, &refbuf[0]);
		hid_t palSpace = H5Dget_space(palID);
		char name[256];
		H5Iget_name(palID, name, 256);
		
		nDims = H5Sget_simple_extent_ndims(palSpace);
		vector<hsize_t> vshPalDims(nDims);
		H5Sget_simple_extent_dims(palSpace, vshPalDims, NULL);
		vector<uint> vnPalDims(nDims);
		_hdf_convert_dvec_to_ivec(vshPalDims, vnPalDims);
		
		nPts = 1;
		for ( ii = 0; ii < nDims; ii++ )
			nPts *= vnPalDims[ii];
		
		vector<int> vnRGBs(nPts);
		vector<hsize_t> vshMemDims(1);
		_hdf_convert_uint_to_double(nPts, vshMemDims[0]);
		hid_t memSpace = H5Screate_simple(1, vshMemDims, NULL);
		
		H5Sselect_all(palSpace);
		H5Dread(palID, H5T_NATIVE_INT, H5S_ALL, palSpace, H5P_DEFAULT, vnRGBs);
		
		free(refbuf);
		H5Sclose(palSpace);
		H5Sclose(memSpace);
		H5Sclose(attSID);
		H5Aclose(attID);
		H5Oclose(palID);
		
		//read image data
		ml.SetSize(1, nHeight, nWidth);
		Matrix<int> mImage(ml, 0);
		H5Dread(dsID, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (int*)mImage);
		
		//convert to 24-bits bitmap data
		for ( int iH = nHeight - 1; iH >= 0; iH-- )
		{
			for ( int iW = 0; iW < nWidth; iW++ )
			{
				int nOffset = ((nHeight - 1 - iH) * nWidth + iW) * 3 + nJunks * (nHeight - 1 - iH);
				int nColorIndex = mImage[iH][iW] * 3;
				vnImageData[nOffset + 0] = (byte)vnRGBs[nColorIndex + 2]; //B
				vnImageData[nOffset + 1] = (byte)vnRGBs[nColorIndex + 1]; //G
				vnImageData[nOffset + 2] = (byte)vnRGBs[nColorIndex + 0]; //R
			}
		}
		SaveAs(STR_TEMP_BITMAP_FILENAME, nWidth ,nHeight, vnImageData, vnImageData.GetSize());
		MatrixObject mo(ml, 0);
		image_import_to_matrix(mo, STR_TEMP_BITMAP_FILENAME);
	}
	else if ( nPlanes == 3 && lstrcmp(interlace, "INTERLACE_PIXEL") == 0 )
	{
		ml.SetSize(1, nHeight, nWidth);
		vector<int> mImage(nPlanes * nWidth * nHeight);
		H5Dread(dsID, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (int*)mImage);
		
		for ( int iH = nHeight - 1; iH >= 0; iH-- )
		{
			for ( int iW = 0; iW < nWidth; iW++ )
			{
				int nOffset = (iH * nWidth + iW) * 3 + nJunks * iH;
				int nSrcOffset = ((nHeight - 1 - iH) * nWidth + iW) * 3;
				vnImageData[nOffset + 0] = (byte)mImage[nSrcOffset + 2]; //B
				vnImageData[nOffset + 1] = (byte)mImage[nSrcOffset + 1]; //G
				vnImageData[nOffset + 2] = (byte)mImage[nSrcOffset + 0]; //R
			}
		}
		SaveAs(STR_TEMP_BITMAP_FILENAME, nWidth, nHeight, vnImageData, vnImageData.GetSize());
		MatrixObject mo(ml, 0);
		image_import_to_matrix(mo, STR_TEMP_BITMAP_FILENAME);
	}
	///Sophy 8/27/2009 QA80-13130-P3 IMPORT_EACH_PLANE_OF_PLANE_INTERLACE_IMAGE_INTO_SEPERATE_IMAGES
	//else if ( nPlanes == 3 && lstrcmp(interlace, "INTERLACE_PLANE") == 0 )
	//{
		//ml.SetSize(nPlanes, nHeight, nWidth);
		//vector<int> mImage(nPlanes * nWidth * nHeight);
		//H5Dread(dsID, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (int*)mImage);
		//
		//for ( int iH = nHeight - 1; iH >= 0; iH-- )
		//{
			//for ( int iW = 0; iW < nWidth; iW++ )
			//{
				//int nOffset = (iH * nWidth + iW) * 3 + nJunks * iH;
				//int nSrcOffsetR = (nHeight - 1 - iH) * nWidth + iW;
				//int nSrcOffsetG = (nHeight - 1 - iH) * nWidth + iW + nHeight * nWidth;
				//int nSrcOffsetB = (nHeight - 1 - iH) * nWidth + iW + 2 * nHeight * nWidth;
				//vnImageData[nOffset + 0] = (byte)mImage[nSrcOffsetB]; //B
				//vnImageData[nOffset + 1] = (byte)mImage[nSrcOffsetG]; //G
				//vnImageData[nOffset + 2] = (byte)mImage[nSrcOffsetR]; //R
			//}
		//}
		//SaveAs(STR_TEMP_BITMAP_FILENAME, nWidth, nHeight, vnImageData, vnImageData.GetSize());
		//MatrixObject mo(ml, 0);
		//image_import_to_matrix(mo, STR_TEMP_BITMAP_FILENAME);
	//}
	///end IMPORT_EACH_PLANE_OF_PLANE_INTERLACE_IMAGE_INTO_SEPERATE_IMAGES
	else//gray scale, maybe multiple planes.)
	{
		ml.SetSize(nPlanes, nHeight, nWidth);
		vector<int> mImage(nPlanes * nWidth * nHeight);
		H5Dread(dsID, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (int*)mImage);
		for ( int iPlane = 0; iPlane < nPlanes; iPlane++ )
		{
			for ( int iH = nHeight - 1; iH >= 0; iH-- )
			{
				for ( int iW = 0; iW < nWidth; iW++ )
				{
					int nOffset = (iH * nWidth + iW) * 3 + nJunks * iH;
					int nSrcOffset = iPlane * nHeight * nWidth + (nHeight - 1 - iH) * nWidth + iW;
					vnImageData[nOffset + 0] = (byte)mImage[nSrcOffset]; //B
					vnImageData[nOffset + 1] = (byte)mImage[nSrcOffset]; //G
					vnImageData[nOffset + 2] = (byte)mImage[nSrcOffset]; //R
				}
			}
			SaveAs(STR_TEMP_BITMAP_FILENAME, nWidth, nHeight, vnImageData, vnImageData.GetSize());
			MatrixObject mo(ml, iPlane);
			image_import_to_matrix(mo, STR_TEMP_BITMAP_FILENAME);
		}
	}
	
	updateUserTree(ml, lpcszDataName, STR_IMAGE_INFO);	///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER

	H5Dclose(dsID);
	return status;
}

///Sophy 9/24/2009 IMPORT_PALETTE_INTO_WORKSHEET
HDFstatus	HDF5::ImportPalette(LPCSTR lpcszDataName, Worksheet& wks)
{
	if ( !wks || !isPaletteType(lpcszDataName) ) //invalid worksheet or not palette dataset
		return HDF_FAIL;
	
	int nType;
	vector<uint> vnDims;
	HDFstatus status = GetOneDatasetInfo(lpcszDataName, vnDims, &nType);
	int nDims = vnDims.GetSize();
	if ( status == HDF_FAIL || nDims != 2 )//palette should be 2D dataset
		return HDF_FAIL;
		
	hid_t iDataset = H5Dopen1(m_hdfID, lpcszDataName);
	if ( iDataset < 0 )
		return HDF_FAIL;
	
	hid_t hDataSpace = H5Dget_space(iDataset);
	if ( hDataSpace < 0 )
		return HDF_FAIL;

	H5Sselect_all(hDataSpace); //select all points to transfer
	
	matrix<int> mm(vnDims[0], vnDims[1]); //palette data is integers
	status = H5Dread(iDataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (int*)mm);
	if ( HDF_SUCCESS == status )
	{
		wks.SetSize(vnDims[0], vnDims[1]);
		for ( int iCol = 0; iCol < vnDims[1]; iCol++ )
		{
			Column col(wks, iCol);
			vectorbase& vbInternal = col.GetDataObject();
			mm.GetColumn(vbInternal, iCol);
		}
	}
	return status;
}
///end IMPORT_PALETTE_INTO_WORKSHEET
///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
static Folder _check_get_sub_folder(Folder& fdr, LPCSTR lpcszSubfdr, bool bActivateSubfdr = true)
{
	string strFolder(lpcszSubfdr);
	if ( strFolder.IsEmpty() )
		return fdr;
	
	Folder subFdr = fdr.GetFolder(lpcszSubfdr);
	if ( !subFdr )
		subFdr = fdr.AddSubfolder(lpcszSubfdr);
	
	if ( bActivateSubfdr )
		subFdr.Activate();
	return subFdr;
}
HDFstatus	HDF5::ImportOneFile(const TreeNode& trGUISetting, DWORD dwOption/* = IMP_USE_SOURCE_CATEGORY_INFO*/)
{
	if ( !trGUISetting )
		return HDF_FAIL;
	
	HDFstatus status = HDF_SUCCESS;
	Folder fdr = Project.ActiveFolder(); //get current folder
	string strSubfdr = GetFileName(m_strFileName);
	Folder fdrSub = _check_get_sub_folder(fdr, strSubfdr);
	Folder fdrCurrent;
	
	foreach(TreeNode trCategory in trGUISetting.Children)
	{
		string strCat = trCategory.tagName;
		BOOL bHide = (strCat.CompareNoCase(STR_DATASET_IMAGES) == 0 ? FALSE : TRUE);
		/// Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
		//progressBox pb("", PBOX_TOPMOST, bHide);
		progressBox pb("", PBOX_DEFAULT_STYLE, bHide);
		/// End QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
		pb.SetRange(0, trCategory.Children.Count());
		int nCurrent = 0;
		DWORD dwNameOptions = OCD_ENUM_NEXT | OCD_LONG_NAME;
		DWORD dwTitleCtrl = WIN_TITLE_SHOW_BOTH;
		foreach(TreeNode trDataset in trCategory.Children)
		{
			fdrSub.Activate();
			if ( 1 == trDataset.nVal )
			{
				
				string strDatasetName;
				trDataset.GetAttribute(STR_NAME, strDatasetName);
				
				vector<string> vsPath;
				strDatasetName.GetTokens(vsPath, CHAR_DATASET_PATH_SEP);
				
				int iLevel = 0;
				fdrCurrent = fdrSub;
				while ( iLevel < vsPath.GetSize() - 1 )
					fdrCurrent = _check_get_sub_folder(fdrCurrent, vsPath[iLevel++]);
				
				vector<uint> vnDim;
				int nType, nAux;
				string strLongName, strComments, strUnits;
				GetOneDatasetInfo(strDatasetName, vnDim, &nType, &strUnits, &strLongName, &strComments, &nAux);
				
				if ( FSI_CHAR == nType && VL_STRING_TYPE == nAux && vnDim.GetSize() == 0 ) //single VL string, import to Note
				{
					status = getOneNote(strDatasetName);
				}
				else if ( checkIsOneD(vnDim) || FSI_MIXED == nType || FSI_CHAR == nType || nType > FSI_EXT_BEGIN ) //1-D or struct type, to worksheet
				{
					Worksheet wks;
					if ( !wks.Create("Origin") )
						return HDF_FAIL;
					
					wks.SetSize(-1, 1);
					if ( FSI_MIXED == nType )
					{
						vector<uint> vnRef(vnDim.GetSize());
						status = getXDMultiVector(strDatasetName, wks, 0, vnDim, vnRef, 0);
					}
					else
					{
						Column col(wks, 0);
						if ( _is_numeric_column(nType) )
						{
							col.SetFormat(OKCOLTYPE_NUMERIC);
							col.SetInternalDataType(nType);
						}
						if ( HDF_SUCCESS == (status = getOneVector(strDatasetName, col)) )
						{
							col.SetUnits(strUnits);
							col.SetLongName(strLongName);
							col.SetComments(strComments);
						}
					}
					if ( HDF_SUCCESS == status)
					{
						wks.SetName(_get_dataset_name(strDatasetName));
						wks.GetPage().SetName(_get_dataset_name(strDatasetName), dwNameOptions);
						wks.GetPage().TitleShow = dwTitleCtrl;
						okutil_SetPageInfo(wks.GetPage().GetName(), m_strFileName, FILTER_TYPE_XFUNC);
					}
				}
				else if ( isPaletteType(strDatasetName) ) //palette data should import to worksheet
				{
					Worksheet wks;
					if ( !wks.Create("Origin") )
						return HDF_FAIL;
					status = ImportPalette(strDatasetName, wks);
					wks.SetName(_get_dataset_name(strDatasetName));
					wks.GetPage().SetName(_get_dataset_name(strDatasetName), dwNameOptions);
					wks.GetPage().TitleShow = dwTitleCtrl;
					okutil_SetPageInfo(wks.GetPage().GetName(), m_strFileName, FILTER_TYPE_XFUNC);
				}
				else //to matrixsheet
				{
					MatrixPage mp;
					mp.Create("Origin");
					if ( mp.Layers.Count() < 1 )
						mp.AddLayer("");
					
					if ( !bHide )
					{
						string strMsg;
						strMsg.Format("Importing %s...", strDatasetName);
						pb.SetText(strMsg, PBOXT_MIDCENTER);
						pb.Set(nCurrent++);
					}
					
					MatrixLayer ml = mp.Layers(0);
					ImportXDMat(strDatasetName, ml);
					ml.SetName(_get_dataset_name(strDatasetName));
					mp.SetName(_get_dataset_name(strDatasetName), dwNameOptions);
					mp.TitleShow = dwTitleCtrl;
					okutil_SetPageInfo(mp.GetName(), m_strFileName, FILTER_TYPE_XFUNC)
				}
			}
		}
	}
	
	fdrSub.Activate();
	Tree trFileInfo;
	if ( HDF_SUCCESS == GetFileStruct(trFileInfo) )
	{
		Note nt;
		nt.Create();
		string strContent;
		///Sophy 2/10/2010 SHOULD_NOT_LIMIT_STRING_DISPLAY_LENGTH_ON_DISPLAY_ATTRIBUTES
		//out_tree(trFileInfo.FirstNode, true, false, &strContent);
		DWORD dwOptions = OTR_SHOW_LINE_AS_CONNECTOR | OTR_USE_LABEL | OTR_NO_DISPLAY_LENGTH_LIMIT;
		TreeNode trFirst = trFileInfo.FirstNode;
		if ( trFirst )
			okutil_out_tree(&trFirst, 0, dwOptions, &strContent);
		///end SHOULD_NOT_LIMIT_STRING_DISPLAY_LENGTH_ON_DISPLAY_ATTRIBUTES
		nt.Text = strContent;
		nt.Rename(GetFileName(m_strFileName));
	}
	return status;
}

HDFstatus	HDF5::GetFileStruct(TreeNode& trFileStruct)
{
	if ( !trFileStruct || m_hdfID <= 0 )
		return HDF_FAIL;
	
	trFileStruct = m_trInfo.Clone(true);
	filterFileStruct(trFileStruct);
	
	return HDF_SUCCESS;
}

///end IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY

///Sophy 8/20/2009 IMPORT_IMAGE_DATA_INTO_MATRIXOBJECT
BOOL	HDF5::SaveAs(LPCSTR lpcszFile, LONG nWidth, LONG nHeight, byte*pRGB, const int nBufferSize, DWORD dwCtrl/* = 0*/)
{
	FILE* fp = fopen(lpcszFile, "wb");
	if ( fp == NULL )
		return FALSE;
	
	byte junks[3];
	memset(junks, 0, sizeof(junks));
	
	byte RGB[3];
	int nJunks = 0, x, y, i, nOffset;
	while ( (nJunks + 3*nWidth)%4 != 0 )
		nJunks++;
	
	BITMAPHEADER bmpHeader;
	bmpHeader.wFlags = 0x4D42; //"BM"
	bmpHeader.dwFileSize = 14 + 40 + (nJunks + nWidth * 3) * nHeight;
	bmpHeader.wReserved1 = bmpHeader.wReserved2 = 0;
	bmpHeader.dwDataOffset = 14 + 40;
	
	
	BMPINFO bmpInfo;
	bmpInfo.dwInfoSize = 40;
	bmpInfo.nWidth = nWidth;
	bmpInfo.nHeight = nHeight;
	bmpInfo.nPlanes = 1;
	bmpInfo.nBitPerPixel = 24; //8 + 8 + 8 RGB
	bmpInfo.dwCompression = 0;
	bmpInfo.dwDataSize = bmpHeader.dwFileSize - 14 - 40;
	bmpInfo.nXPixelPerMeter = 0;
	bmpInfo.nYPixelPerMeter = 0;
	bmpInfo.dwColorsUsed = 0;
	bmpInfo.dwColorsImportant = 0;
	
	
	fwrite(&bmpHeader, sizeof(BITMAPHEADER), 1, fp); 
	
	fwrite(&bmpInfo, sizeof(BMPINFO), 1, fp);
	
	//fwrite(pRGB, sizeof(byte), nBufferSize, fp);
	fwrite(pRGB, nBufferSize, sizeof(byte), fp);
	fclose(fp);
	return TRUE;
}
///end IMPORT_IMAGE_DATA_INTO_MATRIXOBJECT
#define	IMAGE24_RANK	3
HDFstatus	HDF5::getImageInfo(LPCSTR lpcszDataName, uint& nWidth, uint& nHeight, uint& nPlanes, char* interlace, uint& nPals) //H5IMget_image_info
{
	HDFstatus status = HDF_FAIL;
	
	hid_t dsID = 0, attID = 0, dsSID = 0, attTID = 0, attSID = 0;
	vector<hsize_t> dims(IMAGE24_RANK);
	
	dsID = H5Dopen1(m_hdfID, lpcszDataName);
	if ( dsID < 0 )
		return HDF_FAIL;
	
	int hasAtt = findAttribute(dsID, "INTERLACE_MODE");
	if ( hasAtt == 1 )
	{
		attID = H5Aopen(dsID, "INTERLACE_MODE", H5P_DEFAULT);
		if ( attID < 0 )
			goto BEFORE_RETURN;
		
		attTID = H5Aget_type(attID);
		if ( attTID < 0 )
			goto BEFORE_RETURN;

		if ( H5Aread(attID, attTID, interlace) < 0 )
			goto BEFORE_RETURN;

		if ( H5Tclose(attTID) < 0 )
			goto BEFORE_RETURN;

		if ( H5Aclose(attID) < 0 )
			goto BEFORE_RETURN;

	}
	
	if ( (dsSID = H5Dget_space(dsID)) < 0 )
		goto BEFORE_RETURN;
	
	if ( H5Sget_simple_extent_dims(dsSID, dims, NULL) < 0 )
		goto BEFORE_RETURN;

	int nDims = H5Sget_simple_extent_ndims(dsSID);
	//init image dimension
	if ( hasAtt == 1 ) //24 bit image
	{
		if ( strcmp(interlace, "INTERLACE_PIXEL") == 0 )
		{
			_hdf_convert_double_to_uint(dims[0], nHeight);
			_hdf_convert_double_to_uint(dims[1], nWidth);
			_hdf_convert_double_to_uint(dims[2], nPlanes);
		}
		else if ( strcmp(interlace, "INTERLACE_PLANE") == 0 )
		{
			_hdf_convert_double_to_uint(dims[0], nPlanes);
			_hdf_convert_double_to_uint(dims[1], nHeight);
			_hdf_convert_double_to_uint(dims[2], nWidth);
		}
		else
			goto BEFORE_RETURN;
	}
	else	//8 bit image
	{
		if ( nDims == 2 )
		{
			_hdf_convert_double_to_uint(dims[0], nHeight);
			_hdf_convert_double_to_uint(dims[1], nWidth);
			nPlanes = 1;
		}
		else if ( nDims == 3 )
		{
			_hdf_convert_double_to_uint(dims[0], nPlanes);
			_hdf_convert_double_to_uint(dims[1], nHeight);
			_hdf_convert_double_to_uint(dims[2], nWidth);
			
			///Sophy 8/27/2009 QA80-13130-P4 MORE_WORK_ON_DETECT_IMAGE_DIMENSION
			//since in HDF5, there is no principle that P(lanes), W(idth), H(eight) should be put as P-H-W or H-W-P, so we need to try to detect
			if ( nWidth < nPlanes ) //assume nWidth should be larger
			{
				_hdf_convert_double_to_uint(dims[0], nHeight);
				_hdf_convert_double_to_uint(dims[1], nWidth);
				_hdf_convert_double_to_uint(dims[2], nPlanes);
			}
			ASSERT(nPlanes < nWidth);
			///end MORE_WORK_ON_DETECT_IMAGE_DIMENSION
		}
		else
			ASSERT(FALSE);
	}
	
	if ( H5Sclose(dsSID) < 0 )
		goto BEFORE_RETURN;
	
	//get number of palettes
	int has_pal = findPalette(dsID);
	if ( has_pal == 1 )
	{
		if ( (attID = H5Aopen(dsID, "PALETTE", H5P_DEFAULT)) < 0 )
			goto BEFORE_RETURN;
		
		if ( (attTID = H5Aget_type(attID)) < 0 )
			goto BEFORE_RETURN;
		
		H5T_class_t atClass;
		if ( (atClass = H5Tget_class(attTID)) < 0 )
			goto BEFORE_RETURN;
		
		//check in really a reference
		if ( atClass == H5T_REFERENCE )
		{
			if ( (attSID = H5Aget_space(attID)) < 0 )
				goto BEFORE_RETURN;
			
			hssize_t szPals = H5Sget_simple_extent_npoints(attSID);
			_hdf_convert_double_to_uint(szPals, nPals);
			

		}
		if ( H5Sclose(attSID) < 0 )
			goto BEFORE_RETURN;	
			
		if ( H5Tclose(attTID) < 0 )
			goto BEFORE_RETURN;
		
		if ( H5Aclose(attID) < 0 )
			goto BEFORE_RETURN;
	}
	
	if ( H5Dclose(dsID) < 0 )
		goto BEFORE_RETURN;
	
	return HDF_SUCCESS;
	
BEFORE_RETURN:
	
	H5Dclose(dsID);
	H5Aclose(attID);
	H5Sclose(attSID);
	H5Tclose(attTID);
	
	return HDF_FAIL;
}

//copy from H5LT.c
static	herr_t	find_attr(hid_t loc_id, const char* name, const H5A_info_t *ainfo, void* op_data)
{
	int ret = H5_ITER_CONT;
	/* Shut compiler up */
	loc_id = loc_id; ainfo = ainfo;
	if ( strcmp(name, (char*)op_data) == 0 )
		ret = H5_ITER_STOP;
	
	return ret;
}

herr_t		HDF5::findAttribute(hid_t DatasetID, LPCSTR lpcszAttName)
{
	return H5Aiterate2(DatasetID, H5_INDEX_NAME, H5_ITER_INC, NULL, find_attr, (void*)(char*)lpcszAttName);
	//return 0;
}

//copy from H5IM.c
static	herr_t	find_palette(hid_t loc_id, const char* name, const H5A_info_t *ainfo, void *op_data)
{
	int ret = H5_ITER_CONT;
	/* Shut compiler up */
	loc_id = loc_id; ainfo = ainfo;
	if ( strcmp(name, "PALETTE") == 0 )
		ret = H5_ITER_STOP;
	
	return ret;
}

herr_t		HDF5::findPalette(hid_t DatasetID)
{
	return H5Aiterate2(DatasetID, H5_INDEX_NAME, H5_ITER_INC, NULL, find_palette, NULL);
}
///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE

HDFstatus	HDF5::getOneVector(LPCSTR lpcszDataName, Column& col)
{
	int nType;
	vector<uint> vnDims;
	HDFstatus status = GetOneDatasetInfo(lpcszDataName, vnDims, &nType);
	if ( status != HDF_SUCCESS )
		return HDF_FAIL;
	
	hid_t dsID = H5Dopen1(m_hdfID, lpcszDataName);
	if ( dsID < 0 )
		return HDF_FAIL;
	
	uint nNumEle = 1;
	for ( int ii = 0; ii < vnDims.GetSize(); ii++ )
		nNumEle *= vnDims[ii];
	
	vectorbase& vbInternal = col.GetDataObject();
	
	
	uint nOne = 1;
	uint nZero = 0;
	vector<hsize_t> vStart(1);
	vector<hsize_t> vStride(1);
	vector<hsize_t> vCount(1);
	vector<hsize_t> vBlock(1);
	
	hid_t hSpace = H5Dget_space(dsID);
	hid_t hType = H5Dget_type(dsID);
	hid_t hNativeType = H5Tget_native_type(hType, H5T_DIR_DEFAULT);
	hid_t hmemType = H5Tcopy(hNativeType);
	H5T_order_t order = H5Tget_order(hType);
	vector<hsize_t> vshDims(1);
	_hdf_convert_uint_to_double(nNumEle, vshDims[0]);
	hid_t mem_space = H5Screate_simple(1, vshDims, NULL);
	
	size_t nSize = H5Tget_size(hType);
	///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	if ( FSI_CHAR == nType )
	{
		///Sophy 11/16/2009 QA80-13130-P8 MORE_WORK_ON_HANDLE_HDF5_TYPES		
		//H5Tset_size(hmemType, nSize);
		//for ( uint ii = 0; ii < nNumEle; ii++ )
		//{
			//_hdf_convert_uint_to_double(ii, vStart[0]);
			//_hdf_convert_uint_to_double(nOne, vCount[0]);
			//_hdf_convert_uint_to_double(nOne, vStride[0]);
			//_hdf_convert_uint_to_double(nOne, vBlock[0]);
			//
			//if ( H5Sselect_hyperslab(hSpace, H5S_SELECT_SET, vStart, vStride, vCount, vBlock) < 0 )
				//return HDF_FAIL;
			//
			//_hdf_convert_uint_to_double(nZero, vStart[0]);
			//if ( H5Sselect_hyperslab(mem_space, H5S_SELECT_SET, vStart, vStride, vCount, vBlock) < 0 )
				//return HDF_FAIL;
			//
			//string strTmp;
   			//LPSTR lpBuffer = strTmp.GetBuffer(nSize);
			//status = H5Dread(dsID, hmemType, mem_space, hSpace, H5P_DEFAULT, lpBuffer);
			//strTmp.ReleaseBuffer();
//
			//vsData[ii] = strTmp;
		//}
		vector<string> vsData(nNumEle);
		char* cBuffer = (char*)malloc(nSize * nNumEle * sizeof(char));
		H5Dread(dsID, hType, H5S_ALL, H5S_ALL, H5P_DEFAULT, cBuffer);
		LPSTR lp = cBuffer;
		string strTemp;
		for ( int iPts = 0; iPts < nNumEle; iPts++ )
		{
			lp = cBuffer + nSize * iPts;
			LPSTR lpStr = strTemp.GetBuffer(nSize);
			strncpy(lpStr, lp, nSize);
			strTemp.ReleaseBuffer();
			vsData[iPts] = strTemp;
		}
		free(cBuffer);
		///end MORE_WORK_ON_HANDLE_HDF5_TYPES
		///Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
		col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);
		///end UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
		col.PutStringArray(vsData);
	}
	///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
	else
	{
		///Sophy 10/27/2009 FAIL_TO_SELECT_DATA_WHEN_DATASET_IS_1D_WITH_ONE_POINT
		//_hdf_convert_uint_to_double(nZero, vStart[0]);
		//_hdf_convert_uint_to_double(nNumEle, vCount[0]);
		//_hdf_convert_uint_to_double(nOne, vStride[0]);
		//_hdf_convert_uint_to_double(nOne, vBlock[0]);
	//
		//if ( H5Sselect_hyperslab(hSpace, H5S_SELECT_SET, vStart, vStride, vCount, vBlock) < 0 )
				//return HDF_FAIL;
		if ( H5Sselect_all(hSpace) < 0 )
			return HDF_FAIL;
		///end FAIL_TO_SELECT_DATA_WHEN_DATASET_IS_1D_WITH_ONE_POINT
		
		switch ( nType )
		{
		case FSI_SHORT:
			vector<short> vshData(nNumEle);
			status = H5Dread(dsID, H5T_NATIVE_SHORT, H5S_ALL, hSpace, H5P_DEFAULT, vshData);
			vbInternal = vshData;
			break;
			
		case FSI_LONG:
			vector<int> vnData(nNumEle);
			status = H5Dread(dsID, H5T_NATIVE_INT, H5S_ALL, hSpace, H5P_DEFAULT, vnData);
			vbInternal = vnData;
			break;
			
		case FSI_REAL:
			vector<float> vfData(nNumEle);
			status = H5Dread(dsID, H5T_NATIVE_FLOAT, H5S_ALL, hSpace, H5P_DEFAULT, vfData);
			vbInternal = vfData;
			break;
			
		case FSI_DOUBLE:
			vector<double> vdData(nNumEle);
			status = H5Dread(dsID, H5T_NATIVE_DOUBLE, H5S_ALL, hSpace, H5P_DEFAULT, vdData);
			vbInternal = vdData;
			break;

		///Sophy 11/16/2009 QA80-13130-P8 MORE_WORK_ON_HANDLE_HDF5_TYPES
		case FSI_ENUM:
			vector<string> vsNames;
			vector<int> vnVals;
			int nMembers = H5Tget_nmembers(hType);

			int nErr = H5Tset_order(hType, H5T_ORDER_BE);
			for ( int iMem = 0; iMem < nMembers; iMem++ )
			{
				int enumVal;
				char* pName = H5Tget_member_name(hType, iMem);
				//H5Tenum_valueof(hType, pName, &enumVal);
				if ( nSize == sizeof(byte) )
				{
					byte bt;
					status = H5Tget_member_value(hType, iMem, &bt);
					enumVal = bt;
				}
				else if ( nSize == sizeof(short) )
				{
					ushort us;
					status = H5Tget_member_value(hType, iMem, &us);
					enumVal = us;
				}
				else if ( nSize == sizeof(int) )
				{
					status = H5Tget_member_value(hType, iMem, &enumVal);
				}
				vnVals.Add(enumVal);
				vsNames.Add(pName);

				_safe_free(pName);
			}
			vector<int> vnBuffer(nNumEle);
			//status = H5Dread(dsID, H5T_NATIVE_INT, H5S_ALL, hSpace,  H5P_DEFAULT, vnBuffer);
			if ( nSize == sizeof(byte) )
			{
				vector<byte> vb(nNumEle);
				status = H5Dread(dsID, hType, H5S_ALL, hSpace,  H5P_DEFAULT, vb);
				vnBuffer = vb;
			}
			else if ( nSize == sizeof(short) )
			{
				vector<ushort> vs(nNumEle);
				status = H5Dread(dsID, hType, H5S_ALL, hSpace,  H5P_DEFAULT, vs);
				vnBuffer = vs;
			}
			else if ( nSize == sizeof(int) )
			{
				status = H5Dread(dsID, hType, H5S_ALL, hSpace,  H5P_DEFAULT, vnBuffer);
			}
			vector<string> vsData;
			for ( int iEle = 0; iEle < nNumEle; iEle++ )
			{
				int nEnumVal = vnBuffer[iEle];
				
				int nIndex = find_in_list(nEnumVal, vnVals, false);
				if ( nIndex < 0 ) //fatal error, should check why
				{
					ASSERT(FALSE);
					return HDF_FAIL;
				}
				
				if ( order == H5T_ORDER_BE ) //need to cvt to little-endian for display
					nEnumVal = _convert_BE_LE(&nEnumVal, nSize);
				
				string strVal;
				strVal.Format("%d:%s", nEnumVal, vsNames[nIndex]);
				vsData.Add(strVal);
				
			}
			col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);
			col.PutStringArray(vsData);
			break;
			
		case FSI_OPAQUE:
			
			char* buffer = (char*)malloc(nNumEle * nSize * sizeof(char));
			vector<string> vsData;
			LPSTR lpSrc, lp;
			status = H5Dread(dsID, hType, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer);
			for ( int iEle = 0; iEle < nNumEle; iEle++)
			{
				string strTemp;
				lpSrc = buffer + iEle * nSize;
				lp = strTemp.GetBuffer(nSize);
				strncpy(lp, lpSrc, nSize);
				strTemp.ReleaseBuffer();
				vsData.Add(strTemp);
			}
			
			free(buffer);
			
			col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);
			col.PutStringArray(vsData);
			break;
			
		case FSI_REFERENCE:
			
			hobj_ref_t* refbuf = (hobj_ref_t*)malloc(sizeof(hobj_ref_t) * nNumEle);
			status = H5Dread(dsID, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, refbuf);
			
			vector<string> vsData;
			for ( int iEle = 0; iEle < nNumEle; iEle++ )
			{
				hid_t obj = H5Rdereference(dsID, H5R_OBJECT, &refbuf[iEle]);
				int nSize = H5Iget_name(obj, NULL, 0);
				char* name = (char*)malloc((nSize + 1) * sizeof(char));
				H5Iget_name(obj, name, nSize + 1);
				vsData.Add(name);

				_safe_free(name);
				
				H5Oclose(obj);
			}
			free(refbuf);
			col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);
			col.PutStringArray(vsData);			
			break;
			
		case FSI_VLEN:
			
			hvl_t* vlBuffer = (hvl_t*)malloc(sizeof(hvl_t) * nNumEle);
			hid_t hSuper = H5Tget_super(hType);
			H5Dread(dsID, hmemType, H5S_ALL, H5S_ALL, H5P_DEFAULT, vlBuffer);
			vector<string> vsData;
			vector<string> vsRow;
			string strTemp;
			if ( H5Tequal(hSuper, H5T_NATIVE_INT) || H5Tequal(hSuper, H5T_NATIVE_LONG) )
			{
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					vector<int> vnVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vnVals[iEle] = (int)*((int*)vlBuffer[ii].p + iEle);
					}
					_convert_int_vector_to_string_vector(vnVals, vsRow, false);
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
			{
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					vector<short> vstVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vstVals[iEle] = (short)*((short*)vlBuffer[ii].p + iEle);
					}
					_convert_short_vector_to_string_vector(vstVals, vsRow, false);
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
			{
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					vector<float> vfVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vfVals[iEle] = (float)*((float*)vlBuffer[ii].p + iEle);
					}
					_convert_float_vector_to_string_vector(vfVals, vsRow, "%.2lf");
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
			{
				for ( int ii = 0; ii < nNumEle; ii++ )
				{		
					vector<double> vdVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vdVals[iEle] = (double)*((double*)vlBuffer[ii].p + iEle);
					}
					convert_double_vector_to_string_vector(vdVals, vsRow, vdVals.GetSize());
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
			{
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					vector<byte> vbVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vbVals[iEle] = (byte)*((byte*)vlBuffer[ii].p + iEle);
					}
					_convert_byte_vector_to_string_vector(vbVals, vsRow, false);
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			
			H5Dvlen_reclaim(hType, hSpace, H5P_DEFAULT, vlBuffer);
			free(vlBuffer);
			
			col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);
			col.PutStringArray(vsData);			
			break;
			
		case FSI_ARRAY:
			
			hid_t hSuper = H5Tget_super(hType);
			void* pBuffer = (void*)malloc(nNumEle * nSize);
			H5Dread(dsID, hmemType, H5S_ALL, H5S_ALL, H5P_DEFAULT, pBuffer);
			vector<string> vsData;
			vector<string> vsRow;
			string strTemp;
			if ( H5Tequal(hSuper, H5T_NATIVE_INT) || H5Tequal(hSuper, H5T_NATIVE_LONG) )
			{
				int* pStart = (int*)pBuffer;
				int* lp = pStart;
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					int nArrSize = nSize/sizeof(int);
					vector<int> vnVals(nArrSize);
					for ( int iEle = 0; iEle < nArrSize; iEle++ )
					{
						vnVals[iEle] = *lp;
						lp++
					}
					_convert_int_vector_to_string_vector(vnVals, vsRow, false);
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
			{
				short* pStart = (short*)pBuffer;
				short* lp = pStart;
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					int nArrSize = nSize/sizeof(short);
					vector<short> vstVals(nArrSize);
					for ( int iEle = 0; iEle < nArrSize; iEle++ )
					{
						vstVals[iEle] = *lp;
						lp++;
					}
					_convert_short_vector_to_string_vector(vstVals, vsRow, false);
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
			{
				float* pStart = (float*)pBuffer;
				float* lp = pStart;
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					int nArrSize = nSize/sizeof(float);
					vector<float> vfVals(nArrSize);
					for ( int iEle = 0; iEle < nArrSize; iEle++ )
					{
						vfVals[iEle] = *lp;
						lp++;
					}
					_convert_float_vector_to_string_vector(vfVals, vsRow, "%.2lf");
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
			{
				double* pStart = (double*)pBuffer;
				double* lp = pStart;
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					int nArrSize = nSize/sizeof(double);
					vector<double> vdVals(nArrSize);
					for ( int iEle = 0; iEle < nArrSize; iEle++ )
					{
						vdVals[iEle] = *lp;
						lp++;
					}
					convert_double_vector_to_string_vector(vdVals, vsRow, vdVals.GetSize());
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
			{
				byte* pStart = (byte*)pBuffer;
				byte* lp = pStart;
				for ( int ii = 0; ii < nNumEle; ii++ )
				{
					int nArrSize = nSize/sizeof(byte);
					vector<byte> vbVals(nArrSize);
					for ( int iEle = 0; iEle < nArrSize; iEle++ )
					{
						vbVals[iEle] = *lp;
						lp++;
					}
					_convert_byte_vector_to_string_vector(vbVals, vsRow, false);
					strTemp.SetTokens(vsRow, CHAR_VALUE_SEP);
					vsData.Add(strTemp);
				}
			}
			
			free(pBuffer);
			col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);
			col.PutStringArray(vsData);			

			break;
			
		default:
			ASSERT(FALSE); //should not come here
			status = HDF_FAIL;
			break;
		}
	}
	updateUserTree(col, lpcszDataName, STR_DATASET_INFO);	///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER

	H5Sclose(mem_space);
	H5Tclose(hNativeType);
	H5Tclose(hmemType);
	H5Tclose(hType);
	H5Sclose(hSpace);
	status = H5Dclose(dsID);
	return status;
}

//support importing multi-D data of struct type into multi-columns
HDFstatus	HDF5::getXDMultiVector(LPCSTR lpcszDataName, Worksheet& wks, int iStartCol, const vector<uint>& vnDims, vector<uint>& vnRef, int nDepth)
{
	HDFstatus status = HDF_SUCCESS;
	if ( nDepth < vnDims.GetSize() ) //recursively call to import data...
	{
		for ( int ii = 0; ii < vnDims[nDepth]; ii++ )
		{
			vnRef[nDepth] = ii;
			status = getXDMultiVector(lpcszDataName, wks, iStartCol, vnDims, vnRef, nDepth + 1);
			if ( status != HDF_SUCCESS )
				return status;
		}
	}
	else if ( nDepth == vnDims.GetSize() )
	{
		status = getMultiVector(lpcszDataName, wks, iStartCol, vnDims, vnRef);
	}
	
	return status;
}


HDFstatus	HDF5::getMultiVector(LPCSTR lpcszDataName, Worksheet& wks, int iStartCol, const vector<uint>& vnDims, vector<uint>& vnRef)
{
	HDFstatus status = HDF_SUCCESS;
	TreeNode trDataset = m_trInfo.FindNodeByAttribute(STR_NAME, lpcszDataName, true); //recursively search
	if ( !trDataset )
		return HDF_FAIL;
	
	
	uint nDims = vnDims.GetSize();
	uint nOne = 1;
	vector<hsize_t> vStart(nDims);
	vector<hsize_t> vStride(nDims);
	vector<hsize_t> vCount(nDims);
	vector<hsize_t> vBlock(nDims);
	
	hid_t dset = H5Dopen1(m_hdfID, lpcszDataName);
	hid_t hSpace = H5Dget_space(dset);
	hid_t hType = H5Dget_type(dset);
	hid_t hmemType = H5Tcopy(hType);
	vector<hsize_t> vshDims(1);
	_hdf_convert_uint_to_double(nOne, vshDims[0]);
	hid_t mem_space = H5Screate_simple(1, vshDims, NULL);

	size_t nSize = H5Tget_size(hType);
	byte* buffer = (byte*)malloc(nSize);
	
	uint iRow = vnRef[nDims - 1];
	uint nRows = vnDims[nDims -1];
	for ( int iDim = nDims - 2; iDim >= 0; iDim-- )
	{
		iRow += vnRef[iDim] * vnDims[iDim + 1];
		nRows *= vnDims[iDim];
	}
	
	int nColumns;
	if ( !trDataset.GetAttribute(STR_DATASET_SCOPE, nColumns) )
		return HDF_FAIL;
	
	int nWksRows = wks.GetNumRows();
	if ( nWksRows < nRows )
		nWksRows = nRows;
	
	int nWksCols = wks.GetNumCols();
	if ( nWksCols < iStartCol + nColumns )
		nWksCols = iStartCol + nColumns;
	
	wks.SetSize(nWksRows, nWksCols); //resize worksheet
	
	_hdf_convert_ivec_to_dvec(vnRef, vStart);
	for ( iDim = 0; iDim < nDims; iDim++ )
	{
		_hdf_convert_uint_to_double(nOne, vStride[iDim]);
		_hdf_convert_uint_to_double(nOne, vCount[iDim]);
		_hdf_convert_uint_to_double(nOne, vBlock[iDim]);
	}

	if ( H5Sselect_hyperslab(hSpace, H5S_SELECT_SET, vStart, vStride, vCount, vBlock) < 0 )
		return HDF_FAIL;
	
	int iColIndex = iStartCol; //fill form column(iStartCol) to column(iStartCol + nColumns - 1);
	status = H5Dread(dset, hmemType, mem_space, hSpace, H5P_DEFAULT, buffer);
	foreach ( TreeNode trMem in trDataset.Members.Children )
	{
		string strType = trMem.OCType.strVal;
		string strName;
		GET_LABEL(trMem, strName);
		
		int nMemTypeSize;
		GET_SIZE(trMem.OCType, nMemTypeSize);
		int nIndex = H5Tget_member_index(hType, strName);
		int nOffset = H5Tget_member_offset(hType, nIndex);
		int nType = getDataType(strType);
		if ( nType == FSI_ARRAY || nType < 0 ) //maybe array
		{
			if ( nType == FSI_ARRAY )
			{
				trMem.OCType.GetAttribute(STR_OC_TYPE, strType);
				nType = getDataType(strType);
				if ( nType < 0 || FSI_MIXED == nType )
				{
					ASSERT(FALSE);
					printf("Not support nested compound type!");
					continue;
				}
				vector<uint> vnMemDims;
				vnMemDims = trMem.Dims.nVals;
				///Sophy 9/25/2009 SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
				int nPts = vnMemDims[0];
				for ( int iDim = 1; iDim < vnMemDims.GetSize(); iDim++ )
					nPts *= vnMemDims[iDim];
				
				Column col(wks, iColIndex++);
				vector<string> vsData;
				///Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
				//col.SetFormat(OKCOLTYPE_NUMERIC);
				//col.SetInternalDataType(nType);
				///end UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
				
				switch ( nType )
				{
				case FSI_LONG:
					vector<int> vnVals(nPts);
					memcpy((int*)vnVals, (buffer + nOffset), sizeof(int) * nPts);
					convert_int_vector_to_string_vector(vnVals, vsData);		
					
					break;
					
				case FSI_REAL:
					vector<float> vfVals(nPts);
					memcpy((float*)vfVals, (buffer + nOffset), sizeof(float) * nPts);
					vector<double> vTVals(nPts);
					vTVals = vfVals;
					convert_double_vector_to_string_vector(vTVals, vsData, vTVals.GetSize());
					
					break;
					
				case FSI_DOUBLE:
					vector<double> vdVals(nPts);
					memcpy((double*)vdVals, (buffer + nOffset), sizeof(double) * nPts);
					convert_double_vector_to_string_vector(vdVals, vsData, vdVals.GetSize());
					
					break;
				///Sophy 7/24/2009 IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
				case FSI_SHORT:
					vector<short> vsVals(nPts);
					memcpy((short*)vsVals, (buffer + nOffset), sizeof(short) * nPts);
					vector<int> vTVals(nPts);
					vTVals = vsVals;
					convert_int_vector_to_string_vector(vTVals, vsData);

					break;
				///end IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
				
				case FSI_CHAR:
					vector<char> vcBuffer(nPts);
					memcpy((char*)(LPVOID)vcBuffer, (char*)(buffer + nOffset), sizeof(char) * nPts);
					vector<int> vTVals(nPts);
					vTVals = vcBuffer;
					convert_int_vector_to_string_vector(vTVals, vsData);
					
					break;
					
				default:
					ASSERT(FALSE); //should add more cases if come here
					break;
				}

				///end SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
				string strText;
				strText.SetTokens(vsData, CHAR_VALUE_SEP);
				
				string strComments;
				strComments.Format(STR_FIELD_CMT_FMT, _get_dataset_name(lpcszDataName));
				col.SetComments(strComments);
				
				col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);				
				col.SetLongName(strName);
				wks.SetCell(iRow, col.GetIndex(), strText);
			}
			else
				ASSERT(FALSE);

		}
		else if ( nType == FSI_MIXED )
		{
			///Sophy 7/31/2009 SUPPORT_ONE_LEVEL_NESTED_COMPOUND_DATATYPE
#ifndef	_SUPPORT_NESTED_STRUCT_
			printf("Nested compound type not supported!");
			ASSERT(FALSE);
			continue;
#else
			hid_t hSubType = H5Tget_member_type(hType, nIndex);
			foreach( TreeNode trSubMem in trMem.Members.Children )
			{
				string strSubMemType = trSubMem.OCType.strVal;
				string strSubName;
				GET_LABEL(trSubMem, strSubName);
				
				int nSubMemTypeSize;
				GET_SIZE(trSubMem.OCType, nSubMemTypeSize);
				int nSubIndex = H5Tget_member_index(hSubType, strSubName);
				int nSubOffset = H5Tget_member_offset(hSubType, nSubIndex);
				nOffset += nSubOffset; //nested struct member's global offset in the whole struct type
				int nSubType = getDataType(strSubMemType);
				if ( nSubType == FSI_ARRAY || nSubType < 0 ) //maybe array in nested struct
				{
					if ( nSubType == FSI_ARRAY )
					{
						trSubMem.OCType.GetAttribute(STR_OC_TYPE, strSubMemType);
						nSubType = getDataType(strSubMemType);
						if ( nSubType < 0 || FSI_MIXED == nSubType )
						{
							ASSERT(FALSE);
							printf("Not support more level nested compound type!");
							continue;
						}
						vector<uint> vnMemDims;
						vnMemDims = trSubMem.Dims.nVals;
						///Sophy 9/25/2009 SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
						//ASSERT(vnMemDims.GetSize() == 1);//only support 1D currently
						//if ( vnMemDims.GetSize() != 1 )
							//continue;			
						//for ( int kk = 0; kk < vnMemDims[0]; kk++ )
						int nPts = vnMemDims[0];
						for ( int iDim = 1; iDim < vnMemDims.GetSize(); iDim++ )
							nPts *= vnMemDims[iDim];
						///end SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
						
						Column col(wks, iColIndex++);
						vector<string> vsData;
						///Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
						//col.SetFormat(OKCOLTYPE_NUMERIC);
						//col.SetInternalDataType(nType);
						///end UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
						
						switch ( nType )
						{
						case FSI_LONG:
							vector<int> vnVals(nPts);
							memcpy((int*)vnVals, (buffer + nOffset), sizeof(int) * nPts);
							convert_int_vector_to_string_vector(vnVals, vsData);		
							
							break;
							
						case FSI_REAL:
							vector<float> vfVals(nPts);
							memcpy((float*)vfVals, (buffer + nOffset), sizeof(float) * nPts);
							vector<double> vTVals(nPts);
							vTVals = vfVals;
							convert_double_vector_to_string_vector(vTVals, vsData, vTVals.GetSize());
							
							break;
							
						case FSI_DOUBLE:
							vector<double> vdVals(nPts);
							memcpy((double*)vdVals, (buffer + nOffset), sizeof(double) * nPts);
							convert_double_vector_to_string_vector(vdVals, vsData, vdVals.GetSize());
							
							break;
						///Sophy 7/24/2009 IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
						case FSI_SHORT:
							vector<short> vsVals(nPts);
							memcpy((short*)vsVals, (buffer + nOffset), sizeof(short) * nPts);
							vector<int> vTVals(nPts);
							vTVals = vsVals;
							convert_int_vector_to_string_vector(vTVals, vsData);
		
							break;
						///end IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
						
						case FSI_CHAR:
							vector<char> vcBuffer(nPts);
							memcpy((char*)(LPVOID)vcBuffer, (char*)(buffer + nOffset), sizeof(char) * nPts);
							vector<int> vTVals(nPts);
							vTVals = vcBuffer;
							convert_int_vector_to_string_vector(vTVals, vsData);
							
							break;
							
						default:
							ASSERT(FALSE); //should add more cases if come here
							break;
						}
		
						///end SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
						string strText;
						strText.SetTokens(vsData, CHAR_VALUE_SEP);		
						wks.SetCell(iRow, col.GetIndex(), strText);
						col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);				
						
						string strComments;
						strComments.Format(STR_FIELD_CMT_FMT, _get_dataset_name(lpcszDataName));
						col.SetComments(strComments);
						col.SetLongName(strName + "->" + strSubName);

					}
					else
						ASSERT(FALSE);

				}
				else if ( FSI_MIXED == nSubType )
				{
					ASSERT(FALSE);
					printf("Not support more level nested compound type!");
					continue;
				}
				else
				{
					Column col(wks, iColIndex++);
					///Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
					if ( nType != FSI_CHAR )
					{
						col.SetFormat(OKCOLTYPE_NUMERIC);
						///Sophy 11/16/2009 QA80-13130-P9 WRONG_COLUMN_FORMAT_CAUSE_DATA_LOST_WHEN_SAVE_OR_APPEND_NEW_COLUMNS
						//col.SetInternalDataType(nType);
						col.SetInternalDataType(nSubType);
						///end WRONG_COLUMN_FORMAT_CAUSE_DATA_LOST_WHEN_SAVE_OR_APPEND_NEW_COLUMNS
						vectorbase& vbInternal = col.GetDataObject();
						if ( vbInternal.GetSize() <= iRow )
							vbInternal.SetSize(iRow + 1);
						switch ( nSubType )
						{
						case FSI_LONG:
							int nVal;
							memcpy(&nVal, (buffer + nOffset), sizeof(int));
							vbInternal[iRow] = nVal;
							
							break;
							
						case FSI_REAL:
							float fVal;
							memcpy(&fVal, (buffer + nOffset), sizeof(float));
							vbInternal[iRow] = fVal;
							
							break;
							
						case FSI_DOUBLE:
							double dVal;
							memcpy(&dVal, (buffer + nOffset), sizeof(double));
							vbInternal[iRow] = dVal;
							
							break;
						///Sophy 7/24/2009 IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
						case FSI_SHORT:
							short sVal;
							memcpy(&sVal, (buffer + nOffset), sizeof(short));
							vbInternal[iRow] = sVal;
							
							break;
						///end IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
						default:
							ASSERT(FALSE); //add more cases
							break;
						}
					}
					///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
					else	//FSI_CHAR
					{
						vector<char> vBuffer(nSubMemTypeSize);
						strncpy((char*)vBuffer, (char*)(buffer + nOffset), nSubMemTypeSize);
						string strText(vBuffer);
						if ( 1 == nSubMemTypeSize && !IsCharAlpha(vBuffer[0]) ) //single char and not alpha char, set as numeric
						{
							col.SetFormat(OKCOLTYPE_NUMERIC);
							wks.SetCell(iRow, col.GetIndex(), (double)vBuffer[0]);
						}
						else
						{
							col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);				
							wks.SetCell(iRow, col.GetIndex(), strText);
						}
					}
					///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
					///end UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
					col.SetLongName(strName + "->" + strSubName);
					string strComments;
					strComments.Format(STR_FIELD_CMT_FMT, _get_dataset_name(lpcszDataName));
					col.SetComments(strComments);
				}
			}
			H5Tclose(hSubType);
#endif
			///end SUPPORT_ONE_LEVEL_NESTED_COMPOUND_DATATYPE
		}
		else //atomic type
		{
			Column col(wks, iColIndex++);
			///Sophy 9/15/2009 QA80-13130-P6 UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE
			if ( nType != FSI_CHAR )
			{
				col.SetFormat(OKCOLTYPE_NUMERIC);
				col.SetInternalDataType(nType);
				vectorbase& vbInternal = col.GetDataObject();
				if ( vbInternal.GetSize() <= iRow )
					vbInternal.SetSize(iRow + 1);
				switch ( nType )
				{
				case FSI_LONG:
					int nVal;
					memcpy(&nVal, (buffer + nOffset), sizeof(int));
					vbInternal[iRow] = nVal;
					
					break;
					
				case FSI_REAL:
					float fVal;
					memcpy(&fVal, (buffer + nOffset), sizeof(float));
					vbInternal[iRow] = fVal;
					
					break;
					
				case FSI_DOUBLE:
					double dVal;
					memcpy(&dVal, (buffer + nOffset), sizeof(double));
					vbInternal[iRow] = dVal;
					
					break;
				///Sophy 7/24/2009 IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
				case FSI_SHORT:
					short sVal;
					memcpy(&sVal, (buffer + nOffset), sizeof(short));
					vbInternal[iRow] = sVal;
					
					break;
				///end IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
				default:
					ASSERT(FALSE); //add more cases
					break;
				}
			}
			///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
			else	//FSI_CHAR
			{
				string strText;
				LPSTR lpBuffer = strText.GetBuffer(nMemTypeSize);
				strncpy(lpBuffer, (char*)(buffer + nOffset), nMemTypeSize);
				strText.ReleaseBuffer();
				if ( 1 == nMemTypeSize && !IsCharAlpha(strText.GetAt(0)) ) //single char and not alpha char, set as numeric
				{
					col.SetFormat(OKCOLTYPE_NUMERIC);
					///Sophy 9/15/2010 PROPER_DISPLAY_BYTE_VALUE_STRUCTURE_FIELD
					//wks.SetCell(iRow, col.GetIndex(), (double)atof(strText));
					byte byVal = *(byte*)lpBuffer;
					wks.SetCell(iRow, col.GetIndex(), (double)byVal);
					///end PROPER_DISPLAY_BYTE_VALUE_STRUCTURE_FIELD
				}
				else
				{
					col.SetFormat(OKCOLTYPE_TEXT_NUMERIC);				
					wks.SetCell(iRow, col.GetIndex(), strText);
				}
			}
			///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
			///end UPDATE_COLUMN_FORMAT_ACCORDING_TO_SOURCE_FILE_DATATYPE

			col.SetLongName(strName);
			string strComments;
			strComments.Format(STR_FIELD_CMT_FMT, _get_dataset_name(lpcszDataName));
			col.SetComments(strComments);

		}
	}
	updateUserTree(wks, lpcszDataName, STR_DATASET_INFO);	///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER

	free(buffer);
	H5Sclose(mem_space);
	H5Tclose(hmemType);
	H5Tclose(hType);
	H5Sclose(hSpace);
	status = H5Dclose(dset);
	return status;
}

HDFstatus	HDF5::getXDMatrixes(LPCSTR lpcszDataName, MatrixLayer& ml, const vector<uint>& vnDims, vector<uint>& vnRef, int nDepth)
{
	HDFstatus status = HDF_SUCCESS;
	if ( nDepth == vnRef.GetSize() )
	{
		int iMatObj;
		if ( vnRef.GetSize() > 0 )
		{
			iMatObj = vnRef[nDepth - 1];
			for ( int iDim = nDepth - 2; iDim >= 0; iDim -- )
				iMatObj += vnRef[iDim] * vnDims[iDim + 1];
		}
		else
			iMatObj = 0; //lpcszDataName is 2D, imported into the first matrixobject.
		
		
		status =  getOneMatrix(lpcszDataName, ml, iMatObj, vnRef);
	}
	else if ( nDepth < vnRef.GetSize() )
	{
		for ( int ii = 0; ii < vnDims[nDepth]; ii++ )
		{
			vnRef[nDepth] = ii;
			status = getXDMatrixes(lpcszDataName, ml, vnDims, vnRef, nDepth + 1);//init next dimension of vnRef.
			if ( status != HDF_SUCCESS )
				break; //if any exception, break the operation.
		}
	}
	else
	{
		ASSERT(FALSE); //misused.
		status = HDF_FAIL;
	}	
	
	return status;
}

HDFstatus	HDF5::getOneMatrix(LPCSTR lpcszDataName, MatrixLayer& ml, int iMatObj, const vector<uint>& vnRef)
{
	int nType;
	vector<uint> vnDims;
	HDFstatus status = GetOneDatasetInfo(lpcszDataName, vnDims, &nType);
	int nDims = vnDims.GetSize();
	if ( status == HDF_FAIL || nDims - vnRef.GetSize() != 2 )//fail or can not convert to 2D
		return HDF_FAIL;
	
	vector<hsize_t> vStart(nDims);
	vector<hsize_t> vStride(nDims);
	vector<hsize_t> vCount(nDims);
	vector<hsize_t> vBlock(nDims);
	getOneRegion(vnDims, vnRef, vStart, vStride, vCount, vBlock);
	
	hid_t iDataset = H5Dopen1(m_hdfID, lpcszDataName);
	if ( iDataset < 0 )
		return HDF_FAIL;
	
	hid_t hDataSpace = H5Dget_space(iDataset);
	if ( hDataSpace < 0 )
		return HDF_FAIL;
	
	if ( H5Sselect_hyperslab(hDataSpace, H5S_SELECT_SET, vStart, vStride, vCount, vBlock) < 0 )
		return HDF_FAIL;
	
	if ( nType < 0 || !ml.SetInternalDataType(nType) )
		return HDF_FAIL;
	
	vector<hsize_t> vshDims(2);
	_hdf_convert_uint_to_double(vnDims[nDims - 2], vshDims[0]);
	_hdf_convert_uint_to_double(vnDims[nDims - 1], vshDims[1]);
	hid_t mem_space = H5Screate_simple(2, vshDims, NULL);

	switch ( nType )
	{
	case FSI_SHORT:
		Matrix<short> mo(ml, iMatObj);
		status = H5Dread(iDataset, H5T_NATIVE_SHORT, mem_space, hDataSpace, H5P_DEFAULT, (short*)mo);
		break;
		
	case FSI_LONG:
		Matrix<int> mo(ml, iMatObj);
		status = H5Dread(iDataset, H5T_NATIVE_INT, mem_space, hDataSpace, H5P_DEFAULT, (int*)mo);
		break;
		
	case FSI_REAL:
		Matrix<float> mo(ml, iMatObj);
		status = H5Dread(iDataset, H5T_NATIVE_FLOAT, mem_space, hDataSpace, H5P_DEFAULT, (float*)mo);
		break;
		
	case FSI_DOUBLE:
		Matrix<double> mo(ml, iMatObj);
		status = H5Dread(iDataset, H5T_NATIVE_DOUBLE, mem_space, hDataSpace, H5P_DEFAULT, (double*)mo);
		break;

	default:
		ASSERT(FALSE); //should not come here
		status = HDF_FAIL;
	}
	H5Sclose(mem_space);
	H5Sclose(hDataSpace);
	H5Dclose(iDataset);
	return status;
}

///Sophy 9/24/2009 IMPORT_VL_STRING_INTO_NOTE_WINDOW
HDFstatus	HDF5::getOneNote(LPCSTR lpcszDataName)
{
	hid_t dsID = H5Dopen1(m_hdfID, lpcszDataName);
	if ( dsID < 0 )
		return HDF_FAIL;

	HDFstatus status;
	hid_t hSpace = H5Dget_space(dsID);
	hid_t hType = H5Dget_type(dsID);
	hid_t hmemType = H5Tcopy(hType);
	
	size_t nSize = H5Tget_size(hType);
	char* pBuffer = (char*)malloc(sizeof(char) * nSize);
	status = H5Dread(dsID, hmemType, H5S_ALL, H5S_ALL, H5P_DEFAULT, pBuffer);
	FILE* fpTemp = fopen(STR_TEMP_VL_STR_FILENAME, "w");
	fwrite(pBuffer, sizeof(char), nSize, fpTemp);
	fclose(fpTemp);
	free(pBuffer);
	
	//put content into Note window
	Note nt;
	nt.Create(CREATE_VISIBLE, STR_TEMP_VL_STR_FILENAME);
	
	nt.Rename(_get_dataset_name(lpcszDataName));
	
	H5Tclose(hmemType);
	H5Tclose(hType);
	H5Sclose(hSpace);
	status = H5Dclose(dsID);

	return status;
}
///end IMPORT_VL_STRING_INTO_NOTE_WINDOW

HDFstatus	HDF5::getOneRegion(const vector<uint>& vnDims, const vector<uint>& vnRef, vector<hsize_t>& vStart, vector<hsize_t>& vStride, vector<hsize_t>& vCount, vector<hsize_t>& vBlock)
{
	if ( vnDims.GetSize() - vnRef.GetSize() != 2 )
		return HDF_FAIL;
	
	uint ii = 0;
	uint nOne = 1;
	uint nZero = 0;

	for ( ii = 0; ii < vnRef.GetSize(); ii++ )
	{
		_hdf_convert_uint_to_double(vnRef[ii], vStart[ii]);
		_hdf_convert_uint_to_double(nOne, vStride[ii]);
		_hdf_convert_uint_to_double(nOne, vCount[ii]);
		_hdf_convert_uint_to_double(nOne, vBlock[ii]);
	}
	ASSERT(2 == vnDims.GetSize() - ii);
	for ( ; ii < vnDims.GetSize(); ii++ )
	{
		_hdf_convert_uint_to_double(nZero, vStart[ii]);
		_hdf_convert_uint_to_double(nOne, vStride[ii]);
		_hdf_convert_uint_to_double(vnDims[ii], vCount[ii]);
		_hdf_convert_uint_to_double(nOne, vBlock[ii]);
	}
	return HDF_SUCCESS;
}

HDFstatus	HDF5::getDatasetsOneGroup(TreeNode& trGroup, TreeNode& trInfo)
{
	if ( !trGroup || !trInfo )
		return HDF_FAIL;
	
	int nSubDatasets;
	int nSubGroups;
	if ( trGroup.GetAttribute(STR_SUB_DATASETS, nSubDatasets) )
	{
		for ( int ii = 0; ii < nSubDatasets; ii++ )
		{
			string strDataset;
			strDataset.Format(STR_TAGNAME_FORMAT, STR_DATASET, ii);
			TreeNode trDataset = trGroup.GetNode(strDataset, false);
			if ( trDataset )
			{
				TreeNode trCopy = trDataset.Clone(true);
				filterDataset(trCopy);
				int nDims = getDatasetDims(trDataset);
				if ( nDims < 0 )
				{
					ASSERT(FALSE); //error, should check why come here.
				}
				else if ( nDims == 0 )
					nDims = 1;
				
				if ( nDims > 0 )
				{
					///Sophy 7/24/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
					string strDatasetName;
					trDataset.GetAttribute(STR_NAME, strDatasetName);
					if ( isImageType(strDatasetName) )
					{
						TreeNode trImages = tree_check_get_node(trInfo, STR_DATASET_IMAGES);
						trImages.AddNode(trCopy);
					}
					///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
					else
					{
						string strXDData;
						strXDData.Format(STR_DATASET_XD_FORMAT, nDims);
						TreeNode trXD = tree_check_get_node(trInfo, strXDData);
						
						string strXDDatasets;
						strXDDatasets.Format(STR_XD_DATASETS, nDims);
						SET_LABEL(trXD, strXDDatasets);
						trXD.AddNode(trCopy);
					}
				}
			}
		}
	}
	
	if ( trGroup.GetAttribute(STR_SUB_GROUPS, nSubGroups) )
	{
		for ( int ii = 0; ii < nSubGroups; ii++ )
		{
			string strGroup;
			strGroup.Format(STR_TAGNAME_FORMAT, STR_GROUP, ii);
			TreeNode trSubGroup = trGroup.GetNode(strGroup, false);
			getDatasetsOneGroup(trSubGroup, trInfo);
		}
	}
	
	return HDF_SUCCESS;
}

bool		HDF5::filterDataset(TreeNode& trDataset, bool bRemoveAttribs/* = true*/, bool bRemoveMembers /* = true*/)
{
	vector<string> vsUsefulAttribs = 
	{
		STR_UINTS,
		STR_LONGNAME, 
		STR_DESCRIPTION
	};
	
	TreeNode trAttrs = trDataset.GetNode(STR_OBJ_ATTTRIBS);
	if ( bRemoveAttribs && trAttrs )
	{
		foreach ( TreeNode trOneAtt in trAttrs.Children )
		{
			string strTagName = trOneAtt.tagName;
			if ( vsUsefulAttribs.Find(strTagName) >= 0 )
				trDataset.AddNode(trOneAtt); //useful attributes move to upper branch/dataset
		}
		trAttrs.Remove();//remove from dataset node
	}
	else
	{
		filterAttribs(trAttrs);
	}
	
	TreeNode trMembers = trDataset.GetNode(STR_DATASET_MEMBERS);
	if ( trMembers )
	{
		if ( bRemoveMembers )
		{
			trMembers.Remove();
		}
		else //not removed, recursively update members.
		{
			foreach(TreeNode trMem in trMembers.Children)
			{
				filterDataset(trMem, bRemoveAttribs, bRemoveMembers);
			}
		}
	}
	///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	TreeNode trType = trDataset.GetNode(STR_OC_TYPE);
	if ( trType )
		SET_LABEL(trType, STR_DATASET_DATATYPE);
	
	TreeNode trDims = trDataset.GetNode(STR_DATASET_DIMS);
	if ( trDims )
	{
		vector<int> vnDims;
		vnDims = trDims.nVals;
		vector<string> vsDims;
		convert_int_vector_to_string_vector(vnDims, vsDims);
		trDims.Reset();
		trDims.strVal = get_display_string(vsDims, vsDims.GetSize(), STR_DIMS_SEP);
		SET_LABEL(trDims, STR_DIMS_INFO)
	}
	string strLabel;
	if ( trDataset.GetAttribute(STR_NAME_ATTRIB, strLabel) )
	{
		SET_LABEL(trDataset, _get_dataset_name(strLabel));
	}
	///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
	
	return true;
}

///Sophy 9/7/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER
bool		HDF5::filterGroup(TreeNode& trGroup)
{
	if ( !trGroup )
		return false;
	
	TreeNode trAttrs = trGroup.GetNode(STR_OBJ_ATTTRIBS);
	filterAttribs(trAttrs);
	
	foreach(TreeNode trNode in trGroup.Children)
	{
		int nType;
		trNode.GetAttribute(STR_TYPE, nType);
		if ( H5G_GROUP == nType )
			filterGroup(trNode);
		else if ( H5G_DATASET == nType )
		{
			filterDataset(trNode, false, false);
		}
	}
	
	return true;
}

bool		HDF5::filterFileStruct(TreeNode& trFileStruct)
{
	if ( !trFileStruct )
		return false;
	
	return filterGroup(trFileStruct.FirstNode);
}

bool		HDF5::filterAttribs(TreeNode& trAttribs)
{
	if ( !trAttribs )
		return false;
	
	foreach ( TreeNode trAttrib in trAttribs.Children )
	{
		string strOCType;
		int nAtomType;
		string strLabel;
		GET_LABEL(trAttrib, strLabel);
		if ( trAttrib.GetAttribute(STR_OC_TYPE, strOCType) && strOCType.CompareNoCase(STR_OCTYPE_ARRAY) == 0 )
		{
			if ( trAttrib.GetAttribute(STR_TYPE, nAtomType) && FSI_SHORT == nAtomType )
			{
				vector<short> vshtVals;
				vshtVals = trAttrib.sVals;
				vector<string> vsVals;
				_convert_short_vector_to_string_vector(vshtVals, vsVals, false);
				trAttrib.Reset();
				trAttrib.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);

			}
			else if ( trAttrib.GetAttribute(STR_TYPE, nAtomType) && FSI_LONG == nAtomType )
			{
				vector<int> vnVals;
				vnVals = trAttrib.nVals;
				vector<string> vsVals;
				convert_int_vector_to_string_vector(vnVals, vsVals);

				trAttrib.Reset();
				trAttrib.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
			}
			else if ( trAttrib.GetAttribute(STR_TYPE, nAtomType) && FSI_DOUBLE == nAtomType )
			{
				vector<double> vdVals;
				vdVals = trAttrib.dVals;
				vector<string> vsVals;
				convert_double_vector_to_string_vector(vdVals, vsVals, vdVals.GetSize());
				
				trAttrib.Reset();
				trAttrib.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
			}
			else if ( trAttrib.GetAttribute(STR_TYPE, nAtomType) && FSI_REAL == nAtomType )
			{
				vector<double> vdVals;
				vector<float> vfVals;
				vfVals = trAttrib.fVals;
				vdVals = vfVals;
				vector<string> vsVals;
				convert_double_vector_to_string_vector(vdVals, vsVals, vdVals.GetSize());
				
				trAttrib.Reset();
				trAttrib.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
			}
			else if ( trAttrib.GetAttribute(STR_TYPE, nAtomType) && FSI_CHAR == nAtomType )
			{
				vector<string> vsVals;
				vsVals = trAttrib.strVals;
				trAttrib.Reset();
				trAttrib.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
			}
			else if ( trAttrib.GetAttribute(STR_TYPE, nAtomType) && FSI_INT64 == nAtomType )
			{

				vector<string> vsVals;
				vsVals = trAttrib.strVals;
				trAttrib.Reset();
				trAttrib.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
			}
			else
				ASSERT(FALSE);		
		}
		else
		{
			///Sophy 12/1/2009 ATOM_TYPE_ATTRIBS_NOT_VISIBLE_IN_WKS_ORGANIZER
			if ( trAttrib.Children.Count() > 0 )
			{
				filterAttribs(trAttrib);
			}
			else if ( trAttrib.GetAttribute(STR_OC_TYPE, strOCType) && strOCType.CompareNoCase(STR_OCTYPE_BITFIELD) == 0 )
			{
				vector<string> vsVals;
				vsVals = trAttrib.strVals;
				trAttrib.Reset();
				trAttrib.strVal = get_display_string(vsVals, vsVals.GetSize(), STR_DIMS_SEP);
			}
			else
			{
				string strVal = trAttrib.strVal;
				trAttrib.Reset();
				trAttrib.strVal = strVal;
			}
			///end ATOM_TYPE_ATTRIBS_NOT_VISIBLE_IN_WKS_ORGANIZER
		}
		SET_LABEL(trAttrib, strLabel);
	}
	return true;
}

TreeNode	HDF5::getDatasetInfo(const TreeNode& trDataset)
{
	TreeNode trDatasetInfo;
	if ( trDataset )
	{
		trDatasetInfo = trDataset.Clone(true);
		filterDataset(trDatasetInfo);
		
		TreeNode trAttribs = trDataset.GetNode(STR_OBJ_ATTTRIBS);
		TreeNode trAttribsCopy;
		if ( trAttribs && (trAttribsCopy = trAttribs.Clone(true)) && filterAttribs(trAttribsCopy) )
		{
			foreach(TreeNode trAttrib in trAttribsCopy.Children)
			{
				trDatasetInfo.AddNode(trAttrib, true);
			}
		}
	}
	return trDatasetInfo;
}

bool		HDF5::updateUserTree(OriginObject& obj, LPCSTR lpcszDatasetName, LPCSTR lpcszLabel)
{
	TreeNode trDataset = m_trInfo.FindNodeByAttribute(STR_NAME, lpcszDatasetName, true);
	if ( trDataset )
	{
		string strInfoName(lpcszLabel);
		TreeNode trInfo = getDatasetInfo(trDataset);
		if ( trInfo )
		{
			SET_LABEL(trInfo, strInfoName);
			///---Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
			//trInfo.Show = 0; ///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
			//set_user_info(obj, strInfoName, trInfo);
			fu_set_import_file_info(obj, trInfo, strInfoName, IMPORT_INFO_TO_USER_TREE);
			///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
			///---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
			// roll back move column info out of user tree, as CP said
			//trInfo.Show = 1;
			//strInfoName = lpcszLabel;
			//strInfoName.Insert(0, "HDF5 ");
			//SET_LABEL(trInfo, strInfoName);
			//set_import_file_info(obj, trInfo, strInfoName);
			///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
			///---END QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
		}
		return true;
	}
	return false;
}
///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER

///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
bool		HDF5::isImageType(LPCSTR lpcszDataset)
{
	return checkClassName(lpcszDataset, STR_IMAGECLASS);
}
///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE

///Sophy 9/24/2009 IMPORT_PALETTE_INTO_WORKSHEET
bool		HDF5::isPaletteType(LPCSTR lpcszDataset)
{
	return checkClassName(lpcszDataset, STR_PALETTECLASS);
}

bool		HDF5::checkClassName(LPCSTR lpcszDataset, LPCSTR lpcszClass)
{
	TreeNode trDataset = m_trInfo.FindNodeByAttribute(STR_NAME, lpcszDataset, true); //recursively search
	if ( !trDataset )
		return false;
	
	TreeNode trClass = tree_get_node_by_tagname(trDataset, "CLASS", true, true);
	if ( trClass )
	{
		///Sophy 11/16/2009 QA80-13130-P8 MORE_WORK_ON_HANDLE_HDF5_TYPES
		//string strClassName = trClass.strVal;
		vector<string> vsNames;
		vsNames = trClass.strVals;
		string strClassName = vsNames[0];
		///end MORE_WORK_ON_HANDLE_HDF5_TYPES
		if ( strClassName.Compare(lpcszClass) == 0 )
			return true;
	}
	
	return false;
}
///end IMPORT_PALETTE_INTO_WORKSHEET
int			HDF5::getDatasetDims(TreeNode& trDataset)
{
	if ( !trDataset )
		return -1; //error, will handle outside
	
	TreeNode trDims  = trDataset.GetNode(STR_DATASET_DIMS, false);
	if ( !trDims )
		return -1;
	
	vector<uint> vnDims;
	vnDims = trDims.nVals;
	
	return vnDims.GetSize();
}

int			HDF5::getDataType(TreeNode& trDataset)
{
	if ( !trDataset )
		return -1; //error, should handle outside
	
	TreeNode trType = trDataset.GetNode(STR_OC_TYPE, false);
	if ( !trType )
		return -1;
	
	string strType = trType.strVal;
	return getDataType(strType);
}

int			HDF5::getDataType(LPCSTR lpcszTypeName)
{
	string strType(lpcszTypeName);
	if ( strType.CompareNoCase(STR_OCTYPE_INT) == 0 || strType.CompareNoCase(STR_OCTYPE_LONG) == 0 )
		return FSI_LONG;
	else if ( strType.CompareNoCase(STR_OCTYPE_SHORT) == 0 )
		return FSI_SHORT;
	else if ( strType.CompareNoCase(STR_OCTYPE_DOUBLE) == 0 )
		return FSI_DOUBLE;
	else if ( strType.CompareNoCase(STR_OCTYPE_FLOAT) == 0 )
		return FSI_REAL;
	else if ( strType.CompareNoCase(STR_OCTYPE_STRUCT) == 0 )
		return FSI_MIXED;//struct
	else if ( strType.CompareNoCase(STR_OCTYPE_CHAR) == 0 || strType.CompareNoCase(STR_OCTYPE_STRING) == 0 )
		return FSI_CHAR;
	else if ( strType.CompareNoCase(STR_OCTYPE_ENUM) == 0 ) //extent types
		return FSI_ENUM;
	else if ( strType.CompareNoCase(STR_OCTYPE_OPAQUE) == 0 )
		return FSI_OPAQUE;
	else if ( strType.CompareNoCase(STR_OCTYPE_REFER) == 0 )
		return FSI_REFERENCE;
	else if ( strType.CompareNoCase(STR_OCTYPE_VLEN) == 0 )
		return FSI_VLEN;
	else if ( strType.CompareNoCase(STR_OCTYPE_ARRAY) == 0 )
		return FSI_ARRAY;
	
	return -1; //unknown error, should be handled.
}

HDFstatus	HDF5::constructDatasetFromGroup(hid_t groupID, TreeNode& trParent, int nSubIndex)
{
	string strGroup;
	if ( nSubIndex < 0 ) //groupID is file ID
		strGroup = STR_GROUP;
	else
		strGroup.Format(STR_TAGNAME_FORMAT, STR_GROUP, nSubIndex);
	
	TreeNode trGroup = tree_check_get_node(trParent, strGroup);
	trGroup.SetAttribute(STR_TYPE, H5G_GROUP);
	AUTO_DATAID(trGroup);
	
	string strName;	
	int nLength = H5Iget_name(groupID, NULL, 0);
	LPSTR lpName = strName.GetBuffer(nLength + 1);
	H5Iget_name(groupID, lpName, nLength + 1);
	strName.ReleaseBuffer();
	
	trGroup.SetAttribute(STR_NAME, strName);
	
	SET_LABEL(trGroup, nSubIndex < 0 ? GetFileName(m_strFileName) : _get_dataset_name(strName));
	
	//get attributes info
	int nAttribs = H5Aget_num_attrs(groupID);
	TreeNode	trAtts = tree_check_get_node(trGroup, STR_OBJ_ATTTRIBS);
	AUTO_DATAID(trAtts);
	SET_LABEL(trAtts, STR_ATTRIBUTES);
	for ( int iAttr = 0; iAttr < nAttribs; iAttr++ )
	{
		addOneAttrib(iAttr, groupID, trAtts);
	}

	hsize_t dObjs;
	HDFstatus status = H5Gget_num_objs(groupID, &dObjs);

	uint nObjs;
	_hdf_convert_double_to_uint(dObjs, nObjs); //if OC support unsigned long long, this conversion should be deprecated
	
	int nSubGroup = 0;
	int nSubDataset = 0;
	int nDataType = 0, nLink = 0;	///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
	for ( uint iObj = 0; iObj < nObjs; iObj++ )
	{
		double dIndex;
		_hdf_convert_uint_to_double(iObj, dIndex);
		
		nLength = H5Gget_objname_by_idx(groupID, dIndex, NULL, 0);
		
		strName.Empty();
		lpName = strName.GetBuffer(nLength + 1);
		nLength = H5Gget_objname_by_idx(groupID, dIndex, lpName, nLength + 1);
		strName.ReleaseBuffer();
		
		H5G_obj_t objtype = H5Gget_objtype_by_idx(groupID, dIndex);
		if ( H5G_GROUP == objtype )
		{
			hid_t	gID = H5Gopen1(groupID, strName);
			status = constructDatasetFromGroup(gID, trGroup, nSubGroup++);
			H5Gclose(gID);
			
			ASSERT(status == HDF_SUCCESS);
		}
		else if ( H5G_DATASET == objtype )
		{
			hid_t	dID = H5Dopen1(groupID, strName);
			status = addOneDataset(dID, trGroup, nSubDataset++);
			H5Dclose(dID);
		}
		///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
		else if ( H5G_TYPE == objtype )
		{
			status = addOneDataType(groupID, trGroup, strName, nDataType++);
		}
		else if ( H5G_LINK == objtype )
		{
			status = addOneLink(groupID, trGroup, strName, nLink++);
		}
		else if ( H5G_UDLINK == objtype )
		{
			ASSERT(FALSE);
		}
		///end IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
	}
	trGroup.SetAttribute(STR_SUB_GROUPS, nSubGroup);
	trGroup.SetAttribute(STR_SUB_DATASETS, nSubDataset);
	
	return HDF_SUCCESS;
}

///Sophy 9/14/2009 QA80-14272 IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY
HDFstatus	HDF5::addOneDataType(hid_t groupID, TreeNode& trParent, LPCSTR lpcszTypeName, int nSubIndex)
{
	if ( !trParent )
		return HDF_FAIL;
	
	string strName(lpcszTypeName);
	string strDataType;
	strDataType.Format(STR_TAGNAME_FORMAT, STR_DATATYPE, nSubIndex);
	TreeNode trDataType = tree_check_get_node(trParent, strDataType);
	trDataType.SetAttribute(STR_NAME, strName);
	
	hid_t typeID = H5Topen2(groupID, strName, H5P_DEFAULT);
	
	TreeNode trSize = tree_check_get_node(trDataType, STR_SIZE);
	trSize.nVal = H5Tget_size(typeID);
	
	H5T_class_t tClass = H5Tget_class(typeID);
	trDataType.SetAttribute(STR_TYPE_CLASS, tClass);
	
	trDataType.SetAttribute(STR_TYPE, H5G_TYPE);
	H5Tclose(typeID);
	
	return HDF_SUCCESS;
}

HDFstatus	HDF5::addOneLink(hid_t groupID, TreeNode& trParent, LPCSTR lpcszLinkName, int nSubIndex)
{
	HDFstatus status = HDF_SUCCESS;

	string strParentPath;
	trParent.GetAttribute(STR_NAME, strParentPath);
	H5L_info_t lkInfo;
	if ( H5Lget_info(groupID, lpcszLinkName, &lkInfo, H5P_DEFAULT) == HDF_SUCCESS )
	{
		if ( H5L_TYPE_SOFT == lkInfo.type ) //H5L_TYPE_EXTERNAL not supported.
		{
			string strLinkedObjName;
			LPSTR lpName = strLinkedObjName.GetBuffer(lkInfo.addr_val_size[1]);
			status = H5Lget_val(groupID, lpcszLinkName, lpName, lkInfo.addr_val_size[1], H5P_DEFAULT);
			strLinkedObjName.ReleaseBuffer();
			
			string strLinkedFullName = strParentPath + CHAR_DATASET_PATH_SEP + strLinkedObjName;
			
			string strLink;
			strLink.Format(STR_TAGNAME_FORMAT, STR_LINK, nSubIndex);
			TreeNode trLink = tree_check_get_node(trParent, strLink);;
			SET_LABEL(trLink, lpcszLinkName);
			
			trLink.SetAttribute(STR_TYPE, H5G_LINK);
			trLink.SetAttribute(STR_LINK_OBJ_NAME, strLinkedFullName);
			trLink.strVal = strLinkedObjName;
			
			H5O_info_t objInfo;
			status = H5Oget_info_by_name(groupID, strLinkedObjName, &objInfo, H5P_DEFAULT);
		
			if ( status == HDF_SUCCESS )
			{
				int nType = objInfo.type;
				trLink.SetAttribute(STR_LINK_OBJ_TYPE, nType);
				if ( H5O_TYPE_GROUP == nType ) //link to group;
				{
				}
				else if ( H5O_TYPE_DATASET == nType ) //link to dataset
				{
				}
				else if ( H5O_TYPE_NAMED_DATATYPE == nType ) //link to named datatype
				{
				}
				else
				{
					ASSERT(FALSE); //linked to unknown object
				}
			}
			else
			{
				ASSERT(FALSE); //need to check why come here
			}
		}
	}
	return status;
}

///end IMPORT_HDF5_DATASET_ACCORDING_TO_ORIGINAL_GROUP_CATEGORY

HDFstatus	HDF5::addOneDataset(hid_t DatasetID, TreeNode& trParent, int nSubIndex)
{
	if ( !trParent )
		return HDF_FAIL;
	
	HDFstatus status = HDF_SUCCESS;
	int nLength = H5Iget_name(DatasetID, NULL, 0);
	
	string strName;
	LPSTR lpName = strName.GetBuffer(nLength + 1);
	H5Iget_name(DatasetID, lpName, nLength + 1);
	strName.ReleaseBuffer();
	
	string strDataset;
	strDataset.Format(STR_TAGNAME_FORMAT, STR_DATASET, nSubIndex);
	TreeNode	trDataset = tree_check_get_node(trParent, strDataset);
	trDataset.SetAttribute(STR_TYPE, H5G_DATASET);
	AUTO_DATAID(trDataset);

	trDataset.SetAttribute(STR_NAME, strName);
	
	SET_LABEL(trDataset, _get_dataset_name(strName));

		
	//get type info
	addTypeInfo(DatasetID, trDataset);
	
	//get dimension info.
	addDimInfo(DatasetID, trDataset);
	
	//get attributes info
	int nAttribs = H5Aget_num_attrs(DatasetID);
	TreeNode	trAtts = tree_check_get_node(trDataset, STR_OBJ_ATTTRIBS);
	AUTO_DATAID(trAtts);
	SET_LABEL(trAtts, STR_ATTRIBUTES);
	for ( int ii = 0; ii < nAttribs; ii++ )
	{
		addOneAttrib(ii, DatasetID, trAtts);
	}
		
	return status;
}

HDFstatus	HDF5::addDimInfo(hid_t DatasetID, TreeNode& trDataset)
{
	//get dimension info.
	HDFstatus status = HDF_SUCCESS;
	hid_t		hSpace = H5Dget_space(DatasetID);
	if ( hSpace > 0 && trDataset )
	{
		if ( H5Sis_simple(hSpace)  < 0 )
			return H5Sclose(hSpace); //ignore complex type
		
		int nDims = H5Sget_simple_extent_ndims(hSpace);
		if ( nDims < 0 )
		{
			H5Sclose(hSpace);
			return HDF_FAIL;
		}
		
		vector<hsize_t> vhszDimSizes(nDims);
		vector<hsize_t> vhszMaxSizes(nDims);
		vector<uint>	vnDimSizes(nDims);
		if ( H5Sget_simple_extent_dims(hSpace, vhszDimSizes, vhszMaxSizes) < 0 )
		{
			H5Sclose(hSpace);
			return HDF_FAIL;
		}
		
		_hdf_convert_dvec_to_ivec(vhszDimSizes, vnDimSizes);
		
		TreeNode	trDims = tree_check_get_node(trDataset, STR_DATASET_DIMS);
		AUTO_DATAID(trDims);
		SET_NODEID(trDims, TRGP_STR);
		SET_LABEL(trDims, STR_DIMS_INFO);
		trDims.nVals = vnDimSizes;
		
		status = H5Sclose(hSpace);
	}
	else
		status = HDF_FAIL;
	
	
	return status;
}

HDFstatus	HDF5::addTypeInfo(hid_t DatasetID, TreeNode& trDataset)
{
	//get datatype info
	///Sophy 11/16/2009 QA80-13130-P8 MORE_WORK_ON_HANDLE_HDF5_TYPES
	/*
	if ( hDataType > 0 && trDataset )
	{
		H5T_class_t tClass = H5Tget_class(hDataType);
		TreeNode trOCType = tree_check_get_node(trDataset, STR_OC_TYPE);
		size_t nTypeSize = H5Tget_size(hDataType);
		SET_SIZE(trOCType, nTypeSize);
		SET_LABEL(trOCType, STR_DATASET_DATATYPE);
		AUTO_DATAID(trOCType);
		if ( H5T_INTEGER == tClass )
		{
			trOCType.strVal = STR_OCTYPE_INT;
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
		}
		else if ( H5T_FLOAT == tClass )
		{
			hid_t hNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
			if ( H5Tequal(hNativeType, H5T_NATIVE_FLOAT) )
				trOCType.strVal = STR_OCTYPE_FLOAT;
			else if ( H5Tequal(hNativeType, H5T_NATIVE_DOUBLE) )
				trOCType.strVal = STR_OCTYPE_DOUBLE;
			else if ( H5Tequal(hNativeType, H5T_NATIVE_LDOUBLE) )
				trOCType.strVal = "long double"; //not supported
			else
				ASSERT(FALSE); //sophy, need to add more cases.
			
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
			H5Tclose(hNativeType);
			//trOCType.strVal = STR_OCTYPE_DOUBLE;
		}
		else if ( H5T_COMPOUND == tClass )
		{
			int nColumns = 0; //to calculate how many columns needed to put a element of the compound type, say {int, double, double[4], short} will need 1 + 1 + 4 + 1 = 7 columns
			trOCType.strVal = STR_OCTYPE_STRUCT;
			TreeNode trMembers = tree_check_get_node(trDataset, STR_DATASET_MEMBERS);
			AUTO_DATAID(trMembers);
			
			int nMems = H5Tget_nmembers(hDataType);
			trDataset.SetAttribute(STR_DATASET_MEMBERS, nMems);
			for ( uint iM = 0; iM < nMems; iM++ )
			{
				string strOneMem;
				strOneMem.Format(STR_DATASET_MEMBER_FMT, iM);
				TreeNode trMem = tree_check_get_node(trMembers, strOneMem);
				AUTO_DATAID(trMem);
				
				char* name = H5Tget_member_name(hDataType, iM);
				string strMemName(name);
				SET_LABEL(trMem, strMemName);
				///Sophy 9/28/2009 QA80-14370 FAIL_TO_IMPORT_HDF5_FILE_IN_VISTA_WHEN_FREE_CAUSE_INTERNAL_EXCEPTION
				//free(name);
				try 
				{
					free(name);
				}
				catch(int nErr)
				{
					//ignore any exception as to continue the importing process, only come here in Vista, I am not sure why has this kind of exception
				}
				///end FAIL_TO_IMPORT_HDF5_FILE_IN_VISTA_WHEN_FREE_CAUSE_INTERNAL_EXCEPTION
				
				TreeNode trType = tree_check_get_node(trMem, STR_OC_TYPE);
				SET_LABEL(trType, STR_DATASET_DATATYPE);
				AUTO_DATAID(trType);
				
				hid_t memType = H5Tget_member_type(hDataType, iM);
				size_t nMemTypeSize = H5Tget_size(memType);
				SET_SIZE(trType, nMemTypeSize);
				tClass = H5Tget_class(memType);
				string strType = "";
				if ( H5T_ARRAY == tClass )
				{
					hid_t hSuper = H5Tget_super(memType);
					if ( H5Tequal(hSuper, H5T_NATIVE_INT) )
						strType = STR_OCTYPE_INT;
					else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
						strType = STR_OCTYPE_FLOAT;
					else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
						strType = STR_OCTYPE_DOUBLE;
					else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
						strType = STR_OCTYPE_SHORT;
					else if ( H5Tequal(hSuper, H5T_NATIVE_LONG) )
						strType = STR_OCTYPE_LONG;
					else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
						strType = STR_OCTYPE_CHAR;
					else
						ASSERT(FALSE); //need to add more cases if come here
					
					H5Tclose(hSuper);
					trType.SetAttribute(STR_OC_TYPE, strType);
					strType = STR_OCTYPE_ARRAY;
					
					int nDims = H5Tget_array_ndims(memType);
					vector<hsize_t> vshDims(nDims);
					H5Tget_array_dims2(memType, vshDims);
					vector<uint> vnDims;
					_hdf_convert_dvec_to_ivec(vshDims, vnDims);
					TreeNode trDims = tree_check_get_node(trMem, STR_DATASET_DIMS);
					AUTO_DATAID(trDims);
					SET_LABEL(trDims, STR_DIMS_INFO);
					trDims.nVals = vnDims;
					
					///Sophy 9/25/2009 SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
					//int nElements = 1;
					//for ( int ii = 0; ii < vnDims.GetSize(); ii++ )
						//nElements *= vnDims[ii];
					//
					//nColumns += nElements; //array type
					nColumns++; //put array in compound type in one column
					///end SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
					
				}
				///Sophy 7/31/2009 SUPPORT_ONE_LEVEL_NESTED_COMPOUND_DATATYPE
				else if ( H5T_COMPOUND == tClass )
				{
#ifndef	_SUPPORT_NESTED_STRUCT_
					printf("Nested compound type not supported!");
					ASSERT(FALSE);
#else
					strType = STR_OCTYPE_STRUCT; //nested struct
					TreeNode trMembers = tree_check_get_node(trMem, STR_DATASET_MEMBERS);
					AUTO_DATAID(trMembers);
					int nMems = H5Tget_nmembers(memType);
					trMem.SetAttribute(STR_DATASET_MEMBERS, nMems);
					
					for ( uint iSubMem; iSubMem < nMems; iSubMem++ )
					{
						string strOneMem;
						strOneMem.Format(STR_DATASET_MEMBER_FMT, iSubMem);
						TreeNode trSubMem = tree_check_get_node(trMembers, strOneMem);
						AUTO_DATAID(trSubMem);
						
						char* name = H5Tget_member_name(memType, iSubMem);
						string strMemName(name);
						SET_LABEL(trSubMem, strMemName);
						///Sophy 9/28/2009 QA80-14370 FAIL_TO_IMPORT_HDF5_FILE_IN_VISTA_WHEN_FREE_CAUSE_INTERNAL_EXCEPTION
						//free(name);
						try 
						{
							free(name);
						}
						catch(int nErr)
						{
							//ignore any exception as to continue the importing process, only come here in Vista, I am not sure why has this kind of exception
						}
						///end FAIL_TO_IMPORT_HDF5_FILE_IN_VISTA_WHEN_FREE_CAUSE_INTERNAL_EXCEPTION
						
						TreeNode trType = tree_check_get_node(trSubMem, STR_OC_TYPE);
						SET_LABEL(trType, STR_DATASET_DATATYPE);
						AUTO_DATAID(trType);
						
						hid_t SubMemType = H5Tget_member_type(memType, iSubMem);
						size_t nSubMemTypeSize = H5Tget_size(SubMemType);
						SET_SIZE(trType, nSubMemTypeSize);
						tClass = H5Tget_class(SubMemType);
						string strType = "";
						if ( H5T_ARRAY == tClass )
						{
							hid_t hSuper = H5Tget_super(SubMemType);
							
							if ( H5Tequal(hSuper, H5T_NATIVE_INT) )
								strType = STR_OCTYPE_INT;
							else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
								strType = STR_OCTYPE_FLOAT;
							else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
								strType = STR_OCTYPE_DOUBLE;
							else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
								strType = STR_OCTYPE_SHORT;
							else if ( H5Tequal(hSuper, H5T_NATIVE_LONG) )
								strType = STR_OCTYPE_LONG;
							else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
								strType = STR_OCTYPE_CHAR;
							else
								ASSERT(FALSE); //need to add more cases if come here
							
							H5Tclose(hSuper);
							trType.SetAttribute(STR_OC_TYPE, strType);
							strType = STR_OCTYPE_ARRAY;
							
							int nDims = H5Tget_array_ndims(SubMemType);
							vector<hsize_t> vshDims(nDims);
							H5Tget_array_dims2(memType, vshDims);
							vector<uint> vnDims;
							_hdf_convert_dvec_to_ivec(vshDims, vnDims);
							TreeNode trDims = tree_check_get_node(trSubMem, STR_DATASET_DIMS);
							AUTO_DATAID(trDims);
							SET_LABEL(trDims, STR_DIMS_INFO);
							trDims.nVals = vnDims;
							
							///Sophy 9/25/2009 SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE
							//int nElements = 1;
							//for ( int ii = 0; ii < vnDims.GetSize(); ii++ )
								//nElements *= vnDims[ii];
							//
							//nColumns += nElements; //array type
							nColumns++; //put array in compound type in single column
							///end SUPPORT_ARRAY_OF_MULTI_DIMS_IN_COMPOUND_TYPE

						}
						else if ( H5T_COMPOUND == tClass )
						{
							printf("No more level of nested struct supported!");
							ASSERT(FALSE);
						}
						else
						{
							hid_t hNative = H5Tget_native_type(SubMemType, H5T_DIR_DEFAULT);
							if ( H5Tequal(hNative, H5T_NATIVE_INT) )
								strType = STR_OCTYPE_INT;
							else if ( H5Tequal(hNative, H5T_NATIVE_FLOAT) )
								strType = STR_OCTYPE_FLOAT;
							else if ( H5Tequal(hNative, H5T_NATIVE_DOUBLE) )
								strType = STR_OCTYPE_DOUBLE;
							///Sophy 7/24/2009 IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
							else if ( H5Tequal(hNative, H5T_NATIVE_LONG) )
								strType = STR_OCTYPE_LONG;
							else if ( H5Tequal(hNative, H5T_NATIVE_SHORT) )
								strType = STR_OCTYPE_SHORT;
							///end IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
							///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
							else if ( H5Tequal(hNative, H5T_STRING) )
								strType = STR_OCTYPE_CHAR;
							///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
							else
								ASSERT(FALSE); //need to add more cases.
							
							nColumns++; //atom type
							H5Tclose(hNative);
						}
						trType.strVal = strType;
						H5Tclose(SubMemType);
					}
#endif	//_SUPPORT_NESTED_STRUCT_
				}
				///end SUPPORT_ONE_LEVEL_NESTED_COMPOUND_DATATYPE
				else
				{
					hid_t hNative = H5Tget_native_type(memType, H5T_DIR_DEFAULT);
					if ( H5Tequal(hNative, H5T_NATIVE_INT) )
						strType = STR_OCTYPE_INT;
					else if ( H5Tequal(hNative, H5T_NATIVE_FLOAT) )
						strType = STR_OCTYPE_FLOAT;
					else if ( H5Tequal(hNative, H5T_NATIVE_DOUBLE) )
						strType = STR_OCTYPE_DOUBLE;
					///Sophy 7/24/2009 IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
					else if ( H5Tequal(hNative, H5T_NATIVE_LONG) )
						strType = STR_OCTYPE_LONG;
					else if ( H5Tequal(hNative, H5T_NATIVE_SHORT) )
						strType = STR_OCTYPE_SHORT;
					///end IMPORT_MEMBER_OF_SHORT_AND_LONG_TYPE_IN_COMPOUND_DATATYPE
					///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
					else if ( H5Tequal(hNative, H5T_STRING) )
						strType = STR_OCTYPE_CHAR;
					///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
					else
						ASSERT(FALSE); //need to add more cases.
					
					nColumns++; //atom type
					H5Tclose(hNative);
				}
				trType.strVal = strType;
				H5Tclose(memType);
			}
			trDataset.SetAttribute(STR_DATASET_SCOPE, nColumns);
		}
		else if ( H5T_ARRAY == tClass )
		{
			hid_t hSuper = H5Tget_super(hDataType);
			string strType;
			if ( H5Tequal(hSuper, H5T_NATIVE_INT) )
				strType = STR_OCTYPE_INT;
			else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
				strType = STR_OCTYPE_FLOAT;
			else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
				strType = STR_OCTYPE_DOUBLE;
			else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
				strType = STR_OCTYPE_SHORT;
			else if ( H5Tequal(hSuper, H5T_NATIVE_LONG) )
				strType = STR_OCTYPE_LONG;
			else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
				strType = STR_OCTYPE_CHAR;
			else
				ASSERT(FALSE); //need to add more cases if come here
			
			H5Tclose(hSuper);
			trOCType.SetAttribute(STR_OC_TYPE, strType);
			trOCType.strVal = strType;
			
			int nDims = H5Tget_array_ndims(hDataType);
			vector<hsize_t> vshDims(nDims);
			H5Tget_array_dims2(hDataType, vshDims);
			vector<uint> vnDims;
			_hdf_convert_dvec_to_ivec(vshDims, vnDims);
			TreeNode trDims = tree_check_get_node(trDataset, STR_DATASET_DIMS);
			AUTO_DATAID(trDims);
			SET_LABEL(trDims, STR_DIMS_INFO);
			trDims.nVals = vnDims;

			trDataset.SetAttribute(STR_DATASET_SCOPE, 1); //put in single column
		}
		else if ( H5T_BITFIELD == tClass )
		{
			trOCType.strVal = STR_OCTYPE_BITFIELD;
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
		}
		else if ( H5T_ENUM == tClass )
		{
			trOCType.strVal = STR_OCTYPE_ENUM;
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
		}
		else if ( H5T_OPAQUE == tClass )
		{
			trOCType.strVal = STR_OCTYPE_OPAQUE;
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
		}
		else if ( H5T_REFERENCE == tClass )
		{
			trOCType.strVal = STR_OCTYPE_REFER;
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
		}
		else if ( H5T_VLEN == tClass )
		{
			trOCType.strVal = STR_OCTYPE_VLEN;
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
		}
		///Sophy 7/20/2009 SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
		else if ( H5T_STRING == tClass )
		{
			trOCType.strVal = STR_OCTYPE_CHAR;
			trDataset.SetAttribute(STR_DATASET_SCOPE, 1);
			hid_t		hSpace = H5Dget_space(DatasetID);
			if ( H5Tis_variable_str(hSpace) )
				trDataset.SetAttribute(STR_VL_STR, VL_STRING_TYPE);
			H5Sclose(hSpace);
		}
		///end SUPPORT_IMPORT_DATASET_OF_STRING_TYPE_IMAGE_TYPE
		else
			ASSERT(FALSE); //sophy, need to add more cases.
		
		status = H5Tclose(hDataType);
	}
	else
		status = HDF_FAIL;
	
	return status;
	*/
	HDFstatus status = HDF_SUCCESS;
	hid_t hDataType = H5Dget_type(DatasetID);
	hid_t hSpace = H5Dget_space(DatasetID);
	int nCols = _construct_compound_type_info(hSpace, hDataType, trDataset, m_nNodeID);
	if ( nCols < 0 )
		status = HDF_FAIL;
	
	H5Sclose(hSpace);
	H5Tclose(hDataType);
	
	return status;
	///end MORE_WORK_ON_HANDLE_HDF5_TYPES
}

HDFstatus	HDF5::addOneAttrib(int nAttIndex, hid_t loc_ID, TreeNode& trParent)
{
	if ( !trParent )
		return HDF_FAIL;
	
	hid_t attID = H5Aopen_idx(loc_ID, nAttIndex);
	if ( attID > 0 )
	{
		ssize_t nSize = H5Aget_name(attID, 0, NULL);
		string strName;
		LPSTR lpName = strName.GetBuffer(nSize + 1);
		H5Aget_name(attID, nSize + 1, lpName);
		strName.ReleaseBuffer();
		
		string strLabel = strName;
		
		strName.MakeValidCName();
		TreeNode	trOneAttrib = tree_check_get_node(trParent, strName);
		AUTO_DATAID(trOneAttrib);
		SET_LABEL(trOneAttrib, strLabel);
		
		hid_t hSpace = H5Aget_space(attID);
		hid_t typeID = H5Aget_type(attID);
		H5T_class_t type = H5Tget_class(typeID);
		hid_t hNativeType = H5Tget_native_type(typeID, H5T_DIR_DEFAULT);
		
		if ( hSpace < 0 )
		{
			H5Tclose(typeID);
			H5Aclose(attID);
			return HDF_FAIL;
		}
		int nDims = H5Sget_simple_extent_ndims(hSpace);
		
		vector<hsize_t> vshAttDims(nDims);
		H5Sget_simple_extent_dims(hSpace, vshAttDims, NULL);
		vector<uint> vnAttDims(nDims);
		_hdf_convert_dvec_to_ivec(vshAttDims, vnAttDims);
		uint nPts = 1;
		for ( int ii = 0; ii < nDims; ii++ )
			nPts *= vnAttDims[ii];
		
		switch ( type )
		{
		case H5T_INTEGER:
			
			///Sophy 9/7/2009 SUPPORT_ONE_DIMENSION_WITH_SIZE_LARGER_THAN_ONE
			if ( nPts > 1 )
			{
				vector<int> vnVals(nPts);
				herr_t err = H5Aread(attID, H5T_NATIVE_INT, vnVals);
				trOneAttrib.nVals = vnVals;
				trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				SET_NODEID(trOneAttrib, TRGP_STR);
			}
			/// SUPPORT_ONE_DIMENSION_WITH_SIZE_LARGER_THAN_ONE
			else
			{
				int nVal;
				herr_t err = H5Aread(attID, H5T_NATIVE_INT, &nVal);
				trOneAttrib.nVal = nVal;
				SET_NODEID(trOneAttrib, ONODETYPE_EDIT_BOX_NUMERIC_INT);
			}
			trOneAttrib.SetAttribute(STR_TYPE, FSI_LONG);
			break;
			
		case H5T_FLOAT:
			
			///Sophy 9/7/2009 SUPPORT_ONE_DIMENSION_WITH_SIZE_LARGER_THAN_ONE
			hid_t hNativeType = H5Tget_native_type(typeID, H5T_DIR_DEFAULT);
			bool bFloat = H5Tequal(hNativeType, H5T_NATIVE_FLOAT);
			if ( nPts > 1 )
			{
				if ( bFloat ) //float
				{
					vector<float> vfVals(nPts);
					herr_t err = H5Aread(attID, H5T_NATIVE_FLOAT, vfVals);
					trOneAttrib.fVals = vfVals;
				}
				else //double
				{
					vector<double> vdVals(nPts);
					herr_t err = H5Aread(attID, H5T_NATIVE_DOUBLE, vdVals);
					trOneAttrib.dVals = vdVals;
				}
				trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				SET_NODEID(trOneAttrib, TRGP_STR);
			}
			/// SUPPORT_ONE_DIMENSION_WITH_SIZE_LARGER_THAN_ONE
			else 
			{
				double dVal;
				herr_t err = H5Aread(attID, H5T_NATIVE_DOUBLE, &dVal);
				trOneAttrib.dVal = dVal;
				SET_NODEID(trOneAttrib, TRGP_DOUBLE);
			}
			trOneAttrib.SetAttribute(STR_TYPE, bFloat ? FSI_REAL : FSI_DOUBLE);
			break;
			
		case H5T_STRING:

			int nSize = H5Tget_size(typeID);
			hid_t memType = H5Tcopy(typeID);
			
			if ( H5Tis_variable_str(typeID) )
			{
				H5Tset_size(memType, H5T_VARIABLE);
				char** vars = (char**)malloc(nSize * sizeof(int));//sizeof(char*) will cause compile error, I have to use int instead of char*
				H5Aread(attID, memType, vars);
				
				vector<string> vsAttribVals;
				for ( int ii = 0; ii < nSize; ii++ )
				{
					string strVal(vars[ii]);
					vsAttribVals.Add(strVal);
				}
				H5Dvlen_reclaim(memType, hSpace, H5P_DEFAULT, vars);
				free(vars);
				trOneAttrib.strVals = vsAttribVals;
				trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
			}
			else
			{
				///Sophy 11/17/2009 HANDLE_MULTI_DIMENSIONALITY_STRING_ARRAY
				//H5Tset_size(memType, nSize + 1); //null for terminate
				//string strVal;
				//LPSTR lpVal = strVal.GetBuffer(nSize + 1);
				//H5Aread(attID, memType, lpVal);
				//strVal.ReleaseBuffer();
				//trOneAttrib.strVal = strVal;
				char* cBuffer = (char*)malloc(nSize * nPts * sizeof(char));
				H5Aread(attID, typeID, cBuffer);
				LPSTR lp = cBuffer;
				vector<string> vsVals(nPts);
				string strTemp;
				for ( int iPts = 0; iPts < nPts; iPts++ )
				{
					lp = cBuffer + nSize * iPts;
					LPSTR lpStr = strTemp.GetBuffer(nSize);
					strncpy(lpStr, lp, nSize);
					strTemp.ReleaseBuffer();
					vsVals[iPts] = strTemp;
				}
				free(cBuffer);
				trOneAttrib.strVals = vsVals;
				trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				///end HANDLE_MULTI_DIMENSIONALITY_STRING_ARRAY
			}
			trOneAttrib.SetAttribute(STR_TYPE, FSI_CHAR);
			SET_NODEID(trOneAttrib, TRGP_STR);

			break;
		
		///Sophy 9/8/2009 QA80-14271 DISPLAY_VARIABLE_INFO_IN_ORGANIZER	
		case H5T_REFERENCE:

			hobj_ref_t* refbuf = (hobj_ref_t*)malloc(sizeof(hobj_ref_t) * nPts);
			H5Aread(attID, typeID, refbuf);

			hid_t palID = H5Rdereference(loc_ID, H5R_OBJECT, &refbuf);
			
			string strRefName;
			int nLength = H5Iget_name(palID, NULL, 0);
			LPSTR lpName = strRefName.GetBuffer(nLength + 1);
			H5Iget_name(palID, lpName, nLength + 1);
			strRefName.ReleaseBuffer();
			
			free(refbuf);
			H5Dclose(palID);
			trOneAttrib.strVal = strRefName;
			trOneAttrib.SetAttribute(STR_TYPE, FSI_CHAR);
			SET_NODEID(trOneAttrib, TRGP_STR);
			break;
		///end DISPLAY_VARIABLE_INFO_IN_ORGANIZER
		
		///Sophy 11/16/2009 QA80-13130-P8 MORE_WORK_ON_HANDLE_HDF5_TYPES
		case H5T_BITFIELD:
			
			vector<string> vsVals;
			if ( H5Tequal(hNativeType, H5T_NATIVE_B8) )
			{
				vector<byte> vbVals(nPts);
				H5Aread(attID, H5T_NATIVE_B8, vbVals);
				_convert_byte_vector_to_string_vector(vbVals, vsVals);
				trOneAttrib.SetAttribute(STR_TYPE, FSI_BIT_8);			
			}
			else if ( H5Tequal(hNativeType, H5T_NATIVE_B16) )
			{
				vector<short> vstVals(nPts);
				H5Aread(attID, H5T_NATIVE_B16, vstVals);
				_convert_short_vector_to_string_vector(vstVals, vsVals);
				trOneAttrib.SetAttribute(STR_TYPE, FSI_BIT_16);			
			}
			else if ( H5Tequal(hNativeType, H5T_NATIVE_B32) )
			{
				vector<int> vnVals(nPts);
				H5Aread(attID, H5T_NATIVE_B32, vnVals);
				_convert_int_vector_to_string_vector(vnVals, vsVals);
				trOneAttrib.SetAttribute(STR_TYPE, FSI_BIT_32);
			}
			else if ( H5Tequal(hNativeType, H5T_NATIVE_B64) )
			{
				vector<double> vdVals(nPts);
				H5Aread(attID, H5T_NATIVE_B64, vdVals);
				_convert_int64_vector_to_string_vector(vdVals, vsVals);
				trOneAttrib.SetAttribute(STR_TYPE, FSI_BIT_64);
			}
			else
				ASSERT(FALSE);
			
			trOneAttrib.strVals = vsVals;
			trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_BITFIELD);
			SET_NODEID(trOneAttrib, TRGP_STR);
			
			break;
			
		case H5T_COMPOUND:
			
			trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_STRUCT); //compound
			_construct_compound_type_info(hSpace, typeID, trOneAttrib, m_nNodeID);
			
			break;
			
		case H5T_ENUM:
			
			int nMembers = H5Tget_nmembers(typeID);
			vector<string> vsVals;
			vector<int> vnVals(nMembers);
			for ( int iMem = 0; iMem < nMembers; iMem++ )
			{
				char* lpName = H5Tget_member_name(typeID, iMem);
				vsVals.Add(lpName);
				
				H5Tenum_valueof(typeID, lpName, &vnVals[iMem]);
				
				_safe_free(lpName);
			}
			
			TreeNode trNames = tree_check_get_node(trOneAttrib, STR_ENUM_NAMES);
			trNames.strVals = vsVals;
			trNames.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
			trNames.SetAttribute(STR_TYPE, FSI_CHAR);
			
			TreeNode trValues = tree_check_get_node(trOneAttrib, STR_ENUM_VALUES);
			trValues.nVals = vnVals;
			trValues.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
			trValues.SetAttribute(STR_TYPE, FSI_LONG);
			
			trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ENUM);
			SET_NODEID(trOneAttrib, TRGP_STR);
			break;
			
		case H5T_VLEN:
			
			hvl_t* vlBuffer = (hvl_t*)malloc(nPts * sizeof(hvl_t));
			
			hid_t hSuper = H5Tget_super(typeID);
			hid_t memtype = H5Tcopy(hNativeType);
			
			H5Aread(attID, memtype, vlBuffer);
			
			if ( H5Tequal(hSuper, H5T_NATIVE_INT) || H5Tequal(hSuper, H5T_NATIVE_LONG) )
			{
				for ( int ii = 0; ii < nPts; ii++ )
				{
					string strMem;
					strMem.Format(STR_DATASET_MEMBER_FMT, ii);
					TreeNode trOneEle = tree_check_get_node(trOneAttrib, strMem);
					
					vector<int> vnVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vnVals[iEle] = (int)*((int*)vlBuffer[ii].p + iEle);
					}
					
					trOneEle.nVals = vnVals;
					trOneEle.SetAttribute(STR_TYPE, FSI_LONG);
					trOneEle.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
			{
				for ( int ii = 0; ii < nPts; ii++ )
				{
					string strMem;
					strMem.Format(STR_DATASET_MEMBER_FMT, ii);
					TreeNode trOneEle = tree_check_get_node(trOneAttrib, strMem);
					
					vector<short> vstVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vstVals[iEle] = (short)*((short*)vlBuffer[ii].p + iEle);
					}
					
					trOneEle.sVals = vstVals;
					trOneEle.SetAttribute(STR_TYPE, FSI_SHORT);
					trOneEle.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
			{
				for ( int ii = 0; ii < nPts; ii++ )
				{
					string strMem;
					strMem.Format(STR_DATASET_MEMBER_FMT, ii);
					TreeNode trOneEle = tree_check_get_node(trOneAttrib, strMem);
					
					vector<float> vfVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vfVals[iEle] = (float)*((float*)vlBuffer[ii].p + iEle);
					}
					
					trOneEle.fVals = vfVals;
					trOneEle.SetAttribute(STR_TYPE, FSI_REAL);
					trOneEle.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
			{
				for ( int ii = 0; ii < nPts; ii++ )
				{
					string strMem;
					strMem.Format(STR_DATASET_MEMBER_FMT, ii);
					TreeNode trOneEle = tree_check_get_node(trOneAttrib, strMem);
					
					vector<double> vdVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vdVals[iEle] = (double)*((double*)vlBuffer[ii].p + iEle);
					}
					
					trOneEle.dVals = vdVals;
					trOneEle.SetAttribute(STR_TYPE, FSI_DOUBLE);
					trOneEle.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				}
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
			{
				for ( int ii = 0; ii < nPts; ii++ )
				{
					string strMem;
					strMem.Format(STR_DATASET_MEMBER_FMT, ii);
					TreeNode trOneEle = tree_check_get_node(trOneAttrib, strMem);
					
					vector<byte> vbVals(vlBuffer[ii].len);
					for ( int iEle = 0; iEle < vlBuffer[ii].len; iEle++ )
					{
						vbVals[iEle] = (byte)*((byte*)vlBuffer[ii].p + iEle);
					}
					
					trOneEle.bVals = vbVals;
					trOneEle.SetAttribute(STR_TYPE, FSI_BYTE);
					trOneEle.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
				}
			}
			
			trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_VLEN);
			H5Dvlen_reclaim(memtype, hSpace, H5P_DEFAULT, vlBuffer);
			free(vlBuffer);
			H5Tclose(memtype);
			break;
			
		case H5T_ARRAY:
			
			int nArrDims = H5Tget_array_ndims(typeID);
			vector<hsize_t> vshArrDims(nArrDims);
			H5Tget_array_dims2(typeID, vshArrDims);
			vector<uint> vnArrDims(nArrDims);
			_hdf_convert_dvec_to_ivec(vshArrDims, vnArrDims);
			for ( int iArrDim = 0; iArrDim < nArrDims; iArrDim++ )
				nPts *= vnArrDims[iArrDim];
			
			vector<uint> vnMemDims(1);
			vector<hsize_t> vshMemDims(1);
			vnMemDims[0] = nPts;
			_hdf_convert_ivec_to_dvec(vnMemDims, vshMemDims);

			hid_t memtype;
			hid_t hSuper = H5Tget_super(typeID);
			if ( H5Tequal(hSuper, H5T_NATIVE_INT) || H5Tequal(hSuper, H5T_NATIVE_LONG) )
			{
				vector<int> vnVals(nPts);
				memtype = H5Tarray_create2(H5T_NATIVE_INT, 1, vshArrDims);
				H5Aread(attID, memtype, vnVals);
				trOneAttrib.nVals = vnVals;
				trOneAttrib.SetAttribute(STR_TYPE, FSI_LONG);
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_SHORT) )
			{
				vector<short> vstVals(nPts);
				memtype = H5Tarray_create2(H5T_NATIVE_SHORT, 1, vshArrDims);
				H5Aread(attID, memtype, vstVals);
				trOneAttrib.sVals = vstVals;
				trOneAttrib.SetAttribute(STR_TYPE, FSI_SHORT);
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_FLOAT) )
			{
				vector<float> vfVals(nPts);
				memtype = H5Tarray_create2(H5T_NATIVE_FLOAT, 1, vshArrDims);
				H5Aread(attID, memtype, vfVals);
				trOneAttrib.fVals = vfVals;
				trOneAttrib.SetAttribute(STR_TYPE, FSI_REAL);
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_DOUBLE) )
			{
				vector<double> vdVals(nPts);
				memtype = H5Tarray_create2(H5T_NATIVE_DOUBLE, 1, vshArrDims);
				H5Aread(attID, memtype, vdVals);
				trOneAttrib.dVals = vdVals;
				trOneAttrib.SetAttribute(STR_TYPE, FSI_DOUBLE);
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_CHAR) )
			{
				vector<byte> vbVals(nPts);
				memtype = H5Tarray_create2(H5T_NATIVE_CHAR, 1, vshArrDims);
				H5Aread(attID, memtype, vbVals);
				trOneAttrib.bVals = vbVals;
				trOneAttrib.SetAttribute(STR_TYPE, FSI_BYTE);
			}
			else if ( H5Tequal(hSuper, H5T_NATIVE_INT64) )
			{
				double* pBuffer = (double*)malloc(nPts * sizeof(double));
				H5Aread(attID, typeID, pBuffer);

				vector<string> vs;
				_hdf_int64_vector_to_string_vector(pBuffer, nPts, vs);
				trOneAttrib.strVals = vs;
				
				trOneAttrib.SetAttribute(STR_TYPE, FSI_INT64);
				free(pBuffer);
			}
			trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);
			H5Tclose(memtype);
			H5Tclose(hSuper);
			break;
			
		case H5T_OPAQUE:
			int nLength = H5Tget_size(typeID);
			char* tag = H5Tget_tag(typeID);
			string strTag(tag);
			trOneAttrib.SetAttribute(STR_TAG_ATTRIB, strTag);
			
			char* vars = (char*)malloc(nPts * nLength);
			H5Aread(attID, typeID, vars);
			vector<string> vsVals(nPts);
			string strTemp;
			LPSTR lp = vars;
			for ( int ii = 0; ii < nPts; ii++ )
			{
				lp = vars + ii * nLength;
				LPSTR lpBuffer = strTemp.GetBuffer(nLength);
				strncpy(lpBuffer, lp, nLength);
				strTemp.ReleaseBuffer();
				vsVals[ii] = strTemp;
			}
			trOneAttrib.strVals = vsVals;
			trOneAttrib.SetAttribute(STR_TYPE, FSI_CHAR);
			trOneAttrib.SetAttribute(STR_OC_TYPE, STR_OCTYPE_ARRAY);

			free(vars);
			_safe_free(tag);
			
			break;
			
		default:
			ASSERT(FALSE);
			break; //ignore other type of attribute value
		}
		H5Tclose(hNativeType);
		H5Tclose(typeID);
	}
	else
		return HDF_FAIL;
	H5Aclose(attID);
	
	return HDF_SUCCESS;
}

bool		HDF5::checkValidFile(LPCSTR lpcszFileName)
{
	if ( H5Fis_hdf5(lpcszFileName) <= 0 )
		return false;
	
	return true;
}

bool		HDF5::checkIsOneD(const vector<uint>& vnDims)
{
	for ( int ii = vnDims.GetSize() - 2; ii >= 0; ii--)
	{
		if ( vnDims[ii] != 1 )
			return false;
	}
	
	return true; //0 dim or 1 dim or has dim vector like [1, 1...1, lastdimsize];
}



