/*******************************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ******************************************************************************/
package gov.va.med.esr.messaging.parser;

// Java Classes
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

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.hl7.segment.IN1;
import gov.va.med.fw.hl7.segment.MSH;
import gov.va.med.fw.hl7.segment.OBX;
import gov.va.med.fw.hl7.segment.PD1;
import gov.va.med.fw.hl7.segment.PID;
import gov.va.med.fw.hl7.segment.RF1;
import gov.va.med.fw.hl7.segment.ZBT;
import gov.va.med.fw.hl7.segment.ZCD;
import gov.va.med.fw.hl7.segment.ZCT;
import gov.va.med.fw.hl7.segment.ZE2;
import gov.va.med.fw.hl7.segment.ZEL;
import gov.va.med.fw.hl7.segment.ZEM;
import gov.va.med.fw.hl7.segment.ZEN;
import gov.va.med.fw.hl7.segment.ZFE;
import gov.va.med.fw.hl7.segment.ZGD;
import gov.va.med.fw.hl7.segment.ZIC;
import gov.va.med.fw.hl7.segment.ZIE;
import gov.va.med.fw.hl7.segment.ZIO;
import gov.va.med.fw.hl7.segment.ZMH;
import gov.va.med.fw.hl7.segment.ZMT;
import gov.va.med.fw.hl7.segment.ZPD;
import gov.va.med.fw.hl7.segment.ZSP;
import gov.va.med.fw.hl7.segment.ZTA;
import gov.va.med.fw.hl7.segment.ZHP;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.util.builder.Builder;
import gov.va.med.fw.util.builder.BuilderException;
import gov.va.med.esr.common.builder.entity.metaData.AssetMetaDataFromZICPosition;
import gov.va.med.esr.common.builder.datatype.metadata.CE;
import gov.va.med.esr.common.builder.datatype.metadata.XAD;
import gov.va.med.esr.common.builder.datatype.metadata.XTN;
import gov.va.med.esr.common.builder.entity.AddressMetaData;
import gov.va.med.esr.common.builder.entity.AgentOrangeExposureMetaData;
import gov.va.med.esr.common.builder.entity.ApplicationMetaData;
import gov.va.med.esr.common.builder.entity.AssetMetaData;
import gov.va.med.esr.common.builder.entity.AssociationMetaData;
import gov.va.med.esr.common.builder.entity.BeneficiaryMetaData;
import gov.va.med.esr.common.builder.entity.BeneficiaryTravelMetaData;
import gov.va.med.esr.common.builder.entity.CampLejeuneVerificationMetaData;
import gov.va.med.esr.common.builder.entity.CancelDeclineMetaData;
import gov.va.med.esr.common.builder.entity.CatastrophicDisabilityMetaData;
import gov.va.med.esr.common.builder.entity.CombatEpisodeMetaData;
import gov.va.med.esr.common.builder.entity.EligibilityVerificationMetaData;
import gov.va.med.esr.common.builder.entity.EmailMetaData;
import gov.va.med.esr.common.builder.entity.EmploymentMetaData;
import gov.va.med.esr.common.builder.entity.EntityBuilder;
import gov.va.med.esr.common.builder.entity.EnvironmentalContaminationExposureMetaData;
import gov.va.med.esr.common.builder.entity.FeeBasisMetaData;
import gov.va.med.esr.common.builder.entity.FinancialStatementMetaData;
import gov.va.med.esr.common.builder.entity.IncomeTestMetaData;
import gov.va.med.esr.common.builder.entity.IncompetenceRulingMetaData;
import gov.va.med.esr.common.builder.entity.IneligibilityFactorMetaData;
import gov.va.med.esr.common.builder.entity.MedicaidFactorMetaData;
import gov.va.med.esr.common.builder.entity.MedicareMetaData;
import gov.va.med.esr.common.builder.entity.MilitaryServiceMetaData;
import gov.va.med.esr.common.builder.entity.MilitarySexualTraumaMetaData;
import gov.va.med.esr.common.builder.entity.MonetaryBenefitAwardMetaData;
import gov.va.med.esr.common.builder.entity.NoseThroatRadiumMetaData;
import gov.va.med.esr.common.builder.entity.PatientVisitSummaryMetaData;
import gov.va.med.esr.common.builder.entity.PersonMetaData;
import gov.va.med.esr.common.builder.entity.PhoneMetaData;
import gov.va.med.esr.common.builder.entity.PrivateInsuranceMetaData;
import gov.va.med.esr.common.builder.entity.PurpleHeartMetaData;
import gov.va.med.esr.common.builder.entity.RadiationExposureMetaData;
import gov.va.med.esr.common.builder.entity.ReceivedEligibilityMetaData;
import gov.va.med.esr.common.builder.entity.ReceivedEnrollmentMetaData;
import gov.va.med.esr.common.builder.entity.ServiceConnectionAwardMetaData;
import gov.va.med.esr.common.builder.entity.SpinalCordInjuryMetaData;
import gov.va.med.esr.common.builder.entity.VAPensionMetaData;
import gov.va.med.esr.common.builder.entity.metaData.AddressMetaDataFromPID;
import gov.va.med.esr.common.builder.entity.metaData.AddressMetaDataFromXAD;
import gov.va.med.esr.common.builder.entity.metaData.AddressMetaDataFromZTA;
import gov.va.med.esr.common.builder.entity.metaData.AgentOrangeExposureMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.ApplicationMetaDataFromZEN;
import gov.va.med.esr.common.builder.entity.metaData.AssociationMetaDataFromZCT;
import gov.va.med.esr.common.builder.entity.metaData.AssociationMetaDataFromZGD;
import gov.va.med.esr.common.builder.entity.metaData.BeneficiaryMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.BeneficiaryTravelMetaDataFromZBT;
import gov.va.med.esr.common.builder.entity.metaData.CampLejeuneVerificationMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.CancelDeclineMetaDataFromZEN;
import gov.va.med.esr.common.builder.entity.metaData.CatastrophicDisabilityMetaDataFromZCD;
import gov.va.med.esr.common.builder.entity.metaData.CombatEpisodeMetaDataFromZMH;
import gov.va.med.esr.common.builder.entity.metaData.EligibilityVerificationMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.EmailMetaDataFromXTN;
import gov.va.med.esr.common.builder.entity.metaData.EmploymentMetaDataFromZEM;
import gov.va.med.esr.common.builder.entity.metaData.EnvironmentalContaminationExposureMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.FeeBasisMetaDataFromZFE;
import gov.va.med.esr.common.builder.entity.metaData.FinancialStatementMetaDataFromZIC;
import gov.va.med.esr.common.builder.entity.metaData.IncomeTestMetaDataFromZMT;
import gov.va.med.esr.common.builder.entity.metaData.IncompetenceRulingMetaDataFromZGD;
import gov.va.med.esr.common.builder.entity.metaData.IneligibilityFactorMetaDataFromZIE;
import gov.va.med.esr.common.builder.entity.metaData.MedicaidFactorMetaDataFromZPD;
import gov.va.med.esr.common.builder.entity.metaData.MedicareMetaDataFromIN1;
import gov.va.med.esr.common.builder.entity.metaData.MetaDataConstants;
import gov.va.med.esr.common.builder.entity.metaData.MilitaryServiceMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.MilitarySexualTraumaMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.MonetaryBenefitAwardMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.NoseThroatRadiumMetaDataFromOBX;
import gov.va.med.esr.common.builder.entity.metaData.PatientVisitSummaryMetaDataFromZIO;
import gov.va.med.esr.common.builder.entity.metaData.PersonMetaDataFromPID;
import gov.va.med.esr.common.builder.entity.metaData.PhoneMetaDataFromPID;
import gov.va.med.esr.common.builder.entity.metaData.PrivateInsuranceMetaDataFromIN1;
import gov.va.med.esr.common.builder.entity.metaData.PurpleHeartMetaDataFromZMH;
import gov.va.med.esr.common.builder.entity.metaData.RadiationExposureMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.ReceivedEligibilityMetaDataFromZEL;
import gov.va.med.esr.common.builder.entity.metaData.ReceivedEnrollmentMetaDataFromZEN;
import gov.va.med.esr.common.builder.entity.metaData.ServiceConnectionAwardMetaDataFromZSP;
import gov.va.med.esr.common.builder.entity.metaData.SpinalCordInjuryMetaDataFromZPD;
import gov.va.med.esr.common.builder.entity.metaData.VAPensionMetaDataFromZE2;
import gov.va.med.esr.common.model.ee.AgentOrangeExposure;
import gov.va.med.esr.common.model.ee.Application;
import gov.va.med.esr.common.model.ee.CampLejeuneVerification;
import gov.va.med.esr.common.model.ee.CancelDecline;
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.CombatEpisode;
import gov.va.med.esr.common.model.ee.EligibilityVerification;
import gov.va.med.esr.common.model.ee.EnvironmentalContaminationExposure;
import gov.va.med.esr.common.model.ee.FeeBasis;
import gov.va.med.esr.common.model.ee.IncompetenceRuling;
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.MilitarySexualTrauma;
import gov.va.med.esr.common.model.ee.MonetaryBenefitAward;
import gov.va.med.esr.common.model.ee.NoseThroatRadium;
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.ReceivedEligibility;
import gov.va.med.esr.common.model.ee.ReceivedEnrollment;
import gov.va.med.esr.common.model.ee.ServiceConnectionAward;
import gov.va.med.esr.common.model.ee.SpecialFactor;
import gov.va.med.esr.common.model.ee.SpinalCordInjury;
import gov.va.med.esr.common.model.financials.BeneficiaryTravel;
import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.financials.PatientVisitSummary;
import gov.va.med.esr.common.model.insurance.InsurancePolicy;
import gov.va.med.esr.common.model.insurance.Medicare;
import gov.va.med.esr.common.model.insurance.PrivateInsurance;
import gov.va.med.esr.common.model.lookup.AddressType;
import gov.va.med.esr.common.model.lookup.AssetType;
import gov.va.med.esr.common.model.lookup.ConfidentialAddressCategoryType;
import gov.va.med.esr.common.model.lookup.InsurancePlanType;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.party.Email;
import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.model.person.Employment;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.util.CommonDateUtils;
import gov.va.med.esr.service.SystemParameterService;

/**
 * @author Martin Francisco, Rajiv Patnaik
 */
public class Z07Parser extends EntityBuilder
{
    /**
     * An instance of serialVersionUID
     */
    private static final long serialVersionUID = -6746553846341761472L;

    private Builder addressBuilder;

    private Builder addressTypeBuilder;

    private Builder agentOrangeExposureBuilder;

    private Builder applicationBuilder;

    private Builder associationBuilder;

    private Builder beneficiaryBuilder;

    private Builder beneficiaryTravelBuilder;

    private Builder campLejeuneVerificationBuilder;

    private Builder confidentialAddressCategoryTypeBuilder;

    private Builder cancelDeclineBuilder;

    private Builder catastrophicDisabilityBuilder;

    private Builder eligibilityVerificationBuilder;

    private Builder environmentalContaminationExposureBuilder;

    private Builder emailBuilder;

    private Builder feeBasisBuilder;

    private Builder financialStatementBuilder;

    private Builder incomeTestBuilder;

    private Builder incompetenceRulingBuilder;

    private Builder ineligibilityFactorBuilder;

    private Builder medicaidBuilder;

    private Builder medicaidFactorBuilder;

    private Builder medicareBuilder;

    private Builder militaryServiceBuilder;

    private Builder militarySexualTraumaBuilder;

    private Builder monetaryBenefitAwardBuilder;

    private Builder noseThroatRadiumBuilder;

    private Builder patientVisitSummaryBuilder;

    private Builder personBuilder;

    private Builder phoneBuilder;

    private Builder privateInsuranceBuilder;

    private Builder purpleHeartBuilder;

    private Builder radiationExposureBuilder;

    private Builder receivedEligibilityBuilder;

    private Builder receivedEnrollmentBuilder;

    private Builder serviceConnectionAwardBuilder;

    private Builder spinalCordInjuryBuilder;

    private Builder combatEpisodeBuilder;

    private Builder employmentBuilder;

    private Builder vaPensionBuilder;

    /**
     * An instance of systemParameterService
     */
    private SystemParameterService systemParameterService = null;

    /**
     * Default constructor.
     */
    public Z07Parser()
    {
        super();
    }

    public SystemParameterService getSystemParameterService() {
		return systemParameterService;
	}

	public void setSystemParameterService(
			SystemParameterService systemParameterService) {
		this.systemParameterService = systemParameterService;
	}

	public Builder getVaPensionBuilder() {
		return vaPensionBuilder;
	}

	public void setVaPensionBuilder(Builder vaPensionBuilder) {
		this.vaPensionBuilder = vaPensionBuilder;
	}

    public Builder getAddressBuilder()
    {
        return this.addressBuilder;
    }

    public void setAddressBuilder(Builder addressBuilder)
    {
        this.addressBuilder = addressBuilder;
    }

    /**
     * @return Returns the addressTypeBuilder.
     */
    public Builder getAddressTypeBuilder()
    {
        return addressTypeBuilder;
    }

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

    public Builder getAgentOrangeExposureBuilder()
    {
        return this.agentOrangeExposureBuilder;
    }

    public void setAgentOrangeExposureBuilder(Builder agentOrangeExposureBuilder)
    {
        this.agentOrangeExposureBuilder = agentOrangeExposureBuilder;
    }

    public Builder getApplicationBuilder()
    {
        return this.applicationBuilder;
    }

    public void setApplicationBuilder(Builder applicationBuilder)
    {
        this.applicationBuilder = applicationBuilder;
    }

    public Builder getAssociationBuilder()
    {
        return this.associationBuilder;
    }

    public void setAssociationBuilder(Builder associationBuilder)
    {
        this.associationBuilder = associationBuilder;
    }

    public Builder getBeneficiaryBuilder()
    {
        return this.beneficiaryBuilder;
    }

    public void setBeneficiaryBuilder(Builder beneficiaryBuilder)
    {
        this.beneficiaryBuilder = beneficiaryBuilder;
    }

    public Builder getBeneficiaryTravelBuilder()
    {
        return this.beneficiaryTravelBuilder;
    }

    public void setBeneficiaryTravelBuilder(Builder beneficiaryTravelBuilder)
    {
        this.beneficiaryTravelBuilder = beneficiaryTravelBuilder;
    }


    public Builder getCampLejeuneVerificationBuilder() {
		return campLejeuneVerificationBuilder;
	}

	public void setCampLejeuneVerificationBuilder(
			Builder campLejeuneVerificationBuilder) {
		this.campLejeuneVerificationBuilder = campLejeuneVerificationBuilder;
	}

	public Builder getCancelDeclineBuilder()
    {
        return this.cancelDeclineBuilder;
    }

    public void setCancelDeclineBuilder(Builder cancelDeclineBuilder)
    {
        this.cancelDeclineBuilder = cancelDeclineBuilder;
    }

    /**
     * @return Returns the confidentialAddressCategoryTypeBuilder.
     */
    public Builder getConfidentialAddressCategoryTypeBuilder()
    {
        return confidentialAddressCategoryTypeBuilder;
    }

    /**
     * @param confidentialAddressCategoryTypeBuilder The confidentialAddressCategoryTypeBuilder to set.
     */
    public void setConfidentialAddressCategoryTypeBuilder(
            Builder confidentialAddressCategoryTypeBuilder)
    {
        this.confidentialAddressCategoryTypeBuilder = confidentialAddressCategoryTypeBuilder;
    }
    public Builder getCatastrophicDisabilityBuilder()
    {
        return this.catastrophicDisabilityBuilder;
    }

    public void setCatastrophicDisabilityBuilder(
            Builder catastrophicDisabilityBuilder)
    {
        this.catastrophicDisabilityBuilder = catastrophicDisabilityBuilder;
    }

    public Builder getEligibilityVerificationBuilder()
    {
        return this.eligibilityVerificationBuilder;
    }

    public void setEligibilityVerificationBuilder(
            Builder eligibilityVerificationBuilder)
    {
        this.eligibilityVerificationBuilder = eligibilityVerificationBuilder;
    }

    public Builder getEnvironmentalContaminationExposureBuilder()
    {
        return this.environmentalContaminationExposureBuilder;
    }

    public void setEnvironmentalContaminationExposureBuilder(
            Builder environmentalContaminationExposureBuilder)
    {
        this.environmentalContaminationExposureBuilder = environmentalContaminationExposureBuilder;
    }

    /**
     * @return Returns the electronicAddressBuilder.
     */
    public Builder getEmailBuilder()
    {
        return emailBuilder;
    }

    /**
     * @param electronicAddressBuilder
     *            The electronicAddressBuilder to set.
     */
    public void setEmailBuilder(Builder electronicAddressBuilder)
    {
        this.emailBuilder = electronicAddressBuilder;
    }

    /**
     * @return
     */
    public Builder getFinancialStatementBuilder()
    {
        return this.financialStatementBuilder;
    }

    /**
     * @return Returns the feeBasisBuilder.
     */
    public Builder getFeeBasisBuilder()
    {
        return feeBasisBuilder;
    }

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

    public void setFinancialStatementBuilder(Builder financialStatementBuilder)
    {
        this.financialStatementBuilder = financialStatementBuilder;
    }

    public Builder getIncomeTestBuilder()
    {
        return this.incomeTestBuilder;
    }

    public void setIncomeTestBuilder(Builder incomeTestBuilder)
    {
        this.incomeTestBuilder = incomeTestBuilder;
    }

    public Builder getIncompetenceRulingBuilder()
    {
        return this.incompetenceRulingBuilder;
    }

    public void setIncompetenceRulingBuilder(Builder incompetenceRulingBuilder)
    {
        this.incompetenceRulingBuilder = incompetenceRulingBuilder;
    }

    public Builder getIneligibilityFactorBuilder()
    {
        return this.ineligibilityFactorBuilder;
    }

    public void setIneligibilityFactorBuilder(Builder ineligibilityFactorBuilder)
    {
        this.ineligibilityFactorBuilder = ineligibilityFactorBuilder;
    }

    public Builder getMedicaidBuilder()
    {
        return this.medicaidBuilder;
    }

    public void setMedicaidBuilder(Builder medicaidBuilder)
    {
        this.medicaidBuilder = medicaidBuilder;
    }

    public Builder getMedicaidFactorBuilder()
    {
        return this.medicaidFactorBuilder;
    }

    public void setMedicaidFactorBuilder(Builder medicaidFactorBuilder)
    {
        this.medicaidFactorBuilder = medicaidFactorBuilder;
    }

    public Builder getMedicareBuilder()
    {
        return this.medicareBuilder;
    }

    public void setMedicareBuilder(Builder medicareBuilder)
    {
        this.medicareBuilder = medicareBuilder;
    }

    public Builder getMilitaryServiceBuilder()
    {
        return this.militaryServiceBuilder;
    }

    public void setMilitaryServiceBuilder(Builder militaryServiceBuilder)
    {
        this.militaryServiceBuilder = militaryServiceBuilder;
    }

    public Builder getMilitarySexualTraumaBuilder()
    {
        return this.militarySexualTraumaBuilder;
    }

    public void setMilitarySexualTraumaBuilder(
            Builder militarySexualTraumaBuilder)
    {
        this.militarySexualTraumaBuilder = militarySexualTraumaBuilder;
    }

    public Builder getMonetaryBenefitAwardBuilder()
    {
        return this.monetaryBenefitAwardBuilder;
    }

    public void setMonetaryBenefitAwardBuilder(
            Builder monetaryBenefitAwardBuilder)
    {
        this.monetaryBenefitAwardBuilder = monetaryBenefitAwardBuilder;
    }

    public Builder getNoseThroatRadiumBuilder()
    {
        return this.noseThroatRadiumBuilder;
    }

    public void setNoseThroatRadiumBuilder(Builder noseThroatRadiumBuilder)
    {
        this.noseThroatRadiumBuilder = noseThroatRadiumBuilder;
    }

    public Builder getPatientVisitSummaryBuilder()
    {
        return this.patientVisitSummaryBuilder;
    }

    public void setPatientVisitSummaryBuilder(Builder patientVisitSummaryBuilder)
    {
        this.patientVisitSummaryBuilder = patientVisitSummaryBuilder;
    }

    public Builder getPersonBuilder()
    {
        return this.personBuilder;
    }

    public void setPersonBuilder(Builder personBuilder)
    {
        this.personBuilder = personBuilder;
    }

    public Builder getPhoneBuilder()
    {
        return this.phoneBuilder;
    }

    public void setPhoneBuilder(Builder phoneBuilder)
    {
        this.phoneBuilder = phoneBuilder;
    }

    public Builder getPrivateInsuranceBuilder()
    {
        return this.privateInsuranceBuilder;
    }

    public void setPrivateInsuranceBuilder(Builder privateInsuranceBuilder)
    {
        this.privateInsuranceBuilder = privateInsuranceBuilder;
    }

    public Builder getPurpleHeartBuilder()
    {
        return this.purpleHeartBuilder;
    }

    public void setPurpleHeartBuilder(Builder decorationBuilder)
    {
        this.purpleHeartBuilder = decorationBuilder;
    }

    public Builder getRadiationExposureBuilder()
    {
        return this.radiationExposureBuilder;
    }

    public void setRadiationExposureBuilder(Builder radiationExposureBuilder)
    {
        this.radiationExposureBuilder = radiationExposureBuilder;
    }

    public Builder getReceivedEligibilityBuilder()
    {
        return this.receivedEligibilityBuilder;
    }

    public void setReceivedEligibilityBuilder(Builder receivedEligibilityBuilder)
    {
        this.receivedEligibilityBuilder = receivedEligibilityBuilder;
    }

    public Builder getReceivedEnrollmentBuilder()
    {
        return this.receivedEnrollmentBuilder;
    }

    public void setReceivedEnrollmentBuilder(Builder receivedEnrollmentBuilder)
    {
        this.receivedEnrollmentBuilder = receivedEnrollmentBuilder;
    }

    public Builder getServiceConnectionAwardBuilder()
    {
        return this.serviceConnectionAwardBuilder;
    }

    public void setServiceConnectionAwardBuilder(
            Builder serviceConnectionAwardBuilder)
    {
        this.serviceConnectionAwardBuilder = serviceConnectionAwardBuilder;
    }

    public Builder getSpinalCordInjuryBuilder()
    {
        return this.spinalCordInjuryBuilder;
    }

    public void setSpinalCordInjuryBuilder(Builder spinalCordInjuryBuilder)
    {
        this.spinalCordInjuryBuilder = spinalCordInjuryBuilder;
    }

	public Builder getCombatEpisodeBuilder() {
		return this.combatEpisodeBuilder;
	}

	public void setCombatEpisodeBuilder(Builder combatEpisodeBuilder) {
		this.combatEpisodeBuilder = combatEpisodeBuilder;
	}

    public Builder getEmploymentBuilder() {
        return employmentBuilder;
    }

    public void setEmploymentBuilder(Builder employmentBuilder) {
        this.employmentBuilder = employmentBuilder;
    }

    public Person build(Object[] args) throws BuilderException
    {
        return this.build((Person) args[0], (Message) args[1]);
    }

    public Person build(Person input, Message message) throws BuilderException
    {
        try
        {
            Person person = this.buildPerson(input, message);

            person.setApplication(this.buildApplication(
                    person.getApplication(), message));
            person.setCancelDecline(this.buildCancelDecline(person
                    .getCancelDecline(), message));
            person.setEligibilityVerification(this
                    .buildEligibilityVerification(person
                            .getEligibilityVerification(), message));

            person.setIncompetenceRuling(this.buildIncompetenceRuling(person
                    .getIncompetenceRuling(), message));
            person.setIneligibilityFactor(this.buildIneligibilityFactor(person
                    .getIneligibilityFactor(), message));
            person.setMedicaidFactor(this.buildMedicaidFactor(person
                    .getMedicaidFactor(), message));

            person.setMilitaryService(this.buildMilitaryService(person
                    .getMilitaryService(), message));

            person.setMonetaryBenefitAward(this.buildMonetaryBenefitAward(person, message));
            person.setReceivedEnrollment(this.buildReceivedEnrollment(person
                    .getReceivedEnrollment(), message));
            person.setServiceConnectionAward(this.buildServiceConnectionAward(
                    person.getServiceConnectionAward(), message));

            this.buildEmployment(person, message);
            this.buildAddresses(person, message);
            this.buildAssociations(person, message);
            this.buildBeneficiary(person, message);
            this.buildBeneficiaryTravel(person, message);
            this.buildClinicalDeterminations(person, message);
            this.buildFinancialStatement(person, message);
            this.buildFeeBasis(person, message);
            this.buildIncomeTest(person, message);
            this.buildMedicares(person, message);
            this.buildPatientVisitSummary(person, message);
            this.buildPhonesAndEmail(person, message);
            this.buildPrivateInsurances(person, message);
            this.buildPurpleHeart(person, message);
            this.buildReceivedEligibilities(person, message);
            this.buildSpecialFactors(person, message);
            this.buildCombatEpisodes(person, message);
            return person;
        } catch (InvalidMessageException e)
        {
            throw new BuilderException(e);
        }
    }

    private void buildAddresses(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        Set toAdd = new HashSet();

        // List of confidential categories (all types are allowed)
        Set toConfCategories = new HashSet();

        // Only one confidential address will be added, even though
        // multiples (of the same address value) can be sent,
        // each with a different category
        boolean processedConfAddress = false;

        PID pid = (PID) message.getSegment(SegmentConstants.PID);
        ZTA zta = (ZTA) message.getSegment(SegmentConstants.ZTA);

        List rf1s = message.getSegments(SegmentConstants.RF1);
        //RF1s could be

        XAD[] xads = XAD.create(pid.getPatientAddress(), pid
                .getRepeatDelimiter(), pid.getComponentDelimiter());
        for (int index = 0; index < ((xads == null) ? 0 : xads.length); index++)
        {
            String addressTypeFromMsg = ((xads[index] == null || xads[index]
                    .getTypeCode() == null)) ? null : xads[index].getTypeCode()
                    .getValue();

            AddressType addressType = (AddressType) addressTypeBuilder
                    .build(addressTypeFromMsg);

            // CCR 7423 VOA -- Birth City and State is included as one of the addresses
            // But we are not going to store it as an address on ESR
            if (addressType!= null &&
                (AddressType.CODE_BIRTH_ADDRESS.getCode().equals(addressType.getCode()))) {

                processBirthAddress(input, new AddressMetaDataFromXAD(xads[index]));
            }
            else {
                AddressMetaData metaData = new AddressMetaDataFromPID(xads[index],
                        pid, getRF1ByAddressType(rf1s, addressType.getCode()));

                processedConfAddress = processAddress(input, toAdd, toConfCategories, metaData, processedConfAddress);
            }
        }

        //As per BR 7694(and defect 5723), ESR will support a HL7 with a Confidential Address that has a Date/Time Last Updated and no
        //confidential address category, no address information and no start or end dates.
        //In this case, a conf address will have a RF1 but no data in PID.

        //If conf address is null(it is not present in PID), check if a corresponding RF1 exists
        if (!processedConfAddress) {

			RF1 rf1 = getRF1ByAddressType(rf1s,
					AddressType.CODE_CONFIDENTIAL_ADDRESS.getCode());

			if (rf1 != null) {
				AddressType addressType = (AddressType) addressTypeBuilder
						.build(AddressType.CODE_CONFIDENTIAL_ADDRESS.getCode());

				AddressMetaData metaData = new AddressMetaDataFromPID(null,
						pid, getRF1ByAddressType(rf1s, addressType.getCode()));

				Address address = (Address) this.addressBuilder.build(metaData);
				//Set address type explicitly because it was not present in the PID segment
				address.setType(addressType);

				toAdd.add(address);
			}
		}


        // CCR 10248: Z05 messages are failing with null pointer as the changeSite is null in temporary address
        // Comments per Laurie Sheppar: on upload of a Z07, if the site is null on ZTA when a Temp Address exists,
        // then store the site sending the Z07 as the site for the source.
        String changeSite = zta.getTemporaryAddressChangeSite();
        String sendingFacility = message.getSendingFacility();
        if (changeSite == null) {
        	if ( sendingFacility != null)
        		zta.setTemporaryAddressChangeSite(sendingFacility);
        	//else Nothing changed. The Change Site will be intact
        }
        if( logger.isDebugEnabled() ) {
            logger.debug("Z07 change site =" +  zta.getTemporaryAddressChangeSite());
        }

        processAddress(input, toAdd, toConfCategories, new AddressMetaDataFromZTA(XAD.create(zta
                .getTemporaryAddress(), zta.getComponentDelimiter()), zta), processedConfAddress);

        // Remove existing addresses and add the ones from the message
        input.removeAllAddresses();

        for (Iterator i = toAdd.iterator(); i.hasNext();)
        {
            input.addAddress((Address) i.next());
        }

        // Remove existing confidential address categories and add the
        // ones from the message
        input.removeAllConfidentialAddressCategories();

        for (Iterator i = toConfCategories.iterator(); i.hasNext();)
        {
            input.addConfidentialAddressCategory((ConfidentialAddressCategoryType) i.next());
        }
    }


    private AgentOrangeExposure buildAgentOrangeExposure(
            AgentOrangeExposureMetaData metaData) throws BuilderException
    {
        return (AgentOrangeExposure) this.agentOrangeExposureBuilder
                .build(metaData);
    }

    private CampLejeuneVerification buildCampLejeuneVerification(
    		CampLejeuneVerificationMetaData metaData) throws BuilderException
    {
        return (CampLejeuneVerification) this.campLejeuneVerificationBuilder
                .build(metaData);
    }

    private Application buildApplication(Application input, Message message)
            throws BuilderException, InvalidMessageException
    {
        ApplicationMetaData metaData = new ApplicationMetaDataFromZEN(
                (ZEN) message.getSegment(SegmentConstants.ZEN));
        metaData.setEntity(input);

        return this.buildApplication(metaData);
    }

    private Application buildApplication(ApplicationMetaData metaData)
            throws BuilderException
    {
        return (Application) this.applicationBuilder.build(metaData);
    }

    private void buildAssociations(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        Set toAdd = new HashSet();

        List zcts = message.getSegments(SegmentConstants.ZCT);
        for (int index = 0; index < ((zcts == null) ? 0 : zcts.size()); index++)
        {
            ZCT zct = (ZCT) zcts.get(index);
//          As per requirement, there is no explicit delete association. The signal is, if the
            //incoming message has "" (double quote) then it is considered as delete assiciation.
            if("".equals(zct.getContactName())) zct.setContactName("DELETEFLAG~DELETEFLAG~~~~~D");
            this.processAssociation(toAdd, new AssociationMetaDataFromZCT(zct));
            // Set back to original Message...Message is restored..
            if(zct.getContactName().equals("DELETEFLAG~DELETEFLAG~~~~~D")) zct.setContactName("");
        }

        List zgds = message.getSegments(SegmentConstants.ZGD);
        for (int index = 0; index < ((zgds == null) ? 0 : zgds.size()); index++)
        {
            ZGD zgd = (ZGD) zgds.get(index);
            this.processAssociation(toAdd, new AssociationMetaDataFromZGD(zgd));
        }

        // Remove all existing asscoiations and add teh ones from message
        input.removeAllAssociations();

        for (Iterator i = toAdd.iterator(); i.hasNext();)
        {
            input.addAssociation((Association) i.next());
        }
    }

    private void buildBeneficiary(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        OBX obx = null;

        List obxs = message.getSegments(SegmentConstants.OBX);
        for (int index = 0; index < ((obxs == null) ? 0 : obxs.size()); index++)
        {
            OBX current = (OBX) obxs.get(index);
            CE id = CE.create(current.getObservationID(), current
                    .getComponentDelimiter());
            if ((id != null) && "38.1".equals(super.getValue(id.getID()))
                    && "SECURITY LOG".equals(super.getValue(id.getText())))
            {
                obx = current;
            }
        }

        BeneficiaryMetaData metaData = new BeneficiaryMetaDataFromZEL(
                (ZEL) message.getSegment(SegmentConstants.ZEL), (PD1) message
                        .getSegment(SegmentConstants.PD1), obx , message.getSendingFacility());
        metaData.setEntity(input);
        this.beneficiaryBuilder.build(metaData);
    }

    /**
     * Build BeneficiaryTravel by Site year and FacililtyVisited
     *
     * @param input
     * @param message
     * @throws BuilderException
     * @throws InvalidMessageException
     */
    private void buildBeneficiaryTravel(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        BeneficiaryTravelMetaData metaData = new BeneficiaryTravelMetaDataFromZBT(
                (ZBT) message.getSegment(SegmentConstants.ZBT), (ZIC) message
                        .getSegment(SegmentConstants.ZIC), message
                        .getSendingFacility());

        VAFacility facilityVisited = super.build((VAFacility) null, metaData
                .getFacilityVisited());

        Integer siteYear = super.buildYear((Integer) null, metaData
                .getSiteYear());
        metaData.setEntity(input
                .getBeneficiaryTravel(siteYear, facilityVisited));

        BeneficiaryTravel beneficiaryTravel = (BeneficiaryTravel) beneficiaryTravelBuilder
                .build(metaData);

        input
                .setBeneficiaryTravel(siteYear, facilityVisited,
                        beneficiaryTravel);
    }

    private CancelDecline buildCancelDecline(CancelDecline input,
            Message message) throws BuilderException, InvalidMessageException
    {
        CancelDeclineMetaData metaData = new CancelDeclineMetaDataFromZEN(
                (ZEN) message.getSegment(SegmentConstants.ZEN));
        metaData.setEntity(input);

        return this.buildCancelDecline(metaData);
    }

    private CancelDecline buildCancelDecline(CancelDeclineMetaData metaData)
            throws BuilderException
    {
        return (CancelDecline) this.cancelDeclineBuilder.build(metaData);
    }

    private void buildCatastrophicDisabilities(List zcds, Set toAdd)
            throws BuilderException
    {
        Map map = new HashMap();

        for (int index = 0; index < ((zcds == null) ? 0 : zcds.size()); index++)
        {
            ZCD zcd = (ZCD) zcds.get(index);
            ZCDKey key = new ZCDKey(zcd);

            List keyedZCDs = (List) map.get(key);
            if (keyedZCDs == null)
            {
                keyedZCDs = new ArrayList();
                map.put(key, keyedZCDs);
            }

            keyedZCDs.add(zcd);
        }

        for (Iterator i = map.entrySet().iterator(); i.hasNext();)
        {
            Map.Entry entry = (Map.Entry) i.next();

            this.processCatastrophicDisability(toAdd,
                    new CatastrophicDisabilityMetaDataFromZCD((List) entry
                            .getValue()));
        }
    }

    private void buildClinicalDeterminations(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        Set toAdd = new HashSet();
        Set toRemove = new HashSet(input.getClinicalDeterminations());

        // CD
        this.buildCatastrophicDisabilities(message
                .getSegments(SegmentConstants.ZCD), toAdd);

        // MST
        this.processMilitarySexualTrauma(toAdd,
                new MilitarySexualTraumaMetaDataFromZEL((ZEL) message
                        .getSegment(SegmentConstants.ZEL)));

        // NTR
        List obxs = message.getSegments(SegmentConstants.OBX);
        for (int index = 0; index < ((obxs == null) ? 0 : obxs.size()); index++)
        {
            OBX obx = (OBX) obxs.get(index);
            CE id = CE.create(obx.getObservationID(), obx
                    .getComponentDelimiter());
            if ((id != null) && "VISTA".equals(super.getValue(id.getID()))
                    && "28.11".equals(super.getValue(id.getText())))
            {
                this.processNoseThroatRadium(toAdd,
                        new NoseThroatRadiumMetaDataFromOBX(obx));
            }
        }

        // SCI
        this.processSpinalCordInjury(toAdd,
                new SpinalCordInjuryMetaDataFromZPD((ZPD) message
                        .getSegment(SegmentConstants.ZPD)));

        for (Iterator i = toRemove.iterator(); i.hasNext();)
        {
            input.removeClinicalDetermination((ClinicalDetermination) i.next());
        }

        for (Iterator i = toAdd.iterator(); i.hasNext();)
        {
            input.addClinicalDetermination((ClinicalDetermination) i.next());
        }
    }

    private EligibilityVerification buildEligibilityVerification(
            EligibilityVerification input, Message message)
            throws BuilderException, InvalidMessageException
    {
        EligibilityVerificationMetaData metaData = new EligibilityVerificationMetaDataFromZEL(
                (ZEL) message.getSegment(SegmentConstants.ZEL), (MSH) message
                        .getSegment(SegmentConstants.MSH));
        metaData.setEntity(input);

        return this.buildEligibilityVerification(metaData);
    }

    private EligibilityVerification buildEligibilityVerification(
            EligibilityVerificationMetaData metaData) throws BuilderException
    {
        return (EligibilityVerification) this.eligibilityVerificationBuilder
                .build(metaData);
    }

    private void buildFinancialStatement(Person person, Message message)
            throws BuilderException, InvalidMessageException
    {
        FinancialStatementMetaData metaData = new FinancialStatementMetaDataFromZIC(
                (ZIC) message.getSegment(SegmentConstants.ZIC), (ZMT) message
                        .getSegment(SegmentConstants.ZMT), message
                        .getSegments());
        Integer incomeYear = super.buildYear(null, metaData.getIncomeYear());

        //VFA income year is 2009 or latter: set 3 asset values in metaData null
        //make sure it is called after the incomeYear is done.
//        discontinueAssetsIfIncomeYear2009AndLatter(incomeYear, metaData);

        // Remove all existing financial statements and add the one for the
        // income year in message
        person.removeAllFinancialStatements();

        // metaData.setEntity(person.getFinancialStatement(incomeYear));
        FinancialStatement financialStatement = (FinancialStatement) financialStatementBuilder
                .build(metaData);
        if (incomeYear != null)
        {
            person.setFinancialStatement(incomeYear, financialStatement, true);
        }
    }

    private void discontinueAssetsIfIncomeYear2009AndLatter(Integer incomeYear, FinancialStatementMetaData metaData)
    {
        if (CommonDateUtils.isIncomeYear2009OrLatter(incomeYear))
        {
        	//VFA income year is 2009 or latter: assets null
        	//from ICD: cash amounts in bank (seq 16), real property (seq 18), other property or assets (seq 19)
        	AssetMetaData[] assets = metaData.getAssets();
        	assets[0] = new AssetMetaDataFromZICPosition(null, AssetType.CODE_CASH.getName());
        	assets[2] = new AssetMetaDataFromZICPosition(null, AssetType.CODE_REAL_ESTATE.getName());
        	assets[3] = new AssetMetaDataFromZICPosition(null, AssetType.CODE_OTHER.getName());
        }
    }
    private void buildFeeBasis(Person person, Message message)
            throws InvalidMessageException, BuilderException
    {
        List zfeSegments = message.getSegments(SegmentConstants.ZFE);
        MSH msh = (MSH) message.getSegment(SegmentConstants.MSH);

        //remove all Fee Basis from person
        person.removeAllFeeBasis();

        for (Iterator iter = zfeSegments.iterator(); iter.hasNext();)
        {
            ZFE zfe = (ZFE) iter.next();
            FeeBasisMetaData metaData = new FeeBasisMetaDataFromZFE(zfe, msh);
            FeeBasis feeBasis = (FeeBasis) feeBasisBuilder.build(metaData);

            if (feeBasis != null)
            {
                person.addFeeBasis(feeBasis);
            }
        }
    }

    private void buildIncomeTest(Person person, Message message)
            throws BuilderException, InvalidMessageException
    {
        List zmts = message.getSegments(SegmentConstants.ZMT);

        // The IncomeTestType in the IncomeTest should determine if
        // the IncomeTest is means test or LTC Copay test or LTC Copay Exempt
        IncomeTestMetaData incomeTestMetadata = new IncomeTestMetaDataFromZMT(
                (ZPD)message.getSegment(SegmentConstants.ZPD),
                zmts, message.getSegments(SegmentConstants.NTE),
                (ZIC) message.getSegment(SegmentConstants.ZIC),
                message.getSendingFacility());

        Integer incomeYear = super.buildYear(null, incomeTestMetadata
                .getIncomeYear());

        if(incomeYear !=null){
        	incomeTestMetadata.setEntity(person.getIncomeTest(incomeYear));
        }

        IncomeTest incomeTest = (IncomeTest) this.incomeTestBuilder
                .build(incomeTestMetadata);

        // Remove all existing income tests and add the one for the income year
        // in message
        person.removeAllIncomeTests();


        if (incomeYear != null)
        {
            person.setIncomeTest(incomeYear, incomeTest);
        }
    }

    private IncompetenceRuling buildIncompetenceRuling(
            IncompetenceRuling input, Message message) throws BuilderException,
            InvalidMessageException
    {
        // The ZPD does have a couple of fields for incompentent data - but they
        // are NOT used. Rather the date in the ZGD for VA and/or Civil
        // Guardian is the date that is used as the date the veteran was ruled
        // incompetent either by the VA or by Civil.
        // On the Vista side if incompetent dates are entered via the Load/Edit
        // or Registration options, the Rated Incompetent indicator on the ZPD
        // IS populated. However, if the rated incompentent
        // dates are entered via the same option that folks use to enter the
        // guardian info (name, etc) then the Rated Incompetent indicator on
        // the ZPD is NOT populated.
        IncompetenceRulingMetaData metaData = new IncompetenceRulingMetaDataFromZGD(
                message.getSegments(SegmentConstants.ZGD), (ZPD) message
                        .getSegment(SegmentConstants.ZPD));

        metaData.setEntity(input);

        return this.buildIncompetenceRuling(metaData);
    }

    private IncompetenceRuling buildIncompetenceRuling(
            IncompetenceRulingMetaData metaData) throws BuilderException
    {
        return (IncompetenceRuling) this.incompetenceRulingBuilder
                .build(metaData);
    }

    private IneligibilityFactor buildIneligibilityFactor(
            IneligibilityFactor input, Message message)
            throws BuilderException, InvalidMessageException
    {
        IneligibilityFactorMetaData metaData = new IneligibilityFactorMetaDataFromZIE(
                (ZIE) message.getSegment(SegmentConstants.ZIE), (MSH) message
                        .getSegment(SegmentConstants.MSH));
        metaData.setEntity(input);

        return this.buildIneligibilityFactor(metaData);
    }

    private IneligibilityFactor buildIneligibilityFactor(
            IneligibilityFactorMetaData metaData) throws BuilderException
    {
        return (IneligibilityFactor) this.ineligibilityFactorBuilder
                .build(metaData);
    }

    private MedicaidFactor buildMedicaidFactor(MedicaidFactor input,
            Message message) throws BuilderException, InvalidMessageException
    {
        MedicaidFactorMetaData metaData = new MedicaidFactorMetaDataFromZPD(
                (ZPD) message.getSegment(SegmentConstants.ZPD));
        metaData.setEntity(input);

        return this.buildMedicaidFactor(metaData);
    }

    private MedicaidFactor buildMedicaidFactor(MedicaidFactorMetaData metaData)
            throws BuilderException
    {
        return (MedicaidFactor) this.medicaidFactorBuilder.build(metaData);
    }

    private void buildMedicares(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        Set medicares = super.getOfType(input.getInsurances(), Medicare.class);
        Set toAdd = new HashSet();
        Set toRemove = new HashSet(medicares);

        List in1s = message.getSegments(SegmentConstants.IN1);
        IN1 partA = null;
        IN1 partB = null;

        for (int index = 0; index < ((in1s == null) ? 0 : in1s.size()); index++)
        {
            IN1 in1 = (IN1) in1s.get(index);
            if (this.isMedicare(in1))
            {
                if (isMedicarePartA(in1))
                {
                    partA = in1;
                } else if (isMedicarePartB(in1))
                {
                    partB = in1;
                }
            }
        }

        boolean isEnrolledInPartA = partA != null;
        /*Defect294787-Medicare-part A and B -copy A for B -update –data will be shown - REEG_00012084*/
        boolean isEnrolledInPartB = partB != null;
        if (partA != null)
            this.processMedicare(toAdd, new MedicareMetaDataFromIN1(partA,
                    null, isEnrolledInPartA, message.getSendingFacility()));

        if (partB != null)
        	/*Defect294787-Medicare-part A and B -copy A for B -update –data will be shown - REEG_00012084*/        	
            this.processMedicare(toAdd, new MedicareMetaDataFromIN1(null,
                    partB, isEnrolledInPartB, message.getSendingFacility()));
        // Remove all existing medicares
        for (Iterator i = toRemove.iterator(); i.hasNext();)
        {
            input.removeInsurance((InsurancePolicy) i.next());
        }

        for (Iterator i = toAdd.iterator(); i.hasNext();)
        {
            input.addInsurance((InsurancePolicy) i.next());
        }
    }

    private MilitaryService buildMilitaryService(MilitaryService input,
            Message message) throws BuilderException, InvalidMessageException
    {
        MilitaryServiceMetaData metaData = new MilitaryServiceMetaDataFromZEL(
                (MSH) message.getSegment(SegmentConstants.MSH), (ZEL) message
                        .getSegment(SegmentConstants.ZEL), (ZSP) message
                        .getSegment(SegmentConstants.ZSP), (ZPD) message
                        .getSegment(SegmentConstants.ZPD), message
                        .getSegments(SegmentConstants.ZMH));
        metaData.setEntity(input);

        return this.buildMilitaryService(metaData);
    }

    private MilitaryService buildMilitaryService(
            MilitaryServiceMetaData metaData) throws BuilderException
    {
        return (MilitaryService) this.militaryServiceBuilder.build(metaData);
    }

    private MilitarySexualTrauma buildMilitarySexualTrauma(
            MilitarySexualTraumaMetaData metaData) throws BuilderException
    {
        return (MilitarySexualTrauma) this.militarySexualTraumaBuilder
                .build(metaData);
    }

    private MonetaryBenefitAward buildMonetaryBenefitAward(
    		Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        MonetaryBenefitAwardMetaData metaData = new MonetaryBenefitAwardMetaDataFromZEL(
                (ZEL) message.getSegment(SegmentConstants.ZEL));
        metaData.setEntity(input.getMonetaryBenefitAward());


        try {
			if(this.getSystemParameterService().getVBADataSharingIndicator() && input.getEnrollmentDetermination() != null){
				MonetaryBenefitAward awd = this.buildMonetaryBenefitAward(metaData);

		        //VBA Pension Data Sharing
		        VAPensionMetaData pensionMetaData = new VAPensionMetaDataFromZE2((ZE2)message.getSegment(SegmentConstants.ZE2));
		        pensionMetaData.setEntity(awd);
		        awd = (MonetaryBenefitAward) this.vaPensionBuilder.build(pensionMetaData);

		        return awd;

			}
		} catch (ServiceException e) {
			throw new BuilderException("Could not retrieve system parameter VBA Data Sharing Indicator ", e);
		}

		 return this.buildMonetaryBenefitAward(metaData);

    }

    private MonetaryBenefitAward buildMonetaryBenefitAward(
            MonetaryBenefitAwardMetaData metaData) throws BuilderException
    {
        return (MonetaryBenefitAward) this.monetaryBenefitAwardBuilder
                .build(metaData);
    }

    private NoseThroatRadium buildNoseThroatRadium(
            NoseThroatRadiumMetaData metaData) throws BuilderException
    {
        return (NoseThroatRadium) this.noseThroatRadiumBuilder.build(metaData);
    }

    private SpinalCordInjury buildSpinalCordInjury(
            SpinalCordInjuryMetaData metaData) throws BuilderException
    {
        return (SpinalCordInjury) this.spinalCordInjuryBuilder.build(metaData);
    }

    private void buildPatientVisitSummary(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        PatientVisitSummaryMetaData metaData = new PatientVisitSummaryMetaDataFromZIO(
                (ZIO) message.getSegment(SegmentConstants.ZIO), (ZIC) message
                        .getSegment(SegmentConstants.ZIC), message
                        .getSendingFacility());
        VAFacility facilityVisited = super.build((VAFacility) null, metaData
                .getFacilityVisited());

        Integer incomeYear = super.buildYear((Integer) null, metaData
                .getIncomeYear());
        metaData.setEntity(input.getPatientVisitSummary(incomeYear,
                facilityVisited));

        input.setPatientVisitSummary(incomeYear, facilityVisited, this
                .buildPatientVisitSummary(metaData));
    }

    private PatientVisitSummary buildPatientVisitSummary(
            PatientVisitSummaryMetaData metaData) throws BuilderException
    {
        return (PatientVisitSummary) this.patientVisitSummaryBuilder
                .build(metaData);
    }

    private Person buildPerson(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {

        ZEM zem = null;
        List zems = message.getSegments(SegmentConstants.ZEM);
        for (Iterator i = zems.iterator(); (zem == null) && i.hasNext();)
        {
            ZEM temp = (ZEM) i.next();
            if ("1".equals(temp.getSetID()))
            {
                zem = temp;
            }
        }

        PersonMetaData metaData = new PersonMetaDataFromPID((PID) message
                .getSegment(SegmentConstants.PID), (ZPD) message
                .getSegment(SegmentConstants.ZPD), zem, (ZEN) message
                .getSegment(SegmentConstants.ZEN), (ZEL) message
                .getSegment(SegmentConstants.ZEL), (MSH) message
                .getSegment(SegmentConstants.MSH), message
                .getSegments(SegmentConstants.ZMH), (ZIO) message
                .getSegment(SegmentConstants.ZIO));
        metaData.setEntity(input);

        return this.buildPerson(metaData);
    }

    private Person buildPerson(PersonMetaData metaData) throws BuilderException
    {
        return (Person) this.personBuilder.build(metaData);
    }

    /**
     * Builds Phones, Pager, Email from PID-13 and PID-14
     *
     * @param input
     * @param message
     * @throws BuilderException
     * @throws InvalidMessageException
     */
    private void buildPhonesAndEmail(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {

        //Phones to be added
        Set phonesToAdd = new HashSet();
        Set emailsToAdd = new HashSet();

        PID pid = (PID) message.getSegment(SegmentConstants.PID);

        List rf1Segments = message.getSegments(SegmentConstants.RF1);

        //Create an array of XTN from PID-13 which can contain Phone Numbers,
        // Pager, and email address
        XTN[] xtns = XTN.create(pid.getHomePhoneNumber(), pid
                .getRepeatDelimiter(), pid.getComponentDelimiter());

        for (int index = 0; index < ((xtns == null) ? 0 : xtns.length); index++)
        {
            //Get the telecom use code e.g PRN, NET, WPN
            String telecomUseCode = ((xtns[index] == null || xtns[index]
                    .getUseCode() == null)) ? null : xtns[index].getUseCode()
                    .getValue();

            //Get the correct RF1 segment based on the telecom type
            RF1 rf1 = getRF1ByTelecomUseCode(rf1Segments, telecomUseCode);

            //If telecom use code = NET, then process email, else process phone
            if (telecomUseCode != null
                    && SegmentConstants.TELECOM_USE_CODE_EMAIL
                            .equals(telecomUseCode))
            {
                //Get the correct RF1 segment based on the telecom type
                EmailMetaData emailMetaData = new EmailMetaDataFromXTN(
                        xtns[index], rf1);
                this.processEmail(emailsToAdd, emailMetaData);
            } else
            {
                PhoneMetaData metaData = new PhoneMetaDataFromPID(xtns[index],
                        rf1);
                this.processPhone(phonesToAdd, metaData);
            }
        }

        // Add phones to Person
        input.removeAllPhones();
        for (Iterator i = phonesToAdd.iterator(); i.hasNext();)
        {
            input.addPhone((Phone) i.next());
        }

        // Add email to Person
        input.removeAllEmails();
        for (Iterator i = emailsToAdd.iterator(); i.hasNext();)
        {
            input.addEmail((Email) i.next());
        }

    }

    /**
     * There can be upto 5 RF1 segments in the incoming message, SAD, CAD, CPH,
     * PNO and EAD
     *
     * For ORN telecom use code, use CPH RF1 segment For BPN telecom use code,
     * use PNO RF1 segment For NET telecom use code, use EAD RF1 segment For
     * other i.e PRN(primary residence), WPN(work)telecom use code no RF1 data
     * nedded
     *
     * @param rf1Segments
     * @param telecomUseCode
     * @return
     */
    private RF1 getRF1ByTelecomUseCode(List rf1Segments, String telecomUseCode)
    {
        if (rf1Segments == null)
            return null;

        RF1 rf1 = null;
        RF1 rf1Current = null;

        for (Iterator iter = rf1Segments.iterator(); iter.hasNext();)
        {
            rf1Current = (RF1) iter.next();

            if (SegmentConstants.TELECOM_USE_CODE_CELL_PHONE
                    .equals(telecomUseCode))
            {
                //Use CPH RF1
                if (SegmentConstants.REFERRAL_TYPE_CELL_PHONE_CHANGE
                        .equals(rf1Current.getReferralType()))
                {
                    rf1 = rf1Current;
                    break;
                }
            } else if (SegmentConstants.TELECOM_USE_CODE_PAGER
                    .equals(telecomUseCode))
            {
                //Use PNO RF1
                if (SegmentConstants.REFERRAL_TYPE_PAGER_NUMBER_CHANGE
                        .equals(rf1Current.getReferralType()))
                {
                    rf1 = rf1Current;
                    break;
                }
            } else if (SegmentConstants.TELECOM_USE_CODE_EMAIL
                    .equals(telecomUseCode))
            {
                //Use EAD RF1
                if (SegmentConstants.REFERRAL_TYPE_EMAIL_ADDRESS_CHANGE
                        .equals(rf1Current.getReferralType()))
                {
                    rf1 = rf1Current;
                    break;
                }
            } else if (SegmentConstants.TELECOM_USE_CODE_PRIMARY_RESIDENCE
                    .equals(telecomUseCode))
            {
                //Use PHH RF1 - CCR11553
                if (SegmentConstants.REFERRAL_TYPE_HOME_PHONE_CHANGE
                        .equals(rf1Current.getReferralType()))
                {
                    rf1 = rf1Current;
                    break;
                }
            } else if (SegmentConstants.TELECOM_USE_CODE_WORK
                    .equals(telecomUseCode))
            {
                //Use  PHW RF1- Permanent Address Verification - For future release when VistA add OR1 segment for PHW
                /*if (SegmentConstants.REFERRAL_TYPE_WORK_PHONE_CHANGE
                        .equals(rf1Current.getReferralType()))
                {
                    rf1 = rf1Current;
                    break;
                } */
                // Use  SAD RF1- Permanent Address Verification
                if (SegmentConstants.REFERRAL_TYPE_STREET_ADDRESS_CHANGE
                        .equals(rf1Current.getReferralType()))
                {
                    rf1 = rf1Current;
                    break;
                }

            }
        }

        return rf1;
    }


    private RF1 getRF1ByAddressType(List rf1Segments, String addressCode)
    {
        if (rf1Segments == null)
            return null;

        for (Iterator iter = rf1Segments.iterator(); iter.hasNext();)
        {
        	RF1 rf1  = (RF1) iter.next();
            //RF1 contains only SAD and CAD address types
            if ((AddressType.CODE_PERMANENT_ADDRESS.getCode().equals(
            		addressCode) && (SegmentConstants.ADDRESS_TYPE_STREET
                    .equals(rf1.getReferralType()))))
            {
                return rf1;
            } else if ((AddressType.CODE_CONFIDENTIAL_ADDRESS.getCode().equals(
            		addressCode) && (SegmentConstants.ADDRESS_TYPE_CONFIDENTIAL
                    .equals(rf1.getReferralType()))))
            {
                return rf1;
            }
        }

        return null;
    }

    private PrivateInsurance buildPrivateInsurance(
            PrivateInsuranceMetaData metaData) throws BuilderException
    {
        return (PrivateInsurance) this.privateInsuranceBuilder.build(metaData);
    }

    private void buildPrivateInsurances(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        Set privateInsurances = super.getOfType(input.getInsurances(),
                PrivateInsurance.class);
        Set toAdd = new HashSet();
        Set toRemove = new HashSet(privateInsurances);

        List in1s = message.getSegments(SegmentConstants.IN1);

        for (int index = 0; index < ((in1s == null) ? 0 : in1s.size()); index++)
        {
            IN1 in1 = (IN1) in1s.get(index);
            if (this.isPrivateInsurance(in1))
            {
                this.processPrivateInsurance(toAdd,
                        new PrivateInsuranceMetaDataFromIN1(in1, message
                                .getSendingFacility()));
            }
        }

        for (Iterator i = toRemove.iterator(); i.hasNext();)
        {
            input.removeInsurance((InsurancePolicy) i.next());
        }

        for (Iterator i = toAdd.iterator(); i.hasNext();)
        {
            input.addInsurance((InsurancePolicy) i.next());
        }
    }

    private void buildPurpleHeart(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        Set set = super.getOfType(input.getDecorations(), PurpleHeart.class);
        List zmhs = message.getSegments(SegmentConstants.ZMH);

        ZMH zmh = null;
        MSH msh = (MSH) message.getSegment(SegmentConstants.MSH);

        for (int index = 0; ((index < ((zmhs == null) ? 0 : zmhs.size())) && (zmh == null)); index++)
        {
            ZMH current = (ZMH) zmhs.get(index);
            if ("PH".equals(current.getMilitaryHistoryType()))
            {
                zmh = current;
            }
        }

        PurpleHeart current = ((set == null) || set.isEmpty()) ? null
                : (PurpleHeart) set.iterator().next();
        PurpleHeartMetaData metaData = new PurpleHeartMetaDataFromZMH(zmh, msh);
        Boolean shouldAdd = super.build(new Boolean(current != null), metaData
                .getIndicator());

        // Only build PH Data if a MZH segment for a PH is present with an
        // indicator
        // of either Y or N. If we blindly build a purple heart indicator, rules
        // will
        // not allow any update to purple heart from a message. A Z07 message
        // can only
        // update purple heart if a purple heart is NULL. Any modification to an
        // exsiting
        // purple heart must be done through a UI (HEC) - Defect 2257 and 2035
        if (zmh != null
                && (Boolean.TRUE.equals(shouldAdd) || Boolean.FALSE
                        .equals(shouldAdd)))
        {

            if (current == null)
            {
                input.addDecoration(this.buildPurpleHeart(metaData));
            } else
            {
                metaData.setEntity(current);
                this.buildPurpleHeart(metaData);
            }
        }
    }

    private PurpleHeart buildPurpleHeart(PurpleHeartMetaData metaData)
            throws BuilderException
    {
        return (PurpleHeart) this.purpleHeartBuilder.build(metaData);

    }

     /**
		 * Build Combat Episodes for OEF/OIF data
		 *
		 * @param input
		 * @param message
		 * @throws BuilderException
		 * @throws InvalidMessageException
		 */
    private void buildCombatEpisodes(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        List zmhs = message.getSegments(SegmentConstants.ZMH);
        MilitaryService ms = input.getMilitaryService();
        //remove all existing combat episodes
        ms.removeAllCombatEpisodes();

        if (zmhs != null && zmhs.size() > 0) {
        	for (int index=0; index < zmhs.size(); index++){
            	ZMH zmh = (ZMH) zmhs.get(index);
                if (MetaDataConstants.OEF_OIF_EPISODE.equals(zmh.getMilitaryHistoryType()))
                {
                    //process the segment for OEF/OIF
                	CombatEpisodeMetaData metaData = new CombatEpisodeMetaDataFromZMH(zmh);
                	CombatEpisode combatEpisode = (CombatEpisode)
                		getCombatEpisodeBuilder().build(metaData);
                	//build combat episode
                    Boolean shouldAdd = Boolean.TRUE;
                    if (combatEpisode != null && shouldAdd.booleanValue()){
                    	ms.addCombatEpisode(combatEpisode);
                    }
                }
        	}
        }
    }
    private RadiationExposure buildRadiationExposure(
            RadiationExposureMetaData metaData) throws BuilderException
    {
        return (RadiationExposure) this.radiationExposureBuilder
                .build(metaData);
    }

    private ReceivedEnrollment buildReceivedEnrollment(
            ReceivedEnrollment input, Message message) throws BuilderException,
            InvalidMessageException
    {
        ReceivedEnrollmentMetaData metaData = new ReceivedEnrollmentMetaDataFromZEN(
                (ZEN) message.getSegment(SegmentConstants.ZEN));
        metaData.setEntity(input);

        return this.buildReceivedEnrollment(metaData);
    }

    private ReceivedEnrollment buildReceivedEnrollment(
            ReceivedEnrollmentMetaData metaData) throws BuilderException
    {
        return (ReceivedEnrollment) this.receivedEnrollmentBuilder
                .build(metaData);
    }

    private ServiceConnectionAward buildServiceConnectionAward(
            ServiceConnectionAward input, Message message)
            throws BuilderException, InvalidMessageException
    {
        ServiceConnectionAwardMetaData metaData = new ServiceConnectionAwardMetaDataFromZSP(
                (ZSP) message.getSegment(SegmentConstants.ZSP), message
                        .getSegments(SegmentConstants.ZRD));
        metaData.setEntity(input);

        return this.buildServiceConnectionAward(metaData);
    }

    private ServiceConnectionAward buildServiceConnectionAward(
            ServiceConnectionAwardMetaData metaData) throws BuilderException
    {
        return (ServiceConnectionAward) this.serviceConnectionAwardBuilder
                .build(metaData);
    }

    private void buildSpecialFactors(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        ZEL zel = (ZEL) message.getSegment(SegmentConstants.ZEL);

        Set toAdd = new HashSet();

        this.processAgentOrangeExposure(toAdd,
                new AgentOrangeExposureMetaDataFromZEL(zel));
        this.processEnvironmentalContaminationExposure(toAdd,
                new EnvironmentalContaminationExposureMetaDataFromZEL(zel));
        this.processRadiationExposure(toAdd,
                new RadiationExposureMetaDataFromZEL(zel));
        this.processCampLejeuneVerification(toAdd,
                new CampLejeuneVerificationMetaDataFromZEL(zel));

        input.removeAllSpecialFactors();

        for (Iterator i = toAdd.iterator(); i.hasNext();)
        {
            input.addSpecialFactor((SpecialFactor) i.next());
        }
    }

    private void buildEmployment(Person input, Message message)
    	throws BuilderException, InvalidMessageException
    {
    	if (input.getEmployment() != null) {
    		input.removeEmployment(input.getEmployment());
    	}

        EmploymentMetaData metaData = new EmploymentMetaDataFromZEM(
                (ZEM) message.getSegment(SegmentConstants.ZEM));

        Employment employment = (Employment) this.employmentBuilder.build(metaData);
    	if (employment != null) {
    		input.setEmployment(employment);
    	}
    }

    private boolean isMedicaid(IN1 in1)
    {
        return (InsurancePlanType.CODE_MEDICAID.getCode().equals(in1.getPlanType()));
    }

    private boolean isMedicare(IN1 in1)
    {
        return (InsurancePlanType.CODE_MEDICARE_M.getCode().equals(in1.getPlanType()));
    }

    private boolean isPrivateInsurance(IN1 in1)
    {
        return (!this.isMedicaid(in1) && !this.isMedicare(in1));
    }

    /**
     *
     * @param person
     * @param toAdd
     * @param toConfCategories list of ConfidentialAddressCategories
     * @param metaData
     * @return If a confidential address has already been processed
     * @throws BuilderException
     */
    private boolean processAddress(Person person,
            Set toAdd,
            Set toConfCategories,
            AddressMetaData metaData,
            boolean processedConfAddress)
            throws BuilderException
    {

        Address address = (Address) this.addressBuilder.build(metaData);

        if (address != null)
        {
	        if (AddressType.CODE_CONFIDENTIAL_ADDRESS.getCode().equals(address.getType().getCode()))
	        {
                // Only one confidential address needs to be added, the rest are repeated
                if (!processedConfAddress) {
                    toAdd.add(address);
                }
                processedConfAddress = true;

                // now add the confidential address category
                // CCR7423 VOA -- All Confidential Address Categories are allowed

	            ConfidentialAddressCategoryType categoryType = (ConfidentialAddressCategoryType)
	            	confidentialAddressCategoryTypeBuilder.build(metaData.getType());

                if (categoryType != null) {
                    toConfCategories.add(categoryType);
                }
 	        }
            else {
                toAdd.add(address);
            }
        }

        return processedConfAddress;
    }

    /**
     * Overlay Birth Address record data (birth place city and state) onto Person's BirthRecord
     * @param person
     * @param metaData
     */
    private void processBirthAddress(Person person, AddressMetaData metaData)
        throws BuilderException
    {
       if (metaData == null) {
           return;
       }

       BirthRecord birthRecord = (person.getBirthRecord() != null ? person
                .getBirthRecord() : new BirthRecord());

        birthRecord.setCity(super.build(birthRecord.getCity(), metaData
                .getCity()));
        birthRecord.setState(super.build(birthRecord.getState(), metaData
                .getState()));

        person.setBirthRecord(birthRecord);
    }

    private void processAgentOrangeExposure(Set toAdd,
            AgentOrangeExposureMetaData metaData) throws BuilderException
    {
        AgentOrangeExposure value = this.buildAgentOrangeExposure(metaData);
        if (value != null)
        {
            Boolean shouldAdd = super.build(new Boolean(value != null),
                    metaData.getIndicator());
            if (Boolean.TRUE.equals(shouldAdd))
            {
                toAdd.add(value);
            }
        }
    }

    private void processAssociation(Set toAdd, AssociationMetaData metaData)
            throws BuilderException
    {
        Association value = (Association) this.associationBuilder
                .build(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private void processCatastrophicDisability(Set toAdd,
            CatastrophicDisabilityMetaData metaData) throws BuilderException
    {
        CatastrophicDisability value = (CatastrophicDisability) this.catastrophicDisabilityBuilder
                .build(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private void processEnvironmentalContaminationExposure(Set toAdd,
            EnvironmentalContaminationExposureMetaData metaData)
            throws BuilderException
    {
        EnvironmentalContaminationExposure value = (EnvironmentalContaminationExposure) this.environmentalContaminationExposureBuilder
                .build(metaData);
        if (value != null)
        {
            Boolean shouldAdd = super.build(new Boolean(value != null),
                    metaData.getIndicator());
            if (Boolean.TRUE.equals(shouldAdd))
            {
                toAdd.add(value);
            }
        }
    }

    private void processMedicare(Set toAdd, MedicareMetaData metaData)
            throws BuilderException
    {
        Medicare value = (Medicare) this.medicareBuilder.build(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private void processMilitarySexualTrauma(Set toAdd,
            MilitarySexualTraumaMetaData metaData) throws BuilderException
    {
        MilitarySexualTrauma value = this.buildMilitarySexualTrauma(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private void processNoseThroatRadium(Set toAdd,
            NoseThroatRadiumMetaData metaData) throws BuilderException
    {
        NoseThroatRadium value = this.buildNoseThroatRadium(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private void processSpinalCordInjury(Set toAdd,
            SpinalCordInjuryMetaData metaData) throws BuilderException
    {
        SpinalCordInjury value = this.buildSpinalCordInjury(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private void processPhone(Set toAdd, PhoneMetaData metaData)
            throws BuilderException
    {
        Phone value = (Phone) this.phoneBuilder.build(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    /**
     * @param emailsToAdd
     * @param emailMetaData
     * @throws BuilderException
     */
    private void processEmail(Set toAdd, EmailMetaData emailMetaData)
            throws BuilderException
    {
        Email value = (Email) this.emailBuilder.build(emailMetaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }


    private void processPrivateInsurance(Set toAdd,
            PrivateInsuranceMetaData metaData) throws BuilderException
    {
        PrivateInsurance value = this.buildPrivateInsurance(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private void processRadiationExposure(Set toAdd,
            RadiationExposureMetaData metaData) throws BuilderException
    {
        RadiationExposure value = this.buildRadiationExposure(metaData);
        if (value != null)
        {
            Boolean shouldAdd = super.build(new Boolean(value != null),
                    metaData.getIndicator());
            if (Boolean.TRUE.equals(shouldAdd))
            {
                toAdd.add(value);
            }
        }
    }

    private void processCampLejeuneVerification(Set toAdd,
            CampLejeuneVerificationMetaData metaData) throws BuilderException
    {
    	CampLejeuneVerification value = this.buildCampLejeuneVerification(metaData);
        if (value != null)
                   toAdd.add(value);
    }
    /**
     * The first ZEL segment(Set ID 1) is always the PrimaryEligibility and the
     * rest SecondaryEligibility
     *
     * @param input
     * @param message
     * @throws BuilderException
     * @throws InvalidMessageException
     */
    private void buildReceivedEligibilities(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        List zels = message.getSegments(SegmentConstants.ZEL);
        ZPD zpd = (ZPD) message.getSegment(SegmentConstants.ZPD);

        if ((zels != null) && !zels.isEmpty())
        {
            ReceivedEligibilityMetaData primaryMetaData = new ReceivedEligibilityMetaDataFromZEL(
                    (ZEL) zels.get(0), zpd);
            primaryMetaData.setEntity(input.getReceivedPrimaryEligibility());
            input.setReceivedPrimaryEligiblity(this
                    .buildReceivedEligibility(primaryMetaData));

            ReceivedEligibilityMetaData[] secondaryMetaData = new ReceivedEligibilityMetaData[zels
                    .size() - 1];
            for (int index = 1; index < zels.size(); index++)
            {
                secondaryMetaData[index - 1] = new ReceivedEligibilityMetaDataFromZEL(
                        (ZEL) zels.get(index), zpd);
            }

            this.buildReceivedSecondaryEligibilities(input, secondaryMetaData);
        }
    }

    private void buildReceivedSecondaryEligibilities(Person input,
            ReceivedEligibilityMetaData[] metaData) throws BuilderException
    {
        Set toAdd = new HashSet();
        Set toRemove = new HashSet(input.getReceivedSecondaryEligibilities());

        for (int index = 0; index < ((metaData == null) ? 0 : metaData.length); index++)
        {
            this.processReceivedEligibility(toAdd, metaData[index]);
        }

        for (Iterator i = toRemove.iterator(); i.hasNext();)
        {
            input.removeReceivedSecondaryEligibility((ReceivedEligibility) i
                    .next());
        }

        for (Iterator i = toAdd.iterator(); i.hasNext();)
        {
            input.addReceivedSecondaryEligibility((ReceivedEligibility) i
                    .next());
        }
    }

    private ReceivedEligibility buildReceivedEligibility(
            ReceivedEligibilityMetaData metaData) throws BuilderException
    {
        return (ReceivedEligibility) this.receivedEligibilityBuilder
                .build(metaData);
    }

    private void processReceivedEligibility(Set toAdd,
            ReceivedEligibilityMetaData metaData) throws BuilderException
    {
        ReceivedEligibility value = this.buildReceivedEligibility(metaData);
        if (value != null)
        {
            toAdd.add(value);
        }
    }

    private boolean isMedicarePartA(IN1 in1)
    {
        return (IN1.MEDICARE_PART_A.equals(in1.getGroupNumber()) || IN1.MEDICARE_PART_A
                .equals(in1.getGroupName()));
    }

    private boolean isMedicarePartB(IN1 in1)
    {
        return (IN1.MEDICARE_PART_B.equals(in1.getGroupNumber()) || IN1.MEDICARE_PART_B
                .equals(in1.getGroupName()));
    }

    private static class ZCDKey
    {
        private ZCD zcd;

        public ZCDKey(ZCD zcd)
        {
            super();

            this.zcd = zcd;
        }

        /*
         * (non-Javadoc)
         *
         * @see java.lang.Object#equals(java.lang.Object)
         */
        public boolean equals(Object obj)
        {
            if (!(obj instanceof ZCDKey))
            {
                return false;
            }
            ZCDKey key = (ZCDKey) obj;

            return new EqualsBuilder().append(this.zcd.getDecidedBy(),
                    key.zcd.getDecidedBy()).append(this.zcd.getDecisionDate(),
                    key.zcd.getDecisionDate()).append(
                    this.zcd.getDeterminationFacility(),
                    key.zcd.getDeterminationFacility()).append(
                    this.zcd.getDeterminationMethod(),
                    key.zcd.getDeterminationMethod()).append(
                    this.zcd.getReviewDate(), key.zcd.getReviewDate())
                    .isEquals();

        }

        /*
         * (non-Javadoc)
         *
         * @see java.lang.Object#hashCode()
         */
        public int hashCode()
        {
            return new HashCodeBuilder().append(this.zcd.getDecidedBy())
                    .append(this.zcd.getDecisionDate()).append(
                            this.zcd.getDeterminationFacility()).append(
                            this.zcd.getDeterminationMethod()).append(
                            this.zcd.getReviewDate()).toHashCode();
        }
    }



 }