/*
 * $Id: MySQLConcreteInterfaceFactory.java,v 1.4 2006/02/12 15:31:42 rampil Exp $
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 *
 */
package org.logical_paradox.koike.rss;

import java.rmi.RemoteException;
import java.util.Iterator;
import org.logical_paradox.koike.core.ConcreteInterfaceFactory;
import org.logical_paradox.koike.core.document.DocumentAccessor;
import org.logical_paradox.koike.core.indexer.IndexAccessor;
import org.logical_paradox.koike.core.search.SearchConditionOptimizer;
import org.logical_paradox.koike.rss.index.MySQLDocumentAccessor;
import org.logical_paradox.koike.rss.index.MySQLIndexAccessor;
import org.logical_paradox.rss.dsr.RSSDistributedServiceRegistry;
import org.logical_paradox.rss.lookup.LookupFactory;
import org.logical_paradox.rss.oqs4r.OQSConnection;
import org.logical_paradox.rss.oqs4r.ObjectQueueServer;
import org.logical_paradox.rss.rcm.accessor.mysql.validator.ConnectionValidator;

/**
 * MySQLをストレージとして利用するkoike用インターフェースファクトリ
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.4 $
 */
public class MySQLConcreteInterfaceFactory extends ConcreteInterfaceFactory {
	/** データベース接続監視間隔 */
	public static final long CONNECTION_WATCH_INTERVAL = 120 * 1000;
	/** データベース接続監視スレッド */
	private ConnectionValidator validator;
	/** ドキュメントアクセサ */
	private DocumentAccessor documentAccessor;

	/**
	 * コンストラクタ．
	 * @param param 初期化パラメータ
	 * @throws Exception 初期化に失敗した
	 */
	public MySQLConcreteInterfaceFactory(String param) throws Exception {
		super(param);
	}
	/**
	 * ファクトリを初期化します
	 * @throws Exception 初期化処理中に
	 */
	public void setup() throws Exception {
		if(validator == null) {
			validator = new ConnectionValidator(CONNECTION_WATCH_INTERVAL);
			validator.start();
		}
		documentAccessor = new MySQLDocumentAccessor(validator);
	}
	/**
	 * 初期化されたドキュメントアクセサを生成して返す
	 * @return 生成されたドキュメントアクセサ
	 * @throws Exception 生成または初期化に失敗した場合に発生する例外
	 */
	public DocumentAccessor getDocumentAccessor() throws Exception {
		return documentAccessor;
	}
	/**
	 * 初期化されたインデックスアクセサを生成して返す
	 * @return 生成されたインデックスアクセサ
	 * @throws Exception 生成または初期化に失敗した場合に発生する例外
	 */
	public IndexAccessor getIndexAccessor() throws Exception {
		return new MySQLIndexAccessor(validator);
	}
	/**
	 * リモートキューにシーケンシャルにアクセスする方法を生成して返す
	 * @return イテレータ
	 */
	public Iterator getRemoteQueueIterator() throws Exception {
		// リモート参照を不必要に作成しないようにするために
		// 全ての処理をこのメソッド内で完結させる
		ObjectQueueServer oqs4r = (ObjectQueueServer)LookupFactory.getLookup(getInitparam()).lookup(RSSDistributedServiceRegistry.RSS_SERVID_OQS4R);
		OQSConnection con = oqs4r.getConnection();

		// リモートキューを参照しているイテレータを作成して返す．
		Iterator it = new OQSConnectionIterator(con);
		oqs4r = null;
		return it;
	}
	/**
	 * 検索条件オプティマイザーを生成して返す
	 * @return 検索条件オプティマイザー
	 * @throws Exception 生成中に発生した例外
	 */
	public SearchConditionOptimizer getOptimizer() throws Exception {
		return null;
	}

	/**
	 * リモートキューに接続するタイプのイテレータ．
	 * @author satoshi akabane@logical-paradox.org
	 * @version $Revision: 1.4 $
	 */
	class OQSConnectionIterator implements Iterator {
		/** 接続オブジェクト */
		private final OQSConnection connection;

		/**
		 * コンストラクタ．
		 * @param con 接続オブジェクト
		 */
		protected OQSConnectionIterator(OQSConnection con) {
			connection = con;
		}
		/**
		 * 要素を削除する．
		 * この操作はサポートされていないので例外を投げる．
		 */
		public void remove() {
			throw new UnsupportedOperationException("class OQSConnectionIterator doesn't support remove item.");
		}
		/**
		 * 次の要素があるかどうかを返す．
		 * @return true:ある / false:ない
		 */
		public boolean hasNext() {
			try {
				return connection.hasNext();
			} catch (RemoteException e) {
				return false;
			}
		}
		/**
		 * 次の要素を返す．
		 * @return 次の要素
		 */
		public Object next() {
			try {
				return connection.next();
			} catch (RemoteException e) {
				return null;
			}
		}
	}
}
