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

//
//	Xcalact Server情報データ保持クラスより接続サーバを決定　
//			変更履歴
//			2004.01.08 新規作成		kin

package jp.co.ntt.lms.lo.WBT;
import java.util.*;

// XMS2 API
import jp.co.ntt.lms.lo.*;
import jp.co.ntt.lms.xmo.MessageData;

/**
 * Xcalact Server 取得情報より接続サーバを決定。<BR>
 * このクラスは自クラスで保持し、学習開始
 * ときに使用されます。<BR>
 * @author kin
 * @version 2.0.0.3 2004/01/08
 */

public class WbtServerInfo implements WbtLoPropertyDef{

	// サーバ情報をキャッシュで保持します 
	private Hashtable htbSVList = new Hashtable();

	// Singltonとして動作するために自分のインスタンスを保持します 
	private static WbtServerInfo objServerInfo = new WbtServerInfo();


	/**
	 * インスタンスを返却します
	 * @param objServerInfo 
	 */
	public static WbtServerInfo getInstance() {
		return objServerInfo;
	}

	/**
	 * 取得サーバ情報（サーバ番号、名称）＋使用人数して
	 * オブジェクトをキャッシュに保持する
	 * WbtUserInfoクラスのloadメソッドに使用される
	 */
	public void addServerInfo() throws LOException{

		int NumberOfUsers=0;

		// WBT教材環境クラスのインスタンス化
		WbtLoEnv objWbtLoEnv = new WbtLoEnv();

		//WbtLoEnvよりサーバ情報を取得する
		Hashtable htbXcaSVList = objWbtLoEnv.getXcaServerList();
		try {
			//取得した情報をループする
			Enumeration e = htbXcaSVList.keys();

			while(e.hasMoreElements()){

				//サーバ番号、名前を取得
				Object XcaSVNO = e.nextElement();
				String XcaSVName = (String)htbXcaSVList.get(XcaSVNO);

				//WbtServerクラスをインスタンス化する
				WbtServer objServer = new WbtServer();

				//オブジェクトにサーバ番号、名前、人数を設定する
				objServer.setServerNO( (String)XcaSVNO );
				objServer.setServerName( XcaSVName );
				objServer.setNumberOfUsers( NumberOfUsers );

				//設定されたオブジェクトを番号順にキャッシュに入れる
				htbSVList.put(XcaSVNO,objServer);
			}
		}
		catch(Exception e)
		{
			throw new LOException(e.getMessage());
		}
	}

	/**
	 * 接続サーバを決定し、番号と名称を返す
	 * @return Hashtable 
	 */
	public Hashtable getServerSelected() throws LOException {

		//ユーザ登録数比較変数
		int intRetUserNO = 0;
		//割り当てたサーバ番号、名称
		String strRetSVNO = null;
		String strRetSVName= null;
		String strFirstSVNO = null;
		String strFirstSVName = null;

		//ハッシュのインスタンス化
		Hashtable htbServerSelected = new Hashtable();

		//サーバ番号順の情報を取得
		Vector vecIndexSVNO = new Vector(); 
		vecIndexSVNO = getServerInfo();

		try{

			//サーバ数と使用人数オブジェクトでキャッシュで保持
			Enumeration e = vecIndexSVNO.elements();
			
			while(e.hasMoreElements()){

				//サーバ番号順の情報取得
				Object objXcaSVInfo = e.nextElement();

				//サーバの使用人数を取得
				int XcaSVNumOfUser = ((WbtServer)objXcaSVInfo).getNumberOfUsers();
	
				//サーバの割当て（使用人数が少ない順）
				if( XcaSVNumOfUser < intRetUserNO ){
					strRetSVNO = ((WbtServer)objXcaSVInfo).getServerNO();
					strRetSVName = ((WbtServer)objXcaSVInfo).getServerName();
					break;
				}else{
					if(Integer.parseInt(((WbtServer)objXcaSVInfo).getServerNO().substring(9))==1){
						strFirstSVNO=((WbtServer)objXcaSVInfo).getServerNO();
						strFirstSVName=((WbtServer)objXcaSVInfo).getServerName();
					}
					intRetUserNO=XcaSVNumOfUser;
				}
			
			}
			if(strRetSVNO == null){
				strRetSVNO = strFirstSVNO;
				strRetSVName = strFirstSVName;
			}
				
			//決定されたサーバ使用人数を増加する
			incrementNumberOfUsers(strRetSVNO);	
		
			//決定されたサーバ番号、名称をキャッシュに保持する
			htbServerSelected.put(XCAL_SERVER_NO,strRetSVNO);
			htbServerSelected.put(XCAL_SERVER_NAME,strRetSVName);
		
		}
		catch(Exception e)
		{
			throw new LOException(e.getMessage());
		}
		return htbServerSelected;
	}


	/**
	 * サーバ情報割当てにより使用人数増加
	 * 学習開始時使用される
	 * @parm String strServerNO
	 */
	public void incrementNumberOfUsers(String strServerNO) {
		synchronized (this.htbSVList){
	
			int intIncGetNumber=((WbtServer)htbSVList.get(strServerNO)).getNumberOfUsers()+1;
			((WbtServer)htbSVList.get(strServerNO)).setNumberOfUsers(intIncGetNumber);
		}
	}

	/**
	 * サーバ情報割当てにより使用人数減らす
	 * 学習終了時使用される
	 * @parm String strServerNO
	 */
	public void decrementNumberOfUsers(String strServerNO ) {

		synchronized (this.htbSVList){
			int intDecGetNumber= ((WbtServer)htbSVList.get(strServerNO)).getNumberOfUsers()-1;
			((WbtServer)htbSVList.get(strServerNO)).setNumberOfUsers(intDecGetNumber);
		}

	}

	/**
	 * サーバ番号順情報を返す
	 * @return Vector vecgetServerInfo
	 */
	public Vector getServerInfo() throws LOException{

		// 情報返却用Vectorオブジェクトの作成
		Vector vecgetServerInfo = new Vector();

		try{
			//サーバ数と使用人数オブジェクトをキャッシュで保持
			Enumeration e = htbSVList.keys();
			//取得情報ソート用TreeSetの作成
			TreeSet TrS = new TreeSet(new NewComparator());
			//ソートするデータのセット
			while(e.hasMoreElements()){
				TrS.add(e.nextElement());
			}
			//要素取得用
			Iterator iterator = TrS.iterator();
			//ソートされたデータのセット
			while(iterator.hasNext()){
				vecgetServerInfo.add(htbSVList.get(iterator.next()));
			}
		}
		catch(Exception e)
		{
			throw new LOException(e.getMessage());
		}
		return vecgetServerInfo;
	}
	/**
	 * パラメータで送られてきたサーバ番号を持つサーバの名称を取得する
	 * サーバが存在しない場合はNULLを返す
	 * @parm String strOldServerNo
	 * return : サーバ名 OR null
	 */
	public String existServerName( String strOldServerNo ) throws LOException{

		// WBT教材環境クラスのインスタンス化
		WbtLoEnv objWbtLoEnv = new WbtLoEnv();

		//WbtLoEnvよりサーバ情報を取得する
		Hashtable htbXcaSVList = objWbtLoEnv.getXcaServerList();
		try {
			//取得した情報をループする
			Enumeration e = htbXcaSVList.keys();

			while(e.hasMoreElements()){
				//サーバ番号、名前を取得
				Object XcaSVNO = e.nextElement();
				String XcaSVName = (String)htbXcaSVList.get(XcaSVNO);

				String strIniServerNo = (String)XcaSVNO;
				String strIniServerName = XcaSVName;
				if( strOldServerNo.equals(strIniServerNo) ){	
					return strIniServerName;
				}
			}
			return null;
		}
		catch(Exception e)
		{
			throw new LOException(e.getMessage());
		}
	}
}

// 番号順にソートする為のComparatorクラスのセットアップ
class NewComparator implements Comparator{
	public int compare(Object obj1,Object obj2){
		// 番号の取得
		int intObjNo1 = Integer.parseInt(((String)obj1).substring(9));
		int intObjNo2 = Integer.parseInt(((String)obj2).substring(9));
		// 番号順に並び替える為の比較処理
		if(intObjNo1 < intObjNo2){
			return -1;
		}else if(intObjNo1 > intObjNo2){
			return 1;
		}else{
			return 0;
		}
	}
}
