package gov.va.med.fw.rule;

// Framework
import gov.va.med.fw.service.ServiceConfigurationException;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.validation.Validatable;
import gov.va.med.fw.validation.ValidationFieldMessage;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationService;

/**
 * Abstract implementation of the validation service.
 * 
 * @author Muddaiah Ranga
 * @version 3.0
 */
public abstract class AbstractRuleValidationService extends AbstractRuleFlowAwareService implements ValidationService {

   /**
    * A default constructor
    */
   protected AbstractRuleValidationService() {
      super();
   }

   /**
    * @see gov.va.med.fw.validation.ValidationService#validate(gov.va.med.fw.validation.Validatable)
    */
   public ValidationMessages validate(Validatable input) throws ServiceException {
      
      ValidationMessages messages = new ValidationMessages();
      if( input instanceof SimpleValidatableRule ) {
         
         // Get the rule parameters and data to invoke a rule flow
         RuleParameters params = ((SimpleValidatableRule)input).getRuleParameters();
         RuleDataAware data = ((SimpleValidatableRule)input).getRuleDataAware();
         
         this.setExhaustiveMode( params, Validatable.EXHAUSTIVE.equals( input.getValidationMode() ) );
         
         // Set a validation mode in a rule state object
         RuleState state = params.getState();
         
         try {
            this.getRuleFlow().execute( params, data );
            
            // If a validation mode is set exhaustive mode, check for validation messages here
            if( state != null && state.isExhaustiveMode() ) 
            {
                messages = state.getValidationMessages();
            }
         }
         catch( RuleConfigurationException e ) {
         	// There is a problem in a configuration of this service
         	throw new ServiceConfigurationException( "A validation rule flow was not configured properly", e );
         }
         catch( RuleException e ) {
         	// Only handle a target of type rule validation exception
         	if( e.getCause() instanceof RuleValidationException ) {
               // Create a validation field message with data extracted from a rule exception
               String id = e.getMessageID();
               Object field = e.getOriginator();
               // 10399 -- added the option of allowing supression of worklist item
               ValidationFieldMessage msg = 
            	   new ValidationFieldMessage( (field != null ? field.toString() : null), id );
               	msg.setCreateWkList(((RuleValidationException)e).isCreateWkList());
                messages.add( msg );
         	}
         	else {
         		// Should never get here since rule flow manager either throws rule exception and rule configuation exception
            	throw new ServiceException( "An unexpected error occurred", e );
         	}
         }
      }
      return messages;
   }
   

}