/*
 * Copyright (c) 1998, 2021 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 v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.tests.inheritance;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.DeleteAllQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.UpdateAllQuery;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.queries.ReadAllQuery;

import org.eclipse.persistence.testing.framework.JoinedAttributeTestHelper;
import org.eclipse.persistence.testing.framework.TestCase;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.framework.TestSuite;

import org.eclipse.persistence.testing.models.inheritance.*;

public class STI_JoinedAttributeTest extends TestCase {

    // If the flag is set to true then setup method ensures
    // that the objects in db are exactly those created by
    // STI_EmployeePopulator, and nothing else.
    static protected boolean eachTestShouldEnsurePopulation = false;

    // the following static variables are used only in case eachTestShouldEnsurePopulation==true
    static protected Class[] classes = {STI_Employee.class, STI_Project.class};
    static protected Vector[] objectVectors = {null, null};
    static protected STI_EmployeePopulator populator = new STI_EmployeePopulator();

    // The name should start with "test" prefix,
    // it coinsides with the method name the test should use.
    // For instance "testProjectJoinTeamMembers" causes the test's test
    // method to invoke testProjectJoinTeamMembers method.
    public STI_JoinedAttributeTest(String name) {
        super();
        setName(name);
    }

    // Junit-style trick: this method creates a TestSuite which contains
    // a TestCase for each method with the name starting with "test".
    public static TestSuite getTestSuite() {
        TestSuite suite = new TestSuite();
        suite.setName("STI_JoinedAttributeTest");
        suite.setDescription("This suite tests join attribute on a Single Table Inheritance version of Employee/Project.");
        Method[] methods= STI_JoinedAttributeTest.class.getDeclaredMethods();
        for (int i= 0; i < methods.length; i++) {
            if(isPublicTestMethod(methods[i])) {
                suite.addTest(new STI_JoinedAttributeTest(methods[i].getName()));
            }
        }
        return suite;
    }

    // stolen from junit.framework.TestSuite
    private static boolean isPublicTestMethod(Method m) {
        return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
     }

    // stolen from junit.framework.TestSuite
    private static boolean isTestMethod(Method m) {
        String name= m.getName();
        Class[] parameters= m.getParameterTypes();
        Class<?> returnType= m.getReturnType();
        return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE);
     }

    // This method is designed to make sure that the tests always work in the same environment:
    // db has all the objects produced by populate method - and no other objects of the relevant classes.
    // In order to enforce that the first test populates the db and caches the objects in static collections,
    // the following test reads all the objects from the db, compares them with the cached ones - if they are the
    // same (the case if the tests run directly one after another) then no population occurs.
    // Switched on/off with eachTestShouldEnsurePopulation flag.
    @Override
    protected void setup() throws Throwable {
        clearCache();
        if(eachTestShouldEnsurePopulation) {
            if(!compare()) {
                clear();
                populate();
            }
            clearCache();
        }
    }

    // executes the method with the same name as the test
    @Override
    protected void test() throws Exception {
        Method method = this.getClass().getDeclaredMethod(getName());
        method.invoke(this);
    }

    @Override
    public void reset() {
        clearCache();
    }

    protected void clear() {
        UnitOfWork uow = getSession().acquireUnitOfWork();

        UpdateAllQuery updateEmployees = new UpdateAllQuery(STI_Employee.class);
        updateEmployees.addUpdate("manager", null);
        uow.executeQuery(updateEmployees);

        UpdateAllQuery updateProjects = new UpdateAllQuery(STI_Project.class);
        updateProjects.addUpdate("teamLeader", null);
        uow.executeQuery(updateProjects);

        uow.executeQuery(new DeleteAllQuery(STI_Employee.class));
        uow.executeQuery(new DeleteAllQuery(STI_Project.class));

        uow.commit();
        clearCache();
    }

    protected void populate() {
        populator.buildExamples();
        populator.persistExample(getSession());
        clearCache();
        for(int i=0; i < classes.length; i++) {
            objectVectors[i] = getSession().readAllObjects(classes[i]);
        }
    }

    public void testProjectJoinTeamMembers() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();

        query.addJoinedAttribute(query.getExpressionBuilder().anyOf("teamMembers"));

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    public void testProjectJoinTeamLeaderWhereTeamLeaderNotNull() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        Expression teamLeader = query.getExpressionBuilder().get("teamLeader");
        query.setSelectionCriteria(teamLeader.notNull());

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();

        query.addJoinedAttribute(teamLeader);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    public void testProjectOuterJoinTeamMembers() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();

        Expression teamMembers = query.getExpressionBuilder().anyOfAllowingNone("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    public void testProblemReporterProjectJoinTeamMembers() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("name").equal("Problem Reporter"));

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();

        Expression teamMembers = query.getExpressionBuilder().anyOf("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    public void testEmployeeJoinProjects() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Employee.class);

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        query.addJoinedAttribute(query.getExpressionBuilder().anyOf("projects"));

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    public void testEmployeeJoinProjectsJoinTeamLeaderWhereManagerIsNull() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Employee.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("manager").isNull());

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        Expression projects = query.getExpressionBuilder().anyOf("projects");
        query.addJoinedAttribute(projects);
        Expression teamLeader = projects.get("teamLeader");
        query.addJoinedAttribute(teamLeader);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    public void testProjectOuterJoinTeamLeaderTeamMembersWhereProjectName() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("name").equal("Problem Reporting System").
            or(query.getExpressionBuilder().get("name").equal("Bleep Blob")));

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();

        Expression teamLeader = query.getExpressionBuilder().getAllowingNull("teamLeader");
        query.addJoinedAttribute(teamLeader);
        Expression teamMembers = query.getExpressionBuilder().anyOfAllowingNone("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    public void testEmployeeOuterJoinProjectsTeamLeader() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Employee.class);

        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();

        Expression projects = query.getExpressionBuilder().anyOfAllowingNone("projects");
        query.addJoinedAttribute(projects);
        Expression teamLeader = projects.getAllowingNull("teamLeader");
        query.addJoinedAttribute(teamLeader);
        Expression teamMembers = projects.anyOfAllowingNone("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }

    protected String executeQueriesAndCompareResults(ObjectLevelReadQuery controlQuery, ObjectLevelReadQuery queryWithJoins) {
        return JoinedAttributeTestHelper.executeQueriesAndCompareResults(controlQuery, queryWithJoins, (AbstractSession)getSession());
    }

    protected void failTest(String errorMsg) {
        throw new TestErrorException(errorMsg);
    }

    protected boolean compare() {
        for(int i=0; i < classes.length; i++) {
            if(!compare(i)) {
                return false;
            }
        }
        return true;
    }

    protected boolean compare(int i) {
        if(objectVectors[i] == null) {
            return false;
        }
        Vector currentVector = getSession().readAllObjects(classes[i]);

        if(currentVector.size() != objectVectors[i].size()) {
            return false;
        }
        ClassDescriptor descriptor = getSession().getDescriptor(classes[i]);
        for(int j=0; j < currentVector.size(); j++) {
            Object obj1 = objectVectors[i].elementAt(j);
            Object obj2 = currentVector.elementAt(j);
            if(!descriptor.getObjectBuilder().compareObjects(obj1, obj2, (org.eclipse.persistence.internal.sessions.AbstractSession)getSession())) {
                return false;
            }
        }
        return true;
    }

    protected void clearCache() {
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
    }
}
