/*
 * $Id: HashMapLookup.java,v 1.4 2006/01/28 03:37:07 rampil Exp $
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 *
 */
package org.logical_paradox.rss.lookup.impl;

import static org.logical_paradox.rss.dsr.RSSDistributedServiceRegistry.RSS_SERVID_SERVICE_LOCATER;

import java.rmi.RemoteException;
import java.util.HashMap;

import org.logical_paradox.rss.Service;
import org.logical_paradox.rss.dsr.RSSDistributedServiceRegistry;
import org.logical_paradox.rss.lookup.Lookup;

/**
 * ハッシュマップを使用するタイプのルックアップ
 * テストなどで使用するため
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.4 $
 */
public class HashMapLookup implements Lookup {
	/** バインドターゲット */
	private String bindTarget;

	/** サービスレジストリ(JVMで1つ) - rmiregistryの代わりとして使用するため */
	private static final HashMap<String, Service> registry = new HashMap<String, Service>();

	/** 分散ネットワークのエンドポイントたるDSR */
	private RSSDistributedServiceRegistry dsr = null;

	/**
	 * コンストラクタ
	 * @param bt バインドターゲット(この実装の場合はdsruri)
	 */
	public HashMapLookup(String bt) {
		dsr = (RSSDistributedServiceRegistry)registry.get(bt);
		bindTarget = bt;
	}

	/**
	 * 分散サービスをバインドします．
	 * バインド先は，広域分散リソースネットワークが決定します．
	 * @return 実際にバインドされた際の識別文字列
	 * @throws Exception バインドに失敗した
	 */
	public String bind(int type, Object o) throws Exception {
		Service r = (Service)o;

		// 分散サービスレジストリに対して，新しいサービスを登録する
		String node = dsr.bind(type, r);
		// ローカルレジストリにサーバーを登録する
		registry.put(node, r);

		return node;
	}
	/**
	 * 分散サービスをアンバインドします．
	 * @param type サービスのタイプ
	 * @param name 登録解除したいノード名
	 * @throws Exception アンバインドに失敗した
	 */
	public void unbind(int type, String name) throws Exception {
		dsr.unbind(type, name);
		registry.remove(name);
	}

	/**
	 * DSRをレジストリに登録する
	 * @param stub DSRのインスタンス
	 * @throws Exception 登録に失敗した
	 */
	public void register(RSSDistributedServiceRegistry stub) throws Exception {
		registry.put(stub.getName(), stub);
		dsr = stub;
	}

	/**
	 * 広域分散リソースネットワークから，特定の種類のサービスを発見します．
	 * @param name 発見するサービスの種類
	 * @return 発見されたサービスのスタブ
	 * @throws Exception 発見に失敗した
	 */
	public Object lookup(int type) throws Exception {
		// DSRに問い合わせる
		return dsr.getService(type);
	}

	/**
	 * 指定ノードIDのサービスを返します．
	 * @param nodeId ノードID
	 * @return サービスのスタプ
	 * @throws Exception ルックアップに失敗した
	 */
	public Service lookup(String nodeId) throws Exception {
		if(dsr.getName().equals(nodeId)) {
			return dsr;
		} else {
			return dsr.getService(nodeId);
		}
	}

	/**
	 * この発見サービスのバインドターゲット(接続先ノード)名を返す
	 * @return バインドターゲット名
	 */
	public String[] services(int type) throws Exception {
		return dsr.services(type);
	}

	/**
	 * この発見サービスのバインドターゲット(接続先ノード)名を返す
	 * @return バインドターゲット名
	 */
	public String getBindTargetName() {
		return bindTarget;
	}

	/**
	 * この発見サービスのバインドターゲットに対して、ルーティングテーブルの更新を指示する
	 * @throws Exception 更新処理中に発生した例外
	 */
	public void configure() throws Exception {
		dsr.configure();
	}

	/**
	 * リモート参照をお互いに共有する
	 * @param stub 登録してもらうスタブ
	 * @throws RemoteException 登録に失敗した
	 */
	public Service hug(Service stub) throws Exception {
		dsr.bind(RSS_SERVID_SERVICE_LOCATER, stub);
		return dsr;
	}

	/**
	 * リモート参照をお互いに共有する
	 * 登録名を明示的に指定できる
	 * @param stub 登録してもらうスタブ
	 * @param name サービス名
	 * @return RemoteException 登録に失敗した
	 */
	public Service hug(String name, Service stub) throws Exception {
		dsr.bind(RSS_SERVID_SERVICE_LOCATER, name, stub);
		return dsr;
	}

}
