/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
//Package
package gov.va.med.esr.messaging.builder.message;

//Java Classes
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import gov.va.med.fw.hl7.Segment;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.hl7.segment.ZMT;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.util.builder.BuilderException;

import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.Hardship;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.financials.IncomeTestStatus;
import gov.va.med.esr.common.model.lookup.IncomeTestSource;
import gov.va.med.esr.common.model.lookup.IncomeTestType;
import gov.va.med.esr.common.model.lookup.MeansTestStatus;
import gov.va.med.esr.common.model.lookup.MessageType;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SignatureImage;
import gov.va.med.esr.common.util.CommonDateUtils;


/**
 * Class to build the ZMT segment.
 *
 * @author Alex Yoon
 * @author Rajiv Patnaik
 * @version 1.0
 */
public class ZMTBuilder extends AbstractSegmentBuilder
{

    /**
    * An instance of serialVersionUID
    */
   private static final long serialVersionUID = 314261275236681361L;

   /**
     * Default contructor.
     */
    public ZMTBuilder()
    {
        super();
    }

    /**
     * Method to build the ZMT segment.
     *
     * @param metaData
     *            The parameter object used to build the a ZMT segment.
     * @return The ZMT segment.
     */
    public Object build(ZMTMetaData metaData) throws BuilderException
    {
        if ((metaData == null) || (metaData.getEntity() == null)
                || !(metaData.getEntity() instanceof Person)
                || metaData.getMessageType() == null)
        {
            throw new BuilderException(
                    "Invalid input parameter to build a segment");
        }

        List zmtSegments = new ArrayList();

        Person person = (Person) metaData.getEntity();

        try
        {
        	if (MessageType.CODE_ORUZ06_TO_SITE.getName().equals(
                    metaData.getMessageType().getCode()))
            {
        		ZMT segment = new ZMT();
        		if(metaData.getAction().equalsIgnoreCase("R")){
                	segment = buildSelectedZMTSegments(person, metaData.getDeletedIncomeTest(), metaData.getType());
                	zmtSegments.add(segment);
                }
        		else if(metaData.getAction().equalsIgnoreCase("C")){
        			IncomeTest incomeTest = person.getIncomeTest(metaData.getIncomeYear());
        			segment = buildSelectedZMTSegments(person, incomeTest, metaData.getType());
                	zmtSegments.add(segment);
        		}
            }
            //For ORUZ11, only one ZMT segment is returned.
            if (MessageType.CODE_ORUZ11_TO_SITE.getName().equals(
                    metaData.getMessageType().getCode()))
            {
                ZMT segment = new ZMT();
                segment.setSetID("1");
                //Set the means test status only
                segment.setMeansTestStatus(buildMeansTestStatus(person));
                zmtSegments.add(segment);
            }
            //For ORUZ10/ORFZ10 build all the ZMT segments
            if (MessageType.CODE_ORFZ10_TO_SITE.getName().equals(
                    metaData.getMessageType().getCode())
                    || MessageType.CODE_ORUZ10_TO_SITE.getName().equals(
                            metaData.getMessageType().getCode()))
            {
            	VAFacility destinationSite = metaData.getSiteIdentity().getVaFacility();

            	//Income Year will be provided for Z10s. Deleted income test will be available when the
                //income test is deleted, all other times it is null.
                zmtSegments = buildZMTSegments(
                		person,
                		metaData.getIncomeYear(),
                		metaData.getDeletedIncomeTest(),
                		destinationSite);
            }

        } catch (Exception e)
        {
            throw new BuilderException(
                    "Failed to build ZMT Segment due to an exception ", e);
        }

        return zmtSegments;
    }


    private List buildZMTSegments(Person person, Integer incomeYear, IncomeTest deletedIncomeTest, VAFacility destinationSite)
            throws BuilderException
    {
    	try {
	        FinancialStatement financialStatement = person
	                .getFinancialStatement(incomeYear);

	        IncomeTest incomeTest = person.getIncomeTest(incomeYear);
	        Boolean isPost2005Format = financialStatement == null ? null
	                : financialStatement.getIsPost2005Format();

	        IncomeTestSource testSource = null;
	        VAFacility owningSite = null;

	        if (incomeTest != null) {
	        	IncomeTestSource originalSource = incomeTest.getSource();
	        	owningSite = incomeTest.getSiteConductingTest();

	        	// ESR_CodeCR6900 Source of test null for HEC edited tests.
	        	// If the HEC edits the test, the source is being set to NULL.
	        	// (The site conducting test always was set to null)

    	        // ESR_CodeCR6859  Source of Test -- 'Other' Facility vs "VAMC'
    	        // If sending to site owning test, use "VAMC" as source of test;
    	        // otherwise if sending to other sites, use "Other".

	        	if (owningSite != null &&
                    (originalSource != null && originalSource.getCode().equals(IncomeTestSource.CODE_VAMC.getCode()))) {
	        	    // ESR_CodeCR7678 Z10 should send Source of Test = '1' to
                    // Parent Facility when Site Cond Test is its Satellite site
	        		if (owningSite.getCode().equals(destinationSite.getCode()) ||
                         this.isSatelliteSite(owningSite, destinationSite) ) {
	        			testSource = getLookupService().getIncomeTestSourceByCode(IncomeTestSource.CODE_VAMC.getCode());
	        		} else {
	        			testSource = getLookupService().getIncomeTestSourceByCode(IncomeTestSource.CODE_OTHER.getCode());
	        		}
	        	}
	        	else {
	        		testSource = originalSource;
	        	}
	        }

	        List zmtSegments = new ArrayList();

	        //Build Means Test ZMT
	        zmtSegments.add(buildMeansTestZMT(person,incomeTest,deletedIncomeTest,isPost2005Format, testSource));

	        //Build Co-pay Test ZMT
	        zmtSegments.add(buildCoPayTestZMT(incomeTest,deletedIncomeTest,isPost2005Format, testSource));

	        //Build LTC Co-pay exemption test ZMT
	        zmtSegments
	                .add(buildLTCCoPayExemptionZMT(incomeTest,deletedIncomeTest,isPost2005Format, testSource));

	        return zmtSegments;
    	} catch (ServiceException se) {
    		throw new BuilderException(se);
    	}
    }

    /**
     * @param incomeTest
     * @param isPost2005Format
     * @return
     * @throws BuilderException
     */
    private ZMT buildMeansTestZMT(Person person, IncomeTest incomeTest,IncomeTest deletedIncomeTest,
            Boolean isPost2005Format, IncomeTestSource testSource) throws BuilderException
    {
        ZMT segment = new ZMT();

        IncomeTestStatus incomeTestStatus = getIncomeTestStatus(incomeTest,IncomeTestType.CODE_MEANS_TEST);

        SignatureImage signatureImage = incomeTest != null ?
        		person.getSignatureImage(incomeTest.getIncomeYear()) : null;

        segment.setSetID("1");
        // Code CR 8373 - only use default values for delete possibility.
        // By skipping setting default, this will produce ZMT^1 in scenario where
        // none of the logic below is applied. Vista said this should be OK.
        //setDefaultValues(segment);

       //Defect ESR_CodeCR5611. ESR will need to send only the Primary test (copay or means) on the Z10 to VistA.
        if(isPrimaryTest(incomeTest, IncomeTestType.CODE_MEANS_TEST))
        {
	            //2
	            segment.setMeansTestDate(DateFormatter.formatDate(incomeTest
	                    .getEffectiveDate()));
	            //3
	            segment.setMeansTestStatus(super
	                    .build(incomeTestStatus.getStatus()));
	            //4
	            segment.setIncome(super.build(incomeTest.getTotalIncome()));

	            //5 VFA: Included only for Income Year prior to 2009
/*	            if (CommonDateUtils.isIncomeYear2009OrLatter(incomeTest.getIncomeYear()))
	            {
	            	segment.setNetWorth(null);
	            }else
	            {*/
	            	segment.setNetWorth(super.build(incomeTest.getNetWorth()));
//	            }

	            //6
	            segment.setAdjudicationDate(DateFormatter.formatDate(incomeTest
	                    .getAdjudicationDate()));
	            //7
	            segment
	                    .setAgreedToPayDeductible(super
	                            .buildBooleanForVA001(incomeTest
	                                    .getAgreesToPayDeductible()));
	            //8
	            segment.setThresholdA(super.build(incomeTest.getThresholdA()));
	            //9
	            segment.setDeductibleExpenses(super.build(incomeTest
	                    .getDeductibleExpenses()));
	            //10
	            segment.setMeansTestCompletedDate(DateFormatter
	                    .formatDate(incomeTestStatus.getCompletedDate(),DateFormatter.DATETIME_ZONE_FORMAT));
	            //11
	            segment.setPreviousYearMTThresholdFlag(super
	                    .buildBooleanForVA001(incomeTest
	                            .getPreviousYearThresholdApplies()));
	            //12
	            segment.setTotalDependents(super.build(incomeTest
	                    .getTotalNumberOfDependents()));
	            Hardship hardship = incomeTest.getHardship();
	            if (hardship != null)
	            {
	                //13
	                segment.setHardship(super.buildBooleanForVA001(hardship
	                        .getHardshipGranted()));
	                //14
	                segment.setHardshipReviewDate(DateFormatter.formatDate(hardship
	                        .getReviewDate()));
	                //23
	                segment.setHardshipReviewSite(super.build(hardship
	                        .getSiteGrantingHardship()));
	                //24
	                segment.setHardshipEffectiveDate(DateFormatter
	                        .formatDate(hardship.getEffectiveDate()));
	                //29
	                segment.setHardshipReason(hardship.getReason());
	            }
	            //15
	            if (signatureImage != null && signatureImage.getDateIndex() != null) {
	                segment.setVeteranTestSignedDate(
	                	DateFormatter.formatDate(signatureImage.getDateIndex()));
	            }
	            //16 Confirm
	            segment.setDeclinesToGiveIncomeInfo(super
	                    .buildBooleanForVA001(getDeclineToGiveIncomeInfo(incomeTest)));
	            //17
	            segment.setTestType(super.build(incomeTestStatus.getType()));
	            //18
	            segment.setTestSource(super.build(testSource));
	            //19
	            segment.setPrimaryTest(super.buildBooleanForVA001(incomeTest
	                    .getPrimaryIncomeTest()));
	            //22
	            segment.setTestConductingSite(super.build(incomeTest
	                    .getSiteConductingTest()));

	            //25
	            segment.setTestLastEditedDate(DateFormatter
	                    .formatDate(incomeTestStatus.getLastEditedDate(),DateFormatter.DATETIME_ZONE_FORMAT));
	            //26
	            segment.setTestDeterminedStatus(super.build(incomeTestStatus
	                    .getDeterminedStatus()));

	            //27 defect 3815 - ind is true if signature object is not null
	            if (signatureImage != null && signatureImage.getSignatureIndicator() != null)
	            {
	                segment.setMeansTestSignatureIndicator(
	                    signatureImage.getSignatureIndicator().getCode());
	            }

	            //28
	            segment.setGmtThreshold(super.build(incomeTest
	                    .getGmtThresholdAmount()));
	            //30
	            segment.setMeansTestVersion(super
	                    .buildBooleanForVA001(isPost2005Format));

	            // ES 4.2_CodeCR13221_CR_VistA to Send BTFI to ES - and - ES to Send BTFI to VistA
	            //31
	            segment.setBtFinancialIndicator(super.buildBooleanForVA001(incomeTest.getBtFinancialInd()));

        } else {
            //When the income test type is Means Test and is the primary test then send delete request for that
            if(isPrimaryTest(deletedIncomeTest, IncomeTestType.CODE_MEANS_TEST)) {
            	// CR 8373 only set default for delete to produce something like ZMT^1^20090314^""
                setDefaultValues(segment);
            	//2
                segment.setMeansTestDate(DateFormatter.formatDate(deletedIncomeTest.getEffectiveDate()));
            }
        }

        return segment;
    }

    //This method is used to build selected ZMT sequence for a Z06

    private ZMT buildSelectedZMTSegments(Person person, IncomeTest incomeTest, String type)
    throws BuilderException
    {
    	try {

    		IncomeTestSource testSource = null;
    		testSource = getLookupService().getIncomeTestSourceByCode(IncomeTestSource.CODE_IVM.getCode());

    		ZMT segment = new ZMT();
    		if(incomeTest != null){
    			if(type.equalsIgnoreCase("MT")){
    				segment.setSetID("1");
    				IncomeTestStatus incomeTestStatus = getIncomeTestStatus(incomeTest,IncomeTestType.CODE_MEANS_TEST);
    				// 3
    				segment.setMeansTestStatus(super
    						.build(incomeTestStatus != null?incomeTestStatus.getStatus():null));
    				// 10
    				segment.setMeansTestCompletedDate(DateFormatter
    						.formatDate(incomeTestStatus != null ?incomeTestStatus.getCompletedDate():null,DateFormatter.DATETIME_ZONE_FORMAT));
    				// 17
    				segment.setTestType(super.build(incomeTestStatus != null ?incomeTestStatus.getType():null));
    				// 25
    				segment.setTestLastEditedDate(DateFormatter
    						.formatDate(incomeTestStatus != null ?incomeTestStatus.getLastEditedDate():null,DateFormatter.DATETIME_ZONE_FORMAT));
    				// 26
    				segment.setTestDeterminedStatus(super.build(incomeTestStatus != null ?incomeTestStatus
    						.getDeterminedStatus():null));

    			}
    			else if(type.equalsIgnoreCase("RX")){
    				segment.setSetID("2");
    				IncomeTestStatus coPayTestStatus = getIncomeTestStatus(incomeTest,
    						IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST);
    				// 3
    				segment.setMeansTestStatus(super
    						.build(coPayTestStatus != null?coPayTestStatus.getStatus():null));
    				//10
    				segment.setMeansTestCompletedDate(DateFormatter
    						.formatDate(coPayTestStatus != null?coPayTestStatus.getCompletedDate():null,DateFormatter.DATETIME_ZONE_FORMAT));
    				//17
    				segment.setTestType(super.build(coPayTestStatus != null?coPayTestStatus.getType():null));//
    				//25
    				segment.setTestLastEditedDate(DateFormatter
    						.formatDate(coPayTestStatus != null?coPayTestStatus.getLastEditedDate():null,DateFormatter.DATETIME_ZONE_FORMAT));
    				//26
    				segment.setTestDeterminedStatus(super.build(coPayTestStatus != null?coPayTestStatus
    						.getDeterminedStatus():null));
    			}
    			//2
    			segment.setMeansTestDate(DateFormatter.formatDate(incomeTest
    					.getEffectiveDate()));
    			// 7
    			segment
    			.setAgreedToPayDeductible(super
    					.buildBooleanForVA001(incomeTest
    							.getAgreesToPayDeductible()));
    			// 8
    			segment.setThresholdA(super.build(incomeTest.getThresholdA()));
    			//12
    			segment.setTotalDependents(super.build(incomeTest
    					.getTotalNumberOfDependents()));
    			//18
    			segment.setTestSource(super.build(testSource));
    			//20
    			segment.setIvmVerifiedMTCompletedDate(DateFormatter
    					.formatDate(incomeTest.getIVMTestCompletionDate()));

    			// ES 4.2_CodeCR13221_CR_VistA to Send BTFI to ES - and - ES to Send BTFI to VistA
    			//31
    			segment.setBtFinancialIndicator(super.buildBooleanForVA001(incomeTest.getBtFinancialInd()));
    		}
    		return segment;
    	} catch (ServiceException se) {
    		throw new BuilderException(se);
    	}
    }

    /**
     * 'Disclose' = NO   ----->  convert to YES
     * 'Disclose' = YES   ----->  convert to NULL
     *  There should not be a value of Declines = NO sent to the sites
     *
     * @param incomeTest
     * @return
     */
    private Boolean getDeclineToGiveIncomeInfo(IncomeTest incomeTest) {
        //If true or null, retun null
        if (incomeTest.getDiscloseFinancialInformation() == null ||
                (Boolean.TRUE.equals(incomeTest.getDiscloseFinancialInformation()))) {
            return null;
        }else
        {
            //If false, return true
            return Boolean.TRUE;
        }
    }

    /**
     * @param incomeTest
     * @return
     * @throws BuilderException
     */
    private ZMT buildCoPayTestZMT(IncomeTest incomeTest,IncomeTest deletedIncomeTest,
            Boolean isPost2005Format, IncomeTestSource testSource) throws BuilderException
    {
        ZMT segment = new ZMT();


        segment.setSetID("2");
        setDefaultValues(segment);

        //5201[UC54.4.1.4]
        //A Mean Test (MT) takes precedence over a Pharmacy (Rx) Copay Test, unless the MT Status is No Longer Required.

        //Defect REEG_00005484
        // Check if RX Co Pay is the primary test. If so, send the data
        IncomeTestStatus coPayTestStatus = getIncomeTestStatus(incomeTest,
                IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST);

        if(isPrimaryTest(incomeTest, IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST))
        {
            //2
            segment.setMeansTestDate(DateFormatter.formatDate(incomeTest
                    .getEffectiveDate()));
            //3
            segment.setMeansTestStatus(super
                    .build(coPayTestStatus.getStatus()));
            //4
            segment.setIncome(super.build(incomeTest.getTotalIncome()));
            //9
            segment.setDeductibleExpenses(super.build(incomeTest
                    .getDeductibleExpenses()));
            //10
            segment.setMeansTestCompletedDate(DateFormatter
                    .formatDate(coPayTestStatus.getCompletedDate(),DateFormatter.DATETIME_ZONE_FORMAT));
            //12
            segment.setTotalDependents(super.build(incomeTest
                    .getTotalNumberOfDependents()));

            //15 ?
            //segment.setVeteranTestSignedDate(incomeTest.get)
            //16 Confirm
            segment.setDeclinesToGiveIncomeInfo(super
                    .buildBooleanForVA001(getDeclineToGiveIncomeInfo(incomeTest)));
            //17
            segment.setTestType(super.build(coPayTestStatus.getType()));
            //18
            segment.setTestSource(super.build(testSource));
            //19
            segment.setPrimaryTest(super.buildBooleanForVA001(incomeTest
                    .getPrimaryIncomeTest()));
            //22
            segment.setTestConductingSite(super.build(incomeTest
                    .getSiteConductingTest()));
            //25
            segment.setTestLastEditedDate(DateFormatter
                    .formatDate(coPayTestStatus.getLastEditedDate(),DateFormatter.DATETIME_ZONE_FORMAT));
            //26
            segment.setTestDeterminedStatus(super.build(coPayTestStatus
                    .getDeterminedStatus()));
            //30
            segment.setMeansTestVersion(super
                    .buildBooleanForVA001(isPost2005Format));

            // ES 4.2_CodeCR13221_CR_VistA to Send BTFI to ES - and - ES to Send BTFI to VistA
            //31
            segment.setBtFinancialIndicator(super.buildBooleanForVA001(incomeTest.getBtFinancialInd()));

        } else {
            //When the income test type is RX CoPay and is the primary test then send delete request for that
        	if(isPrimaryTest(deletedIncomeTest, IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST)) {
                //2
                segment.setMeansTestDate(DateFormatter.formatDate(deletedIncomeTest.getEffectiveDate()));
            }
        }

        return segment;
    }

    /**
     * Checks if a IncomeTest is the primary test.
     * @param incomeTest
     * @param incomeTestCode
     * @return
     */
    private boolean isPrimaryTest(IncomeTest incomeTest, IncomeTestType.Code incomeTestCode)
    {
        IncomeTestType incomeTestType = incomeTest == null ? null : incomeTest.getType();

        return (incomeTestType != null
        		&& StringUtils.equals(incomeTestCode.getCode(), incomeTestType.getCode())
        		&& (Boolean.TRUE.equals(incomeTest.isPrimaryIncomeTest())));
    }


    /**
     * @param incomeTest
     * @return
     * @throws BuilderException
     */
    private ZMT buildLTCCoPayExemptionZMT(IncomeTest incomeTest,IncomeTest deletedIncomeTest,
            Boolean isPost2005Format, IncomeTestSource testSource) throws BuilderException
    {
        ZMT segment = new ZMT();

        IncomeTestStatus incomeTestStatus = getIncomeTestStatus(incomeTest, IncomeTestType.CODE_LTC_CO_PAY_EXEMPTION_TEST);

        segment.setSetID("4");
        setDefaultValues(segment);
        //If income test status is null i.e does not have a LTC copay test,do not populate data
        if (incomeTestStatus != null)
        {
            //2
            segment.setMeansTestDate(DateFormatter.formatDate(incomeTest
                    .getEffectiveDate()));
            //3
            segment.setMeansTestStatus(super
                    .build(incomeTestStatus.getStatus()));
            //4
            segment.setIncome(super.build(incomeTest.getTotalIncome()));
            //7
            segment
                    .setAgreedToPayDeductible(super
                            .buildBooleanForVA001(incomeTest
                                    .getAgreesToPayDeductible()));
            //9
            segment.setDeductibleExpenses(super.build(incomeTest
                    .getDeductibleExpenses()));
            //10
            segment.setMeansTestCompletedDate(DateFormatter
                    .formatDate(incomeTestStatus.getCompletedDate(),DateFormatter.DATETIME_ZONE_FORMAT));
            //12
            segment.setTotalDependents(super.build(incomeTest
                    .getTotalNumberOfDependents()));

            //16 Confirm
            segment.setDeclinesToGiveIncomeInfo(super
                    .buildBooleanForVA001(getDeclineToGiveIncomeInfo(incomeTest)));
            //17
            segment.setTestType(super.build(incomeTestStatus.getType()));
            //18
            segment.setTestSource(super.build(testSource));
            //22
            segment.setTestConductingSite(super.build(incomeTest
                    .getSiteConductingTest()));
            //25
            segment.setTestLastEditedDate(DateFormatter
                    .formatDate(incomeTestStatus.getLastEditedDate(),DateFormatter.DATETIME_ZONE_FORMAT));
            //30
            segment.setMeansTestVersion(super
                    .buildBooleanForVA001(isPost2005Format));

            // ES 4.2_CodeCR13221_CR_VistA to Send BTFI to ES - and - ES to Send BTFI to VistA
            //31
            segment.setBtFinancialIndicator(super.buildBooleanForVA001(incomeTest.getBtFinancialInd()));
        }

        return segment;
    }

    /**
     * Method that gets means test status.
     *
     * @param person
     *            The Person Object.
     * @return means test status.
     */
    private String buildMeansTestStatus(Person person)
    {
        String status = null;

        IncomeTest incomeTest = getHelperService().getCurrentIncomeTest(person);

        IncomeTestStatus incomeTestStatus = getIncomeTestStatus(incomeTest,
                IncomeTestType.CODE_MEANS_TEST);

        if (incomeTestStatus != null)
        {
            MeansTestStatus mtStatus = incomeTestStatus.getStatus();
            status = mtStatus == null ? null : mtStatus.getCode();
        }

        return status;
    }

    /**
     * @param incomeTest
     * @param incomeTestStatusCode
     * @return
     */
    private IncomeTestStatus getIncomeTestStatus(IncomeTest incomeTest,
            IncomeTestType.Code incomeTestStatusCode)
    {
        IncomeTestStatus incomeTestStatus = null;

        if (incomeTest != null)
        {
            Set statuses = incomeTest.getStatuses();

            if (statuses != null)
            {
                Iterator iterStatuses = statuses.iterator();

                while (iterStatuses.hasNext())
                {
                    IncomeTestStatus currentStatus = (IncomeTestStatus) iterStatuses
                            .next();
                    if ((currentStatus != null)
                            && (currentStatus.getType() != null))
                    {
                        if (incomeTestStatusCode.getName().equals(
                                currentStatus.getType().getCode()))
                        {
                            incomeTestStatus = currentStatus;
                            break;
                        }
                    }
                }
            }
        }
        return incomeTestStatus;
    }


	/**
	 * Tests if incomingSite is a parent, or ancestor, to the satellite site.
	 * @param satellite
	 * @param incomingSite
	 * @return
	 * @throws BuilderException
	 */
    private boolean isSatelliteSite(VAFacility satellite, VAFacility incomingSite) throws BuilderException {
        // Only need to check one direction. Sending sites are not satellites.
 	   try {
 	       if (satellite != null && incomingSite != null) {
 	    	   BigDecimal childId = satellite.getIdentifier();
 	           BigDecimal parentId = satellite.getParentId();
 	           VAFacility parentFacility = null;
                /*
 				* CCR9564 -- test for grand parent of satellite as well Income
 				* test not uploading when Site Conducting Test is a child to
 				* another child facility
 				*/

 	           // also prevents cases where parentId = childId, causing infinite loops
 	           while (parentId != null && !(parentId.compareTo(childId) == 0)) {
 	        	   // test for parent of satellite site
 	               if (parentId.compareTo(incomingSite.getIdentifier()) == 0) {
 	            	   return true;
 	               }

 	               // further go up the chain of parents until we exhaust the ancestor tree or find a match
 	               parentFacility = this.getLookupService().getVAFacilityById(parentId);
 	               childId = parentId;
 	               parentId = (parentFacility==null ? null : parentFacility.getParentId());
 	           }
 	       }
 	   }
  	   catch( ServiceException e ) {
  		   throw new BuilderException("Failed to get VA Facility ", e);
 	   }

  	   return false;
    }

    /**
     * ZMT-3 (Means Test Status)indicates a deletion. Set that to null.
     */
    protected void setDefaultValues(Segment segment)
    {
    	ZMT zmt = (ZMT)segment;
    	zmt.setMeansTestDate(SegmentConstants.DEFAULT_VALUE);
    	zmt.setMeansTestStatus(SegmentConstants.DEFAULT_VALUE);
    }

}