package com.ibm.emb.test;

import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;
import javax.emb.MediaException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import com.ibm.emb.junit.EMBStaticHelper;
import com.ibm.emb.junit.EMBTestCaseBase;
import com.ibm.emb.meb.test.ejb.MetaDataEntityLocalTestDriver;
import com.ibm.emb.meb.test.ejb.MetaDataEntityLocalTestDriverHome;

/**
 * <pre>
 *
 *
 *
 *    Line Item: MEB API
 *    Subcategory 1: javax.emb
 *    Subcategory 2: MetaDataEntityLocalHome
 *
 *
 *
 * </pre>
 */

public class MetaDataEntityLocalHomeTest extends EMBTestCaseBase {

    /**
     * Constructor for MetaDataEntityLocalHomeTest.
     * @param name
     */
    public MetaDataEntityLocalHomeTest(String name) throws MediaException {
        super(name);
    }

    private static String MDEBTESTER_JNDI = "java:comp/env/ejb/MetaDataEntityLocalTestDriverHome";

    private static String TXUSER_JNDI = "jta/usertransaction";

    private InitialContext ic;

    private MetaDataEntityLocalTestDriverHome mdebHome;

    private MetaDataEntityLocalTestDriver mdebTester = null;

    /**
     * do initialisation of each individual Test method here this method is
     * called before each individual Test Method
     */
    protected void setUp() throws RemoteException, CreateException {
        if (mdebHome == null) {
            try {
                ic = new InitialContext();
                Object ojb = ic.lookup(MDEBTESTER_JNDI);
                mdebHome = (MetaDataEntityLocalTestDriverHome) PortableRemoteObject.narrow(ojb,
                        MetaDataEntityLocalTestDriverHome.class);
            } catch (NamingException ne) {
                System.out.println("NamingException thrown during setup. Msg: " + ne.getMessage());
            }
        }
        mdebTester = mdebHome.create();
        return;
    }

    /**
     * <pre>
     *
     *
     *
     *    Testcase Name: create()
     *    Testcase Number: EMB165
     *
     *    setup: create testInstance of MetaDataEntityLocalHome
     *
     *    test procedure:
     *    1.call testInstance.create()
     *      expected result: new meta data entity created
     *    		       		  verify result is not null
     *
     *
     *
     * </pre>
     */
    public void testEMB165() throws MediaException, CreateException, RemoteException, NamingException, FinderException,
            RemoveException {
        //
        // test 1
        //
        String md = mdebTester.createMetaDataEntityBean();
        assertNotNull("test 1: meta data entity is null", md);
        testTrace("test 1 passed");

        mdebTester.removeMDEBByPK(md);
        succeed();
    }

    /**
     * Testcase Name: findByPrimaryKey(String) Testcase Number: EMB166 setup:
     * create testInstance of MetaDataEntityLocalHome test procedure: 1.call
     * findByPrimaryKey(null) expected result: NullPointerException 2.call
     * create for new meta data entity md1 and get primary key of md1 call
     * testInstance.findByPrimaryKey and pass in primary key of md1 expected
     * result: md1 3.call findByPrimaryKey with random string expected result:
     * javax.ejb.FinderException
     *
     * </pre>
     */
    public void testEMB166() throws EJBException, MediaException, CreateException, RemoteException, NamingException,
            FinderException, RemoveException {

        int exception = -1;
        //
        // test 1
        //

        // TODO : EMB 166 : JOnAS finbyprimarykey(null) not throw a NPE
        try {
            exception = mdebTester.findByPKExceptions(null);
        } catch (Throwable e) {
            fail("test 1 threw " + e.toString());
        }
        // assertEquals("test 1: Should throw a NullPointerException",
        // MetaDataEntityLocalTestDriver.NULLPOINTER,
        // exception);
        testTrace("test 1 passed");
        //
        // test 2
        //
        String testInstance = mdebTester.createMetaDataEntityBean();
        assertEquals("test 2: wrong meta data entity found", testInstance, mdebTester
                .findMDEBByPrimaryKey(testInstance));
        testTrace("test 2 passed");
        //
        // test 3
        //
        try {
            exception = mdebTester.findByPKExceptions(EMBStaticHelper.createRandomString(EMBStaticHelper.randomInt(0,
                    20)));
        } catch (Throwable e) {
            fail("test 3 threw " + e.toString());
        }
        assertEquals("test 3: Should throw a FinderException", MetaDataEntityLocalTestDriver.FINDER, exception);
        testTrace("test 3 passed");

        mdebTester.removeMDEBByPK(testInstance);
        succeed();
    }

    /**
     * <pre>
     *
     *
     *
     *    Testcase Name: query(String, String, String)
     *    Testcase Number: EMB167
     *
     *    setup: create testInstance of MetaDataEntityLocalHome
     *    		  include property in configuration file listing all supported query
     *    	 	  languages with a valid query, for each language perform the following
     *
     *    test procedure:
     *    1.call query(null, queryLanguage, options)
     *      expected result: NullPointerException
     *
     *    2.call query(valid query, queryLanguage, null)
     *      expected result: no exception, return results in collection (can be empty)
     *
     *    3.call query(valid query, queryLanguage, options)
     *      expected result: no exception, return resuls in collection (can be empty)
     *
     *    4.call query(invalid query, queryLanguage, options)
     *      expected result: MalformedQueryException
     *
     *    perform tests 5 &amp; 6 only once
     *    5.call query(valid query, unsupportedQueryLanguage, options)
     *      expected result: UnsupportedQueryLanguageException
     *
     *    6.call query(query, null, options)
     *      expected result: NullPointerException
     *
     *
     *
     * </pre>
     */
    public void testEMB167() throws RemoteException, MediaException, NamingException, FinderException {

        String[] metaDataEntities = null;

        String queryLanguages = embTestConfig.getQueryLanguages();
        StringTokenizer tokenizer = new StringTokenizer(queryLanguages, ";");
        StringTokenizer queryTok = null;
        String currentToken = null;
        String language = null;
        String query = null;
        Map options = new HashMap();

        int exception = -1;

        while (tokenizer.hasMoreTokens()) {
            currentToken = tokenizer.nextToken();
            queryTok = new StringTokenizer(currentToken, ",");
            assertEquals("test initialization: ", queryTok.countTokens(), 2);
            language = queryTok.nextToken();
            query = queryTok.nextToken();

            //
            // test 1
            //
            try {
                exception = mdebTester.queryExceptions(null, language, options);
            } catch (Throwable e) {
                fail("[" + language + "] test 1 threw " + e.toString());
            }
            assertEquals("[" + language + "] test 1: Should throw a NullPointerException",
                    MetaDataEntityLocalTestDriver.NULLPOINTER, exception);
            testTrace("test 1 passed");
            //
            // test 2
            //
            metaDataEntities = mdebTester.queryMetaDataEntity(query, language, null);
            assertNotNull("[" + language + "] test 2: result is null", metaDataEntities);
            testTrace("[" + language + "] test 2 passed");
            //
            // test 3
            //
            metaDataEntities = mdebTester.queryMetaDataEntity(query, language, options);
            assertNotNull("[" + language + "] test 3: result is null", metaDataEntities);
            testTrace("[" + language + "] test 3 passed");
            //
            // test 4
            //

            try {
                exception = mdebTester.queryExceptions(EMBStaticHelper.createRandomString(EMBStaticHelper.randomInt(0,
                        20)), language, options);
            } catch (Throwable e) {
                fail("[" + language + "] test 4 threw " + e.toString());
            }
            if (language.equals("MatchString")) {
                assertEquals("[MatchString] test 4 threw an exception: " + exception, 0, exception);
            } else {
                assertEquals("[" + language + "] test 4: Should throw a MalformedQueryException",
                        MetaDataEntityLocalTestDriver.MALFORMEDQUERY, exception);
            }
            testTrace("test 4 passed");
        }
        //
        // test 5
        //
        try {
            exception = mdebTester.queryExceptions(query, EMBStaticHelper.createRandomString(EMBStaticHelper.randomInt(
                    0, 5)), options);
        } catch (Throwable e) {
            fail("[" + language + "] test 5 threw " + e.toString());
        }
        assertEquals("test 5: Should throw a UnsupportedQueryLanguageException",
                MetaDataEntityLocalTestDriver.UNSUPPORTEDQUERYLANG, exception);
        testTrace("test 5 passed");
        //
        // test 6
        //
        try {
            exception = mdebTester.queryExceptions(query, null, options);
        } catch (Throwable e) {
            fail("[" + language + "] test 6 threw " + e.toString());
        }
        assertEquals("test 6: Should throw a NullPointerException", MetaDataEntityLocalTestDriver.NULLPOINTER,
                exception);
        testTrace("test 7 passed");

        succeed();
    }

    /**
     * <pre>
     *
     *
     *
     *    Testcase Name: retrieveSupportedOptions(String)
     *    Testcase Number: EMB168
     *
     *    setup: create testInstance of MetaDataEntityLocalHome and read in list of
     *    		  supported query languages
     *
     *    test procedure:
     *    1.for each query language, call retrieveSupportedOptions
     *      expected result: no exception and not null
     *
     *    2.call retrieveSupportedOptions(null)
     *      expected result: NullPointerException
     *
     *    3.call retrieveSupportedOptions(&quot;&quot;)
     *      expected result: UnsupportedQueryLanguageException
     *
     *
     *
     * </pre>
     */
    public void testEMB168() throws RemoteException, MediaException, NamingException {

        String[] supportedOptions = null;

        String queryLanguages = embTestConfig.getQueryLanguages();
        StringTokenizer tokenizer = new StringTokenizer(queryLanguages, ";");
        StringTokenizer queryTok = null;
        String currentToken = null;
        String language = null;
        int exception = -1;

        //
        // test 1
        //
        while (tokenizer.hasMoreTokens()) {
            currentToken = tokenizer.nextToken();
            queryTok = new StringTokenizer(currentToken, ",");
            assertEquals("test initialization: ", queryTok.countTokens(), 2);
            language = queryTok.nextToken();

            supportedOptions = mdebTester.retrieveMetaDataEntitySupportedOptions(language);
            assertNotNull("[" + language + "] test 1:  options are null", supportedOptions);
            testTrace("[" + language + "] test 1 passed");
        }
        //
        // test 2
        //
        try {
            exception = mdebTester.retrieveSupportedOptionsExceptions(null);
        } catch (Throwable e) {
            fail("test 2 threw " + e.toString());
        }
        assertEquals("test 2: Should throw a NullPointerException", MetaDataEntityLocalTestDriver.NULLPOINTER,
                exception);
        testTrace("test 2 passed");
        //
        // test 3
        //
        try {
            exception = mdebTester.retrieveSupportedOptionsExceptions("");
        } catch (Throwable e) {
            fail("test 3 threw " + e.toString());
        }
        assertEquals("test 3: Should throw an UnsupportedQueryLanguageException",
                MetaDataEntityLocalTestDriver.UNSUPPORTEDQUERYLANG, exception);
        testTrace("test 3 passed");

        succeed();
    }

    /**
     * <pre>
     *
     *
     *
     *    Testcase Name: retrieveSupportedQueryLanguages()
     *    Testcase Number: EMB169
     *
     *    setup: create testInstance of MetaDataEntityLocalHom and get lists of supported
     *    	      query languages from configuration file
     *
     *    test procedure:
     *    1.call retrieveSupportedQueryLanguages and compare with array from file
     *      expected results: arrays match
     *
     *
     *
     * </pre>
     */
    public void testEMB169() throws RemoteException, MediaException, NamingException {
        String[] supportedQueryLanguages = null;

        //
        // test 1
        //
        String queryLanguages = embTestConfig.getQueryLanguages();
        StringTokenizer tokenizer = new StringTokenizer(queryLanguages, ";");
        StringTokenizer queryTok = null;
        String currentToken = null;

        String[] retrievedLanguages = new String[tokenizer.countTokens()];
        for (int i = 0; i < tokenizer.countTokens(); i++) {
            currentToken = tokenizer.nextToken();
            queryTok = new StringTokenizer(currentToken, ",");
            assertEquals("test initialization: ", queryTok.countTokens(), 2);
            retrievedLanguages[i] = queryTok.nextToken();
        }

        supportedQueryLanguages = mdebTester.retrieveMetaDataEntitySupportedQueryLanguages();
        assertTrue("test 1: languages do not match", java.util.Arrays.equals(retrievedLanguages,
                supportedQueryLanguages));
        testTrace("test 1 passed");

        succeed();
    }
}