

package gov.va.med.cds.integration.vim.ha;


import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import gov.va.med.cds.clinicaldata.DomainEntryPoint;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.testharness.vhim400.TemplateIdHelper;
import gov.va.med.cds.testharness.vhim400.builders.BaseDatatypesBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDataBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDomainBuilderFactoryInterface;
import gov.va.med.cds.testharness.vhim400.builders.FilterBuilder;
import gov.va.med.cds.testharness.vhim400.builders.HAMoodJournalBuilder;
import gov.va.med.cds.testharness.vhim400.builders.HAPatientEnteredMoodJournalEntryBuilderFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;


@RunWith( SuiteAwareSpringRunner.class )
public class EndToEndPatientEnteredMoodJournalEntryTest
    extends
        AbstractHealthAdapterEndToEndTest
{
    private static final String MOOD_TEST_PATIENT_PREFIX = "Mood_Test_Patient_";
    private static String OBSERVATION_DATE_XPATH = "//observationDate/literal";

    private static final String MOOD_JOURNAL_ENTRY_POINT = "PatientEnteredMoodJournalEntry";
    private static String READ_TEST_DOMAINENTRYPOINT_XPATH = "//genericJournalEntryDetails/patient";
    private String observationDateString;
    private String queryStartDateOffset;
    private String queryEndDateOffset;
    private String queryStartDateZulu;
    private String queryEndDateZulu;
    private String queryStartDateNormal;
    private String queryEndDateNormal;

    private static String recordIdentifier;


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = "deprecatedtest" )
    public void testMoodJournalDetailsCRUD( )
        throws Exception
    {
        /// clear out any mood journal test records 
        hdrJdbcTemplate.update( "delete from mood_journal where patient_identity like '" + MOOD_TEST_PATIENT_PREFIX + "%'" );

        /// leave random patient identity in integration test - remove from functional test
        /// reasoning:  The functional tests use a control xml file to compare against the xml result. 
        /// Thus, the control file will not be identical to an xml request with a random patient identity.
        /// However, in the case of this integration test, we can leave the random patient identity in place
        String patientIdentity = MOOD_TEST_PATIENT_PREFIX + ( ( int )( Math.random() * 10000000 ) );

        /// CREATE
        String createRequestXml = createMHACreateXml( patientIdentity, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, null );
        Document createRequest = DocumentHelper.parseText( createRequestXml );
        String base64BinaryAttachmentName = createRequest.selectSingleNode("//base64BinaryAttachment").getParent().elementText("name");
        Document createResponse = createAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, createRequestXml );
        recordIdentifier = createResponse.selectSingleNode( RECORD_IDENTIFIER_IDENTITY_XPATH ).getText();
        createResponse = null;

        /// READ WITHOUT DATES
        Map<String, String> assigningAuthorityAndFacilityMap = new HashMap<String, String>();
        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( "ID_1", "PatientEnteredMoodJournalEntry" );
        entryPointFilterMap.put( FilterBuilder.QUERY_TIMEOUT_SECONDS, QUERY_TIMOUT_SECONDS_MAX );
        String filterXml = createMHAFilter( patientIdentity, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, "PatientEnteredMoodJournalEntry",
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, null, null );
        Document readResponseWithoutDatesDocument = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        List<Element> dataList = readResponseWithoutDatesDocument.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        readResponseWithoutDatesDocument = null;

        /// READ DETAIL before update and with attachment name 
        Map<String, String> otherQueryParameters = new HashMap<String, String>();
        otherQueryParameters.put( "attachmentName", base64BinaryAttachmentName );
        String beforeUpdateDetailFilterXml = FilterBuilder.buildHealthAdapterJournalDetailsFilter( MOOD_JOURNAL_ENTRY_POINT, recordIdentifier, otherQueryParameters );
        Document readDetailsWithBase64 = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID,
                        beforeUpdateDetailFilterXml, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        dataList = readDetailsWithBase64.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        List<Element> base64AttachmentList = readDetailsWithBase64.selectNodes("//base64BinaryAttachment");
        assertTrue( base64AttachmentList.size()==1);
        readDetailsWithBase64=null;


        /// UPDATE 
        String updateRequestXml = createHAUpdateXml( patientIdentity, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier, "updated mood", null );
        Document clinicalDataDocumentUpdate = updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, updateRequestXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID" );
        assertNotNull( clinicalDataDocumentUpdate );
        clinicalDataDocumentUpdate = null;


        /// READ DETAIL after update and without update attachment name ( 2 attachments) 
        String afterUpdateDetailFilterXml = FilterBuilder.buildHealthAdapterJournalDetailsFilter( MOOD_JOURNAL_ENTRY_POINT, recordIdentifier, null );
        Document afterUpdateReadResponseWithoutOtherQueryParameters = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID,
                        afterUpdateDetailFilterXml, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        dataList = afterUpdateReadResponseWithoutOtherQueryParameters.selectNodes( "//patients/patient/patientJournalEntries" );
        List<Node> attachments = afterUpdateReadResponseWithoutOtherQueryParameters.selectNodes( "//binaryAttachment" );
        assertTrue( attachments.size() == 2 ); /// this read should return exactly two attachments since an attachment name is not specified        
        assertTrue( dataList.size() > 0 );

        /// READ DETAIL after update and with update attachment name
        String afterUpdateDetailFilterWithXml = FilterBuilder.buildHealthAdapterJournalDetailsFilter( MOOD_JOURNAL_ENTRY_POINT, recordIdentifier, otherQueryParameters );
        Document afterUpdateReadResponseWithOtherQueryParameters = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID,
                        afterUpdateDetailFilterWithXml, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        dataList = afterUpdateReadResponseWithOtherQueryParameters.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        attachments = afterUpdateReadResponseWithOtherQueryParameters.selectNodes( "//binaryAttachment" );
        assertTrue( attachments.size() == 1 ); /// this read should return exactly one attachment since an attachment name is specified        

        ///DELETE
        // Logically Delete mood journal entry
        String logicalDeleteXml = createHADeleteXml( "PatientEnteredMoodJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, LOGICAL_DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, logicalDeleteXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID", true );
      
//        String physicalDeleteXml = createHADeleteXml( "PatientEnteredMoodJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, DELETE_RECORD_STATUS );
//        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, physicalDeleteXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID", true );

        
    }


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = "deprecatedtest" )
    public void testPatientEnteredMoodJournalEntryCRUD( )
        throws Exception
    {
        /// clear out any mood journal test records 
        hdrJdbcTemplate.update( "delete from mood_journal where patient_identity like '" + MOOD_TEST_PATIENT_PREFIX + "%'" );

        /// leave random patient identity in integration test - remove from functional test
        /// reasoning:  The functional tests use a control xml file to compare against the xml result. 
        /// Thus, the control file will not be identical to an xml request with a random patient identity.
        /// However, in the case of this integration test, we can leave the random patient identity in place
        String patientIdentity = MOOD_TEST_PATIENT_PREFIX + ( ( int )( Math.random() * 10000000 ) );

        /// CREATE
        String createRequestXml = createMHACreateXml( patientIdentity, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, null );
        Document createResponseDocument = createAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, createRequestXml );

        /// get the record identifier returned in the create xml
        Node recordIdentifierNode = createResponseDocument.selectSingleNode( RECORD_IDENTIFIER_IDENTITY_XPATH );
        recordIdentifier = recordIdentifierNode.getText();

        /// READ WITHOUT DATES
        Map<String, String> assigningAuthorityAndFacilityMap = new HashMap<String, String>();
        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( "ID_1", "PatientEnteredMoodJournalEntry" );
        entryPointFilterMap.put( FilterBuilder.QUERY_TIMEOUT_SECONDS, QUERY_TIMOUT_SECONDS_MAX );
        String filterXml = createMHAFilter( patientIdentity, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, "PatientEnteredMoodJournalEntry",
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, null, null );
        Document readResponseWithoutDatesDocument = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        List<Element> dataList = readResponseWithoutDatesDocument.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );

        // READ WITH OFFSET DATES (to ensure that the queries capture a record entered today regardless of one's timezone)
        filterXml = createMHAFilter( patientIdentity, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER,
                        queryStartDateOffset, queryEndDateOffset );
        Document readResponseWithOffsetDatesDocument = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        dataList = readResponseWithOffsetDatesDocument.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );

        /// READ WITH ZULU DATES (add a day and subtract a day to the range to ensure the record is captured regardless of timezone
        filterXml = createMHAFilter( patientIdentity, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER,
                        queryStartDateZulu, queryEndDateZulu );
        Document readResponseWithZuluDatesDocument = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        dataList = readResponseWithZuluDatesDocument.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );

        /// READ WITH REGULAR DATES 
        filterXml = createMHAFilter( patientIdentity, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER,
                        queryStartDateNormal, queryEndDateNormal );
        Document readResponseWithRegularDatesDocument = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        dataList = readResponseWithRegularDatesDocument.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );

        /// UPDATE 
        String updateRequestXml = createHAUpdateXml( patientIdentity, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier, "updated mood", null );
        Document clinicalDataDocumentUpdate = updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, updateRequestXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID" );
        assertNotNull( clinicalDataDocumentUpdate );

        ///DELETE
        // Logically Delete mood journal entry
        String logicalDeleteXml = createHADeleteXml( "PatientEnteredMoodJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, LOGICAL_DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, logicalDeleteXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID", true );

    }


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = "deprecatedtest" )
    public void testMoodJournalDetailsWithDuplicateAttachmentName( )
        throws Exception
    {
        String attachmentName1 = "Image1";
        String attachmentName2 = "Image2";

        /// clear out any mood journal test records 
        hdrJdbcTemplate.update( "delete from mood_journal where patient_identity = '" + uniquePatientIdentity + "'" );

        /// CREATE
        String createRequestXml = createMHACreateXml( uniquePatientIdentity, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, attachmentName1 );
        Document createResponse = createAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, createRequestXml );
        recordIdentifier = createResponse.selectSingleNode( RECORD_IDENTIFIER_IDENTITY_XPATH ).getText();
        createResponse = null;

        /// READ WITHOUT DATES
        Map<String, String> assigningAuthorityAndFacilityMap = new HashMap<String, String>();
        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( "ID_1", "PatientEnteredMoodJournalEntry" );
        entryPointFilterMap.put( FilterBuilder.QUERY_TIMEOUT_SECONDS, QUERY_TIMOUT_SECONDS_MAX );

        /// READ DETAIL before update and with attachment name 
        Map<String, String> otherQueryParameters = new HashMap<String, String>();
        otherQueryParameters.put( "attachmentName", attachmentName1 );
        String filterXml = FilterBuilder.buildHealthAdapterJournalDetailsFilter( MOOD_JOURNAL_ENTRY_POINT, recordIdentifier, otherQueryParameters );
        Document readResponseWithOtherQueryParameters = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        List<Element> dataList = readResponseWithOtherQueryParameters.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        List<Node> attachments = readResponseWithOtherQueryParameters.selectNodes( "//binaryAttachment" );
        assertTrue( attachments.size() == 1 );

        readResponseWithOtherQueryParameters = null;

        /// UPDATE 
        String updateRequestXml = createHAUpdateXml( uniquePatientIdentity, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier, "updated mood",
                        attachmentName1 );
        Document clinicalDataDocumentUpdate = updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, updateRequestXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID" );
        assertNotNull( clinicalDataDocumentUpdate );
        clinicalDataDocumentUpdate = null;

        updateRequestXml = createHAUpdateXml( uniquePatientIdentity, MOOD_JOURNAL_ENTRY_POINT, TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier, "updated mood", attachmentName2 );
        clinicalDataDocumentUpdate = updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, updateRequestXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID" );
        assertNotNull( clinicalDataDocumentUpdate );
        clinicalDataDocumentUpdate = null;

        /// READ DETAIL after update and without update attachment name ( duplicate attachments) 
        Document afterUpdateReadResponseWithoutOtherQueryParameters = readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID,
                        filterXml, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER, READ_TEST_DOMAINENTRYPOINT_XPATH, 1 );
        dataList = afterUpdateReadResponseWithoutOtherQueryParameters.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        attachments = afterUpdateReadResponseWithoutOtherQueryParameters.selectNodes( "//binaryAttachment" );
        assertTrue( attachments.size() == 2 ); /// this read should return exactly two attachments since an attachment name is not specified        

        ///DELETE
        // Logically Delete mood journal entry
        String logicalDeleteXml = createHADeleteXml( "PatientEnteredMoodJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, LOGICAL_DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, logicalDeleteXml, "MOOD_JOURNAL", "MOOD_JOURNAL_ID", true );
    }


    protected String createHADeleteXml( String entryPoint, String templateId, String recordIdentifierIdentity, String recordStatus )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.PatientEnteredMoodJournalEntry );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientEnteredMoodJournalEntryBuilderFactory factory = new HAPatientEnteredMoodJournalEntryBuilderFactory();
        factory.setMoodJournalBuilder( new HAMoodJournalBuilder() );

        domainEntryPointsWrappersMap.put( "PatientEnteredMoodJournalEntry", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "identifier", "200DOD", "USDOD" );
        Document clinicalDataDeleteDocument = clinicalDataBuilder.deleteClinicalData( domainEntryPointsMap.get( templateId ), templateId, patient, recordIdentifierIdentity, recordStatus );

        return clinicalDataDeleteDocument.asXML();
    }


    private String createHAUpdateXml( String patientIdentifier, String entryPoint, String templateId, String recordIdentifier, String updatedMood, String attachmentName )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.PatientEnteredMoodJournalEntry );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientEnteredMoodJournalEntryBuilderFactory factory = new HAPatientEnteredMoodJournalEntryBuilderFactory();
        factory.setMoodJournalBuilder( new HAMoodJournalBuilder( recordIdentifier, updatedMood, attachmentName ) );
        domainEntryPointsWrappersMap.put( MOOD_JOURNAL_ENTRY_POINT, factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = null;
        if ( patientIdentifier == null )
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest" );
        }
        else
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "identifier", patientIdentifier );
        }

        Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( templateId, 1, patient );

        return vdmClinicalDataInsert.asXML();
    }


    protected String createMHACreateXml( String patientIdentifier, String entryPoint, String templateId, String attachementName )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.PatientEnteredMoodJournalEntry );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientEnteredMoodJournalEntryBuilderFactory factory = new HAPatientEnteredMoodJournalEntryBuilderFactory();
        factory.setMoodJournalBuilder( new HAMoodJournalBuilder( attachementName ) );
        domainEntryPointsWrappersMap.put( "PatientEnteredMoodJournalEntry", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = null;
        if ( patientIdentifier == null )
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest" );
        }
        else
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest", patientIdentifier );
        }

        Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( templateId, 1, patient );

        try
        {
            initializeQueryDates( vdmClinicalDataInsert );
        }
        catch ( ParseException e )
        {
            e.printStackTrace();
        }

        return vdmClinicalDataInsert.asXML();
    }


    protected String createMHAUpdateXml( String patientIdentifier, String entryPoint, String templateId )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.PatientEnteredMoodJournalEntry );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientEnteredMoodJournalEntryBuilderFactory factory = new HAPatientEnteredMoodJournalEntryBuilderFactory();
        factory.setMoodJournalBuilder( new HAMoodJournalBuilder() );
        domainEntryPointsWrappersMap.put( "PatientEnteredMoodJournalEntry", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = null;
        if ( patientIdentifier == null )
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest" );
        }
        else
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest", patientIdentifier );
        }

        Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( templateId, 1, patient );

        try
        {
            initializeQueryDates( vdmClinicalDataInsert );
        }
        catch ( ParseException e )
        {
            e.printStackTrace();
        }

        return vdmClinicalDataInsert.asXML();
    }


    protected void initializeQueryDates( Document vdmClinicalDataInsert )
        throws ParseException
    {
        observationDateString = vdmClinicalDataInsert.selectSingleNode( OBSERVATION_DATE_XPATH ).getText();
        queryStartDateOffset = observationDateString.substring( 0, 4 ) + "-" + observationDateString.substring( 4, 6 ) + "-" + observationDateString.substring( 6, 8 )
                        + observationDateString.substring( 14, 17 ) + ":" + observationDateString.substring( 17 );
        queryEndDateOffset = queryStartDateOffset;

        Calendar zuluStartCalendar = javax.xml.bind.DatatypeConverter.parseDate( queryStartDateOffset );
        queryStartDateNormal = new SimpleDateFormat( "yyyy-MM-dd" ).format( zuluStartCalendar.getTime() );
        zuluStartCalendar.add( Calendar.DATE, -1 );
        queryStartDateZulu = new SimpleDateFormat( "yyyy-MM-dd" ).format( zuluStartCalendar.getTime() ) + "Z";

        Calendar zuluEndCalendar = javax.xml.bind.DatatypeConverter.parseDate( queryEndDateOffset );
        queryEndDateNormal = new SimpleDateFormat( "yyyy-MM-dd" ).format( zuluEndCalendar.getTime() );
        zuluEndCalendar.add( Calendar.DATE, 1 );
        queryEndDateZulu = new SimpleDateFormat( "yyyy-MM-dd" ).format( zuluEndCalendar.getTime() ) + "Z";

    }


    protected String createMHAFilter( String patientIdentifier, String assigningAuthority, String assigningFacility, String entryPoint, String filterId, String startDate, String endDate )
    {
        Document filterDocument = FilterBuilder.buildEmptyFilterDocument();
        Element element = filterDocument.getRootElement();
        element.add( FilterBuilder.createFilterId( "filterId", filterId ) );
        element.add( FilterBuilder.createClientName( "clientName", "testClientName" ) );
        element.add( FilterBuilder.createClientRequestInitiationTime( "clientRequestInitiationTime", DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) ) );
        element.add( FilterBuilder.createPatientWithEdipi( "patients", patientIdentifier, null, assigningAuthority, assigningFacility ) );
        element.add( FilterBuilder.createMHAEntryFilterWithAdditionalParameters( "entryPointFilter", entryPoint, startDate, endDate, "ID_1" ) );
        element.addAttribute( "vhimVersion", "Vhim_4_00" );
        return element.asXML();
    }


    @After
    public void deleteTestRecord( )
    {
        //hdrJdbcTemplate.update( "delete from mood_journal where patient_identity like '" + MOOD_TEST_PATIENT_PREFIX + "%'" );
    }

}
