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

/*
 * Created on Jan 31, 2005
 */
package gov.va.med.esr.common.rule.service;

// Java classes
import java.util.Calendar;

// Library classes
import org.apache.commons.lang.Validate;

// Framework classes
import gov.va.med.fw.validation.ValidationFieldMessage;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationServiceException;

// EDB Classes
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.util.RuleAbstractTestCase;
import gov.va.med.esr.common.model.person.DeathRecord;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.insurance.InsurancePolicy;
import gov.va.med.esr.common.model.insurance.InsuranceSubscriber;
import gov.va.med.esr.common.model.lookup.InsuredRelationship;
import gov.va.med.esr.common.model.insurance.Medicare;
import gov.va.med.esr.common.model.insurance.PrivateInsurance;
import gov.va.med.esr.common.rule.service.impl.RuleValidationMessage;
import gov.va.med.esr.common.infra.ImpreciseDate;

/**
 * Provides test cases for an InsuranceRuleService
 *
 * Project: Common</br>
 * Created on: 1:16:24 PM </br>
 *
 * @author DNS   LEV
 */
public class InsuranceRuleServiceTest extends RuleAbstractTestCase {

	/**
	 * An instance of onFile
	 */
	private Person onFile = null;

	/**
	 * constructor
	 */
	public InsuranceRuleServiceTest(String testName) throws Exception {
		super(testName);
	}
	
	/**
	 * @see gov.va.med.fw.util.AbstractTestCase#customSetUp()
	 */
	protected void customSetUp() throws Exception {
		super.customSetUp();
		onFile = this.buildPerson();
	}

	/**
	 * @see gov.va.med.fw.util.AbstractTestCase#customTearDown()
	 */
	protected void customTearDown() throws Exception {
		super.customTearDown();
		onFile = null;
	}

	/** Tests enrolledInMedicarePartA BAL rule in ProcessInsurances.irl
	 * @throws Exception Thrown in case of errors
	 */
	public void testEnrolledInMedicarePartA() throws Exception {
		/**
		3124[UC22.14] Part A Effective Date –
		Part A Effective Date is not a required entry even if the Enrolled In Medicare Part A Indicator  = Yes 

		3125[UC22.14.1]  
		If the actor enters Part A Effective Date, the system will set the Enrolled in Medicare Part A Indicator to Yes.
		**/		
		// Create a policy for a veteran
		Medicare policy = (Medicare)this.createMedicareInsurance();
		InsuredRelationship relationship = 
			this.getLookupService().getInsuredRelationshipByCode( InsuredRelationship.CODE_VETERAN.getName() );
		
		InsuranceSubscriber subscriber = new InsuranceSubscriber();
		subscriber.setRelationship( relationship );
		
		policy.setSubscriber( subscriber );
		policy.setReportSource( this.getRandomReportSource() );
		
		onFile.addInsurance( policy );
		this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		Person incoming = (Person)onFile.clone();
		
		policy = (Medicare)incoming.getInsurances().iterator().next();
		// policy.setPartAEffectiveDate( Calendar.getInstance().getTime() );
		policy.setPartAEffectiveDate( new ImpreciseDate( Calendar.getInstance() ) );
		policy.setEnrolledInPartA( Boolean.FALSE );
		
		// Test a scenario where we expect a validation message
		try {
			this.getInsuranceRuleService().processInsurancePolicies( incoming.getInsurances(), working, policy.getReportSite() );
			
			assertEquals( incoming.getInsurances().size(), working.getInsurances().size() );
			
			Medicare updated = (Medicare)working.getInsurances().iterator().next();
			assertEquals( updated.getEnrolledInPartA(), Boolean.TRUE );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an un-expected exception ", e );
			}
		}
	}
	
	/** Tests enrolledInMedicarePartB BAL rule in ProcessInsurances.irl
	 * @throws Exception Thrown in case of errors
	 */
	public void testEnrolledInMedicarePartB() throws Exception {
		
		/** 3127[UC22.15] Part B Effective Date –  
		Part B Effective Date is not a required entry even if the Enrolled In Medicare Part B Indicator  = Yes 

		3128[UC22.15.1]  
		If the actor enters Part B Effective Date, the system will set the Enrolled in Medicare Part B Indicator to Yes.
		*/
		// Create a policy for a veteran
		Medicare policy = (Medicare)this.createMedicareInsurance();
		InsuredRelationship relationship = 
			this.getLookupService().getInsuredRelationshipByCode( InsuredRelationship.CODE_VETERAN.getName() );
		
		InsuranceSubscriber subscriber = new InsuranceSubscriber();
		subscriber.setRelationship( relationship );
		
		policy.setSubscriber( subscriber );
		policy.setReportSource( this.getRandomReportSource() );
		
		onFile.addInsurance( policy );
		this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		Person incoming = (Person)onFile.clone();
		
		policy = (Medicare)incoming.getInsurances().iterator().next();
		policy.setPartBEffectiveDate( new ImpreciseDate( Calendar.getInstance() ) );
		// policy.setPartBEffectiveDate( Calendar.getInstance().getTime() );
		policy.setEnrolledInPartB( Boolean.FALSE );
		
		// Test a scenario where we expect a validation message
		try {
			this.getInsuranceRuleService().processInsurancePolicies( incoming.getInsurances(), working, policy.getReportSite() );
			
			assertEquals( incoming.getInsurances().size(), working.getInsurances().size() );
			
			Medicare updated = (Medicare)working.getInsurances().iterator().next();
			assertEquals( updated.getEnrolledInPartB(), Boolean.TRUE );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an un-expected exception ", e );
			}
		}
	}
	
	/** Tests updateInsurancePolicyPartB BAL rule in ProcessInsurances.irl
	 * @throws Exception Thrown in case of errors
	 */
	public void testUpdateInsurancePolicyPartA() throws Exception {
		
		/** 4121[UC22.12] Medicare Part A Indicator  
		 * When an actor enters Yes to Medicare Part A the system 
		 * automatically populates the following fields:
		 * Insurance Company Name is set to Medicare
		 * Group Name is set to Part A
		 * Group Number is set to Part A 
		 */
		
		// Create a policy for a veteran
		Medicare policy = (Medicare)this.createMedicareInsurance();
		InsuredRelationship relationship = 
			this.getLookupService().getInsuredRelationshipByCode( InsuredRelationship.CODE_VETERAN.getName() );
		
		InsuranceSubscriber subscriber = new InsuranceSubscriber();
		subscriber.setRelationship( relationship );
		
		policy.setSubscriber( subscriber );
		policy.setReportSource( this.getRandomReportSource() );
		
		onFile.addInsurance( policy );
		Person pristine = this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)pristine.clone();
		Person incoming = (Person)pristine.clone();
		
		policy = (Medicare)incoming.getInsurances().iterator().next();
		policy.setEnrolledInPartA( Boolean.TRUE );
		
		// Test a scenario where we expect a validation message
		try {
			this.getInsuranceRuleService().processInsurancePolicies( incoming.getInsurances(), working, policy.getReportSite() );
			
			assertEquals( incoming.getInsurances().size(), working.getInsurances().size() );
			
			Medicare updated = (Medicare)working.getInsurances().iterator().next();
			assertEquals( updated.getGroupName(), "Part A" );
			assertEquals( updated.getGroupNumber(), "Part A" );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an un-expected exception ", e );
			}
		}
	}
	
	/** Tests updateInsurancePolicyPartB BAL rule in ProcessInsurances.irl
	 * @throws Exception Thrown in case of errors
	 */
	public void testUpdateInsurancePolicyPartB() throws Exception {
		
		/** 4122[UC22.13] Medicare Part B Indicator  -
		 * When an actor enters Yes to Medicare Part B the system 
		 * automatically populates the following fields: 
		 * Insurance Company Name to Medicare, Group Name, and Group Number to Part B
		 */
		
		// Create a policy for a veteran
		Medicare policy = this.createMedicareInsurance();
		InsuredRelationship relationship = 
			this.getLookupService().getInsuredRelationshipByCode( InsuredRelationship.CODE_VETERAN.getName() );
		
		InsuranceSubscriber subscriber = new InsuranceSubscriber();
		subscriber.setRelationship( relationship );
		
		policy.setSubscriber( subscriber );
		policy.setReportSource( this.getRandomReportSource() );
		
		onFile.addInsurance( policy );
		Person pristine = this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)pristine.clone();
		Person incoming = (Person)pristine.clone();
		
		policy = (Medicare)incoming.getInsurances().iterator().next();
		policy.setEnrolledInPartA( Boolean.TRUE );
		policy.setEnrolledInPartB( Boolean.TRUE );
		// policy.setPartAEffectiveDate( this.getDate( 2004, 5, 15 ) );
		// policy.setPartBEffectiveDate( this.getDate( 2005, 1, 15 ) );
		policy.setPartAEffectiveDate( ImpreciseDateUtils.createImpreciseDate( 2004, 5, 15 ) );
		policy.setPartBEffectiveDate( ImpreciseDateUtils.createImpreciseDate( 2005, 1, 15 ) );
		// Test a scenario where we don't expect a validation message
		try {
			this.getInsuranceRuleService().processInsurancePolicies( incoming.getInsurances(), working, policy.getReportSite() );
//			
//			assertEquals( incoming.getInsurances().size(), updated.size() );
//			
//			Medicare updated_policy = (Medicare)updated.iterator().next();
//			assertEquals( updated_policy.getGroupName(), "Part B" );
//			assertEquals( updated_policy.getGroupNumber(), "Part B" );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an un-expected exception ", e );
			}
		}
	}
	
	/** Tests defaultNameOfInsured BAL rule in ProcessInsurances.irl
	 * @throws Exception Thrown in case of errors
	 */
	public void testDefaultNameOfInsured() throws Exception {
		
		/** 3143[UC22.21.2]  defaultNameOfInsured 
		 * If the Patients Relationship to the Insured is “Self,” 
		 * then the system defaults the Name of Insured to the patient’s name.
		**/		
		// Create a policy for a veteran
		InsurancePolicy policy = this.createPrivateInsurance();
		InsuredRelationship relationship = 
			this.getLookupService().getInsuredRelationshipByCode( InsuredRelationship.CODE_VETERAN.getName() );
		
		InsuranceSubscriber subscriber = new InsuranceSubscriber();
		subscriber.setRelationship( relationship );
		
		policy.setSubscriber( subscriber );
		policy.setReportSource( this.getRandomReportSource() );
		
		onFile.addInsurance( policy );
		this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		Person incoming = (Person)onFile.clone();
		
		policy = (InsurancePolicy)incoming.getInsurances().iterator().next();
		policy.getSubscriber().setName( null );
		
		// Test a scenario where we expect a validation message
		try {
			this.getInsuranceRuleService().processInsurancePolicies( incoming.getInsurances(), working, policy.getReportSite() );
			
			assertEquals( incoming.getInsurances().size(), working.getInsurances().size() );
			// TODO: After Ranga checked in his code, switch to InsuranceInput.getPatientName
			// to set a correct value
			// assertEquals( policy.getSubscriber().getName(), "TEST" );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an un-expected exception ", e );
			}
		}
	}
	
	/** Tests IsInsurancePolicyNew BAL rule in ProcessInsurances.irl
	 * @throws Exception Thrown in case of errors
	 */
	public void testIsInsurancePolicyNew() throws Exception {
		
		// Create a policy for a veteran
		Medicare policy = (Medicare)this.createMedicareInsurance();
		InsuredRelationship relationship = 
			this.getLookupService().getInsuredRelationshipByCode( InsuredRelationship.CODE_VETERAN.getName() );
		
		InsuranceSubscriber subscriber = new InsuranceSubscriber();
		subscriber.setRelationship( relationship );
		
		policy.setSubscriber( subscriber );
		policy.setReportSource( this.getRandomReportSource() );
		policy.setEnrolledInPartB( Boolean.TRUE );
		
		onFile.addInsurance( policy );
		this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		Person incoming = (Person)onFile.clone();
		this.attachMedicare( incoming );
		
		try {
			assertEquals( 1, working.getInsurances().size() );
			this.getInsuranceRuleService().processInsurancePolicies( incoming.getInsurances(), working, policy.getReportSite() );
			assertEquals( 2, working.getInsurances().size() );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an un-expected exception ", e );
			}
		}
	}
	
	/** Tests IsInsurancePolicyUpdated BAL rule in ProcessInsurances.irl
	 * @throws Exception Thrown in case of errors
	 */
	public void testIsInsurancePolicyUpdated() throws Exception {
		
		// Create a policy for a veteran
		Medicare policy = (Medicare)this.createMedicareInsurance();
		InsuredRelationship relationship = 
			this.getLookupService().getInsuredRelationshipByCode( InsuredRelationship.CODE_VETERAN.getName() );
		
		InsuranceSubscriber subscriber = new InsuranceSubscriber();
		subscriber.setRelationship( relationship );
		
		policy.setSubscriber( subscriber );
		policy.setReportSource( this.getRandomReportSource() );
		policy.setEnrolledInPartB( Boolean.TRUE );
		policy.setMedicareClaimNumber( "111111" );
		
		onFile.addInsurance( policy );
		this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		Person incoming = (Person)onFile.clone();
		
		policy = (Medicare)incoming.getInsurances().iterator().next();
		policy.setMedicareClaimNumber( "222222" );
		
		try {
			assertEquals( "111111", ((Medicare)working.getInsurances().iterator().next()).getMedicareClaimNumber() );
			this.getInsuranceRuleService().processInsurancePolicies( incoming.getInsurances(), working, policy.getReportSite() );
			assertEquals( "222222", ((Medicare)working.getInsurances().iterator().next()).getMedicareClaimNumber() );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an un-expected exception ", e );
			}
		}
	}
	
	/** Tests IsInsuranceCompanyAddressIncomplete BAL rule in InsuranceValidation
	 * @throws Exception Thrown in case of errors
	 */
	public void testIsInsuranceCompanyAddressIncomplete() throws Exception {

		/** IsInsuranceCompanyAddressIncomplete - 
		 * If the Insurance company address information does not include at least 
		 * Street Address Line 1, City, State and Zip Code, 
		 * then generate an AE message with the description that 
		 * Insurance Company Address is Incomplete.
		*/		
		// Create a policy
		InsurancePolicy policy = this.createMedicareInsurance();

		// Create an address 
		Address address = this.createAddress();
		
		// Save person on file
		policy.setAddress( address );
		onFile.addInsurance( policy );
		Person pristine = this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		
		// Create test insurance address data
		address = this.createAddress();
		address.setLine1( null );
		address.setCity( null );
		address.setZipCode( null );
		policy = this.createPrivateInsurance();
		policy.setAddress( address );
		working.addInsurance( policy );
		
		// Test a scenario where we expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an expected validation exception ", e );
			}
			ValidationMessages messages = e.getValidationMessages();
			assertTrue( !messages.isEmpty() );
			assertEquals( ((ValidationFieldMessage)messages.get().next()).getKey(), 
							  RuleValidationMessage.INSURANCE_COMPANY_ADDRESS_INCOMPLETE.getName() );
		}
		
		// Create test insurance address data
		address = this.createAddress();
		address.setLine1( "Water Run Court" );
		address.setCity( "Ashburn" );
		address.setZipCode( "33428" );
		policy = this.createPrivateInsurance();
		policy.setAddress( address );
		working.addInsurance( policy );

		// Test a scenario where we don't expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an unexpected validation exception ", e );
			}
			this.fail( "Got an un-expected validation exception", e );
		}
	}
	
	/** Tests IsInsuranceEffectiveDateValid_DOB BAL rule in InsuranceValidation
	 * @throws Exception Thrown in case of errors
	 */
	public void testIsInsuranceEffectiveDateValid_DOB() throws Exception {
	
		/** IsInsuranceEffectiveDateValid – 
		 * If the Insurance Effective Date is before the Date of Birth 
		 * then generate an AE message to the site with the description 
		 * that the Insurance Effective Date is invalid, before Date of Birth.
		 */
		
		// Create a policy
		PrivateInsurance policy = this.createPrivateInsurance();
		onFile.addInsurance( policy );
		Person pristine = this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)pristine.clone();
		
		// Create test insurance data
		policy = (PrivateInsurance)working.getInsurances().iterator().next();
		
		policy.setPolicyEffectiveDate( ImpreciseDateUtils.createImpreciseDate( 2000, 10, 19 ) );
		working.setBirthRecord( this.createBirthRecord( new ImpreciseDate( Calendar.getInstance() ) ) );
		
		// Test a scenario where we expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an expected validation exception ", e );
			}
			ValidationMessages messages = e.getValidationMessages();
			assertTrue( !messages.isEmpty() );
			assertEquals( ((ValidationFieldMessage)messages.get().next()).getKey(), 
							  RuleValidationMessage.INVALID_INSURANCE_EFFECTIVE_DATE_DOB_CHECK.getName() );
		}
		
		// Create test insurance data
		policy.setPolicyEffectiveDate( new ImpreciseDate( Calendar.getInstance() ) );
		working.setBirthRecord( this.createBirthRecord( ImpreciseDateUtils.createImpreciseDate( 2000, 10, 19 ) ) );

		// Test a scenario where we don't expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an unexpected validation exception ", e );
			}
			this.fail( "Got an un-expected validation exception", e );
		}
	}
	
	/** Tests IsInsuranceEffectiveDateValid_DOD BAL rule in InsuranceValidation
	 * @throws Exception Thrown in case of errors
	 */
	public void testIsInsuranceEffectiveDateValid_DOD() throws Exception {
		
		/** IsInsuranceEffectiveDateValid – 
		 * If the Insurance Effective Date is after the Date of Death, 
		 * then generate an AE message to the site with the description 
		 * that the Insurance Effective Date is invalid, after Date of Death.
		 */
		
		// Create a policy
		PrivateInsurance policy = this.createPrivateInsurance();
		onFile.addInsurance( policy );
		Person pristine = this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)pristine.clone();
		
		// Create test insurance data
		policy = (PrivateInsurance)working.getInsurances().iterator().next();
		policy.setPolicyEffectiveDate( new ImpreciseDate( Calendar.getInstance() ) );
		working.setDeathRecord( this.createDeathRecord() );
		
		// Test a scenario where we expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an expected validation exception ", e );
			}
			ValidationMessages messages = e.getValidationMessages();
			assertTrue( !messages.isEmpty() );
			assertEquals( ((ValidationFieldMessage)messages.get().next()).getKey(), 
							  RuleValidationMessage.INVALID_INSURANCE_EFFECTIVE_DATE_DOD_CHECK.getName() );
		}
		
		// Create test insurance data
		policy.setPolicyEffectiveDate( ImpreciseDateUtils.createImpreciseDate( 2000, 10, 19 ) );
		DeathRecord dod = new DeathRecord();
		dod.setDeathDate( new ImpreciseDate( Calendar.getInstance() ) );
		working.setDeathRecord( dod );

		// Test a scenario where we don't expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an unexpected validation exception ", e );
			}
			this.fail( "Got an un-expected validation exception", e );
		}
	}
	
	/** Tests IsInsuranceExpirationDateValid BAL rule in InsuranceValidation
	 * @throws Exception Thrown in case of errors
	 */
	public void testIsInsuranceExpirationDateValid() throws Exception {
		
		/** IsInsuranceExpirationDateValid – 
		 * If the Insurance Expiration Date is on or before 
		 * the Insurance Effective Date for the policy, 
		 * then generate an AE message to the site with description 
		 * Insurance Expiration Date must be after Insurance Effective Date.
		 */

		// Create a policy
		PrivateInsurance policy = this.createPrivateInsurance();
		onFile.addInsurance( policy );
		Person pristine = this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		
		// Create test insurance data
		policy = (PrivateInsurance)working.getInsurances().iterator().next();
		policy.setPolicyEffectiveDate( new ImpreciseDate( Calendar.getInstance() ) );
		policy.setPolicyExpirationDate( ImpreciseDateUtils.createImpreciseDate( 2000, 10, 19 ) );	
		
		// Test a scenario where we expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an expected validation exception ", e );
			}
			ValidationMessages messages = e.getValidationMessages();
			assertTrue( !messages.isEmpty() );
			assertEquals( ((ValidationFieldMessage)messages.get().next()).getKey(), 
							  RuleValidationMessage.INVALID_EXPIRATION_DATE_BEFORE_OR_EQUAL_EFFECTIVE_DATE.getName() );
		}
		
		// Create test insurance data
		policy = (PrivateInsurance)working.getInsurances().iterator().next();
		policy.setPolicyExpirationDate( new ImpreciseDate( Calendar.getInstance() ) );
		policy.setPolicyEffectiveDate( ImpreciseDateUtils.createImpreciseDate( 2000, 10, 19 ) );	

		// Test a scenario where we don't expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an unexpected validation exception ", e );
			}
			this.fail( "Got an un-expected validation exception", e );
		}
	}

	/** Tests IsMedicarePartBButNotPartA BAL rule in InsuranceValidation
	 * @throws Exception Thrown in case of errors
	 */
	public void testIsMedicarePartBButNotPartA() throws Exception {
		
		/** IsMedicarePartBButNotPartA - 
		 * if the Medicare Part B Effective Date for the veteran is provided 
		 * and Enrolled in Medicare Part A is not true THEN 
		 * generate an AE message to the site with the description that 
		 * Enrollment is Medicare Part B requires Enrollment in Medicare Part A.
		 */	
		// Create a policy
		Medicare policy = this.createMedicareInsurance();
		onFile.addInsurance( policy );
		Person pristine = this.getPersonService().save( onFile );
		
		// Create a working person
		Person working  = (Person)onFile.clone();
		
		// Create test insurance data
		policy = (Medicare)working.getInsurances().iterator().next();
		policy.setEnrolledInPartA( Boolean.FALSE );
		// policy.setPartBEffectiveDate( Calendar.getInstance().getTime() );
		policy.setPartBEffectiveDate( new ImpreciseDate( Calendar.getInstance() ) );
		
		// Test a scenario where we expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an expected validation exception ", e );
			}
			ValidationMessages messages = e.getValidationMessages();
			assertTrue( !messages.isEmpty() );
			assertEquals( ((ValidationFieldMessage)messages.get().next()).getKey(), 
							  RuleValidationMessage.ENROLLED_IN_PARTB_REQUIRES_PARTA.getName() );
		}
		
		// Create test insurance data
		policy.setEnrolledInPartA( Boolean.TRUE );
		// policy.setPartBEffectiveDate( Calendar.getInstance().getTime() );
		policy.setPartAEffectiveDate( new ImpreciseDate( Calendar.getInstance() ) );

		// Test a scenario where we don't expect a validation message
		try {
			this.getRuleValidationService().validateInsurancePolicy( policy, working, pristine, false  );
		} 
		catch( ValidationServiceException e ) {
			if( logger.isDebugEnabled() ) {
				logger.debug( "Got an unexpected validation exception ", e );
			}
			this.fail( "Got an un-expected validation exception", e );
		}
	}

	/**
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		super.afterPropertiesSet();
		Validate.notNull( this.getInsuranceRuleService(), "An insurance rule service is required" );
		Validate.notNull( this.getInsuranceService(), "An insurance service is required" );
		Validate.notNull( this.getRuleValidationService(), "A rule validation service is required" );
	}
}