//
// メソッド管理XMO データアクセスクラス
//		変更履歴
//			2005.03.28	新規作成	 梅原 浩司
//
package jp.co.ntt.lms.xmo.Method;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;

import org.apache.commons.lang.StringEscapeUtils;

import jp.co.ntt.lms.lo.LOException;
import jp.co.ntt.lms.toeic650.common.TOEIC650CommonConst;
import jp.co.ntt.lms.xmo.DataAccess;
import jp.co.ntt.lms.xmo.Environment;
import jp.co.ntt.lms.xmo.MessageData;
import jp.co.ntt.lms.xmo.XMOException;
import jp.co.ntt.lms.xmo.Message.Message;
import jp.co.ntt.lms.xmo.Method.MethodData;
import jp.co.ntt.lms.xmo.util.ChangeEncode;
import jp.co.ntt.lms.xmo.util.DebugLog;


/**
 * メソッド 管理XMO データアクセスクラスです。<BR>
 * このクラスはメソッドテーブルへの登録、修正、削除、検索処理を実行します。<BR>
 * DataAccessクラスを使用し、登録、修正、削除、検索処理単位で
 * トランザクション管理を行います。
 * @author 梅原 浩司
 * @version 0.0.0.1 2005.03.28
 */
public class MethodDataAccess
	implements MethodTable, MethodMessage
{

	/**
	 * コンストラクタです。<BR>
	 */
	public MethodDataAccess() {
	}
	
	/**
	 * メソッドテーブルへ検索処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             CONDITION_KEY           検索条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 検索情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception XMOException データベースエラーが発生した場合
	 */
	public synchronized Vector select( Hashtable htData )
		throws XMOException
	{
		// グループデータがnullのとき
		if( htData == null ) {
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}

		// 戻り値
		Vector vecReturn = new Vector();

		// データアクセスクラスをインスタンス化します
		DataAccess objDataAccess = new DataAccess(TABLE_NAME);
		try {
			// トランザクションを開始する
			objDataAccess.trans( htData );

			// 検索処理実行メソッド
			vecReturn = selectAction( htData, objDataAccess );

			// コミット
			objDataAccess.commit();
		}
		catch( XMOException xe ) {
			DebugLog.write( this.getClass(), xe, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			throw xe;
		}
		catch( SQLException e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			// データベースエラーを設定
			throw new XMOException( getMessageData( DB_ERR ) );
		}

		return vecReturn;
	}

	/**
	 * 検索処理実行メソッドです。<BR>
	 * パラメータのチェックおよびトランザクションの管理は
	 * 上位メソッド内で行ってください。<BR>
	 * @param htbParam 検索情報
	 * @return Vector 検索結果
	 * @exception XMOException XMO独自エラー
	 * @exception SQLException DBエラーが発生した場合
	 */
	private Vector selectAction( Hashtable htbParam, DataAccess objDataAccess )
		throws XMOException, SQLException
	{

		Vector vecReturn = new Vector();

		try{
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv=new Environment();
			
			// アサイン検索フラグ("1"ならtrue)
			boolean blnAssignFlag = ( htbParam.containsKey( ASSIGNFLAG_KEY ) ) ? ((Boolean)htbParam.get( ASSIGNFLAG_KEY )).booleanValue() : false;
			
			// SQLの組み立て
			StringBuffer sbSQL = new StringBuffer();
			if( !blnAssignFlag ) {
				// 通常検索の場合
				sbSQL.append( "SELECT * FROM " + TABLE_NAME + " INNER JOIN " + LO_TABLE_NAME + " ON Method.LOID=LO.RealLOID" );
			} else {
				// アサイン検索の場合
				String strUserID = ( htbParam.containsKey( USERID_KEY ) ) ? (String)htbParam.get( USERID_KEY ) : "";
				if( strUserID.equals( "" ) ) {
					
				}
				int intAssignType = ( htbParam.containsKey( ASSIGNTYPE_KEY ) ) ? ((Integer)htbParam.get( ASSIGNTYPE_KEY )).intValue() : NON_TYPE;
				String strAssignTypeConditon = "";
				switch( intAssignType ) {
				case LEARN_TYPE:	// 検索条件に学習アサインを付加する
					strAssignTypeConditon = "AND learn_authority='1' ";
					break;
				case MANAGE_TYPE:	// 検索条件に管理アサインを付加する
					strAssignTypeConditon = "AND management_authority='1' ";
					break;
				}
				sbSQL.append( "SELECT * FROM GroupAndPeople INNER JOIN Assignments ON " );
				sbSQL.append( "(GroupAndPeople.memberShipID=Assignments.memberShipID " );
				sbSQL.append( "AND GroupAndPeople.childID='" + StringEscapeUtils.escapeSql(strUserID) + "' AND method_flag='1' " + strAssignTypeConditon );
				sbSQL.append( ") INNER JOIN LoRelation ON (Assignments.materialID=LoRelation.materialID) " );
				sbSQL.append( "INNER JOIN LO ON LoRelation.childID=LO.LOID " );
				sbSQL.append( "INNER JOIN Method ON LO.RealLOID=Method.LOID " );
			}
			
			// 条件文の取得
			String strCondition = (String)htbParam.get( CONDITION_KEY );
			if( strCondition != null ) {
				sbSQL.append( strCondition );
			}
			String strOrderBy = (String)htbParam.get( ORDER_BY );
			if( strOrderBy != null ) {
				sbSQL.append( strOrderBy );
			} else {
				//SQLServerの場合
				if(objEnv.getDBType().equals( Environment.DB_SQLSERVER )){
					sbSQL.append(" ORDER BY CONVERT(INT,SUBSTRING(LO.LOID, 3, { fn LENGTH(LO.LOID) })) ");
				//Oracleの場合
				}else if(objEnv.getDBType().equals( Environment.DB_ORACLE )){
					sbSQL.append(" ORDER BY TO_NUMBER(SUBSTR(LO.LOID, 3, LENGTH(LO.LOID))) ");
				//PostgreSQLの場合
				}else if(objEnv.getDBType().equals( Environment.DB_POSTGRE )){
					sbSQL.append(" ORDER BY TO_NUMBER(SUBSTR(LO.LOID, 3, LENGTH(LO.LOID)),'9999999999') ");
				}
			}

			ResultSet rs = objDataAccess.executeQuery(sbSQL.toString());
			while(rs.next()) {
				String strLoID = ChangeEncode.setChar( rs.getString( LO_ID ) );
				String strLoType = ChangeEncode.setChar( rs.getString( LO_TYPE ) );
				String strLoTytle = ChangeEncode.setChar( rs.getString( LO_TYTLE ) );
				String strLoExplanation = ChangeEncode.setChar( rs.getString( LO_EXPLANATION ) );
				String strLoVersion = ChangeEncode.setChar( rs.getString( LO_VERSION ) );
				String strRealLOID = ChangeEncode.setChar( rs.getString( REAL_LOID ) );
				String strConclusion = ChangeEncode.setChar( rs.getString( CONCLUSION ) );
			   String strMentorEmailAddress = ChangeEncode.setChar( rs.getString( MENTOR_EMAIL_ADDRESS ) );
				String strDeleteFlag = ChangeEncode.setChar( rs.getString( DELETE_FLAG ) );
				String strForeignID = ChangeEncode.setChar( rs.getString( FOREIGN_ID ) );
				String strKeyWord = ChangeEncode.setChar( rs.getString( KEYWORD ) );
				String strPrere = ChangeEncode.setChar( rs.getString( PRERE ) );
				String strMethodLOID = ChangeEncode.setChar( rs.getString( METHODLOID ));
				String strLOURL = ChangeEncode.setChar( rs.getString( LOURL ));
				boolean blnParallelFlag = (rs.getString( PARALLELFLAG ) != null && rs.getString( PARALLELFLAG ).equals("1") );
				Date dtDateStart;
				try {
					dtDateStart = rs.getDate( STARTDATE );
				} catch( Exception e ) {
					DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
					dtDateStart = null;
				}
				Date dtDateEnd;
				try {
					dtDateEnd = rs.getDate( ENDDATE );
				} catch( Exception e ) {
					DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
					dtDateEnd = null;
				}
				int intPreiodNum;
				try {
					intPreiodNum = Integer.parseInt( rs.getString( PERIODNUM ) );
				} catch( NumberFormatException e ) {
					intPreiodNum = 0;
				}
				boolean blnBeforeLearnFlag = (rs.getString( BEFORELEARNFLAG ) != null && rs.getString( BEFORELEARNFLAG ).equals("1") );
				boolean blnAfterLearnFlag = (rs.getString( AFTERLEARNFLAG ) != null && rs.getString( AFTERLEARNFLAG ).equals("1") );
				MethodData objData = new MethodData();
				objData.setLoID( strLoID );
				objData.setLoType( strLoType );
				objData.setLoTytle( strLoTytle );
				objData.setLoexplanation( strLoExplanation );
				objData.setLoVersion( strLoVersion );
				objData.setRealLOID( strRealLOID );
				objData.setConclusion( strConclusion );
				objData.setDeleteFlag( strDeleteFlag );
				objData.setForeignID( strForeignID );
				objData.setKeyWord( strKeyWord );
				objData.setPrere( strPrere );
				objData.setMentorEmail( strMentorEmailAddress );
				objData.setMethodLOID( strMethodLOID );
				objData.setParallelFlag( blnParallelFlag );
				objData.setDateStart( dtDateStart );
				objData.setDateEnd( dtDateEnd );
				objData.setPeriodNum( intPreiodNum );
				objData.setBeforeLearnFlag( blnBeforeLearnFlag );
				objData.setAfterLearnFlag( blnAfterLearnFlag );
				objData.setLOUrl(strLOURL);
				vecReturn.add( objData );
			}
		}
		catch(Exception ex)
		{

		}
		return vecReturn;

	}
	
	/**
	 * Methodテーブルへ登録処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。<BR>
	 * なおテーブルの主キー以外を省略した場合は省略したフィールドには
	 * Null値が格納されます。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             LOID                    LoID
	 *             METHODLOID              メソッドLOID
	 *             PARALLELFLAG            配下の並び順 並列フラグ
	 *             STARTDATE               開始日付
	 *             ENDDATE                 終了予定日付
	 *             PERIODNUM               期間
	 *             BEFORELEARNFLAG         計画日付前学習可能フラグ
	 *             AFTERLEARNFLAG          計画日付後学習可能フラグ
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 登録情報
	 * @exception LOException データベースエラーが発生した場合
	 */
	synchronized public void insert( Hashtable htData )
		throws LOException
	{
		// 評価データがnullのとき
		if( htData == null ) {
			// パラメータエラーをスローする
			throw new LOException( getMessageData( PARAM_WAR ) );
		}

		// データアクセスクラスをインスタンス化します
		DataAccess objDataAccess = new DataAccess(TABLE_NAME);
		try {
			// トランザクションを開始する
			objDataAccess.trans();

			// 登録処理を実行します
			insertAction( htData, objDataAccess );

			// コミット処理
			objDataAccess.commit();
		}
		catch( SQLException e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			// データベースエラーを設定
			throw new LOException( getMessageData( DB_ERR ) );
		}

		return;
	}

	/**
	 * 登録処理実行メソッドです。<BR>
	 * 自分のテーブルに登録処理を行った後、GroupAndPeople管理XMO
	 * に親子関係を登録します。
	 * パラメータのチェックおよびトランザクションの管理は
	 * 上位メソッド内で行ってください。<BR>
	 * @param htbParam 登録情報
	 * @exception LOException パラメータエラーが発生した場合
	 * @exception SQLException DBエラーが発生した場合
	 */
	private void insertAction( Hashtable htbParam, DataAccess objDataAccess )
		throws SQLException, LOException
	{
		String strLoID = (String)htbParam.get( LO_ID );
		if( strLoID != null ) {
			// レコードが既に存在する場合は例外を発生させる。
			if( objDataAccess.isExit(htbParam, LO_ID, TABLE_NAME) ) {
				throw new LOException( getMessageData( EXIST_RECORD_WAR ) );
			}
		}
		
		// 登録処理用のデータをセットします
		Hashtable htbData = getData( htbParam );
		// 登録用SQLを生成します
		String strSQL = objDataAccess.getInsertSQL(htbData);
		// 登録処理を実行
		objDataAccess.execute( strSQL );
	}
	
	/**
	 * Methodテーブルへ更新処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。<BR>
	 * 省略したフィールドは更新されません。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             LOID                    LoID
	 *             METHODLOID              メソッドLOID
	 *             PARALLELFLAG            配下の並び順 並列フラグ
	 *             STARTDATE               開始日付
	 *             ENDDATE                 終了予定日付
	 *             PERIODNUM               期間
	 *             BEFORELEARNFLAG         計画日付前学習可能フラグ
	 *             AFTERLEARNFLAG          計画日付後学習可能フラグ
	 *             LOURL                   URL
	 *          ---------------------------------------------
	 *             CONDITION_KEY           更新条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 更新情報
	 * @exception LOException データベースエラーが発生した場合
	 */
	synchronized public void update( Hashtable htData )
		throws LOException, XMOException
	{
		// データがnullのとき
		if( htData == null ) {
			// パラメータエラーをスローする
			throw new LOException( getMessageData( PARAM_WAR ) );
		}

		// データアクセスクラスをインスタンス化します
		DataAccess objDataAccess = new DataAccess(TABLE_NAME);
		try {

			// トランザクションを開始する
			objDataAccess.trans();

			// 更新処理を実行します
			updateAction( htData, objDataAccess );

			// コミット処理
			objDataAccess.commit();
		}
		catch( SQLException e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			// データベースエラーを設定
			throw new LOException( getMessageData( DB_ERR ) );
		}

		return;
	}

	/**
	 * 更新処理実行メソッドです。<BR>
	 * パラメータのチェックおよびトランザクションの管理は
	 * 上位メソッド内で行ってください。<BR>
	 * @param htbParam 更新情報
	 * @exception LOException DBエラーが発生した場合
	 * @exception SQLException DBエラーが発生した場合
	 */
	private void updateAction( Hashtable htbParam, DataAccess objDataAccess  )
		throws SQLException, LOException, XMOException
	{
		///////////////////////////////////////////////////////
		// 更新対象レコードの存在チェックを行います
		///////////////////////////////////////////////////////
		String strCondition = (String)htbParam.get( CONDITION_KEY );
		if( strCondition != null ) {
			if( !objDataAccess.isExit( strCondition ) ) {
				throw new LOException( getMessageData( NOEXIST_RECORD_WAR ) );
			}
		}
		// 更新するレコードを取得します
		Vector vecSelect = selectAction( htbParam, objDataAccess );
		// 登録処理用のデータをセットします
		Hashtable htbData = getData( htbParam );
		
		String strSQL = objDataAccess.getUpdateSQL(htbData);
		// 条件文の設定
		if( strCondition != null ) {
			strSQL += strCondition;
		}
		
		// 登録処理を実行
		objDataAccess.execute( strSQL );
	}
	
	/**
	 * Methodテーブルへ削除処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 * 	　　　　　　DELETE_LOID             削除対象のLOID
	 *          ---------------------------------------------
	 *             CONDITION_KEY           削除条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 削除情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception LOException データベースエラーが発生した場合
	 */
	synchronized public void delete( Hashtable htData )
		throws LOException
	{
		// データアクセスクラスをインスタンス化します
		DataAccess objDataAccess = new DataAccess(TABLE_NAME);
		try {
			// トランザクションを開始する
			objDataAccess.trans();
			// 削除処理実行メソッドを実行します
			deleteAction( htData, objDataAccess );
			// コミット処理
			objDataAccess.commit();
		}
		catch( SQLException e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			// データベースエラーを設定
			throw new LOException( getMessageData( DB_ERR ) );
		}
		return;
	}

	/**
	 * 削除処理実行メソッドです。<BR>
	 * パラメータのチェックおよびトランザクションの管理は
	 * 上位メソッド内で行ってください。<BR>
	 * @param htbParam 削除情報
	 * @exception LOException パラメータエラーが発生した場合
	 * @exception SQLException DBエラーが発生した場合
	 * MOD 2005/02/25 START
	 */
	synchronized public void deleteAction( Hashtable htbParam, DataAccess objDataAccess )
		throws LOException, SQLException
	{
		///////////////////////////////////////////////////////
		// 削除対象レコードの存在チェックを行います
		///////////////////////////////////////////////////////
		String strCondition = (String)htbParam.get( CONDITION_KEY );
		if( strCondition != null ) {
			if( !objDataAccess.isExit( strCondition ) ) {
				throw new LOException( getMessageData( NOEXIST_RECORD_WAR ) );
			}
		}

		// LOLogテーブルデータ削除用SQLの組み立て
		StringBuffer sbSQL = new StringBuffer();
		sbSQL.append( "DELETE FROM " );
		sbSQL.append( TABLE_NAME );
		if (strCondition != null) {
			sbSQL.append( " " );
			sbSQL.append( strCondition );
		}

		// SQLを実行する
		objDataAccess.execute( sbSQL.toString() );
	}
	
	/**
	 * 登録、更新処理時のデータを組み立てます
	 * @param htData
	 * @return Hashtable
	 */
	private Hashtable getData( Hashtable htbParam ) {
		Hashtable htbData = new Hashtable();
		putData( htbData, htbParam, LO_ID );
		putData( htbData, htbParam, METHODLOID );
		putData( htbData, htbParam, PARALLELFLAG );
		putData( htbData, htbParam, STARTDATE );
		putData( htbData, htbParam, ENDDATE );
		putData( htbData, htbParam, PERIODNUM );
		putData( htbData, htbParam, BEFORELEARNFLAG );
		putData( htbData, htbParam, AFTERLEARNFLAG );
		putData( htbData, htbParam, LOURL );		
		return htbData;
	}

	/**
	 * 安全にHashtableに追加するメソッドです
	 */
	private void putData( Hashtable htbData,  Hashtable htbParam, String strKey ) {
		String strValue = (String)htbParam.get( strKey );
		if( strValue != null ) {
			htbData.put( strKey, strValue );
		}
	}

	/**
	 * メッセージオブジェクトを作成します
	 * @param strMessageID メッセージID
	 * @return MessageData メッセージオブジェクト 例外発生時はnullを返します
	 */
	private MessageData getMessageData( String strMessageID) {
		MessageData objMessage = null;
		try {
			objMessage = Message.getInstance().getMessageData( strMessageID, MSG_FILE_PATH, MSG_FILE_NAME );
		}
		catch( Exception e ) {

		}
		return objMessage;
	}
	
//	ADD 2005/05/16 START Koji Umehara [toeic650]
	/**
	 * カウンセルスケジュールを取得します。<BR>
	 * 以下の情報をHashtableに格納して渡してください。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             CONDITION_KEY           検索条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 検索情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception XMOException データベースエラーが発生した場合
	 */
	public synchronized Vector getCounselSchedule( Hashtable htData )
		throws XMOException
	{
		// グループデータがnullのとき
		if( htData == null ) {
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}

		// 戻り値
		Vector vecReturn = new Vector();

		// データアクセスクラスをインスタンス化します
		DataAccess objDataAccess = new DataAccess(TABLE_NAME);
		try {
			// トランザクションを開始する
			objDataAccess.trans( htData );

			// 検索処理実行メソッド
			vecReturn = getCounselScheduleAction( htData, objDataAccess );

			// コミット
			objDataAccess.commit();
		}
		catch( XMOException xe ) {
			DebugLog.write( this.getClass(), xe, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			throw xe;
		}
		catch( SQLException e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			// データベースエラーを設定
			throw new XMOException( getMessageData( DB_ERR ) );
		}

		return vecReturn;
	}

	/**
	 * カウンセルスケジュール取得処理実行メソッドです。<BR>
	 * パラメータのチェックおよびトランザクションの管理は
	 * 上位メソッド内で行ってください。<BR>
	 * @param htbParam 検索情報
	 * @return Vector 検索結果
	 * @exception XMOException XMO独自エラー
	 * @exception SQLException DBエラーが発生した場合
	 */
	private Vector getCounselScheduleAction( Hashtable htbParam, DataAccess objDataAccess )
		throws XMOException, SQLException
	{

		Vector vecReturn = new Vector();

		try{
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv=new Environment();
			
			// SQLの組み立て
			StringBuffer sbSQL = new StringBuffer();
			String strUserID = ( htbParam.containsKey( USERID_KEY ) ) ? (String)htbParam.get( USERID_KEY ) : "";
			if( strUserID.equals( "" ) ) {
				// ユーザーIDがないエラー
				DebugLog.write( this.getClass(), "ユーザーIDがありません。", DebugLog.HIGHT );
				return vecReturn;
			}
			sbSQL.append( "SELECT * FROM GroupAndPeople INNER JOIN Assignments ON " );
			sbSQL.append( "(GroupAndPeople.memberShipID=Assignments.memberShipID " );
			sbSQL.append( "AND GroupAndPeople.childID='" + StringEscapeUtils.escapeSql(strUserID) + "' AND method_flag='1' AND learn_authority='1' " );
			sbSQL.append( ") INNER JOIN LoRelation ON (Assignments.materialID=LoRelation.materialID) " );
			sbSQL.append( "INNER JOIN LO ON LoRelation.childID=LO.LOID " );
			sbSQL.append( "INNER JOIN Method ON LO.RealLOID=Method.LOID AND KeyWord='" + TOEIC650CommonConst.LO_TYPE_KEY_OnlineCounseling + "' " );
			sbSQL.append( "ORDER BY Method.start_date " );
			
			ResultSet rs = objDataAccess.executeQuery(sbSQL.toString());
			while(rs.next()) {
				String strLoID = ChangeEncode.setChar( rs.getString( LO_ID ) );
				String strLoType = ChangeEncode.setChar( rs.getString( LO_TYPE ) );
				String strMethodLOID = ChangeEncode.setChar( rs.getString( METHODLOID ));
				Date dtDateStart = null;
				try {
					dtDateStart = rs.getDate( STARTDATE );
				} catch( Exception e ) {
					DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
				}
				Date dtDateEnd = null;
				try {
					dtDateEnd = rs.getDate( ENDDATE );
				} catch( Exception e ) {
					DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
				}
				Date dtStudyStart = null;
				try {
					dtStudyStart = rs.getTimestamp( OPENING_DATE );
				} catch( Exception e ) {
					DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
				}
				SimpleDateFormat objFormat = new SimpleDateFormat("yyyy年M月d日H時m分");
				Date dtStudyEnd = null;
				try {
					dtStudyEnd = rs.getTimestamp( MethodTable.CLOSING_DATE );
				} catch( Exception e ) {
					DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
				}
				Hashtable htData = new Hashtable();
				htData.put(LO_ID, strLoID);
				htData.put(LO_TYPE, strLoType);
				htData.put(METHODLOID, strMethodLOID);
				htData.put(STARTDATE, dtDateStart);
				htData.put(ENDDATE, dtDateEnd);
				htData.put(OPENING_DATE, dtStudyStart);
				htData.put(CLOSING_DATE, dtStudyEnd);

				vecReturn.add( htData );
			}
		}
		catch(Exception ex)
		{
			DebugLog.write( this.getClass(), ex.getMessage(), DebugLog.HIGHT );
		}
		return vecReturn;

	}
	
	/**
	 * 指定されたメソッド配下のメソッド一覧を取得します。<BR>
	 * アサインされてるかどうかは考慮しません。
	 * 以下の情報をHashtableに格納して渡してください。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             LO_ID                   親LOID
	 *             CONDITION_KEY           検索条件文
	 *             ORDER_BY                ソート条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 検索情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception XMOException データベースエラーが発生した場合
	 */
	public synchronized Vector getChildMethodList( Hashtable htData )
		throws XMOException
	{
		// グループデータがnullのとき
		if( htData == null ) {
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}

		// 戻り値
		Vector vecReturn = new Vector();

		// データアクセスクラスをインスタンス化します
		DataAccess objDataAccess = new DataAccess(TABLE_NAME);
		try {
			// トランザクションを開始する
			objDataAccess.trans( htData );

			// 検索処理実行メソッド
			vecReturn = getChildMethodListAction( htData, objDataAccess );

			// コミット
			objDataAccess.commit();
		}
		catch( XMOException xe ) {
			DebugLog.write( this.getClass(), xe, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			throw xe;
		}
		catch( SQLException e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// ロールバック
			try { objDataAccess.rollback(); } catch( Exception ex ) {}
			// データベースエラーを設定
			throw new XMOException( getMessageData( DB_ERR ) );
		}

		return vecReturn;
	}

	/**
	 * 指定したメソッド配下のメソッド一覧取得処理実行メソッドです。<BR>
	 * パラメータのチェックおよびトランザクションの管理は
	 * 上位メソッド内で行ってください。<BR>
	 * @param htbParam 検索情報
	 * @return Vector 検索結果
	 * @exception XMOException XMO独自エラー
	 * @exception SQLException DBエラーが発生した場合
	 */
	private Vector getChildMethodListAction( Hashtable htbParam, DataAccess objDataAccess )
		throws XMOException, SQLException
	{
		Vector vecReturn = new Vector();

		try{
			
			// 親LOIDの取得
			String strLOID = ( htbParam.containsKey( LO_ID ) ) ? (String)htbParam.get( LO_ID ) : "";
			if( strLOID.equals( "" ) ) {
				// LOIDがないエラー
				return vecReturn;
			}
			// SQLの組み立て
			StringBuffer sbSQL = new StringBuffer();
			sbSQL.append( "SELECT * FROM LORelation " );
			sbSQL.append( "INNER JOIN LO ON LoRelation.parentID='" + StringEscapeUtils.escapeSql(strLOID) + "' AND LoRelation.childID=LO.LOID " );
			sbSQL.append( "INNER JOIN Method ON LO.RealLOID=Method.LOID " );
			
			// 条件文の取得
			String strCondition = (String)htbParam.get( CONDITION_KEY );
			if( strCondition != null ) {
				sbSQL.append( strCondition );
			}
			String strOrderBy = (String)htbParam.get( ORDER_BY );
			if( strOrderBy != null ) {
				sbSQL.append( strOrderBy );
			} else {
				//XMS.iniファイルロードクラスのインスタンス
				Environment objEnv=new Environment();
				//SQLServerの場合
				if(objEnv.getDBType().equals( Environment.DB_SQLSERVER )){
					sbSQL.append(" ORDER BY CONVERT(INT,SUBSTRING(LO.LOID, 3, { fn LENGTH(LO.LOID) })) ");
				//Oracleの場合
				}else if(objEnv.getDBType().equals( Environment.DB_ORACLE )){
					sbSQL.append(" ORDER BY TO_NUMBER(SUBSTR(LO.LOID, 3, LENGTH(LO.LOID))) ");
				//PostgreSQLの場合
				}else if(objEnv.getDBType().equals( Environment.DB_POSTGRE )){
					sbSQL.append(" ORDER BY TO_NUMBER(SUBSTR(LO.LOID, 3, LENGTH(LO.LOID)),'9999999999') ");
				}
				objEnv = null;
			}

			// クエリ実行
			ResultSet rs = objDataAccess.executeQuery(sbSQL.toString());
			vecReturn = makeMethodDataFromResultSet(rs);
		}
		catch(Exception ex)
		{
			DebugLog.write( this.getClass(), ex.getMessage(), DebugLog.HIGHT );
		}
		return vecReturn;
	}
	
	/**
	 * リザルトセットからメソッドデータリストを生成してベクターで返すメソッドです。<BR>
	 * @param ResultSet rs リザルトセット
	 * @return Vector メソッドリスト
	 * @throws Exception
	 */
	private Vector makeMethodDataFromResultSet( ResultSet rs ) 
		throws Exception
	{
		Vector vecReturn = new Vector();
		Environment env = new Environment();
		
		while(rs.next()) {
			String strLoID = ChangeEncode.setChar( env, rs.getString( LO_ID ));
			String strLoType = ChangeEncode.setChar( env, rs.getString( LO_TYPE ));
			String strLoTytle = ChangeEncode.setChar( env, rs.getString( LO_TYTLE ) );
			String strLoExplanation = ChangeEncode.setChar( env, rs.getString( LO_EXPLANATION ) );
			String strLoVersion = ChangeEncode.setChar( env, rs.getString( LO_VERSION ) );
			String strRealLOID = ChangeEncode.setChar( env, rs.getString( REAL_LOID ));
			String strConclusion = ChangeEncode.setChar( env, rs.getString( CONCLUSION ) );
			String strMentorEmailAddress = ChangeEncode.setChar( env, rs.getString( MENTOR_EMAIL_ADDRESS ) );
			String strDeleteFlag = ChangeEncode.setChar( env, rs.getString( DELETE_FLAG ));
			String strForeignID = ChangeEncode.setChar( env, rs.getString( FOREIGN_ID ) );
			String strKeyWord = ChangeEncode.setChar( env, rs.getString( KEYWORD ) );
			String strPrere = ChangeEncode.setChar( env, rs.getString( PRERE ) );
			String strMethodLOID = ChangeEncode.setChar( env, rs.getString( METHODLOID ));
			String strLOURL = ChangeEncode.setChar( env, rs.getString( LOURL ));
			boolean blnParallelFlag = (rs.getString( PARALLELFLAG ) != null && rs.getString( PARALLELFLAG ).equals("1") );
			Date dtDateStart;
			try {
				dtDateStart = rs.getDate( STARTDATE );
			} catch( Exception e ) {
				DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
				dtDateStart = null;
			}
			Date dtDateEnd;
			try {
				dtDateEnd = rs.getDate( ENDDATE );
			} catch( Exception e ) {
				DebugLog.write( this.getClass(), e.getMessage(), DebugLog.HIGHT );
				dtDateEnd = null;
			}
			int intPreiodNum;
			try {
				intPreiodNum = Integer.parseInt( rs.getString( PERIODNUM ) );
			} catch( NumberFormatException e ) {
				intPreiodNum = 0;
			}
			boolean blnBeforeLearnFlag = (rs.getString( BEFORELEARNFLAG ) != null && rs.getString( BEFORELEARNFLAG ).equals("1") );
			boolean blnAfterLearnFlag = (rs.getString( AFTERLEARNFLAG ) != null && rs.getString( AFTERLEARNFLAG ).equals("1") );
			MethodData objData = new MethodData();
			objData.setLoID( strLoID );
			objData.setLoType( strLoType );
			objData.setLoTytle( strLoTytle );
			objData.setLoexplanation( strLoExplanation );
			objData.setLoVersion( strLoVersion );
			objData.setRealLOID( strRealLOID );
			objData.setConclusion( strConclusion );
			objData.setDeleteFlag( strDeleteFlag );
			objData.setForeignID( strForeignID );
			objData.setKeyWord( strKeyWord );
			objData.setPrere( strPrere );
			objData.setMentorEmail( strMentorEmailAddress );
			objData.setMethodLOID( strMethodLOID );
			objData.setParallelFlag( blnParallelFlag );
			objData.setDateStart( dtDateStart );
			objData.setDateEnd( dtDateEnd );
			objData.setPeriodNum( intPreiodNum );
			objData.setBeforeLearnFlag( blnBeforeLearnFlag );
			objData.setAfterLearnFlag( blnAfterLearnFlag );
			objData.setLOUrl( strLOURL );
			vecReturn.add( objData );
		}

		return vecReturn;
	}
	
//	ADD 2005/05/16 END Koji Umehara [toeic650]

}
