/*
このファイルの中身は、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) ______________________________________.
*/

//
//	Offline教材 AICCログパースクラス
//			変更履歴
//				2004.01.08	新規作成	二條　智文
//
package jp.co.ntt.lms.lo.Offline.Aicc;


import java.io.*;
import java.util.*;
import java.util.StringTokenizer;
import org.xml.sax.SAXException;

import jp.co.ntt.lms.Common.RDF.*;
import jp.co.ntt.lms.xmo.util.*;
import jp.co.ntt.lms.lo.Offline.OfflineLog.*;
import jp.co.ntt.lms.lo.*;
import jp.co.ntt.lms.lo.Offline.OfflineLoEnv;


/**
 * AICCログパースクラス
 * <PRE>
 * 処理内容：入力されたAiccLogのXMLデータをパースし、DBのレコード
 * クラスに変換する。
 * </PRE>
 */

public class AiccLogConverter
{

	//////////////////////////////////////////////////////////
	//	クラス変数
	//////////////////////////////////////////////////////////

	/** LOID */
	private String mstrLoID = null;

	/** USERID */
	private String mstrUserID = null;

	/** 教材IDを保持します。 */
	private String mstrMaterialID = null;

	/** ログのファイルパスを保持します。 */
	private String mstrLogPath = null;

	/** Offlineログ パースモジュール */
	private OfflineDocument mobjOfflineDoc = null;

	/** Offline ログ Courseタグデータ */
	private OfflineCourse mobjCourse = null;

	/** Offline ログ itemsタグデータ */
	private OfflineItems mobjItems = null;

	/** Offline ログ lomsタグデータ */
	private OfflineLoms mobjLoms = null;

	/** LOLogRecord */
	private LoLogRecord mobjLoLogRecord = null;

	/** LOLogSessionRecord */
	private LoLogSessionRecord[] mobjLoLogSessionRecords = null;

	/** AiccCoreRecord */
	private AiccCoreRecord[] mobjAiccCoreRecords = null ;

	/** SectionLogRecord */
	private SectionLogRecord[] mobjSectionLogRecords = null ;

	/** AiccInteractionRecord */
	private AiccInteractionRecord[] mobjAiccInteractionRecords = null;

	/** AiccCommentRecord */
	private AiccCommentRecord[] mobjAiccCommentRecords = null;

	/** AiccObjectivesRecord */
	private AiccObjectivesRecord[] mobjAiccObjectivesRecords = null;

	/** Aiccの教材ID */
	private String mstrCourseID = null;

	/** AiccのBLOCKID */
	private String mstrBlockID = null;

	/** AiccのレッスンID */
	private String mstrLessonID = null;

	/** AiccUID */
	private String mstrUid = null;

	/** 教材構造を保持します */
	private RDFNode mobjRDFNode = null;

	/** セッションIDを[mcnt](学習回数)をキーにして、保持します。 */
	private Hashtable mhtbSessionID = new Hashtable();

	//エラーメッセージ
	private static final String WRONG_ARGUMENT = "パラメータが不正です。";
	private static final String FAIL_PARSE = "パース処理に失敗しました。";
	private static final String NO_EXIST_COURSE = "courseタグが存在しません。";
	private static final String NO_EXIST_ITEMS = "itemsタグが存在しません。";
	private static final String NO_EXIST_LOMS = "lomsタグが存在しません。";
	private static final String FAIL_LOLOGSESSION = "LOLogSessionレコードが1件も作成できませんでした。";

	// ログファイル出力
	private static final String LOG_PRE = "OfflineLO:ログアップロード処理:パース処理:";
	private static final String START_INF_LOG = LOG_PRE + "処理を開始します。:";
	private static final String END_INF_LOG = LOG_PRE + "処理が終了しました。:";

	/**
	*	コンストラクタ<br>
	*	XMLデータをパースしてインスタンスを生成します。
	*	@param strFilePath ログファイルパス
	*/
	public AiccLogConverter( String strUserID, String strLoID, String strMaterialID, String strLogPath ){
		mstrUserID = strUserID;
		mstrLoID = strLoID;
		mstrMaterialID = strMaterialID;
		mstrLogPath = strLogPath;
	}


	/**
	 *	XMLデータをパースします。<BR>
	 *	レコードを作成しますので、事前にLoID,SessionID,UesrIDを設定してください。
	 *	@exception SAXException パースに失敗した場合
	 *	@exception IOException データ読み込みに失敗した場合
	 *	@exception AiccParseException 内部異常の場合
	 */
	public void parse() throws SAXException,AiccParseException,IOException
	{
		if ( mstrLogPath == null || mstrLoID == null || mstrUserID == null || mstrMaterialID == null ){
			throw new AiccParseException(WRONG_ARGUMENT);
		}

		// @debug 単体テスト用データ作成処理
		DebugLog.write( this.getClass(), START_INF_LOG + mstrLogPath, DebugLog.MID );

		mobjOfflineDoc = new OfflineDocument();

		try {
			mobjOfflineDoc.parse(mstrLogPath);
		}
		catch( OfflineLogParseException oe ) {
			DebugLog.write( this.getClass(), oe.getMessage(), DebugLog.HIGHT );
			DebugLog.write( this.getClass(), oe, DebugLog.HIGHT );
			throw new AiccParseException( FAIL_PARSE );
		}

		try {

			OfflineLoEnv objEnv = new OfflineLoEnv();

			String strMaterialPath = objEnv.getMaterialPath() + "/" + mstrMaterialID + "/" + mstrMaterialID + ".xml";

			// 教材構造を読み込む
			RDFDocument objDoc = new RDFDocument();
			mobjRDFNode = objDoc.load( strMaterialPath );
			// 教材IDの設定
			mstrCourseID = mobjRDFNode.getID();
		}
		catch( LOException le ) {
			// @log
			DebugLog.write( this.getClass(), le, DebugLog.HIGHT );
			throw new AiccParseException( le.getMessage() );
		}
		catch( RDFParseException rp ) {
			// @log
			DebugLog.write( this.getClass(), rp, DebugLog.HIGHT );
			throw new AiccParseException(rp.getMessage());
		}

		// オフラインログからcourse情報を取得します。取得できない場合はエラーとします。
		mobjCourse = mobjOfflineDoc.getCourse();
		if( mobjCourse == null ) {
			// @log
			DebugLog.write( this.getClass(), NO_EXIST_COURSE, DebugLog.HIGHT );
			throw new AiccParseException( FAIL_PARSE );
		}

		// オフラインログからitems情報を取得します。取得できない場合はエラーとします。
		mobjItems = mobjOfflineDoc.getItems();
		if( mobjItems == null ) {
			// @log
			DebugLog.write( this.getClass(), NO_EXIST_ITEMS, DebugLog.HIGHT );
			throw new AiccParseException( FAIL_PARSE );
		}

		// オフラインログからloms情報を取得します。取得できない場合はエラーとします。
		mobjLoms = mobjOfflineDoc.getLoms();
		if( mobjLoms == null ) {
			// @log
			DebugLog.write( this.getClass(), NO_EXIST_LOMS, DebugLog.HIGHT );
			throw new AiccParseException( FAIL_PARSE );
		}

		// LoLogSessionを作成します。
		mobjLoLogSessionRecords = makeLoLogSessionRecords();

		// LoLogSessionレコードが1件も作成できなかった場合はエラーとする
		if( mobjLoLogSessionRecords.length == 0 ) {
			throw new AiccParseException( FAIL_LOLOGSESSION );
		}

		// LoLogを作成します。
		mobjLoLogRecord = makeLoLogRecord();

		// OL_AiccCoreを作成します。
		mobjAiccCoreRecords = makeAiccCoreRecords();

		// OL_AiccInteractionを作成します。
		mobjAiccInteractionRecords = makeAiccInteractionRecords();

		// OL_AiccComments を作成します。
		mobjAiccCommentRecords = makeAiccCommentRecords();

		// OL_AiccObjectives を作成します。
		mobjAiccObjectivesRecords = makeAiccObjectivesRecords();

		// OL_SelcionLog を作成します。
		mobjSectionLogRecords = makeSectionLogRecords();

		// @LOG >info >5
		DebugLog.write( this.getClass(), END_INF_LOG + mstrLogPath, DebugLog.MID );
	}



	/**
	*	AiccCoreRecord配列を返却します。<br>
	*	レコードが存在しない場合は、nullを返却します。
	*	@return AiccCoreRecord[] AiccCoreRecord配列
	*/
	public AiccCoreRecord[] getAiccCoreRecords()
	{
		return mobjAiccCoreRecords;
	}

	/**
	*	SectionLogRecord配列を返却します。<br>
	*	レコードが存在しない場合は、nullを返却します。
	*	@return SectionLogRecord[] SectionLogRecord配列
	*/
	public SectionLogRecord[] getSectionLogRecords()
	{
		return mobjSectionLogRecords;
	}

	/**
	*	AiccInteractionRecord配列を返却します。<br>
	*	レコードが存在しない場合は、nullを返却します。
	*	@return AiccCoreRecord[] AiccInteractionRecord配列
	*/
	public AiccInteractionRecord[] getAiccInteractionRecords()
	{
		return mobjAiccInteractionRecords;
	}

	/**
	*	AiccCommentRecord配列を返却します。<br>
	*	レコードが存在しない場合は、nullを返却します。
	*	@return AiccCommentRecord[] AiccCommentRecord配列
	*/
	public AiccCommentRecord[] getAiccCommentRecords()
	{
		return mobjAiccCommentRecords;
	}

	/**
	*	AiccObjectivesRecord配列を返却します。<br>
	*	レコードが存在しない場合は、nullを返却します。
	*	@return AiccObjectivesRecord[] AiccObjectivesRecord配列
	*/
	public AiccObjectivesRecord[] getAiccObjectivesRecords()
	{
		return mobjAiccObjectivesRecords;
	}

	/**
	 * LoLogRecordを返却します
	 * @return LoLogRecord
	 */
	public LoLogRecord getLoLogRecord() {
		return mobjLoLogRecord;
	}

	/**
	 * LoLogSession配列を返却します
	 * @return LoLogSessionRecord[]
	 */
	public LoLogSessionRecord[] getLoLogSessionRecords() {
		return mobjLoLogSessionRecords;
	}


	/**
	 * LoLogSessionレコードを生成します
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private LoLogSessionRecord[] makeLoLogSessionRecords()
		throws AiccParseException
	{
		// セッションレコード数を取得する。
		int intSesCount = mobjCourse.getSesLength();

		// セッションIDを作成
		int intSessionID = 1;

		Vector vecSesRecord = new Vector();

		for( int i = 0; i < intSesCount; i++ ) {

			// オフラインログのcourse-org-ses情報を取得する
			OfflineCourseSes objSes = mobjCourse.getSes(i);

			// 学習回数を取得する
			int intMCNT = objSes.getMCNT();

			// 学習回数が設定されているもの( 0 以上 )のみレコードを作成する
			if( intMCNT >= 0 ) {

				// セッションIDの作成
				String strSessionID = Integer.toString( intSessionID );

				// 学習回数をキーにしてSessionIDを保存する
				mhtbSessionID.put( new Integer( intMCNT ), strSessionID );

				// インスタンス化
				LoLogSessionRecord objSesRecord = new LoLogSessionRecord();

				// ユーザIDの設定
				objSesRecord.setUserID( mstrUserID );
				// LOIDの設定
				objSesRecord.setLoID( mstrLoID );
				// SessionIDの設定
				objSesRecord.setSessionID( strSessionID );

				// 学習開始日付の設定
				if( objSes.getSDDate() != null ) {
					objSesRecord.setStudyStartDate( XMODate.parseTime( objSes.getSDDate() ) );
				}

				// 累積滞在時間の設定
				if( objSes.getSTLong() >= 0 ) {
					objSesRecord.setResidanceTime( Long.toString( objSes.getSTLong() ) );
				}

				// 合格・完了日付の設定
				char chrStatus = objSes.getStatusChar();

				// ステータスが合格なら、合格・完了
				if( chrStatus == OfflineLogConst.PASSED_STATUS ) {
					if( objSes.getEDDate() != null ) {
						objSesRecord.setPassday( XMODate.parseTime( objSes.getEDDate() ) );
						objSesRecord.setStudyEndDate( XMODate.parseTime( objSes.getEDDate() ) );
					}
				}
				// ステータスが完了なら、完了
				else if( chrStatus == OfflineLogConst.COMPLETED_STATUS ) {
					if( objSes.getEDDate() != null ) {
						objSesRecord.setStudyEndDate( XMODate.parseTime( objSes.getEDDate() ) );
					}
				}

				// レコードベクターに追加
				vecSesRecord.add( objSesRecord );

				// セッションIDをプラスする
				intSessionID++;
			}
		}

		LoLogSessionRecord[] objSesRecord = new LoLogSessionRecord[vecSesRecord.size()];
		vecSesRecord.copyInto( objSesRecord );

		return objSesRecord;

	}

	/**
	 * LoLogレコードを作製します。
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private LoLogRecord makeLoLogRecord()
		throws AiccParseException
	{
		LoLogRecord objLoLogRecord = new LoLogRecord();

		// ユーザIDの設定
		objLoLogRecord.setUserID( mstrUserID );
		// LOIDの設定
		objLoLogRecord.setLoID( mstrLoID );

		// 学習開始時間の設定
		objLoLogRecord.setStudyStartDate( XMODate.parseTime( mobjCourse.getSDDate() ) );

		// 累積滞在時間の設定
		if( mobjCourse.getTTLong() >= 0 ) {
			objLoLogRecord.setResidanceTime( Long.toString( mobjCourse.getTTLong() ) );
		}

		// アクセス回数の設定
		objLoLogRecord.setAccessCnt( Integer.toString(mobjCourse.getSesLength()) );

		return objLoLogRecord;
	}

	/**
	 * すべてのAiccCoreレコードを生成します。
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private AiccCoreRecord[] makeAiccCoreRecords()
		throws AiccParseException
	{
		// セッションレコード数を取得する。
		int intSesCount = mobjCourse.getSesLength();

		Vector vecAiccCoreRecord = new Vector();

		// lomレコード数を取得する。
		int intLomCount = mobjLoms.getLomLength();

		// セッションレコード数分Coreレコードを生成する。
		for( int i = 0; i < intSesCount; i++ ) {

			// lomタグ分ループする。
			for( int j = 0; j < intLomCount; j++ ) {

				// 一件分のCoreレコードを作製する
				AiccCoreRecord objTempRecord = makeAiccCoreRecord( i, j );
				if( objTempRecord != null ) {
					vecAiccCoreRecord.add( objTempRecord );
				}
			}
		}

		// 配列へのコピー
		AiccCoreRecord[] objRecList = new AiccCoreRecord[vecAiccCoreRecord.size()];
		vecAiccCoreRecord.copyInto( objRecList );

		return objRecList;
	}

	/**
	 *	一つのAiccLog要素配下の全Interactionレコードを検索します。<br>
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private AiccInteractionRecord[] makeAiccInteractionRecords()
		throws AiccParseException
	{
		Vector vecAiccInteractionRecord = new Vector();

		// lomレコード数を取得する。
		int intLomCount = mobjLoms.getLomLength();

		// lomレコード分ループする
		for( int i = 0; i < intLomCount; i++ ) {

			OfflineLom objLom = mobjLoms.getLom( i );

			int intBkCount= objLom.getBkLength();

			// lomタグ分ループする。
			for( int j = 0; j < intBkCount; j++ ) {

				OfflineBk objBk = objLom.getBk(j);

				int intBkLogCount = objBk.getBkLogLength();

				for( int n = 0; n < intBkLogCount; n++ ) {
					OfflineBkLog objBkLog = objBk.getBkLog( n );
					// 一件分のCoreレコードを作製する
					AiccInteractionRecord objTempRecord = makeAiccInteractionRecord( objLom, objBk, objBkLog );

					if( objTempRecord != null ) {
						vecAiccInteractionRecord.add( objTempRecord );
					}
				}
			}
		}

		// 配列へのコピー
		AiccInteractionRecord[] objRecList = new AiccInteractionRecord[vecAiccInteractionRecord.size()];
		vecAiccInteractionRecord.copyInto( objRecList );

		return objRecList;
	}

	/**
	 * すべてのAiccCommentレコードを生成します。
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private AiccCommentRecord[] makeAiccCommentRecords()
		throws AiccParseException
	{

		Vector vecAiccCommentRecord = new Vector();

		// lomレコード数を取得する。
		int intLomCount = mobjLoms.getLomLength();

		// course-sesのmcntの最大値を取得する
		int intMaxMcnt = mobjCourse.getMaxMcnt();

		// 最大値が取得できなかった場合は0件の配列を返す。
		if( intMaxMcnt == -1 ) {
			return new AiccCommentRecord[0];
		}

		// lomタグ分ループする。
		for( int i = 0; i < intLomCount; i++ ) {

			OfflineLom objLom = mobjLoms.getLom(i);
			OfflineCmi objCmi = objLom.getCmi();

			// コメントタグが存在する場合のみ作成する
			if( objCmi.getComments() != null ) {
				// 一件分のCommentレコードを作製する
				AiccCommentRecord objTempRecord = makeAiccCommentRecord( objLom, intMaxMcnt );
				// nullでは無い場合のみVectorに追加
				if( objTempRecord != null ) {
					vecAiccCommentRecord.add( objTempRecord );
				}
			}
		}

		// 配列へのコピー
		AiccCommentRecord[] objRecList = new AiccCommentRecord[vecAiccCommentRecord.size()];
		vecAiccCommentRecord.copyInto( objRecList );

		return objRecList;
	}

	/**
	 *	一つのAiccLog要素配下の全Objectivesレコードを検索します。<br>
 	 *	@param Element AiccLog１要素
	 *	@param Vector  Objectives情報を格納するVector
	 *
	 */
	private AiccObjectivesRecord[] makeAiccObjectivesRecords()
		throws AiccParseException
	{


		Vector vecAiccObjectivesRecord = new Vector();

		// lomレコード数を取得する。
		int intLomCount = mobjLoms.getLomLength();

		// course-sesのmcntの最大値を取得する
		int intMaxMcnt = mobjCourse.getMaxMcnt();

		// 最大値が取得できなかった場合は0件の配列を返す。
		if( intMaxMcnt == -1 ) {
			return new AiccObjectivesRecord[0];
		}

		// lomタグ分ループする。
		for( int i = 0; i < intLomCount; i++ ) {

			OfflineLom objLom = mobjLoms.getLom(i);

			OfflineCmi objCmi = objLom.getCmi();
			OfflineCmiObjectives objObjectives = objCmi.getObjectives();

			if( objObjectives != null ) {

				int intObjCount = objObjectives.getObjectivesLogLength();

				for( int j = 0; j < intObjCount; j++ ) {

					OfflineCmiObjectivesLog objObjectivesLog = objObjectives.getObjectivesLog(j);
					// 一件分のObjectivesレコードを作成する
					AiccObjectivesRecord objTempRecord = makeAiccObjectivesRecord( objLom, objObjectivesLog, intMaxMcnt );
					// nullでは無い場合のみVectorに格納する
					if( objTempRecord != null ) {
						vecAiccObjectivesRecord.add( objTempRecord );
					}
				}
			}
		}

		// 配列へのコピー
		AiccObjectivesRecord[] objRecList = new AiccObjectivesRecord[vecAiccObjectivesRecord.size()];
		vecAiccObjectivesRecord.copyInto( objRecList );

		return objRecList;
	}



	/**
	 * Coreレコードを生成します。<br>
	 * @param intSesIndex セッションインデックス
	 * @param intLomIndex lomインデックス
	 * @return AiccCoreRecord 生成したレコード
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private AiccCoreRecord makeAiccCoreRecord(	int intSesIndex,
												int intLomIndex
												)
		throws AiccParseException
	{
		// オフラインログのセッション情報を取得する
		OfflineCourseSes objCourseSes = mobjCourse.getSes( intSesIndex );

		int intMCNT = objCourseSes.getMCNT();

		// セッションIDを取得する
		String strSessionID = (String)mhtbSessionID.get( new Integer( intMCNT ) );

		// セッションIDが取得できない場合はnullを返す。
		if( strSessionID == null ) {
			return null;
		}

		// セッションIDが存在した場合のみ作成

		// lomデータを取得する
		OfflineLom objLom = mobjLoms.getLom( intLomIndex );
		String strElementID = objLom.getID();

		// cmiデータを取得する
		OfflineCmi objCmi = objLom.getCmi();

		// Coreレコードのインスタンス化
		AiccCoreRecord result = new AiccCoreRecord();

		// ユーザIDの設定
		result.setUserID(mstrUserID);

		// LOIDの設定
		result.setLoID(mstrLoID);

		// セッションIDの設定
		result.setSessionID(strSessionID);

		// UIDの設定
		// 教材構造から該当するエレメントIDを持つノードを取得する
		String strUid = getUid( strElementID );
		if( strUid == null ) {
			// UIDが取得できない場合はレコードを作成しない
			return null;
		}
		result.setUid( strUid );

	   	// 該当するitem-org-sesを取得
		OfflineItem objItem = mobjItems.getItemFromID( strElementID );

		// LessonStatusの設定
		if( objItem != null ){
			String strStatus = objItem.getStatus( intMCNT );
			//LessonStatusが0の場合、訪問していないエレメントの為OL_AiccCoreテーブルにセットしない。
			if( strStatus == null ){
				return null;
			}
			result.setLessonStatus( strStatus );
		}

		// rawの設定
		if( objItem != null ){
			String strRawScore = objItem.getRawScore( intMCNT );
			result.setRawScore( strRawScore );
		}

		// maxの設定
		if( objItem != null ){
			String strMaxScore = objItem.getMaxScore( intMCNT );
			result.setMaxScore( strMaxScore );
		}

		// minの設定
		if( objItem != null ){
			String strMinScore = objItem.getMinScore( intMCNT );
			result.setMinScore( strMinScore );
		}


		// 取得できた場合のみ合計時間を取得
		if( objItem != null ) {
			// 該当回数の合計時間を取得
			String strTime = objItem.getTotalSt( intMCNT );
			result.setStayTime( strTime );
		}

		// Lesson_Locationの設定
		result.setLessonLocation( objCmi.getLessonLocation() );

		// exitの設定
		result.setExist( objCmi.getExit() );

		return result;
	}


	/**
	 * すべてのSectionLogレコードを生成します。<br>
	 * @return 取得したノード。ノードを取得できなかった場合はnullが返る。
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private SectionLogRecord[] makeSectionLogRecords()
		throws AiccParseException
	{
		Vector vecSectionLogRecord = new Vector();

		// item数を取得する
		int intItemCount = mobjItems.getItemLength();

		// セクションレコードを作成する
		for( int i = 0; i < intItemCount; i++ ) {

			OfflineItem objItem = mobjItems.getItem(i);

			char chrType = objItem.getTypeChar();

			// ブロック要素のみSectionLogレコードを作成する
			if( chrType == OfflineLogConst.BLOCK_TYPE ) {

				// itemのセッションを取得する
				int intSesCount = objItem.getSesLength();


				for( int j = 0; j < intSesCount; j++ ) {

					OfflineItemSes objSes = objItem.getSes(j);

					// 1件分のSectionLogレコードを作成する
					SectionLogRecord objTempRecord = makeSectionLogRecord( objItem, objSes );

					if( objTempRecord != null ) {
						vecSectionLogRecord.add( objTempRecord );
					}
				}

			}
		}

		// 配列へのコピー
		SectionLogRecord[] objRecList = new SectionLogRecord[vecSectionLogRecord.size()];
		vecSectionLogRecord.copyInto( objRecList );

		return objRecList;
	}

	/**
	 * Courseのセッション情報から1件のSectionLogレコードを生成します。<br>
	 * @param objSes Course-ses情報
	 * @return 取得したノード
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private SectionLogRecord makeSectionLogRecord( OfflineItem objItem, OfflineItemSes objSes )
		throws AiccParseException
	{
		// 学習回数の取得
		int intMCNT = objSes.getMCNT();

		// SessionIDを取得する
		String strSessionID = (String)mhtbSessionID.get( new Integer( intMCNT ) );

		// セッションIDが取得できなかった場合はnullを返す。
		if( strSessionID == null ) {
			return null;
		}

		// レコードのインスタンス化
		SectionLogRecord result = new SectionLogRecord();

		// ユーザIDの設定
		result.setUserID(mstrUserID);
		// LOIDの設定
		result.setLoID(mstrLoID);

		// セッションIDの設定
		result.setSessionID( strSessionID );

		// Uidの設定(コースIDを設定する)
		String strUid = getUid( objItem.getID() );
		if( strUid == null ) {
			// UIDが取得できない場合はレコードを作成しない
			return null;
		}
		result.setUid( strUid );

		// Lesson_Statusの設定
		result.setLessonStatus( objSes.getStatus() );

		// timeの設定
		result.setTime( objSes.getST() );

		return result;
	}

	/**
	 * Interactionレコードを生成します。<br>
	 * @param childElementName 検索するエレメント名<br>
	 * @param objLom Lom情報
	 * @param objBk Bk情報
	 * @return AiccInteractionRecord 取得したノード
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private AiccInteractionRecord makeAiccInteractionRecord( OfflineLom objLom, OfflineBk objBk, OfflineBkLog objBkLog )
		throws AiccParseException
	{

		AiccInteractionRecord result = new AiccInteractionRecord();

		// 学習回数
		int intMCNT = objBk.getMCNT();
		// 表示回数
		int intNCNT = objBk.getNCNT();

		// セッションIDを取得する
		String strSessionID = (String)mhtbSessionID.get( new Integer( intMCNT ) );

		// セッションIDが取得できない場合はnullを返す。
		if(strSessionID == null ) {
			return null;
		}

		// ユーザIDの設定
		result.setUserID(mstrUserID);

		// LOIDの設定
		result.setLoID(mstrLoID);

		// セッションIDの設定
		result.setSessionID( strSessionID );

		// course_idの設定
		result.setCourseID( mstrCourseID );

		// UIDの設定
		String strElementID = objLom.getID();
		String strUid = getUid( strElementID );
		if( strUid == null ) {
			// UIDが取得できない場合はレコードを作成しない
			return null;
		}
		result.setUid( strUid );

		// student_idの設定
		result.setStudentID( mobjCourse.getSID() );

		// lesson_idの設定
		result.setLessonID( strElementID );

		// response_timesの設定
		result.setResponseTimes( Integer.toString( objBkLog.getTagNo() ) );

		// 日付と時間の設定
		OfflineItemSes objItemSes = mobjItems.getSesFromIdMcntNcnt( strElementID, intMCNT, intNCNT );
		// 存在した場合のみ設定する
		if( objItemSes != null ) {
			String strSD = objItemSes.getSD();
			String strDate = null;
			String strTime = null;
			if( strSD != null && strSD.indexOf( " " ) >= 0 ) {
				strDate = strSD.substring( 0, strSD.indexOf( ' ' ) );
				// 日付の':'を'/'に変関する
				strDate = strDate.replace( ':', '/' );
				strTime = strSD.substring( strSD.indexOf( ' ' ) + 1, strSD.length() );
			}
			// 日付の設定
			result.setDate( strDate );
			// 時間の設定
			result.setTime( strTime );
		}

		// interaction_id の設定
		result.setInteractionID( objBkLog.getID() );

		// objective_idの設定
		result.setObjectiveID( objBkLog.getObjectivesID() );

		// type_interactionの設定
		result.setTypeInteraction( objBkLog.getType()  );

		// correct_responseの設定
		result.setCorrectResponse( objBkLog.getCorrectResponse() );

		// student_responseの設定
		result.setStudentResponse( objBkLog.getStudentResponse() );

		// resultの設定
		result.setResult( objBkLog.getResult() );

		// weighting の設定
		result.setWeighting( objBkLog.getWeighting() );

		// latency の設定
		result.setLatency( objBkLog.getLatency() );

		return result;
	}





	/**
	 * 1件分のCommentレコードを生成します。<br>
	 * @param objLom lomエレメントデータ
	 * @int intMaxMcnt 最大の学習回数
	 * @return 取得したノード
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 */
	private AiccCommentRecord makeAiccCommentRecord( OfflineLom objLom, int intMaxMcnt )
		throws AiccParseException
	{

		// セッションIDを取得する
		String strSessionID = (String)mhtbSessionID.get( new Integer( intMaxMcnt ) );

		// セッションIDが取得できない場合はnullを返す。
		if( strSessionID == null ) {
			return null;
		}

		AiccCommentRecord result = new AiccCommentRecord();

		// cmi情報を取得する
		OfflineCmi objCmi = objLom.getCmi();

		// ユーザIDを設定します。
		result.setUserID(mstrUserID);

		// LOIDを設定します。
		result.setLoID(mstrLoID);

		// セッションIDを設定します。
		result.setSessionID( strSessionID );

		// course_idを設定する
		result.setCourseID( mstrCourseID );

		// student_idを設定する
		result.setStudentID( mobjCourse.getSID() );

		// uidを設定する
		String strUid = getUid( objLom.getID() );
		if( strUid == null ) {
			// UIDが取得できない場合はレコードを作成しない
			return null;
		}
		result.setUid( strUid );

		// lesson_idを設定する
		result.setLessonID( objLom.getID() );

		// DateとTimeの設定
		OfflineItemSes objItemSes = mobjItems.getSesFromIdMcntNcnt( objLom.getID(), intMaxMcnt, 1 );
		// 取得できた場合のみ設定する
		if( objItemSes != null ) {

			String strSD = objItemSes.getSD();
			String strDate = null;
			String strTime = null;
			if( strSD != null && strSD.indexOf( " " ) >= 0 ) {
				strDate = strSD.substring( 0, strSD.indexOf( ' ' ) );
				// 日付の':'を'/'に変関する
				strDate = strDate.replace( ':', '/' );
				strTime = strSD.substring( strSD.indexOf( ' ' ) + 1, strSD.length() );
			}
			result.setDate( strDate );
			result.setTime( strTime );
		}

		// commentの設定
		result.setComment( objCmi.getComments() );


		return result;
	}





	/**
	 * 1件分のObjectivesレコードを生成します。<br>
	 * @param objLom lomエレメントデータ
	 * @param objObjectives objectivesエレメントデータ
	 * @int intMaxMcnt 最大の学習回数
	 * @return 取得したノード
	 * @exception AiccParseException ログ不整合のため、レコードが生成できなかった場合
	 *
	 */
	private AiccObjectivesRecord makeAiccObjectivesRecord(
			OfflineLom objLom,
			OfflineCmiObjectivesLog objObjectives,
			int intMaxMcnt )
		throws AiccParseException
	{

		// セッションIDを取得する
		String strSessionID = (String)mhtbSessionID.get( new Integer(intMaxMcnt) );

		// セッションIDが取得できなかった場合はnullを返す。
		if( strSessionID == null ) {
			return null;
		}

		AiccObjectivesRecord result = new AiccObjectivesRecord();

		// ユーザIDの設定
		result.setUserID(mstrUserID);

		// LOIDの設定
		result.setLoID(mstrLoID);

		// SessionIDの設定
		result.setSessionID( strSessionID );

		// uidの設定
		String strUid = getUid( objLom.getID() );
		if( strUid == null ) {
			// UIDが取得できない場合はレコードを作成しない
			return null;
		}
		result.setUid( strUid );

		// course_idの設定
		result.setCourseID( mstrCourseID );

		// student_idの設定
		result.setStudentID( mobjCourse.getSID() );

		// lesson_idの設定
		result.setLessonID( objLom.getID() );

		// DateとTimeの設定
		OfflineItemSes objItemSes = mobjItems.getSesFromIdMcntNcnt( objLom.getID(), intMaxMcnt, 1 );
		// 取得できた場合のみ設定する
		if( objItemSes != null ) {

			String strSD = objItemSes.getSD();
			String strDate = null;
			String strTime = null;
			if( strSD != null && strSD.indexOf( " " ) >= 0 ) {
				strDate = strSD.substring( 0, strSD.indexOf( ' ' ) );
				// 日付の':'を'/'に変関する
				strDate = strDate.replace( ':', '/' );
				strTime = strSD.substring( strSD.indexOf( ' ' ) + 1, strSD.length() );
			}
			result.setDate( strDate );
			result.setTime( strTime );
		}

		// objective_idの設定
		result.setObjectiveID( objObjectives.getID() );

		// rawの設定
		result.setRawScore( objObjectives.getRaw() );

		// maxの設定
		result.setMaxScore( objObjectives.getMax() );

		// minの設定
		result.setMinScore( objObjectives.getMin() );

		// statusの設定
		result.setStatus( objObjectives.getStatus() );

		return result;
	}


	/**
	 * 教材構造から該当エレメントIDのUIDを取得する。
	 * @param strElementID エレメントID
	 * @return String UID
	 * @exception AiccParseException 該当するエレメントが存在しない場合
	 */
	private String getUid( String strSystemID )
		throws AiccParseException
	{
		if( strSystemID == null || strSystemID.equals( "" ) ) {
			return null;
		}

		RDFNode objTempNode = mobjRDFNode.searchNodeFromSystemID(strSystemID);
		// 見つからなかった場合はnullを返す。
		if( objTempNode == null ) {
			return null;
		}
		String strUid = objTempNode.getID();

		return strUid;
	}

}

