

package gov.va.med.cds.xml.schema;


import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;

import javax.sql.rowset.serial.SerialException;


@RunWith( SuiteAwareRunner.class )
public class SchemaHelperTest
{
    private static Resource[] jarResources = null;
    private static PathMatchingResourcePatternResolver pathResolver = new PathMatchingResourcePatternResolver();
    public static final String TEMPLATE_JAR_PATH_PATTERN = "file:templatecache/**/*.jar";
    public static byte[] byteArrayJar = null;


    @BeforeClass
    @Suite( groups = { "checkintest" }, order = 1 )
    public static void setUp( )
        throws IOException
    {
        jarResources = pathResolver.getResources( TEMPLATE_JAR_PATH_PATTERN );
        Resource jarResource = jarResources[0];
        byteArrayJar = getBytesFromFile( jarResource.getFile() );
        assertNotNull( byteArrayJar );
    }


    /**
     * This test excercises schema loading from a jar file.
     *
     * @throws IOException
     */
    @Test( expected = SchemaException.class )
    @Suite( groups = { "checkintest" }, order = 2 )
    public void testLoadSchemaFailure( )
        throws IOException
    {
        new SchemaHelper( null, null );
    }


    /**
     * This test excercises schema loading from a jar file.
     *
     * @throws IOException
     * @throws Exception 
     * @throws SerialException 
     */
    @Test( expected = SchemaException.class )
    @Suite( groups = { "checkintest" }, order = 3 )
    public void testLoadInvalidSchemaJar( )
        throws Exception
    {
        byte[] bytes = { 0, 1 };
        Blob blobJar = new javax.sql.rowset.serial.SerialBlob( bytes );
        new SchemaHelper( blobJar, null );
    }


    /**
     * This test excercises schema loading from a jar file.
     *
     * @throws IOException
     */
    @Test
    @Suite( groups = { "checkintest" }, order = 4 )
    public void testLoadSchemaFromJar( )
        throws Exception
    {
        Blob blobJar = new javax.sql.rowset.serial.SerialBlob( byteArrayJar );
        SchemaHelperInterface schemaHelper = new SchemaHelper( blobJar, "testSchema" );
        assertNotNull( schemaHelper );
        assertTrue( schemaHelper.toString().contains( "testSchema" ) );
        assertNotNull( schemaHelper.getSymbolMap() );
        assertNotNull( schemaHelper.getValidator() );
    }


    @Test( expected = SchemaException.class )
    @Suite( groups = { "checkintest" }, order = 5 )
    public void testSchemaHelperWithGroups( )
        throws Exception
    {
        jarResources = pathResolver.getResources( "classpath:gov/va/med/cds/xml/schema/SchemaWithGroupDefinitions.jar" );
        Resource jarResource = jarResources[0];
        byteArrayJar = getBytesFromFile( jarResource.getFile() );
        assertNotNull( byteArrayJar );

        Blob blobJar = new javax.sql.rowset.serial.SerialBlob( byteArrayJar );
        new SchemaHelper( blobJar, "testSchema" );
    }


    @Test( expected = SchemaException.class )
    @Suite( groups = { "checkintest" }, order = 6 )
    public void testSchemaHelperWithErrors( )
        throws Exception
    {
        jarResources = pathResolver.getResources( "classpath:gov/va/med/cds/xml/schema/AllergiesRead40010WithError.jar" );
        Resource jarResource = jarResources[0];
        byteArrayJar = getBytesFromFile( jarResource.getFile() );
        assertNotNull( byteArrayJar );

        Blob blobJar = new javax.sql.rowset.serial.SerialBlob( byteArrayJar );
        new SchemaHelper( blobJar, "testSchema" );
    }


    @Test( expected = SchemaException.class )
    @Suite( groups = { "checkintest" }, order = 7 )
    public void testSchemaHelperWithFatalErrors( )
        throws Exception
    {
        jarResources = pathResolver.getResources( "classpath:gov/va/med/cds/xml/schema/AllergiesRead40010WithFatalError.jar" );
        Resource jarResource = jarResources[0];
        byteArrayJar = getBytesFromFile( jarResource.getFile() );
        assertNotNull( byteArrayJar );

        Blob blobJar = new javax.sql.rowset.serial.SerialBlob( byteArrayJar );
        new SchemaHelper( blobJar, "testSchema" );
    }


    /**
     * Returns the contents of the file in a byte array
     * @param file File this method should read
     * @return byte[] Returns a byte[] array of the contents of the file
     */
    private static byte[] getBytesFromFile( File file )
        throws IOException
    {

        InputStream is = new FileInputStream( file );

        // Get the size of the file
        long length = file.length();

        /*
         * You cannot create an array using a long type. It needs to be an int
         * type. Before converting to an int type, check to ensure that file is
         * not loarger than Integer.MAX_VALUE;
         */
        if ( length > Integer.MAX_VALUE )
        {
            System.out.println( "File is too large to process" );
            return null;
        }

        // Create the byte array to hold the data
        byte[] bytes = new byte[( int )length];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while ( ( offset < bytes.length ) && ( ( numRead = is.read( bytes, offset, bytes.length - offset ) ) >= 0 ) )
        {

            offset += numRead;

        }

        // Ensure all the bytes have been read in
        if ( offset < bytes.length )
        {
            throw new IOException( "Could not completely read file " + file.getName() );
        }

        is.close();
        return bytes;

    }

}
