/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/

package gov.va.med.fw.rule;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;

import org.springframework.aop.AfterReturningAdvice;

import gov.va.med.fw.service.AbstractComponent;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.trigger.TriggerAware;
import gov.va.med.fw.service.trigger.TriggerRouter;

/**
 * Performs post-processing of RuleFlow execution.  Currently implemented to perform:
 * <ul>
 * <li> Route any TriggerEvent's that were created by the RuleFlow's parameters (via the TriggerAware interface)
 * </ul>
 * 
 * Created Aug 22, 2005 10:00:24 PM
 * 
 * @author DNS   BOHMEG
 */
public class RuleFlowInterceptor extends AbstractComponent implements
		AfterReturningAdvice {

	private TriggerRouter triggerRouter;
	
	/* (non-Javadoc)
	 * @see org.springframework.aop.AfterReturningAdvice#afterReturning(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
	 */
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		// NOTE: This assumes pass by reference so changes to args that RuleFlow makes is visible to this		
		for (int i = 0; i < args.length; i++) {
			if (args[i] instanceof RuleParameters) { // check this first
				postProcess((RuleParameters) args[i]);
			} else if (args[i] instanceof RuleParameter) {
				postProcess((RuleParameter) args[i]);
			}
		}
	}

	private void postProcess(RuleParameters ruleParameters) throws ServiceException {
		Map params = ruleParameters.getRuleParameters();
		Iterator itr = params != null ? params.values().iterator() : null;
		while (itr != null && itr.hasNext()) {
			postProcess((RuleParameter) itr.next());
		}

	}

	private void postProcess(RuleParameter ruleParameter) throws ServiceException {
		if(ruleParameter instanceof TriggerAware) {
			getTriggerRouter().processTriggerAware((TriggerAware) ruleParameter);	
		}
	}

	/**
	 * @return Returns the triggerRouter.
	 */
	public TriggerRouter getTriggerRouter() {
		return triggerRouter;
	}

	/**
	 * @param triggerRouter The triggerRouter to set.
	 */
	public void setTriggerRouter(TriggerRouter triggerRouter) {
		this.triggerRouter = triggerRouter;
	}
	
	public void afterPropertiesSet() throws Exception {
		if(triggerRouter == null) 
			throw new RuleConfigurationException("A TriggerRouter is necessary for RuleFlow interception");
	}
}
