/*
このファイルの中身は、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.25	lcg  新規作成		
//
package jp.co.ntt.lms.lo.scorm.cbtcom;

import java.lang.NumberFormatException;
//import java.util.StringTokenizer;
 
/**
 * CMI データモデル　基底要素クラス
 * @author lcg
 */
public abstract class CMIElement {
	
	/**
	 * CMI AICC バージョン
	 */
	public static final String DEF_CMI_AICC_VERSION = "3.0.2";
	
	/**
	 * 改行コード
	 */
	public static final String CHAR_CRLF = "\r\n";
   
	/**
	 * 改行コード
	 */
	public static final String STR_CRLF = CHAR_CRLF;
   
	/**
     * 完全(通常)
     */
	private int INIT_FULL = 0;
   
	/**
     * セッション
     */
	private int INIT_SESSION = 1;
   
	/**
     * arrayのときの要素番号
     * arrayの要素でないときは、-1、最初の要素は、0
     */
	protected int m_arrayIndex = -1;
   
	/**
     * プロトタイプ・データ
     */
	protected CMIElementProto m_proto = null;
   
	/**
     * 親オブジェクト
     */
	protected CMIElement m_parent = null;
   
	/**
     * CBTオブジェクト
     */
	protected CMICBT m_CBT = null;
   
	/**
     * CBTオブジェクト
     */
	protected CMIGlobalCBT m_GCBT = null;
   
	/**
     * 値のNULL値状態
     */
	protected boolean m_ValueIsNULL = true;
   
	/**
     * リンクカウント値
     */
	protected int m_LinkCount = 0;
   
	/**
     * setValue による更新あり
     */
	protected boolean m_bySetValue = false;
   
	/**
     * protoデータが新規に作成されたかどうかのフラグ
     */
	protected boolean m_isProtoAllocated = false;
   
	/**
     * CMIElementクラスのコンストラクタ<br>
     * @param proto プロトタイプ・データ
     */
	public CMIElement(CMIElementProto proto) {
		m_proto = proto;
		m_arrayIndex = -1;
		m_parent = null;
		m_CBT = null;
		m_GCBT = null;
		m_ValueIsNULL = true;
		m_LinkCount	= 0;
		m_bySetValue = false;
		m_isProtoAllocated = false;
   }
   
	/**
     * CMIElementクラスのコンストラクタ<br>
     */
	public CMIElement() {

	   m_arrayIndex	= -1;
	   m_parent = null;
	   m_CBT = null;
	   m_GCBT = null;
	   m_ValueIsNULL = true;
	   m_LinkCount = 0;
	   m_bySetValue = false;
	   m_isProtoAllocated = false;
	}
	
	/**
	 * 親 の設定 <br>
	 * @param parent
	 */
	public void setParent( CMIElement parent) {
		this.m_parent = parent;
	}
   
	/**
     * CBT 設定 <br>
     * @param cbt
     */
	public void setCBT( CMICBT cbt) {
		this.m_CBT = cbt;
	}
   
	/**
	 * CBTの 取得 <br>
	 * @return CMICBT CMICBTオブジェクト
	 */
	public CMICBT getCBT() {
		return m_CBT;
	}
   
	/**
     * CBT 設定 <br>
     * @param　 gcbt CMIGlobalCBT グローバルCBTオブジェクト
     */
	public void setGCBT( CMIGlobalCBT gcbt) {
		m_GCBT = gcbt;
   	}
   
	/**
	 * GCBTの 取得 <br>
	 * @return CMIGlobalCBT グローバルCBTオブジェクト
	 */
	public CMIGlobalCBT getGCBT() {
		return m_GCBT;
	}
   
	/**
	 * 要素名の取得 <br>
	 * @return String 要素名 
	 * 			配列の要素のとき（m_arrayIndexが負）は、インデクス番号を名前として返す。
	 * 			それ以外のときは、プロトデータの名前を返す。		
	 */
	public String getName() {
		String strName = null;
		if ( 0 <= m_arrayIndex ) {
			strName = String.valueOf( m_arrayIndex );
		} else {
			strName = m_proto.getName();
		}
		return strName;
	}
   
	/**
	 * キーワードの取得 <br>
	 * @return String キーワード 
	 */
	public String getKeyWord() {
		String strKeyWord = m_proto.getKeyWord();
		if ( null == strKeyWord ) {
			String strName = m_proto.getName();
			strKeyWord = CMIUtil.makeKeyWord(strName);
		}
		return strKeyWord;
   }
   
	/**
	 * null値の 判定 <br>																				
	 * @return boolean null値の判定
	 */
	public boolean isNull() {
		return m_ValueIsNULL;
	}
   
	/**
	 * 配列要素番号 設定 <br>																				
	 * @param index
	 */
	public void setArrayIndex(int index) {
		m_arrayIndex = index;
	}
   
	/**
	 * 配列要素番号 取得 <br>																				
	 * @return int 配列要素番号
	 */
	public int getArrayIndex() {
		return m_arrayIndex;
	}
   
	/**		
	 * リンクカウンタのインクリメント <br>	
	 * @return int リンクカウンタの値
	 */	
	public int incrementLinkCount() {
		m_LinkCount++;
		return m_LinkCount;
	}
   
	/**		
	 * リンクカウンタのデクリメント <br>	
	 * @return int リンクカウンタの値
	 */
	public int decrementLinkCount() {
		return ( m_LinkCount > 0 ) ? ( --m_LinkCount ) : m_LinkCount;
	}
   
	/**
     * リンクカウンタの 取得 <br>
     * @return int リンクカウンタ
     */
	public int getLinkCount() {
	    return m_LinkCount;
	}
   
	/**
     * SetValue実行状況 の取得 <br>
     * @return boolean SetValue実行状況
     */
	public boolean isSetValue() {
		return m_bySetValue;
	}
	
	/**
	 * SetValue実行状況の リセット <br>
     */
	public void resetSetValue() {
		m_bySetValue = false;
	}
   
	/**
     * プロトデータ要解放フラグのセット
     */
	public void setIsProtoAllocated( boolean value ) {
		m_isProtoAllocated = value;
	}
   
	/**
	 * プロトデータ の取得  <br>
	 * @return CMIElementProto プロトデータ
	 */
	public CMIElementProto getElementProto() {
		return m_proto;
	}
   
	/**		
	 * グローバル の判定  <br>	
	 * @return boolean グローバル  	
	 */	
	public boolean isGlobal() {
		return m_proto.getIsGlobal();
	}
   
	/**		
	 * セッション 判定 <br>	
	 * @return boolean セッション 判定	
	 */
	public boolean isSession() {
		return m_proto.getIsSession();
	}
   
	/**		
	 * 末端 の 判定 <br>	
	 * @return boolean 末端 の 状態	
	 */
	public boolean isLeaf() {
		return m_proto.getIsLeaf();
	}
   
	/**
     * 配列 判定
     * @return boolean 配列 判定
     */
	public boolean isArray() {
		return m_proto.getIsArray();
	}
   
	/**
     * Get 可否判定
     * @return boolean Get可否状態
     */
	public boolean isReadable() {
		return m_proto.getIsReadable();
	}
   
	/**
     * Set 可否判定
     * @return boolean Set可否状態
     */
	public boolean isWritable() {
		return m_proto.getIsWritable();
	}
   
	/**
     * Set 必須 の 判定  <br>
     * @return boolean 必須ならtrue、そうでないならfalse
     */
	public boolean isMandatory() {
		return m_proto.getIsMandatory();
	}
   
	/**
     * シリアライズの 判定  <br>
     * @return boolean
     */
	public boolean isSerializable() {
	    return m_proto.getIsSerializable();
	}
   
	/**
     * CBTバージョンが 3 以上であることの判定  <br>
     * @return boolean true:3 以上の場合 / false:その他
     */
	public boolean isV3Above() {
		boolean blnRet = false;
		CMICBT cbt = getCBT();
		blnRet = cbt.isV3Above();	
		return blnRet;
	}
   
	/**
     * CMIバージョンが 3 以上であることの判定  <br>
     * @return boolean true:3 以上の場合 / false:その他
     */
	public boolean isCMIV3Above() {
		boolean blnRet = false;
		CMICBT cbt = getCBT();
		blnRet = cbt.isCmiV3Above();
		return blnRet;
	}
   
	/**
     * CMIバージョンが 3 以上であることの判定  <br>
     * @return int true:3 以上の場合 / false:その他
     */
	public int getVersion() {
		String strVer = null;
		int intVer;
		CMICBT cbt = getCBT();
		
		// CBTバージョンを取得
		strVer = cbt.getVersionStr();
	
		if (  null == strVer || "".equals(strVer) ) {
			strVer = DEF_CMI_AICC_VERSION;
		}
	
		intVer = getVersionInteger(strVer);

		return intVer;
	}
   
	/**
     * CBTバージョンを整数型として取得する  <br>
     * @param version String バージョン情報
     * @return int CBTバージョンを整数として返却する
     */
	public int getVersionInteger(String version) {

		//カンマなしバージョン情報
		StringBuffer sb = new StringBuffer();
		
		//マイナー情報番号桁数
		int  intLen = 0;
		
		//カンマを除いた全体の桁数
		int  intVerFig = 0;
		
		//小数点存在フラグ
		boolean blnIndexDot = false;
		
		char [] chrVersion = version.toCharArray();
		
		// バージョン情報が存在する間ループ
		for ( int i = 0 ; i < chrVersion.length ; i++ ) {
		
			// バージョン情報がドット以外の場合
			if  ( chrVersion[i]  !=  '.' ) {
		
				// バージョン情報の文字列を格納
				sb.append( chrVersion[i] );
		
				// 既に小数点が存在していた場合、小数点以下桁数インクリメント
				if ( blnIndexDot ) {
					intLen++;
				}
				// 全体桁数インクリメント
				intVerFig++;
			}
			// 小数点が以前になかった場合、小数点フラグをTrueにする
			else if ( !blnIndexDot ) {
				blnIndexDot = true;
			}
		} // ループ処理ここまで
		
		// マイナー情報番号が3桁に満たない場合、不足分を0で桁埋めする
		if ( intLen < 3 ) {
			for ( int i = 0; i < 3 - intLen; i++ ) {
				sb.append( '0' );
			}
		}
		int intVersion;
		// バージョン情報をint型に変換
		try{
			intVersion = Integer.parseInt( sb.toString() );
		}catch( NumberFormatException ex ) { 
			intVersion = 0;
		}
		return intVersion;
	}
   
	/**
     * 対象がキーワードかチェックする  <br>
     * @return boolean キーワードの場合：true、キーワードでない場合：false
     */
	public boolean checkParamKeyword(String paramName) {
		if( paramName == null || "".equals( paramName ) ) {
   			return false;
		}
		//キーワード配列の設定
	   	String [] strKeyArray = {"_children","_count","core","objectives"
	   										,"evaluation","interactions","tries"
	   										,"student_data","paths","attempt_records"
	   										,"cmi","student_preference","score"
	   										,"correct_responses","lesson_score"
	   										,"student_demographics"
	   									};
	   	boolean blnExist = false;
	   	for ( int i = 0; i< strKeyArray.length; i++ ) {
	   		if ( paramName.equals( strKeyArray[i] ) ) {
	   			blnExist = true;
	   			break;
	   		}
	   	}
	   	return blnExist;
	}
   
	/**
     * データモデル要素がCMINodeの場合のフォーマットチェック <br>
     * @param　 value　チェックデータ
     * @param　 dataType データ型
     * @param　 name　チェックデータ
     * @return	 boolean 数値だった場合(小数含む):true、数値以外の場合:false
     */
	public boolean checkCMIDataType(String value, int dataType, String name) {
   	
		boolean blnCheck = true;

		if ((value == null) || "".equals(value) == true ) {
			return true;
		}
	
		// 対象エレメントのデータ型により、チェックを分岐する
		switch(dataType){
			case CMIElementProto.CMIDecimal:
				blnCheck = checkCMIDecimal(value);
				break;
				
			// CMIIdentifer型のチェック
			case CMIElementProto.CMIIdentifier:
				blnCheck = checkCMIIdentifer(value);
				break;
			
			// CMIInteger型のチェック
			case CMIElementProto.CMIInteger:
				blnCheck = checkCMIInteger(value);
				break;
			
			// CMISInteger型のチェック
			case CMIElementProto.CMISInteger:
				blnCheck = checkCMISInteger(value);
				break;
			
			// CMIString256型のチェック
			case CMIElementProto.CMIString256:
				blnCheck = checkCMIString256(value);
				break;
			
			// CMIString1000型のチェック
			case CMIElementProto.CMIString1000:
				blnCheck = checkCMIString1000(value);
				break;
			
			// CMIString4096型のチェック
			case CMIElementProto.CMIString4096:
				blnCheck = checkCMIString4096(value);
				break;
			
			// CMITimespan型のチェック
			case CMIElementProto.CMITimespan:
				blnCheck = checkCMITimespan(value);
				break;
			
			// CMIVocabulary型のチェック
			case CMIElementProto.CMIVocabulary:
				blnCheck = checkCMIVocabulary(value, name);
				break;
			
			// CMINoType型の場合はチェックを行わない
			default:
				blnCheck = true;
				break;
		}
		return blnCheck;
	}
   
	/**
     * カレントエレメントからトップまでのパスを生成する。<br>
     * パスは、取得バッファに追加していく。<br>
     * 親オブジェクトがある場合は、再起呼び出しをしてから、パスを追加する <br>
     * @return String 生成のパス
     */
	public String getPath() {
	   	StringBuffer sb = new StringBuffer();
	   	
		//親オブジェクトを呼び出す
		if ( m_parent != null ) {
			sb.append( m_parent.getPath() );
			sb.append( "." );
		}
		// 自名称を取得バッファに追加する
		sb.append( getName() );
		return sb.toString();
	}
   
	/**
     * カレントエレメントからトップまでのパスを生成する。<br>
     * パスは、取得バッファに追加していく。<br>
     * 親オブジェクトがある場合は、再起呼び出しをしてから、パスを追加する。 <br>
     * @param outStr StringBuffer パス名
     * @return boolean 取得結果(true-有効 , false-無効)
     */
	public boolean getKeyPath( StringBuffer outStr ) {
		// 配列の場合は、無効
		boolean blnIsArray = m_proto.getIsArray();
		if ( blnIsArray ) {
			return false;
		}
		/// 親オブジェクトを呼び出す
		if ( m_parent != null ) {
			boolean blnParent = false;
			blnParent = m_parent.getKeyPath( outStr );
			
			if  ( !blnParent ) {
				return false;
			}
			outStr.append( "." );
		}
	
		/// 自名称を取得バッファに追加する
		outStr.append( getName() );
		
		return true;
   }
   
	/**
     * setAllValue用の値を取得する<br>
     * @param value エンコードされた値
     * @return String エンコードした値
     */
	private String putValue(String value) {
		if ( null == value ) {
			return "#";
		}
		String strRet = new String();
		strRet = CMIUtil.urlEncode( value );
		return strRet;
	}
   
	/**
     * データがCMIDecimal型かチェックする<br>
     * @param value チェックされた値
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMIDecimal(String value) {
		
		// 検査結果
		boolean blnCheck = false;
		
		// 数値であるかを調べる
		blnCheck = CMIUtil.isNumeric( value, false );
		
		return blnCheck;
	}
   
    /**
     * データがCMIIdentifer型かチェックする<br>
     * @param value String チェックされた値
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMIIdentifer(String value) {
		//検査結果
		boolean blnCheck = false; 
	
		blnCheck = CMIUtil.checkIdentifier(value);
	
		return blnCheck;
	   }
   
	/**
     * データがCMIInteger型かチェックする<br>
     * @param value String チェックされた値
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMIInteger(String value) {
		
		// 検査結果
		boolean blnCheck = false;
		boolean blnIsNum = CMIUtil.isNumber(value);
		
		if ( blnIsNum ) {
			// データが0から65536の間であれば
			try {
				int intNumber = Integer.parseInt( value );
				if ( 0 <= intNumber && intNumber <= 65536 ) {
					blnCheck = true;
				}
			} catch ( NumberFormatException ex) {
				blnCheck = false;
			}
		}
		return blnCheck;
	}
   
	/**
     * データがCMISInteger型かチェックする<br>
     * @param value String チェックされた値
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMISInteger(String value) {
		
		//検査結果
		boolean blnCheck = false;
		
		boolean blnIsNum = CMIUtil.isNumeric(value, true);
		
		// valueが数値であり、-32768〜32768の範囲内の場合、Trueを返却する
		if ( blnIsNum ) {
			try {
				int intNumber = Integer.parseInt( value );
				if ( -32768 <= intNumber && intNumber <= 32768 ) {
					blnCheck = true;
				}
			} catch ( NumberFormatException ex) {
				blnCheck = false;
			}
		}
		return blnCheck;
   }
   
	/**
     * データがCMIString256型かチェックする<br>
     * @param value String チェックされた値
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMIString256(String value) {
		
		//検査結果
		boolean blnCheck = false; 

		// バージョン情報の取得
		int version = getVersion();

		// バージョンが3.4以降の場合は、CMIString255型となる
		// データが255文字以内であれば、検査結果をTrueにする
		if ( 3400 <= version || CMIS13ModelUtil.isScorm13() == true) {
			if ( value.length( ) <= 255 ) {
				blnCheck = true;
			}
		}
		// バージョンが3.4以前の場合は、CMIString256型となる
		// データが256文字以内であれば、検査結果をFalseにする
		else {
			if ( value.length() <= 256 ) {
				blnCheck = true;
			}
		}
		// 検査結果の返却
		return blnCheck;
   }
   
	/**
     * データがCMIString4096型かチェックする<br>
     * @param value String チェックされた値
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMIString4096(String value) {
		//検査結果
		boolean blnCheck = false; 

		// データが4096文字以内であれば検査結果をTrueにする
		if ( value.length() <= 4096 ) {
			blnCheck = true;
		}
		return blnCheck;   
	}

   
	/**
	 * データがCMIString1000型かチェックする<br>
	 * @param value String チェックされた値
	 * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
	 */
	private boolean checkCMIString1000(String value) {
		//検査結果
		boolean blnCheck = false; 

		// データが1000文字以内であれば検査結果をTrueにする
		if ( value.length() <= 1000 ) {
			blnCheck = true;
		}
		return blnCheck;   
	}
   
	/**
     * データがCMITimespan型かチェックする<br>
     * @param value String チェックされた値
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMITimespan(String value) {
		
		//検査結果
		boolean blnCheck = false; 
		
		try {
			CMIS13ModelUtil.parseTimeintervalToLong(value);
			blnCheck = true;
		}
		catch (S13LogFormatException ex) {
			blnCheck = false;
		}
		
		return blnCheck; 
	}
   
	/**
     * setValue<br>
     * @param name 名前
     * @param value 値
     * @param doCheck チェックフラグ
     */
	public abstract void localSetValue(String name, String value, boolean doCheck);
   
	/**
     * データがCMIVocabulary型かチェックする<br>
     * @param value チェックされた値
     * @param name チェックされた名前
     * @return boolean データと型が一致した場合：true、データと型が一致しなかった場合：false
     */
	private boolean checkCMIVocabulary(String value, String name) {
   	
		//検査結果
		boolean blnCheck = false; 
	
		name = name.toLowerCase();
		value = value.toLowerCase();
	
		if ( (value == null) || ("".equals(value) == true) ) {
			return true;
		}
	
		if ( "mode".equals( name ) || "lesson_mode".equals( name ) ) {
			if ( "normal".equals( value ) || "browse".equals( value ) || "review".equals( value ) ||
			   value.charAt(0) == 'n' || value.charAt(0) == 'b'   || value.charAt(0) == 'r'  ) {
				blnCheck = true;
			}
		} else if ( "status".equals( name ) || "lesson_status".equals( name )  ) {
			// 送信バージョンがSCORM1.3の場合
			if ( "passed".equals( value ) || "failed".equals( value ) ||
				"unknown".equals( value ) ) {
				blnCheck = true;
			}
		} else if ( "completion_status".equals( name ) ) {
			// 送信バージョンがSCORM1.3の場合のみ実行される
			if ( "completed".equals( value ) || "incomplete".equals( value ) ||
				"unknown".equals( value ) ) {
				blnCheck = true;
			}
		} else if ( "exit".equals( name ) ) {
			if ( "time-out".equals( value ) || "suspend".equals( value ) || "logout".equals( value ) ||
			   value.charAt(0) == 't'	   ||  value.charAt(0) == 's'	 ||  value.charAt(0) == 'l'   ) {
				blnCheck = true;
			}
		} else if ( "why_left".equals( name ) ) {
			if( "student selected".equals( value ) || "lesson directed".equals( value ) ||
				"exit".equals( value ) || "directed departure".equals( value ) ||
				value.charAt(0) == 's' || value.charAt(0)  == 'l' || value.charAt(0)  == 'e' ||
				value.charAt(0)  == 'd')	{
					blnCheck = true;
			}
		} else if ( "credit".equals( name ) ) {
			if ( "credit".equals( value ) || "no-credit".equals( value ) ||
			   value.charAt(0) == 'c'	 || value.charAt(0) == 'n'		 ) {
				blnCheck = true;
			}
		} else if ( "entry".equals( name ) ) {
			if ( "ab-initio".equals( name ) || "ab initio".equals( name ) ||  "resume".equals( name ) ||
			   value.charAt(0) == 'a' || value.charAt(0) == 'r' ) {
				blnCheck = true;
			}
		} else if ( "time_limit_action".equals( name )) {
			if ( "exit, message".equals( value ) || "exit, no message".equals( value )||
				"continue, message".equals( value ) || "continue, no message".equals( value )	||
				value.charAt(0) == 'e' || value.charAt(0) == 'c'){
					blnCheck = true;
			}
		} else if ("type".equals( name ) ) {
			if ( "true-false".equals( value ) ||  "choice".equals( value ) ||
				"fill-in".equals( value ) || "matching".equals( value ) ||
				"performance".equals( value ) || "likert".equals( value ) ||
				"sequencing".equals( value ) || "unique".equals( value ) ||
				 "numeric".equals( value ) || value.charAt(0) == 't' || 
				 value.charAt(0)== 'c' || value.charAt(0)== 'f' || value.charAt(0) == 'm' || 
				 value.charAt(0) == 'p' || value.charAt(0) == 'l' ||	value.charAt(0) == 's' || 
				 value.charAt(0) == 'u' || value.charAt(0) == 'n' ) {
					blnCheck = true;
			}
		} else if( "result".equals( name ) ) {
			if ( "correct".equals( value ) || "wrong".equals( value )	|| "incorrect".equals( value )	||
				"unanticipated".equals( value ) || "neutral".equals( value )	||
				CMIUtil.isNumeric(value, false)	 || value.charAt(0) == 'c' ||
				value.charAt(0) == 'w' || value.charAt(0) == 'u' || value.charAt(0) == 'n') {
				blnCheck = true;
			}
		}
	
		return blnCheck;
	}
   
	/**
     * データがCMIVocabulary型かチェックする<br>
     * @return String シリアライズデータ
     */
	protected String serializeCMIValue() {
   	    
		StringBuffer sbOut = new StringBuffer();
		String strName = getName();
		String strLocalValue = getLocalValue();
		String strLessonValue = getLessonValue();
		
		strLocalValue = putValue ( strLocalValue );
		strLessonValue = putValue( strLessonValue );
	
		sbOut.append(strLocalValue);
		sbOut.append(":");
		sbOut.append(strLessonValue);
		//シリアライズデータを復帰する
		return sbOut.toString();
	}
   
	/**
	 * シリアライズデータを解凍し、値をセットする<br>
     * @param data String シリアライズされたデータ
     */
	protected void deserializeCMIValue(String data) {
   	
		String strLocalValue = "";
		String strLessonValue = "";
		int iLessonPos = data.indexOf(":");
		if (iLessonPos != -1) {
			strLocalValue = data.substring(0,iLessonPos);
			strLessonValue = data.substring(iLessonPos+1,data.length());
		}
			
		if ( null != strLocalValue && !"#".equals( strLocalValue ) ) {
			strLocalValue = CMIUtil.urlDecode( strLocalValue );
			setLocalValue( strLocalValue );
			m_bySetValue = true;
		}
		if ( null != strLessonValue && !"#".equals( strLessonValue ) ) {
			strLessonValue = CMIUtil.urlDecode( strLessonValue );
			setLessonValue( strLessonValue );
			m_bySetValue = true;
		}
	}
   
	/**
     * 値を設定する。エレメントパスで指定したエレメントに値をセットする<br>
     * @param name エレメントパス
     * @param value 値
     */
	public abstract void localSetValue(String name, String value);
   
	/**
     * 値を取得する。エレメントパスで指定したエレメントに値を取得する<br>
     * @param name エレメントパス
     * @param doCheck チェックフラグ
     * @return String 取得された値
     */
	public abstract String localGetValue(String name, boolean doCheck);
   
	/**
     * 値を取得する。エレメントパスで指定したエレメントに値を取得する<br>
     * @param name エレメントパス
     * @return String 取得された値
     */
	public String localGetValue(String name) {
    	return localGetValue( name, true );
	}
   
    /**
     * localValue の値を設定する<br>
     * @param name エレメント名前
     */
	public abstract void setLocalValue(String name);
   
    /**
     * localValue の値を設定する<br>
     * @param name エレメント名前
     * @param value 設定された値
     */
	public abstract void setLocalValue(String name, String value);
   
	/**
     * localValue の値を取得する<br>
     * @return String 取得された値
     */
	public abstract String getLocalValue();
   
	/**
     * localValue の値がnullかどうかの判断する<br>
     * @return boolean 取得された値
     */
	public abstract boolean getIsNullValue();

	/**
     * localValue の値を取得する<br>
     * @param name String 名前
     * @return String 取得された値
     */
	public abstract String getLocalValue(String name);
   
	/**
     * lessonValue の値を設定する<br>
     * @param value String 設定された値
     */
	public abstract void setLessonValue(String value);
   
	/**
     * lessonValue の値を設定する<br>
     * @param name String エレメント名前
     * @param value String 設定された値
     */
	public abstract void setLessonValue(String name, String value);
   
	/**
	 * lessonValue の値を取得する<br>
	 * @return String 取得された値
	 */
	public abstract String getLessonValue();
   
    /**
     * lessonValue の値を取得する<br>
     * @param name String 名前
     * @return String 取得された値
     */
	public abstract String getLessonValue(String name);
   
	/**
     * localValue 値初期化<br>
     */
	public abstract void initLocalValue(); 
   
	/**
     * localValue 値初期化<br>
     * @param value String 初期化の値
     */
	public abstract void initLocalValue(String value);
   
	/**
     * lessonValue 値初期化<br>
     */
	public abstract void initLessonValue();
   
	/**
     * localValue 値初期化<br>
     * @param name String 初期化されたパス
     */
	public abstract void initLessonValue(String name);
   
	/**
	 * 必須チェック <br>
	 * @return boolean 必須入力の場合:true、必須入力ない場合:false
	 */
	public abstract boolean checkMandatory(); 
   
	/**
	 * デフォルト値をセットする <br>
	 */
	public abstract void setDefaultValue();
   
	/**
	 * 初期化前処理 <br>
	 */
	public abstract void before_initialize();
   
	/**
	 * 初期化処理 <br>
	 */
	public abstract void initialize();
   
	/**
	 * シリアライズ処理 <br>
	 * 値からシリアライズデータを生成する。<br>
	 * @param buf StringBuffer シリアライズデータ
	 */
	public abstract void serialize(StringBuffer buf);
   
	/**
	 * パラメータの取得 <br>
	 * シリアライズデータを解凍し、値をセットする<br>
	 * @param inString String シリアライズデータ
	 */
	public abstract void deserialize(String inString);
   
	/**
	 * デシリアライズ処理 <br>
	 * @param buf StringBuffer データバッファ
	 * @return int エラーコード
	 */
	public int getParam(StringBuffer buf) {
		int intErrCode = HACPError.HACP_ERR_SUCCESSFUL;
	
		IMaintenanceGetParam maintenanceGetParam = m_proto.getMaintenanceGetParam();
	
		if ( maintenanceGetParam != null ) {
			intErrCode = maintenanceGetParam.getParam(this, buf);
		} else {
			intErrCode = getParamSub(buf);
		}
		return intErrCode;
	}

	/**
	 * パラメータの設定 <br>
	 * @param name String 名前
	 * @param inString String データ
	 * @return int エラーコード
	 */
	public int putParam(String name, String inString) {
		int intErrCode = HACPError.HACP_ERR_SUCCESSFUL;
		IMaintenancePutParam maintenancePutParam = m_proto.getMaintenancePutParam();
		StringBuffer sbBuffer = new StringBuffer();
		sbBuffer.append( inString );
		if ( maintenancePutParam != null ) {	
			intErrCode = maintenancePutParam.putParam( this, sbBuffer );
		} else {
			intErrCode = putParamSub(name, inString);
		}
		return intErrCode;
   }
   
	/**
	 * サブパラメータ取得 <br>
	 * @param value StringBuffer 取得のデータ
	 * @return int エラーコード
	 */
	public abstract int getParamSub(StringBuffer value);
   
	/**
	 * サブパラメータ設定 <br>
	 * @param name String 名前
	 * @param inString String データ
	 * @return int エラーコード
	 */
	public abstract int putParamSub(String name, String inString);
   
	/**
	 * PutParamに必要なCMIデータを取得する
	 * CMIプロトデータインスタンスに登録しているPutParam用のグループ
	 * データ取得メソッドが存在する場合、そのメソッドを実行する <br>
	 * @param buf StringBuffer 取得のデータ
	 * @return int エラーコード
	 */
	public int getPutParam(StringBuffer buf) {
		int intErrCode = HACPError.HACP_ERR_SUCCESSFUL;
		IMaintenanceGetPutParam maintenanceGetPutParam = m_proto.getMaintenanceGetPutParam();
		
		if ( maintenanceGetPutParam != null ) {
			// CMIプロトデータインスタンスにPutParam用のグループデータ取得
			// メソッドが存在する場合、そのメソッドを実行する
			intErrCode = maintenanceGetPutParam.getPutParam(this, buf);
		}
		return intErrCode;
	}
   
	/**
	 * 発生したエラーコードを設定する
	 * @param code int エラーコード
	 */
	public void setError(int code) {
		if ( m_CBT != null ) {
			m_CBT.setError(code);
		} else {
			m_GCBT.setError(code);
		}
	}
   
	/**
	 * 発生したエラーコードを取得する
	 * @return int エラーコード
	 */
	public int getError() {
		int intErrCode;
		if ( m_CBT != null) {
			intErrCode = m_CBT.getError();
		} else {
			intErrCode = m_GCBT.getError();
		}
		return intErrCode;
   }
   
	/**
     * 発生したエラーコードを設定する
     * @param msg String エラーメッセージ
     */
	public void setVendorError(String msg) {
		if ( m_CBT != null ) {
			m_CBT.setVendorError(msg);
		} else {
			m_GCBT.setVendorError(msg);
		}
	}
   
	/**
     * デバッグ(プロトタイプ)取得する
     * @return String デバッグ(プロトタイプ)
     */
	public abstract String getDebugProto();
   
	/**
     * デバッグ(CMIデータ)取得取得する
     * @return デバッグ(CMIデータ)取得
     */
	public abstract String getDebugCMIData();
   
	/**
     * メッセージとエレメントから生成したベンダーメッセージを取得する。
     * @param buffer String メッセージ
     * @param element CMIElement エレメント
     * @return String メッセージ
     */
	public String getVendorData(String buffer, CMIElement element){
		StringBuffer sbBuffer = new StringBuffer();

		if ( buffer != null ) {
			sbBuffer.append(buffer);
		}
		if ( element != null ) {	
			String strPath = element.getPath();
			sbBuffer.append("/");
			sbBuffer.append(strPath);
		}

		return sbBuffer.toString();
	 }
	 
	/**
	 * メッセージから生成したベンダーメッセージを取得する。
	 * @param buffer String メッセージ
	 * @return String ベンダー情報
	 */
	public String getVendorData(String buffer){
		return getVendorData(buffer, null);
	}

	/**
	 * 保持している値からシリアライズデータを生成する。<br>
	 * @param buf StringBuffer シリアライズXMLデータ
	 */
	public abstract void serializeXMLLog(StringBuffer buf);

	/**
	 * XML形式でデータを取得する<br>
	 * @return String シリアライズデータ（XML形式）
	 */
	protected String serializeXMLValue() {
   	    
		StringBuffer sbOut = new StringBuffer();
		String strName = getName();
		String strLocalValue = getLocalValue();
		String strLessonValue = getLessonValue();

		if ((strLessonValue == null) || "".equals(strLessonValue) ) {
			if (strLocalValue != null) {
				sbOut.append(strLocalValue);
			}
		}
		else {
			sbOut.append(strLessonValue);
		}

		//シリアライズデータを復帰する
		return sbOut.toString();
	}

} 
