/*
このファイルの中身は、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.28	zcj  新規作成		
//

package jp.co.ntt.lms.lo.scorm.cbtcom;

/**
 * CMI データモデル　末端要素 クラス
 * @author zhaicj
 *
 */

public class CMILeafElement extends CMIElement {
	
	private CMIValueBuffer m_value = null;
	
	/**
	 * CMILeafElementクラスの初期処理<br>
	 * @param proto CMIElementProtoオブジェクト
	 * @param val CMIValueBufferオブジェクト
	 */
	public CMILeafElement(CMIElementProto proto, CMIValueBuffer val) {
		super(proto);
		if  (val == null)  {
			m_value = new CMIValueBuffer();
		} else {
			m_value = val;
			m_value.incLinkValueBuffer();
		}
		initialize();    
	}
	
	/**
	 * CMILeafElement クラスの初期処理(m_valueの初期化）<br>
	 */
	public CMILeafElement() {
		m_value = new CMIValueBuffer();
		m_value.incLinkValueBuffer();    
	}
   
	/**
	 * 値を設定(ローカル)処理<br>
	 * @param name　エレメントパス
	 * @param value　値
	 * @param doCheck
	 */
	public void localSetValue(String name, String value, boolean doCheck) {
		
		// バージョン情報の取得
		int inVersion = getVersion();
		
		if ( isWritable() ) {
				
			// ローカル値にデータを設定する
			setLocalValue(value);

			// setValue による設定フラグを真にする
			m_bySetValue = true;
					
			// パラメータがセッション項目の場合、レッスン値にも指定値を設定する。
			if ( isSession() ) {

				setLessonValue(value);
				
			}
		} else {
			// バージョン情報によりエラー情報を変更する
			if ( 3400 <= inVersion) {

				// エレメントがキーワードかチェック
				if ( checkParamKeyword(name) ) {
					// エラー：エレメントはキーワード
					setError(CMIError.ERR_INVALID_SETVALUE_CMI_KEYWORD);
				} else {
					// エラー ： 読み込み専用のエレメントに値をセットしようとした
					setError(CMIError.ERR_ELEMENT_IS_READ_ONLY);
				}
			}
			// バージョンが3.4以前の場合
			else {
				setError(CMIError.ERR_ELEMENT_CANNAT_HAVE_A_VALUE);
			}
			setVendorError(getVendorData("CMILeafElement.localSetValue", this));
		}   
	}
   
	/**
	 * 値を設定(ローカル)処理<br>
	 * @param name　エレメントパス
	 * @param value　値
	 */
	public void localSetValue(String name, String value) {
		localSetValue(name, value, true );
	}
   
	/**
	 * 値を取得(ローカル)処理<br>
	 * @param name　エレメントパス
	 * @param doCheck
	 * @return String  パラメータの値（文字列）
	 */
	public String localGetValue(String name, boolean doCheck) {
		
		String retStr = null;
		CMIParameterPath param = new CMIParameterPath(name);
		String strTheName = param.popFirstElement();

		if ( strTheName.equals( getName() ) ) {
			
			String strChildName = param.getNthElement(1);

			if ( null == strChildName || "".equals(strChildName) ) {
				// 読み込み許可がある場合
				if ( isReadable() ) {
					IMaintenanceGetValue maintenanceGetValue = 
											m_proto.getMaintenanceGetValue();
					if ( maintenanceGetValue != null ) {
						// GetValue メソッドが登録されている場合
						// メソッドをコールする
						StringBuffer sbName = new StringBuffer();
						sbName.append(name);
						retStr = maintenanceGetValue.getValue( this, sbName );
					} else {
						if ( isSession() ) {
							// セッションの場合
							if ( !m_value.getLessonIsNull() ) {
								// LessonValue を返す
								retStr = m_value.getLessonValue();
							}	
						} else {
							// 固定の場合
							if ( !m_value.getLessonIsNull() ) {
								// LessonValue を返す
								retStr = m_value.getLessonValue();
							} else {
								if ( !m_value.getLocalIsNull() ) {
									// LocalValue を返す
									retStr = m_value.getLocalValue();
								}	
							}
						}
					}
				}
	
				// 読み込み許可がない場合
				else {
					// バージョン情報を取得する
					int inVersion = getVersion();
	
					// バージョンが3.4以降の場合
					if( 3400 <= inVersion) {
						setError(CMIError.ERR_ELEMENT_IS_WRITE_ONLY);
					}
	
					// バージョンが3.4以前の場合
					else {
						setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
					}
					setVendorError(getVendorData("CMILeafElement.localGetValue", this));
				}
			} else {
				setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
				setVendorError(getVendorData("CMILeafElement.localGetValue", this));
			}
		} else {
			setError(CMIError.ERR_NOT_INPLEMENTED_ERROR);
			setVendorError(getVendorData("CMILeafElement.localGetValue", this));
		}	
		return retStr;
   }
   
   /**
	* 値を取得(ローカル)処理<br>
	* @param name　エレメントパス
	* @return String  パラメータの値（文字列）
	*/
	public String localGetValue(String name) {
		return localGetValue( name, true );
	}
	
	/**
	 * localValue の値を設定処理<br>
	 * @param value　String ローカル値
	 */
	public void setLocalValue(String value) {
		if (checkCMIDataType(value, m_proto.getValueType(), m_proto.getName()) != true) {
			int inVersion = getVersion();
			if ( 3400 <= inVersion ) {
				setError(CMIError.ERR_INCORRECT_DATA_TYPE);
			}
			else {
				setError(CMIError.ERR_ELEMENT_TYPE_MISMATCH);
			}
			setVendorError(getVendorData("CMILeafElement.setLessonValue", this));
		}
		else {
			m_value.setLocalValue(value);
			m_value.setLocalIsNull(false);
		}
	}
   
	/**
	 * 値を取得(ローカル)処理<br>
	 * @param name　エレメントパス
	 * @param value パラメータの値（文字列）
	 */
	public void setLocalValue(String name, String value) {
		if (  name == null || "".equals(name) ) {
			setLocalValue(value);
		} else {
			setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
			setVendorError(getVendorData("CMILeafElement.setLocalValue", this));
		}
	}
   
	/**
	 * localValue 値取得(パス指定)処理<br>
	 * @param name　パス
	 * @return String   localValue 値
	 */
	public String getLocalValue(String name) {
		String strValue = null;
		if ( null == name || "".equals(name) ){
			if ( !m_value.getLocalIsNull() ) {
				strValue = m_value.getLocalValue();
			}
		}else{
			setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
			setVendorError(getVendorData("CMILeafElement.getLocalValue", this));	
		}
		return strValue;
	}
   
	/**
	 * localValue 値取得(パス指定)処理<br>
	 * @return String   localValue 値
	 */
	public String getLocalValue() {
		String strValue = null;
		if ( !m_value.getLocalIsNull() ) {
			strValue = m_value.getLocalValue();
		}	
		return strValue;
	}
   
	/**
	 * LessonValue の値を設定処理<br>
	 * @param value String レッスン値
	 */			
	public void setLessonValue(String value) {

		if (checkCMIDataType(value, m_proto.getValueType(), m_proto.getName()) != true) {
			int inVersion = getVersion();
			if ( 3400 <= inVersion ) {
				setError(CMIError.ERR_INCORRECT_DATA_TYPE);
			}
			else {
				setError(CMIError.ERR_ELEMENT_TYPE_MISMATCH);
			}
			setVendorError(getVendorData("CMILeafElement.setLessonValue", this));
		}
		else {
			m_value.setLessonValue(value);
			m_value.setLessonIsNull(false);
		}
	}
   
	/**
	 * LessonValue の値を設定処理<br>
	 * @param name　String パス
	 * @param value　String 設定値
	 */
	public void setLessonValue(String name, String value) {
		if ( name == null || "".equals(name) ) {
			setLessonValue(value);
		} else {
			setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
			setVendorError(getVendorData("CMILeafElement.setLessonValue",this));
		}  
	}
   
	/**
	 * LessonValue 値取得処理<br>
	 * @return String   lessonValue 値
	 */
	public String getLessonValue() {
		String strValue = null;
		if ( !m_value.getLessonIsNull() ) {
			strValue = m_value.getLessonValue();
		}
		return strValue;
	}
   
	/**
	 * LessonValue 値取得(パス指定)処理<br>
	 * @param name　パス
	 * @return String   LessonValue 値
	 */
	public String getLessonValue(String name) {
		String strValue = null;

		if (  name == null || "".equals( name ) ) {
			if ( !m_value.getLessonIsNull() ) {
				strValue = m_value.getLessonValue();
			}	
		} else {
			setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
			setVendorError(getVendorData("CMILeafElement.getLessonValue", this));
		}
		return strValue;
	}
   
	/**
	 * localValue の値を初期化する。<br>
	 */
	public void initLocalValue() {
		m_value.setLocalValue("");
		m_value.setLocalIsNull(true);    
	}
   
	/**
	 * localValue の値を初期化する。<br>
     * @param value
     */
	public void initLocalValue(String value) {
		if ( value == null || "".equals( value ) ) {
			m_value.setLocalValue("");
			m_value.setLocalIsNull(true);
		} else {
			setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
			setVendorError(getVendorData("CMILeafElement.initLocalValue",this));
		}   
	}
   
	/**
	 * LessonValue の値を初期化処理<br>
	 * @param name　パス
	 */
	public void initLessonValue(String name) {
		if ( name == null || "".equals( name ) ) {
			m_value.setLessonValue("");
			m_value.setLessonIsNull(true);
		} else {
			setError(CMIError.ERR_INVALID_AURGUMENT_ERROR);
			setVendorError(getVendorData("CMILeafElement.initLessonValue",this));
		}   
	}
   
	/**
	 * LessonValue の値を初期化処理<br>
	 */
	public void initLessonValue() {
		m_value.setLessonValue("");
		m_value.setLessonIsNull(true);
	}
   
	/**
	 * 必須入力のチェック処理<br>
	 * @return boolean
	 */
	public boolean checkMandatory() {
		if ( isMandatory( ) ) {
			// 入力必須の場合
			if ( !m_bySetValue && m_value.getLocalIsNull() ) {
				// エラー
				setError(CMIError.ERR_NOT_INITALIZED);
				setVendorError(getVendorData("CMILeafElement.checkMandatory",this));
				return false;
			}
		}
		return true;
	}
   
	/**
	 * デフォルト値をセット処理<br>
	 */
	public void setDefaultValue( ) {
		String strDefaultData = m_proto.getDefaultData();
		if ( strDefaultData != null ) {
			
			m_value.setLocalValue(strDefaultData);
			m_value.setLocalIsNull(false);

			// パラメータがセッション項目の場合、レッスン値にも指定値を設定する。
			if ( isSession() ) {
				m_value.setLessonValue(strDefaultData);
				m_value.setLessonIsNull(false);
			}
			
			// setValue による設定フラグを真にする
			m_bySetValue = true;	
		}
	}
   
	/**
	 * 初期化前処理<br>
	 */			
	public void before_initialize() {
		IBeforeInitializer beforeInitializer = m_proto.getBeforeInitializer();
		
		if ( null != beforeInitializer ) {
			// before_initializer メソッドが登録されている場合
			// メソッドをコールする
			beforeInitializer.before_Initializer(this);		
		} else {
			// before_initializer メソッドが登録されていない場合
			if ( isSession() ) {
				// セッションタイプの処理
				if ( !m_bySetValue ) {
					// setValue による更新なし
					// LessonValue の値をLocalValue にコピーする
					if  (!m_value.getLessonIsNull() ) {
						m_value.setLocalValue( m_value.getLessonValue() );
						m_value.setLocalIsNull(false);
					}
				}
			}
		}
	}
   
	/**
	 * 初期化処理<br>
	 */
	public void initialize() {
		IInitializer initializer = m_proto.getInitializer();
		if ( initializer != null ) {
			// initializer メソッドが登録されている場合
			// メソッドをコールする
			initializer.initializer(this);
		} else {
			// initializer メソッドが登録されていない場合
			// デフォルト処理
			if ( isSession() ) {
				// セッションタイプの処理
				// setValueによる更新がない場合、レッスン値を初期化するように修正
				if ( !m_bySetValue ) {
					// setValue による更新なし
					// LessonValue を初期化する
					initLessonValue();
				}
				// setValueによる更新がある場合、フラグを落とすように修正
				else {
					// setValue実行フラグをfalseにする。
					m_bySetValue = false;
				}
			} 
		}
	}
   
	/**
	 * 値からシリアライズデータを生成処理<br>
	 * @param buf StringBuffer シリアライズデータ
	 */
	public void serialize(StringBuffer buf) {
		if ( buf == null ) {
			buf = new StringBuffer();
		}
		String strName = getName();

		if ( isSerializable() ) {
			String strSerializedValue = serializeCMIValue();
			buf.append(strName);
			buf.append("=");
			buf.append( strSerializedValue );
		}
	}
   
	/**
	 * シリアライズデータを解凍し、値をセット処理<br>
	 * @param inString シリアライズデータ
	 */
	public void deserialize( String inString ) {
		if ( isSerializable() ) {
			deserializeCMIValue(inString);
		}
	}
   
	/**
	 * パラメータの取得処理<br>
	 * @param value StringBuffer データ値
	 * @return int エラーコード
	 */
	
	public int getParamSub( StringBuffer value ) {
		int intErrCode = HACPError.HACP_ERR_SUCCESSFUL;
		if ( value == null ) {
			value = new StringBuffer();
		}
		value.append(getKeyWord());
		value.append("=");
		value.append(m_value.getLocalValue());
		value.append(STR_CRLF);
		return intErrCode;
	}
   
	/**
	 *  パラメータの設定処理<br>
	 * @param name　名称
	 * @param inString　パラメータ
	 * @return int エラーコード
	 */
	public int putParamSub(String name, String inString) {
		int intErrCode = HACPError.HACP_ERR_SUCCESSFUL;
		m_value.setLocalValue(inString);
		return intErrCode;
	}
   
	/**
	 * デバッグ(プロトタイプ)を取得処理<br>
	 * @return String デバッグ情報
	 */
	public String getDebugProto() {
		String strPath = null;
		StringBuffer buff = new StringBuffer();
		StringBuffer sbuff = new StringBuffer();
		// パスを取得する。	
		strPath = getPath();	
		
		buff.append("Leaf Leaf=");
		if (isLeaf()) {
			buff.append("1");
		} else {
			buff.append("0");
		}
		
		buff.append("/Array=");
		if (isArray()) {
			buff.append("1");
		} else {
			buff.append("0");
		}
		
		buff.append("/Readable=");
		if (isReadable()) {
			buff.append("1");
		} else {
			buff.append("0");
		}
		
		buff.append("/Write=");
		if (isWritable()) {
			buff.append("1");
		} else {
			buff.append("0");
		}		
			
		buff.append("/Man=");	
		if (isMandatory()) {
			buff.append("1");
		} else {
			buff.append("0");
		}		
		
		buff.append("/Serial=");
		if (isSerializable()) {
			buff.append("1");
		} else {
			buff.append("0");
		}		
		
		buff.append("\n");			

		
		sbuff.append(strPath);
		sbuff.append("：(");
		sbuff.append(String.valueOf(m_LinkCount));
		sbuff.append(")\n");
		sbuff.append("    ");
		sbuff.append(buff.toString());
		
		return sbuff.toString();
	}
	/**
	 * デバッグ(CMIデータ)を取得処理<br>
	 * @return String CMIモデルのデバッグ情報
	 */
	public String getDebugCMIData() {
		String strPath = null;
		
		StringBuffer sval = new StringBuffer();
		
		// パスを取得する。
		strPath = getPath();
		
		StringBuffer sbuff = new StringBuffer();
		sbuff.append(strPath);
		sbuff.append(":(");
		sbuff.append(String.valueOf(m_LinkCount));
		sbuff.append(")\n");
		sbuff.append("    Leaf  Value=");
		sbuff.append("[");
		sbuff.append(m_bySetValue?" SET ":" --- ");
		sbuff.append("] ");
		// localValue
		sval.append(m_value.getLocalIsNull()?"(null)":"");
		sval.append("[");
		sval.append(m_value.getLocalValue());
		sval.append("]");
		sbuff.append(sval.toString());
		for ( int i = 0; i < ( 40 - (int)sval.length()); i++){
			sbuff.append(" ");
		}	
		// lessonValue
		sval.setLength(0);
		sval.append(" / ");
		sval.append(m_value.getLessonIsNull()?"(null)":"");
		sval.append("[");
		sval.append(m_value.getLessonValue());
		sval.append("]");
		sbuff.append(sval.toString());
		sbuff.append("\n");		
		return sbuff.toString();
	}

	/**
	 * 値からシリアライズXMLデータを生成処理<br>
	 * @param buf StringBuffer シリアライズデータ
	 */
	public void serializeXMLLog(StringBuffer buf) {
		if ( buf == null ) {
			buf = new StringBuffer();
		}
		
		String strName = getName();
		buf.append("<");
		buf.append(strName);
		buf.append(">");
		String strSerializedValue = serializeXMLValue();
		buf.append(strSerializedValue);
		buf.append("</");
		buf.append(strName);
		buf.append(">");
		buf.append("\n");
	}

	public boolean getIsNullValue(){
		return m_value.getLocalIsNull();
	}
}











