/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: SeqLogicalOperatorTest.java,v 1.1 2005/05/31 14:38:20 rampil Exp $
 */
package org.logical_paradox.koike.rss.search.lo;

import java.util.Iterator;

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

import junit.framework.TestCase;

/**
 * SEQ擬似論理演算子のテスト
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.1 $
 */
public class SeqLogicalOperatorTest extends TestCase {
	/** 論理演算子 */
	private LogicalOperator op;

	/**
	 * Constructor for SeqLogicalOperatorTest.
	 * @param arg0
	 */
	public SeqLogicalOperatorTest(String arg0) {
		super(arg0);
	}
	/**
	 * 引数なしの場合のテスト
	 */
	public void testNoArgument() throws LogicalOperationException {
		// null
		assertNull(op.execute(null));
		// 配列が空
		assertNull(op.execute(new KoikeIndexResultSet[]{}));
	}
	/**
	 * 転置インデックスは存在するが，位置情報が全くない場合
	 */
	public void testNoLocation() throws LogicalOperationException {
		KoikeIndexResultSet rs1 = new KoikeIndexResultSet();
		rs1.addInvertedIndex(new InvertedIndex("NODE00001", 100, 0));
		rs1.addInvertedIndex(new InvertedIndex("NODE00002", 255, 0));

		KoikeIndexResultSet rs2 = new KoikeIndexResultSet();
		rs2.addInvertedIndex(new InvertedIndex("NODE00003", 100, 0));

		KoikeIndexResultSet[] result = op.execute(new KoikeIndexResultSet[]{rs1, rs2});
		assertNull(result);
	}
	/**
	 * 引数1件だけ指定する場合のテスト
	 * 引数として渡したものがそのまま回答として返ってくる
	 */
	public void testOperationUsingSingleArgument() throws LogicalOperationException {
		KoikeIndexResultSet rs = new KoikeIndexResultSet();
		InvertedIndex ii1 = new InvertedIndex("NODE10000", 10, 13);
		ii1.addLocation(new Location("NODE10000", 640, 1033));
		ii1.addLocation(new Location("NODE10000", 655, 1092));
		InvertedIndex ii2 = new InvertedIndex("NODE10001", 99, 15);

		rs.addInvertedIndex(ii1);
		rs.addInvertedIndex(ii2);

		// 実行
		KoikeIndexResultSet[] results = op.execute(new KoikeIndexResultSet[]{rs});

		assertSame(results[0], rs);
		assertFalse(results[0].isEmpty());

		Iterator iii = results[0].iteratorInvertedIndexes();
		assertEquals(ii1, iii.next());
		assertEquals(ii2, iii.next());


		assertTrue(results[0].isLocated("NODE10000", 640, 1033));
		assertTrue(results[0].isLocated("NODE10000", 655, 1092));
	}
	/**
	 * 同じドキュメント中に複数個一致するものがある場合のテスト
	 */
	public void testOperationPattern01() throws LogicalOperationException {
		// 索引語1
		KoikeIndexResultSet rs1 = new KoikeIndexResultSet();
		InvertedIndex ii11 = new InvertedIndex("NODE00001", 10,20);
		ii11.addLocation(new Location("NODE00001", 641, 1024));		// ○
		ii11.addLocation(new Location("NODE00001", 641, 1055));		// ×
		rs1.addInvertedIndex(ii11);

		// 索引語2
		KoikeIndexResultSet rs2 = new KoikeIndexResultSet();
		InvertedIndex ii21 = new InvertedIndex("NODE00011", 10, 20);
		ii21.addLocation(new Location("NODE00011", 642, 199));			// ×

		InvertedIndex ii22 = new InvertedIndex("NODE00001", 10, 2);
		ii22.addLocation(new Location("NODE00001", 641, 1025));		// ○

		rs2.addInvertedIndex(ii21);
		rs2.addInvertedIndex(ii22);

		// 索引語3
		KoikeIndexResultSet rs3 = new KoikeIndexResultSet();
		InvertedIndex ii31 = new InvertedIndex("NODE10001", 1, 3);
		ii31.addLocation(new Location("NODE10001", 64, 199));			// ×
		ii31.addLocation(new Location("NODE10001", 64, 203));			// ×
		ii31.addLocation(new Location("NODE10001", 65, 1099));			// ×

		InvertedIndex ii32 = new InvertedIndex("NODE00001", 10, 2);
		ii32.addLocation(new Location("NODE00001", 641, 1026));		// ○
		rs3.addInvertedIndex(ii31);
		rs3.addInvertedIndex(ii32);

		// 実行
		KoikeIndexResultSet[] results = op.execute(new KoikeIndexResultSet[]{rs1, rs2, rs3});

		// 結果セット数の妥当性判定
		assertNotNull(results);
		assertEquals(1, results.length);
		assertNotSame(rs1, results[0]);
		assertNotSame(rs2, results[0]);
		assertNotSame(rs3, results[0]);

		assertFalse(results[0].isEmpty());
		assertTrue(results[0].isLocated("NODE00001", 641, 1024));

		Iterator it = results[0].iteratorInvertedIndexes();
		assertTrue(it.hasNext());
		InvertedIndex iidx = (InvertedIndex)it.next();
		Location beginningPoint = iidx.getLocation(641, 1024);
		assertEquals(new Location("NODE00001", 641, 1024), beginningPoint);

		iidx.removeLocation(beginningPoint);
		assertFalse(iidx.hasLocations());
	}
	/**
	 * いくつか位置情報が存在するものの、一部のせいで一致しない場合
	 */
	public void testOperationPattern02() throws LogicalOperationException {
		// 索引語1
		KoikeIndexResultSet rs1 = new KoikeIndexResultSet();
		InvertedIndex ii11 = new InvertedIndex("NODE00001", 10, 2);
		ii11.addLocation(new Location("NODE00001", 641, 1024));		// ○
		ii11.addLocation(new Location("NODE00001", 641, 1055));		// ×
		rs1.addInvertedIndex(ii11);

		// 索引語2
		KoikeIndexResultSet rs2 = new KoikeIndexResultSet();
		InvertedIndex ii21 = new InvertedIndex("NODE00011", 10, 4);
		ii21.addLocation(new Location("NODE00011", 642, 199));			// ×

		InvertedIndex ii22 = new InvertedIndex("NODE00001", 10, 2);
		ii22.addLocation(new Location("NODE00001", 641, 1025));		// ○

		rs2.addInvertedIndex(ii21);
		rs2.addInvertedIndex(ii22);

		// 索引語3
		KoikeIndexResultSet rs3 = new KoikeIndexResultSet();
		InvertedIndex ii31 = new InvertedIndex("NODE10001", 1, 3);
		ii31.addLocation(new Location("NODE10001", 64, 199));			// ×
		ii31.addLocation(new Location("NODE10001", 64, 203));			// ×
		ii31.addLocation(new Location("NODE10001", 65, 1099));			// ×

		InvertedIndex ii32 = new InvertedIndex("NODE00001", 10, 2);
		ii32.addLocation(new Location("NODE00001", 641, 1029));		// ×
		rs3.addInvertedIndex(ii31);
		rs3.addInvertedIndex(ii32);

		// 実行
		KoikeIndexResultSet[] results = op.execute(new KoikeIndexResultSet[]{rs1, rs2, rs3});

		// 結果セット数の妥当性判定
		assertNull(results);
	}
	/**
	 * テストの初期化
	 */
	protected void setUp() throws Exception {
		super.setUp();
		op = LogicalOperatorFactory.getOperator(Element.TYPE_SEQ);
	}

}
