package eu.dnetlib.dummy;

import static org.junit.Assert.assertTrue;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * Test for SesamePostgresDAO.
 * 
 * @author lexis
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SesamePostgresDAOTest {

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(SesamePostgresDAOTest.class);
	/** Entity under test. */
	@Resource
	private DummyDAOInterface sesamePGDAO;
	/** Sesame repository used before and after all tests method to clear the repository and ask for triples. */
	@Resource
	private Repository sesameRepositoryBean;
	/**
	 * How many triples I expect to have in the triplestore after a test method and the subjectId of the triples o
	 * search for.
	 */
	private int expectedTriples, subjectId;

	/**
	 * Before executing a test better clean up the repository deleting all existing triples.
	 * 
	 * @throws RepositoryException
	 *             deleting tripels
	 */
	@Before
	public void clearAllTriples() throws RepositoryException {
		System.setProperty("org.openrdf.repository.debug", "true");
		this.sesamePGDAO.deleteAllContents();
	}

	/**
	 * After all test we should check if the triple store contains the number of triples we expect.
	 * 
	 * @throws RepositoryException
	 *             querying the triplestore
	 */
	@After
	public void tripleRimaste() throws RepositoryException {
		//now I expect to read 0 triple
		RepositoryConnection con = this.sesameRepositoryBean.getConnection();
		URI soggetto = con.getValueFactory().createURI("http://dummy/" + this.subjectId);
		RepositoryResult<Statement> res = con.getStatements(soggetto, null, null, false);
		int quante = 0;
		while (res.hasNext()) {
			quante++;
			res.next();
		}
		res.close();
		con.close();
		log.debug("Found " + quante + " triples");
		assertTrue(quante == this.expectedTriples);
		//this.sesameRepositoryBean.shutDown();
	}

	/**
	 * Test method for {@link eu.dnetlib.dummy.SesamePostgresDAO#save(eu.dnetlib.dummy.DummyObject, boolean)}. Expect
	 * all ok!
	 */
	@DirtiesContext
	@Test
	public void testSave() {
		DummyObject obj1 = new DummyObject(1, "ciao1");
		log.debug(this.sesamePGDAO);
		this.sesamePGDAO.save(obj1, false);
		this.expectedTriples = 2;
		this.subjectId = 1;
	}

	/**
	 * Test method for {@link eu.dnetlib.dummy.SesamePostgresDAO#save(eu.dnetlib.dummy.DummyObject, boolean)}. Expect
	 * that everything rolledback!
	 */
	@DirtiesContext
	@Test(expected = RuntimeException.class)
	public void testSaveWithException() {
		DummyObject obj1 = new DummyObject(2, "ciao1");
		log.debug(this.sesamePGDAO);
		this.sesamePGDAO.save(obj1, true);
		this.expectedTriples = 0;
		this.subjectId = 2;
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dummy.SesamePostgresDAO#saveUsingConnection(eu.dnetlib.dummy.DummyObject, boolean)}. Expect all
	 * ok.
	 */
	@DirtiesContext
	@Test
	public void testSaveUsingConnecction() {
		int i = 2 + 1;
		DummyObject obj1 = new DummyObject(i, "ciao1");
		log.debug(this.sesamePGDAO);
		this.sesamePGDAO.saveUsingConnection(obj1, false);
		this.expectedTriples = 2;
		this.subjectId = i;
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dummy.SesamePostgresDAO#saveUsingConnection(eu.dnetlib.dummy.DummyObject, boolean)}. Expect
	 * that everything rolledback!
	 */
	@DirtiesContext
	@Test(expected = RuntimeException.class)
	public void testSaveUsingConnecctioneWithException() {
		int i = 2 + 2;
		DummyObject obj1 = new DummyObject(i, "ciao1");
		log.debug(this.sesamePGDAO);
		this.sesamePGDAO.saveUsingConnection(obj1, true);
		this.expectedTriples = 0;
		this.subjectId = i;
	}

}
