/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.fw.cache;

// Java classes
import java.io.Serializable;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import gov.va.med.fw.service.AbstractComponent;

// Framework classes

// ESR classes

/**
 * Clean up cached data accumulated in a transaction scope.  This
 * class provides an around advice to a method invocation to clean
 * up cached data after a method is invoked in a transaction.  
 *
 * Project: Framework</br>
 * Created on: 9:23:19 AM </br>
 *
 * @author DNS   LEV
 */
public class CacheResourceAdvice extends AbstractComponent 
	implements MethodInterceptor, Serializable {

	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = 7086772476623070151L;

	/**
	 * An instance of cacheManager
	 */
	private EntityCacheManager cacheManager = null;
	
	/**
	 * Create a new TransactionInterceptor.
	 */
	public CacheResourceAdvice() {
		super();
	}

	/**
	 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
	 */
	public Object invoke(MethodInvocation invocation) throws Throwable {

		Object result = null;
		try {
			result = invocation.proceed();
		}
		catch( Throwable t ) {
			// Simply log minimal information here 
			if( this.logger.isDebugEnabled() ) {
				logger.debug( "Exception thrown in " + invocation.getMethod().getName() );
				Throwable root = ExceptionUtils.getRootCause( t );
				logger.debug( "Exception root cause message: " + ((root != null) ? root.getMessage() : null) );
			}
			throw t;
		}
		finally {
			doAfterInvocation( invocation );
		}
		return result;
	}

	/**
	 * @see org.springframework.transaction.interceptor.TransactionAspectSupport#afterPropertiesSet()
	 */
	public void afterPropertiesSet() {
		Validate.notNull( this.cacheManager, "An entityCacheManager is required" );
	}

	/**
	 * Perform any post processing task after a method is invoked in a transaction 
	 * @param invocation Encapsulates information to invoke a method
	 */
	protected void doAfterInvocation(MethodInvocation invocation) {
		
		if( this.logger.isDebugEnabled() ) {
			logger.debug( "Post processing of method: " + invocation.getMethod().getName() );
		}
		
		String txName = TransactionSynchronizationManager.getCurrentTransactionName();
		if( txName != null ) {
			this.getCacheManager().removeItem( txName );
		}
	}

	/**
	 * @return Returns the cacheManager.
	 */
	public EntityCacheManager getCacheManager() {
		return cacheManager;
	}

	/**
	 * @param cacheManager The cacheManager to set.
	 */
	public void setCacheManager(EntityCacheManager cacheManager) {
		this.cacheManager = cacheManager;
	}
}