package com.hammurapi.common.concurrent.transactions;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;

import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.xa.XAResource;

import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.resource.ehcache.EhCacheXAResourceProducer;

import com.hammurapi.common.Context;
import com.hammurapi.common.concurrent.LocalStringPropertySet;
import com.hammurapi.common.concurrent.NonQueueingThreadPoolExecutorService;
import com.hammurapi.common.concurrent.PropertySet;
import com.hammurapi.convert.ConvertingService;

/**
 * Transactional processor which uses NonQueueingThreadPoolExecutor, String PropertySet, and Bitronix transaction manager.
 * @author Pavel Vlasov
 *
 */
public class StandaloneTransactionalProcessor extends AbstractTransactionalProcessor<String> {
	
	private ExecutorService nqtpes;

	private BitronixTransactionManager tm;
	
	private static ThreadLocal<ExecutorService> tmp = new ThreadLocal<ExecutorService>(); 
	
	private static ExecutorService setExecutorService(ExecutorService es) {
		tmp.set(es);
		return es;
	}

	public StandaloneTransactionalProcessor(ThreadFactory threadFactory, int threadPoolSize) {
		super(setExecutorService(new NonQueueingThreadPoolExecutorService(threadFactory, threadPoolSize)));
		nqtpes = tmp.get();
		tmp.set(null);
		tm = TransactionManagerServices.getTransactionManager();
	}

	@Override
	protected PropertySet<String> createPropertySet(ExecutorService executorService, Context context, PropertySet<String>... chain) {
		return new LocalStringPropertySet(executorService, ConvertingService.CONVERTER, context, Thread.currentThread().getContextClassLoader(), chain);
	}

	@Override
	protected Transaction beginTransaction() throws NotSupportedException,	SystemException {
		tm.begin();
		return tm.getTransaction();
	}	
	
	public void shutdown() {
		if (nqtpes!=null) {
			nqtpes.shutdown();
		}
		if (tm!=null) {
			tm.shutdown();
		}
	}		
	
	public void setTransactionTimeout(int seconds) throws SystemException {
		tm.setTransactionTimeout(seconds);
	}

	@Override
	protected void registerXAResource(String uniqueId, XAResource xaResource) {
		EhCacheXAResourceProducer.registerXAResource(uniqueId, xaResource);
	}
	
	@Override
	protected void unregisterXAResource(String uniqueId, XAResource xaResource) {
		EhCacheXAResourceProducer.unregisterXAResource(uniqueId, xaResource);
	}

}
