/********************************************************************
 * Copyright � 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.service.impl;

// Java Classes
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;

import gov.va.med.esr.UseCaseName;
import gov.va.med.esr.common.clock.Clock.Type;
import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.ee.AgentOrangeExposure;
import gov.va.med.esr.common.model.ee.CDCondition;
import gov.va.med.esr.common.model.ee.CDDescriptor;
import gov.va.med.esr.common.model.ee.CDDiagnosis;
import gov.va.med.esr.common.model.ee.CDProcedure;
import gov.va.med.esr.common.model.ee.CatastrophicDisability;
import gov.va.med.esr.common.model.ee.EnrollmentOverride;
import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.ee.EnvironmentalContaminationExposure;
import gov.va.med.esr.common.model.ee.IneligibilityFactor;
import gov.va.med.esr.common.model.ee.MedicaidFactor;
import gov.va.med.esr.common.model.ee.MilitaryService;
import gov.va.med.esr.common.model.ee.MilitaryServiceSiteRecord;
import gov.va.med.esr.common.model.ee.MonetaryBenefit;
import gov.va.med.esr.common.model.ee.MonetaryBenefitAward;
import gov.va.med.esr.common.model.ee.Pension;
import gov.va.med.esr.common.model.ee.PrisonerOfWar;
import gov.va.med.esr.common.model.ee.PurpleHeart;
import gov.va.med.esr.common.model.ee.RadiationExposure;
import gov.va.med.esr.common.model.ee.SHAD;
import gov.va.med.esr.common.model.ee.ServiceConnectionAward;
import gov.va.med.esr.common.model.lookup.DecorationStatus;
import gov.va.med.esr.common.model.lookup.EligibilityType;
import gov.va.med.esr.common.model.lookup.EligibilityVerificationSource;
import gov.va.med.esr.common.model.lookup.Indicator;
import gov.va.med.esr.common.model.lookup.RegistryType;
import gov.va.med.esr.common.model.lookup.RejectionRemark;
import gov.va.med.esr.common.model.lookup.ServicePeriod;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.messaging.SiteIdentity;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonEntityKey;
import gov.va.med.esr.common.model.person.id.VPIDEntityKey;
import gov.va.med.esr.common.persistent.history.HistoryDAO;
import gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO;
import gov.va.med.esr.common.rule.service.EventRuleService;
import gov.va.med.esr.service.EligibilityEnrollmentService;
import gov.va.med.esr.service.FinancialsHelperService;
import gov.va.med.esr.service.PersonService;
import gov.va.med.esr.service.RegistryService;
import gov.va.med.esr.service.external.person.EligibilitySummary;
import gov.va.med.fw.hl7.InvalidMessageException;
import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.model.AbstractEntity;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.builder.Builder;
import gov.va.med.fw.util.builder.BuilderException;
import gov.va.med.fw.validation.ValidationServiceException;
import gov.va.med.esr.service.EEResultInfo;
import gov.va.med.esr.common.model.ee.CampLejeuneVerification;

/**
 * The Eligibility and Enrollment Service implementation.
 * <p/>
 * Project: Common
 *
 * @author DNS   LEV
 * @author DNS   KATIKM
 * @author Andrew Pach
 * @version 3.0
 */
public class EligibilityEnrollmentServiceImpl extends AbstractHistoricalInfoServiceImpl
    implements EligibilityEnrollmentService
{
    /**
     * Added to fix CR_7516 for ExpireMeansTest batch process to pass PersonService which will not update identity traits.
     */
    private PersonService personServiceWithNoUpdateIdTraits = null;
    /**
     * An instance of serialVersionUID
     */
    private static final long serialVersionUID = 3485681593834139471L;

    /**
     * An instance of registryService.
     */
    private RegistryService registryService = null;

    private Map diagnosisMap;
    private Map procedureMap;
    private Map conditionMap;

    /**
     * An instance of financialsHelperService
     */
    private FinancialsHelperService financialsHelperService = null;

    /**
     * HistoryDAO that retrieves the eligibility history data.
     */
    private HistoryDAO eligibilityHistoryDAO = null;

    private HistoryDAO powHistoryDAO = null;

    /**
     * HistoryDAO that retrieves the enrollment history data.
     */
    private HistoryDAO enrollmentHistoryDAO = null;

    /**
     * HistoryDAO that retrieves the enrollment history data specific tailored for rules.
     */
    private RulesEnrollmentHistoryDAO rulesEnrollmentHistoryDAO = null;

    /**
     * HistoryDAO that retrieves the Health Benefit Plans history data.
     */

    private Builder eligibilitySummaryBuilder;

    public static final String INVALID_MILITARY_DISABILITY_RETIREMENT_WITH_NSC =
        "INVALID_MILITARY_DISABILITY_RETIREMENT_WITH_NSC";
    public static final String MILITARY_DISABILITY_RETIREMENT_FIELD = "disabilityRetirementIndicator";

    /**
     * Default Constructor.
     */
    public EligibilityEnrollmentServiceImpl()
    {
        super();
    }

    /**
     * Assesses the E&E Impact on the incoming person. This method is used when invoked directly from the GUI.  It does
     * not result in the triggering of letters.
     *
     * @param incoming The incoming person
     *
     * @return The updated person
     * @throws ServiceException if any problems were encountered.
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#assessEEImpact(gov.va.med.esr.common.model.person.Person)
     */
    public Person assessEEImpact(Person incoming) throws ServiceException
    {
        // Ensure the veteran was passed in
        Validate.notNull(incoming, "The incoming veteran can not be null.");

        // Get the on-file person
        Person onFile = this.getPersonService().getPerson((PersonEntityKey)incoming.getEntityKey());

        //CCR12710
        if (logger.isDebugEnabled()) {
	          logger.debug("EESvcImpl assessEEImpact 1 : incoming: " + incoming);
	    }


        // Ensure that something changed on the incoming entity as compared to the onFile entity
        ensureEntityChanged(incoming, onFile);

        this.getEnrollmentRuleService()
            .processServiceConnectedIndicator(incoming); // Set the service connected indicator
        this.removeAllEligibilityFactorsFromNonVet(incoming);
        this.getEligibilityFactorRuleService().validateMonetaryBenefit(incoming.getMonetaryBenefitAward(), onFile);

        // Perform the E&E Calculation
        Person calculated = assessEEImpact(incoming, true, true, null);

        //CCR12710
        if (logger.isDebugEnabled()) {
	          logger.debug("EESvcImpl assessEEImpact calculated : calc: " + calculated);
	    }

        // Must perform this validation afterwards since it looks at calculated primary eligibility
        validateMilitaryServiceForEE(calculated);

        // Return the updated person
        return calculated;
    }

    /**
     * Assesses the E&E Impact on the incoming person. This method should be invoked from UI oriented business services
     * (e.g. update methods).  The caller can control whether or not to produce letter triggers. If isReviewOnly is
     * true, this method will NOT trigger letters.  This method is the same as calling assessEEImpact(incoming, true,
     * isReviewOnly, null).
     *
     * @param incoming The incoming person
     * @param isReviewOnly Flag to determine whether this assessment is being done as a review only assessment.
     *
     * @return The updated person
     * @throws ServiceException if any problems were encountered.
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#assessEEImpact(gov.va.med.esr.common.model.person.Person,
     *      boolean)
     */
    public Person assessEEImpact(Person incoming, boolean isReviewOnly) throws ServiceException
    {
        return assessEEImpact(incoming, true, isReviewOnly, null);
    }

    /**
     * Assesses the E&E Impact on the incoming person. This method should be invoked from UI oriented business services
     * (e.g. update methods).  The caller can control whether or not to produce letter triggers. If isReviewOnly is
     * true, this method will NOT trigger letters.  This method supports the passing of an optional clock type.
     *
     * @param incoming The incoming person
     * @param isReviewOnly Flag to determine whether this assessment is being done as a review only assessment.
     * @param clockType the clock type to use during the assessment.
     *
     * @return The updated person
     * @throws ServiceException if any problems were encountered.
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#assessEEImpact(gov.va.med.esr.common.model.person.Person,
     *      boolean, gov.va.med.esr.common.clock.Clock.Type)
     */
    public Person assessEEImpact(Person incoming, boolean isReviewOnly, Type clockType) throws ServiceException
    {
        return assessEEImpact(incoming, true, isReviewOnly, true, clockType, null);
    }

    /**
     * Assesses the E&E Impact on the incoming person. This method can be invoked from the UI or Messaging, but requires
     * the setting of the appropriate flags (i.e. isDataFromUI and isReviewOnly).
     *
     * @param incoming The incoming person
     * @param isDataFromGUI Flag to determine whether this call is being made from a UI flow.
     * @param isReviewOnly Flag to determine whether this assessment is being done as a review only assessment.
     *
     * @return The updated person
     * @throws ServiceException if any problems were encountered.
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#assessEEImpact(gov.va.med.esr.common.model.person.Person,
     *      boolean, boolean)
     */
    public Person assessEEImpact(Person incoming, boolean isDataFromGUI, boolean isReviewOnly) throws ServiceException
    {
    	return assessEEImpact(incoming, isDataFromGUI, isReviewOnly, true, null, null);
    }

    public Person assessEEImpact(Person incoming, boolean isDataFromGUI, boolean isReviewOnly, boolean shouldTriggerHBP) throws ServiceException
    {
    	return assessEEImpact(incoming, isDataFromGUI, isReviewOnly, shouldTriggerHBP, null, null);
    }

    public Person assessEEImpact(Person incoming, boolean isDataFromGUI, boolean isReviewOnly, VAFacility sendingFacility) throws ServiceException
    {
        return assessEEImpact(incoming, isDataFromGUI, isReviewOnly, true, null, sendingFacility);
    }

    /**
     * This is the main entry point into performing E&E calculations. This method delegates to doEECalculation(incoming,
     * isDataFromGUI, isReviewOnly, clockType).
     */
    private Person assessEEImpact(Person incoming, boolean isDataFromGUI, boolean isReviewOnly, boolean shouldTriggerHBP, Type clockType, VAFacility sendingFacility)
        throws ServiceException
    {
        // Ensure the veteran was passed in
        Validate.notNull(incoming, "The incoming veteran can not be null.");

        //CCR12710
        if (logger.isDebugEnabled()) {
	          logger.debug("EESvcImpl assessEEImpact main : incoming: " + incoming);
	    }

        // Perform the E&E calculation
        return this.doEECalculation(incoming, isDataFromGUI, isReviewOnly, shouldTriggerHBP, clockType, sendingFacility);
    }

    /**
     * This method only intended for use by the Expire Means Test batch process.
     *
     * @param key - Identifies the person
     * @return - boolean indicating whether person is subject to means test
     */
    public boolean processExpiredMeansTestForBatchProcess(PersonEntityKey key) throws ServiceException
    {
        Person person = this.getPersonServiceWithNoUpdateIdTraits().getPerson(key);

        //if the person is subject to MT asses EE
        if (getFinancialsHelperService().isSubjectToMeansTestForBatchProcess(person))
        {
            this.assessEEImpact(person, false, false, null);

            // Handle post events
            EventRuleService eventRuleService = this.getEventRuleService();
            eventRuleService.manageMessageEvents(person);
            //ccr11159
            eventRuleService.manageHandBookEvents(person);

            // Persist the person
            this.getPersonServiceWithNoUpdateIdTraits().save(person);
            return true;
        }
        // if the person is not subject to MT return false
        else
        {
            return false;
        }
    }



    public Person processCalculateEEForCleanup(PersonEntityKey key, boolean savePerson, boolean triggerEvents) throws ServiceException {
        Person person = this.getPersonService().getPerson(key);

        this.getEnrollmentRuleService().calculateEEForCleanup(person);

        if (triggerEvents)
        {
            // Handle post events
            EventRuleService eventRuleService = this.getEventRuleService();
            eventRuleService.manageMessageEvents(person);
            //CCR11159
            eventRuleService.manageHandBookEvents(person);
        }
        if (savePerson)
        {
            // Persist the person
            return this.getPersonService().save(person);
        }
        return person;
	}

	/**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#processCalculateEE(gov.va.med.esr.common.model.person.id.PersonEntityKey,
     *      boolean, boolean)
     */
    public Person processCalculateEE(PersonEntityKey key, boolean savePerson, boolean triggerEvents)
        throws ServiceException
    {
        Person person = this.getPersonService().getPerson(key);

        this.assessEEImpact(person, false, false, null);

        //CCR12710
        if (logger.isDebugEnabled()) {
	          logger.debug("EESvcImpl procCalcEE : person: " + person);
	    }

        if (triggerEvents)
        {
            // Handle post events
            EventRuleService eventRuleService = this.getEventRuleService();
            eventRuleService.manageMessageEvents(person);
            // all the process is done. call handbook rule service. ccr 11159
            eventRuleService.manageHandBookEvents(person);
        }
        if (savePerson)
        {
            // Persist the person
            return this.getPersonService().save(person);
        }
        return person;
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#processCalculateEEOverride(gov.va.med.esr.common.model.person.id.PersonEntityKey,
     *      boolean, boolean)
     */
    public Person processCalculateEEOverride(PersonEntityKey key, boolean savePerson, boolean triggerEvents)
        throws ServiceException
    {
        Boolean override = new Boolean(true);


        Person person = this.getPersonService().getPerson(key);

        if(person.getEnrollmentOverride() != null){
            person.getEnrollmentOverride().setOverride(override);
            person.getEnrollmentOverride().setOverrideBy("Batch ReprocessCERec");
            person.getEnrollmentOverride().setOverrideDate(new Date());

        }
        else{
            EnrollmentOverride eo = new EnrollmentOverride();
            eo.setOverride(override);
            eo.setOverrideBy("Batch ReprocessCERec");
            eo.setOverrideDate(new Date());
            person.setEnrollmentOverride(eo);
        }
        //CCR12710
        if (logger.isDebugEnabled()) {
	          logger.debug("EESvcImpl procCalcEEOverride : person: " + person);
	    }

        this.assessEEImpact(person, false, false, null);

        if (triggerEvents)
        {
            // Handle post events
            EventRuleService eventRuleService = this.getEventRuleService();
            eventRuleService.manageMessageEvents(person);
            eventRuleService.manageHandBookEvents(person);
        }
        if (savePerson)
        {
            // Persist the person
            return this.getPersonService().save(person);
        }
        return person;
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#updateEligibilityData(gov.va.med.esr.common.model.person.Person)
     */
    public Person updateEligibilityData(Person incoming) throws ServiceException
    {
        Validate.notNull(incoming, "A veteran must not be null");
        
        Person onFile = this.getPersonService().getPerson((PersonEntityKey)incoming.getEntityKey());

        // Note that ensureEntityChanged is not called here because on the UI, the user calls
        // assessEEImpact before calling updateEligibilityData and it will be checked there.

        // Validate that an enrollment record exists for the on-file Person
        validateEnrollmentDetermination(onFile);

        // Process rules and merge
        onFile.setVeteran(incoming.getVeteran());
        this.getEnrollmentRuleService()
            .processServiceConnectedIndicator(incoming); // Set the service connected indicator
        this.getEnrollmentRuleService().manageIneligibility(incoming, onFile);
        this.getEnrollmentRuleService().manageReceivedEligibilities(incoming, onFile);
        this.getEligibilityFactorRuleService().processIncompetenceRuling(incoming.getIncompetenceRuling(), onFile);
        this.getInsuranceRuleService().manageMedicaidFactor(incoming.getMedicaidFactor(), onFile);


        this.getEligibilityFactorRuleService().manageMonetaryBenefitAward(incoming.getMonetaryBenefitAward(), onFile);
        this.getEligibilityFactorRuleService()
            .processServiceConnectionAward(incoming.getServiceConnectionAward(), onFile);
        this.getEligibilityFactorRuleService().manageSpecialFactors(incoming, onFile);
        this.getEligibilityFactorRuleService()
            .manageEligibilityVerification(incoming.getEligibilityVerification(), onFile);

        // Update PH only when something is changed.
        if (!AbstractEntity.matchesDomainValues(incoming.getPurpleHeart(), onFile.getPurpleHeart()))
        {
            this.getPurpleHeartRuleService().managePurpleHeart(incoming, onFile);
        }

        this.getPowRuleService().managePOW(incoming, onFile);
        // Bypass Military Service validation until later
        this.getMilitaryRuleService().manageMilitaryService(incoming.getMilitaryService(), onFile, true);

        // Execute Rules - use review only since want to delay sending letters until after
        // we calculate E&E
        this.getEnrollmentRuleService().calculateEE(onFile, true, true);

        // Perform Military Service validation on calculated person
        validateMilitaryServiceForEE(onFile);

        // Calculate POS
        this.getMilitaryRuleService().calculatePeriodOfServiceForUI(incoming, onFile, UseCaseName.EE);

        //Recalculate POS if POS is still absent
        recalculatePOS(incoming, onFile);

        this.getCommunicationRuleService().triggerAutomaticLetters(onFile, null, false, null);

        // Handle post events
        EventRuleService eventRuleService = this.getEventRuleService();
        eventRuleService.manageMessageEvents(onFile);
        eventRuleService.managePersonEvents(onFile);

        //Link POW Registry
        PrisonerOfWar incomingPOW = incoming.getPrisonerOfWar();
        if (incomingPOW != null && onFile != null && incomingPOW.getRegistryTrait() == null)
        {
            RegistryType regType = (RegistryType)this.getLookupService()
                .getByCode(RegistryType.class, RegistryType.CODE_POW_REGISTRY.getCode());
            this.getRegistryService()
                .linkPersonRegistry(incomingPOW, onFile.getPrisonerOfWar(), incoming, onFile, regType, true);
        }
        //hanbook
        eventRuleService.manageHandBookEvents(onFile);
      
        // Persist the person
        return this.getPersonService().save(onFile);

       
    }

    //This is done only if POS is not yet calculated
    private boolean recalculatePOS(Person incoming, Person onFile) throws ServiceException {
    	boolean isSuccess = false;
		if (incoming != null && onFile != null) {
	        MilitaryService militaryService = incoming.getMilitaryService();
	        MilitaryServiceSiteRecord hecSite = militaryService.getHECMilitaryServiceSiteRecord();
	        ServicePeriod servicePeriod = (hecSite != null) ? hecSite.getServicePeriod() : null;
	        if(servicePeriod == null || servicePeriod.getCode() == null) {

	        	this.getMilitaryRuleService().calculatePeriodOfServiceForUI(incoming, onFile, UseCaseName.MS);

		        militaryService = onFile.getMilitaryService();
		        hecSite = militaryService.getHECMilitaryServiceSiteRecord();
		        servicePeriod = (hecSite != null) ? hecSite.getServicePeriod() : null;
		        if(servicePeriod != null) {
		        	String posCode = servicePeriod.getCode();
		        	logger.info("Recalculated POS is "+posCode+":"+servicePeriod.getName()+servicePeriod.getDescription());
		        }
	        }

		}
    	return isSuccess;
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#updateEnrollmentData(gov.va.med.esr.common.model.person.Person)
     */
    public Person updateEnrollmentData(Person incoming) throws ServiceException
    {
        Validate.notNull(incoming, "A veteran must not be null");

        Person onFile = this.getPersonService().getPerson((PersonEntityKey)incoming.getEntityKey());

        // Ensure that something changed on the incoming entity as compared to the onFile entity
        ensureEntityChanged(incoming, onFile);

        // Validate that an enrollment record exists for the on-file Person
        validateEnrollmentDetermination(onFile);

        // Process rules and merge
        this.getEnrollmentRuleService().manageApplication(incoming.getApplication(), onFile);
        this.getEnrollmentRuleService().processCancelDecline(incoming.getCancelDecline(), onFile);
        this.getEligibilityFactorRuleService().manageEnrollmentOverride(incoming.getEnrollmentOverride(), onFile);

        // Execute ee calculation
        Person calculatedPerson = assessEEImpact(onFile, false);

        // Handle post events
        EventRuleService eventRuleService = this.getEventRuleService();
        eventRuleService.manageMessageEvents(calculatedPerson);
        eventRuleService.managePersonEvents(calculatedPerson);
        eventRuleService.manageHandBookEvents(calculatedPerson);
        // Persist the person
        return this.getPersonService().save(calculatedPerson);
    }

    public boolean isServicePeriodNeeded(Person incoming) throws ServiceException
    {
        Validate.notNull(incoming, "A veteran must not be null");

        if (incoming.getEnrollmentDetermination() != null &&
            incoming.getEnrollmentDetermination().getPrimaryEligibility() != null)
        {
            EligibilityType type = incoming.getEnrollmentDetermination().getPrimaryEligibility().getType();
            String code = (type == null) ? null : type.getCode();
            if (code != null &&
                (code.equals(EligibilityType.ALLIED_VETERAN.getCode())
                    || code.equals(EligibilityType.OTHER_FEDERAL_AGENCY.getCode())
                    || code.equals(EligibilityType.COLLATERAL_OF_VETERAN.getCode())
                    || code.equals(EligibilityType.CHAMPVA.getCode())
                    || code.equals(EligibilityType.EMPLOYEE.getCode())
                    || code.equals(EligibilityType.SHARING_AGREEMENT.getCode())
                    || code.equals(EligibilityType.TRICARE_CHAMPUS.getCode())
                ))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#getEligibilityHistoryChangeTimes(gov.va.med.fw.model.EntityKey)
     */
    public Set getEligibilityHistoryChangeTimes(EntityKey personID) throws ServiceException
    {
        try
        {
            return eligibilityHistoryDAO.getHistoryChangeTimes(personID);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#getEligibilityHistoryByChangeTime(gov.va.med.esr.service.impl.ChangeEvent)
     */
    public HistoricalInfo getEligibilityHistoryByChangeTime(ChangeEvent event) throws ServiceException
    {
        try
        {
            return eligibilityHistoryDAO.getHistoryByChangeTime(event);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /*
      *
      * @see gov.va.med.esr.service.EligibilityEnrollmentService#getEnrollmentHistoryChangeTimes(gov.va.med.fw.model.EntityKey)
      */
    public Set getEnrollmentHistoryChangeTimes(EntityKey personID)
        throws ServiceException
    {
        try
        {
            return enrollmentHistoryDAO.getHistoryChangeTimes(personID);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }


    /*
    * @see gov.va.med.esr.service.EligibilityEnrollmentService#getEnrollmentHistoryByChangeTime(gov.va.med.esr.service.impl.ChangeEvent)
    */
    public HistoricalInfo getEnrollmentHistoryByChangeTime(ChangeEvent event) throws ServiceException
    {
        try
        {
            return enrollmentHistoryDAO.getHistoryByChangeTime(event);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /*
    * @see gov.va.med.esr.service.EligibilityEnrollmentService#getAppDateForMostRecentUnverifiedEnrollment(gov.va.med.fw.model.EntityKey)
    */
    public Date getAppDateFromEarliestUnverifiedEnrollment(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getEnrollmentApplicationDateForEarliestSpecifiedStatusUnlessCancelledOrRejectedBelowThreshold(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * Return true if the person has ANY enrollment record before the specified date
     * @param personId
     * @param beofreDate
     * @return
     * @throws DAOException
     */
    public boolean hasAnyEnrollmentRecordBeforeDate(EntityKey personId, Date beforeDate) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.hasAnyEnrollmentRecordBeforeDate(personId, beforeDate);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /*
    * @see gov.va.med.esr.service.EligibilityEnrollmentService#getFirstNotNullEffDate(gov.va.med.fw.model.EntityKey)
    */
    public Date getFirstNotNullEffDate(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getFirstNotNullEffDate(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /*
    * @see gov.va.med.esr.service.EligibilityEnrollmentService#getPersonForPriorEnrollment(gov.va.med.fw.model.EntityKey)
    */
    public Person getPersonForPriorEnrollment(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getPersonForPriorEnrollment(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }

    }

    /**
     * Returns the enrollment status and application date for the earliest enrollment.
     *
     * @param personId
     *
     * @return
     * @throws ServiceException
     */
    public Object[] getStatusAndAppDateForEarliest(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getStatusAndAppDateForEarliest(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * Returns the codes for priority group and priority subGroup for the most recent enrollment.
     *
     * @param personId
     *
     * @return
     * @throws ServiceException
     */
    public String[] getPriorityGrpsForMostRecent(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getPriorityGrpsForMostRecent(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * Returns the Enrollment Date from the earliest enrollment with Verified Status UNLESS a Cancel Decline Status is
     * encountered, in which case use subsequent (one more recent than cancel).
     *
     * @param personId
     *
     * @return
     * @throws ServiceException
     */
    public Date getEnrollmentDateForEarliestVerifiedUnlessCancelled(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getEnrollmentDateForEarliestVerifiedUnlessCancelled(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * Returns the Effective Date from the earliest enrollment with Verified Status UNLESS a Cancel Decline Status is
     * encountered, in which case use subsequent (one more recent than cancel).
     *
     * @param personId
     *
     * @return
     * @throws ServiceException
     */
    public Date getEffectiveDateForEarliestVerifiedUnlessCancelledOrRejectedBelowEnrollmentThreshold(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getEffectiveDateForEarliestVerifiedUnlessCancelledOrRejectedBelowEnrollmentThreshold(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * Returns the Enrollment Determination record from the earliest enrollment with Verified Status UNLESS a Cancel Decline Status is
     * encountered, in which case use subsequent (one more recent than cancel).
     *
     * @param personId
     *
     * @return
     * @throws ServiceException
     */
    public EnrollmentDetermination getEnrollmentDeterminationForEarliestVerifiedUnlessCancelledOrRejectedBelowEnrollmentGroupThreshold(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getEnrollmentDeterminationForEarliestVerifiedUnlessCancelledOrRejectedBelowEnrollmentGroupThreshold(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
	 * @see gov.va.med.esr.service.EligibilityEnrollmentService#getEarliestEnrollmentEffectiveDatewithAOWatDMZ(gov.va.med.fw.model.EntityKey)
	 */
    public Date getEarliestEnrollmentEffectiveDatewithAOWatDMZ(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getEarliestEnrollmentEffectiveDatewithAOWatDMZ(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
      * @see gov.va.med.esr.service.EligibilityEnrollmentService#isApplicationDatePriortoEGTEffectiveDate(gov.va.med.fw.model.EntityKey)
      */
    public boolean isApplicationDatePriortoEGTEffectiveDate(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.isApplicationDatePriortoEGTEffectiveDate(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
      * @see gov.va.med.esr.service.EligibilityEnrollmentService#isVerifiedEnrollmentExistsforCombatVeteran(gov.va.med.fw.model.EntityKey)
      */
    public boolean isVerifiedEnrollmentExistsforCombatVeteran(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.isVerifiedEnrollmentExistsforCombatVeteran(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }


    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#isVerifiedEnrollmentExists(gov.va.med.fw.model.EntityKey)
     */
    public boolean isVerifiedEnrollmentExists(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.isVerifiedEnrollmentExists(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
	 * @see gov.va.med.esr.service.EligibilityEnrollmentService#isVerifiedEnrollmentExistsForEligibilityCode(gov.va.med.fw.model.EntityKey, java.lang.String)
	 */
    public boolean isVerifiedEnrollmentExistsForEligibilityCode(EntityKey personId, String eligiblityTypeCode)
        throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.isVerifiedEnrollmentExistsForEligibilityCode(personId, eligiblityTypeCode);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
	 * DNS   doank: CCR 8797
	 *
     */
    public boolean isVerifiedEnrollmentExistsForMedicaidEligibility(EntityKey personId) throws ServiceException
    {
    	try
        {
            return rulesEnrollmentHistoryDAO.isVerifiedEnrollmentExistsForMedicaidEligibility(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#getIncomeYearForVerifiedMT(gov.va.med.fw.model.EntityKey)
     */
    public Integer getIncomeYearForVerifiedMT(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getIncomeYearForVerifiedMT(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    public List getIncomeYearsForVerifiedMT(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getIncomeYearsForVerifiedMT(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }


    // CodeCR10023 and CR9803
    public List getIncomeYearsFromVerifiedEnrollmentDueToP8(EntityKey personId) throws ServiceException {
        try
        {
            return rulesEnrollmentHistoryDAO.getIncomeYearsForVerifiedP8(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
	}

    // CodeCR10023 and CR9803
    public String[] getMostRecentVerifiedEnrollmentPriorityGroups(EntityKey personId) throws ServiceException {
        try
        {
            return rulesEnrollmentHistoryDAO.getMostRecentVerifiedEnrollmentPriorityGroups(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
	}

    // CodeCR10023 and CR9803
	public boolean hasIncomeTestMeetingP8RecheckCriteria(EntityKey personId, float relaxPercent) throws ServiceException {
        try
        {
            return rulesEnrollmentHistoryDAO.hasIncomeTestMeetingP8RecheckCriteria(personId, relaxPercent);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
	}


    // CodeCR10023 and CR9803
	public List getHistoricalIncomeYearsForVerifiedMT(EntityKey personId) throws ServiceException {
        try
        {
            return rulesEnrollmentHistoryDAO.getHistoricalIncomeYearsForVerifiedMT(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
	}

	/* (non-Javadoc)
	 * @see gov.va.med.esr.service.EligibilityEnrollmentService#isVerifiedEnrollmentExistsforSvcConnPercent(gov.va.med.fw.model.EntityKey, java.lang.Integer)
	 */
    public boolean isVerifiedEnrollmentExistsforSvcConnPercent(EntityKey personId, Integer percent)
        throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.isVerifiedEnrollmentExistsforSvcConnPercent(personId, percent);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    public EnrollmentDetermination getMostRecentEnrollmentforContinuousEnrollment(EntityKey personId) throws ServiceException {
        try
        {
            EnrollmentDetermination e = new EnrollmentDetermination();
            EEResultInfo results = rulesEnrollmentHistoryDAO.getMostRecentEnrollmentforContinuousEnrollment(personId);
            if (results != null) {
                e.setEffectiveDate(results.getEffectiveDate());
                Integer flag = results.getOverrideFlag();
                e.setOverridden(new Boolean(flag != null && flag.equals(new Integer(1)) ));
                e.setEnrollmentStatus(results.getStatusCode() != null ?
                        this.getLookupService().getEnrollmentStatusByCode(results.getStatusCode()) : null);
                e.setPriorityGroup(results.getGroupCode() != null ?
                        this.getLookupService().getEnrollmentPriorityGroupByCode(results.getGroupCode()) : null);
                return e;
            }
            return null;
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * Returns the enrollment priority code and status code before PH was added. Used when letter 630D is triggered
     * @param personId
     * @return String[] with enrollment priority code and enrollment status code. Return null if not found.
     */
    public String[] getEnrollmentPriorityBeforePH(EntityKey personId)
        throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getEnrollmentPriorityBeforePH(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#getMostRecentNonNullPriorityCode(gov.va.med.fw.model.EntityKey)
     */
    public String getMostRecentNonNullPriorityCode(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getMostRecentNonNullPriorityCode(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    public String getMostRecentNonNullPriorityLevelByDate(EntityKey personId, Date beforeDate) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getMostRecentNonNullPriorityLevelByDate(personId, beforeDate);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#removeAllEligibilityFactorsFromNonVet(gov.va.med.esr.common.model.person.Person)
     */
    public void removeAllEligibilityFactorsFromNonVet(Person incoming) throws ServiceException
    {
        if (incoming != null)
        {
            IneligibilityFactor inelig = incoming.getIneligibilityFactor();
            if (inelig != null && inelig.getIneligibleDate() != null && inelig.getReason() != null)
            {
                ServiceConnectionAward scw = incoming.getServiceConnectionAward();
                if (scw == null || (scw != null && (scw.getServiceConnectedIndicator() == null || (
                    scw.getServiceConnectedIndicator() != null && !scw.getServiceConnectedIndicator().booleanValue()))))
                {
                    this.removeAllEligibilityFactors(incoming);
                    incoming.setVeteran(Boolean.FALSE);
                }
            }
        }

    }

    public void removeAllEligibilityFactors(Person incoming) throws ServiceException
    {
        /*
         * 5919 [UC33.3.3.4] When the Veteran Indicator is changed from YES to
         * NO the system automatically sets several fields as follows:
         */
        if (incoming != null)
        {

            Indicator noIndicator = this.getLookupService().getIndicatorByCode(Indicator.NO);
            // POW Indicator � If Yes, set to No and set all other POW fields to NULL.
            // Doing what UI does:
            PrisonerOfWar pow = incoming.getPrisonerOfWar();
            if (pow != null)
            {
                pow.setPowIndicator(noIndicator);
                pow.removeAllEpisodes();
                pow.setIcn(null);
                pow.setDateEntered(null);
                pow.setUser(null);
            }

            PurpleHeart ph = incoming.getPurpleHeart();
            //PH Indicator � If Yes, set to No and set Rejected Remark to Entered In Error
            //and PH status to Rejected; If No, leave as No and set Rejected Remark to Entered in Error
            if (ph != null)
            {
                if (ph.getPhIndicator() != null)
                {
                    if (ph.getPhIndicator().booleanValue())
                    {

                        ph.setPhIndicator(Boolean.FALSE);
                        ph.setRejectionRemark(this.getLookupService().getRejectionRemarkByCode(
                            RejectionRemark.CODE_ENTERED_IN_ERROR.getCode()));
                        //DecorationStatus
                        ph.setStatus(this.getLookupService().getDecorationStatusByCode(
                            DecorationStatus.CODE_REJECTED.getCode()));
                    }
                    else
                    {
                        ph.setRejectionRemark(this.getLookupService().getRejectionRemarkByCode(
                            RejectionRemark.CODE_ENTERED_IN_ERROR.getCode()));
                    }
                }
            }

            //SHAD Indicator � If Yes, set to No
            SHAD shad = incoming.getShad();
            if (shad != null)
            {
                shad.setShadIndicator(noIndicator);
            }

            MonetaryBenefitAward mba = incoming.getMonetaryBenefitAward();
            if (mba != null)
            {
                //Aid and Attendance Indicator � If Yes, set to No
                MonetaryBenefit aa = mba.getAidAndAttendance();
                if (aa != null)
                {
                    aa.setMonetaryBenefitIndicator(noIndicator);
                }

                //Housebound Indicator � If Yes, set to No
                MonetaryBenefit hb = mba.getHouseBound();
                if (hb != null)
                {
                    hb.setMonetaryBenefitIndicator(noIndicator);
                }

                //VA Pension � If Yes, set to No
                MonetaryBenefit va = mba.getVAPension();
                if (va != null)
                {
                    va.setMonetaryBenefitIndicator(noIndicator);
                    Pension pension = va.getPension();
                    if(pension != null){
                    	pension.setAwardReasonCode(null);
                    	pension.setEffectiveDate(null);
                    }
                }

                //Receiving VA Disability Compensation Indicator � If Yes, set to No
                MonetaryBenefit dc = mba.getDisabilityCompensation();
                if (dc != null)
                {
                    dc.setMonetaryBenefitIndicator(noIndicator);
                }

                //Total Check Amount � Null
                mba.setCheckAmount(null);
            }

            ServiceConnectionAward scw = incoming.getServiceConnectionAward();

            if (scw != null)
            {
                //Unemployable Indicator � If Yes, set to No
                scw.setUnemployable(Boolean.FALSE);

                //P&T Indicator � If Yes, set to No and set P&T Effective Date � Null
                scw.setPermanentAndTotal(Boolean.FALSE);
                scw.setPermanentAndTotalEffectiveDate(null);

                //SC% - Null
                scw.setServiceConnectedPercentage(null);

                //SC Indicator - If Yes, set to No
                scw.setServiceConnectedIndicator(Boolean.FALSE);

                //Rated Disability Fields � Null
                scw.removeAllRatedDisability();
            }


            MilitaryService ms = incoming.getMilitaryService();
            if (ms != null)
            {
                //Discharge Due to Disability � If Yes, set to No
                ms.setDisabilityRetirementIndicator(Boolean.FALSE);

                //Military Disability Retirement � If Yes, set to No
                ms.setDischargeDueToDisability(Boolean.FALSE);

                //CV End Date � Null
                ms.setCombatVeteranEligibilityEndDate(null);
            }

            //Eligible for Medicaid Indicator � If Yes, set to No and Capture Date/Time Last Updated when set
            MedicaidFactor mf = incoming.getMedicaidFactor();
            if (mf != null)
            {
                mf.setEligibleForMedicaid(Boolean.FALSE);
                mf.setLastUpdateDate(new Date());
            }


            AgentOrangeExposure aoe = incoming.getAgentOrangeExposure();
            if (aoe != null)
            {
                //Agent Orange Indicator � If Yes, set to No
                aoe.setAgentOrangeExposureIndicator(noIndicator);

                //Agent Orange Location � Null
                aoe.setLocation(null);
            }

            RadiationExposure re = incoming.getRadiationExposure();
            if (re != null)
            {
                //Radiation Exposure Indicator � If Yes, set to No
                re.setRadiationExposureIndicator(noIndicator);

                //Radiation Exposure Method � Null
                re.setExposureMethod(null);
            }


            EnvironmentalContaminationExposure ecx = incoming.getEnvironmentalContaminationExposure();
            if (ecx != null)
            {
                //SW Asia Conditions Indicator � If Yes, set to No
                ecx.setEnvironmentalContaminationExposureIndicator(noIndicator);
            }


            //////////////////////////////////////CLV///////////////////////////////////////////////////
            CampLejeuneVerification clv = incoming.getCampLejeuneVerification();
            if(clv != null)
            {
            	clv.setSpecialFactorIndicator(noIndicator);
            }
            //////////////////////////////////////CLV///////////////////////////////////////////////////


            //Incompetent Indicator, VA and/or Civil Dates � Do not change the values
            //CD Indicator/CD Data�Do not change the values
            //MST Data- Do not change the values
            //NTR Data � Do not change the values
        }
    }

    private Person doEECalculation(Person incoming, boolean isDataFromGUI, boolean isReviewOnly, boolean shouldTriggerHBP, Type clockType, VAFacility sendingFacility)
        throws ServiceException
    {
    	//WI# 193135 - ensure CD conversion upon each EE calculation
    	CatastrophicDisability cd = incoming.getCatastrophicDisability();
        if (cd != null && cd.isCatastrophicallyDisabled() != null && cd.isCatastrophicallyDisabled().booleanValue() &&
        		cd.getCDDescriptors().isEmpty()) {
        	this.convertCDOnly(incoming);
        }

    	// The incoming person will have the results added to it.
        this.getEnrollmentRuleService().calculateEE(incoming, isDataFromGUI, isReviewOnly, shouldTriggerHBP, clockType, sendingFacility);
        return incoming;

    }

    /**
	 * Convert the CD to use descriptors. Leaves the existing CDP sets untouched.
	 * Return true if descriptor added/exists
	 */
	@SuppressWarnings("unchecked")
	public boolean convertCDOnly(Person person) throws ServiceException {
		CatastrophicDisability cd = person.getCatastrophicDisability();
		Set<CDDescriptor> descriptorsToAdd = new HashSet<CDDescriptor>();
		boolean existsAlready = false;

		if (cd != null) {

			Set<CDDescriptor> descriptors = cd.getCDDescriptors();
			if (descriptors.size() > 0) {
				existsAlready = true;
			}

			Set<CDCondition> conditions = cd.getConditions();
			for (CDCondition cdCondition : conditions) {
				String code = cdCondition.getCondition().getCode();
				String translated = (String)getConditionMap().get(code);
				if (translated != null) {
					descriptorsToAdd.add(buildCDDescriptor(translated));
				}
			}
			Set<CDProcedure> procedures = cd.getProcedures();
			for (CDProcedure cdProcedure : procedures) {
				String code = cdProcedure.getProcedure().getCode();
				String translated = (String)getProcedureMap().get(code);
				if (translated != null) {
					descriptorsToAdd.add(buildCDDescriptor(translated));
				}
			}
			Set<CDDiagnosis> diagnoses = cd.getDiagnoses();
			for (CDDiagnosis cdDiagnosis : diagnoses) {
				String code = cdDiagnosis.getDiagnosis().getCode();
				String translated = (String)getDiagnosisMap().get(code);
				if (translated != null) {
					descriptorsToAdd.add(buildCDDescriptor(translated));				}
			}
			for (CDDescriptor descriptorToAdd : descriptorsToAdd) {
				boolean exists = false;
				for (CDDescriptor descriptor : descriptors){
					if (descriptor.getDescriptorType().getCode().equals(
							descriptorToAdd.getDescriptorType().getCode())) {
						exists = true;
						break;
					}
				}
				if (!exists) {
					cd.addCDDescriptor(descriptorToAdd);
				}
			}
		}
		// We want to force Z11 if descriptor exists
		return descriptorsToAdd.size() > 0 || existsAlready;
	}

	private CDDescriptor buildCDDescriptor(String code) throws ServiceException {
		CDDescriptor cdd = new CDDescriptor();
		cdd.setDescriptorType(this.getLookupService().getDescriptorTypeByCode(code));
		return cdd;
	}

    public HistoryDAO getEligibilityHistoryDAO()
    {
        return eligibilityHistoryDAO;
    }

    public void setEligibilityHistoryDAO(HistoryDAO eligibilityHistoryDAO)
    {
        this.eligibilityHistoryDAO = eligibilityHistoryDAO;
    }

    public HistoryDAO getPowHistoryDAO() {
        return this.powHistoryDAO;
    }

    public void setPowHistoryDAO(HistoryDAO powHistoryDAO) {
        this.powHistoryDAO = powHistoryDAO;
    }

    public HistoryDAO getEnrollmentHistoryDAO()
    {
        return enrollmentHistoryDAO;
    }

    public void setEnrollmentHistoryDAO(HistoryDAO enrollmentHistoryDAO)
    {
        this.enrollmentHistoryDAO = enrollmentHistoryDAO;
    }

    public RulesEnrollmentHistoryDAO getRulesEnrollmentHistoryDAO()
    {
        return rulesEnrollmentHistoryDAO;
    }

    public void setRulesEnrollmentHistoryDAO(RulesEnrollmentHistoryDAO rulesEnrollmentHistoryDAO)
    {
        this.rulesEnrollmentHistoryDAO = rulesEnrollmentHistoryDAO;
    }

    /**
     * @return Returns the registryService.
     */
    public RegistryService getRegistryService()
    {
        return registryService;
    }

    /**
     * Sets registryService.
     *
     * @param registryService
     */
    public void setRegistryService(
        RegistryService registryService)
    {
        this.registryService = registryService;
    }

    public FinancialsHelperService getFinancialsHelperService()
    {
        return this.financialsHelperService;
    }

    public void setFinancialsHelperService(
        FinancialsHelperService financialsHelperService)
    {
        this.financialsHelperService = financialsHelperService;
    }

    private void validateMilitaryServiceForEE(Person calculated) throws ValidationServiceException
    {
        MilitaryService ms = calculated.getMilitaryService();
        if (ms != null)
        {
            Boolean dri = ms.getDisabilityRetirementIndicator();
            if (dri != null && dri.booleanValue())
            {
                String primary = (calculated.getEnrollmentDetermination() != null &&
                    calculated.getEnrollmentDetermination().getPrimaryEligibility() != null &&
                    calculated.getEnrollmentDetermination().getPrimaryEligibility().getType() != null) ?
                    calculated.getEnrollmentDetermination().getPrimaryEligibility().getType().getCode() : null;
                //DNS   doank: CCR8890 Remove failure of NSC Military Disability Retirement
                /*
                if (EligibilityType.NSC.getCode().equals(primary))
                {
                    ValidationMessages validationMessages = new ValidationMessages();
                    validationMessages.add(new ValidationMessage(
                        INVALID_MILITARY_DISABILITY_RETIREMENT_WITH_NSC,
                        MILITARY_DISABILITY_RETIREMENT_FIELD));
                    throw new ValidationServiceException(validationMessages);
                }
                */
            }
        }
    }

    /* (non-Javadoc)
      * @see gov.va.med.esr.service.PersonService#getEligibilitySummary(gov.va.med.esr.service.external.person.VPIDEntityKey)
      */
    public EligibilitySummary getEligibilitySummary(gov.va.med.esr.service.external.person.VPIDEntityKey vpid)
        throws ServiceException
    {
    	if(logger.isInfoEnabled())
    		logger.info("Received an external request to getEligibilitySummary for VPID: " + vpid.getVPID());

        VPIDEntityKey internalVpid = CommonEntityKeyFactory.createVPIDEntityKey(vpid);
        Person person = this.getPersonService().getPerson(internalVpid);
        try
        {
            return (EligibilitySummary)eligibilitySummaryBuilder.build(person);
        }
        catch (BuilderException e)
        {
            throw new ServiceException("Unable to get EligibilitySummary", e);
        }
    }

    /**
     * @return Returns the eligibilitySummaryBuilder.
     */
    public Builder getEligibilitySummaryBuilder()
    {
        return eligibilitySummaryBuilder;
    }

    /**
     * @param eligibilitySummaryBuilder The eligibilitySummaryBuilder to set.
     */
    public void setEligibilitySummaryBuilder(Builder eligibilitySummaryBuilder)
    {
        this.eligibilitySummaryBuilder = eligibilitySummaryBuilder;
    }

    /* (non-Javadoc)
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#getPOWHistoryChangeTimes(gov.va.med.fw.model.EntityKey)
     */
    public Set getPOWHistoryChangeTimes(EntityKey personID) throws ServiceException {
        try
        {
            return powHistoryDAO.getHistoryChangeTimes(personID);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
     * @see gov.va.med.esr.service.EligibilityEnrollmentService#getPOWHistoryHistoryByChangeTime(gov.va.med.esr.service.impl.ChangeEvent)
     */

    public HistoricalInfo getPOWHistoryByChangeTime(ChangeEvent event) throws ServiceException {
        try
        {
            return powHistoryDAO.getHistoryByChangeTime(event);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

	public PersonService getPersonServiceWithNoUpdateIdTraits() {
		return personServiceWithNoUpdateIdTraits;
	}

	public void setPersonServiceWithNoUpdateIdTraits(
			PersonService personServiceWithNoUpdateIdTraits) {
		this.personServiceWithNoUpdateIdTraits = personServiceWithNoUpdateIdTraits;
	}

    public List getEnrollmentDeterminationHistory(EntityKey personId) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getPersonEnrollmentDeterminationHistory(personId);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    public Map getDiagnosisMap() {
		return diagnosisMap;
	}

	public void setDiagnosisMap(Map diagnosisMap) {
		this.diagnosisMap = diagnosisMap;
	}

	public Map getProcedureMap() {
		return procedureMap;
	}

	public void setProcedureMap(Map procedureMap) {
		this.procedureMap = procedureMap;
	}

	public Map getConditionMap() {
		return conditionMap;
	}

	public void setConditionMap(Map conditionMap) {
		this.conditionMap = conditionMap;
	}

    public boolean getPriorToEnrDetermHistory(EntityKey personId, Date beforeDate, Date recModifiedDate) throws ServiceException
    {
        try
        {
            return rulesEnrollmentHistoryDAO.getPriorToEnrDetermHistory(personId, beforeDate, recModifiedDate);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }
}