2階層(2つのキーを持つ)の構造を考えてみる。
どう実装するのがよいか。
MXBeanにするためにインタフェースを定義
package jp.person.akaitsuki.sample; import javax.management.MXBean; @MXBean public interface ObjectTable { /** * オブジェクトテーブルを初期化する。 * * @param id1Num id1オブジェクトの数 * @param id2Num id2オブジェクトの数 * @return 初期化に成功すればtrue,失敗ならfalse */ boolean initTable(int id1Num, int id2Num); /** * id1とid2に指定したオブジェクトの状態を参照する。 * * @param id1 id1オブジェクトの番号 * @param id2 id2オブジェクトの番号 * @return 指定したオブジェクトの状態 */ int read(int id1, int id2); /** * id1に指定したオブジェクトのサマリー状態を参照する。 * * @param id1 id1オブジェクトの番号 * @return 指定したオブジェクトの状態 */ int readSummary(int id1); /** * 指定したid1オブジェクトのMapから利用可能なid2オブジェクトの番号を取得する。 * * @param id1 id1オブジェクトの番号 * @return 利用可能なid2オブジェクトの番号(複数存在する場合は、番号の小さいものを取得する) * 利用可能なものがない場合は、AVAILABLE_ID2_ERRORを返す。 * 使用中であり利用可能なものがない場合は、AVAILABLE_ID2_BUSYvを返す。 */ int getAvailableID2Object(int id1); /** * 利用可能なid1オブジェクトの番号を取得する。 * * @return 利用可能なid1オブジェクトの番号をint配列で返す。 */ int[] getAvailableID1Object(); /** * id1とid2に指定したオブジェクトの状態を更新する。 * * @param id1 id1オブジェクトの番号 * @param id2 id2オブジェクトの番号 * @param status 更新する状態 * @return 更新結果(更新成功:true,更新失敗:false) */ boolean update(int id1, int id2, int status); /** * 保持するオブジェクトのid2オブジェクトの数を取得する。 * * @return id2オブジェクトの数 */ int getConnectionNum(); /** * 全id2オブジェクトの状態を文字列として取得する。 * * @return 全id2オブジェクトの状態を表す文字列 */ String getStatusList(); }
インタフェースの実装クラス
package jp.person.akaitsuki.sample; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * オブジェクトテーブルの実装クラス * * @author akaitsuki * */ public class ObjectTableInfo implements ObjectTable { /** id2の状態を示す定数:エラー(状態未定義) */ public static final int STATUS_ERROR = -1; /** id2の状態を示す定数:停止 */ public static final int STATUS_STOP = 0; /** id2の状態を示す定数:準備中 */ public static final int STATUS_PREPARING = 1; /** id2の状態を示す定数:利用可能 */ public static final int STATUS_AVAILABLE = 2; /** id2の状態を示す定数:使用中 */ public static final int STATUS_BUSY = 3; /** id1の状態を示す定数:エラー(状態未定義) */ public static final int SUMMARY_STATUS_ERROR = -1; /** id1の状態を示す定数:ステータス0 */ public static final int SUMMARY_STATUS_NOT_AVAILABLE = 0; /** id1の状態を示す定数:ステータス1 */ public static final int SUMMARY_STATUS_AVAILABLE = 1; /** 利用可能な状態を取得する際の応答定数:エラー(利用可能なものがない) */ public static final int AVAILABLE_ID2_ERROR = -1; /** 利用可能な状態を取得する際の応答定数:エラー(利用中でありすぐに利用可能なものがない) */ public static final int AVAILABLE_ID2_BUSY = 0; /* id1Map_ , id2Mapは1オリジンになっている点に注意。 */ private Map<Integer, Map<Integer, StatusObject>> id1Map_; private int id1Num_ = 0; private int id2Num_ = 0; /** * デフォルトコンストラクタ * * 内部のid1オブジェクトMapを生成する。 */ public ObjectTableInfo() { id1Map_ = new HashMap<Integer, Map<Integer, StatusObject>>(); } public boolean initTable(int id1Num, int id2Num) { this.id1Num_ = id1Num; this.id2Num_ = id2Num; boolean result = true; for (int cntIdx1 = 1; cntIdx1 <= id1Num; cntIdx1++) { Map<Integer, StatusObject> id2Map = new HashMap<Integer, StatusObject>(); for (int cntIdx2 = 1; cntIdx2 <= id2Num; cntIdx2++) { StatusObject status = new StatusObject(); status.setStatus(STATUS_STOP); id2Map.put(cntIdx2, status); } id1Map_.put(cntIdx1, id2Map); } return result; } @Override public int getConnectionNum() { int connectionNum = 0; for (int idx = 1; idx <= this.id1Num_; idx++) { Map<Integer, StatusObject> id2Map = this.id1Map_.get(idx); if (null != id2Map) { connectionNum += id2Map.size(); } } return connectionNum; } @Override public String getStatusList() { // TODO Auto-generated method stub return null; } @Override public int read(int id1, int id2) { int status = STATUS_ERROR; Map<Integer, StatusObject> id2Map = this.id1Map_.get(id1); if (null != id2Map) { StatusObject obj = id2Map.get(id2); if (null != obj) { status = obj.getStatus(); } } return status; } /** * id1に指定した状態マップのサマリー状態を取得する。 * * 状態マップの中で、STATUS_AVAILABLE or STATUS_BUSY に該当するものがあれば * SUMMARY_STATUS_AVAILABLEを返す。なければSUMMARY_STATUS_NOT_AVAILABLEを返す。 * id1に指定した状態マップがない場合はSUMMARY_STATUS_ERRORを返す。 * * (non-Javadoc) * * @see jp.person.akaitsuki.sample.ObjectTable#readSummary(int) */ @Override public int readSummary(int id1) { int summaryStatus = SUMMARY_STATUS_NOT_AVAILABLE; Map<Integer, StatusObject> id2Map = this.id1Map_.get(id1); if (null != id2Map) { for (int idx = 1; idx <= this.id2Num_; idx++) { StatusObject obj = id2Map.get(idx); int status = obj.getStatus(); if (STATUS_BUSY == status || STATUS_AVAILABLE == status) { summaryStatus = SUMMARY_STATUS_AVAILABLE; } } } else { summaryStatus = SUMMARY_STATUS_ERROR; } return summaryStatus; } @Override public boolean update(int id1, int id2, int status) { boolean result = true; Map<Integer, StatusObject> id2Map = id1Map_.get(id1); if (null != id2Map) { StatusObject obj = id2Map.get(id2); if (null != obj) { obj.setStatus(status); } else { result = false; } } else { result = false; } return result; } @Override public int[] getAvailableID1Object() { List<Integer> availableNumberList = new ArrayList<Integer>(); for (int idx = 1; idx <= this.id1Num_; idx++) { int summaryStatus = readSummary(idx); if( SUMMARY_STATUS_AVAILABLE == summaryStatus) { availableNumberList.add(idx); } } int listSize = availableNumberList.size(); int[] availableNumbers = new int[listSize]; for(int cnt = 0 ;cnt < listSize; cnt++) { availableNumbers[cnt] = availableNumberList.get(cnt); } return availableNumbers; } @Override public int getAvailableID2Object(int id1) { int availableId2 = AVAILABLE_ID2_ERROR; Map<Integer, StatusObject> id2Map = this.id1Map_.get(id1); if (null != id2Map) { for (int idx = 1; idx <= this.id2Num_; idx++) { StatusObject obj = id2Map.get(idx); int status = obj.getStatus(); if (STATUS_AVAILABLE == status) { availableId2 = idx; break; } else if (STATUS_BUSY == status) { availableId2 = AVAILABLE_ID2_BUSY; } } } return availableId2; } }