package eu.dnetlib.dummy;

import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;

import eu.dnetlib.sesame.xapool.XAConnectionSesame;
import eu.dnetlib.sesame.xapool.XADataSourceSesame;

/**
 * DummyDAO for Sesame to use with JTA transaction. The method saveUsingConnecction is not implemented, since we do not
 * use JdbcTemplate, but works directly with a RepositoryConnection obtained by the XADataSourceSesame instance.
 * 
 * @author lexis
 */
public class DummyDAOSesame implements DummyDAOInterface {

	/** datasource to get connections to the triplestore. */
	private XADataSourceSesame xaDataSource;

	public void setXaDataSource(final XADataSourceSesame xaDataSource) {
		this.xaDataSource = xaDataSource;
	}

	public XADataSourceSesame getXaDataSource() {
		return this.xaDataSource;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.dummy.DummyDAOInterface#save(eu.dnetlib.dummy.DummyObject, boolean)
	 */
	public void save(final DummyObject obj, final boolean fail) {
		XAConnectionSesame xaCon = null;
		RepositoryConnection con = null;
		try {
			xaCon = (XAConnectionSesame) this.xaDataSource.getXAConnection();
			con = xaCon.getRepositoryCon();
			this.doSave(con, obj, fail);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (xaCon != null)
					xaCon.close();
				if (con.isOpen())
					con.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}

	}

	/**
	 * Does the dirty work saving triples to the triplestore using the given RepositoryConnection.
	 * 
	 * @param con
	 *            open connection to a Repository
	 * @param obj
	 *            DummyObject instance to save
	 * @param fail
	 *            true if we want to fail the operation, thus leading to a rollback
	 * @throws RepositoryException
	 *             problems saving triples to the repository through the given connection
	 */
	private void doSave(final RepositoryConnection con, final DummyObject obj, final boolean fail) throws RepositoryException {
		URI soggetto = con.getValueFactory().createURI("http://dummy/" + obj.getTheInt());
		URI predicatoInt = con.getValueFactory().createURI("http://dummy/hasInt");
		URI predicatoStr = con.getValueFactory().createURI("http://dummy/hasStr");
		Literal oggettoInt = con.getValueFactory().createLiteral(obj.getTheInt());
		con.add(soggetto, predicatoInt, oggettoInt);
		Literal oggettoStr = con.getValueFactory().createLiteral(obj.getTheString());
		con.add(soggetto, predicatoStr, oggettoStr);
		if (fail) {
			//so we can test if we rollback!
			throw new RuntimeException();
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.dummy.DummyDAOInterface#saveUsingConnection(eu.dnetlib.dummy.DummyObject, boolean)
	 */
	public void saveUsingConnection(final DummyObject obj, final boolean fail) {
		throw new RuntimeException("Method not implemented");
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.dummy.DummyDAOInterface#deleteAllContents()
	 */
	public void deleteAllContents() {
		XAConnectionSesame xaCon = null;
		RepositoryConnection con = null;
		try {
			xaCon = (XAConnectionSesame) this.xaDataSource.getXAConnection();
			con = xaCon.getRepositoryCon();
			con.remove(null, null, (Value) null);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (xaCon != null)
					xaCon.close();
				if (xaCon != null)
					con.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
	}

}
