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

// Java classes
import gov.va.med.fw.model.lookup.SeverityType;
import gov.va.med.fw.validation.ValidationFieldMessage;
import gov.va.med.fw.validation.ValidationMessages;

import java.io.Serializable;

import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// Framework classes

// EDB classes

/**
 * Project: Framework
 * 
 * @author DNS   LEV
 * @version 1.0
 */
public class RuleState implements Serializable {
    private Log logger = LogFactory.getLog(this.getClass());
	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = -4973518623152819174L;

	/**
	 * An instance of ruleFlowNameAware
	 */
	private RuleFlowNameAware ruleFlowNameAware = null;

	/**
	 * An instance of ruleParameter
	 */
	private RuleParameter ruleParameter = null;

	/**
	 * A constant string to represent a variable name of a rule state object in a
	 * rule engine's agenda.
	 */
	public static final String DEFAULT_PARAM_NAME = StringUtils
			.uncapitalize(ClassUtils.getShortClassName(RuleState.class));

	/**
	 * Flag to indicate whether a rule is executed
	 */
	private boolean executed = false;

	/**
	 * A variable name of a rule state in a rule engine's agenda
	 */
	private String name = DEFAULT_PARAM_NAME;

	/**
	 * flag to indicate whether a BOM data elements is modified
	 */
	private boolean inSession = false;

	/**
	 * An instance of exhaustiveMode
	 */
	private boolean exhaustiveMode = false;

	/**
	 * An instance of validationMessages
	 */
	private ValidationMessages validationMessages = new ValidationMessages();

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

	/**
	 * Sets a flag to indicate a rule is executed successfully. This method is
	 * for a derived rule wrapper class to call when a rule participates in a
	 * complex rule flow.
	 */
	public void setRuleExecuted(boolean flag) {
	    logger.debug("" + flag);
		executed = flag;
	}

	/**
	 * sets a flag to indicate if the rules are in the same session
	 * 
	 * @param flag
	 *           true if in the same session. false otherwise.
	 */
	public void setInSession(boolean flag) {
		inSession = flag;
	}

	/**
	 * Returns true if a rule is executed successfully otherwise returns false.
	 * This method should be called by an action method if a rule participates in
	 * a complex rule flow.
	 * 
	 * @return True if a rule is executed successfully. false otherwise
	 */
	public boolean isRuleExecuted() {
		return executed;
	}

	/**
	 * Returns true if rules are in the same session </br> otherwise returns
	 * false.
	 * 
	 * @return
	 */
	public boolean isInSession() {
		return inSession;
	}

	/**
	 * @return Returns the name.
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *           The name to set.
	 */
	public void setName(String name) {
		this.name = name;
	}

	public void generateRuleException( String id, String originator) throws RuleException {
		generateRuleException(id, originator, SeverityType.ERROR, null);
	}

	public void generateRuleException( String id, String originator, SeverityType severity) throws RuleException {
		generateRuleException(id, originator, severity, null);
	}
	
	/** Throws a rule validation exceptioin if a validation mode is not exhaustive and if ServerityType is ERROR 
	 * @param id A message id to allow a client to look up for a message
	 * @param originator An originator 
	 * @param severity Severity level of the rule validation
	 * @param contextInfo Context info
	 * @throws RuleException A RuleValidationException is thrown in case of error
	 */
	public void generateRuleException( String id, String originator, SeverityType severity, Object contextInfo) throws RuleException {
		generateRuleException(id, originator, severity, null, true);

	}

	/** 
	 * CCR10399 -- add createWklist flag to allow instances where outbound message is 
	 * blocked but worklist item is not generated
	 * 
	 * Throws a rule validation exceptioin if a validation mode is not exhaustive and if ServerityType is ERROR 
	 * @param id A message id to allow a client to look up for a message
	 * @param originator An originator 
	 * @param severity Severity level of the rule validation
	 * @param contextInfo Context info
	 * 
	 * @throws RuleException A RuleValidationException is thrown in case of error
	 */
	public void generateRuleException( String id, String originator, SeverityType severity, Object contextInfo, boolean createWkList) throws RuleException {
		if( !this.isExhaustiveMode() && SeverityType.ERROR.getCode().equals(severity.getCode())) { 
			RuleValidationException e = new RuleValidationException( id, 
														  originator,
														  this.getRuleFlowNameAware().getRuleFlowName(), 
					  									  this.getRuleParameter() );
			e.setSeverityType(severity);
			e.setContextInfo(contextInfo);
			e.setCreateWkList(createWkList);
			throw e;
		}

		// Create a validation field message with data extracted from a rule exception
		ValidationFieldMessage msg = new ValidationFieldMessage( originator, id, severity);
		msg.setContextInfo(contextInfo);
		msg.setCreateWkList(createWkList);
		validationMessages.add(msg);
	}

	/**
	 * @see gov.va.med.fw.rule.RuleSession#getRuleFlowNameAware()
	 */
	public RuleFlowNameAware getRuleFlowNameAware() {
		return this.ruleFlowNameAware;
	}

	/**
	 * @see gov.va.med.fw.rule.RuleSession#getRuleParameter()
	 */
	public RuleParameter getRuleParameter() {
		return this.ruleParameter;
	}

	/**
	 * @see gov.va.med.fw.rule.RuleSession#setRuleFlowNameAware(gov.va.med.fw.rule.RuleFlowNameAware)
	 */
	public void setRuleFlowNameAware(RuleFlowNameAware ruleFlow) {
		this.ruleFlowNameAware = ruleFlow;
	}

	/**
	 * @see gov.va.med.fw.rule.RuleSession#setRuleParameter(gov.va.med.fw.rule.RuleParameter)
	 */
	public void setRuleParameter(RuleParameter ruleParam) {
		this.ruleParameter = ruleParam;
	}

	/**
	 * @return Returns the exhaustiveMode.
	 */
	public boolean isExhaustiveMode() {
		return exhaustiveMode;
	}

	/**
	 * @param exhaustiveMode The exhaustiveMode to set.
	 */
	public void setExhaustiveMode(boolean exhaustiveMode) {
		this.exhaustiveMode = exhaustiveMode;
	}

	/**
	 * @return Returns the validationMessages.
	 */
	public ValidationMessages getValidationMessages() {
		return validationMessages;
	}
}