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

//
//	GroupAndPeople 管理XMO クライアントクラス
//			変更履歴
//				2004.01.08	新規作成	二條智文
//

package jp.co.ntt.lms.xmo.GroupAndPeople;

import java.rmi.RemoteException;
import java.util.*;

import org.apache.commons.lang.StringEscapeUtils;

import jp.co.ntt.lms.xmo.*;
import jp.co.ntt.lms.xmo.util.*;
import jp.co.ntt.lms.xms.framework.XmsException;
import jp.co.ntt.lms.xms.framework.XmsSystemException;
import jp.co.ntt.lms.xms.framework.XmsWarningException;

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

	private static final String CLASS_NAME = "jp.co.ntt.lms.xmo.GroupAndPeople.GroupAndPeople";

	/**
	 * GroupAndPeopleXMO独自のメソッドです。<BR>
	 * 指定されたIDのパスを検索します。
	 */
	private static final String METHOD_GETPATH = "getPath";

	/**
	 * GroupAndPeopleXMO独自のメソッドです。<BR>
	 * コピーします。
	 */
	private static final String METHOD_COPY = "copy";

	/**
	 * GroupAndPeopleXMO独自のメソッドです。<BR>
	 * 移動します。
	 */
	private static final String METHOD_TRANSFER = "transfer";

	/**
	 * GroupAndPeopleXMO独自のメソッドです。<BR>
	 * ツリーキャッシュを参照せず、直接ＤＢを検索します。
	 */
	private static final String METHOD_SELECT2 = "selectDatabase";

	/**
	 * GroupAndPeopleのキャッシュしているツリーをリロードするメソッド名です。<BR>
	 */
	private static final String METHOD_RELOADTREE = "reloadTree";


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

	/**
	 * パラメータにメンバーシップIDをセットします
	 */
	public void setMemberShipID( String strData ) {
		putData( MEMBER_SHIP_ID, strData );
	}

	/**
	 * メンバーシップIDを取得します
	 */
	public String getMemberShipID() {
		GroupAndPeopleData objData = (GroupAndPeopleData)getResult();
		return objData.getMemberShipID();
	}

	/**
	 * パラメータに親IDをセットします
	 */
	public void setParentID( String strData ) {
		putData( PARENT_ID, strData );
	}

	/**
	 * 親IDを取得します
	 */
	public String getParentID() {
		GroupAndPeopleData objData = (GroupAndPeopleData)getResult();
		return objData.getParentID();
	}

	/**
	 * パラメータに子IDをセットします
	 */
	public void setChildID( String strData ) {
		putData( CHILD_ID, strData );
	}

	/**
	 * 子IDを取得します
	 */
	public String getChildID() {
		GroupAndPeopleData objData = (GroupAndPeopleData)getResult();
		return objData.getChildID();
	}

	/**
	 * パス検索の結果を取得します
	 * @return String[]
	 */
	public String[] getPath() {
		String[] strPath = (String[])getResult();
		return strPath;
	}

	/**
	 * 子IDがグループか人かを返します
	 * @return boolean true: グループ false: 人
	 */
	public boolean isGroup() {
		GroupAndPeopleData objData = (GroupAndPeopleData)getResult();
		return objData.isGroup();
	}

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

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

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

	/**
	 * GroupAndPeopleXMOの独自のメソッドです。<BR>
	 * 指定されたIDのパスを取得します
	 * @param 検索ID
	 * @return boolean ture: 検索成功 false: 検索失敗
	 */
	public boolean searchPath( String strID )
		throws Exception
	{
		// ID設定
		setParentID( strID );

		// 検索実行
		Vector vecPathList = (Vector)super.execute( METHOD_GETPATH, htParams );

		// メッセージデータを取得します
		MessageData objMessage = (MessageData)vecPathList.get(0);
		mobjMessage = objMessage;
		if( isErr( objMessage ) ) {
			return false;
		}

		vecResults = vecPathList;

		return true;
	}

	/**
	 * 削除するselectID(Group_idまたはuser_id)を設定する。<BR>
	 * 共通処理管理 ログ削除処理で使用する。
	 *
	 * @param strID selectID
	 */
	public void setDeleteSelectID( String strID ) {
		putData( DELETE_SELECTID, strID );
	}

	/**
	 * 削除するparent_idを設定する。<BR>
	 * 共通処理管理 ログ削除処理で使用する。
	 *
	 * @param strID parent_id
	 */
	public void setDeleteParentID( String strID ) {
		putData( DELETE_PARENTID, strID );
	}

	/**
	 * 更新処理の際に、Assignmentsテーブルを更新しないフラグを設定する<BR>
	 */
	public void setDontUpdateAssignments() {
		putData( UPDATE_ASSIGNMENTS, UPDATE_ASSIGNMENTS );
	}
	/**
	 * GroupAndPeopleXMOの独自のメソッドです。<BR>
	 * 指定されたGroupID配下の全ユーザーIDを取得します。
	 * @param String GroupID        グループID
	 * @param Vector vecUserList    ユーザーIDリスト
	 */
	public void getUserList( String strParentID, Vector vecUserList )
		throws Exception
	{
		GroupAndPeopleClient objGroupAndPeople = new GroupAndPeopleClient();
		// 検索処理
		objGroupAndPeople.setWhereParentID( strParentID );

		// selectメソッド実行
		if( !objGroupAndPeople.select() ) {
			// 検索失敗
			// エラー処理
			throw new Exception();
		}

		// 検索結果
		while( objGroupAndPeople.next() ) {
			String strChildID = objGroupAndPeople.getChildID();
			// ユーザかどうか調べる
			if( !objGroupAndPeople.isGroup() ) {
				if( !vecUserList.contains( strChildID ) ) {
					vecUserList.add( strChildID );
				}
			}
			else {
				// グループなら再帰処理
				this.getUserList( strChildID, vecUserList );
			}
		}
	}


	/**
	 * ユーザの所属追加を行います。
	 * @param strSendMemberShipIDList 移動元メンバーシップIDリスト
	 * @param strReceiveMemberShipID 移動先メンバシップID
	 * @param intType 移動処理区分(1: 上へ 2: 中へ 3: 下へ)
	 * @return boolean 正常時はtrue エラー時はfalse
	 * @exception Exception RMI通信エラー、内部エラー
	 */
	public boolean copy(String[] strSendMemberShipIDList, String strReceiveMemberShipID, int intType)
		throws Exception
	{
		// パラメータチェック
		if( strSendMemberShipIDList == null || strReceiveMemberShipID == null ) {
			XMOException xe = new XMOException("内部エラー: 所属追加処理でパラメータが不正です。");
			// ログ書き込み
			DebugLog.write( this.getClass(), xe, DebugLog.ROW );
			throw xe;
		}

		if( !(intType == UP_TYPE || intType == IN_TYPE || intType == DOWN_TYPE) ) {
			XMOException xe = new XMOException("内部エラー: 所属追加処理で処理タイプが不正です。");
			// ログ書き込み
			DebugLog.write( this.getClass(), xe, DebugLog.ROW );
			throw xe;
		}

		// パラメータをHashtableに格納します
		// 所属追加元IDリストの設定
		htParams.put(SEND_MEMBERSHIPID_LIST, strSendMemberShipIDList);
		// 所属追加先IDの設定
		htParams.put(RECEIVE_MEMBERSHIPID, strReceiveMemberShipID);
		// 処理タイプの設定
		htParams.put(PROCESS_TYPE, new Integer(intType));

		vecResults = (Vector)super.execute( METHOD_COPY, htParams );
		// メッセージデータを取得します
		MessageData objMessage = (MessageData)vecResults.get(0);
		mobjMessage = objMessage;
		if( isErr( objMessage ) || isWarning( objMessage )  ) {
			return false;
		}
		return true;
	}


	/**
	 * 検索処理
	 * @return boolean 正常時はtrue　エラー時はfalse
	 * @exception Exception RMI接続に失敗した場合
	 */
	public boolean selectDatabase()
		throws Exception
	{
		return select_m( METHOD_SELECT2 );
	}

	/**
	 * GroupAndPeopleのキャッシュしているツリーをリロードするメソッドです。<BR>
	 * @return boolean ture: リロード成功 false: リロード失敗
	 */
	public boolean reloadTree()
		throws Exception
	{
		Vector vecPathList = (Vector)super.execute( METHOD_RELOADTREE, htParams );
		// メッセージデータを取得します
		MessageData objMessage = (MessageData)vecPathList.get(0);
		mobjMessage = objMessage;
		if( isErr( objMessage ) ) {
			return false;
		}
		vecResults = vecPathList;
		return true;
	}

	/**
	 * 単一グループ又はユーザの移動を行います。<BR>
	 * @param strSendMemberShipID 移動元メンバーシップID
	 * @param strReceiveMemberShipID 移動先メンバシップID
	 * @param intType 移動処理区分(1: 上へ 2: 中へ 3: 下へ)
	 * @return boolean 正常時はtrue エラー時はfalse
	 * @exception Exception RMI通信エラー、内部エラー
	 */
	public boolean transfer(String strSendMemberShipID, String strReceiveMemberShipID, int intType)
		throws Exception
	{
		String[] strSendMemberShipIDList = new String[1];
		strSendMemberShipIDList[0] = strSendMemberShipID;
		return transfer(strSendMemberShipIDList, strReceiveMemberShipID, intType);
	}

	/**
	 * グループとユーザの移動を行います。<BR>
	 * 複数の移動処理に対応します。
	 * @param strSendMemberShipIDList 移動元メンバーシップIDリスト
	 * @param strReceiveMemberShipID 移動先メンバシップID
	 * @param intType 移動処理区分(1: 上へ 2: 中へ 3: 下へ)
	 * @return boolean 正常時はtrue エラー時はfalse
	 * @exception Exception RMI通信エラー、内部エラー
	 */
	public boolean transfer(String[] strSendMemberShipIDList, String strReceiveMemberShipID, int intType)
		throws Exception
	{
		// パラメータチェック
		if( strSendMemberShipIDList == null || strReceiveMemberShipID == null ) {
			XMOException xe = new XMOException("内部エラー: 移動処理でパラメータが不正です。");
			// ログ書き込み
			DebugLog.write( this.getClass(), xe, DebugLog.ROW );
			throw xe;
		}

		if( !(intType == UP_TYPE || intType == IN_TYPE || intType == DOWN_TYPE) ) {
			XMOException xe = new XMOException("内部エラー: 移動処理で処理タイプが不正です。");
			// ログ書き込み
			DebugLog.write( this.getClass(), xe, DebugLog.ROW );
			throw xe;
		}

		// パラメータをHashtableに格納します
		// 移動元IDリストの設定
		htParams.put(SEND_MEMBERSHIPID_LIST, strSendMemberShipIDList);
		// 移動先IDの設定
		htParams.put(RECEIVE_MEMBERSHIPID, strReceiveMemberShipID);
		// 処理タイプの設定
		htParams.put(PROCESS_TYPE, new Integer(intType));

		vecResults = (Vector)super.execute( METHOD_TRANSFER, htParams );
		// メッセージデータを取得します
		MessageData objMessage = (MessageData)vecResults.get(0);
		mobjMessage = objMessage;
		if( isErr( objMessage ) || isWarning( objMessage )  ) {
			return false;
		}
		return true;
	}

	/**
	 * GroupAndPeopleXMOの独自のメソッドです。<BR>
	 * 指定されたGroupID及び配下の全GroupIDを取得します。
	 * @param String GroupID        グループID
	 * @param List lstGroupIdList   グループIDリスト
	 */
	public List getGroupIdList( String strParentID, List lstGroupIdList )
		throws XmsException {

		try {

			GroupAndPeopleClient objGroupAndPeople = new GroupAndPeopleClient();
	
			// 検索処理
			objGroupAndPeople.setWhereParentID( strParentID );
	
			// GroupIdをグループIDリストに設定
			lstGroupIdList.add(strParentID);
	
			// selectメソッド実行
			if( !objGroupAndPeople.select() ) {
				if(objGroupAndPeople.isErr()){
					// エラーの場合
					throw new XmsSystemException(objGroupAndPeople.getMessage());
				} else {
					// 警告の場合
					throw new XmsWarningException(objGroupAndPeople.getMessage());
				}
			}
			// 検索結果
			while( objGroupAndPeople.next() ) {
				String strChildID = objGroupAndPeople.getChildID();
				// グループかどうか調べる
				if( objGroupAndPeople.isGroup() ) {
					// 再帰処理
					this.getGroupIdList( strChildID, lstGroupIdList );
				}
			}
		} catch(XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
		return lstGroupIdList;
	}

	/**
	 * 配下学習者数を取得する
	 *
	 * @param gid グループID
	 * @return 学習者数
	 */
	public int getUserCount(String gid, int ret) throws XmsException {

		try {
			GroupAndPeopleClient objGandP = new GroupAndPeopleClient();
			objGandP.setWhereParentID(gid);
			if(!objGandP.select()) {
				// 検索がうまくいかなかった場合
				if(objGandP.isErr()){
					// エラーの場合
					throw new XmsSystemException(objGandP.getMessage());
				} else {
					// 警告の場合
					throw new XmsWarningException(objGandP.getMessage());
				}
			}
	
			while(objGandP.next()){
				String strChildID = objGandP.getChildID();
				if(objGandP.isGroup()){
					ret = getUserCount( strChildID, ret );
				} else {
					ret++;
				}
			}
		} catch(XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
		return ret;
	}


	/**
	 * 直下学習者数を取得する
	 *
	 * @param gid グループID
	 * @return 学習者数
	 */
	public int getUserCount(String gid) throws XmsException {
		int ret = 0;

		try {
			GroupAndPeopleClient objGandP = new GroupAndPeopleClient();
			objGandP.setWhereParentID(gid);
			if(!objGandP.select()) {
				// 検索がうまくいかなかった場合
				if(objGandP.isErr()){
					// エラーの場合
					throw new XmsSystemException(objGandP.getMessage());
				} else {
					// 警告の場合
					throw new XmsWarningException(objGandP.getMessage());
				}
			}
	
			while(objGandP.next()){
				String strChildID = objGandP.getChildID();
				if(objGandP.isGroup()){
					//グループの時はなにもしない
				} else {
					ret++;
				}
			}
		} catch(XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
		return ret;
	}

}

