/*
 * $Id: KoikeIndexResultSet.java,v 1.4 2006/02/21 13:16:51 akabane Exp $
 * Copyright (c) 2004 LOGICAL-PARADOX.ORG
 */
package org.logical_paradox.koike.core.search;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.logical_paradox.koike.core.KoikeConstant;

/**
 * インデックスサーバーに問い合わせた結果を保持するオブジェクト
 * ある索引語(あるいは検索語)が存在する位置情報を集約して格納する。<br>
 * 索引語ごとに別々のインスタンスによって表現される。
 * @author  satoshi akabane@logical-paradox.org
 * @version $Revision: 1.4 $
 */
public class KoikeIndexResultSet {
	/** 転置インデックスのリスト(位置情報) */
	private ArrayList<InvertedIndex> invertedIndexes = new ArrayList<InvertedIndex>();
	
	/**
	 * コンストラクタ
	 */
	public KoikeIndexResultSet() {
	}
	/**
	 * 指定された位置に索引語が配置されているかどうかを調べる
	 * @param nodeId ノードID
	 * @param docno 文書番号
	 * @param offset 先頭からのオフセット
	 * @return true:ある / false:ない
	 */
	public boolean isLocated(String nodeId, int docno, int offset) {
		// 指定されたブロックの転置インデックスを取得する
		int blkno = docno / KoikeConstant.INVERTED_INDEX_BLK_SIZE;
		InvertedIndex iidx = getInvertedIndex(nodeId, blkno);

		if(iidx == null) {
			// 転置インデックスそのものがなかった
			return false;
		}
		// 転置インデックス情報から、指定位置の情報を取得してみる
		Location found = iidx.getLocation(docno, offset);
		if(found == null) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * 転置インデックス情報を結果セットに対して追加する．
	 * 既に同じ位置情報が存在する場合，それを削除してから追加される．
	 * @param iidx 転置インデックス情報
	 */
	public void addInvertedIndex(InvertedIndex iidx) {
		synchronized(invertedIndexes) {
			// 既に同じ位置情報が存在する場合、それを削除してから追加する(二重登録防止)
			invertedIndexes.remove(iidx);
			invertedIndexes.add(iidx);
		}
	}
	/**
	 * 転置インデックス情報を結果セットに対して追加する．
	 * @param list 転置インデックス情報のリスト
	 */
	public void addInvertedIndexes(List<InvertedIndex> list) {
		invertedIndexes.addAll(list);
	}
	/**
	 * この結果セットの位置情報が空かどうかを返す
	 * @return true:空 / false:何か入っている
	 */
	public boolean isEmpty() {
		return invertedIndexes.size() == 0;
	}
	/**
	 * 転置インデックスの位置情報を初期化する
	 */
	public void clear() {
		invertedIndexes.clear();
	}
	/**
	 * 転置インデックスを返す(存在すれば)
	 * @param nodeId ノードID
	 * @param blkno ブロック番号
	 * @return 転置インデックス(null:存在せず)
	 */
	public InvertedIndex getInvertedIndex(String nodeId, int blkno) {
		return getInvertedIndex(new InvertedIndex(nodeId, blkno, 0L));	
	}
	/**
	 * 転置インデックスを返す(存在すれば)
	 * 転置インデックスで転置インデックスを検索しているが、これはInvertedIndexのequals()が<br>
	 * nodeidとblknoの組み合わせでtrue/falseを判定しているため、引数として与えられた転置インデックスと<br>
	 * 結果セットとして格納されている転置インデックスのdocuments値が違う場合があるため
	 * @param 転置インデックス
	 * @return 転置インデックス(null:存在せず)
	 */
	public InvertedIndex getInvertedIndex(InvertedIndex iidx) {
		synchronized(invertedIndexes) {
			int index = invertedIndexes.indexOf(iidx);
			if(index < 0) {
				return null;
			}
			return (InvertedIndex)invertedIndexes.get(index);
		}
	}
	/**
	 * 指定されたものと同じノードID,blknoを持つ転置インデックスをリストから除去する
	 */
	public void removeInvertedIndex(InvertedIndex iidx) {
		invertedIndexes.remove(iidx);
	}
	/**
	 * 転置インデックスのイテレータを返す
	 * @return 転置インデックスのイテレータ
	 */
	public Iterator iteratorInvertedIndexes() {
		return invertedIndexes.iterator();
	}
	/**
	 * 転置インデックスのリストを返す．
	 * ただし，変更できない．
	 * @return 転置インデックスのリスト
	 */
	public List getInvertedIndexes() {
		return Collections.unmodifiableList(invertedIndexes);
	}
	/**
	 * このインスタンスをコピーする
	 */
	@Override
	@SuppressWarnings("unchecked")
	public Object clone() throws CloneNotSupportedException {
		KoikeIndexResultSet result = new KoikeIndexResultSet();
		result.invertedIndexes = (ArrayList<InvertedIndex>)invertedIndexes.clone();

		return result;
	}

}
