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

//
//	XMS_B 検索API
//			変更履歴
//				2004.01.08	新規作成	二條智文
//
package jp.co.ntt.lms.xmo.Base;

// javaAPI
import java.util.Vector;
import java.util.Hashtable;
import java.text.Collator;
// XMOAPI
import jp.co.ntt.lms.xmo.Groups.*;
import jp.co.ntt.lms.xmo.People.PeopleClient;
import jp.co.ntt.lms.xmo.GroupAndPeople.GroupAndPeopleClient;
import jp.co.ntt.lms.xmo.Lo.*;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xmo.Environment;
import jp.co.ntt.lms.xmo.LoRelation.LoRelationClient;
import jp.co.ntt.lms.xmo.XMOException;

/**
 * パス検索API<BR>
 * このクラスは以下のXMOを使用して指定された名称のパスを
 * 検索して返します。<BR>
 *    GroupsXMO: グループ名称からIDを取得するのに使用する。<BR>
 *    PeopleXMO: ユーザ名称からIDを取得するのに使用する。<BR>
 *    GroupAndPeopleXMO: グループとユーザのツリー構造からパスを取得する。<BR>
 *    LoXMO: LO名称からIDを取得するのに使用する<BR>
 *    LoRelation: LOのツリー構造からパスを取得する。<BR>
 * @version 0.0.0.1 2004/01/08
 * @author T.Nijou
 */
public class SearchPath {

	/** グループと人タイプを表します */
	public final String GROUP_TYPE = "1";

	/** LOタイプを表します */
	public final String LO_TYPE = "2";

	/** XMS.iniの検索時最大表示件数です。*/
	private static final String SEARCH_RESULT_ROW_COUNT = "search_result_row_count";

	// スーパーユーザIDをあらわします
	private final String SUPER_USER = "PE000000";

	// グループのルートIDをあらわします
	private final String GROUP_ROOT = "GR000000";

	// LOのルートIDをあらわします
	private final String LO_ROOT = "LO0";

	// ツリーのルートを表します
	private final String GROUP_TREE_ROOT = "grouptreeroot";

	// rootユーザ以外のLOルートIDです
	private final String LO_TREE_ROOT = "lotreeroot";


	/** グループ名称から検索するタイプです */
	public static final int GROUP_NAME = 1;
	/** ユーザ名称から検索するタイプです */
	public static final int USER_NAME = 2;
	/** LO名称から検索するタイプです */
	public static final int LO_NAME = 3;
	/** LO名称から検索するタイプです(メソッドは除く） */
	public static final int LO_NAME_WITHOUT_METHOD = 4;

	/** 名称キャッシュ用ハッシュテーブルです */
	private Hashtable mhtbName = null;

	/** 検索タイプを保持します */
	private int mintSearchType = 0;

	/** 検索結果表示件数を保持します */
	private String mstrPageRowCount = "";
	
	/** 検索ヒット時の最大IDを保持します。 */
	private String mstrSearchResultMaxId = "";

	/** 検索結果数を返却します */
	private String[][]  mobjSearchResult = null;

	/** 検索タイプを保持します */
	private int mintSearchResultHitCnt = 0;

	private String mstrTreeViewType = "";

	private String mstrUserID = "";

	/**
	 * コンストラクタです。
	 * @param intSearchType 検索タイプを指定します
	 */
	public SearchPath( int intSearchType, String strTreeViewType, String strUserID ) throws Exception{
		// 検索タイプの設定
		mintSearchType = intSearchType;

		//ページ表示件数の取得
		Environment objEnv = new Environment();
		mstrPageRowCount = objEnv.getProperty(SEARCH_RESULT_ROW_COUNT);
		mstrTreeViewType = strTreeViewType;
		mstrUserID = strUserID;
	}

	/**
	 * パスの検索処理を行います。<BR>
	 * @param strName 検索名称
	 * @return String[][] 検索結果
	 */
	public String[][] searchPath( String strName, String strLimit ) {

		try {
			// 名称キャッシュ用ハッシュテーブルをインスタンス化
			mhtbName = new Hashtable();

			String[][] strSearchResult = null;

			// タイプにより処理を振り分けます
			switch( mintSearchType ) {
				case GROUP_NAME:
					strSearchResult = searchGroups( strName );
					break;
				case USER_NAME:
					strSearchResult = searchGroups( strName );
					break;
				case LO_NAME:
					strSearchResult = searchLo( strName );
					break;
				case LO_NAME_WITHOUT_METHOD:
					strSearchResult = searchLoWithoutMethod( strName );
					break;
				default:
					// 検索タイプが不正の場合はnullを返す
					DebugLog.write( this.getClass(), "検索タイプが不正です。検索タイプ=" + mintSearchType, DebugLog.HIGHT );
					return null;
			}

			strSearchResult = AuthFilter(mstrTreeViewType, mstrUserID, strSearchResult);
			mobjSearchResult = strSearchResult;
			mintSearchResultHitCnt = strSearchResult.length;

			return getSearchResultByRange(strLimit, strSearchResult);
		}
		catch( Exception e ) {
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			e.printStackTrace();
			// @pending エラー処理
		}
		finally {
			// キャッシュクリア
			mhtbName = null;
		}

		return null;
	}

	////////////////////////////////////////////////////////////////////////////
	// グループと人検索
	////////////////////////////////////////////////////////////////////////////

	/**
	 * グループと人のパス検索を行います。
	 * @param strName 検索名称
	 * @return String[][] 検索結果
	 * @exception XMOException XMO独自例外
	 */
	public String[][] searchGroups( String strName )
		throws Exception
	{
		String[] strIDList = null;
		if( mintSearchType == GROUP_NAME ) {
			// 名称からグループIDのリストを検索します
			strIDList = searchGroupsID( strName );
		}
		else if( mintSearchType == USER_NAME ) {
			// 名称からユーザIDのリストを検索します
			strIDList = searchPeopleID( strName );
		}

		// 上記2種類の結果をあわせます
		Vector vecIDList = new Vector();
		// グループの結果
		for( int i = 0; i < strIDList.length; i++ ) {
			vecIDList.add( strIDList[i] );
		}

		// 取得したIDリストからパスを取得します
		Vector vecPathList = getGroupPathList( vecIDList );
		// 取得したIDパスと名称をマッピングします
		Vector vecPathMapping = setGroupPathMapping( vecPathList );

		// 取得したベクターをStringの配列に変換
		String[][] strResult = new String[vecPathMapping.size()][2];
		vecPathMapping.copyInto( strResult );

		return strResult;

	}

	/**
	 * 名称からグループIDのリストを検索して返します
	 * @param strName 検索名称
	 * @return String[] 検索結果
	 * @exception XMOException XMO独自例外
	 */
	private String[] searchGroupsID( String strName )
		throws Exception
	{
		// グループ管理XMOクライアントのインスタンス化
		GroupsClient objGroups = new GroupsClient();

		objGroups.setWhereSearchCondition(strName);

		// 検索実施
		if( !objGroups.select() ) {
			// 検索失敗時
			throw new XMOException( objGroups.getMessage() );
		}

		// 検索がうまくいった場合
		Vector vecIDList = new Vector();
		while( objGroups.next() ) {
			vecIDList.add( objGroups.getGroupID() );
		}

		// IDリストをStringの配列に変換
		String[] strIDList = new String[vecIDList.size()];
		vecIDList.copyInto( strIDList );

		return strIDList;

	}

	/**
	 * 名称からユーザIDのリストを検索して返します
	 * @param strName 検索名称
	 * @return String[] 検索結果
	 * @exception XMOException XMO独自例外
	 */
	private String[] searchPeopleID( String strName )
		throws Exception
	{
		// グループ管理XMOクライアントのインスタンス化
		PeopleClient objPeople = new PeopleClient();

		objPeople.setWhereSearchCondition(strName );

		// 検索実施
		if( !objPeople.select() ) {
			// 検索失敗時
			throw new XMOException( objPeople.getMessage() );
		}

		// 検索がうまくいった場合
		Vector vecIDList = new Vector();
		while( objPeople.next() ) {
			vecIDList.add( objPeople.getUserID() );
		}

		// IDリストをStringの配列に変換
		String[] strIDList = new String[vecIDList.size()];
		vecIDList.copyInto( strIDList );

		return strIDList;

	}

	/**
	 * グループおよびユーザIDからIDパスを検索して返します
	 * @param vecIDList 検索IDリスト
	 * @return Vector 検索結果
	 * @exception XMOException XMO独自例外
	 */
	private Vector getGroupPathList( Vector vecIDList )
		throws Exception
	{
		// パラメータチェック
		if( vecIDList == null || vecIDList.size() == 0 ) {
			// 空のVectorを返す
			return new Vector();
		}

		// グループと人管理XMOクライアントのインスタンス化
		GroupAndPeopleClient objGroupAndPeople = new GroupAndPeopleClient();

		// パスリスト保持用Vectorです
		Vector vecPathList = new Vector();
		for( int i = 0; i < vecIDList.size(); i++ ) {
			String strID = (String)vecIDList.get(i);
			// ルートの検索の場合は何もしない
			if( strID.equals( "GR000000" ) ||
				strID.equals( "PE000000" )
			) {
				continue;
			}
			// パスの取得
			if( !objGroupAndPeople.searchPath(strID) ) {
				throw new XMOException( objGroupAndPeople.getMessage() );
			}

			// パスの取得がうまくいった場合
			while( objGroupAndPeople.next() ) {
				String[] strPath = objGroupAndPeople.getPath();
				vecPathList.add( strPath );
			}
			// 検索条件のクリア
			objGroupAndPeople.clear();
		}

		return vecPathList;

	}

	/**
	 * IDパスリストから名称パスリストを作成して返します
	 * @param vecPathList IDパスリスト(中身はString[])
	 * @return Vector 名称パスリスト(中身はString[][])
	 * @exception XMOException XMO独自例外
	 */
	private Vector setGroupPathMapping( Vector vecPathList )
		throws Exception
	{
		// パラメータチェック
		if( vecPathList == null || vecPathList.size() == 0 ) {
			// 空のVectorを返します
			return new Vector();
		}

		// 返却用Vector
		Vector vecReturn = new Vector();

		// 検索用クライアント部品
		GroupsClient objGroups = new GroupsClient();
		PeopleClient objPeople = new PeopleClient();

		for( int i = 0; i < vecPathList.size(); i++ ) {
			// パスの取得
			String[] strPath = (String[])vecPathList.get(i);

			// IDパス格納用
			StringBuffer strIDPath = new StringBuffer();
			// 名称パス格納用
			StringBuffer strNamePath = new StringBuffer();

			for( int j = 0; j < strPath.length; j++ ) {
				String strID = strPath[j];

				// キャッシュから名称取得
				String strName = (String)mhtbName.get( strID );

				// キャッシュに存在しない場合DBから名称取得
				if( strName == null ) {

					// パスIDが人の場合
					if( strID.substring(0,2).equals( "PE" ) ) {
						objPeople.clear();
						objPeople.setWhereUserID( strID );

						// グループ検索処理
						if( !objPeople.select() ) {
							throw new XMOException( objPeople.getMessage() );
						}

						// ユーザ名称の取得
						if( objPeople.next() ) {
							strName = objPeople.getUserName();
						}
					}
					// パスIDがグループの場合
					else if( strID.substring(0,2).equals( "GR" ) ) {

						objGroups.clear();
						objGroups.setWhereGroupID( strID );

						// グループ検索処理
						if( !objGroups.select() ) {
							throw new XMOException( objGroups.getMessage() );
						}

						// グループ名称の取得
						if( objGroups.next() ) {
							strName = objGroups.getGroupName();
						}
					}

					// キャッシュに名称をIDをキーにして格納
					mhtbName.put( strID, strName );
				}

				strIDPath.append( strID );
				strNamePath.append( strName );

				// 区切り文字の挿入
				if( j < strPath.length -1 ) {
					strIDPath.append( "/" );
					strNamePath.append( "," );
				}
			}

			String[] strFullPath = new String[2];
			strFullPath[0] = strIDPath.toString();
			strFullPath[1] = strNamePath.toString();
			// 返却用Vectorに格納
			vecReturn.add( strFullPath );
		}

		return vecReturn;
	}

	////////////////////////////////////////////////////////////////////////////
	// LO検索
	////////////////////////////////////////////////////////////////////////////

	/**
	 * LOのパス検索を行います。
	 * @param strName 検索名称
	 * @return String[][] 検索結果
	 * @exception XMOException XMO独自例外
	 */
	public String[][] searchLo( String strName )
		throws Exception
	{
		// 名称からLoIDのリストを検索します
		String[] strLoIDList = searchLoID( strName );
		Vector vecIDList = new Vector();
		// Loの結果
		for( int i = 0; i < strLoIDList.length; i++ ) {
			vecIDList.add( strLoIDList[i] );
		}

		// 取得したIDリストからパスを取得します
		Vector vecPathList = getLoPathList( vecIDList );
		// 取得したIDパスと名称をマッピングします
		Vector vecPathMapping = setLoPathMapping( vecPathList );

		// 取得したベクターをStringの配列に変換
		String[][] strResult = new String[vecPathMapping.size()][2];
		vecPathMapping.copyInto( strResult );

		return strResult;


	}

	/**
	 * 名称からLoIDのリストを検索して返します
	 * @param strName 検索名称
	 * @return String[] 検索結果
	 * @exception XMOException XMO独自例外
	 */
	private String[] searchLoID( String strName )
		throws Exception
	{
		// LoRelation管理XMOクライアントのインスタンス化
		LoClient objLo = new LoClient();

		objLo.setWhereSearchCondition(strName);

		// 検索実施
		if( !objLo.select() ) {
			// 検索失敗時
			throw new XMOException( objLo.getMessage() );
		}

		// 検索がうまくいった場合
		Vector vecIDList = new Vector();
		while( objLo.next() ) {
			vecIDList.add( objLo.getLoID() );
		}

		// IDリストをStringの配列に変換
		String[] strIDList = new String[vecIDList.size()];
		vecIDList.copyInto( strIDList );

		return strIDList;

	}

	/**
	 * LOのパス検索を行います。(メソッドタイプのLOは除きます）
	 * @param strName 検索名称
	 * @return String[][] 検索結果
	 * @exception XMOException XMO独自例外
	 */
	public String[][] searchLoWithoutMethod( String strName )
		throws Exception
	{
		// 名称からLoIDのリストを検索します
		String[] strLoIDList = searchLoIDWithoutMethod( strName );
		Vector vecIDList = new Vector();
		// Loの結果
		for( int i = 0; i < strLoIDList.length; i++ ) {
			vecIDList.add( strLoIDList[i] );
		}

		// 取得したIDリストからパスを取得します
		Vector vecPathList = getLoPathList( vecIDList );
		// 取得したIDパスと名称をマッピングします
		Vector vecPathMapping = setLoPathMapping( vecPathList );

		// 取得したベクターをStringの配列に変換
		String[][] strResult = new String[vecPathMapping.size()][2];
		vecPathMapping.copyInto( strResult );

		return strResult;


	}

	/**
	 * 名称からLoIDのリストを検索して返します
	 * @param strName 検索名称
	 * @return String[] 検索結果
	 * @exception XMOException XMO独自例外
	 */
	private String[] searchLoIDWithoutMethod( String strName )
		throws Exception
	{
		// LoRelation管理XMOクライアントのインスタンス化
		LoClient objLo = new LoClient();

		objLo.setCondition("LOType <> '21'");
		objLo.setWhereSearchCondition(strName);

		// 検索実施
		if( !objLo.select() ) {
			// 検索失敗時
			throw new XMOException( objLo.getMessage() );
		}

		// 検索がうまくいった場合
		Vector vecIDList = new Vector();
		while( objLo.next() ) {
			vecIDList.add( objLo.getLoID() );
		}

		// IDリストをStringの配列に変換
		String[] strIDList = new String[vecIDList.size()];
		vecIDList.copyInto( strIDList );

		return strIDList;

	}

	/**
	 * LoIDからIDパスを検索して返します
	 * @param vecIDList 検索IDリスト
	 * @return Vector 検索結果
	 * @exception XMOException XMO独自例外
	 */
	private Vector getLoPathList( Vector vecIDList )
		throws Exception
	{
		// パラメータチェック
		if( vecIDList == null || vecIDList.size() == 0 ) {
			// 空のVectorを返す
			return new Vector();
		}

		// LoRelationと人管理XMOクライアントのインスタンス化
		LoRelationClient objLoRelation = new LoRelationClient();

		// パスリスト保持用Vectorです
		Vector vecPathList = new Vector();
		for( int i = 0; i < vecIDList.size(); i++ ) {
			String strID = (String)vecIDList.get(i);
			// ルートの検索の場合は何もしない
			if( strID.equals( "LO0" ) ) {
				continue;
			}
			//2005/11/14
			//メソッドルートを除くように変更
			if (strID.equals("MD0")) continue;
			// パスの取得
			if( !objLoRelation.searchPath(strID) ) {
				throw new XMOException( objLoRelation.getMessage() );
			}

			// パスの取得がうまくいった場合
			while( objLoRelation.next() ) {
				String[] strPath = objLoRelation.getPath();
				vecPathList.add( strPath );
			}
			// 検索条件のクリア
			objLoRelation.clear();
		}
		return vecPathList;

	}

	/**
	 * IDパスリストから名称パスリストを作成して返します
	 * @param vecPathList IDパスリスト(中身はString[])
	 * @return Vector 名称パスリスト(中身はString[][])
	 * @exception XMOException XMO独自例外
	 */
	private Vector setLoPathMapping( Vector vecPathList )
		throws Exception
	{
		// パラメータチェック
		if( vecPathList == null || vecPathList.size() == 0 ) {
			// 空のVectorを返します
			return new Vector();
		}

		// 返却用Vector
		Vector vecReturn = new Vector();

		// 検索用クライアント部品
		LoClient objLo = new LoClient();

		for( int i = 0; i < vecPathList.size(); i++ ) {
			// パスの取得
			String[] strPath = (String[])vecPathList.get(i);

			// IDパス格納用
			StringBuffer strIDPath = new StringBuffer();
			// 名称パス格納用
			StringBuffer strNamePath = new StringBuffer();

			for( int j = 0; j < strPath.length; j++ ) {
				String strID = strPath[j];

				// キャッシュから名称取得
				String strLoTytle = (String)mhtbName.get( strID );

				// キャッシュから取得できない場合はDBから取得
				if( strLoTytle == null ) {
					objLo.clear();
					objLo.setWhereLoID( strID );

					// LoRelation検索処理
					if( !objLo.select() ) {
						throw new XMOException( objLo.getMessage() );
					}

					// ユーザ名称の取得
					if( objLo.next() ) {
						strLoTytle = objLo.getLoTytle();
					}

					// キャッシュに登録
					mhtbName.put( strID, strLoTytle );
				}

				strIDPath.append( strID );
				strNamePath.append( strLoTytle );

				// パスIDがLoRelationの場合
				// 区切り文字の挿入
				if( j < strPath.length -1 ) {
					strIDPath.append( "/" );
					strNamePath.append( "," );
				}
			}

			String[] strFullPath = new String[2];
			strFullPath[0] = strIDPath.toString();
			strFullPath[1] = strNamePath.toString();
			// 返却用Vectorに格納
			vecReturn.add( strFullPath );
		}

		return vecReturn;
	}
	
	/**
	 * ページ表示件数を返却します。
	 * @return int ページ表示件数(エラーの時は-１)
	 */
	public int getPageRowCount(){
		int result = -1 ;
		try{
			result = Integer.parseInt(mstrPageRowCount);
		}catch(Exception e){
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			e.printStackTrace();
		}
		
		return result;
	}

	/**
	 * ページ表示件数を設定します。
	 * @param String ページ表示件数
	 */
	public void setPageRowCount(String strPageRowCount){
		mstrPageRowCount = strPageRowCount;
	}

	/**
	 * 検索ヒット時の最大IDを返却します。
	 * @return 最大ID
	 */
	public String getSearchResultMaxId(){
		return mstrSearchResultMaxId;
	}

	/**
	 * 検索キーワードに対する総ヒット件数を返却します。
	 * @param strKey 検索キーワード
	 * @return int ヒット件数(エラーの時は-１)
	 */
	public int getSearchHitCount(){
		return mintSearchResultHitCnt;
	}

	/**
	 * 検索結果に権限フィルタを適用します。
	 * @param strTreeViewType ツリータイプ
	 * @param strUserID ログインID
	 * @return Vector 検索結果
	 * @exception XMOException XMO独自例外
	 */
	private String[][] AuthFilter(String strTreeViewType, 
								  String strUserID, 
								  String[][] strSearchResultList )
		throws XMOException, Exception
	{

		// スーパーユーザ以外は権限が及ぶ範囲で絞り込む
		Vector vecLoginUserResult = null;
		if( !strUserID.equals( SUPER_USER ) ) {

			// 検索結果格納用ベクターをインスタンス化
			vecLoginUserResult = new Vector();
			// ログインユーザの権限が及ぶIDリストを取得
			Vector vecRootList = getRootList( strTreeViewType, strUserID);

			if( strSearchResultList != null ) {
				for( int i = 0; i < strSearchResultList.length; i++ ) {
					String strIDPath = strSearchResultList[i][0];
					String strIDPathTemp = strIDPath + "/";
					String strNamePath = strSearchResultList[i][1];
					// ログインユーザの権限が及ぶID分ループ
					for( int j = 0; j < vecRootList.size(); j++ ) {
						String[] strTemp = (String[])vecRootList.get(j);
						// 割り当てられている教材IDと教材タイトルを取得
						String strAssID = strTemp[0];
						String strAssTitle = strTemp[1];

						// 検索結果のIDパスにユーザの権限がおよぶIDが含まれていた場合
						if( strIDPathTemp.indexOf( "/"+strAssID+"/" ) > 0 ) {
							// 権限がおよぶIDまでのパスを取得し'/'の数で名称パスを取得します
							String strIDTemp = strIDPath.substring( 0, strIDPath.indexOf( strAssID ) );
							// '/'の数を取得
							int intSCount = 0;
							for( int k = 0; k < strIDTemp.length(); k++ ) {

								char chrTemp = strIDTemp.charAt(k);
								if( chrTemp == '/' ) {
									intSCount++;
								}
							}

							// 名称パスから必要なパスを取得します
							StringBuffer strNameBuf = new StringBuffer();
							int intSPos = 0;
							for( int k = 0; k < intSCount; k++ ) {
								intSPos = strNamePath.indexOf( ',', intSPos ) + 1;
							}
							String strLoginUserNamePath = "";
							if( intSPos < strNamePath.length() ) {
								strLoginUserNamePath = strNamePath.substring( intSPos, strNamePath.length() );
							}
							String strLoginUserIDPath = "";
							if( ( strIDPath.indexOf( strAssID ) + strAssID.length()) < strIDPath.length() ) {
								strLoginUserIDPath = strIDPath.substring( strIDPath.indexOf( strAssID ) + strAssID.length(), strIDPath.length() );
							}
							String strRootID = null;
							if( strTreeViewType.equals( GROUP_TYPE ) ) {
								strRootID = GROUP_TREE_ROOT;
							}
							else {
								strRootID = LO_TREE_ROOT;
							}
							strLoginUserIDPath = strRootID + "/" + strAssID  + strLoginUserIDPath;
							strLoginUserNamePath = "root," + strLoginUserNamePath;

							String[] strLoginUserInfo = new String[2];
							strLoginUserInfo[0] = strLoginUserIDPath;
							strLoginUserInfo[1] = strLoginUserNamePath;
							vecLoginUserResult.add( strLoginUserInfo );
						}
					}
				}
			}
			// 検索結果リストを学習者の検索結果に置き換えます
			strSearchResultList = new String[vecLoginUserResult.size()][2];
			vecLoginUserResult.copyInto( strSearchResultList );
		}
		


		//*************************************************************************************************
		//パスの名前でソートします。（階層を日本語でソートする）
		//*************************************************************************************************
		Collator collator = Collator.getInstance();
		collator.setDecomposition(Collator.FULL_DECOMPOSITION);
		Vector vecSortResult = new Vector();
		
		for(int i = 0; i<strSearchResultList.length; i++ ){
			
			String strSortId = strSearchResultList[i][0];
			String strSortPasth = strSearchResultList[i][1];
			
			// 検索タイプがユーザの場合、ユーザ名部分をはずしてソートする。
			if ( mintSearchType == USER_NAME ){
				String strUserPath = strSearchResultList[i][1];
				strUserPath = strUserPath.substring( 0, strUserPath.lastIndexOf(",") );
				
				//リスト最終追加判定フラグの初期化
				boolean bflg = false;
				//パス名を結果格納リストの中のパスと比較する。
				for( int j = 0; j < vecSortResult.size(); j++ ){
					
					// ターゲットもパスだけの文字列を取得しチェック
					String strTargetPath = ((String[])vecSortResult.get(j))[1];
					strTargetPath = strTargetPath.substring( 0, strTargetPath.lastIndexOf(",") );
					
					if( collator.compare( strUserPath,  strTargetPath ) < 0){
						//現在の位置に挿入する。
						String[] strLoginUserInfo = new String[2];
						strLoginUserInfo[0] = strSortId;
						strLoginUserInfo[1] = strSortPasth;
						vecSortResult.add( j, strLoginUserInfo );
						//最終判定フラグをTRUEに設定
						bflg = true;
						break;
					}
				}
				//リスト全てと比較した結果、リストにまだ追加していなかったら
				if( !bflg ){
					//リストの最後に追加する。
					String[] strLoginUserInfo = new String[2];
					strLoginUserInfo[0] = strSortId;
					strLoginUserInfo[1] = strSortPasth;
					vecSortResult.add( strLoginUserInfo );
				}
			}
			else{
				//リスト最終追加判定フラグの初期化
				boolean bflg = false;
				//パス名を結果格納リストの中のパスと比較する。
				for( int j = 0; j < vecSortResult.size(); j++ ){
					if( collator.compare( strSortPasth, ((String[])vecSortResult.get(j))[1] ) < 0){
						//現在の位置に挿入する。
						String[] strLoginUserInfo = new String[2];
						strLoginUserInfo[0] = strSortId;
						strLoginUserInfo[1] = strSortPasth;
						vecSortResult.add( j, strLoginUserInfo );
						//最終判定フラグをTRUEに設定
						bflg = true;
						break;
					}
				}
				//リスト全てと比較した結果、リストにまだ追加していなかったら
				if( !bflg ){
					//リストの最後に追加する。
					String[] strLoginUserInfo = new String[2];
					strLoginUserInfo[0] = strSortId;
					strLoginUserInfo[1] = strSortPasth;
					vecSortResult.add( strLoginUserInfo );
				}
			}
		}

		// 検索結果リストを学習者の検索結果に置き換えます
		strSearchResultList = new String[vecSortResult.size()][2];
		vecSortResult.copyInto( strSearchResultList );
		
		return strSearchResultList;
	}


	/**
	 * ツリー表示時のルートに表示する情報一覧を取得するメソッドです。
	 * @param strTreeType ツリータイプ
	 * @param strUserID ユーザID
	 * @param strLearner 学習者区分
	 * @param response HTTPリスポンス
	 * @return Vector ルート情報
	 */
	private Vector getRootList( String strTreeType, String strUserID )
		throws XMOException, Exception
	{
		// ルートに表示する情報を格納するベクターです
		Vector vecRootList = new Vector();
		XMSBaseClient objXms = new XMSBaseClient();
		if( strTreeType.equals( GROUP_TYPE ) ) {

			// ルートLOリスト検索処理(管理アサインされているものを検索)
			if( !objXms.searchRootGroupList(strUserID) ) {
				throw new XMOException( objXms.getMessageData() );
			}

			// 検索がうまくいった場合
			GroupsData[] objGroupsList = objXms.getRootGroupList();

			// ルート直下のMemberShipIDをセッションに格納するためのHashtableをインスタンス化
			Hashtable htbRootInfo = new Hashtable();
			// セッションに格納します
//			session.setAttribute( ROOT_INFO, htbRootInfo );
			for( int i = 0; i < objGroupsList.length; i++ ) {
				GroupsData objGroupsData = objGroupsList[i];

				String strGroupID = objGroupsData.getGroupID();
				String strParentGroupID = objGroupsData.getParentID();
				if( strParentGroupID != null ) {
					// セッション情報にLOIDをキーにして、MemberShipIDを格納します
					htbRootInfo.put( strGroupID, strParentGroupID );
				}

				// LO情報を格納する配列を作成します
				String[] strGroupInfo = new String[3];
				// グループ情報配列の１番目にグループIDを格納します
				strGroupInfo[0] = strGroupID;
				// グループ情報配列の２番目にグループ名を格納します
				strGroupInfo[1] = objGroupsData.getGroupName();
				// グループ情報配列の３番目に親IDを格納します
				strGroupInfo[2] = strParentGroupID;
				// グループ情報をベクターに格納します
				vecRootList.add( strGroupInfo );
			}

		}
		else if( strTreeType.equals( LO_TYPE ) ) {

			// ルートLOリスト検索処理(管理アサインされているものを検索)
			if( !objXms.searchRootLoList(strUserID ) ) {
				throw new XMOException( objXms.getMessageData() );
			}

			// 検索がうまくいった場合
			LoData[] objLoList = objXms.getRootLoList();

			// ルート直下のMemberShipIDをセッションに格納するためのHashtableをインスタンス化
			Hashtable htbRootInfo = new Hashtable();
			// セッションに格納します
			for( int i = 0; i < objLoList.length; i++ ) {
				LoData objLoData = objLoList[i];

				String strLoID = objLoData.getLoID();
				String strParentLoID = objLoData.getParentID();
				// セッション情報にLOIDをキーにして、MemberShipIDを格納します
				htbRootInfo.put( strLoID, strParentLoID );

				// LO情報を格納する配列を作成します
				String[] strLoInfo = new String[3];
				// LO情報配列の１番目にLOIDを格納します
				strLoInfo[0] = strLoID;
				// LO情報配列の２番目にLOタイトルを格納します
				strLoInfo[1] = objLoData.getLoTytle();
				// LO情報配列の３番目に親IDを格納します
				strLoInfo[2] = strParentLoID;

				// グループ情報をベクターに格納します
				vecRootList.add( strLoInfo );
			}
		}

		return vecRootList;
	}


	/**
	 * 指定されたIDより大きいものをiniファイルに指定された件数分返すメソッドです。
	 * @param strLimit 指定ID
	 * @param strSearchResultList 権限フィルタ後の検索結果
	 * @return Vector 指定された件数の検索結果
	 */
	private String[][] getSearchResultByRange(String strLimit, 
								  String[][] strSearchResultList )
	{
		if ( strSearchResultList == null ){
			return null;
		}
		if ( strSearchResultList.length == 0 ){
			return strSearchResultList;
		}
		
		int iLastID = 0;
		
		//ページ表示件数を取得
		int iPageRowCnt = getPageRowCount();
		Vector vecUserResult = new Vector();
		
		if ( strLimit != null ){
			boolean bcopyFlg = false;
			int iLimit = Integer.parseInt( strLimit );
			int copycnt = 0;
			//検索結果分ループし指定されたIDより大きいものをページ表示件数分取得
			for( int i=0; i<strSearchResultList.length; i++ ){
				String strIdPath = strSearchResultList[i][0];
				String strNamePath = strSearchResultList[i][1];
				String strTarget = strIdPath.substring( strIdPath.lastIndexOf("/")+1 );
				//指定されたIDより大きい場合はコピーフラグをonにする。
				if ( i > iLimit ){
					bcopyFlg = true;
				}
				//コピーフラグがonでかつ取得数がページ表示件数に満たない場合は取得する。
				if ( bcopyFlg && copycnt < iPageRowCnt){
					String[] strUserInfo = new String[2];
					strUserInfo[0] = strIdPath;
					strUserInfo[1] = strNamePath;
					vecUserResult.add( strUserInfo );
					copycnt++;
					iLastID = i;
				}
				
			}
		}
		else{
			//ページ表示件数分先頭から取得する。
			int copycnt = 0;
			for( int i=0; i<strSearchResultList.length; i++ ){

				String strIdPath = strSearchResultList[i][0];
				String strNamePath = strSearchResultList[i][1];
				//取得数がページ表示件数に満たない場合は取得する。
				if ( copycnt < iPageRowCnt){
					String[] strUserInfo = new String[2];
					strUserInfo[0] = strIdPath;
					strUserInfo[1] = strNamePath;
					vecUserResult.add( strUserInfo );
					copycnt++;
					iLastID = i;
				}
			}
		}
		
		// 検索結果リストを置き換えます
		strSearchResultList = new String[vecUserResult.size()][2];
		vecUserResult.copyInto( strSearchResultList );
		
		//取得リストの最後のIDをMAXIDとして設定する。
		mstrSearchResultMaxId = Integer.toString( iLastID );
		
		return strSearchResultList;
	}
	
}


