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

// Java classes
import gov.va.med.esr.common.model.ee.CDCondition;
import gov.va.med.esr.common.model.ee.CDDiagnosis;
import gov.va.med.esr.common.model.lookup.CDDeterminationMethod;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.ee.CDDescriptor;
import gov.va.med.esr.common.model.ee.CatastrophicDisability;
import gov.va.med.esr.common.model.ee.ClinicalDetermination;
import gov.va.med.esr.common.model.ee.MilitarySexualTrauma;
import gov.va.med.esr.common.model.ee.NoseThroatRadium;
import gov.va.med.esr.common.model.ee.SpinalCordInjury;
import gov.va.med.esr.common.model.lookup.Diagnosis;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.rule.ClinicalFactorInput;
import gov.va.med.esr.common.rule.data.ClinicalDeterminationInputData;
import gov.va.med.esr.common.rule.service.MergeRuleService;
import gov.va.med.esr.common.rule.service.MatchRuleService;
import gov.va.med.fw.rule.RuleDataAware;
import gov.va.med.fw.rule.RuleException;
import gov.va.med.fw.service.ServiceException;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.EqualsBuilder;

/**
 * This class is used for Clinical determination or by E&E calculation.
 *
 * @author Muddaiah Ranga
 * @version 1.0
 */
public class ClinicalFactorInputParameter extends BaseParameter implements
        ClinicalFactorInput {

    private static final long serialVersionUID = 2004163891862166279L;

    // CatastrophicDisability for the incoming person.
    private CatastrophicDisability catastrophicDisability = null;

    // CatastrophicDisability for the (pristine person).
    private CatastrophicDisability veteranCD = null;

    // MST for the incoming person.
    private MilitarySexualTrauma militarySexualTrauma = null;

    // MST for the Veteran (pristine person).
    private MilitarySexualTrauma veteranMilitarySexualTrauma = null;

    // NTR for the incoming person.
    private NoseThroatRadium noseThroatRadium = null;

    // NTR for the Veteran (pristine person).
    private NoseThroatRadium veteranNoseThroatRadium = null;

    // ClinicalDetermination for th incoming person.
    private ClinicalDetermination clinicalDetermination = null;

    private ClinicalDeterminationInputData clinicalDeterminationInputData = null;

    // For use in comms context to find most recent prior CD.
    private CatastrophicDisability priorCD = null;

    /**
     * Default constructor
     */
    public ClinicalFactorInputParameter() {
        super();
    }

    public String getSendingFacilityCode() {
        VAFacility sendingFacility = super.getSendingFacility();
        return (sendingFacility != null) ? sendingFacility.getCode() : null;
    }

    /** *************************************************************************************** */
    /**
     * ************************* Catastropic Disability Methods
     * ****************************
     */
    /** *************************************************************************************** */

    /**
     * Gets the CatastrophicDisability for the incoming person.
     */
    public CatastrophicDisability getCatastrophicDisability() {
        if (catastrophicDisability == null) {
            this.catastrophicDisability = getCatastrophicDisability(this
                    .getIncomingPerson());
        }
        return this.catastrophicDisability;
    }

    /**
     * Gets CatastrophicDisability Indicator for the incoming person.
     */
    public String getCatastrophicDisabilityIndicator() {
        CatastrophicDisability cd = this.getCatastrophicDisability();
        return this.getCatastrophicDisabilityIndicator(cd);
    }

    /*
     * @see gov.va.med.esr.common.rule.ClinicalFactorInput#getCatastrophicDisabilityIndicator(gov.va.med.esr.common.model.person.Person)
     */
    public String getCatastrophicDisabilityIndicator(Person person) {
        CatastrophicDisability cd = getCatastrophicDisability(person);
        return this.getCatastrophicDisabilityIndicator(cd);
    }

    private String getCatastrophicDisabilityIndicator(CatastrophicDisability cd) {
        return (cd != null && cd.isCatastrophicallyDisabled() != null && cd
                .isCatastrophicallyDisabled().booleanValue()) ? YES_INDICATOR
                : NO_INDICATOR;
    }

    /**
     * Gets the CatastrophicDisability date of decision for the incoming person.
     */
    public Date getDateOfDecision() {
        CatastrophicDisability cd = this.getCatastrophicDisability();
        return (cd != null) ? cd.getDecisionDate() : null;
    }

    /**
     * Gets the CatastrophicDisability determiniation method for the incoming
     * person.
     */
    public String getMethodOfDetermination() {
        CatastrophicDisability cd = this.getCatastrophicDisability();
        CDDeterminationMethod method = cd != null ? cd.getDeterminationMethod()
                : null;
        return (method != null) ? method.getCode() : null;
    }

    /**
     * Gets the determining site for the incoming person.
     */
    public String getDeterminingSite() {
        CatastrophicDisability cd = this.getCatastrophicDisability();
        return (cd != null && cd.getDeterminationFacility() != null) ? cd
                .getDeterminationFacility().getCode() : null;
    }

    public Date getDateOfReview() {
        CatastrophicDisability cd = this.getVeteranCatastrophicDisability();
        return (cd != null) ? cd.getReviewDate() : null;
    }

    public Date getCatastrophicReviewDate() {
        return this.getDateOfReview();
    }

    /**
     * Gets the Catastrophic Disability for the Veteran (pristine person).
     */
    public CatastrophicDisability getVeteranCatastrophicDisability() {
        if (this.veteranCD == null) {
            this.veteranCD = getCatastrophicDisability(this.getPristinePerson());
        }
        return this.veteranCD;
    }

    /**
     * Gets CatastrophicDisability Indicator for the Veteran (pristine person).
     */
    public String getVeteranCatastrophicDisabilityIndicator() {
        CatastrophicDisability cd = this.getVeteranCatastrophicDisability();
        return (cd != null && cd.isCatastrophicallyDisabled() != null && cd
                .isCatastrophicallyDisabled().booleanValue()) ? YES_INDICATOR
                : NO_INDICATOR;
    }

    /**
     * Gets veteran's (pristine person) the CatastrophicDisability date of
     * decision.
     */
    public Date getVeteranDateOfDecision() {
        CatastrophicDisability cd = this.getVeteranCatastrophicDisability();
        return (cd != null) ? cd.getDecisionDate() : null;
    }

    /**
     * Gets Catastrophic Disability determination method for the Veteran
     * (pristine person).
     */
    public String getVeteranMethodOfDetermination() {

        CatastrophicDisability cd = this.getVeteranCatastrophicDisability();
        CDDeterminationMethod method = cd != null ? cd.getDeterminationMethod()
                : null;
        return (method != null) ? method.getCode() : null;
    }

    /**
     * Gets the determining site for the veteran (pristine person).
     */
    public String getVeteranDeterminingSite() {
        CatastrophicDisability cd = this.getVeteranCatastrophicDisability();
        return (cd != null && cd.getDeterminationFacility() != null) ? cd
                .getDeterminationFacility().getCode() : null;
    }

    /**
     * Updates the Veteran's CatastrophicDisability info with the incoming
     * CatastrophicDisability info.
     */
    public void updateVeteranDisability() {
        try {
            CatastrophicDisability veteranCD = this
                    .getCatastrophicDisability(this.getResultPerson());
            ;
            if (veteranCD == null) {
                veteranCD = new CatastrophicDisability();
                this.getMergeRuleService().mergeCatastrophicDisability(
                        this.getCatastrophicDisability(), veteranCD, false);
                this.getResultPerson().addClinicalDetermination(veteranCD);
            } else {
                this.getMergeRuleService().mergeCatastrophicDisability(
                        this.getCatastrophicDisability(), veteranCD, false);
            }
        } catch (ServiceException e) {
            this.logger.debug("Failed to merge an CatastrophicDisability", e);
            throw new RuntimeException(
                    "Failed to merge an CatastrophicDisability", e);
        }
    }

    /*
     * The intent of this method is to ADD CDDescriptors only. It will not remove them.
     * 
     * (non-Javadoc)
     * @see gov.va.med.esr.common.rule.ClinicalFactorInput#updateCDDescriptorsOnly()
     */
    public void updateCDDescriptorsOnly() {
    	try {
    		CatastrophicDisability veteranCD = this.getCatastrophicDisability(this.getResultPerson());
    		if (veteranCD != null) {
    			// Allow adds only of descriptors
    			this.getMergeRuleService().mergeCatastrophicDisabilityCDDescriptorsOnly(this.getCatastrophicDisability(),
    					veteranCD, true);
    		}
    	} catch (ServiceException e) {
    		this.logger.debug("Failed to merge a CatastrophicDisability with CDDescriptor(s)", e);
    		throw new RuntimeException("Failed to merge a CatastrophicDisability with CDDescriptor(s)", e);
    	}		
    }

    /**
     * Removes the Veteran's CatastrophicDisability.
     */
    public void removeVeteranDisability() {
        Person resultPerson = this.getResultPerson();
        CatastrophicDisability veteranCD = this
                .getCatastrophicDisability(resultPerson);
        if (veteranCD != null) {
            resultPerson.removeClinicalDetermination(veteranCD);
        }
    }

    /**
     * Gets the CatastrophicDisability for the given person.
     *
     * @param person
     *            the person object
     * @return CatastrophicDisability for the given person.
     */
    private CatastrophicDisability getCatastrophicDisability(Person person) {
        return (CatastrophicDisability) this.getHelperService()
                .getClinicalDetermination(CatastrophicDisability.class, person);
    }

    /** *************************************************************************************** */
    /**
     * ********************* Military Sexual Trauma Methods
     * ********************************
     */
    /** *************************************************************************************** */

    /**
     * @return Returns the militarySexualTrauma.
     */
    public MilitarySexualTrauma getMilitarySexualTrauma() {
        if (militarySexualTrauma == null) {
            this.militarySexualTrauma = getMST(this.getIncomingPerson());
        }
        return this.militarySexualTrauma;
    }

    /**
     * Gets the MST status for the incoming person.
     */
    public String getMSTStatus() {
        MilitarySexualTrauma mst = this.getMilitarySexualTrauma();
        return (mst != null && mst.getStatus() != null) ? mst.getStatus()
                .getCode() : null;
    }

    /**
     * Gets the MST indicator for the incoming person.
     */
    public String getMSTIndicator() {
        MilitarySexualTrauma mst = getMilitarySexualTrauma();
        return (mst != null) ? YES_INDICATOR : NO_INDICATOR;
    }

    /**
     * Gets the MST status change date for the incoming person.
     */
    public Date getMSTStatusChangeDate() {
        MilitarySexualTrauma mst = this.getMilitarySexualTrauma();
        return (mst != null) ? mst.getStatusChangeDate() : null;
    }

    /**
     * Gets the MST indicator for the incoming person.
     */
    public String getScreenedReportsMSTIndicator() {
        MilitarySexualTrauma mst = getMilitarySexualTrauma();
        return (mst != null && mst.getStatus() != null) ? mst.getStatus()
                .getCode() : null;
    }

    /**
     * Gets the site determining MST for the incoming person.
     */
    public String getSiteDeterminingMST() {
        MilitarySexualTrauma mst = getMilitarySexualTrauma();
        return (mst != null && mst.getDeterminationFacility() != null) ? mst
                .getDeterminationFacility().getStationNumber() : null;
    }

    /**
     * Gets the MilitarySexualTrauma for the person on file.
     */
    public MilitarySexualTrauma getVeteranMST() {
        if (veteranMilitarySexualTrauma == null) {
            this.veteranMilitarySexualTrauma = getMST(this.getPristinePerson());
        }
        return this.veteranMilitarySexualTrauma;
    }

    /**
     * Gets the MST status for the incoming person.
     */
    public String getVeteranMSTStatus() {
        MilitarySexualTrauma mst = this.getVeteranMST();
        return (mst != null && mst.getStatus() != null) ? mst.getStatus()
                .getCode() : null;
    }

    public Date getVeteranMSTStatusChangedDate() {
        MilitarySexualTrauma mst = this.getVeteranMST();
        return (mst != null) ? mst.getStatusChangeDate() : null;
    }

    public boolean isReceivedMSTSameAsVeteran() {
        return false;
    }

    /**
     * Updates the veteran's (on file person) MST with the incoming person's MST
     * information.
     */
    public void updateVeteranMST() {
        try {
            MilitarySexualTrauma vetMST = getMST(this.getResultPerson());
            ;
            if (vetMST == null) {
                vetMST = new MilitarySexualTrauma();
                this.getMergeRuleService().mergeMilitarySexualTrauma(
                        this.getMilitarySexualTrauma(), vetMST);

                this.getResultPerson().addClinicalDetermination(vetMST);
            } else {
                this.getMergeRuleService().mergeMilitarySexualTrauma(
                        this.getMilitarySexualTrauma(), vetMST);
            }
        } catch (ServiceException e) {
            this.logger.debug("Failed to merge an MilitarySexualTrauma", e);
            throw new RuntimeException(
                    "Failed to merge an MilitarySexualTrauma", e);
        }
    }
                /**
     * Gets the SpinalCordInjury for the person on file.
     */
    public SpinalCordInjury getVeternSpinalCordInjury()
    {
    	//CCR-13414
    	if (!this.isMessageFromVOA()) {
    		return null;
    	}
    	return this.getPristinePerson().getSpinalCordInjury();
    }


    /**
     * copy the vetern's spinal cord injury from the message
     */
    public void updateVeternSpinalCordInjury()
    {
    	SpinalCordInjury sci = this.getIncomingPerson().getSpinalCordInjury();
    	if (sci != null)
    	{
    		sci.setPerson(null); //CCR 9836, check null to avoid null pointer exception
    	}
    	this.getResultPerson().setSpinalCordInjury(sci);

    }

    /**
     * Gets the MST for the given person.
     */
    private MilitarySexualTrauma getMST(Person person) {
        return (MilitarySexualTrauma) this.getHelperService()
                .getClinicalDetermination(MilitarySexualTrauma.class, person);
    }

    /** *************************************************************************************** */
    /**
     * ************************* Nose Throat Radium Methods
     * ********************************
     */
    /** *************************************************************************************** */

    /**
     * ***************************** Methods for the incoming person
     * *************************
     */

    /**
     * Gets the NTR for the incoming person.
     */
    public NoseThroatRadium getNoseThroatRadium() {
        if (noseThroatRadium == null) {
            this.noseThroatRadium = getNTR(this.getIncomingPerson());
        }
        return this.noseThroatRadium;
    }

    /**
     * Gets the NTR verification date for the incoming person.
     */
    public Date getNTRVerificationDate() {
        NoseThroatRadium ntr = getNoseThroatRadium();
        return (ntr != null) ? ntr.getVerificationDate() : null;
    }

    /**
     * Gets the NTR station number for the incoming person.
     */
    public String getNTRStationNumber() {
        NoseThroatRadium ntr = getNoseThroatRadium();
        return (ntr != null && ntr.getVerificationFacility() != null) ? ntr
                .getVerificationFacility().getStationNumber() : null;
    }

    /**
     * Gets the NTR verification method for the incoming person.
     */
    public String getNTRVerificationMethod() {
        NoseThroatRadium ntr = getNoseThroatRadium();
        return (ntr != null && ntr.getVerificationMethod() != null) ? ntr
                .getVerificationMethod().getCode() : null;
    }

    /**
     * ***************************** Methods for the Veteran (pristine person)
     * ***************************
     */

    /**
     * Gets the NTR for the veteran (person on file).
     */
    public NoseThroatRadium getVeteranNTR() {
        if (veteranNoseThroatRadium == null) {
            this.veteranNoseThroatRadium = getNTR(this.getPristinePerson());
        }
        return this.veteranNoseThroatRadium;
    }

    /**
     * Gets the NTR verification date for the Veteran (person on file).
     */
    public Date getNTRVerificationDateForVeteran() {
        NoseThroatRadium ntr = getVeteranNTR();
        return (ntr != null) ? ntr.getVerificationDate() : null;
    }

    /**
     * Updates the Veteran's NTR record to the incoming NTR information.
     */
    public void updateVeteranNTR() {
        try {
            NoseThroatRadium vetNTR = getNTR(this.getResultPerson());
            ;
            if (vetNTR == null) {
                vetNTR = new NoseThroatRadium();
                this.getMergeRuleService().mergeNoseThroatRadium(
                        this.getNoseThroatRadium(), vetNTR);
                this.getResultPerson().addClinicalDetermination(vetNTR);
            } else {
                this.getMergeRuleService().mergeNoseThroatRadium(
                        this.getNoseThroatRadium(), vetNTR);
            }
        } catch (ServiceException e) {
            this.logger.debug("Failed to merge an NoseThroatRadium", e);
            throw new RuntimeException("Failed to merge an NoseThroatRadium", e);
        }
    }

    /**
     * Updates the Veteran's NTR record to the incoming VOA NTR information.
     * 5.21 Do Not Upload Nose Throat Radium Observation Date
	 * SUC461.23.1 In step, [5073], if this is a Z07 from the Veteran's Online App
	 * the Observation Date and Time for Nose Throat Radium (NTR) is never uploaded from the HL7.

     */
    public void updateVeteranNTRFromVOA()
    {
        try
        {
            NoseThroatRadium vetNTR = getNTR(this.getResultPerson());

            //clone and set the observation date to null so the date will not be copied
        	NoseThroatRadium incomingNTR = (NoseThroatRadium)this.getNoseThroatRadium().clone();
        	incomingNTR.setDiagnosisVerifiedDate(null);

            if(vetNTR == null)
            {
            	vetNTR = new NoseThroatRadium ();
            	this.getMergeRuleService().mergeNoseThroatRadium(incomingNTR,vetNTR);
                this.getResultPerson().addClinicalDetermination(vetNTR);
            }
            else
            {
                this.getMergeRuleService().mergeNoseThroatRadium(incomingNTR,vetNTR);
            }
        }
        catch( ServiceException e )
        {
            this.logger.debug( "Failed to merge an NoseThroatRadium", e);
			throw new RuntimeException("Failed to merge an NoseThroatRadium", e );
        }
    }


    /**
     * Removes the Veteran's NTR record.
     */
    public void removeVeteranNTR() {
        NoseThroatRadium veteranNTR = getNTR(this.getResultPerson());
        this.getResultPerson().removeClinicalDetermination(veteranNTR);
    }

    /**
     * Returns true if the received NTR data is different than the Veteran's NTR
     * (pristine person), otherwise returns false. NTR verification date is not
     * used for comparison.
     */
    public boolean isReceivedNTRDataSameAsVeteran() {
        NoseThroatRadium ntr = this.getNoseThroatRadium();
        NoseThroatRadium veteranNTR = getVeteranNTR();

        if (ntr == null && veteranNTR == null)
            return true;

        final EqualsBuilder builder = new EqualsBuilder();
        builder.append(ntr.getVerificationMethod(), veteranNTR
                .getVerificationMethod());
        builder.append(ntr.getVerificationFacility(), veteranNTR
                .getVerificationFacility());
        builder.append(ntr.getReceivingTreatment(), veteranNTR
                .getReceivingTreatment());
        builder.append(ntr.getFromAviatorServiceBefore1955(), veteranNTR
                .getFromAviatorServiceBefore1955());
        builder.append(ntr.getFromSubmarinerServiceBefore1965(), veteranNTR
                .getFromSubmarinerServiceBefore1965());
        builder.append(ntr.getDiagnosedWithCancer(), veteranNTR
                .getDiagnosedWithCancer());
        builder.append(ntr.getDiagnosisVerifiedDate(), veteranNTR
                .getDiagnosisVerifiedDate());
        return builder.isEquals();
    }

    /**
     * *************************************** Private methods
     * *****************************************
     */

    /**
     * Gets the NTR for the given person.
     *
     * @param person
     *            the incoming person.
     * @return the NTR for the given person.
     */
    private NoseThroatRadium getNTR(Person person) {
        return (NoseThroatRadium) this.getHelperService()
                .getClinicalDetermination(NoseThroatRadium.class, person);
    }

    /**
     * *************************************** End of NTR methods
     * *****************************************
     */

    /**
     * @return Returns the clinicalDetermination.
     */
    public ClinicalDetermination getClinicalDetermination() {
        if (clinicalDetermination == null) {
            ClinicalDeterminationInputData clinicalDeterminationInputData = this
                    .getClinicalDeterminationInputData();
            if (clinicalDeterminationInputData != null) {
                this.clinicalDetermination = clinicalDeterminationInputData
                        .getIncomingClinicalDetermination();
            } else {
                this.clinicalDetermination = (ClinicalDetermination) this
                        .getHelperService().getClinicalDetermination(
                                ClinicalDetermination.class,
                                this.getIncomingPerson());
            }
        }
        return this.clinicalDetermination;
    }

    private ClinicalDeterminationInputData getClinicalDeterminationInputData() {
        if (clinicalDeterminationInputData == null) {
            RuleDataAware ruleDataAware = this.getRuleDataAware();
            if (ruleDataAware instanceof ClinicalDeterminationInputData) {
                this.clinicalDeterminationInputData = (ClinicalDeterminationInputData) ruleDataAware;
            }
        }
        return this.clinicalDeterminationInputData;
    }

    /**
     * Returns true if the Catastrophic Disability Condition Score for the
     * incoming person.
     */
    public boolean isScoreEmptyForConditionCode() {
        Set conditions = (this.getCatastrophicDisability() != null) ? this
                .getCatastrophicDisability().getConditions() : null;
        if (conditions != null) {
            for (Iterator iter = conditions.iterator(); iter.hasNext();) {
                CDCondition cdCondition = (CDCondition) iter.next();
                if ((cdCondition != null) && (cdCondition.getScore() == null)) {
                    return true;
                }
            }
        }
        return false;
    }

    /*
     * (non-Javadoc)
     *
     * @see gov.va.med.esr.common.rule.parameter.ClinicalFactorInput#isDiagnosisContained(java.lang.String)
     */
    public boolean isDiagnosisContained(String code) {
        Set setOfDiagnoses = (this.getCatastrophicDisability() != null) ? this
                .getCatastrophicDisability().getDiagnoses() : null;

        if (setOfDiagnoses != null && !setOfDiagnoses.isEmpty()) {
            Iterator iter = setOfDiagnoses.iterator();
            while (iter.hasNext()) {
                CDDiagnosis cdDiagnosis = (CDDiagnosis) iter.next();
                Diagnosis diagnosis = cdDiagnosis.getDiagnosis();
                if ((diagnosis != null) && (diagnosis.getCode().equals(code))) {
                    return true;
                }
            }
        } else if (setOfDiagnoses != null && setOfDiagnoses.isEmpty()) {
            return true;
        } else if (setOfDiagnoses == null) {
            return true;
        }
        return false;
    }

    /**
     * @see gov.va.med.esr.common.rule.ClinicalFactorInput#getPriorCatastrophicDisabilityIndicator()
     */
    public String getPriorCatastrophicDisabilityIndicator()
            throws RuleException {
        // Returns the catastrophicDisabilityIndicator
        // based on the prior enrollment record (associated with
        // a business rules where the system must decide that the
        // enrollment change was based on CD Indicator being set to Yes
        if (priorCD == null) {
            this.priorCD = getPriorCatastrophicDisability(this
                    .getIncomingPerson());
        }
        return this.priorCD != null ? YES_INDICATOR : NO_INDICATOR;
    }

    public Date getCDDecisionDate(Person person) {
    	CatastrophicDisability cd = person.getCatastrophicDisability();
    	return cd != null ? cd.getDecisionDate() : null;
    }

    public Date getCDReviewDate(Person person) {
    	CatastrophicDisability cd = person.getCatastrophicDisability();
    	return cd != null ? cd.getReviewDate() : null;
    }

    public boolean isCDDescriptorDataChanged() {
    	boolean changed = false;
    	CatastrophicDisability cdIncoming = getCatastrophicDisability(
    			this.getIncomingPerson());
    	CatastrophicDisability cdOnFile = getCatastrophicDisability(
    			this.getPristinePerson());
    	if (cdIncoming == null && cdOnFile != null) {
    		return true;
    	}
    	if (cdIncoming != null && cdOnFile == null) {
    		return true;
    	}    	
    	if (cdIncoming == null && cdOnFile == null) {
    		return false;
    	}    	
		if (ObjectUtils.equals(cdIncoming.getCDDescriptors().size(), cdOnFile.getCDDescriptors().size())) {
			for (CDDescriptor descriptor : cdIncoming.getCDDescriptors()) {
				CDDescriptor matched = (CDDescriptor)getMatchRuleService().findMatchingElement(
						descriptor, cdOnFile.getCDDescriptors());
				if (matched == null) {
					changed = true;
					break;
				}
			}					
		}
		else {
			changed = true;
		}
    	return changed;
    }

    private MatchRuleService getMatchRuleService() {
    	MatchRuleService service = null;
    	service = this.getMergeRuleService().getMatchRuleService();
    	return service;
    }
    
	public boolean hasIncomingCDDescriptors() {
    	CatastrophicDisability cd = getCatastrophicDisability(
    			this.getIncomingPerson());
    	return cd != null ? cd.getCDDescriptors().size() > 0 : false;
	}

	private CatastrophicDisability getPriorCatastrophicDisability(Person person)
            throws RuleException {
        Validate.notNull(person, "A person must not be null ");
        Person priorPerson = this.getPriorEEPerson();
        if (priorPerson != null) {
            return this.getCatastrophicDisability(priorPerson);
        }
        return null;
    }
}