/*
 * 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.jpql;

import java.util.*;

import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.queries.JPQLCallQueryMechanism;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.employee.domain.*;

/**
 * Generic EJBQL test case.
 * Executes the EJBQL string and verifies the results.
 */
public class JPQLTestCase extends TransactionalTestCase {
    private String ejbql;
    protected ObjectLevelReadQuery theQuery = null;
    private Class<?> referenceClass;
    private Expression originalExpression = null;
    private Object originalObject;
    private DomainObjectComparer comparer = null;
    private Object returnedObjects;
    public boolean useReportQuery;
    private Vector arguments = null;
    protected Vector supportedPlatforms;
    protected Vector unsupportedPlatforms;

    public JPQLTestCase() {
        super();
        useReportQuery = false;
    }

    public JPQLTestCase(String ejbqlString) {
        this();
        this.ejbql = ejbqlString;
    }

    public JPQLTestCase(ObjectLevelReadQuery theQuery) {
        this();
        this.theQuery = theQuery;
        this.ejbql = (((JPQLCallQueryMechanism)theQuery.getQueryMechanism()).getJPQLCall()).getEjbqlString();
    }

    public JPQLTestCase(String ejbqlString, ObjectLevelReadQuery theQuery) {
        this();
        this.ejbql = ejbqlString;
        this.theQuery = theQuery;
    }

    public JPQLTestCase(String ejbqlString, ObjectLevelReadQuery theQuery, Class<?> theReferenceClass) {
        this();
        this.ejbql = ejbqlString;
        this.theQuery = theQuery;
        this.referenceClass = theReferenceClass;
    }

    public static JPQLTestCase getBaseTestCase() {
        return new BaseTestCase();
    }

    public Vector getAttributeFromAll(String attributeName, Vector objects) {
        ClassDescriptor descriptor = getSession().getClassDescriptor(getReferenceClass());
        DirectToFieldMapping mapping = (DirectToFieldMapping)descriptor.getMappingForAttributeName(attributeName);

        Vector attributes = new Vector();
        Object currentObject;
        for (int i = 0; i < objects.size(); i++) {
            currentObject = objects.elementAt(i);
            if (currentObject.getClass() == ReportQueryResult.class) {
                attributes.addElement(((ReportQueryResult)currentObject).get(attributeName));
            } else {
                attributes.addElement(mapping.getAttributeValueFromObject(currentObject));
            }
        }
        return attributes;
    }

    @Override
    public void reset() {
        // Force the query to be rebuilt each time...
        setQuery(null);
        super.reset();
    }

    /**
     * Return the first employee that has a long enough name for the test.
     * If no match is found throw a warning exception.
     * See bug 223005
     */
    public Employee getEmployeeWithRequiredNameLength(int minFirstNameLength, String testName) {
        return getEmployeeWithRequiredNameLength(getSomeEmployees(), minFirstNameLength, testName);
    }

    /**
     * Return the first employee that has a long enough name for the test.
     * If no match is found throw a warning exception.
     * See bug 223005
     */
    public Employee getEmployeeWithRequiredNameLength(Vector vectorOfEmployees, int minFirstNameLength, String testName) {
        Employee empMatch = null;
        Vector<Employee> employees = vectorOfEmployees;
        String firstName;
        StringBuffer partialFirstName;

        // Loop through the collection of employees to find one that matches our test requirements
        for(int i=0; i<employees.size();i++) {
            empMatch = employees.get(i);
            firstName = empMatch.getFirstName();
            // Verify length criteria
            if(firstName.length() >= minFirstNameLength) {
                // exit the for loop - return the last empMatch
                i = employees.size();
            }
        }

        // If we could not find a proper employee for testing - throw a warning
        if(null == empMatch) {
            throw new RuntimeException(testName + " Setup Failed: unable to find an Employee with firstName size of at least  " + minFirstNameLength);
        } else {
            return empMatch;
        }
    }

    @Override
    public void setup() {
        if (!isPlatformSupported(getSession().getLogin().getPlatform())) {
            throw new TestWarningException("This EJBQL is not supported on this platform.");
        }

        if (getReferenceClass() == null) {
            setReferenceClass(Employee.class);
        }
        getQuery().setEJBQLString(getEjbqlString());
    }

    @Override
    public void test() throws Exception {
        getSession().logMessage("Running EJBQL -> " + getEjbqlString());
        executeEJBQLQuery();
    }

    //lowest level execute that can be subclassed if required
    public void executeEJBQLQuery() throws Exception {
        if (hasArguments()) {
            addArgumentNamesToQuery();
            setReturnedObjects(getSession().executeQuery(getQuery(), getArguments()));
        } else {
            setReturnedObjects(getSession().executeQuery(getQuery()));
        }
    }

    //add the "1", "2", ... to the query for each parameter
    private void addArgumentNamesToQuery() {
        int argumentIndex = 1;
        while (argumentIndex <= getArguments().size()) {
            getQuery().addArgument(String.valueOf(argumentIndex));
            ++argumentIndex;
        }
    }

    @Override
    public void verify() throws Exception {
        if (!getComparer().compareObjects(getOriginalObject(), getReturnedObjects())) {
            throw new TestErrorException(getName() + " Verify Failed:" + getOriginalObject() + " != " + getReturnedObjects());
        }
    }

    /**
     * Return some projects to be used for querying
     */
    public Vector getSomeProjects() {
        return getSession().readAllObjects(Project.class);
    }

    /*
     * Return all the addresses to be used for querying
     */
    public Vector getSomeAddresses() {
        return getSession().readAllObjects(Address.class);
    }

    /*
     * Return some employees to be used for querying
     */
    public Vector getSomeEmployees() {
        return getSession().readAllObjects(Employee.class);
    }

    /**
     * Set the ejbql string to the passed value
     */
    public void setEjbqlString(String theEjbqlString) {
        this.ejbql = theEjbqlString;
    }

    /**
     * Return the ejbqlString
     */
    public String getEjbqlString() {
        return ejbql;
    }

    public ObjectLevelReadQuery getQuery() {
        if (theQuery == null) {
            if (shouldUseReportQuery()) {
                setQuery(buildReportQuery());
            } else {
                setQuery(new ReadAllQuery());
            }
            getQuery().setEJBQLString(getEjbqlString());
        }
        return theQuery;
    }

    public ReportQuery buildReportQuery() {
        ReportQuery reportQuery = new ReportQuery();
        reportQuery.dontRetrievePrimaryKeys();
        reportQuery.returnSingleAttribute();
        return reportQuery;
    }

    public void setQuery(ObjectLevelReadQuery theQuery) {
        this.theQuery = theQuery;
    }

    public Class<?> getReferenceClass() {
        return referenceClass;
    }

    public void setReferenceClass(Class<?> theClass) {
        this.referenceClass = theClass;
    }

    public Object getReturnedObjects() {
        return returnedObjects;
    }

    public void setReturnedObjects(Object theReturnedObjects) {
        returnedObjects = theReturnedObjects;
    }

    public DomainObjectComparer getComparer() {
        if (comparer == null) {
            setComparer(new DomainObjectComparer());
            getComparer().setSession(getSession());
        }
        return comparer;
    }

    public Expression getOriginalObjectExpression() {
        return originalExpression;
    }

    public void setOriginalObjectExpression(Expression theOriginalExpression) {
        originalExpression = theOriginalExpression;
    }

    public void setComparer(DomainObjectComparer theComparer) {
        comparer = theComparer;
    }

    public Object getOriginalObject() {
        return originalObject;
    }

    public void setOriginalOject(Object theObject) {
        originalObject = theObject;
    }

    public void useReportQuery() {
        useReportQuery = true;
    }

    public boolean shouldUseReportQuery() {
        return getUseReportQuery();
    }

    public boolean getUseReportQuery() {
        return useReportQuery;
    }

    public void setUseReportQuery(boolean useReportQuery) {
        this.useReportQuery = useReportQuery;
    }

    //get and set for arguments to the EJBQL query
    public Vector getArguments() {
        return arguments;
    }

    public void setArguments(Vector newArguments) {
        arguments = newArguments;
    }

    public boolean hasArguments() {
        return getArguments() != null;
    }

    /**
     * A clean way to specify which tests run on which platforms.
     */
    public boolean isPlatformSupported(DatabasePlatform platform) {
        boolean supported = false;
        boolean notSupported = false;
        if ((unsupportedPlatforms == null) && (supportedPlatforms == null)) {
            return true;
        }
        if (supportedPlatforms != null) {
            for (Iterator iterator = supportedPlatforms.iterator(); iterator.hasNext();) {
                Class<?> platformClass = (Class)iterator.next();
                if (platformClass.isInstance(platform)) {
                    supported = true;
                }
            }
        } else {
            supported = true;
        }
        if (unsupportedPlatforms != null) {
            for (Iterator iterator = unsupportedPlatforms.iterator(); iterator.hasNext();) {
                Class<?> platformClass = (Class)iterator.next();
                if (platformClass.isInstance(platform)) {
                    notSupported = true;
                }
            }
        }
        return supported && (!notSupported);
    }

    public void addSupportedPlatform(Class<?> platform) {
        if (supportedPlatforms == null) {
            supportedPlatforms = new Vector();
        }
        supportedPlatforms.addElement(platform);
    }

    public void addUnsupportedPlatform(Class<?> platform) {
        if (unsupportedPlatforms == null) {
            unsupportedPlatforms = new Vector();
        }
        unsupportedPlatforms.addElement(platform);
    }
}
