/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//機能名称 
//		  CMI ユーティリティ クラス
//変更履歴
//			  2003.11.24	zcj  新規作成		
//
package jp.co.ntt.lms.lo.scorm.cbtcom;

//import java.util.StringTokenizer;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.io.IOException;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.BitSet;
import java.util.Vector;
import java.util.Calendar;
import java.util.Properties;


/**
 * CMI ユーティリティ クラス <BR>
 * @author zhaicj
 * 
 */
public class CMIUtil {

	private static final String CR_ONLY="\n";
	
	private static final String LF_ONLY="\r";

	/**
	 * エンコード文字列 <BR>
	 */
	private static String m_strEncode;

	
	/**
	 * クラスの終了処理 <BR>
	 */
	public void finalize() {
	}
	/**																			
	 * グローバルインスタンスを生成する<br>																		
	 * @param proto CMIElementProto																		
	 * @param node CMINode																		
	 * @return CMIElement																		
	 */																		
	public static CMIElement makeGlobalInstance(CMIElementProto proto, CMINode node) {
		CMIElement element = null;
		CMIGlobalCBT gcbt = null;
		StringBuffer sbKeyPath = new StringBuffer();

		gcbt = node.getGCBT();
		//String strKeyPath = node.getKeyPath();
		boolean blnKey = node.getKeyPath(sbKeyPath);
		
		if ( blnKey ) {
			// 管理対象
			sbKeyPath.append(".");
			sbKeyPath.append( proto.getName() );

			// 新規に生成
			element = makeGlobalProto2Instance( proto, node );
			node.addChild( element );

			// グローバルノードの場合は、管理に登録する。
			if ( element.isGlobal() ) {
				String strKey = sbKeyPath.toString();
				gcbt.addPathElement(strKey, element);
			}
			makeGlobalChildInstance(element);
		} else {
			// 管理対象外
			// ※ 規格上、存在しないケースなので、必要に応じて見直しが必要である。
			// 新規に生成
			element = makeGlobalProto2Instance(proto, node);
			node.addChild( element );
			makeGlobalChildInstance( element );
		}
		return element;
	}
   
	/**																		
	 * インスタンスを生成する<br>																	
	 * @param proto CMIElementProto																	
	 * @param node CMINode																	
	 * @return インスタンス CMIElement																	
	 */																	
	public static CMIElement makeInstance(CMIElementProto proto, CMINode node) {
		
		CMIElement element = null;
		CMIGlobalCBT gcbt = null;
		CMICBT cbt = null;
		
		StringBuffer sbKeyPath = new StringBuffer();

		gcbt = CMIGlobalCBT.getGlobalCBT();
		cbt = node.getCBT();
		
		//String strKeyPath = node.getKeyPath();
		boolean blnKey = node.getKeyPath(sbKeyPath);
		
		//if ( strKeyPath != null && !"".equals(strKeyPath ) ) {
		if( blnKey ){
			// 管理対象
			sbKeyPath.append(".");
			sbKeyPath.append(proto.getName());
			
			// グローバル
			String strKey = sbKeyPath.toString();
			if (gcbt != null) {
				element = gcbt.getPath2Element( strKey );
			}
			if ( element != null ) {
				node.addChildLink( element );
			} else {
				// ローカル
				if(cbt != null) {
					element = cbt.getPath2Element( strKey );
				}
				if (element == null) {
					// 新規に生成
					element = makeProto2Instance(proto, node);
					node.addChild(element);

					cbt.addPathElement(strKey, element);
					makeChildInstance(element);
				} else {
					node.addChildLink(element);
				}
			}
		} else {
			// 管理対象外
			// 新規に生成
			element = makeProto2Instance(proto, node);
			node.addChild(element);
			makeChildInstance(element);
		}
		return element;
	}
   
	/**																		
	 * 単語の1文字目を大文字にした他を小文字にした名前を返す。<br>
	 * lesson_status  ->Lesson_Status<br>																	
	 * @param name String																	
	 * @return 生成キーワード名 String																	
	 */																	
	public static String makeKeyWord(String name) {
		String strWord = null;
		StringBuffer strKeyWord = new StringBuffer();
//		StringTokenizer strTokenizerWords = new StringTokenizer(name, "_");
		CMITokenizer strTokenizerWords = new CMITokenizer(name, "_");

		while( strTokenizerWords.hasMoreTokens() ) {
			strWord = strTokenizerWords.nextToken();
			strWord = strWord.toLowerCase();
			
			char chr = strWord.charAt(0);
			String strvo = String.valueOf(chr); 
			strvo = strvo.toUpperCase();
			StringBuffer sb = new StringBuffer();
			String str = strWord.substring(1);
			sb.append(strvo);
			sb.append(str); 		
			strWord = sb.toString();

			strKeyWord.append(strWord);
			if( !strTokenizerWords.hasMoreTokens() ) {
				break;
			}
			strKeyWord.append("_");
		}
		return strKeyWord.toString();
	}
   
	/**																		
	 * URL エンコード<br>																	
	 * @param url String																	
	 * @return エンコード文字列 String																	
	 */														
	public static String urlEncode(String url) {

		BitSet dontNeedEncoding;
		int intCaseDiff = ('a' - 'A');
		dontNeedEncoding = new BitSet(65536);
		int i;
		for (i = 'a'; i <= 'z'; i++) {
			dontNeedEncoding.set(i);
		}
		for (i = 'A'; i <= 'Z'; i++) {
			dontNeedEncoding.set(i);
		}
		for (i = '0'; i <= '9'; i++) {
			dontNeedEncoding.set(i);
		}
		dontNeedEncoding.set(' ');	
		StringBuffer sbOut = new StringBuffer(url.length()*3);

		byte[] ba1 = null;
		try {
			ba1	= url.getBytes(m_strEncode);
		}
		catch( Exception ex ) {
			System.out.println(ex.getMessage() + "\n");
		}
		for (int j = 0; j < ba1.length; j++) {
			int c = (int)ba1[j];

			boolean bNeedEncoding = false;
			if ( 0 < c ) {
				if (dontNeedEncoding.get(c)) {
					if (c == ' ') {
						c = '+';
					}
					sbOut.append((char)c);
				} else {
					bNeedEncoding = true;
				}
			} else {
				bNeedEncoding = true;
			}
			if ( bNeedEncoding == true ) {
				sbOut.append('%');
				char ch = Character.forDigit((c >> 4) & 0xF, 16);
				// converting to use uppercase letter as part of
				// the hex value if ch is a letter.
				if (Character.isLetter(ch)) {
					ch -= intCaseDiff;
				}
				sbOut.append(ch);
				ch = Character.forDigit(c & 0xF, 16);
				if (Character.isLetter(ch)) {
					ch -= intCaseDiff;
				}
				sbOut.append(ch);
			}
		}
		return sbOut.toString();	
	}
   
	/**																	
	 * URL デコード<br>																
	 * @param url String																
	 * @return デコード文字列 String																
	 */														
	public static String urlDecode(String url) {

		try {
			url = URLDecoder.decode(url, m_strEncode);
		}
		catch(UnsupportedEncodingException ex) {
			System.out.println(ex.getMessage() + "\n");
		}
		return url;
	}

	/**																			
	 * 文字列がコメント行であるかを検証し、コメント行の場合は、真を返す<br>																		
	 * @param str String																		
	 * @return コメント行である-true, コメント行ではない-false
	 */																		
	public static boolean isComment(String str) {
		boolean blnIsSkippable = false;
				
		int intIndex = getIndexNotTab(str, 0);
		if ( intIndex == -1 ) {
			// 空行もコメントとみなす
			blnIsSkippable = true;
		} else {
			// 空白以外の最初の文字がセミコロンであればコメント
			blnIsSkippable = ( str.charAt( intIndex ) == ';' );
		}
		return blnIsSkippable;
	}
 
	/**																			
	 * @param inStr String																		
	 * @return index = find_first_not_of(" \t")																		
	 */																		
	public static int getIndexNotTab (String inStr, int intFirst) {
		int intIndex = -1;		
		char strTem;
		for (int i = intFirst; i <inStr.length(); i++){
			strTem = inStr.charAt(i);
			if ( ' ' == strTem || '\t' == strTem) {
				continue;
			} else {
				intIndex = i;
				break;
			}	
		}		
		return intIndex;
	} 
  
	/**																			
	 * グループ行であるかを検証する<br>																		
	 * @param str String																		
	 * @return グループ行である-true, グループ行ではない-false																		
	 */																		
	public static boolean isGroup(String str) {
		boolean blnIsKeyWord = false;
		// 空白文字をスキップする。
		
		if(str != null) {
			int intIndex = getIndexNotTab(str, 0);				
			if ( intIndex != -1 && str.charAt( intIndex ) == '[' 
								&& str.charAt( str.length() - 1 ) == ']' ) {
				blnIsKeyWord = true;
			}
		}
		return blnIsKeyWord;
	}
   
	/**															
	 * グループ名を取得する<br>														
	 * @param str String														
	 * @return グループ名 String														
	 */														
	public static String getGroupName(String str) {
		String strKeyWord = "";
		if ( str != null ) {				
			int intFirst = str.indexOf("[");
			int intLast;
			if ( intFirst != -1 ) {
				intLast = str.indexOf( "]", intFirst );
				if(intLast != -1 ) {
					strKeyWord = str.substring( intFirst + 1, intLast );
				}
			}
		}
		return strKeyWord;
	}
   
	/**																		
	 * 文字列が数値かどうか調べる<br>																	
	 * @param str String																	
	 * @return 数値文字列だった場合	: true
	 *				数値以外の場合			: false  																	
	 */																	
	public static boolean isNumeric(String str, boolean bTypeInteger) {
		//bTypeInteger が Trueの場合は、整数値。Falseの場合は、小数としてチェックする
		//小数点フラグ。 値が整数の場合は、
		boolean blnIndexDot = bTypeInteger; 
		boolean blnCheck	= true;
		
		// 文字列を評価する
		if ( str == null || "".equals(str.trim()) ) {
			return false;
		}
		char[] chr = str.toCharArray();
		for ( int i = 0; i < str.length(); i++ ) {

			// 文字が0から9以外の場合
			if ( chr[i] < '0' || chr[i] > '9' ) {

				// その文字が小数点の場合
				if ( chr[i] == '.' ) {
					// 既に小数点が存在していれば、Falseを返却する
					if ( blnIndexDot ){
						blnCheck = false;
						break;
					}
					// 初めての小数点であればフラグをTrueにする
					else {
						blnIndexDot = true;
					}
				}

				// 文字がマイナスの場合
				else if ( chr[i] == '-' ) {
					// 文字列の先頭でなければFalseを返却する
					if ( i  != 0 ) {
						blnCheck = false;
						break;
					}
				}
				// 文字が数字、小数点、マイナスいずれにも該当しなかった場合、Falseを返却する
				else {
					blnCheck = false;
					break;
				}
			}
		}
		return blnCheck;
	}
   
	/**																		
	 * 引数の値がID型かどうか調べる。<br>
	 * AICC規格の場合、半角英数字＆255文字であることを確認する。<br>
	 * SCORM1.3規格の場合、4096半角英数字＆255文字であることを確認する。<br>
	 * @param str String 対象データ
	 * @return boolean ID型だった場合	: true
	 * 					ID型以外の場合	: false
	 */
	public static boolean checkIdentifier( String str ) {
		//検査結果フラグ
		boolean blnCheck = true;

		// 文字列が存在する限りループ
		if (str != null) {
			// SCORM1.3用のデータであるか判定する
			if (CMIS13ModelUtil.isScorm13() == true) {
				// 文字列が4096文字以上になった場合
				if (str.length() > 4096){
					blnCheck = false;
				}
			}
			else {
				for ( int i = 0; i < str.length(); i++ ) {
					// 文字列が255文字以上になった場合
					if ( 255 < i + 1) {
						// 検査結果をFalseにする
						blnCheck = false;
						break;
					}

					// 半角数字(0x30 - 0x39)
					// 大英字(0x41 - 0x5a)
					// 小英字(0x61 - 0x7a)
					// いずれにも該当しない場合検査結果をFalseにする
					boolean blnNumber = (int)str.charAt(i) >= 0x30 && (int)str.charAt(i) <= 0x39;
					boolean blnUpperCase = (int)str.charAt(i) >= 0x41 && (int)str.charAt(i) <= 0x5a;
					boolean blnLowerCase = (int)str.charAt(i) >= 0x61 && (int)str.charAt(i) <= 0x7a; 	 
					if ( !( blnNumber || blnUpperCase || blnLowerCase ) ) {
						blnCheck = false;
						break;
					}
				}
			}
		}
		return blnCheck;
	}
   
	/**																			
	 * 時間フォーマット適合性検査を行う<br>																		
	 * @param str String																		
	 * @param type String
	 * @return フォーマットが正しい場合			: true
	 * 			フォーマットがが正しくない場合		: false																		
	 */																		
	public static boolean isCMITime(String str, String type) {
		
		//検査結果
		boolean blnCheck = false;
		
		//時間格納用配列(時分秒)
		String [] strTimeArray = new String[3];
		
		//コロンの数
		int colonCnt = 0;
		
		//合計バイト数
		int totalByte = -1;

		if ( str == null ){
			return false;
		}
		
		for ( int i = 0; i < str.length(); i++ ) {
			if ( colonCnt == 2 ) {
				strTimeArray[2] = str.substring( totalByte + 1 );
				break;
			} else if ( str.charAt(i) == ':' ) {
				strTimeArray[colonCnt] = str.substring( totalByte + 1, i );
				colonCnt++;
				totalByte = i;
			}
		}
		boolean blnIsNumber = true;
		try {
			Long.parseLong( strTimeArray[0] );
			Long.parseLong( strTimeArray[1] );
		} catch ( NumberFormatException ex) {
			blnIsNumber = false;
		}
		boolean blnIsNumeric = isNumeric(strTimeArray[2],false); 
		int intHourseLen = strTimeArray[0].length();
		int intMinutesLen = strTimeArray[1].length();
		int intSecondLen = strTimeArray[2].length();
		
		if ( blnIsNumber && blnIsNumeric && ( intMinutesLen == 2 ) ) {
			if ( "CMITimespan".equals(type) ) {
				if ( intHourseLen >= 2 && 4 >= intHourseLen
													&& intSecondLen >= 2 ) {
					blnCheck = true;
				}
			} else if ( "CMITime".equals(type) ) {
				
				if ( intHourseLen == 2 && intSecondLen >=2 && 5 >= intSecondLen ) {
					blnCheck = true;
				}
			}
		}
		return blnCheck;
	}

	/**
	 * SCORE 値文字列を取得する。<br>
	 * 　AICC2.xの場合、raw値のみを取得する<br>
	 * 　AICC3.xの場合、raw値、max値、min値を取得する<br>
	 * 　SCORM1.3の場合、scaled値、raw値、max値、min値を取得する<br>
	 * @param element CMIElement スコアエレメント
	 * @return String SCORE値
	 */
	public static String getScoreValue(CMIElement element) {
		CMINode node = null;
		if ( element instanceof CMINode ) {
			node = (CMINode) element;
		}
		String strValue = null;
		String strMyPath = null;
		String strPath = null;
		StringBuffer sbValue = new StringBuffer();
		if ( node != null ) {
			boolean blnCbt = false;
			if (CMIS13ModelUtil.isScorm13() == true) {
				// クライアントからのSCORM1.3形式での受信要求である場合
				strPath = "scaled";
				strValue = node.getLocalValue( strPath );
				if ( strValue != null ) {
					sbValue.append( strValue );
				} else {
					sbValue.append("");
				}

				// SCORM v1.3の場合は、,max,min を追加する。
				blnCbt = true;
			}
			else {
				CMICBT cbt = element.getCBT();
				String strCBTVer = cbt.getVersionStr();
				// AICCのバージョン別処理
				// v3.0以降の場合のみ、,max,min を追加する。
				// v2.0, v2.1, v2.2 は、 ,max,min が使用できない。
				try{
					blnCbt = ( strCBTVer.charAt(0) - '0') >= 3;
				}catch(Exception e){
					blnCbt = false;
				}
			}
			strMyPath = node.getName();

			strPath = "raw";
			strValue = node.getLocalValue( strPath );
			if ( strValue != null ) {
				if (CMIS13ModelUtil.isScorm13() == true) {
					sbValue.append(",");
				}
				sbValue.append( strValue );
			} else {
				sbValue.append("");
			}

			//v3.0 or above
			if ( blnCbt ) {
				String strMaxValue = null;
				String strMinValue = null;

				strPath = "max";
				strValue = node.getLocalValue(strPath);
				if ( strValue != null && strValue.length() > 0 ) {
					strMaxValue = strValue;
					sbValue.append(",");
					sbValue.append(strMaxValue);
				}
				strPath = "min";
				strValue = node.getLocalValue(strPath);
				if ( strValue != null && strValue.length() > 0) {
					strMinValue = strValue;
					if ( strMaxValue == null || "".equals( strMaxValue ) ) {
						//maxが省略されているため、「,」を付け足す
						sbValue.append(",");
					}
					sbValue.append(",");
					sbValue.append(strMinValue);
				}
			}
		}
		return sbValue.toString();
	}
   
	/**															
	 * 改行文字列の判定<br>														
	 * @param str String														
	 * @return string 改行文字列 （不明な場合は、空文字列）														
	 */														
	public static String checkLineDelimiter(String str) {
		String strLineDelimiter = null;
		int intHead;
		if ((intHead = str.indexOf(CMIElement.CHAR_CRLF)) != -1) {
			strLineDelimiter = CMIElement.CHAR_CRLF;
		} else if ((intHead = str.indexOf(CR_ONLY)) != -1) {
			strLineDelimiter = CR_ONLY;
		} else if ((intHead = str.indexOf(LF_ONLY)) != -1) {
			strLineDelimiter = LF_ONLY;
		} else {
			// unknown;
			strLineDelimiter = CMIElement.CHAR_CRLF;
		}
		return strLineDelimiter;
	}
   
	/**															
	 * デバッグログを出力する<br>														
	 * @param logData String																												
	 */														
	public static void putLog(String logData) {
		String strKey = "CBTLOG";
		String strValue = getEnv(strKey);
		
		if ( strValue != null ) {
			Date tdate = Calendar.getInstance().getTime();	
			SimpleDateFormat simpleformate = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
			String tnow = simpleformate.format(tdate);
			
			StringBuffer data = new StringBuffer();
			data.append(tnow);
			data.append(" : ");
			data.append(logData);
			data.append("\n");
			String bos = data.toString();
			writeFile(strValue, bos);
		}   	
	}
 
	/**															
	 * データをファイルへ書き込む<br>														
	 * @param inFileName String 出力ログファイル名
	 * @param buffer String 出力データ 
	 */
	public static void writeFile(String inFileName, String buffer) {
		try {
			
			File tempFile = new File(inFileName);
			if ( !tempFile.exists() ) {
				tempFile.createNewFile();
			}
			
			FileWriter filewriter = new FileWriter(tempFile, true);
			PrintWriter printwriter = new PrintWriter(filewriter, true);
			if ( buffer != null ) {
				printwriter.println("");
				printwriter.println(buffer);
			}
			printwriter.close();
			filewriter.close();
		} catch (Exception e) {
			 e.printStackTrace(); 
		}
	}

	/**																											
	 * グローバルプロトデータからインスタンスを生成する<br>																										
	 * @param proto CMIElementProto																										
	 * @param inNode CMINode																										
	 * @return CMIElement																										
	 */	
	public static CMIElement makeGlobalProto2Instance(CMIElementProto proto, CMINode inNode) {
		CMIElement element = null;
		CMINode node = null;
		CMIGlobalCBT gcbt = null;
		gcbt = inNode.getGCBT();

		// 配列の場合
		boolean blnIsArray = proto.getIsArray();
		if ( blnIsArray ) {
			node = new CMIArrayNode(proto);
			node.setGCBT(gcbt);
			element = node;
		}
		// 配列意外の場合
		else {
			Vector vtrTable = proto.getMemberTable();
			if ( vtrTable != null ) {
				// ノードの作成
				node = new CMINode(proto);
				node.setGCBT(gcbt);
				element = node;
			}
			else {
				// リーフエレメントの作成
				// ※ 規格上、存在しないケースなので、必要に応じて見直しが必要である。
				element = new CMILeafElement(proto,null);
				element.setGCBT(gcbt);
			}
		}
		return element;
	}
   
	/**																					
	 * プロトデータからインスタンスを生成する<br>																				
	 * @param proto CMIElementProto																				
	 * @return inNode CMINode																				
	 * @return インスタンス CMIElement																				
	 */																				
	public static CMIElement makeProto2Instance(CMIElementProto proto, CMINode inNode) {
		CMIElement element = null;
		CMINode node = null;
		CMICBT cbt = null;
		CMIGlobalCBT gcbt = null;
		cbt = inNode.getCBT();
		gcbt = inNode.getGCBT();

		// 配列の場合
		boolean blnIsArray = proto.getIsArray();
		if ( blnIsArray ) {
			node = new CMIArrayNode(proto);
			if ( cbt != null) {
				node.setCBT(cbt);
			} else {
				node.setGCBT(gcbt);
			}
			element = node;
		}
		// 配列意外の場合
		else {
			Vector vtrTable = proto.getMemberTable();
			if ( vtrTable != null) {
				// ノードの作成
				node = new CMINode(proto);
				if (cbt != null) {
					node.setCBT(cbt);
				} else {
					node.setGCBT(gcbt);
				}
				element = node;
			}
			else {
				// リーフエレメントの作成
				boolean blnIsGlobal = proto.getIsGlobal();
				if ( blnIsGlobal ) {
					// グローバルの場合
					// 未登録(初回のAU)の場合は、バッファを生成し、マネージャーに登録する。
					// 登録済み(2回目以降のAU)の場合は、バッファを取得する。
					CMIGlobalCBT globalCBT = CMIGlobalCBT.getGlobalCBT();
					CMIValueBuffer val = globalCBT.getElementValueBuffer( proto.getName() );
					if ( val == null ) {
						// 未登録(初回のAU)の処理
						val = new CMIValueBuffer();
						CMIGlobalCBT.getGlobalCBT().addElementValueBuffer(proto.getName(), val);
					}
					element = new CMILeafElement(proto, val);
					if (cbt != null) {
						element.setCBT(cbt);
					} else {
						element.setGCBT(gcbt);
					}
				} else {
					// グローバル意外の場合
					element = new CMILeafElement(proto,null);
					if (cbt != null) {
						element.setCBT(cbt);
					} else {
						element.setGCBT(gcbt);
					}
				}
			}
		}
		return element;
	}
   
	/**																			
	 * グローバル子インスタンスを生成する<br>																		
	 * @param element CMIElement																																				
	 */																		
	public static void makeGlobalChildInstance(CMIElement element) {
		CMIElementProto proto = element.getElementProto();
		Vector vtrTable = proto.getMemberTable();
		boolean blnIsArray = proto.getIsArray();
		if ( vtrTable != null && !blnIsArray) {
			CMINode node = (CMINode)element;
			for ( int i = 0; i < vtrTable.size(); i++) {
				CMIElement child = makeGlobalInstance( (CMIElementProto)vtrTable.get(i), node);
			}
		}    
	}

	/**																	
	 * 子インスタンスを生成する<br>																
	 * @param element CMIElement																																
	 */																
	public static void makeChildInstance(CMIElement element) {
		CMIElementProto proto = element.getElementProto();
		Vector vtrTable = proto.getMemberTable();
		boolean blnIsArray = proto.getIsArray();	
		if ( vtrTable != null && !blnIsArray ) {
			CMINode node = (CMINode)element;
			for ( int i = 0; i < vtrTable.size(); i++ ) {
				CMIElement child = makeInstance( (CMIElementProto)vtrTable.get(i), node );
			}
		}
	}
	
	/**
	 * 子インスタンスを生成する<br>
	 * @param element CMIElement
	 * @return
	 */																
	private static String getEnv( String strKey ) {
		String strFileName = "log.ini";
		Properties mobjLoProperty = null;
		try {			
			InputStream objFile = ClassLoader.getSystemClassLoader().getResourceAsStream(strFileName);
			mobjLoProperty = new Properties();
			if( objFile != null ) {				
				try {
					mobjLoProperty.load(objFile);
				} catch( IOException Ex ) {
					throw Ex;
				}
				finally {
					try {
						objFile.close();
					} catch( Exception e ) {
						e.printStackTrace();
					}
				}
			}
			try {
				String strValue = mobjLoProperty.getProperty( strKey );	
				return strValue;
			} catch (Exception e) {
				e.printStackTrace();	
			}
			
		} catch( Exception e ) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 数文字列であるかを検証する<br>
	 * @param value 文字列
	 * @return 数文字列である-true, 数文字列ではない-false
	 */			
	public static boolean isNumber(String value ) {
		boolean blnIsNum = false;
		if ( value == null ){
			return false;
		}
		try{
			Long.parseLong(value);
			blnIsNum = true;
		}catch( NumberFormatException ex ){
			blnIsNum = false;
		}
		return blnIsNum;
	}
	/**
	 * 数文字列であるかを検証する<br>
	 * @return boolean 数文字列である-true, 数文字列ではない-false
	 */	
	public static boolean isDetailLogging() {
		String strvalue = getEnv("CBTCOM_DETAIL");
		if (strvalue == null) {
			return false;
		} else {
			return true;	
		}		
	}

	/**
	 * 受信データのエンコード文字列を設定する。<br>
	 * @param strEnc String エンコード文字列
	 */
	public static void setEncodeString( String strEnc ) {
		m_strEncode = strEnc;
	}

	
}
