/*******************************************************************************
 * Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/
package org.eclipse.persistence.testing.tests.jpa.customfeatures;

import java.io.*;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.List;

import org.w3c.dom.*;

import javax.xml.parsers.*;
import javax.xml.transform.stream.StreamResult;
import javax.persistence.EntityManager;

import junit.framework.*;
import org.eclipse.persistence.testing.framework.TestCase;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.customfeatures.*;
import org.eclipse.persistence.tools.schemaframework.PackageDefinition;
import org.eclipse.persistence.tools.schemaframework.StoredProcedureDefinition;
import org.eclipse.persistence.tools.schemaframework.SchemaManager;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.platform.xml.XMLTransformer;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.ServerSession;

public class CustomFeaturesJUnitTestSuite extends JUnitTestCase {
    private static int empId;
    protected static int NUM_INSERTS = 200;
    public static String dbVersion;

    public CustomFeaturesJUnitTestSuite() {
        super();
    }

    public CustomFeaturesJUnitTestSuite(String name) {
        super(name);
    }

    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.setName("CustomFeaturesJUnitTestSuite");
        suite.addTest(new CustomFeaturesJUnitTestSuite("testSetup"));
        suite.addTest(new CustomFeaturesJUnitTestSuite("testNCharXMLType"));
        suite.addTest(new CustomFeaturesJUnitTestSuite("testBatchInserts"));
        suite.addTest(new CustomFeaturesJUnitTestSuite("testBatchUpdates"));
        suite.addTest(new CustomFeaturesJUnitTestSuite("testNamedStoredProcedureInOutQuery"));
        suite.addTest(new CustomFeaturesJUnitTestSuite("testNamedStoredProcedureCursorQuery"));
        return suite;
    }

    public void testSetup() throws SQLException {
        ServerSession session = JUnitTestCase.getServerSession("customfeatures");
        new EmployeeTableCreator().replaceTables(session);
        buildOraclePackage(session);
        buildOracleStoredProcedureReadFromEmployeeInOut(session);
        buildOracleStoredProcedureReadFromEmployeeCursor(session);
        
        Accessor accessor = session.getDefaultConnectionPool().acquireConnection();
        try {
            accessor.incrementCallCount(session);
            DatabaseMetaData metaData = accessor.getConnection().getMetaData(); 
            String dbMajorMinorVersion = Integer.toString(metaData.getDatabaseMajorVersion()) + '.' + Integer.toString(metaData.getDatabaseMinorVersion()); 
            String dbProductionVersion =  metaData.getDatabaseProductVersion();
            // For Helper.compareVersions to work the first digit in the passed version String should be part of the version,
            // i.e. "10.2.0.2 ..." is ok, but "Oracle 10g ... 10.2.0.2..." is not.
            dbVersion = dbProductionVersion.substring(dbProductionVersion.indexOf(dbMajorMinorVersion));
        } finally {
            accessor.decrementCallCount();
            session.getDefaultConnectionPool().releaseConnection(accessor);
        }
    }

    /**
     * Tests a NChar and XML Type with Document.
     */
    public void testNCharXMLType() {
        EntityManager em = createEntityManager("customfeatures");
        beginTransaction(em);
        Employee emp = null;
        try {
            emp = new Employee();
            emp.setResume_xml(resume0());
            char nCh = '\u0410';
            emp.setEmpNChar(nCh);
            emp.setResume_dom(documentFromString(resume0()));
            em.persist(emp);
            empId = emp.getId();
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw e;
        }

        try {
            em.clear();
            clearCache("customfeatures");
            if(isOnServer()) {
                beginTransaction(em);
            }
            Employee readEmp = em.find(Employee.class, empId);
            compare(readEmp, emp);
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    /**
     * Tests a Native Batch Writing as batch inserts.
     */
    public void testBatchInserts() {
        EntityManager em = createEntityManager("customfeatures");
        beginTransaction(em);
        try {
            for (int i = 0; i < NUM_INSERTS; i++) {
                Employee emp = new Employee();
                emp.setResume_xml(resume0());
                emp.setResume_dom(documentFromString(resume0()));
                char nCh = '\u0410';
                emp.setEmpNChar(nCh);
                em.persist(emp);
            }
            commitTransaction(em);
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    /**
     * Tests a Native Batch Writing as batch updates with
     * OptimisticLockingException.
     */
    public void testBatchUpdates() {
        EntityManager em = createEntityManager("customfeatures");
        beginTransaction(em);
        List emps = em.createQuery("SELECT OBJECT(e) FROM Employee e").getResultList();
        try {
            for (int i = 0; i < emps.size(); i++) {
                Employee e = (Employee) emps.get(i);
                String newName = ((Employee) emps.get(i)).getName() + i + "test";
                e.setName(newName);
                e.setVersion(e.getVersion() - 1);
            }
            em.flush();
            commitTransaction(em);
            fail("OptimisticLockingException is not thrown!");
        } catch (Exception exception) {
            if (exception.getMessage().indexOf("org.eclipse.persistence.exceptions.OptimisticLockException") == -1) {
                fail("it's not the right exception");
            }
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    /**
     * Tests a @NamedStoredProcedureQuery with store procedure IN_OUT parameter,
     * and XML Type using String
     */
    public void testNamedStoredProcedureInOutQuery() {
        if(Helper.compareVersions(dbVersion, "11.2.0.2") < 0) {
            // Oracle db 11.2.0.2 or later is required for this test
            return;
        }
        EntityManager em = createEntityManager("customfeatures");
        beginTransaction(em);
        try {
            Employee emp = new Employee();
            emp.setResume_xml(resume1());
            emp.setResume_dom(documentFromString(resume0()));
            char nCh = '\u0400';
            emp.setEmpNChar(nCh);
            em.persist(emp);
            commitTransaction(em);
            em.clear();
            clearCache("customfeatures");
            if(isOnServer()) {
                beginTransaction(em);
            }
            // note that readEmployee will have only two attributes set: id and empNChar
            Employee readEmp = (Employee) em.createNamedQuery("ReadEmployeeInOut").setParameter("ID", emp.getId()).getSingleResult();
            if (emp.getEmpNChar() != readEmp.getEmpNChar()) {
                fail("readEmp.getEmpNChar() == " + readEmp.getEmpNChar() + ", does not match empNChar of the object that was written: " + emp.getEmpNChar());
            }
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    /**
     * Tests a @NamedStoredProcedureQuery with store procedure ref Cursor, and
     * XML Type using String
     */
    public void testNamedStoredProcedureCursorQuery() {
        EntityManager em = createEntityManager("customfeatures");
        beginTransaction(em);
        try {
            Employee emp = new Employee();
            emp.setResume_xml(resume1());
            emp.setResume_dom(documentFromString(resume0()));
            char nCh = '\u0400';
            emp.setEmpNChar(nCh);
            emp.setName("Edward Xu");
            em.persist(emp);
            commitTransaction(em);
            em.clear();
            clearCache("customfeatures");
            if(isOnServer()) {
                beginTransaction(em);
            }
            Employee readEmp = (Employee) em.createNamedQuery("ReadEmployeeCursor").setParameter("ID", emp.getId()).getSingleResult();
            compare(readEmp, emp);
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    public static String resume0() {
        String resume = "<resume>\n";
        resume += "  <first-name>Bob</first-name>\n";
        resume += "   <last-name>Jones</last-name>\n";
        resume += "   <age>45</age>\n";
        resume += "   <education>\n";
        resume += "     <degree>BCS</degree>\n";
        resume += "     <degree>MBA</degree>\n";
        resume += "   </education>\n";
        resume += "</resume>";
        return resume;
    }

    public static String resume1() {
        String resume = "<resume>\n";
        resume += "  <first-name>Frank</first-name>\n";
        resume += "   <last-name>Cotton</last-name>\n";
        resume += "   <age>27</age>\n";
        resume += "   <education>\n";
        resume += "     <degree>BCS</degree>\n";
        resume += "   </education>\n";
        resume += "</resume>";
        return resume;
    }

    public static Document documentFromString(String xmlString) {
        try {
            ByteArrayInputStream stream = new ByteArrayInputStream(xmlString.getBytes());
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(stream);
            return doc;
        } catch (Exception ex) {
            fail("Unable to create document due to: " + ex.getMessage());
        }
        return null;
    }

    public PackageDefinition buildOraclePackage(Session session) {
        if (TestCase.supportsStoredProcedures(session)) {
            PackageDefinition types = new PackageDefinition();
            types.setName("Cursor_Type");
            types.addStatement("Type Any_Cursor is REF CURSOR");

            SchemaManager schema = new SchemaManager(((DatabaseSession) session));
            schema.replaceObject(types);
            return types;
        } else {
            fail("store procedure is not supported!");
            return null;
        }
    }

    public void buildOracleStoredProcedureReadFromEmployeeInOut(Session session) {
        if (TestCase.supportsStoredProcedures(session)) {
            StoredProcedureDefinition proc = new StoredProcedureDefinition();
            proc.setName("Read_Employee_InOut");

            proc.addInOutputArgument("employee_id_v", Integer.class);
            proc.addOutputArgument("nchar_v", "NCHAR");

            String statement = "SELECT NCHARTYPE INTO nchar_v FROM CUSTOM_FEATURE_EMPLOYEE WHERE (ID = employee_id_v)";

            proc.addStatement(statement);
            SchemaManager schema = new SchemaManager(((DatabaseSession) session));
            schema.replaceObject(proc);
        } else
            fail("store procedure is not supported!");
    }

    public void buildOracleStoredProcedureReadFromEmployeeCursor(Session session) {
        if (TestCase.supportsStoredProcedures(session)) {
            StoredProcedureDefinition proc = new StoredProcedureDefinition();
            proc.setName("Read_Employee_Cursor");

            proc.addArgument("employee_id_v", Integer.class);
            proc.addOutputArgument("RESULT_CURSOR", "CURSOR_TYPE.ANY_CURSOR");
            proc.addStatement("OPEN RESULT_CURSOR FOR SELECT * FROM CUSTOM_FEATURE_EMPLOYEE WHERE (ID = employee_id_v)");

            SchemaManager schema = new SchemaManager(((DatabaseSession) session));
            schema.replaceObject(proc);
        } else
            fail("store procedure is not supported!");
    }

    /*
     * This method is necessary because of a bug in Oracle xdb 11.2.0.2: XDB - 11.2.0.2 DB FORMATS RETURNED XML 
     * This bug describes the following workaround:
     *   In init.ora, add "31151 trace name context forever, level 0x100" 
     * When the bug is fixed (or 11.2.0.2 db configurured as described in the workaround))
     * the special case for 11.2.0.2 Oracle db should be removed:
     *
     *  void compare(Employee readEmp, Employee emp) {
     *       if (!getServerSession("customfeatures").compareObjects(readEmp, emp)) {
     *           fail("Object: " + readEmp + " does not match object that was written: " + emp + ". See log (on finest) for what did not match.");
     *       }
     *   }
     */
    void compare(Employee readEmp, Employee emp) {
        if(Helper.compareVersions(dbVersion, "11.2.0.2") >= 0) {
            // Oracle db 11.2.0.2 returns formatted xml, therefore the original and the read back strings might differ.
            String originalReadResume_xml = null;
            String originalResume_xml = null;
            if(!readEmp.getResume_xml().equals(emp.getResume_xml())) {
                originalReadResume_xml = readEmp.getResume_xml(); 
                originalResume_xml = emp.getResume_xml();
                String unformattedReadResume_xml = removeWhiteSpaceFromString(originalReadResume_xml); 
                String unformattedResume_xml = removeWhiteSpaceFromString(originalResume_xml); 
                if(unformattedReadResume_xml.equals(unformattedResume_xml)) {
                    // xml docs defined by the two strings are equivalent
                    // temporary remove the strings from their owner Employees so that it could pass compareObjects
                    readEmp.setResume_xml(null);
                    emp.setResume_xml(null);
                } else {
                    fail("unformattedReadResume_xml == " + unformattedReadResume_xml + "\nunformattedResume_xml == " + unformattedResume_xml);
                }
            }

            // Oracle db 11.2.0.2 returns formatted xml, therefore the original and the read back doms might differ.
            Document originalReadResume_dom = null;
            Document originalResume_dom = null;
            if(!readEmp.getResume_dom().equals(emp.getResume_dom())) {
                originalReadResume_dom = readEmp.getResume_dom(); 
                originalResume_dom = emp.getResume_dom();
                Document unformattedReadResume_dom =  (Document)originalReadResume_dom.cloneNode(true);
                removeEmptyTextNodes(unformattedReadResume_dom);
                Document unformattedResume_dom =  (Document)originalResume_dom.cloneNode(true);
                removeEmptyTextNodes(unformattedResume_dom);
                String unformattedReadResume_dom_toString = convertDocumentToString(unformattedReadResume_dom);
                String unformattedResume_dom_toString = convertDocumentToString(unformattedResume_dom);
                if(unformattedReadResume_dom_toString.equals(unformattedResume_dom_toString)) {
                    // xml docs defined by the two strings are equivalent
                    // temporary remove the doms from their owner Employees so that it could pass compareObjects
                    readEmp.setResume_dom(null);
                    emp.setResume_dom(null);
                } else {
                    fail("unformattedReadResume_dom_toString == " + unformattedReadResume_dom_toString + "\nunformattedResume_dom_toString == " + unformattedResume_dom_toString);
                }
            }

            try {
                if (!getServerSession("customfeatures").compareObjects(readEmp, emp)) {
                    fail("Object: " + readEmp + " does not match object that was written: " + emp + ". See log (on finest) for what did not match.");
                }
            } finally {
                if(emp.getResume_xml() == null && originalResume_xml != null) {
                    // set back the temporary removed resume_xml into both objects
                    readEmp.setResume_xml(originalReadResume_xml);
                    emp.setResume_xml(originalResume_xml);
                }
                if(emp.getResume_dom() == null && originalResume_dom != null) {
                    // set back the temporary removed resume_dom into both objects
                    readEmp.setResume_dom(originalReadResume_dom);
                    emp.setResume_dom(originalResume_dom);
                }
            }
        } else {
            // Before version 11.2.0.2 Oracle db returned xml string exactly as it was written (keeping the same format: white spaces, \r, \n etc).
            // No special comparison for resume_xml is required.
            if (!getServerSession("customfeatures").compareObjects(readEmp, emp)) {
                fail("Object: " + readEmp + " does not match object that was written: " + emp + ". See log (on finest) for what did not match.");
            }
        }
    }
    
    // Contributed by Blaise
    public static void removeEmptyTextNodes(Node node) {
        NodeList nodeList = node.getChildNodes();
        Node childNode;
        for (int x = nodeList.getLength() - 1; x >= 0; x--) {
            childNode = nodeList.item(x);
            if (childNode.getNodeType() == Node.TEXT_NODE) {
                if (childNode.getNodeValue().trim().equals("")) {
                    node.removeChild(childNode);
                }
            } else if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                removeEmptyTextNodes(childNode);
            }
        }
    }

    // Contributed by Blaise
    public static String removeWhiteSpaceFromString(String s) {
        String returnString = s.replaceAll(" ", "");
        returnString = returnString.replaceAll("\n", "");
        returnString = returnString.replaceAll("\t", "");
        returnString = returnString.replaceAll("\r", "");

        return returnString;
    }
    
    static String convertDocumentToString(Document doc) {
        XMLTransformer xmlTransformer = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer();
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        xmlTransformer.transform(doc, result);
        return writer.getBuffer().toString();
    }
}
