/********************************************************************
 * 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;
	}
}