package com.shin1ogawa.entity;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.junit.Before;
import org.junit.Test;

import com.shin1ogawa.AbstractRelasionShipTest;

public class ListPropertyEntityTest extends AbstractRelasionShipTest {

	@Before
	public void setUp() {
		super.setUp();
		createInitialData();
	}

	@Test
	public void stringProperties1() {
		PersistenceManager manager = getFactory().getPersistenceManager();
		Query query = manager.newQuery(ListPropertyEntity.class);
		query.setFilter("stringProperty == p1");
		query.declareParameters("java.lang.String p1");
		query.setOrdering("name asc");
		@SuppressWarnings("unchecked")
		List<ListPropertyEntity> list = (List<ListPropertyEntity>) query
				.execute("Google");
		assertThat(list.size(), is(equalTo(2)));
		assertThat(list.get(0).getName(), is(equalTo("entity1")));
		assertThat(list.get(1).getName(), is(equalTo("entity2")));
	}

	@Test
	public void stringProperties2() {
		PersistenceManager manager = getFactory().getPersistenceManager();
		Query query = manager.newQuery(ListPropertyEntity.class);
		query.setFilter("stringProperty == p1");
		query.declareParameters("java.lang.String p1");
		query.setOrdering("name asc");
		@SuppressWarnings("unchecked")
		List<ListPropertyEntity> list = (List<ListPropertyEntity>) query
				.execute("Apple");
		assertThat(list.size(), is(equalTo(1)));
		assertThat(list.get(0).getName(), is(equalTo("entity2")));
	}

	/**
	 * 値を保持しないlist propertyを検索する。
	 */
	@Test
	public void stringProperties3() {
		PersistenceManager manager = getFactory().getPersistenceManager();
		Query query = manager.newQuery(ListPropertyEntity.class);
		query.setFilter("stringProperty == p1");
		query.declareParameters("java.lang.String p1");
		query.setOrdering("name asc");
		@SuppressWarnings("unchecked")
		List<ListPropertyEntity> list = (List<ListPropertyEntity>) query
				.execute(null);
		assertThat(list.size(), is(equalTo(1)));
		assertThat(list.get(0).getName(), is(equalTo("entity3")));
	}

	/**
	 * 値を保持しないlist propertyを検索する。パラメータは無くても平気。
	 */
	@Test
	public void stringProperties4() {
		PersistenceManager manager = getFactory().getPersistenceManager();
		Query query = manager.newQuery(ListPropertyEntity.class);
		query.setFilter("stringProperty == null");
		query.setOrdering("name asc");
		@SuppressWarnings("unchecked")
		List<ListPropertyEntity> list = (List<ListPropertyEntity>) query
				.execute();
		assertThat(list.size(), is(equalTo(1)));
		assertThat(list.get(0).getName(), is(equalTo("entity3")));
	}

	/**
	 * Entityが保持する日付範囲の中で、指定した日付を含むものを検索する。
	 * <p>
	 * start、endを別々のpuropertに保持すると、
	 * ふたつのpropertyに対してinequalityフィルタを指定できないという問題にあたってしまうが、 ひとつのlist
	 * propertyにstart,endを保持する事で実現できる。
	 * </p>
	 */
	@Test
	public void dateRange1() {
		PersistenceManager manager = getFactory().getPersistenceManager();
		Query query = manager.newQuery(ListPropertyEntity.class);
		query.setFilter("startAndEndDate >= p1 && startAndEndDate <= p1");
		query.declareParameters("java.util.Date p1");
		query.setOrdering("startAndEndDate asc");
		@SuppressWarnings( { "unchecked", "deprecation" })
		List<ListPropertyEntity> list = (List<ListPropertyEntity>) query
				.execute(new Date(2006, 1, 1));
		assertThat(list.size(), is(equalTo(2)));
	}

	/**
	 * Entityが保持する日付範囲の中で、指定した範囲を含むものを検索する。
	 */
	@Test
	public void dateRange2() {
		PersistenceManager manager = getFactory().getPersistenceManager();
		Query query = manager.newQuery(ListPropertyEntity.class);
		query.setFilter("startAndEndDate >= p1 && startAndEndDate <= p1"
				+ "&& startAndEndDate >= p2 && startAndEndDate <= p2");
		query.declareParameters("java.util.Date p1, java.util.Date p2");
		query.setOrdering("startAndEndDate asc");
		@SuppressWarnings( { "unchecked", "deprecation" })
		List<ListPropertyEntity> list = (List<ListPropertyEntity>) query
				.executeWithArray(new Date(2006, 1, 1), new Date(2010, 1, 1));
		assertThat(list.size(), is(equalTo(1)));
	}

	@SuppressWarnings("deprecation")
	private void createInitialData() {
		PersistenceManager manager = getFactory().getPersistenceManager();
		createAndPersist(manager, "entity1", //
				new Date(2000, 1, 1), new Date(2003, 12, 31), //
				new String[] { "Google", "Yahoo" });
		createAndPersist(manager, "entity2", //
				new Date(2000, 1, 1), new Date(2009, 12, 31), //
				new String[] { "Google", "Apple" });
		createAndPersist(manager, "entity3", //
				new Date(2004, 1, 1), new Date(2005, 12, 31), //
				null);
		createAndPersist(manager, "entity4", //
				new Date(2005, 1, 1), new Date(2010, 12, 31), //
				new String[] { "Softbank" });
		manager.close();
	}

	private void createAndPersist(PersistenceManager manager, String name,
			Date start, Date end, String[] stringProperties) {
		ListPropertyEntity entity = new ListPropertyEntity();
		entity.setName(name);
		entity.getStartAndEndDate().add(start);
		entity.getStartAndEndDate().add(end);
		if (stringProperties != null) {
			for (String string : stringProperties) {
				entity.getStringProperty().add(string);
			}
		}
		manager.makePersistent(entity);
	}
}
