package net.yher2.workstyle.manager;

import java.io.File;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.yher2.commons.io.Classpath;
import net.yher2.commons.lang.DateUtils;
import net.yher2.commons.lang.Pager;
import net.yher2.commons.torque.Transaction;
import net.yher2.workstyle.FileData;
import net.yher2.workstyle.TaskQuery;
import net.yher2.workstyle.exception.NotFoundException;
import net.yher2.workstyle.test.DBTestCase;
import net.yher2.workstyle.torque.AttachedFile;
import net.yher2.workstyle.torque.AttachedFilePeer;
import net.yher2.workstyle.torque.FilePeer;
import net.yher2.workstyle.torque.Status;
import net.yher2.workstyle.torque.StatusPeer;
import net.yher2.workstyle.torque.Tag;
import net.yher2.workstyle.torque.TagPeer;
import net.yher2.workstyle.torque.Task;
import net.yher2.workstyle.torque.TaskCommentPeer;
import net.yher2.workstyle.torque.TaskFileRelationPeer;
import net.yher2.workstyle.torque.TaskPeer;
import net.yher2.workstyle.torque.bean.AttachedFileBean;
import net.yher2.workstyle.torque.bean.TaskBean;
import net.yher2.workstyle.torque.bean.TaskCommentBean;

import org.apache.commons.lang.StringUtils;
import org.apache.torque.NoRowsException;
import org.apache.torque.om.SimpleKey;
import org.apache.torque.util.Criteria;

public class TaskManagerTest extends DBTestCase {
	TaskManager manager = null;
	Connection con = null;
	Classpath testData = new Classpath("net/yher2/workstyle/manager/TaskManagerTest.xls");
	Date date = null;

	protected void setUp() throws Exception {
		super.setUp();
		super.prepare(testData);
		
		date = new Date();
		
		con = getConnection();
		con.setAutoCommit(false);
		manager = new TaskManager(con);
	}

	protected void tearDown() throws Exception {
		super.tearDown();
		Transaction.rollback(con);
		super.clear(testData);
	}
	
	public void testDelete_TASKテーブルからレコードを削除する() throws Exception {
		manager.delete(1);
		try {
			TaskPeer.retrieveByPK(1, con);
		} catch (NoRowsException e) {
			return;
		}
		fail();
	}
	public void testDelete_TASK_COMMENTテーブルから指定のタスクへのコメントを削除する() throws Exception {
		TaskBean task = manager.get(1);
		manager.delete(1);
		
		assertTrue(task.getTaskCommentBeans().size() > 0);
		for (TaskCommentBean comment : task.getTaskCommentBeans()) {
			try {
				TaskCommentPeer.retrieveByPK(comment.getCommentId(), con);
			} catch (NoRowsException e) {
				continue;
			}
			fail();
		}
	}
	public void testDelete_FILEテーブルから指定のタスクへの添付ファイルを削除する() throws Exception {
		TaskBean task = manager.get(1);
		manager.delete(1);
		
		assertTrue(task.getAttachedFileBeans().size() > 0);
		for (AttachedFileBean file : task.getAttachedFileBeans()) {
			try {
				FilePeer.retrieveByPK(file.getFileId(), con);
			} catch (NoRowsException e) {
				continue;
			}
			fail();
		}
	}
	public void testDelete_対象のタスクが存在しない場合はそのまま終了() throws Exception {
		try {
			manager.delete(0);
		} catch (Exception e) {
			fail();
		}
	}
	
	public void testGet() throws Exception {
		TaskBean result = manager.get(1);
		Task dbTask = TaskPeer.retrieveByPK(result.getTaskId(), con);
		
		assertEquals(dbTask.getContents(), result.getContents());
		assertEquals(dbTask.getEstimatedManHour(), result.getEstimatedManHour());
		assertEquals(dbTask.getStatusId(), result.getStatusId());
		assertEquals(dbTask.getTagList(), result.getTagList());
		assertEquals(dbTask.getUpdateDate(), result.getUpdateDate());
		
		assertNotNull(result.getStatusBean());
		assertNotNull(result.getTaskCommentBeans());
		assertNotNull(result.getAttachedFileBeans());
	}
	
	public void testGet_存在しない場合はNotFoundException() throws Exception {
		try {
			manager.get(0);
		} catch (NotFoundException e) {
			return;
		}
		fail();
	}

	public void testAdd_TASKテーブルにレコードを追加する() throws Exception {
		TaskBean task = prepareValidTask();
		TaskBean result = null;
		try {
			result = manager.add(task);
			
			assertTrue(result.getTaskId() != 0);
			Task dbTask = TaskPeer.retrieveByPK(result.getTaskId(), con);
			
			assertEquals(task.getContents(), result.getContents());
			assertEquals(task.getEstimatedManHour(), result.getEstimatedManHour());
			assertEquals(task.getStatusId(), result.getStatusId());
			assertEquals(task.getTagList(), result.getTagList());
			assertNotNull(result.getUpdateDate());

			assertEquals(result.getContents(), dbTask.getContents());
			assertEquals(result.getEstimatedManHour(), dbTask.getEstimatedManHour());
			assertEquals(result.getStatusId(), dbTask.getStatusId());
			assertEquals(result.getTagList(), dbTask.getTagList());
			assertEquals(result.getUpdateDate(), dbTask.getUpdateDate());
		} finally {
			remove(result);
		}
	}
	public void testAdd_存在しない場合はTAGテーブルにもレコードを追加する() throws Exception {
		TaskBean task = prepareValidTask();
		
		assertEquals(0, TagPeer.doSelectByName(task.getTagAsList(), con).size());

		TaskBean result = null;
		try {
			result = manager.add(task);
			
			assertTrue(task.getTagAsList().size() > 0);
			assertEquals(task.getTagAsList().size(), TagPeer.doSelectByName(task.getTagAsList(), con).size());
		} finally {
			remove(result);
		}
	}
	public void testAdd_statusIdが不正な場合はNormalに() throws Exception {
		TaskBean task = prepareValidTask();
		task.setStatusId(0);
		
		TaskBean result = null;
		try {
			result = manager.add(task);
			assertEquals(Status.NORMAL, result.getStatusId());
		} finally {
			remove(result);
		}
	}
	
	public void testAdd_まとめて追加_TASKテーブルにレコードが追加されていること2() throws Exception {
		TaskBean result = null;
		try {
			TaskBean task = prepareValidTask();
			FileData file = new FileData("test.file1", new byte[]{1}, ".");
			TaskCommentBean comment = prepareValidComment();
			
			result = manager.add(task, comment, file);
			
			TaskPeer.retrieveByPK(result.getTaskId(), con);
		} finally {
			remove(result);
		}
	}
	public void testAdd_まとめて追加_COMMENTテーブルにレコードが追加されていること() throws Exception {
		TaskBean result = null;
		try {
			TaskBean task = prepareValidTask();
			FileData file = new FileData("test.file1", new byte[]{1}, ".");
			TaskCommentBean comment = prepareValidComment();
			
			result = manager.add(task, comment, file);
			
			Criteria criteria = new Criteria();
			criteria.add(TaskCommentPeer.TASK_ID, result.getTaskId());
			assertTrue(TaskCommentPeer.doSelect(criteria, con).size() > 0);
		} finally {
			remove(result);
		}
	}
	public void testAdd_まとめて追加_FILEテーブルにレコードが追加されていること() throws Exception {
		TaskBean result = null;
		try {
			TaskBean task = prepareValidTask();
			FileData file = new FileData("test.file1", new byte[]{1}, ".");
			TaskCommentBean comment = prepareValidComment();
			
			result = manager.add(task, comment, file);
			
			Criteria criteria = new Criteria();
			criteria.add(AttachedFilePeer.TASK_ID, result.getTaskId());
			assertTrue(AttachedFilePeer.doSelect(criteria, con).size() > 0);
		} finally {
			remove(result);
		}
	}
	public void testAdd_まとめて追加_実ファイルが作成されていること() throws Exception {
		TaskBean result = null;
		try {
			TaskBean task = prepareValidTask();
			FileData file = new FileData("test.file1", new byte[]{1}, ".");
			TaskCommentBean comment = prepareValidComment();
			
			result = manager.add(task, comment, file);
			
			Criteria criteria = new Criteria();
			criteria.add(AttachedFilePeer.TASK_ID, result.getTaskId());
			List<AttachedFile> fileList = AttachedFilePeer.doSelect(criteria, con);
			for (AttachedFile dbFile : fileList) {
				File sysFile = new File(dbFile.getPath());
				assertTrue(sysFile.exists());
			}
		} finally {
			remove(result);
		}
	}
	public void testAdd_まとめて追加_commentがnullでもちゃんと動くこと() throws Exception {
		TaskBean result = null;
		try {
			TaskBean task = prepareValidTask();
			FileData file = new FileData("test.file1", new byte[]{1}, ".");
			
			result = manager.add(task, null, file);
			
			Task dbTask = TaskPeer.retrieveByPK(result.getTaskId(), con);
			assertEquals(0, dbTask.getTaskComments(con).size());
		} finally {
			remove(result);
		}
	}
	public void testAdd_まとめて追加_fileがnullでもちゃんと動くこと() throws Exception {
		TaskBean result = null;
		try {
			TaskBean task = prepareValidTask();
			TaskCommentBean comment = prepareValidComment();
			
			result = manager.add(task, comment, null);
			
			Task dbTask = TaskPeer.retrieveByPK(result.getTaskId(), con);
			assertEquals(0, dbTask.getAttachedFiles(con).size());
		} finally {
			remove(result);
		}
	}
	public void testAdd_まとめて追加_存在しない場合はTAGテーブルにもレコードを追加する() throws Exception {
		TaskBean task = prepareValidTask();
		
		assertEquals(0, TagPeer.doSelectByName(task.getTagAsList(), con).size());

		TaskBean result = null;
		try {
			result = manager.add(task, null, null);
			
			assertTrue(task.getTagAsList().size() > 0);
			assertEquals(task.getTagAsList().size(), TagPeer.doSelectByName(task.getTagAsList(), con).size());
		} finally {
			remove(result);
		}
	}
	public void testAdd_まとめて追加_statusIdが不正な場合はNormalに() throws Exception {
		TaskBean task = prepareValidTask();
		task.setStatusId(0);
		
		TaskBean result = null;
		try {
			result = manager.add(task, null, null);
			assertEquals(Status.NORMAL, result.getStatusId());
		} finally {
			remove(result);
		}
	}
	public void testAddTag_指定のタグがTaskに追加されていること() throws Exception {
		Thread.sleep(1000);
		TaskBean task = manager.get(1);
		manager.addTag(task.getTaskId(), "テストのタグ");
		
		TaskBean result = manager.get(task.getTaskId()); 
		assertEquals(task.getTagList()+Tag.format("テストのタグ"), 
				result.getTagList());
		
		assertTrue(result.getUpdateDate().after(date));
	}
	public void testAddTag_指定のタグが空やnullの場合何もしない() throws Exception {
		TaskBean task = manager.get(1);
		manager.addTag(task.getTaskId(), "");
		assertEquals(task.getTagList(), manager.get(task.getTaskId()).getTagList());

		manager.addTag(task.getTaskId(), null);
		assertEquals(task.getTagList(), manager.get(task.getTaskId()).getTagList());
	}
	public void testAddTag_タスクが存在しない場合はNotFoundException() throws Exception {
		try {
			manager.addTag(0, "タグ");
		} catch (NotFoundException e) {
			return;
		}
		fail();
	}
	public void testDeleteTag_指定のタグがタスクから削除されていること() throws Exception {
		TaskBean task = manager.get(1);
		String testTag = task.getTagAsList().get(0);
		
		manager.deleteTag(task.getTaskId(), testTag);
		
		TaskBean result = manager.get(task.getTaskId());
		for (String tag : result.getTagAsList()) {
			assertFalse(StringUtils.equals(testTag, tag));
		}
	}
	public void testDeleteTag_存在しないタグが指定された場合は何もしない() throws Exception {
		TaskBean task = manager.get(1);
		manager.deleteTag(task.getTaskId(), "存在しないタグ");
		
		TaskBean result = manager.get(task.getTaskId());
		assertEquals(task.getTagList(), result.getTagList());
	}
	public void testDeleteTag_指定のタグがnullや空文字の場合は何もしない() throws Exception {
		TaskBean task = manager.get(1);
		
		manager.deleteTag(task.getTaskId(), "");
		TaskBean result = manager.get(task.getTaskId());
		assertEquals(task.getTagList(), result.getTagList());

		manager.deleteTag(task.getTaskId(), null);
		result = manager.get(task.getTaskId());
		assertEquals(task.getTagList(), result.getTagList());
	}
	public void testDeleteTag_タスクが存在しない場合はNotFoundException() throws Exception {
		try {
			manager.deleteTag(0, "タグ");
		} catch (NotFoundException e) {
			return;
		}
		fail();
	}
	
	public void testUpdateStatus_指定のタスクが指定の状態になること() throws Exception {
		Thread.sleep(1000);
		manager.updateStatus(1, Status.FINISHED);
		TaskBean result = manager.get(1);
		assertEquals(Status.FINISHED, result.getStatusId());
		assertTrue(result.getUpdateDate().after(date));

	}
	public void testUpdateStatus_指定のタスクが存在しない場合はNotFoundException() throws Exception {
		try {
			manager.updateStatus(0, Status.FINISHED);
		} catch (NotFoundException e) {
			return;
		}
		fail();
	}
	public void testUpdateStatus_指定の状態が存在しない場合は何もしない() throws Exception {
		TaskBean task = manager.get(1);
		int original = task.getStatusId();
		task.setStatusId(0);
		manager.updateStatus(task.getTaskId(), 0);
		assertEquals(original, manager.get(task.getTaskId()).getStatusId());
	}
	
	public void testUpdate_まとめて更新_TASKテーブルのレコードを更新する() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		task.setContents("変更後");
		task.setTagList("[変更後のテスト]");
		TaskCommentBean comment = prepareValidComment();
		FileData file = new FileData("test.file1", new byte[]{1}, ".");
		
		TaskBean result = null;
		try {
			result = manager.update(task, comment, file);
			assertEquals(task.getContents(), result.getContents());
			assertEquals(task.getTagList(), result.getTagList());
		} finally {
			remove(result);
		}
	}

	public void testUpdate_まとめて更新_新しいタグの場合はTAGテーブルにレコードを追加する() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		task.setContents("変更後");
		task.setTagList("[変更後のテスト]");
		TaskCommentBean comment = prepareValidComment();
		FileData file = new FileData("test.file1", new byte[]{1}, ".");
		
		TaskBean result = null;
		
		try {
			result = manager.update(task, comment, file);
			
			Criteria criteria = new Criteria();
			criteria.add(TagPeer.NAME, task.getTagAsList().get(0));
			assertEquals(1, TagPeer.doSelect(criteria, con).size());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_まとめて更新_TASK_COMMENTテーブルにレコードが追加されていること() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		task.setContents("変更後");
		task.setTagList("[変更後のテスト]");
		TaskCommentBean comment = prepareValidComment();
		FileData file = new FileData("test.file1", new byte[]{1}, ".");
		
		TaskBean result = null;
		
		try {
			result = manager.update(task, comment, file);
			assertEquals(1, manager.get(result.getTaskId()).getTaskCommentBeans().size());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_まとめて更新_FILEテーブルとTASK_FILE_RELATIONにレコードが追加されていること() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		task.setContents("変更後");
		task.setTagList("[変更後のテスト]");
		TaskCommentBean comment = prepareValidComment();
		FileData file = new FileData("test.file1", new byte[]{1}, ".");
		
		TaskBean result = null;
		
		try {
			result = manager.update(task, comment, file);
			assertEquals(1, manager.get(result.getTaskId()).getAttachedFileBeans().size());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_まとめて更新_実ファイルが作成されていること() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		task.setContents("変更後");
		task.setTagList("[変更後のテスト]");
		TaskCommentBean comment = prepareValidComment();
		FileData file = new FileData("test.file1", new byte[]{1}, ".");
		
		TaskBean result = null;
		
		try {
			result = manager.update(task, comment, file);
			File sysFile = new File(
					manager.get(task.getTaskId()).getAttachedFileBeans().get(0).getPath());
			assertTrue(sysFile.exists());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_まとめて更新_コメントがnullの場合もOK() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		FileData file = new FileData("test.file1", new byte[]{1}, ".");
		
		TaskBean result = null;
		
		try {
			result = manager.update(task, null, file);
			assertEquals(0, manager.get(result.getTaskId()).getTaskCommentBeans().size());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_まとめて更新_ファイルがnullの場合もOK() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		TaskCommentBean comment = prepareValidComment();
		
		TaskBean result = null;
		
		try {
			result = manager.update(task, comment, null);
			assertEquals(0, manager.get(result.getTaskId()).getAttachedFileBeans().size());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_まとめて更新_statusIdが不正な場合はstatusは元のまま() throws Exception {
		TaskBean task = manager.add(prepareValidTask());
		int expected = task.getStatusId();
		task.setStatusId(0);
		
		TaskBean result = null;
		try {
			result = manager.update(task, null, null);
			assertEquals(expected, result.getStatusId());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_まとめて更新_対象のタスクが存在しない場合はNotFoundException() throws Exception {
		TaskBean task = prepareValidTask();
		task.setTaskId(0);
		
		TaskBean result = null;
		try {
			result = manager.update(task, null, null);
		} catch (NotFoundException e) {
			return;
		} finally {
			remove(result);
		}
		fail();
	}

	public void testUpdate_TASKテーブルのレコードを更新する() throws Exception {
		Thread.sleep(1000);
		TaskBean task = prepareValidTask();
		task.setTaskId(1);
		TaskBean result = null;
		try {
			result = manager.update(task);
			
			assertTrue(result.getTaskId() != 0);
			Task dbTask = TaskPeer.retrieveByPK(result.getTaskId(), con);
			
			assertEquals(task.getContents(), result.getContents());
			assertEquals(task.getEstimatedManHour(), result.getEstimatedManHour());
			assertEquals(task.getStatusId(), result.getStatusId());
			assertEquals(task.getTagList(), result.getTagList());
			assertNotNull(result.getUpdateDate());

			assertEquals(result.getContents(), dbTask.getContents());
			assertEquals(result.getEstimatedManHour(), dbTask.getEstimatedManHour());
			assertEquals(result.getStatusId(), dbTask.getStatusId());
			assertEquals(result.getTagList(), dbTask.getTagList());
			assertEquals(result.getUpdateDate(), dbTask.getUpdateDate());
			
			assertTrue(result.getUpdateDate().after(date));
		} finally {
			remove(result);
		}
	}
	public void testUpdate_存在しない場合はTAGテーブルにもレコードを追加する() throws Exception {
		TaskBean task = prepareValidTask();
		task.setTaskId(1);
		
		assertEquals(0, TagPeer.doSelectByName(task.getTagAsList(), con).size());

		TaskBean result = null;
		try {
			result = manager.update(task);
			
			assertTrue(task.getTagAsList().size() > 0);
			assertEquals(task.getTagAsList().size(), TagPeer.doSelectByName(task.getTagAsList(), con).size());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_statusIdが不正な場合はstatusを元のままに() throws Exception {
		TaskBean task = prepareValidTask();
		int expected = task.getStatusId();
		task.setTaskId(1);
		task.setStatusId(0);
		
		TaskBean result = null;
		try {
			result = manager.update(task);
			assertEquals(expected, result.getStatusId());
		} finally {
			remove(result);
		}
	}
	public void testUpdate_対象のタスクが存在しない場合はNotFoundException() throws Exception {
		TaskBean task = prepareValidTask();
		task.setTaskId(0);
		
		TaskBean result = null;
		try {
			result = manager.update(task);
		} catch (NotFoundException e) {
			return;
		} finally {
			remove(result);
		}
		fail();
	}
	private void remove(TaskBean task) throws Exception {
		if (task == null) return;
		
		Criteria criteria = new Criteria();
		criteria.add(TaskCommentPeer.TASK_ID, task.getTaskId());
		TaskCommentPeer.doDelete(criteria, con);
		
		Task dbTask = manager.getDBModel(task.getTaskId());
		deleteAttachedFile(dbTask.getAttachedFiles(con));
		
		TaskPeer.doDelete(SimpleKey.keyFor(task.getTaskId()), con);
		
		criteria.clear();
		criteria.add(TaskCommentPeer.TASK_ID, task.getTaskId());
		TaskCommentPeer.doSelect(criteria, con);
		
		criteria.clear();
		criteria.add(AttachedFilePeer.TASK_ID, task.getTaskId());
		deleteAttachedFile(AttachedFilePeer.doSelect(criteria, con));

		List<String> tagList = task.getTagAsList();
		if (tagList.size() > 0) {
			criteria.clear();
			criteria.addIn(TagPeer.NAME, task.getTagAsList());
			TagPeer.doDelete(criteria, con);
		}
	}
	private void deleteAttachedFile(List<AttachedFile> fileList) throws Exception {
		if (fileList.isEmpty()) return;
		
		List<Integer> fileIdList = new ArrayList<Integer>();
		for (AttachedFile file : fileList) {
			fileIdList.add(file.getFileId());
			File sysFile = new File(file.getPath());
			sysFile.delete();
		}
		Criteria criteria = new Criteria();
		criteria.addIn(TaskFileRelationPeer.FILE_ID, fileIdList);
		TaskFileRelationPeer.doDelete(criteria, con);
		
		criteria.clear();
		criteria.addIn(FilePeer.FILE_ID, fileIdList);
		FilePeer.doDelete(criteria, con);
	}
	private TaskBean prepareValidTask() {
		TaskBean task = new TaskBean();
		task.setContents("タスクの内容");
		task.setEstimatedManHour(10);
		task.setStatusId(Status.FINISHED);
		task.setTagList("[タスク追加テスト１][タスク追加テスト2]");
		return task;
	}
	
	private TaskCommentBean prepareValidComment() {
		TaskCommentBean comment = new TaskCommentBean();
		comment.setCommentator("人");
		comment.setContents("コメント");
		return comment;
	}

	public void testSearchDetail_詳細検索はコメントも同時に返す() throws Exception {
		TaskQuery query = new TaskQuery();
		Pager pager = new Pager();
		pager.setLimit(2);
		pager.setOffset(0);
		
		List<TaskBean> result = manager.searchDetail(query, pager);

		assertEquals(2, result.size());
		for (TaskBean task : result) {
			assertNotNull(task.getTaskCommentBeans());
		}
	}
	public void testSearchDetail_検索結果が0件の場合はサイズ0のリストを返す() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setStatus(new int[]{-1});
		
		List<TaskBean> result = manager.searchDetail(query, null);

		assertEquals(0, result.size());
	}

	public void testSearch_Pagerがある場合は指定のリミット数の検索結果を返す() throws Exception {
		TaskQuery query = new TaskQuery();
		Pager pager = new Pager();
		pager.setLimit(2);
		pager.setOffset(0);
		
		List<TaskBean> result = manager.search(query, pager);

		assertEquals(2, result.size());
	}
	public void testSearch_Pagerがある場合は指定のオフセット以降の検索結果を返す() throws Exception {
		TaskQuery query = new TaskQuery();
		Pager pager = new Pager();
		pager.setLimit(2);
		pager.setOffset(0);
		List<TaskBean> expected = manager.search(query, pager);

		pager = new Pager();
		pager.setLimit(2);
		pager.setOffset(1);
		List<TaskBean> result = manager.search(query, pager);

		assertEquals(expected.get(1).getTaskId(), result.get(0).getTaskId());
	}
	public void testSearch_Pagerがある場合は全検索結果数をrowCountとして返す() throws Exception {
		TaskQuery query = new TaskQuery();
		Pager pager = new Pager();
		pager.setLimit(2);
		pager.setOffset(0);
		
		manager.search(query, pager);
		
		assertEquals(getAllRowCount(), pager.getRowCount());
	}
	private int getAllRowCount() throws Exception {
		Criteria criteria = new Criteria();
		criteria.addJoin(TaskPeer.STATUS_ID, StatusPeer.STATUS_ID);
		return TaskPeer.doSelectCount(criteria, con);
	}
	public void testSearch_検索結果をSTATUS順にソートできる() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setOrder(TaskQuery.ORDER_BY_STATUS_ASC);
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		int sortOrder = 0;
		for (TaskBean task : result) {
			assertTrue(sortOrder <= task.getStatusBean().getSortOrder());
			sortOrder = task.getStatusBean().getSortOrder();
		}
	}
	public void testSearch_検索結果をID順にソートできる() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setOrder(TaskQuery.ORDER_BY_ID_ASC);
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		int sortOrder = 0;
		for (TaskBean task : result) {
			assertTrue(sortOrder <= task.getTaskId());
			sortOrder = task.getTaskId();
		}
	}
	public void testSearch_検索結果を見積時間順にソートできる() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setOrder(TaskQuery.ORDER_BY_MAN_HOUR_ASC);
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		double sortOrder = 0;
		for (TaskBean task : result) {
			assertTrue(sortOrder <= task.getEstimatedManHour());
			sortOrder = task.getEstimatedManHour();
		}
	}
	public void testSearch_検索結果を更新日時順にソートできる() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setOrder(TaskQuery.ORDER_BY_DATE_ASC);
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		Date sortOrder = DateUtils.parse(1974, 1, 1);
		for (TaskBean task : result) {
			assertTrue(sortOrder.getTime() <= task.getUpdateDate().getTime());
			sortOrder = task.getUpdateDate();
		}
	}
	public void testSearch_結果はStatusBeanも含む() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setStatus(new int[]{Status.ON_GOING});
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		for (TaskBean task : result) {
			assertNotNull(task.getStatusBean());
		}
	}
	public void testSearch_状態を条件に検索ができる() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setStatus(new int[]{Status.ON_GOING});
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		for (TaskBean task : result) {
			assertEquals(Status.ON_GOING, task.getStatusId());
		}
	}
	public void testSearch_複数の状態条件はOR検索() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setStatus(new int[]{Status.ON_GOING, Status.RAPID});
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		boolean rapidFlag = false;
		boolean onGoingFlag = false;
		for (TaskBean task : result) {
			assertTrue(
					task.getStatusId() == Status.ON_GOING ||
					task.getStatusId() == Status.RAPID);
			switch (task.getStatusId()) {
			case Status.ON_GOING:
				onGoingFlag = true;
				break;
			case Status.RAPID:
				rapidFlag = true;
				break;
			default:
				fail();
			}
		}
		assertTrue(rapidFlag);
		assertTrue(onGoingFlag);
	}
	public void testSearch_タグ条件は完全一致検索() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setTag(new String[]{"タグ条件"});
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		for (TaskBean task : result) {
			boolean tagFlag = false;
			for (String tag : task.getTagAsList()) {
				if (tag.toUpperCase().equals("タグ条件")) {
					tagFlag = true;
				}
			}
			assertTrue(tagFlag);
		}
	}
	public void testSearch_複数タグ条件はAND検索() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setTag(new String[]{"タグ条件", "タグ条件2"});
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		for (TaskBean task : result) {
			boolean tagFlag1 = false;
			boolean tagFlag2 = false;
			for (String tag : task.getTagAsList()) {
				if (tag.toUpperCase().equals("タグ条件")) {
					tagFlag1 = true;
				}
				if (tag.toUpperCase().equals("タグ条件2")) {
					tagFlag2 = true;
				}
			}
			assertTrue(tagFlag1 && tagFlag2);
		}
	}
	public void testSearch_キーワード条件はタスク内容とタグが対象の部分一致検索() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setKeyword("検索条件");
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		for (TaskBean task : result) {
			assertTrue(
					StringUtils.indexOf(task.getContents(), "検索条件") >= 0 ||
					StringUtils.indexOf(task.getTagList(), "検索条件") >= 0);
		}
	}
	public void testSearch_空白区切りのキーワード条件は複数キーワードのAND条件() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setKeyword("検索条件 やつ");
		
		List<TaskBean> result = manager.search(query, null);

		assertTrue(result.size() > 0);
		for (TaskBean task : result) {
			assertTrue(
					StringUtils.indexOf(task.getContents(), "検索条件") >= 0 ||
					StringUtils.indexOf(task.getTagList(), "検索条件") >= 0);
			assertTrue(
					StringUtils.indexOf(task.getContents(), "やつ") >= 0 ||
					StringUtils.indexOf(task.getTagList(), "やつ") >= 0);
		}
	}
	public void testSearch_最古更新日条件で検索できること() throws Exception {
		TaskQuery query = new TaskQuery();
		query.setDateFrom(new Date());
		
		assertEquals(0, manager.search(query, null).size());
		
		TaskBean task = prepareValidTask();
		manager.add(task);
		
		List<TaskBean> result = manager.search(query, null);
		assertTrue(result.size() > 0);
		for (TaskBean bean : result) {
			assertTrue(bean.getUpdateDate().getTime() > query.getDateFrom().getTime());
		}
	}
}
