/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: SeqLogicalOperator.java,v 1.4 2006/02/27 14:20:33 akabane Exp $
 */
package org.logical_paradox.koike.rss.search.lo;

import java.util.Iterator;

import org.logical_paradox.koike.core.search.InvertedIndex;
import org.logical_paradox.koike.core.search.KoikeIndexResultSet;
import org.logical_paradox.koike.core.search.Location;

/**
 * SEQ演算子(オリジナル)
 * 指定された要素が全て連続している必要がある
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.4 $
 */
public class SeqLogicalOperator implements LogicalOperator {
	/**
	 * インデックスシステムの回答セットに対して論理演算を適用し，結果セットを返す
	 * @param resultset 演算対象
	 * @return 演算結果の配列(それぞれの回答セットに対して論理演算を適用した結果を配列で返す)
	 */
	public KoikeIndexResultSet[] execute(KoikeIndexResultSet[] resultset) throws LogicalOperationException {
		if(resultset == null || resultset.length == 0) {
			// 引数自体がnullまたは空配列
			return null;
		} else if(resultset.length == 1) {
			// 引数が1件の場合、引数=答え
			return new KoikeIndexResultSet[] {resultset[0] };
		}
		// 第1索引語の位置情報をもとにして、追随する位置情報を調べる
		KoikeIndexResultSet base = resultset[0];
		KoikeIndexResultSet rs = new KoikeIndexResultSet();

		for(Iterator it = base.iteratorInvertedIndexes(); it.hasNext();) {
			// 第1引数の転置インデックスのコピーを作成して，それを元に判定する
			InvertedIndex iidx = new InvertedIndex((InvertedIndex)it.next());
			for(Iterator locations = iidx.iteratorLocations(); locations.hasNext();) {
				Location location = (Location)locations.next();
				// この位置の次の位置から、連続して索引語が配置されているかどうかを調べる
				int offset = location.getOffset() +1;
				boolean found = true;
				for(int i = 1; found == true && i < resultset.length; i++, offset++) {
					if(resultset[i].isLocated(location.getNodeId(), location.getDocno(), offset) == true) {
						// あった
					} else {
						// なかったので直ちに処理を中断
						found = false;
					}
				}
				if(found == false) {
					// 索引語が連続して配置されていなかったので、位置情報を破棄する
					iidx.removeLocation(location);
				}
			}
			// この転置インデックスが位置情報を持っている場合、演算適用結果があるという意味
			// なので、結果セットに追加する
			if(iidx.getDocumentAvailability() > 0L) {
				rs.addInvertedIndex(iidx);
			}
		}

		if(rs.isEmpty() == true) {
			// 結局位置情報がなかった
			return null;
		}
		// この演算子は結果を1つだけ返す(=第1索引語の結果)
		KoikeIndexResultSet[] result = new KoikeIndexResultSet[1];
		result[0] = rs;

		return result;
	}
}
