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

import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;

import java.util.Collection;
import java.util.Map;

import gov.va.med.cds.persistence.hibernate.common.PointInTimeUserType;
import gov.va.med.cds.persistence.hibernate.common.PointInTime;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.type.Type;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import weblogic.application.internal.flow.CreateModulesFlow;

public class OptionalParameterQueryParameterBinderTest
{

    @Before
    public void setUp( )
        throws Exception
    {
    }


    @After
    public void tearDown( )
        throws Exception
    {
    }


    @Test
    public void testBindQueryParameters( )
    {
        // create the mock objects to be used by the test
        Query query = createMock( Query.class );
        Map<String, Object> queryParametersMap = createMock( Map.class );
        Collection<String> collection = createMock( Collection.class ); 
        Map<String, Object> map = createMock( Map.class );
        
        // set the expectations for the mock objects
        expect(query.getNamedParameters()).andReturn( new String[]{"param1", "param2", "param3", "_optional_param4", "_optional_null_param4", "_optional_param5", "param_pointInTime"} );
        
        // set a normal parameter
        expect(queryParametersMap.containsKey( "param1" )).andReturn( true );
        expect(queryParametersMap.get( "param1" )).andReturn( "param1-value" );
        expect(query.setParameter( "param1", "param1-value" )).andReturn( query );
        
        // set a list parameter
        expect(queryParametersMap.containsKey( "param2" )).andReturn( true );
        expect(queryParametersMap.get( "param2" )).andReturn( collection );
        expect(query.setParameterList( "param2", collection )).andReturn( query );
        
        // set a map parameter
        expect(queryParametersMap.containsKey( "param3" )).andReturn( true );
        expect(queryParametersMap.get( "param3" )).andReturn( map );
        expect(query.getNamedParameters()).andReturn( new String[]{"map_param1", "map_param2"} );
        
        expect(map.containsKey( "map_param1" )).andReturn( true );
        expect(map.get( "map_param1" )).andReturn( "map_param1-value" );
        expect(query.setParameter( "map_param1", "map_param1-value" )).andReturn( query );
        expect(map.containsKey( "map_param2" )).andReturn( true );
        expect(map.get( "map_param2" )).andReturn( "map_param2-value" );
        expect(query.setParameter( "map_param2", "map_param2-value" )).andReturn( query );
        
        // optional parameter
        expect(queryParametersMap.containsKey( "param4" )).andReturn( true );
        expect(queryParametersMap.get( "param4" )).andReturn( "param4-value" ).times(2);
        expect(query.setParameter( "_optional_param4", "param4-value" )).andReturn( query );
        
        expect(queryParametersMap.containsKey( "null_param4" )).andReturn( false );
        expect(query.setParameter( "_optional_null_param4", 1 )).andReturn( query );
        
        expect(queryParametersMap.containsKey( "param5" )).andReturn( false );
        expect(query.setParameter( "_optional_param5", null, org.hibernate.type.StandardBasicTypes.STRING )).andReturn( query );
        
        // point in time parameter
        expect(queryParametersMap.containsKey( "param_pointInTime" )).andReturn( true );
        expect(queryParametersMap.get( "param_pointInTime" )).andReturn( new PointInTime() );
        expect(query.setParameter(eq("param_pointInTime"), anyObject( PointInTime.class ), anyObject(Type.class) )).andReturn( query );
       
        
        // prepare the mocks for the test
        replay(query, queryParametersMap, collection, map);
        
        QueryParameterBinderInterface binder = new OptionalParameterQueryParameterBinder();
        binder.bindQueryParameters( query, queryParametersMap, PointInTimeUserType.class );
        
        // verify the results
        verify(query, queryParametersMap, collection, map);
        
    }

}
