package gov.va.med.esr.jms.vadir.inboundRequest;

import org.apache.commons.logging.Log;
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests;
import gov.va.med.esr.jms.vadir.inboundRequest.SingletonApplicationContext;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * A base class for all JUnit test cases that utilizes a Request Broker to
 * obtain spring managed components. This base class also provides utility
 * methods to obtain a reference to a logging component and to execute methods
 * in a transaction scope.
 * 
 * @author Vu Le, Yi He
 */

@ContextConfiguration(locations={"/test_components.xml","/applicationContext-vadir.xml" })
public abstract class AbstractBrokerTestCase extends AbstractJUnit38SpringContextTests { 

	/**
	 * An instance of configLocations
	 */


	// #####################################
	// ### below are used for test drivers in Framework
	// #####################################
	// allows subclasses to not have to name testcases
	public AbstractBrokerTestCase() {
	}
	

	// preserved for old code
	public AbstractBrokerTestCase(String name) {
		super(name);

	}
	
	
	// #####################################
	// ### below are used for test drivers in clients of Framework (1 level deep)
	// #####################################
	// allows subclasses to not have to name testcases
	public AbstractBrokerTestCase(String[] configFiles) {

	}

	// preserved for old code
	public AbstractBrokerTestCase(String name, String[] configFiles) {
		this(name);

	}

	// #####################################
	// ### below are used for test drivers in clients of Framework (2 levels
	// deep)
	// #####################################
	// allows subclasses to not have to name testcases
	public AbstractBrokerTestCase(String[] configFiles, String[] parentConfigFiles) {

	}

	// preserved for old code
	public AbstractBrokerTestCase(String name, String[] configFiles,
			String[] parentConfigFiles) {
		this(name);

	}

	// overridden from Spring
	public void onSetUpInTransaction() throws Exception {
      
      SingletonApplicationContext.getInstance().setSingletonContext( this.applicationContext );
      // Set a transaction name
      String name = TransactionSynchronizationManager.getCurrentTransactionName();
      if( TransactionSynchronizationManager.isActualTransactionActive() && name == null ) {
         TransactionSynchronizationManager.setCurrentTransactionName( this.getName() );
      }
		customSetUp();
	}

	// for convenience
	protected Log getLogger() {
		return logger;
	}

	protected void customSetUp() throws Exception {
	}

	// overridden from Spring
	public void onTearDownInTransaction() {
		try {
			customTearDown();
		}
		catch (Exception e) {
			fail("Unable to tear down data", e);
		}
	}

	/** Subclasses can override (helpful in testing services that start their own TX) */
	protected boolean shouldTestCaseStartTransaction() {
		return true;
	}

	protected void customTearDown() throws Exception {
	}


	/**
	 * Useful for html reporting to see the entire stack trace
	 * 
	 * @param message
	 * @param e
	 */
	protected void fail(String message, Exception e) {
		e.fillInStackTrace(); // just to get the most information possible
		Throwable cause = e;
		StringBuffer trace = new StringBuffer();
		while (cause != null) {
			trace.append("******").append(cause.getMessage()).append(" ").append(
					cause);
			cause = cause.getCause();
		}
		fail(message + trace.toString());
	}

}