

package gov.va.med.cds.audit.persistence.hibernate;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import gov.va.med.cds.audit.AbstractAuditLog;
import gov.va.med.cds.audit.ClientMapping;
import gov.va.med.cds.audit.ClientMappingPathways;
import gov.va.med.cds.audit.LegacyReadAuditLog;
import gov.va.med.cds.audit.VhimReadPathwaysResponseAuditLog;
import gov.va.med.cds.audit.VhimReadResponseAuditLog;
import gov.va.med.cds.audit.persistence.AuditLogPersistenceManagerInterface;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import gov.va.med.cds.properties.PropertiesUtil;
import gov.va.med.cds.util.StreamUtil;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.orm.hibernate4.HibernateTemplate;

import java.io.IOException;
import java.util.Date;


@RunWith( SuiteAwareRunner.class )
public class HibernateAuditLogPersistenceManagerTest
{

    private AuditLogPersistenceManagerInterface auditLogPersistenceManager;
    private AuditLogPersistenceManagerInterface auditLogPersistenceManagerPathways;
    private AuditLogPersistenceManagerInterface auditLogPersistenceManagerHa;

    private HibernateTemplate hibernateTemplate;
    private HibernateTemplate hibernateTemplatePathways;
    private HibernateTemplate hibernateTemplateHa;


    public HibernateAuditLogPersistenceManagerTest( )
    {
        // load up the system properties.
        try
        {
            new PropertiesUtil().loadSystemRunProperties();
        }
        catch ( IOException ioe )
        {
            fail( ioe.getMessage() );
        }

        // load up the application context and set the members because we can't
        // use the test harness Abstract test classes because of a circular
        // dependency issue
        ConfigurableApplicationContext appCtxt = new ClassPathXmlApplicationContext(
                        new String[] { "gov/va/med/cds/audit/persistence/hibernate/hibernateAuditLogPersistenceManagerTestContext.xml" } );
        appCtxt.getBeanFactory().autowireBeanProperties( this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true );
    }


    @Test
    @Suite( groups = "brokentest" )
    public void testStoreAuditLog( )
        throws Exception
    {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource = null;

        resource = resourceLoader.getResource( "classpath:gov/va/med/cds/audit/persistence/hibernate/Good_Read_Results.xml" );

        String goodReadResults = StreamUtil.resourceToString( resource );

        resource = resourceLoader.getResource( "classpath:gov/va/med/cds/audit/persistence/hibernate/Valid_Read_Filter.xml" );

        String validReadFilter = StreamUtil.resourceToString( resource );

        AbstractAuditLog auditLog = new VhimReadResponseAuditLog();

        ClientMapping clientMapping;

        auditLog.setEndTime( 12345L );
        auditLog.setFacility( "FACILITY" );
        auditLog.setLocalTime( new Date( 55555L ) );
        auditLog.setIsoLocalTime( "20081021125959.999-600" );
        auditLog.setTemplateId( "TestRead40010" );
        auditLog.setFilterRequest( validReadFilter );
        auditLog.setFilterId( "TEST_FILTER" );
        auditLog.setRequestId( "55667788" );
        auditLog.setResponse( goodReadResults );
        auditLog.setSendingApplication( "SENDING_APPLICATION" );
        auditLog.setStartTime( 12335L );
        auditLog.setClientId( "A CLIENT ID" );
        auditLog.setClientRequestInitiationTime( "2001-12-17T09:30:47.0Z" );
        assertNotNull( auditLog.getClientMapping() );

        // persist the audit log record
        auditLogPersistenceManager.storeAuditLog( auditLog );

        try
        {
            // read it back in
            VhimReadResponseAuditLog auditLogPersisted = ( VhimReadResponseAuditLog )hibernateTemplate.get( VhimReadResponseAuditLog.class,
                            auditLog.getAuditLogId() );

            // validate that the values are the same.
            assertEquals( auditLog.getAuditLogId().longValue(), auditLogPersisted.getAuditLogId().longValue() );
            assertEquals( auditLog.getEndTime(), auditLogPersisted.getEndTime() );
            assertEquals( auditLog.getFacility(), auditLogPersisted.getFacility() );
            assertEquals( auditLog.getIsoLocalTime(), auditLogPersisted.getIsoLocalTime() );
            assertEquals( auditLog.getMilliseconds(), auditLogPersisted.getMilliseconds() );
            assertEquals( auditLog.getTemplateId(), auditLogPersisted.getTemplateId() );
            assertEquals( auditLog.getFilterRequest(), auditLogPersisted.getFilterRequest() );
            assertEquals( auditLog.getFilterId(), auditLogPersisted.getFilterId() );
            assertEquals( auditLog.getRequestId(), auditLogPersisted.getRequestId() );
            assertEquals( null, auditLogPersisted.getResponse() );
            assertEquals( auditLog.getSendingApplication(), auditLogPersisted.getSendingApplication() );
            assertEquals( auditLog.getStartTime(), auditLogPersisted.getStartTime() );
            assertNotNull( auditLogPersisted.getClientMapping() );
            assertEquals( auditLog.getClientMapping().getFilterId(), auditLogPersisted.getClientMapping().getFilterId() );
            assertEquals( auditLog.getClientMapping().getTemplateId(), auditLogPersisted.getClientMapping().getTemplateId() );
            assertEquals( auditLog.getClientId(), auditLogPersisted.getClientId() );
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
        finally
        {
            // remove the audit log record.
            hibernateTemplate.delete( auditLog );
        }
    }


    @Test
    @Suite( groups = "brokentest" )
    public void testStoreLegacyReadAuditLog( )
    {

        AbstractAuditLog auditLog = new LegacyReadAuditLog();
        ClientMapping clientMapping;

        auditLog.setEndTime( 12345L );
        auditLog.setFacility( "FACILITY" );
        auditLog.setLocalTime( new Date( 55555L ) );
        auditLog.setIsoLocalTime( "20081021125959.999-600" );
        auditLog.setTemplateId( "TestRead40010_L" );
        auditLog.setFilterRequest( "REQUEST" );
        auditLog.setFilterId( "TEST_FILTER_L" );
        auditLog.setRequestId( "55667788" );
        auditLog.setResponse( "RESPONSE1\rRESPONSE2\rRESPONSE3" );
        auditLog.setSendingApplication( "SENDING_APPLICATION" );
        auditLog.setStartTime( 12335L );
        clientMapping = new ClientMapping( auditLog.getFilterId(), auditLog.getTemplateId() );
        auditLog.setClientMapping( clientMapping );
        auditLog.setClientId( "A CLIENT ID2" );
        auditLog.setClientRequestInitiationTime( "2001-12-17T09:30:47.0Z" );

        // persist the audit log record
        auditLogPersistenceManager.storeAuditLog( auditLog );

        try
        {
            // read it back in
            LegacyReadAuditLog auditLogPersisted = ( LegacyReadAuditLog )hibernateTemplate.get( LegacyReadAuditLog.class, auditLog.getAuditLogId() );

            // validate that the values are the same.
            assertEquals( auditLog.getAuditLogId().longValue(), auditLogPersisted.getAuditLogId().longValue() );
            assertEquals( auditLog.getEndTime(), auditLogPersisted.getEndTime() );
            assertEquals( auditLog.getFacility(), auditLogPersisted.getFacility() );
            assertEquals( auditLog.getIsoLocalTime(), auditLogPersisted.getIsoLocalTime() );
            assertEquals( auditLog.getMilliseconds(), auditLogPersisted.getMilliseconds() );
            assertEquals( auditLog.getTemplateId(), auditLogPersisted.getTemplateId() );
            assertEquals( auditLog.getFilterRequest(), auditLogPersisted.getFilterRequest() );
            assertEquals( auditLog.getFilterId(), auditLogPersisted.getFilterId() );
            assertEquals( auditLog.getRequestId(), auditLogPersisted.getRequestId() );
            assertEquals( null, auditLogPersisted.getResponse() );
            assertEquals( auditLog.getSendingApplication(), auditLogPersisted.getSendingApplication() );
            assertEquals( auditLog.getStartTime(), auditLogPersisted.getStartTime() );

        }
        finally
        {
            // remove the audit log record.
            hibernateTemplate.delete( auditLog );
        }
    }


    @Test
    @Suite( groups = "brokentest" )
    public void testStoreVhimReadPathwaysResponseAuditLog( )
        throws Exception
    {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource = null;

        resource = resourceLoader.getResource( "classpath:gov/va/med/cds/audit/persistence/hibernate/Good_Read_Results.xml" );
        String goodReadResults = StreamUtil.resourceToString( resource );

        VhimReadPathwaysResponseAuditLog auditLog = new VhimReadPathwaysResponseAuditLog();

        ClientMappingPathways clientMapping;

        auditLog.setEndTime( 12345L );
        auditLog.setFacility( "FACILITY" );
        auditLog.setLocalTime( new Date( 55555L ) );
        auditLog.setIsoLocalTime( "20081021125959.999-600" );
        auditLog.setTemplateId( "PathwaysTestRead1" );
        auditLog.setFilterRequest( "REQUEST" );
        auditLog.setFilterId( "PATHWAYS_FILTER" );
        auditLog.setRequestId( "55667789" );
        auditLog.setResponse( goodReadResults );
        auditLog.setSendingApplication( "SENDING_APPLICATION" );
        auditLog.setStartTime( 12335L );
        clientMapping = new ClientMappingPathways( auditLog.getFilterId(), auditLog.getTemplateId() );
        auditLog.setClientMappingPathways( clientMapping );
        auditLog.setClientId( "PATHWAYS CLIENT ID2" );
        auditLog.setClientRequestInitiationTime( "2001-12-17T09:30:47.0Z" );

        // persist the audit log record
        auditLogPersistenceManagerPathways.storeAuditLog( auditLog );

        try
        {
            // read it back in
            VhimReadPathwaysResponseAuditLog auditLogPersisted = ( VhimReadPathwaysResponseAuditLog )hibernateTemplatePathways.get(
                            VhimReadPathwaysResponseAuditLog.class, auditLog.getAuditLogId() );

            // validate that the values are the same.
            assertEquals( auditLog.getAuditLogId().longValue(), auditLogPersisted.getAuditLogId().longValue() );
            assertEquals( auditLog.getEndTime(), auditLogPersisted.getEndTime() );
            assertEquals( auditLog.getFacility(), auditLogPersisted.getFacility() );
            assertEquals( auditLog.getIsoLocalTime(), auditLogPersisted.getIsoLocalTime() );
            assertEquals( auditLog.getMilliseconds(), auditLogPersisted.getMilliseconds() );
            assertEquals( auditLog.getTemplateId(), auditLogPersisted.getTemplateId() );
            assertEquals( auditLog.getFilterRequest(), auditLogPersisted.getFilterRequest() );
            assertEquals( auditLog.getFilterId(), auditLogPersisted.getFilterId() );
            assertEquals( auditLog.getRequestId(), auditLogPersisted.getRequestId() );
            assertEquals( null, auditLogPersisted.getResponse() );
            assertNotNull( auditLogPersisted.getClientMappingPathways() );
            assertEquals( auditLog.getSendingApplication(), auditLogPersisted.getSendingApplication() );
            assertEquals( auditLog.getStartTime(), auditLogPersisted.getStartTime() );

        }
        finally
        {
            // remove the audit log record.
            hibernateTemplatePathways.delete( auditLog );
        }
    }


    @Test
    @Suite( groups = "brokentest" )
    public void testStoreHaAuditLog( )
        throws Exception
    {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource = null;

        resource = resourceLoader.getResource( "classpath:gov/va/med/cds/audit/persistence/hibernate/Good_Read_Results.xml" );
        String goodReadResults = StreamUtil.resourceToString( resource );

        AbstractAuditLog auditLog = new VhimReadResponseAuditLog();
        ClientMapping clientMapping;

        auditLog.setEndTime( 12345L );
        auditLog.setFacility( "FACILITY" );
        auditLog.setLocalTime( new Date( 55555L ) );
        auditLog.setIsoLocalTime( "20081021125959.999-600" );
        auditLog.setTemplateId( "HealthAdapterRead1" );
        auditLog.setFilterRequest( "REQUEST" );
        auditLog.setFilterId( "HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER" );
        auditLog.setRequestId( "55667788" );
        auditLog.setResponse( goodReadResults );
        auditLog.setSendingApplication( "SENDING_APPLICATION" );
        auditLog.setStartTime( 12335L );
        auditLog.setClientId( "HA" );
        auditLog.setClientRequestInitiationTime( "2001-12-17T09:30:47.0Z" );
        assertNotNull( auditLog.getClientMapping() );

        // persist the audit log record
        auditLogPersistenceManagerHa.storeAuditLog( auditLog );

        try
        {
            // read it back in
            VhimReadResponseAuditLog auditLogPersisted = ( VhimReadResponseAuditLog )hibernateTemplateHa.get( VhimReadResponseAuditLog.class,
                            auditLog.getAuditLogId() );

            // validate that the values are the same.
            assertEquals( auditLog.getAuditLogId().longValue(), auditLogPersisted.getAuditLogId().longValue() );
            assertEquals( auditLog.getEndTime(), auditLogPersisted.getEndTime() );
            assertEquals( auditLog.getFacility(), auditLogPersisted.getFacility() );
            assertEquals( auditLog.getIsoLocalTime(), auditLogPersisted.getIsoLocalTime() );
            assertEquals( auditLog.getMilliseconds(), auditLogPersisted.getMilliseconds() );
            assertEquals( auditLog.getTemplateId(), auditLogPersisted.getTemplateId() );
            assertEquals( auditLog.getFilterRequest(), auditLogPersisted.getFilterRequest() );
            assertEquals( auditLog.getFilterId(), auditLogPersisted.getFilterId() );
            assertEquals( auditLog.getRequestId(), auditLogPersisted.getRequestId() );
            assertEquals( null, auditLogPersisted.getResponse() );
            assertEquals( auditLog.getSendingApplication(), auditLogPersisted.getSendingApplication() );
            assertEquals( auditLog.getStartTime(), auditLogPersisted.getStartTime() );
            assertNotNull( auditLogPersisted.getClientMapping() );
            assertEquals( auditLog.getClientMapping().getFilterId(), auditLogPersisted.getClientMapping().getFilterId() );
            assertEquals( auditLog.getClientMapping().getTemplateId(), auditLogPersisted.getClientMapping().getTemplateId() );
            assertEquals( auditLog.getClientId(), auditLogPersisted.getClientId() );
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
        finally
        {
            // remove the audit log record.
            hibernateTemplateHa.delete( auditLog );
        }
    }


    @Test
    @Suite( groups = "brokentest" )
    public void testStoreLegacyAuditLog( )
    {
        AbstractAuditLog auditLog = new LegacyReadAuditLog();
        ClientMapping clientMapping;

        auditLog.setEndTime( 12345L );
        auditLog.setFacility( "FACILITY" );
        auditLog.setLocalTime( new Date( 55555L ) );
        auditLog.setIsoLocalTime( "20081021125959.999-600" );
        auditLog.setTemplateId( "TestRead40010_L" );
        auditLog.setFilterRequest( "REQUEST" );
        auditLog.setFilterId( "TEST_FILTER_L" );
        auditLog.setRequestId( "55667788" );
        auditLog.setResponse( "RESPONSE1\rRESPONSE2\rRESPONSE3" );
        auditLog.setSendingApplication( "SENDING_APPLICATION" );
        auditLog.setStartTime( 12335L );
        clientMapping = new ClientMapping( auditLog.getFilterId(), auditLog.getTemplateId() );
        auditLog.setClientMapping( clientMapping );
        auditLog.setClientId( "A CLIENT ID2" );
        auditLog.setClientRequestInitiationTime( "2001-12-17T09:30:47.0Z" );

        // persist the audit log record
        auditLogPersistenceManager.storeAuditLog( auditLog );

        try
        {
            // read it back in
            LegacyReadAuditLog auditLogPersisted = ( LegacyReadAuditLog )hibernateTemplate.get( LegacyReadAuditLog.class, auditLog.getAuditLogId() );

            // validate that the values are the same.
            assertEquals( auditLog.getAuditLogId().longValue(), auditLogPersisted.getAuditLogId().longValue() );
            assertEquals( auditLog.getEndTime(), auditLogPersisted.getEndTime() );
            assertEquals( auditLog.getFacility(), auditLogPersisted.getFacility() );
            assertEquals( auditLog.getIsoLocalTime(), auditLogPersisted.getIsoLocalTime() );
            assertEquals( auditLog.getMilliseconds(), auditLogPersisted.getMilliseconds() );
            assertEquals( auditLog.getTemplateId(), auditLogPersisted.getTemplateId() );
            assertEquals( auditLog.getFilterRequest(), auditLogPersisted.getFilterRequest() );
            assertEquals( auditLog.getFilterId(), auditLogPersisted.getFilterId() );
            assertEquals( auditLog.getRequestId(), auditLogPersisted.getRequestId() );
            assertEquals( null, auditLogPersisted.getResponse() );
            assertEquals( auditLog.getSendingApplication(), auditLogPersisted.getSendingApplication() );
            assertEquals( auditLog.getStartTime(), auditLogPersisted.getStartTime() );

        }
        finally
        {
            // remove the audit log record.
            hibernateTemplate.delete( auditLog );
        }
    }


    public void setAuditLogPersistenceManager( AuditLogPersistenceManagerInterface auditLogPersistenceManager )
    {
        this.auditLogPersistenceManager = auditLogPersistenceManager;
    }


    public void setHibernateTemplate( HibernateTemplate hibernateTemplate )
    {
        this.hibernateTemplate = hibernateTemplate;
    }


    public void setHibernateTemplatePathways( HibernateTemplate hibernateTemplatePathways )
    {
        this.hibernateTemplatePathways = hibernateTemplatePathways;
    }


    public void setAuditLogPersistenceManagerPathways( AuditLogPersistenceManagerInterface auditLogPersistenceManagerPathways )
    {
        this.auditLogPersistenceManagerPathways = auditLogPersistenceManagerPathways;
    }


    public HibernateTemplate getHibernateTemplateHa( )
    {
        return hibernateTemplateHa;
    }


    public void setHibernateTemplateHa( HibernateTemplate hibernateTemplateHa )
    {
        this.hibernateTemplateHa = hibernateTemplateHa;
    }


    public AuditLogPersistenceManagerInterface getAuditLogPersistenceManagerHa( )
    {
        return auditLogPersistenceManagerHa;
    }


    public void setAuditLogPersistenceManagerHa( AuditLogPersistenceManagerInterface auditLogPersistenceManagerHa )
    {
        this.auditLogPersistenceManagerHa = auditLogPersistenceManagerHa;
    }
}
