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

//
//	LoRelation 管理XMO データアクセスクラス
//			変更履歴
//				2004.01.08	新規作成	二條智文
//
package jp.co.ntt.lms.xmo.LoRelation;

import java.util.*;
import java.sql.*;

import org.apache.commons.lang.StringEscapeUtils;

import jp.co.ntt.lms.xmo.LoRelation.*;
import jp.co.ntt.lms.xmo.*;
import jp.co.ntt.lms.xmo.util.ChangeEncode;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xmo.Assignments.AssignmentsClient;
import jp.co.ntt.lms.xmo.Lo.LoClient;
import jp.co.ntt.lms.xmo.Message.Message;
import jp.co.ntt.lms.Common.status.*;
import jp.co.ntt.lms.Common.status.prerequisite.*;

/**
 * LoRelation 管理XMO データアクセスクラスです。<BR>
 * このクラスはLoRelationテーブルへの登録、修正、削除、検索処理を実行します。<BR>
 * DataAccessクラスを使用し、登録、修正、削除、検索処理単位で
 * トランザクション管理を行います。
 * @author T.Nijou
 * @version 0.0.0.1 2004/01/08
 */
public class LoRelationDataAccess
	implements LoRelationMessage, LoRelationTable
{

	/**
	 * コンストラクタです。<BR>
	 */
	public LoRelationDataAccess() {
	}

	/**
	 * LoRelationテーブルへ登録処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。<BR>
	 * なおテーブルの主キー以外を省略した場合は省略したフィールドには
	 * Null値が格納されます。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             PARENT_ID               親ID
	 *             CHILD_ID                子ID
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 登録情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception XMOException データベースエラーが発生した場合
	 */
	public synchronized String insert( Hashtable htData )
		throws XMOException
	{
		// LORelationデータがnullのとき
		if( htData == null ) {
			// パラメータエラーをスローする
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}

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

			// 登録処理実行メソッドを実行します
			insertAction( 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 "";
	}

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

		// 登録処理用のデータをセットします
		Hashtable htbData = setData( htbParam );
		// 親IDの取得
		String strParentID = (String)htbParam.get(PARENT_ID);
		// 子IDの取得
		String strChildID = (String)htbParam.get(CHILD_ID);
		// ソート番号の取得
		String strSortNo = (String)htbParam.get(SORT_NO);
		// パラメータにソート番号が設定されていない場合は、ソート番号を採番する。
		if(strSortNo==null || strSortNo.equals("")){
			// ソート番号の最大値を取得します
			int intMaxSortNo = getMaxSortNo( strParentID, objDataAccess );
			// ソート番号を+1して、登録用Hashtableにsort_noをキーにして格納します。
			strSortNo = Integer.toString( ++intMaxSortNo );
		}
		htbData.put( SORT_NO, strSortNo );

		htbData.put( MATERIAL_ID, strParentID + strChildID );

		//////////////////////////////////////////////////////
		// 教材IDの存在チェックを行います
		//////////////////////////////////////////////////////
		if( objDataAccess.isExit( htbData, MATERIAL_ID ) ) {
			throw new XMOException( getMessageData( EXIT_MATERIALID_WAR ) );
		}


		String strSQL = objDataAccess.getInsertSQL(htbData);

		// 登録処理実行
		objDataAccess.execute( strSQL );

	}

	/**
	 * LoRelatioinテーブルへ更新処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。<BR>
	 * 省略したフィールドは更新されません。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             MATERIAL_ID             マテリアルID
	 *             PARENT_ID               親ID
	 *             CHILD_ID                子ID
	 *          ---------------------------------------------
	 *             CONDITION_KEY           更新条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 更新情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception XMOException データベースエラーが発生した場合
	 */
	public synchronized String update( Hashtable htData )
		throws XMOException
	{
		// LoRelatioinデータがnullのとき
		if( htData == null ) {
			// パラメータエラーをスローする
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}

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

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

			// 更新処理実行メソッドを実行します
			updateAction( 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 "";
	}

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

		// 更新するレコードを取得します
		Vector vecSelect = selectAction( htbParam, objDataAccess );

		//////////////////////////////////////////////////////
		// 存在チェックを行います
		//////////////////////////////////////////////////////
		// 親IDの取得
		String strParentID = (String)htbParam.get(PARENT_ID);
		// 子IDの取得
		String strChildID = (String)htbParam.get(CHILD_ID);
		// 更新後マテリアルID
		String strUpdateMaterialID = strParentID + strChildID;
		// 更新前マテリアルID
		String strBeforeMaterialID = "";
		// 更新前親ID
		String strBeforeParentID = "";

		// 親ID、子IDどちらかが更新対象の場合のみ存在チェックを行う
		if( strParentID != null && strChildID != null ) {
			int intCount = vecSelect.size();
			for( int i = 0; i < intCount; i++ ) {
				LoRelationData objData = (LoRelationData)vecSelect.get(i);
				strBeforeMaterialID = objData.getMaterialID();
				// 更新前親IDの取得
				strBeforeParentID = objData.getParentID();
				if( !strUpdateMaterialID.equals( strBeforeMaterialID ) ) {
					if( objDataAccess.isExit( htbParam, MATERIAL_ID ) ) {
						throw new XMOException( getMessageData( EXIT_MATERIALID_WAR ) );
					}
				}
			}
		}

		// 更新処理用のデータをセットします
		Hashtable htbData = setData( htbParam );

		String strSQL = objDataAccess.getUpdateSQL(htbData);

		// 条件文の取得
		String strCondition = (String)htbParam.get( CONDITION_KEY );
		if( strCondition != null ) {
			strSQL += strCondition;
		}

		// 更新処理を実行
		objDataAccess.execute( strSQL );

		String strDont = (String)htbParam.get( UPDATE_ASSIGNMENTS );
		if( strDont == null ) {
			try {
				// LO割当テーブルを更新します
				AssignmentsClient objAss = new AssignmentsClient();
				objAss.setMaterialID( strUpdateMaterialID );
				objAss.setWhereMaterialID( strBeforeMaterialID );

				// LO割当テーブル更新処理
				if( !objAss.update() ) {
					// DBエラーを投げる
					throw new XMOException( objAss.getMessageData() );
				}
			}
			catch( Exception e ) {
				DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
				// システムエラーを投げる
				throw new XMOException( getMessageData( SYSTEM_ERR ) );
			}
		}

		// コンテナ変換時にはステータス伝播は行わない。
		if((String)htbParam.get( CHANGE_PARENTID ) == null){
			// 更新前の親IDでステータス伝搬処理を行います
			propagate( strBeforeParentID, objDataAccess );
			// 更新後の親IDでステータス伝搬処理を行います
			propagate( strParentID, objDataAccess );
		}

	}

	/**
	 * LoRelationテーブルへ削除処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             CONDITION_KEY           削除条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 削除情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception XMOException データベースエラーが発生した場合
	 */
	public synchronized String delete( Hashtable htData )
		throws XMOException
	{
		// データアクセスクラスをインスタンス化します
		DataAccess objDataAccess = new DataAccess(TABLE_NAME);
		try {

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

			// 削除処理実行メソッドを実行します
			deleteAction( 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 "";
	}

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

		// SelectIDの取得
		String strSelectID = (String)htbParam.get( DELETE_SELECTID );
		if( strSelectID == null ) {
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}
		// ParentIDの取得
		String strParentID = (String)htbParam.get( DELETE_PARENTID );
		if( strParentID == null ) {
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}

		// materialIDを設定し、Assignments XMO の削除を実行する
		deleteAssignments( strSelectID, strParentID, objDataAccess );


		// LoRelationテーブルからレコードを削除する
		StringBuffer sbSQL = new StringBuffer( "DELETE FROM " );
		sbSQL.append( TABLE_NAME );
		sbSQL.append( " WHERE " );
		sbSQL.append( CHILD_ID );
		sbSQL.append( " = '" );
		sbSQL.append( StringEscapeUtils.escapeSql(strSelectID) );
		sbSQL.append( "' AND " );
		sbSQL.append( PARENT_ID );
		sbSQL.append( " = '" );
		sbSQL.append( StringEscapeUtils.escapeSql(strParentID) );
		sbSQL.append( "'");
		// SQLを実行する
		objDataAccess.execute( sbSQL.toString() );


		/// LO削除以外から呼ばれた場合に伝搬処理を行う
		if( htbParam.get( CALL_FROM_DELETE ) == null ) {
			// 親LOの得点の再集計を行います
			// 削除後の親IDでステータス伝搬処理を行います
			propagate( strParentID, objDataAccess );
		}


	}

	/**
	 * LoRelationテーブルを検索し、取得したレコードのmaterialIDを
	 * 設定して、Assignments XMO の削除を実行します
	 *
	 * @param strSelectID
	 * @paran strParentID
	 * @param objDataAccess データアクセスオブジェクト
	 * @exception XMOException XMO独自エラー
	 * @exception SQLException DBエラーが発生した場合
	 */
	private void deleteAssignments( String strSelectID, String strParentID,
		DataAccess objDataAccess ) throws XMOException, SQLException
	{
		try {
			// MaterialIDの作成
			String strMaterialID = strParentID + strSelectID;
			// Assignmentsクライアントをインスタンス化します。
			AssignmentsClient objAssignments = new AssignmentsClient();
			// materialIDを設定し、Assignments XMO の削除を実行する
			objAssignments.setWhereMaterialID( strMaterialID );
			objAssignments.setConnectionIndex(
				objDataAccess.getConnectionIndex() );
			if( !objAssignments.delete() ) {
				throw new XMOException( objAssignments.getMessageData() );
			}
		} catch (Exception e) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// データベースエラーを設定
			throw new XMOException( getMessageData( DB_ERR ) );
		}
	}



	/**
	 * SelectIDが所属するグループを判定し、
	 * LoRelationテーブルの更新または削除を行います。
	 *
	 * @param strSelectID
	 * @param strParentID
	 * @param objDataAccess データアクセスオブジェクト
	 * @exception XMOException XMO独自エラー
	 * @exception SQLException DBエラーが発生した場合
	 */
	private void deleteEqSelectID( String strSelectID, String strParentID,
		DataAccess objDataAccess ) throws XMOException, SQLException
	{

	}

	/**
	 * LoRelationテーブルへ検索処理を行います。<BR>
	 * 以下の情報をHashtableに格納して渡してください。
	 * <PRE>
	 *             key                     説明
	 *          ---------------------------------------------
	 *             CONDITION_KEY           検索条件文
	 *          ---------------------------------------------
	 * </PRE>
	 * @param htData 検索情報
	 * @return String 結果(正しく終了した場合のみ)
	 * @exception XMOException データベースエラーが発生した場合
	 */
	public synchronized Vector select( Hashtable htData )
		throws XMOException
	{
		// LoRelationデータが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
	{

		// SQLの組み立て
		StringBuffer sbSQL = new StringBuffer();
		sbSQL.append( "SELECT * FROM " + TABLE_NAME );
		// 条件文の取得
		String strCondition = (String)htbParam.get( "condition_key" );
		if( strCondition != null ) {
			sbSQL.append( strCondition );
			// ORDER BY句がない場合、LOIDのORDER BY句を追加する
			if(strCondition.indexOf("ORDER BY") == -1)
			{
				sbSQL.append(" ORDER BY " + SORT_NO );
			}
		}
		else
		{
				sbSQL.append(" ORDER BY " + SORT_NO );
		}

		ResultSet rs = objDataAccess.executeQuery(sbSQL.toString());

		Vector vecReturn = new Vector();
		while(rs.next()) {
			String strMaterialID = ChangeEncode.setChar( rs.getString( MATERIAL_ID ) );
			String strParentID = ChangeEncode.setChar( rs.getString( PARENT_ID ) );
			String strChildID = ChangeEncode.setChar( rs.getString( CHILD_ID ) );
			LoRelationData objData = new LoRelationData();
			objData.setMaterialID( strMaterialID );
			objData.setParentID( strParentID );
			objData.setChildID( strChildID );
			vecReturn.add( objData );
		}

		return vecReturn;

	}

	/**
	 * 親IDを指定して、sort_noの最大値を取得し、
	 * int型で返します。
	 * @param strParentID 親ID
	 * @param objDataAccess データアクセス
	 * @exception SQLException DBエラーが発生した場合
	 */
	public int getMaxSortNo(String strParentID, DataAccess objDataAccess)
		throws SQLException
	{
		// SQLの組み立て
		StringBuffer sbSQL = new StringBuffer();
		sbSQL.append( "SELECT MAX(sort_no) as sort_no FROM " + TABLE_NAME + " WHERE " + PARENT_ID + "='" + StringEscapeUtils.escapeSql(strParentID) + "'" );

		// SQLの実行を行います
		ResultSet rs = objDataAccess.executeQuery(sbSQL.toString());

		int intSortNo = 0;
		if( rs.next() ) {
			intSortNo = rs.getInt( "sort_no" );
		}

		return intSortNo;
	}

	/**
	 * 登録、更新処理時のデータを組み立てます
	 * @param htData
	 * @return Hashtable
	 */
	private Hashtable setData( Hashtable htbParam ) {
		Hashtable htbData = new Hashtable();
		putData( htbData, htbParam, MATERIAL_ID );
		putData( htbData, htbParam, PARENT_ID );
		putData( htbData, htbParam, CHILD_ID );
		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_FIEL_PATH, MSG_FILE_NAME );
		}
		catch( Exception e ) {

		}
		return objMessage;
	}

	/**
	 * ステータス伝搬処理
	 * 移動、削除時にステータス伝搬処理を走らせます。
	 * @param strLoID LOID
	 */
	private void propagate( String strLoID, DataAccess objDataAccess )
		throws XMOException, SQLException
	{
		StatusPropagation objPropagation = new StatusPropagation( strLoID );
		PropagateControl.getInstance().addPropagate(objPropagation);
	}

	/**
	 * 親子IDを指定して、sort_noを取得し、
	 * int型で返します。
	 * @param strMaterialID 親子ID
	 * @param objDataAccess データアクセス
	 * @exception SQLException DBエラーが発生した場合
	 */
	public int getMaterialIDSortNo(String strMaterialID, DataAccess objDataAccess)
		throws SQLException
	{
		// SQLの組み立て
		StringBuffer sbSQL = new StringBuffer();
		sbSQL.append( "SELECT sort_no FROM " + TABLE_NAME + " WHERE " + MATERIAL_ID + "='" + StringEscapeUtils.escapeSql(strMaterialID) + "'" );
		// SQLの実行を行います
		ResultSet rs = objDataAccess.executeQuery(new String(sbSQL));
		int intSortNo = 0;
		if( rs.next() ) {
			intSortNo = rs.getInt( "sort_no" );
		}
		return intSortNo;
	}

	/**
	 * 上への時：移動先のsort_no以上のsort_noをメソッド引数の移動元IDリスト配列数プラスする。
	 * 下への時：移動先のsort_noより大きいsort_noをメソッド引数の移動元IDリスト配列数プラスする。
	 * @param intSortNo 移動先のsort_no
	 * @param intSendListLength 移動元ID配列数
	 * @param strParentID 移動先の親ID
	 * @param intType 処理区分(上へ：1、中へ：2、下へ：3)
	 * @param objDataAccess データアクセス
	 * @exception SQLException DBエラーが発生した場合
	 */
	public void updateSortNo(int intSortNo,
										int intSendListLength,
										String strParentID,
										int intType, DataAccess objDataAccess)
		throws SQLException
	{

				// SQLの組み立て
		StringBuffer sbSQL = new StringBuffer();
		sbSQL.append( "UPDATE " );
		sbSQL.append( TABLE_NAME );
		sbSQL.append( " SET " );
		sbSQL.append( SORT_NO );
		sbSQL.append( " = " );
		sbSQL.append( SORT_NO );
		sbSQL.append( " + '" );
		sbSQL.append( intSendListLength );
		sbSQL.append( "' ");
		sbSQL.append( " WHERE " );
		sbSQL.append( PARENT_ID );
		sbSQL.append( " = '" );
		sbSQL.append( StringEscapeUtils.escapeSql(strParentID) );
		sbSQL.append( "' ");
		sbSQL.append( " AND " );
		sbSQL.append( SORT_NO );
		//上への時
		if (intType == 1){
			sbSQL.append( " >= '" );
		}
		//下への時
		if (intType == 3){
			sbSQL.append( " > '" );
		}
		sbSQL.append( intSortNo );
		sbSQL.append( "' ");

		// SQLの実行を行います
		objDataAccess.execute( new String(sbSQL) );

	}

	/**
	 * LoRelationIDをキーにLORelationテーブルのLoRelationID、parentID、sort_noを更新する。
	 * @param objSendData 移動元：LoRelationID、parentID、childID
	 * @param strParentID 親ID(上へ又は下への時：移動先の親ID。下への時：移動先の子ID。)
	 * @param intSortNo 上へ又は下への時：移動先のsort_no
	 *                          中への時：移動先の子の配下のsort_noの最大値
	 * @param objDataAccess データアクセス
	 * @exception SQLException DBエラーが発生した場合
	 */
	public void updateLoRelation(LoRelationData objSendData,
							String strParentID,
							int intSortNo,
							DataAccess objDataAccess)
		throws SQLException
	{
				// SQLの組み立て
		StringBuffer sbSQL = new StringBuffer();

		sbSQL.append( "UPDATE " );
		sbSQL.append( TABLE_NAME );
		sbSQL.append( " SET " );
		sbSQL.append( MATERIAL_ID );
		sbSQL.append( " = '" );
		sbSQL.append( StringEscapeUtils.escapeSql(strParentID + objSendData.getChildID()) );
		sbSQL.append( "' ,");
		sbSQL.append( PARENT_ID );
		sbSQL.append( " = '" );
		sbSQL.append( StringEscapeUtils.escapeSql(strParentID) );
		sbSQL.append( "' ,");
		sbSQL.append( SORT_NO );
		sbSQL.append( " = '" );
		sbSQL.append( intSortNo );
		sbSQL.append( "' ");
		sbSQL.append( " WHERE " );
		sbSQL.append( MATERIAL_ID );
		sbSQL.append( " = '" );
		sbSQL.append( StringEscapeUtils.escapeSql(objSendData.getMaterialID()) );
		sbSQL.append( "' ");

		// SQLの実行を行います
		objDataAccess.execute( new String(sbSQL) );

	}

	/**
	 * 複製先に複製元のMemberShipID、parentID、childID、sort_noを追加する。
	 * @param objSendData 移動元：LoRelationID、parentID、childID
	 * @param intSortNo 上へ又は下への時：移動先のsort_no
	 *                          中への時：移動先の子の配下のsort_noの最大値
	 * @param objDataAccess データアクセス
	 * @exception SQLException DBエラーが発生した場合
	 */
	public void insertLoRelation(LoRelationData objSendData,
							String strParentID,
							int intSortNo,
							DataAccess objDataAccess)
		throws SQLException
	{
				// SQLの組み立て
		StringBuffer sbSQL = new StringBuffer();

		sbSQL.append( "INSERT " );
		sbSQL.append( "INTO " );
		sbSQL.append( TABLE_NAME );
		sbSQL.append( "( " );
		sbSQL.append( MATERIAL_ID );
		sbSQL.append( "," );
		sbSQL.append( SORT_NO );
		sbSQL.append( "," );
		sbSQL.append( PARENT_ID );
		sbSQL.append( "," );
		sbSQL.append( CHILD_ID );
		sbSQL.append( " )" );
		sbSQL.append( "VALUES" );
		sbSQL.append( "( '" );
		sbSQL.append( StringEscapeUtils.escapeSql(strParentID + objSendData.getChildID()) );
		sbSQL.append( "' , '");
		sbSQL.append( intSortNo );
		sbSQL.append( "' , '");
		sbSQL.append( StringEscapeUtils.escapeSql(strParentID) );
		sbSQL.append( "' , '");
		sbSQL.append( StringEscapeUtils.escapeSql(objSendData.getChildID()) );
		sbSQL.append( "' ");
		sbSQL.append( " )" );
		// SQLの実行を行います
		objDataAccess.execute( new String(sbSQL) );
	}

	/**
	 * MaterialIDを指定して、レコードの件数を取得します。
	 * 検索でテーブル排他を行います。
	 * @param strMaterialID MaterialID
	 * @param objDataAccess objDataAccess
	 * @return int レコード存在確認(レコード存在する場合"１"、ない場合"0")
	 * @exception SQLException DB例外
	 */
	public int getCountMaterialID( String strMaterialID, DataAccess objDataAccess )
		throws SQLException
	{
		int intCount = 0;

		try{
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv=new Environment();

			// SQLの組み立て
			StringBuffer sbSQL = new StringBuffer();
			sbSQL.append( "SELECT * " );
			sbSQL.append( " FROM " );
			sbSQL.append( TABLE_NAME );

			//SQLServerの場合
			if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
				sbSQL.append( " WITH(TABLOCKX) WHERE ");
			//Oracleの場合 OR PostgreSQLの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sbSQL.append( " WHERE ");
			}
			sbSQL.append( MATERIAL_ID );
			sbSQL.append( "='" );
			sbSQL.append( StringEscapeUtils.escapeSql(strMaterialID) );
			sbSQL.append( "'" );
			//Oracleの場合 OR PostgreSQLの場合
			if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sbSQL.append( " FOR UPDATE" );
			}

			DebugLog.write( this.getClass(), new String(sbSQL) , DebugLog.ROW );
			ResultSet rs = objDataAccess.executeQuery( new String(sbSQL) );

			while(rs.next()) {
				//レコードが存在する場合
				intCount = 1;
			}
		}
		catch(Exception ex)
		{

		}
		return intCount;
	}

	/**
	 * ChildIDを指定して、レコードの件数を取得します。
	 * 検索でテーブル排他を行います。
	 * @param strChildID 子ID
	 * @param objDataAccess objDataAccess
	 * @return int レコード件数
	 * @exception SQLException DB例外
	 */
	public int getCountChildID( String strChildID, DataAccess objDataAccess )
		throws SQLException
	{
			int intCount = 0;
		try{
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv=new Environment();

			// SQLの組み立て
			StringBuffer sbSQL = new StringBuffer();
			sbSQL.append( "SELECT COUNT(*) " );
			sbSQL.append( " FROM " );
			sbSQL.append( TABLE_NAME );

			//SQLServerの場合
			if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
				sbSQL.append( " WITH(TABLOCKX) WHERE ");
			//Oracleの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_ORACLE )){
				sbSQL.append( " WHERE ");
			}

			sbSQL.append( CHILD_ID );
			sbSQL.append( "='" );
			sbSQL.append( StringEscapeUtils.escapeSql(strChildID) );
			sbSQL.append( "'" );

			ResultSet rs = objDataAccess.executeQuery( new String(sbSQL) );
			if( rs.next() ) {
				intCount = rs.getInt(1);
			}
		}
		catch(Exception ex)
		{

		}
		return intCount;
	}


	/**
	 * 前提条件テーブルに登録処理を行います。<BR>
	 * @param strLOID 登録LOID
	 * @param strPrereID 登録内容PrereID
	 * @exception XMOException XMO独自エラー
	 * @exception SQLException DBエラーが発生した場合
	 */
	public void insertPrerequisiteAction( Hashtable htbParam, DataAccess objDataAccess )
		throws XMOException, SQLException
	{

		// LOIDの取得
		String strLOID              = (String)htbParam.get( LO_ID );
		if ( strLOID == null || strLOID.equals( "" ) )
		{
			throw new XMOException( getMessageData( PARAM_WAR ) );
		}
		try {

			// Prerequisiteクラスをインスタンス化
			String strPrerequisite      = (String)htbParam.get( PRERE );
			Prerequisite objPrere = new Prerequisite( strPrerequisite );
			objPrere.parse();
			String strPrere[] = (String[])objPrere.getLoIDList();
			for ( int i=0; i < strPrere.length; i++ )
			{
				Hashtable htbData = new Hashtable();
				htbData.put( LO_ID , strLOID );
				htbData.put( PRERE_ID , strPrere[i] );
				// 登録処理用のデータをセットします
				String strSQL = objDataAccess.getInsertSQL(htbData,TABLE_NAME2);
				// 登録処理を実行
				objDataAccess.execute( strSQL );
			}
		}
		catch( Exception e )
		{
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			throw new XMOException( getMessageData( SYSTEM_ERR ) );
		}
	}

}
