package com.shin1ogawa.entity;

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

import java.util.List;

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

import org.apache.commons.lang.builder.ToStringBuilder;
import org.junit.Test;

import com.google.appengine.api.datastore.Text;
import com.shin1ogawa.AbstractRelasionShipTest;

public class ParentBTest extends AbstractRelasionShipTest {
	@Test
	public void 新規追加1() {
		ParentB parent1 = new ParentB();
		parent1.setText(new Text("parent1"));

		PersistenceManager pm = getFactory().getPersistenceManager();
		pm.makePersistent(parent1);
		pm.close();

		pm = getFactory().getPersistenceManager();
		pm.getObjectById(ParentB.class, parent1.getKey());
		assertThat(parent1, notNullValue());
		assertThat(parent1.getText().getValue(), is(equalTo("parent1")));
		assertThat(parent1.getChildren(), notNullValue());
		assertThat(parent1.getChildren().size(), is(equalTo(0)));
	}

	@Test
	public void 新規追加_子供あり() {
		ParentB parent1 = new ParentB();
		parent1.setText(new Text("parent1"));
		ChildB childB1 = new ChildB();
		childB1.setValue("childB1");
		ChildB childB2 = new ChildB();
		childB2.setValue("childB2");
		parent1.getChildren().add(childB1);
		parent1.getChildren().add(childB2);

		PersistenceManager pm = getFactory().getPersistenceManager();
		pm.makePersistent(parent1);
		pm.close();

		pm = getFactory().getPersistenceManager();
		pm.getObjectById(ParentB.class, parent1.getKey());
		assertThat(parent1, notNullValue());
		assertThat(parent1.getText().getValue(), is(equalTo("parent1")));
		assertThat(parent1.getChildren(), notNullValue());
		assertThat(parent1.getChildren().size(), is(equalTo(2)));
	}

	@Test
	public void 新規追加_孫まで() {
		ParentB parent1 = new ParentB();
		parent1.setText(new Text("parent1"));
		ChildB childB1 = new ChildB();
		childB1.setValue("childB1");
		ChildB childB2 = new ChildB();
		childB2.setValue("childB2");
		parent1.getChildren().add(childB1);
		parent1.getChildren().add(childB2);
		ChildBChild childB1Child1 = new ChildBChild();
		childB1Child1.setValue("childB1Child1");
		ChildBChild childB1Child2 = new ChildBChild();
		childB1Child2.setValue("childB1Child2");
		childB1.getChildren().add(childB1Child1);
		childB1.getChildren().add(childB1Child2);

		PersistenceManager pm = getFactory().getPersistenceManager();
		parent1 = pm.makePersistent(parent1);
		pm.close();
		System.out.println(ToStringBuilder.reflectionToString(parent1));

		pm = getFactory().getPersistenceManager();
		parent1 = pm.getObjectById(ParentB.class, parent1.getKey());
		assertThat(parent1, notNullValue());
		assertThat(parent1.getText().getValue(), is(equalTo("parent1")));
		assertThat(parent1.getChildren(), notNullValue());
		assertThat(parent1.getChildren().size(), is(equalTo(2)));
		childB1 = parent1.getChildren().get(0);
		assertThat(childB1.getValue(), is(equalTo("childB1")));
		assertThat(childB1.getChildren(), notNullValue());
		assertThat(childB1.getChildren().size(), is(equalTo(2)));
		childB1Child1 = childB1.getChildren().get(0);
		assertThat(childB1Child1.getValue(), is(equalTo("childB1Child1")));
		childB1Child2 = childB1.getChildren().get(1);
		assertThat(childB1Child2.getValue(), is(equalTo("childB1Child2")));
		childB2 = parent1.getChildren().get(1);
		assertThat(childB2.getValue(), is(equalTo("childB2")));
		assertThat(childB2.getChildren(), notNullValue());
		assertThat(childB2.getChildren().size(), is(equalTo(0)));

		assertThat(childB1Child1.getKey().getParent(), is(equalTo(childB1
				.getKey())));
		assertThat(childB1.getKey().getParent(), is(equalTo(parent1.getKey())));

		// 親(ParentB)を指定してChildBを取得する。
		Query query = pm.newQuery(ChildB.class);
		query.setFilter("ancestor == pAncestor");
		query.declareParameters(ParentB.class.getName() + " pAncestor");
		@SuppressWarnings("unchecked")
		List<ChildB> childBList = (List<ChildB>) query
				.execute(parent1.getKey());
		query.closeAll();
		assertThat(childBList, notNullValue());
		assertThat(childBList.size(), is(equalTo(2)));
		assertThat(childBList.get(0).getKey(), is(equalTo(childB1.getKey())));
		assertThat(childBList.get(1).getKey(), is(equalTo(childB2.getKey())));
		assertThat(childBList.get(0).getAncestor().getKey(), is(equalTo(parent1
				.getKey())));
		assertThat(childBList.get(1).getAncestor().getKey(), is(equalTo(parent1
				.getKey())));

		// 親(ChildB)を指定してChildBChildを取得する。
		query = pm.newQuery(ChildBChild.class);
		query.setFilter("ancestor == pAncestor");
		query.declareParameters(ParentB.class.getName() + " pAncestor");
		@SuppressWarnings("unchecked")
		List<ChildBChild> childBChildList = (List<ChildBChild>) query
				.execute(childB1.getKey());
		query.closeAll();
		assertThat(childBChildList, notNullValue());
		assertThat(childBChildList.size(), is(equalTo(2)));
		assertThat(childBChildList.get(0).getKey(), is(equalTo(childB1Child1
				.getKey())));
		assertThat(childBChildList.get(1).getKey(), is(equalTo(childB1Child2
				.getKey())));
		assertThat(childBChildList.get(0).getAncestor().getKey(),
				is(equalTo(childB1.getKey())));
		assertThat(childBChildList.get(1).getAncestor().getKey(),
				is(equalTo(childB1.getKey())));

		pm.close();
	}

	@SuppressWarnings("unchecked")
	public void DeleteCascade() {
		ParentB parent1 = new ParentB();
		parent1.setText(new Text("parent1"));
		ChildB childB1 = new ChildB();
		childB1.setValue("childB1");
		ChildB childB2 = new ChildB();
		childB2.setValue("childB2");
		parent1.getChildren().add(childB1);
		parent1.getChildren().add(childB2);
		ChildBChild childB1Child1 = new ChildBChild();
		childB1Child1.setValue("childB1Child1");
		ChildBChild childB1Child2 = new ChildBChild();
		childB1Child2.setValue("childB1Child2");
		childB1.getChildren().add(childB1Child1);
		childB1.getChildren().add(childB1Child2);

		PersistenceManager pm = getFactory().getPersistenceManager();
		parent1 = pm.makePersistent(parent1);
		pm.close();
		System.out.println(ToStringBuilder.reflectionToString(parent1));

		pm = getFactory().getPersistenceManager();
		// ParentBを全件取得、1件だけ存在する事を確認する。
		Query query = pm.newQuery(ParentB.class);
		List<ParentB> parentBlist = (List<ParentB>) query.execute();
		query.closeAll();
		assertThat(parentBlist.size(), is(equalTo(1)));
		// ChildBを全件取得、2件だけ存在する事を確認する。
		query = pm.newQuery(ParentB.class);
		List<ChildB> childBlist = (List<ChildB>) query.execute();
		query.closeAll();
		assertThat(childBlist.size(), is(equalTo(2)));
		// ChildBChildを全件取得、2件だけ存在する事を確認する。
		query = pm.newQuery(ChildBChild.class);
		List<ChildBChild> childBChildlist = (List<ChildBChild>) query.execute();
		query.closeAll();
		assertThat(childBChildlist.size(), is(equalTo(2)));
		pm.close();

		pm = getFactory().getPersistenceManager();
		parent1 = pm.getObjectById(ParentB.class, parent1.getKey());
		pm.deletePersistent(parent1);
		pm.close();

		pm = getFactory().getPersistenceManager();
		// ParentBを全件取得、一件も存在しない事を確認する。
		query = pm.newQuery(ParentB.class);
		parentBlist = (List<ParentB>) query.execute();
		query.closeAll();
		assertThat(parentBlist.size(), is(equalTo(0)));
		// ChildBを全件取得、一件も存在しない事を確認する。
		query = pm.newQuery(ParentB.class);
		childBlist = (List<ChildB>) query.execute();
		query.closeAll();
		assertThat(childBlist.size(), is(equalTo(0)));
		// ChildBChildを全件取得、一件も存在しない事を確認する。
		query = pm.newQuery(ChildBChild.class);
		childBChildlist = (List<ChildBChild>) query.execute();
		query.closeAll();
		assertThat(childBChildlist.size(), is(equalTo(0)));
		pm.close();
	}
}
