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

//
//	Assignments 管理XMO クライアントクラス
//			変更履歴
//				2004.01.08	新規作成	二條智文
//
package jp.co.ntt.lms.xmo.Assignments;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;

import jp.co.ntt.lms.xmo.MessageData;
import jp.co.ntt.lms.xmo.XMOBasicClient;
import jp.co.ntt.lms.xmo.XMOException;
import jp.co.ntt.lms.xmo.XMOPropertyDef;
import jp.co.ntt.lms.xmo.Base.XMSBaseClient;
import jp.co.ntt.lms.xmo.Lo.LoData;
import jp.co.ntt.lms.xmo.LoRelation.LoRelationClient;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xms.framework.XmsException;
import jp.co.ntt.lms.xms.framework.XmsSystemException;
import jp.co.ntt.lms.xms.framework.XmsWarningException;
import jp.co.ntt.lms.xmo.Environment;

/**
 * Assignments 管理XMO クライアントクラスです。<BR>
 * このクラスはAssignments XMO サーバクラスとの接続および、
 * 登録、更新、削除、検索処理に必要なパラメータの設定、検索後の
 * 検索結果の取得メソッドを提供します。<BR>
 * @author T.Nijou
 * @version 0.0.0.1 2004/01/08
 */
public class AssignmentsClient extends XMOBasicClient
	implements AssignmentsTable
{

	/** 接続先サーバクラス名です */
	public static final String CLASS_NAME = "jp.co.ntt.lms.xmo.Assignments.Assignments";

	/**
	 * AssignmentsXMO独自のメソッドです。<BR>
	 * 教材をアサインされたユーザリストの取得を行います。
	 */
	private static final String METHOD_GETUSERLIST = "getUserList";
	/**
	 * AssignmentsXMO独自のメソッドです。<BR>
	 * アサイン者一覧の検索を行います。
	 */
	private static final String METHOD_SEARCHASSINERLIST = "searchAssignerList";

	/**
	 * AssignmentsXMO独自のメソッドです。<BR>
	 * アサインされているレコードを取得します。
	 */
	private static final String METHOD_CHECKASSIGNUSABLE = "checkAssignUsable";
   /**
	* AssignmentsXMO独自のメソッドです。<BR>
	* アサインの有効・無効の判定を行う。
	*/
   private static final String METHOD_GETASSIGNINFO = "getAssignInfo";
   /**
	* AssignmentsXMO独自のメソッド。<BR>
	* 学習回数のカウントアップするメソッド名称。
	*/
   private static final String METHOD_COUNTUP_STUDY_COUNT = "countupStudyCount";

   /**
	* AssignmentsXMO独自のメソッド。<BR>
	* メール送信の１回あたりの送信件数を取得するメソッド名称。
	*/
   private static final String METHOD_GET_SEND_MAIL_COUNT = "getSendMailCount";
   
   /**
    * ＲＭＩ戻り値Ｍａｐキー：エラーメッセージ。
    */
   private static final String KEY_ERROR_MESSAGE = "errormessage";

   /**
    * ＲＭＩ戻り値Ｍａｐキー：送信件数。
    */
   private static final String KEY_SEND_MAIL_COUNT = "sendMailCount";


	/**
	 * ユーザリスト取得結果を設定します
	 */
	private Vector mobjUserListResult;

	/**
	 * アサイン者リスト取得結果を保持します
	 */
	private String[] mstrAssingerList = null;
	/**
	 * アサイン情報を保持します
	 */
	private Map assignHash;

	/**
	 * コンストラクタです。<BR>
	 * 親クラスのコンストラクタを呼び出し、接続先サーバクラス名を
	 * 設定します。
	 */
	public AssignmentsClient() throws Exception {
		super( CLASS_NAME );
	}

	/**
	 * パラメータに割当IDをセットします
	 */
	public void setAssignID( String strAssignID ) {
		putData( ASSIGN_ID, strAssignID );
	}

	/**
	 * 検索結果の現在のインデックスの割当IDを取得します
	 */
	public String getAssignID() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getAssignID();
	}

	/**
	 * パラメータに人々IDをセットします
	 */
	public void setMemberShipID( String strMemberShipID ) {
		putData( MEMBER_SHIP_ID, strMemberShipID );
	}

	/**
	 * 検索結果から現在のインデックスの人々IDを取得します
	 */
	public String getMemberShipID() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getMemberShipID();
	}

	/**
	 * パラメータにコンポーネントIDをセットします
	 */
	public void setMaterialID( String strMaterialID ) {
		putData( MATERIAL_ID, strMaterialID );
	}

	/**
	 * 検索結果から現在のインデックスのコンポーネントIDを取得します
	 */
	public String getMaterialID() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getMaterialID();
	}

	/**
	 * パラメータに開始日をセットします
	 */
	public void setStudyStartDate( String strStudyStartDate ) {
		putData( STUDY_START_DATE, strStudyStartDate );
	}

	/**
	 * 検索結果から現在のインデックスの開始日を取得します
	 */
	public String getStudyStartDate() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getStudyStartDate();
	}

	/**
	 * パラメータに終了日をセットします
	 */
	public void setEndDate( String strEndDate ) {
		putData( END_DATE, strEndDate );
	}

	/**
	 * 検索結果から現在のインデックスの終了日を取得します
	 */
	public String getEndDate() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getEndDate();
	}

	/**
	 * パラメータにアサイン者をセットします
	 */
	public void setAssigner( String strAssigner ) {
		putData( ASSIGNER, strAssigner );
	}

	/**
	 * 検索結果から現在のインデックスのアサイン者を取得します
	 */
	public String getAssigner() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getAssigner();
	}

	/**
	 * パラメータに学習権限をセットします
	 */
	public void setLearnAuthority( String strLearnAuthority ) {
		putData( LEARN_AUTHORITY, strLearnAuthority );
	}

	/**
	 * 検索結果から現在のインデックスの学習権限を取得します
	 */
	public String getLearnAuthority() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getLearnAuthority();
	}

	/**
	 * パラメータに管理権限をセットします
	 */
	public void setManagementAuthority( String strManagementAuthority ) {
		putData( MANAGEMENT_AUTHORITY, strManagementAuthority );
	}

	/**
	 * 検索結果から現在のインデックスの管理権限を取得します
	 */
	public String getManagementAuthority() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getManagementAuthority();
	}

	/**
	 * メール未送信情報を取得します
	 * @return ArrayList メール未送信情報<BR>
	 *                   メールを送信しなかったUserIDリストが返ります。<BR>
	 *                   メール送信がメール送信が行われなかった場合はnullが返ります。
	 */
	public ArrayList getNotSendMailList() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getNotSendMailList();
	}

	/**
	 * メール送信NG情報を取得します
	 * @return ArrayList メール送信NG情報<BR>
	 *                   メール送信に失敗したUserIDリストが返ります。<BR>
	 *                   メール送信をしなかった場合はnullが返ります。
	 */
	public ArrayList getNgMailList() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getNgMailList();
	}

	/**
	 * アサインされたユーザのリストを取得します。
	 * @return Vector アサインユーザリスト<BR>
	 *                グループにLOをアサインした場合、グループ配下のユーザで
	 *                LOをアサインされたユーザIDリストが返ります。
	 */
	public Vector getAssignUserList() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getAssignUserList();
	}

	/**
	 * メソッドフラグ情報を取得します。
	 * @return String メソッドフラグ情報
	 */
	public String getMethodFlag() {
		AssignmentsData objData = (AssignmentsData)getResult();
		return objData.getMethodFlag();
	}
	
	/**
	 * メソッドフラグ情報をセットします
	 * @param String メソッドフラグ情報
	 */
	public void setMethodFlag(String methodFlag) {
		putData( METHOD_FLAG, methodFlag);
	}
	
	/**
	 * パラメータに処理モードをセットします
	 */
	public void setMode( String strMode ) {
		putData( MODE_KEY, strMode );
	}

	/**
	 * AssignmentsIDを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 * @param strAssignID	AssignID
	 */
	public void setWhereAssignmentsID( String strAssignID ) {
		String strCondition = ASSIGN_ID + SEARCH_EQUALS + "'" + StringEscapeUtils.escapeSql(strAssignID) + "' ";
		setCondition( strCondition );
	}

	/**
	 * AssignmentsIDを検索条件に付与します
	 * @param strAssignID	AssignID
	 * @param strSearchCondition 検索条件
	 */
	public void setWhereAssignmentsID( String strAssignID, String strSearchCondition ) {
		String strCondition = ASSIGN_ID + strSearchCondition + "'" + StringEscapeUtils.escapeSql(strAssignID) + "' ";
		setCondition( strCondition );
	}

	/**
	 * AssignmentsIDでOrderbyをかけて検索します
	 */
	public void setOrderByAssignmentsID() throws XMOException {
		try{
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv = new Environment();
			//SQLServerの場合
			if(objEnv.getDBType().equals( Environment.DB_SQLSERVER )){
				setOrderBy( "CONVERT(INT," + ASSIGN_ID + ")");
			//Oracleの場合
			}else if(objEnv.getDBType().equals( Environment.DB_ORACLE )){
				setOrderBy( "TO_NUMBER(" + ASSIGN_ID + ")" );
			//PostgreSQLの場合
			}else if(objEnv.getDBType().equals( Environment.DB_POSTGRE )){
				setOrderBy( "TO_NUMBER((" + ASSIGN_ID + "),'9999999999')" );
			}
		}
		catch ( Exception e ) {
			throw new XMOException( e.getMessage() );
		}
	}

	/**
	 * MemberShipIDを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 * @param strMemberShipID	MemberShipID
	 */
	public void setWhereMemberShipID( String strMemberShipID ) {
		String strCondition = MEMBER_SHIP_ID + SEARCH_EQUALS + "'" + StringEscapeUtils.escapeSql(strMemberShipID) + "' ";
		setCondition( strCondition );
	}

	/**
	 * MaterialIDを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 * @param strMaterialID	MaterialID
	 */
	public void setWhereMaterialID( String strMaterialID ) {
		String strCondition = MATERIAL_ID + SEARCH_EQUALS + "'" + StringEscapeUtils.escapeSql(strMaterialID) + "' ";
		setCondition( strCondition );
	}

	/**
	 * 学習アサインを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 */
	public void setWhereLearnAuthority() {
		String strCondition = LEARN_AUTHORITY + SEARCH_EQUALS + "'1' ";
		setCondition( strCondition );
	}

	/**
	 * 管理アサインを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 */
	public void setWhereManagementAuthority() {
		String strCondition = MANAGEMENT_AUTHORITY + SEARCH_EQUALS + "'1' ";
		setCondition( strCondition );
	}

	//	ADD 2005/03/25 START Koji Umehara [メソッド管理追加]
	/**
	 * MethodFlagを検索条件に付与します
	 * @param blnMethodFlag true:メソッドを検索/false:メソッド以外を検索
	 */
	public void setWhereMethodFlag( boolean blnMethodFlag ) {
		String strCondition;
		if( blnMethodFlag ) {
			strCondition = METHOD_FLAG + SEARCH_EQUALS + "'1' ";
		} else {
			strCondition = METHOD_FLAG + " is null " + "or " + METHOD_FLAG + "<>" + "'1' ";
		}
		setCondition( strCondition );
	}
	//	ADD 2005/03/25 END Koji Umehara [メソッド管理追加]

	/**
	 * メール送信可不可を設定します
	 * @param String メール送信フラグ 0:送信しない 1:送信する
	 */
	public void setSendMailFlag(String strFlag)
	{
		putData(SEND_MAIL_FLAG, strFlag);
	}

	/**
	 * パラメータにLOIDをセットします
	 * @param String LOID
	 */
	public void setLOID(String strLOID)
	{
		putData(LO_ID, strLOID);
	}

	/**
	 * AssignmentsXMO独自のメソッドです。<BR>
	 * 教材をアサインされたユーザリストの取得を行います。
	 * @return boolean true: リスト取得成功 false: エラー
	 */
	public boolean getUserList(String strLOID) throws Exception {
		// LOIDを設定します
		setLOID( strLOID );

		mobjUserListResult = (Vector)super.execute( METHOD_GETUSERLIST, htParams );

		if( mobjUserListResult == null ) {
			return false;
		}

		return true;

	}

	/**
	 * ユーザリストを返します
	 * @return Vector ユーザリスト
	 */
	public Vector getUserListResult() {
		return mobjUserListResult;
	}


	/**
	 * あるユーザにあるLOをアサインしたアサイン者のユーザID
	 * を検索します。<BR>
	 * ユーザは兼務ユーザも含みます。また、LOは上位のアサインまで調べます。<BR>
	 * アサインタイプを指定して、学習アサイン、管理アサイン、両方の指定ができます。
	 * アサインタイプは以下のように指定してください。
	 * <PRE>
	 *     AssignmentsClient.NON_TYPE    :: アサインタイプ指定なし
	 *     AssignmentsClient.LEARN_TYPE  :: 学習アサインされているもの
	 *     AssignmentsClient.MANAGE_TYPE :: 管理アサインされているもの
	 * </PRE>
	 * @param strUserID ユーザID
	 * @param strLoID LOID
	 * @param intAssignType アサインタイプ
	 * @return boolean true: 検索成功 false: 検索失敗
	 * @exception Exception RMI通信エラー、内部エラー
	 */
	public boolean searchAssignerList( String strUserID, String strLoID, int intAssignType )
		throws Exception
	{
		// パラメータチェック
		if( strUserID == null || strLoID == null ) {
			// パラメータ不正
			throw new XMOException( "パラメータが不正です。" );
		}
		// アサインタイプの設定
		if( intAssignType != NON_TYPE &&
			intAssignType != LEARN_TYPE &&
			intAssignType != MANAGE_TYPE )
		{
			// パラメータ不正
			throw new XMOException( "パラメータが不正です。" );
		}

		// パラメータにユーザIDを設定する
		htParams.put( USER_ID, strUserID );

		// パラメータにLOIDを設定する
		htParams.put( LO_ID, strLoID );

		// パラメータにアサインタイプを設定する
		htParams.put( ASSIGN_TYPE, new Integer( intAssignType ) );

		// サーバのメソッドを呼び出します。
		vecResults = (Vector)super.execute( METHOD_SEARCHASSINERLIST, htParams );

		// メッセージデータを取得します
		mobjMessage = (MessageData)vecResults.get(0);

		// メッセージ種別がエラー、警告の場合はfalseを返します。
		if( isErr( mobjMessage ) || isWarning( mobjMessage ) ) {
			return false;
		}

		// 正常終了時はアサイン者リストを取り出し(Vectorの2番目から)内部変数に格納します。
		mstrAssingerList = (String[])vecResults.get(1);

		return true;
	}

	/**
	 * アサイン者検索結果を取得します。
	 * searchAssigner メソッドをコールしていない場合はnullが返ります。
	 * @return  String[] アサイン者のユーザIDリスト
	 */
	public String[] getAssignerList() {
		return mstrAssingerList;
	}

	/**
	 * 指定されたユーザに指定されたＬＯがアサインされているかのチェックを行う。<BR>
	 * ＬＯは上位のコンテナのアサインチェックも行う。
	 * 本メソッドは単なるチェック処理の為、static メソッドとして定義する。
	 * @param strUserID ユーザＩＤ
	 * @param strLoID ＬＯＩＤ（RealLOIDではない)
	 * @param intAssignType アサイン種別の指定
	 *     AssignmentsClient.NON_TYPE    :: アサインタイプ指定なし
	 *     AssignmentsClient.LEARN_TYPE  :: 学習アサインされているもの
	 *     AssignmentsClient.MANAGE_TYPE :: 管理アサインされているもの
	 * @return boolean true: アサイン有り false: アサインなし
	 * @exception Exception RMI通信エラー、内部エラー
	 */
	public static boolean checkAssignAuth( String strUserID, String strLoID, int intAssignType )
		throws Exception
	{
		// ユーザIDがスーパユーザの場合は無条件にOK
		if( strUserID.equals(XMOPropertyDef.ROOT_USER) ) {
			return true;
		}

		// 権限チェックフラグ
		boolean isAuth = false;

		// 権限対象LOのリストを取得します。
		// XMSBaseを使用して、ログインユーザが使用できるLOリストを取得します。
		XMSBaseClient objBase = new XMSBaseClient();
		if( !objBase.searchRootLoList( strUserID, intAssignType ) ) {
			throw new XMOException( objBase.getMessage() );
		}

		LoData[] objRootLo = objBase.getRootLoList();
		// 権限のあるLOIDリストを作成する。
		Vector vecAuthList = new Vector();
		for( int i = 0; i < objRootLo.length; i++ ) {
			vecAuthList.add( objRootLo[i].getLoID() );
		}

		// 指定LOIDのパスを取得します。
		// 参照LOIDのパスを取得する
		LoRelationClient objLoRelation = new LoRelationClient();
		if( !objLoRelation.searchPath(strLoID) ) {
			// パス検索がうまくいかなかった場合
			throw new XMOException( objLoRelation.getMessage() );
		}

		// パス毎に権限チェックを行う。
		while( objLoRelation.next() ) {
			String[] strPath = objLoRelation.getPath();
			for( int i = 0; i < strPath.length; i++ ) {

				if( vecAuthList.contains( strPath[i] ) ) {
					// 権限のあるLOIDリストにIDが含まれていたら権限フラグをtrueにする
					isAuth = true;
					break;
				}
			}

			if( isAuth ) {
				break;
			}
		}

		return isAuth;
	}
	

// アサイン有効/無効判定メソッドの追加
	/**
	 * ユーザＩＤとＬＯＩＤを指定して、ユーザに対するＬＯのアサインの有効/無効の
	 * 判定を行います。<BR>
	 * ユーザの親グループの指定があった場合は、そのグループのユーザのみが対象となります。<BR>
	 * 親グループの指定がない場合(nullの場合) はそのユーザの兼務も対象となります。<BR>
	 * 本処理は指定されたＬＯの直下のＬＯ郡のアサイン判定をまとめて行うことができます。<BR>
	 * 指定ＬＯ自身のアサイン判定を行う場合は、SELF を指定してください。<BR>
	 * ＬＯの直下のアサイン判定を行う場合は、UNDER を指定してください。<BR>
	 * アサインの有効・無効の判定は、注目しているＬＯ自身にアサインがあった場合は、
	 * そのアサイン情報を元に判定されます。<BR>
	 * もし注目しているＬＯ自身にアサインがない場合は、そのＬＯの上位でより近い階層のＬＯの
	 * アサインを元に判定されます。<BR>
	 * 自身にも上位にもアサインがない場合は、必ず無効と判定されます。<BR>
	 * 判定結果は、Mapオブジェクトで返却されます。<BR>
	 * LOID を元にMapから判定結果オブジェクトを取得します。
	 *    Mapの内容は以下のようになっています。
	 * <PRE>
	 *       key: LOID
	 *       value: AssignUsableList
	 * </PRE>
	 * @param strUserID ユーザID
	 * @param strGroupID グループID 指定された場合は、このグループに限定されたアサインチェックが走ります。<BR>
	 *                   nullを指定すると、ユーザに兼務が存在した場合はすべての兼務がアサインチェックの対象となります。
	 * @param strLoID LOID
	 * @param intType 処理タイプ以下の2パターンを指定する。
	 *                 SELF: 指定されたLOID自身のアサイン判定
	 *                 UNDER: 指定されたLOIDの直下のアサイン判定
	 * @return Map 以下の内容が格納される。
	 * <PRE>
	 *       key: LOID
	 *       value: AssignUsableList
	 * </PRE>
	 * @exception XMOException 実行時例外、DBエラーなど
	 * @exception Exception RMI通信エラーなど
	 */
	public Map checkAssignUsable( String strUserID, String strGroupID, String strLoID, int intType )
		throws XMOException, Exception
	{
		Map result = null;
		
		if( strUserID == null || strLoID == null ) {
			throw new XMOException( "パラメータが不正" );
		}
		
		if( intType != SELF &&
			intType != UNDER )
		{
			throw new XMOException( "処理タイプが不正" );
		}

		// パラメータにユーザIDを設定する
		htParams.put( "user_id", strUserID );
		
		// パラメータにグループIDを設定する(指定があった場合のみ)
		if( strGroupID != null ) {	
			htParams.put( "group_id", strGroupID );
		}

		// パラメータにLOIDを設定する
		htParams.put( "lo_id", strLoID );

		// パラメータにアサインタイプを設定する
		htParams.put( "process_type", new Integer( intType ) );

		// サーバのメソッドを呼び出します。
		vecResults = (Vector)super.execute( METHOD_CHECKASSIGNUSABLE, htParams );
		
		// 事後チェック
		if( vecResults == null ) {
			throw new XMOException( "処理結果がnull" );
		}
		
		// メッセージデータを取得します
		mobjMessage = (MessageData)vecResults.get(0);

		if( mobjMessage != null ) {
			// メッセージが格納されていた場合はエラーとする
			throw new XMOException( mobjMessage );
		}
		
		// 正常終了時はアサインチェック結果を取り出す。
		result = (Map)vecResults.get(1);
		
		// 事後チェック
		if( result == null ) {
			throw new XMOException( "処理結果がnull" );
		}
		
		return result;
	}

/**
 * アサイン情報取得メソッド。<BR>
 * 
 * 条件の中からアサインされているレコードのみを取得します。<BR>
 * ユーザID指定されている場合、strGroupIDにはそのユーザが所属しているグループID、<BR>
 * ユーザID指定されていない(null)場合、strGroupIDには基本画面で選択されたグループIDとなります。<BR>
 * 指定ＬＯ自身のアサインの検索を行う場合は、SELF を指定してください。<BR>
 * ＬＯの直下のアサインの検索を行う場合は、UNDER を指定してください。<BR>
 * 指定したグループ配下の検索を行う場合は、on を指定して下さい。<BR>
 * 指定したグループ直下の検索を行う場合は、off を指定して下さい。<BR> 
 * 検査結果は、Mapオブジェクトで保持されます。<BR>
 * 
 * @param strUserID		ユーザID
 * @param strGroupID		グループID or 所属グループID
 * @param strLoID			LOID
 * @param intType			0 or 1
 * @param subordinateFlg	配下フラグ
 * 
 * @exception XMOException 実行時例外、DBエラーなど
 * @exception Exception RMI通信エラーなど
 * 
 */
	public void getAssignInfo( String strUserID, String strGroupID, 
		String strLoID, int intType, String subordinateFlg )
		throws XMOException, Exception {

		if( strLoID == null ) {
			throw new XMOException( "パラメータが不正" );
		}
	
		// パラメータにユーザIDを設定する
		if (strUserID != null) {
			htParams.put( "user_id", strUserID );
		}
		
	
		// パラメータにグループIDを設定する(指定があった場合のみ)
		if( strGroupID != null ) {	
			htParams.put( "group_id", strGroupID );
		}

		if( intType != SELF &&
			intType != UNDER ) {
			throw new XMOException( "処理タイプが不正" );
		}

		// パラメータにLOIDを設定する
		htParams.put( "lo_id", strLoID );

		// パラメータにアサインタイプを設定する
		htParams.put( "process_type", Integer.toString( intType ) );

		// パラメータにアサインタイプを設定する
		htParams.put( "subordinateFlg", subordinateFlg );

		// サーバのメソッドを呼び出します。
		List lstResults = (List)super.execute( METHOD_GETASSIGNINFO, htParams );

		// 事後チェック
		if( lstResults == null ) {
			throw new XMOException( "処理結果がnull" );
		}
	
		// メッセージデータを取得します
		mobjMessage = (MessageData)lstResults.get(0);

		if( mobjMessage != null ) {
			// メッセージが格納されていた場合はエラーとする
			throw new XMOException( mobjMessage );
		}
	
		// 正常終了時はアサインチェック結果を取り出す。
		assignHash = (Map)lstResults.get(1);
	
		// 事後チェック
		if( assignHash == null ) {
			throw new XMOException( "処理結果がnull" );
		}

	}

	/**
	 * アサインが可能であるかチェックを行います。
	 * 
	 * @param userId ユーザId
	 * @param loId   loId
	 * @return アサイン可能であればtrue,不可能はfalse
	 */
	public boolean isAssign(String userId,String loId)throws XmsException{

		//引数userIdとloIdに一致したAssignUsableオブジェクトを取得する
		AssignUsable assign = getAssignUsable(userId,loId);

		//最終的にAssignUsableがみつからなかった
		if(assign == null){
			return false;
		}

		return assign.isUsableAssain();
	}

	/**
	 * 引数userIdとloIdに一致したAssignUsableオブジェクトを返却する.
	 * 
	 * @param userId ユーザId
	 * @param loId   loId
	 * @return 引数userIdとloIdに一致したAssignUsable
	 * 
	 */
	public AssignUsable getAssignUsable(String userId,String loId)throws XmsException{

		try{

			AssignUsable assign = null;

			String materialId = getMaterialID(loId);
			String compId = userId + materialId;

			//キーがあるかどうか調べる
			if(assignHash.containsKey(compId)){
				assign = (AssignUsable)assignHash.get(compId);
			
			//キーがなければ上位にをチェック	
			}else{
				//親LOＩＤを取得
				String parentLoId = getParentLoId(loId);

				// 最上位まで該当するキーがない(アサインがない)ので無効として返却する
				if (parentLoId.equals("/")) {
					return null;				
				}
				//再帰
				assign=getAssignUsable(userId,parentLoId);					
			}
			return assign;

		} catch (XmsException e) {
			throw e;

		} catch (Exception e) {
			throw new XmsSystemException(e);

		}		
		
	} 	

	/***
	 * 親LOIDの取得
	 * 
	 * @param ChildId loId
	 * @Exception XmsException
	 * @return 親LOID
	 * 
	 */
	public String getParentLoId(String childId)throws XmsException{
		String parentID = "";
		try {
			LoRelationClient client = new LoRelationClient();
			client.setChildID(childId);
			if (client.select()) {
				while (client.next()) {
					parentID = client.getParentID();

				}
			} else {

				//検索がうまくいかなかった
				if (client.isErr()) {
					//エラーの場合
					throw new XmsSystemException(client.getMessage());
				} else {
					//警告の場合
					throw new XmsWarningException(client.getMessage());
				}
			}

			client = null;
		} catch (XmsException e) {
			throw e;

		} catch (Exception e) {
			throw new XmsSystemException(e);

		}		
		return parentID;
	}


	/***
	 * 親ID子IDが連結された文字列を取得する.
	 * <pre>
	 * 親LO1
	 * 子LO2
	 * 
	 * 返却値はLO1LO2
	 * </pre>
	 * @param loId ChildId
	 * @Exception XmsException
	 * @return 親ID子IDが連結された文字列
	 * 
	 */
	public String getMaterialID(String loId)throws XmsException{
		String materialID = "";
		try {
			LoRelationClient client = new LoRelationClient();
			// 条件として子IDを設定します
			client.setChildID(loId);
			if (client.select()) {
				while (client.next()) {
					materialID = client.getmaterialID();

				}
			} else {

				//検索がうまくいかなかった
				if (client.isErr()) {
					//エラーの場合
					throw new XmsSystemException(client.getMessage());
				} else {
					//警告の場合
					throw new XmsWarningException(client.getMessage());
				}
			}

			client = null;
		} catch (XmsException e) {
			throw e;

		} catch (Exception e) {
			throw new XmsSystemException(e);

		}		
		return materialID;
	}


// 新規カラム用にget/setメソッドを追加
	/**
	 * 検索結果から学習終了日時を取得します。
	 * @return 学習終了日時。設定されていない場合はnull。
	 */
	public Date getClosingDate() {
		Date closingDate = null;
		AssignmentsData objData = null;
		
		objData = (AssignmentsData)getResult();
		closingDate = objData.getClosingDate();
		return closingDate;
	}

	/**
	 * 検索結果から学習開始日時を取得します。
	 * @return 学習開始日時。設定されていない場合はnull。
	 */
	public Date getOpeningDate() {
		Date openingDate = null;
		AssignmentsData objData = null;
		
		objData = (AssignmentsData)getResult();
		openingDate = objData.getOpeningDate();
		return openingDate;
	}

	/**
	 * 検索結果から学習回数を取得します。
	 * @return 学習回数。設定されていない場合はnull。
	 */
	public String getStudyCount() {
		String studyCount = null;
		AssignmentsData objData = null;
		
		objData = (AssignmentsData)getResult();
		studyCount = objData.getStudyCount();
		return studyCount;
	}

	/**
	 * 検索結果から学習制限回数を取得します。
	 * @return 学習制限回数。設定されていない場合はnull。
	 */
	public String getStudyLimitCount() {
		String studyLimitCount = null;
		AssignmentsData objData = null;
		
		objData = (AssignmentsData)getResult();
		studyLimitCount = objData.getStudyLimitCount();
		return studyLimitCount;
	}

	/**
	 * パラメータに学習終了日時を設定します。
	 * @param closeingDate 学習終了日時。
	 */
	public void setClosingDate(String closingDate) {
		putData(CLOSING_DATE, closingDate);
	}

	/**
	 * パラメータに学習開始日時を設定します。
	 * @param openingDate 学習開始日時。
	 */
	public void setOpeningDate(String openingDate) {
		putData(OPENING_DATE, openingDate);
	}

	/**
	 * パラメータに学習回数を設定します。
	 * @param studyCount 学習回数。
	 */
	public void setStudyCount(String studyCount) {
		putData(STUDY_COUNT, studyCount);
	}

	/**
	 * パラメータに学習制限回数を設定します。
	 * @param studyLimitCount 学習制限回数。
	 */
	public void setStudyLimitCount(String studyLimitCount) {
		putData(STUDY_LIMIT_COUNT, studyLimitCount);
	}


	/**
	 * 指定したメンバー、教材の組み合わせの学習回数を１つ増加する。<br>
	 * @param userID ユーザID。
	 * @param loID 教材ID。
	 * @param loType 教材種別。<br>
	 *         LoConstantクラスの定数を使用する。<br>
	 *         WBT教材、SmartForce教材、またはPerception教材以外はnullを指定にする。<br>
	 * @see jp.co.ntt.lms.lo.LoConstant#LO_TYPE_WBT
	 * @see jp.co.ntt.lms.lo.LoConstant#LO_TYPE_SMARTFORCE
	 * @see jp.co.ntt.lms.lo.LoConstant#LO_TYPE_PERCEPTION
	 */
// 教材の指定をLOIDから行い、合わせて教材種別を渡すように修正。
	public void countupStudyCount(String userID, String loID, String loType) throws XMOException {
		try {
// マテリアルIDだけではLOIDからもカウントアップできるように変更
			// 条件クリア
			clear();
			// ユーザIDの設定
			setMemberShipID(userID);
// 教材の指定をLOIDから行うように修正。
			// 教材の設定
			setLOID(loID);

// 教材種別を取得するように追加
			setLoType(loType);
			countupStudyCount();
		} catch (XMOException e) {
			throw e;
		} catch (Exception e) {
			DebugLog.write(this.getClass(), e, DebugLog.HIGHT );
			throw new XMOException(e.getMessage() );
		}
	}

	/**
	 * あらかじめ指定したメンバー、教材の組み合わせの学習回数を１つ増加する。<br>
	 * このメソッドを呼ぶ前にsetWhereMaterialIDメソッド、setWhereMemberShipIDメソッドを呼び、
	 * 対象のメンバー、教材を指定する。
	 * @see #setWhereMaterialID(String)
	 * @see #setWhereMemberShipID(String)
	 * @throws XMOException
	 */
	private void countupStudyCount() throws XMOException {
		List executeResult = null;
		try {
			executeResult = (List)super.execute(METHOD_COUNTUP_STUDY_COUNT, htParams);
			// リストが空ではない場合、例外が発生したのでエラーを表示する。
			if (executeResult != null && executeResult.size() > 0 ) {
				String message = null;
				message = (String)executeResult.get(0);
				throw new XMOException( message );
			}
		} catch (XMOException e) {
			throw e;
		} catch ( Exception e ) {
			DebugLog.write(this.getClass(), e, DebugLog.HIGHT );
			throw new XMOException( e.getMessage() );
		}
	}

	/**
	 * メール送信の１回あたりの送信件数を取得する。
	 * @return メール送信の１回あたりの送信件数。
	 * @throws XMOException
	 */
	public int getSendMailCount() throws XMOException {
		Map executeResult = null;
		int returnValue = 0;
		try {
			executeResult = (Map)super.execute(METHOD_GET_SEND_MAIL_COUNT, htParams);
			// エラーメッセージの取得
			String message = null;
			message = (String)executeResult.get( KEY_ERROR_MESSAGE );
			if ( message != null ) {
				throw new XMOException( message );
			}
			// 送信件数の取得
			Integer sendMailCount = null;
			sendMailCount = (Integer)executeResult.get( KEY_SEND_MAIL_COUNT );
			if ( sendMailCount == null ) {
				throw new XMOException( "sendMailCount == null" );
			}
			returnValue = sendMailCount.intValue();
		} catch (XMOException e) {
			throw e;
		} catch ( Exception e ) {
			DebugLog.write(this.getClass(), e, DebugLog.HIGHT );
			throw new XMOException( e.getMessage() );
		}
		return returnValue;
	}


// 学習回数カウントアップのため、教材種別を渡せるように修正。
	/**
	 * 教材種別を設定します。<br>
	 * @param loType 教材種別。
	 * @see jp.co.ntt.lms.lo.LoConstant#LO_TYPE_WBT
	 * @see jp.co.ntt.lms.lo.LoConstant#LO_TYPE_SMARTFORCE
	 * @see jp.co.ntt.lms.lo.LoConstant#LO_TYPE_PERCEPTION
	 */
	private void setLoType(String loType) {
		putData(KEY_LO_TYPE, loType);
	}

}

