/*
 * 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
     * @param minFirstNameLength
     * @param testName
     * @return
     */
    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
     * @param vectorOfEmployees
     * @param minFirstNameLength
     * @param testName
     * @return
     */
    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
     * @param theEjbqlString
     */
    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);
    }
}
