/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.esr.common.persistent.person.hibernate;

// Java classes

// Library classes
import org.aopalliance.intercept.MethodInvocation;

// Framework classes
import gov.va.med.fw.cache.AbstractEntityCacheAdvice;

// ESR classes
import gov.va.med.esr.common.model.person.id.PersonEntityKey;

/**
 * This AOP advice intercepts any method to query a person from a data
 * source.  In addition, a first argument of a method must be a person
 * entity.  A result from a query with be cached in a thread-bound storage
 * within a transaction scope.
 *
 * Project: Common</br>
 * Created on: 10:26:04 AM </br>
 *
 * @author DNS   LEV
 */
public class PersonEntityCacheAdvice extends AbstractEntityCacheAdvice {

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

	/**
	 * A default constructor
	 */
	public PersonEntityCacheAdvice() {
		super();
	}

	/**
	 * @see gov.va.med.fw.cache.AbstractEntityCacheAdvice#isCached(org.aopalliance.intercept.MethodInvocation)
	 */
	protected boolean isCached(MethodInvocation invocation) {

		boolean isCached = false;
		Object[] arguments = invocation.getArguments();
		if( arguments != null && arguments.length >= 1 ) {
			PersonEntityKey id = (arguments[0] instanceof PersonEntityKey) ? (PersonEntityKey)arguments[0] : null;
			isCached = (id != null) ? this.isCached( id ) : false;

			if (logger.isDebugEnabled()) {
	            logger.debug("PersonEntityCacheAdvice isCachedKey: " + id + " invocation: " + invocation + " isCached:" + isCached);
			}
		}
		return isCached;
	}
	
	//CCR 13437: override the method so that the person just explicit added can avoid extra 1305 calls 
	//by passsing person traits (in addition to PersonEntityKey) in getPristinePerson() method for ilog rules
	//ignore the second argument of PersonIdentityTraits and just use the first argument of PersonEntityKey as the key
   protected Object getCachedKey( Object result, MethodInvocation invocation ) {
	      
	      Object key = null;
	      Object[] args = invocation.getArguments();
	      int size = args != null ? args.length : 0;

	      // If there is only one input argument  
	      // then use it as a key to cache
	      if( size == 1 ) {
	         key = args[0];
	      }
	      // If there are more than one args, call toString on the arg
	      // then append all string info together to form a key
	      else if( size > 1 ){
	    	  key = (args[0] instanceof PersonEntityKey) ? (PersonEntityKey)args[0] : null;
	      }
	      else {
	         // Can't really cache an entity without a key so log debug here
	         if( logger.isDebugEnabled() ) {
	            logger.debug( "A key is required to cache " + result );
	         }
	      }
	      return key;
	}
	/**
	 * @see gov.va.med.fw.cache.AbstractEntityCacheAdvice#getCachedItem(org.aopalliance.intercept.MethodInvocation)
	 */
	protected Object getCachedItem(MethodInvocation invocation) {

		Object entity = null;
		Object[] arguments = invocation.getArguments();
		if( arguments != null && arguments.length >= 1 ) {
			PersonEntityKey id = (arguments[0] instanceof PersonEntityKey) ? (PersonEntityKey)arguments[0] : null;
			entity = (id != null) ? this.getCachedItem( id ) : null;

			if (entity != null && logger.isDebugEnabled()) {
	            logger.debug("PersonEntityCacheAdvice getCachedItem: " + id + " invocation: " + invocation + " item:" + entity);
			}
		}
		return entity;
	}
	

}