AKAI TSUKI

System development or Technical something

2階層Mapを管理する

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;
	}

}