/*
 * Copyright 2002-2007 Network Engine for Objects in Lund AB [neotechnology.com]
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.neo4j.impl.transaction;

import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

import org.neo4j.impl.event.Event;
import org.neo4j.impl.event.EventData;
import org.neo4j.impl.event.EventManager;


public class UserTransactionImpl implements UserTransaction
{
	private static final UserTransactionImpl instance = 
		new UserTransactionImpl();

	private final TransactionManager tm = 
		TransactionFactory.getTransactionManager();
	
	public static UserTransactionImpl getInstance()
	{
		return instance;
	}

	private UserTransactionImpl()
	{
	}
	
	public void begin() throws NotSupportedException, SystemException
	{
		tm.begin();
		// Neo generates TX_BEGIN, TX_ROLLBACK and TX_COMMIT events on
		// transaction begin, rollback and commit, respectively. TX_BEGIN is
		// generated here in UserTransaction.begin(), while ROLLBACK and COMMIT
		// are generated by a synchronization hook (TxEventGenerator) registered
		// below.
		try
		{
			TransactionImpl tx = ( TransactionImpl ) tm.getTransaction();
			EventManager.getManager().generateReActiveEvent(
				Event.TX_BEGIN, new EventData( tx.getEventIdentifier() ) );
			tx.registerSynchronization( TxEventGenerator.getInstance() );
		}
		catch ( Exception e )
		{
			e.printStackTrace();
			throw new SystemException( "Unable to generate tx events:" + e );
		}
	}

	public void commit() throws RollbackException, HeuristicMixedException,
				 HeuristicRollbackException, SecurityException,
				 IllegalStateException, SystemException
	{
		tm.commit();
	}

	public void rollback() throws SecurityException, IllegalStateException,
				 SystemException
	{
		tm.rollback();
	}

	public void setRollbackOnly() throws IllegalStateException, SystemException
	{
		tm.setRollbackOnly();
	}

	public int getStatus() throws SystemException
	{
		return tm.getStatus();
	}

	public void setTransactionTimeout(int seconds) throws SystemException
	{
		tm.setTransactionTimeout(seconds);
	}
	
	/**
	 * Returns the event identifier for the current transaction. If no 
	 * transaction is active <CODE>null</CODE> is returned.
	 */
	public Integer getEventIdentifier()
	{
		try
		{
			TransactionImpl tx = ( TransactionImpl ) tm.getTransaction();
			if ( tx != null )
			{
				return tx.getEventIdentifier();
			}
		}
		catch ( SystemException e )
		{
		}
		return null;
	}
}
