/*
 * Copyright (c) 2012, 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
//     Zoltan NAGY & tware - updated support for MaxRows
//     11/01/2010-2.2 Guy Pelletier
//       - 322916: getParameter on Query throws NPE
//     11/09/2010-2.1 Michael O'Brien
//       - 329089: PERF: EJBQueryImpl.setParamenterInternal() move indexOf check inside non-native block
//     02/08/2012-2.4 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     06/20/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/24/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     11/05/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/11/2012-2.5 Guy Pelletier
//       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.
package org.eclipse.persistence.internal.jpa;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.LockTimeoutException;
import jakarta.persistence.NoResultException;
import jakarta.persistence.NonUniqueResultException;
import jakarta.persistence.Parameter;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.PessimisticLockException;
import jakarta.persistence.Query;
import jakarta.persistence.QueryTimeoutException;
import jakarta.persistence.TemporalType;
import jakarta.persistence.TransactionRequiredException;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.querydef.ParameterExpressionImpl;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DatabaseQuery.ParameterType;
import org.eclipse.persistence.queries.ModifyQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Session;

/**
 * Concrete JPA query class. The JPA query wraps a DatabaseQuery which is
 * executed.
 */
public class QueryImpl {

    public static final int UNDEFINED = -1;

    /**
     * Wrapped native query. The query may be {@link #isShared}
     */
    protected DatabaseQuery databaseQuery = null;

    protected EntityManagerImpl entityManager = null;
    protected String queryName = null;
    protected Map<String, Object> parameterValues = null;
    protected Map<String, Parameter<?>> parameters;
    protected int firstResultIndex = UNDEFINED;
    protected int maxResults = UNDEFINED;

    protected LockModeType lockMode = null;

    /**
     * Stores if the wrapped query is shared, and requires cloning before being
     * changed.
     */
    protected boolean isShared;

    /**
     * Base constructor for EJBQueryImpl. Initializes basic variables.
     */
    protected QueryImpl(EntityManagerImpl entityManager) {
        this.parameterValues = new HashMap<String, Object>();
        this.entityManager = entityManager;
        this.isShared = true;
    }

    /**
     * Create an EJBQueryImpl with a DatabaseQuery.
     */
    public QueryImpl(DatabaseQuery query, EntityManagerImpl entityManager) {
        this(entityManager);
        this.databaseQuery = query;
    }

    /**
     * This method should be called to close any left over open connection to
     * the database (if there is one).
     */
    public void close() {
        // Currently nothing to do at this level. Connections are not left open.
    }

    /**
     * INTERNAL:
     * Change the internal query to data modify query.
     */
    protected void setAsDataModifyQuery() {
        DataModifyQuery query = new DataModifyQuery();
        query.setIsUserDefined(this.databaseQuery.isUserDefined());
        // By default, do not batch user native queries, as row count must be returned.
        query.setIsBatchExecutionSupported(false);
        query.copyFromQuery(this.databaseQuery);
        // Need to clone call, in case was executed as read.
        query.setDatasourceCall((Call) this.databaseQuery.getDatasourceCall().clone());
        this.databaseQuery = query;
    }

    /**
     * Internal method to change the wrapped query to a DataModifyQuery if
     * necessary. When created, the query is created as a DataReadQuery as it is
     * unknown if it is a SELECT or UPDATE. Note that this prevents the original
     * named query from every being prepared.
     */
    protected void setAsSQLModifyQuery() {
        if (getDatabaseQueryInternal().isDataReadQuery()) {
            setAsDataModifyQuery();
        }
    }

    /**
     * Internal method to change the wrapped query to a DataReadQuery if
     * necessary. This should never occur, but could possibly if the same query
     * was executed as executeUpdate() then as getResultList(). Note that the
     * initial conversion to modify would loose any read settings that had been
     * set.
     */
    protected void setAsSQLReadQuery() {
        if (getDatabaseQueryInternal().isDataModifyQuery()) {
            DataReadQuery query = new DataReadQuery();
            query.setResultType(DataReadQuery.AUTO);
            query.setIsUserDefined(databaseQuery.isUserDefined());
            query.copyFromQuery(this.databaseQuery);
            this.databaseQuery = query;
        }
    }

    /**
     * Execute a ReadQuery by assigning the stored parameter values and running
     * it in the database
     *
     * @return the results of the query execution
     */
    protected Object executeReadQuery() {
        List<Object> parameterValues = processParameters();
        // TODO: the following performFlush() call is a temporary workaround for
        // bug 4752493:
        // CTS: INMEMORY QUERYING IN EJBQUERY BROKEN DUE TO CHANGE TO USE
        // REPORTQUERY.
        // Ideally we should only flush in case the selectionExpression can't be
        // conformed in memory.
        // There are two alternative ways to implement that:
        // 1. Try running the query with conformInUOW flag first - if it fails
        // with
        // QueryException.cannotConformExpression then flush and run the query
        // again -
        // now without conforming.
        // 2. Implement a new isComformable method on Expression which would
        // determine whether the expression
        // could be conformed in memory, flush only in case it returns false.
        // Note that doesConform method currently implemented on Expression
        // requires object(s) to be confirmed as parameter(s).
        // The new isComformable method should not take any objects as
        // parameters,
        // it should return false if there could be such an object that
        // passed to doesConform causes it to throw
        // QueryException.cannotConformExpression -
        // and true otherwise.
        boolean shouldResetConformResultsInUnitOfWork = false;
        DatabaseQuery query = getDatabaseQueryInternal();
        boolean isObjectLevelReadQuery = query.isObjectLevelReadQuery();
        if (isFlushModeAUTO() && (!isObjectLevelReadQuery || !((ObjectLevelReadQuery)query).isReadOnly())) {
            performPreQueryFlush();
            if (isObjectLevelReadQuery) {
                if (((ObjectLevelReadQuery)query).shouldConformResultsInUnitOfWork()) {
                    cloneSharedQuery();
                    query = getDatabaseQueryInternal();
                    ((ObjectLevelReadQuery)query).setCacheUsage(ObjectLevelReadQuery.UseDescriptorSetting);
                    shouldResetConformResultsInUnitOfWork = true;
                }
            }
        }

        // Set a pessimistic locking on the query if specified.
        if (this.lockMode != null && !this.lockMode.equals(LockModeType.NONE)) {
            // We need to throw TransactionRequiredException if there is no
            // active transaction
            this.entityManager.checkForTransaction(true);

            // The lock mode setters and getters validate the query type
            // so should be safe to make the casting.
            cloneSharedQuery();
            query = getDatabaseQueryInternal();

            // Set the lock mode (the session is passed in to do some validation
            // checks)
            // If the return value from the set returns true, it indicates that
            // we were unable to set the lock mode.
            if (((ObjectLevelReadQuery)query).setLockModeType(lockMode.name(), (AbstractSession) getActiveSession())) {
                throw new PersistenceException(ExceptionLocalization.buildMessage("ejb30-wrong-lock_called_without_version_locking-index", null));
            }
        }

        Session session = getActiveSession();
        try {
            // in case it's a user-defined query
            if (query.isUserDefined()) {
                // and there is an active transaction
                if (this.entityManager.checkForTransaction(false) != null) {
                    // verify whether uow has begun early transaction
                    if (session.isUnitOfWork() && !((UnitOfWorkImpl)session).wasTransactionBegunPrematurely()) {
                        // uow begins early transaction in case it hasn't
                        // already begun.
                        // TODO: This is not good, it means that no SQL queries
                        // can ever use the cache,
                        // using isUserDefined to mean an SQL query is also
                        // wrong.
                        ((UnitOfWorkImpl)session).beginEarlyTransaction();
                    }
                }
            }

            // Execute the query and return the result.
            return session.executeQuery(query, parameterValues);
        } catch (DatabaseException e) {
            throw getDetailedException(e);
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        } finally {
            this.lockMode = null;

            if (shouldResetConformResultsInUnitOfWork) {
                ((ObjectLevelReadQuery)query).conformResultsInUnitOfWork();
            }
        }
    }

    /**
     * Execute an update or delete statement.
     *
     * @return the number of entities updated or deleted
     */
    public int executeUpdate() {
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            setAsSQLModifyQuery();
            // bug:4294241, only allow modify queries - UpdateAllQuery preferred
            if (!(getDatabaseQueryInternal() instanceof ModifyQuery)) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_execute_update"));
            }

            // need to throw TransactionRequiredException if there is no active
            // transaction
            entityManager.checkForTransaction(true);

            // fix for bug:4288845, did not add the parameters to the query
            List<Object> parameterValues = processParameters();
            if (isFlushModeAUTO()) {
                performPreQueryFlush();
            }
            Integer changedRows = (Integer) getActiveSession().executeQuery(databaseQuery, parameterValues);
            return changedRows;
        } catch (PersistenceException exception) {
            setRollbackOnly();
            throw exception;
        } catch (IllegalStateException exception) {
            setRollbackOnly();
            throw exception;
        }catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        }
    }

    /**
     * Return the wrapped {@link DatabaseQuery} ensuring that if it
     * {@link #isShared} it is cloned before returning to prevent corruption of
     * the query cache.
     *
     * @see #getDatabaseQueryInternal()
     */
    public DatabaseQuery getDatabaseQuery() {
        cloneSharedQuery();
        return getDatabaseQueryInternal();
    }

    /**
     * INTERNAL: Return the cached database query for this EJBQueryImpl. If the
     * query is a named query and it has not yet been looked up, the query will
     * be looked up and stored as the cached query.
     */
    public DatabaseQuery getDatabaseQueryInternal() {
        if ((this.queryName != null) && (this.databaseQuery == null)) {
            // Always ask for the query from the active session. Table per
            // tenant multitenant entity queries may be isolated per EM meaning
            // those queries will not have been initialized (and made available)
            // from their parent session.
            this.databaseQuery = this.entityManager.getActiveSessionIfExists().getQuery(this.queryName);
            // need error checking and appropriate exception for non-existing query
            if (this.databaseQuery != null) {
                if (!this.databaseQuery.isPrepared()) {
                    // prepare the query before cloning, this ensures we do not
                    // have to continually prepare on each usage
                    try {
                        this.databaseQuery.checkPrepare(this.entityManager.getActiveSessionIfExists(), new DatabaseRecord());
                    } catch(RuntimeException re){
                        throw new IllegalArgumentException(re);
                    }
                }
                if (this.databaseQuery.isObjectLevelReadQuery() && ((ObjectLevelReadQuery)this.databaseQuery).getLockModeType() != null){
                    this.lockMode = LockModeType.valueOf(((ObjectLevelReadQuery)this.databaseQuery).getLockModeType());
                }
                if (this.databaseQuery.isReadQuery()){
                    this.maxResults = ((ReadQuery)this.databaseQuery).getInternalMax();
                    // Bug 501272
                    // Do not reset a Query's uninitialized first result index, unless the parameter is greater than 0 (default for ReadQuery).
                    int queryFirstResult = ((ReadQuery)this.databaseQuery).getFirstResult();
                    if ((this.firstResultIndex != UNDEFINED) || (this.firstResultIndex == UNDEFINED && queryFirstResult > 0)) {
                        this.firstResultIndex = queryFirstResult;
                    }
                }
            } else {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unable_to_find_named_query", new Object[] { this.queryName }));
            }

        }

        return this.databaseQuery;
    }

    /**
     * Given a DatabaseException, this method will determine if we should
     * throw a different more specific exception like a lock timeout exception.
     */
    protected RuntimeException getDetailedException(DatabaseException e) {
        // If we catch a database exception as a result of executing a
        // pessimistic locking query we need to ask the platform which
        // JPA 2.0 locking exception we should throw. It will be either
        // be a PessimisticLockException or a LockTimeoutException (if
        // the query was executed using a wait timeout value)
        if (this.lockMode != null && this.lockMode.name().contains(ObjectLevelReadQuery.PESSIMISTIC_)) {
            // ask the platform if it is a lock timeout
            if (getActiveSession().getPlatform().isLockTimeoutException(e)) {
                return new LockTimeoutException(e);
            } else {
                return new PessimisticLockException(e);
            }
        } else {
            setRollbackOnly();
            return new PersistenceException(e);
        }
    }

    /**
     * Return the entityManager this query is tied to.
     */
    public JpaEntityManager getEntityManager() {
        return entityManager;
    }

    /**
     * Return the internal map of parameters.
     */
    protected Map<String, Parameter<?>> getInternalParameters() {
        if (this.parameters == null) {
            this.parameters = new HashMap<String, Parameter<?>>();
            DatabaseQuery query = getDatabaseQueryInternal(); // Retrieve named
                                                              // query
            int count = 0;
            if (query.getArguments() != null && !query.getArguments().isEmpty()) {
                boolean checkParameterType = query.getArgumentParameterTypes().size() == query.getArguments().size();
                for (String argName : query.getArguments()) {
                    Parameter<?> param = null;
                    ParameterType type = null;
                    if (checkParameterType){
                        type = query.getArgumentParameterTypes().get(count);
                    }
                    if (type == ParameterType.POSITIONAL){
                        Integer position = Integer.parseInt(argName);
                        param = new ParameterExpressionImpl(null, query.getArgumentTypes().get(count), position);
                    } else {
                        param = new ParameterExpressionImpl(null, query.getArgumentTypes().get(count), argName);
                    }
                    this.parameters.put(argName, param);
                    ++count;
                }
            }

        }

        return this.parameters;
    }

    /**
     * Get the current lock mode for the query.
     *
     * @return lock mode
     * @throws IllegalStateException
     *             if not a Java Persistence query language SELECT query
     */
    public LockModeType getLockMode() {
        entityManager.verifyOpen();

        if (!getDatabaseQueryInternal().isObjectLevelReadQuery()) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("invalid_lock_query", null));
        }

        return this.lockMode;
    }

    /**
     * Execute the query and return the query results as a List.
     *
     * @return a list of the results
     */
    public List getResultList() {
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            setAsSQLReadQuery();
            propagateResultProperties();
            // bug:4297903, check container policy class and throw exception if
            // its not the right type
            DatabaseQuery query = getDatabaseQueryInternal();
            if (query.isReadAllQuery()) {
                Class containerClass = ((ReadAllQuery) query).getContainerPolicy().getContainerClass();
                if (!Helper.classImplementsInterface(containerClass, ClassConstants.List_Class)) {
                    throw QueryException.invalidContainerClass(containerClass, ClassConstants.List_Class);
                }
            } else if (query.isReadObjectQuery()) {
                List<Object> resultList = new ArrayList<>();
                Object result = executeReadQuery();
                if (result != null) {
                    resultList.add(result);
                }
                return resultList;
            } else if (!query.isReadQuery()) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_result_list"));
            }
            return (List) executeReadQuery();
        } catch (LockTimeoutException exception) {
            throw exception;
        } catch (PersistenceException exception) {
            setRollbackOnly();
            throw exception;
        } catch (IllegalStateException exception) {
            setRollbackOnly();
            throw exception;
        } catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        }
    }

    /**
     * Execute a SELECT query that returns a single untyped result.
     *
     * @return the result
     * @throws NoResultException if there is no result
     * @throws NonUniqueResultException if more than one result
     * @throws IllegalStateException if called for a Java Persistence query
     *         language UPDATE or DELETE statement
     * @throws QueryTimeoutException if the query execution exceeds the query
     *         timeout value set and only the statement is rolled back
     * @throws TransactionRequiredException if a lock mode other than NONE has
     *         been been set and there is no transaction or the persistence
     *         context has not been joined to the transaction
     * @throws PessimisticLockException if pessimistic locking fails and the
     *         transaction is rolled back
     * @throws LockTimeoutException if pessimistic locking fails and only the
     *         statement is rolled back
     * @throws PersistenceException if the query execution exceeds the query
     *         timeout value set and the transaction is rolled back
     */
    public Object getSingleResult() {
        boolean rollbackOnException = true;
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            setAsSQLReadQuery();
            propagateResultProperties();
            // This API is used to return non-List results, so no other validation is done.
            // It could be Cursor or other Collection or Map type.
            if (!(getDatabaseQueryInternal().isReadQuery())) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_single_result"));
            }
            Object result = executeReadQuery();
            if (result instanceof List) {
                List results = (List) result;
                if (results.isEmpty()) {
                    rollbackOnException = false;
                    throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
                } else if (results.size() > 1) {
                    rollbackOnException = false;
                    throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null));
                }
                return results.get(0);
            } else {
                if (result == null) {
                    rollbackOnException = false;
                    throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
                }
                return result;
            }
        } catch (LockTimeoutException exception) {
            throw exception;
        } catch (PersistenceException exception) {
            if (rollbackOnException) {
                setRollbackOnly();
            }
            throw exception;
        } catch (IllegalStateException exception) {
            setRollbackOnly();
            throw exception;
        } catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        }
    }

    /**
     * Internal method to add the parameters values to the query prior to
     * execution. Returns a list of parameter values in the order the parameters
     * are defined for the databaseQuery.
     */
    protected List<Object> processParameters() {
        DatabaseQuery query = getDatabaseQueryInternal();
        List<String> arguments = query.getArguments();
        if (arguments.isEmpty()) {
            // This occurs for native queries, as the query does not know of its arguments.
            // This may have issues, it is better if the query set its arguments
            // when parsing the SQL.

            arguments = new ArrayList<>(this.parameterValues.keySet());
            query.setArguments(arguments);
        }
        // now create parameterValues in the same order as the argument list
        int size = arguments.size();
        List<Object> parameterValues = new ArrayList<Object>(size);
        for (int index = 0; index < size; index++) {
            String name = arguments.get(index);
            Object parameter = this.parameterValues.get(name);
            if ((parameter != null) || this.parameterValues.containsKey(name)) {
                parameterValues.add(parameter);
            } else if (query.hasNullableArguments() && query.getNullableArguments().contains(new DatabaseField(name))) {
                parameterValues.add(null);
            } else {
                // Error: missing actual parameter value
                throw new IllegalStateException(ExceptionLocalization.buildMessage("missing_parameter_value", new Object[] { name }));
            }
        }
        return parameterValues;
    }

    /**
     * Replace the cached query with the given query.
     */
    public void setDatabaseQuery(DatabaseQuery query) {
        databaseQuery = query;
    }

    /**
     * Set the position of the first result to retrieve.
     *
     * @param startPosition
     *            position of the first result, numbered from 0
     * @return the same query instance
     */
    public QueryImpl setFirstResult(int startPosition) {
        try {
            entityManager.verifyOpen();
            setFirstResultInternal(startPosition);
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * @see jakarta.persistence.Query#getFirstResult()
     * @since Java Persistence API 2.0
     */
    public int getFirstResult() {
        entityManager.verifyOpenWithSetRollbackOnly();
        if (this.firstResultIndex == UNDEFINED) {
            return 0;
        }
        return this.firstResultIndex;
    }

    /**
     * Set the flush mode type to be used for the query execution.
     *
     */
    public QueryImpl setFlushMode(FlushModeType flushMode) {
        try {
            entityManager.verifyOpen();
            if (flushMode == null) {
                getDatabaseQueryInternal().setFlushOnExecute(null);
            } else {
                cloneSharedQuery();
                getDatabaseQueryInternal().setFlushOnExecute(flushMode == FlushModeType.AUTO);
            }
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * Set the position of the first result to retrieve.
     *
     * @param startPosition
     *            position of the first result, numbered from 0.
     */
    protected void setFirstResultInternal(int startPosition) {
        if (startPosition < 0) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("negative_start_position", null));
        }
        // bug 362804
        firstResultIndex = startPosition;
    }

    /**
     * Define the query arguments based on the procedure call.
     */
    protected static void applyArguments(StoredProcedureCall call, DatabaseQuery query) {
        if (call instanceof PLSQLStoredProcedureCall) {
            PLSQLStoredProcedureCall plsqlCall = (PLSQLStoredProcedureCall)call;
            for (int index = 0; index < plsqlCall.getArguments().size(); index++) {
                PLSQLargument argument = plsqlCall.getArguments().get(index);
                int type = argument.direction;
                if ((type == StoredProcedureCall.IN) || (type == StoredProcedureCall.INOUT)) {
                    if (call.hasOptionalArguments()) {
                        query.addArgument(argument.name, Object.class, call.getOptionalArguments().contains(new DatabaseField(argument.name)));
                    } else {
                        query.addArgument(argument.name);
                    }
                }
            }
        } else {
            for (int index = 0; index < call.getParameters().size(); index++) {
                int type = call.getParameterTypes().get(index);
                if ((type == StoredProcedureCall.IN) || (type == StoredProcedureCall.INOUT)) {
                    Object value = call.getParameters().get(index);
                    DatabaseField parameter = null;
                    if (value instanceof Object[]) {
                        parameter = (DatabaseField) ((Object[])value)[0];
                    } else {
                        parameter = (DatabaseField)call.getParameters().get(index);
                    }
                    if (call.hasOptionalArguments()) {
                        query.addArgument(parameter.getName(), Object.class, call.getOptionalArguments().contains(parameter));
                    } else {
                        query.addArgument(parameter.getName());
                    }
                }
            }
        }
    }

    /**
     * Set implementation-specific hints.
     *
     * @param hints
     *            a list of hints to be applied to the query
     * @param query
     *            the query to apply the hints to
     */
    protected static DatabaseQuery applyHints(Map<String, Object> hints, DatabaseQuery query, ClassLoader classLoader, AbstractSession session) {
        return QueryHintsHandler.apply(hints, query, classLoader, session);
    }


    /**
     * Return the identifier of this parameter.  This will be the name if it is set, else it will be the position
     */
    public static String getParameterId(Parameter param){
        Integer id= param.getPosition();
        if (id == null ){
            return String.valueOf(((ParameterExpressionImpl)param).getInternalName());
        }
        return String.valueOf(id);
    }

    /**
     * Return a boolean indicating whether a value has been bound to the
     * parameter.
     *
     * @param param
     *            parameter object
     * @return boolean indicating whether parameter has been bound
     */
    public boolean isBound(Parameter<?> param) {
        entityManager.verifyOpenWithSetRollbackOnly();
        if (param == null)
            return false;
        return this.parameterValues.containsKey(getParameterId(param));
    }

    /**
     * Spec. 3.5.2: "FlushMode.AUTO is set on the Query object, or if the flush
     * mode setting for the persistence context is AUTO (the default) and a
     * flush mode setting has not been specified for the Query object, the
     * persistence provider is responsible for ensuring that all updates to the
     * state of all entities in the persistence context which could potentially
     * affect the result of the query are visible to the processing of the
     * query."
     */
    protected boolean isFlushModeAUTO() {
        if (getDatabaseQueryInternal().getFlushOnExecute() != null) {
            return getDatabaseQueryInternal().getFlushOnExecute();
        } else {
            return entityManager.isFlushModeAUTO();
        }
    }

    /**
     * Set an implementation-specific hint. If the hint name is not recognized,
     * it is silently ignored.
     *
     * @throws IllegalArgumentException
     *             if the second argument is not valid for the implementation.
     */
    protected void setHintInternal(String hintName, Object value) {
        cloneSharedQuery();
        ClassLoader loader = getEntityManager().getAbstractSession().getLoader();
        DatabaseQuery hintQuery = QueryHintsHandler.apply(hintName, value, getDatabaseQueryInternal(), loader, (AbstractSession) getActiveSession());
        if (hintQuery != null) {
            setDatabaseQuery(hintQuery);
        }
    }

    /**
     * Set the lock mode type to be used for the query execution.
     *
     * @throws IllegalStateException
     *             if not a Java Persistence query language SELECT query
     */
    public QueryImpl setLockMode(LockModeType lockMode) {
        try {
            entityManager.verifyOpen();

            if (!getDatabaseQueryInternal().isObjectLevelReadQuery()) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("invalid_lock_query", null));
            }

            this.lockMode = lockMode;
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * If the query was from the jpql parse cache it must be cloned before being
     * modified.
     */
    protected void cloneSharedQuery() {
        DatabaseQuery query = getDatabaseQueryInternal();
        if (this.isShared) {
            // Clone to allow setting of hints or other properties without
            // corrupting original query.
            query = (DatabaseQuery) databaseQuery.clone();
            setDatabaseQuery(query);
            this.isShared = false;
        }
    }

    /**
     * Convert the given object to the class represented by the given temporal
     * type.
     *
     * @return an object representing the given TemporalType.
     */
    protected Object convertTemporalType(Object value, TemporalType type) {
        ConversionManager conversionManager = getEntityManager().getActiveSession().getDatasourcePlatform().getConversionManager();
        if (type == TemporalType.TIME) {
            return conversionManager.convertObject(value, ClassConstants.TIME);
        } else if (type == TemporalType.TIMESTAMP) {
            return conversionManager.convertObject(value, ClassConstants.TIMESTAMP);
        } else if (type == TemporalType.DATE) {
            return conversionManager.convertObject(value, ClassConstants.SQLDATE);
        }
        return value;
    }

    /**
     * Set the maximum number of results to retrieve.
     *
     * @return the same query instance
     */
    public QueryImpl setMaxResults(int maxResult) {
        try {
            entityManager.verifyOpen();
            setMaxResultsInternal(maxResult);
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * @see jakarta.persistence.Query#getMaxResults()
     * @since Java Persistence API 2.0
     */
    public int getMaxResults() {
        entityManager.verifyOpenWithSetRollbackOnly();
        if (this.maxResults == UNDEFINED) {
            return Integer.MAX_VALUE;
        }
        return this.maxResults;
    }

    /**
     * @see jakarta.persistence.Query#getMaxResults()
     * @since Java Persistence API 2.0
     */
    public int getMaxResultsInternal() {
        return this.maxResults;
    }

    /**
     * Set the maximum number of results to retrieve.
     *
     */
    public void setMaxResultsInternal(int maxResult) {
        if (maxResult < 0) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("negative_max_result", null));
        }
        if (maxResult == Integer.MAX_VALUE) {
            this.maxResults = UNDEFINED;
        } else {
            this.maxResults = maxResult;
        }
    }

    /**
     * Configure the firstResult, maxRows and lock mode in the EclipseLink
     * ReadQuery.
     */
    protected void propagateResultProperties() {
        DatabaseQuery databaseQuery = getDatabaseQueryInternal();
        if (databaseQuery.isReadQuery()) {
            ReadQuery readQuery = (ReadQuery) databaseQuery;
            if (maxResults >= 0) {
                cloneSharedQuery();
                readQuery = (ReadQuery) getDatabaseQueryInternal();
                int maxRows = maxResults + ((firstResultIndex >= 0) ? firstResultIndex : 0);
                readQuery.setMaxRows(maxRows);
            }
            if (firstResultIndex > UNDEFINED) {
                cloneSharedQuery();
                readQuery = (ReadQuery) getDatabaseQueryInternal();
                readQuery.setFirstResult(firstResultIndex);
            }
        }
    }

    /**
     * Bind an argument to a positional parameter.
     *
     */
    protected void setParameterInternal(int position, Object value) {
        setParameterInternal(String.valueOf(position), value, true);
    }

    /**
     * Bind an argument to a named or indexed parameter.
     *
     * @param name
     *            the parameter name
     * @param value
     *            to bind
     * @param isIndex
     *            defines if index or named
     */
    protected void setParameterInternal(String name, Object value, boolean isIndex) {
        DatabaseQuery query = getDatabaseQueryInternal();
        if (query.getQueryMechanism().isJPQLCallQueryMechanism()) { // only non native queries
            int index = query.getArguments().indexOf(name);
            if (index == -1) {
                if (isIndex) {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-index", new Object[] { name, query.getEJBQLString() }));
                } else {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-name", new Object[] { name, query.getEJBQLString() }));
                }
            }
            Class type = query.getArgumentTypes().get(index);
            if (!isValidActualParameter(value, type)) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-incorrect-parameter-type", new Object[] { name, value.getClass(), query.getArgumentTypes().get(index), query.getEJBQLString() }));
            }
        } else {
            // native queries start a 1 not 0.
            if (isIndex && name.equals("0")) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-index", new Object[] { name, query.getSQLString() }));
            }
        }
        this.parameterValues.put(name, value);
    }

    protected boolean isValidActualParameter(Object value, Class parameterType) {
        if (value == null) {
            return true;
        } else {
            return BasicTypeHelperImpl.getInstance().isAssignableFrom(parameterType, value.getClass());
        }
    }

    protected Session getActiveSession() {
        DatabaseQuery query = getDatabaseQueryInternal();
        // PERF: If read-only query, avoid creating unit of work and JTA transaction.
        if (query.isObjectLevelReadQuery() && ((ObjectLevelReadQuery) query).isReadOnly()) {
            return this.entityManager.getReadOnlySession();
        }
        return this.entityManager.getActiveSession();
    }

    protected void performPreQueryFlush() {
        if (this.entityManager.shouldFlushBeforeQuery()) {
            this.entityManager.flush();
        }
    }

    protected void setRollbackOnly() {
        entityManager.setRollbackOnly();
    }

    protected void throwNoResultException(String message) {
        throw new NoResultException(message);
    }

    protected void throwNonUniqueResultException(String message) {
        throw new NonUniqueResultException(message);
    }

    /**
     * @see Query#getFlushMode()
     * @since Java Persistence 2.0
     */
    public FlushModeType getFlushMode() {
        try {
            entityManager.verifyOpen();
            Boolean flushOnExecute = getDatabaseQueryInternal().getFlushOnExecute();
            if ((flushOnExecute == null) || flushOnExecute)
                return FlushModeType.AUTO;
            return FlushModeType.COMMIT;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * @see Query#getHints()
     * @since Java Persistence 2.0
     */
    public Map<String, Object> getHints() {
        entityManager.verifyOpenWithSetRollbackOnly();
        return (Map<String, Object>) getDatabaseQueryInternal().getProperty(QueryHintsHandler.QUERY_HINT_PROPERTY);
    }

    /**
     * @see Query#getParameter(String, Class)
     * @since Java Persistence 2.0
     */
    public <T> Parameter<T> getParameter(String name, Class<T> type) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter param = getInternalParameters().get(name);
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { name, this.databaseQuery }));
        } else if (param.getParameterType() != null && type != null && !type.isAssignableFrom(param.getParameterType())){
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { name, type }));
        }
        return param;
    }

    /**
     * @see Query#getParameter(int, Class)
     * @since Java Persistence 2.0
     */
    public <T> Parameter<T> getParameter(int position, Class<T> type) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter param = getInternalParameters().get(String.valueOf(position));
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_INDEX", new Object[] { position, this.databaseQuery }));
        } else if (param.getParameterType() != null && type != null && !type.isAssignableFrom(param.getParameterType())){
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { position, type }));
        }
        return param;
    }

    /**
     * @see Query#getParameter(String, Class)
     * @since Java Persistence 2.0
     */
    public Parameter<?> getParameter(String name) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter<?> param = getInternalParameters().get(name);
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { name, this.databaseQuery }));
        }
        return param;
    }

    /**
     * @see Query#getParameter(int, Class)
     * @since Java Persistence 2.0
     */
    public Parameter<?> getParameter(int position) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter<?> param = getInternalParameters().get(String.valueOf(position));
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_INDEX", new Object[] { position, this.databaseQuery }));
        }
        return param;
    }

    /**
     * @see Query#getParameterValue(Parameter)
     * @since Java Persistence 2.0
     */
    public <T> T getParameterValue(Parameter<T> param) {
        if (param == null)
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("PARAMETER_NILL_NOT_FOUND"));

        ParameterExpressionImpl<T> parameter = (ParameterExpressionImpl<T>) this.getInternalParameters().get(getParameterId(param));
        if (parameter == null || !parameter.getParameterType().equals(param.getParameterType())) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { param.toString(), this.databaseQuery }));
        }

        return (T) this.getParameterValue(getParameterId(param));
    }

    /**
     * Return the value bound to the named parameter.
     *
     * @return parameter value
     * @throws IllegalStateException
     *             if the parameter has not been been bound
     */
    public Object getParameterValue(String name) {
        entityManager.verifyOpen();//don't rollback transaction
        if (!getInternalParameters().containsKey(name)) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { name, this.databaseQuery }));
        }
        if (!this.parameterValues.containsKey(name)) { // must check for
            // key. get() would
            // return negative
            // for value == null.
            throw new IllegalStateException(ExceptionLocalization.buildMessage("NO_VALUE_BOUND", new Object[] { name }));
        }
        return this.parameterValues.get(name);
    }

    /**
     * Return the value bound to the positional parameter.
     *
     * @return parameter value
     * @throws IllegalStateException
     *             if the parameter has not been been bound
     */
    public Object getParameterValue(int position) {
        entityManager.verifyOpen();//don't rollback transaction
        String param = String.valueOf(position);

        if (!getInternalParameters().containsKey(param)) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("position_param_not_found", new Object[] { position }));
        }

        if (!this.parameterValues.containsKey(param)) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("position_bound_param_not_found", new Object[] { position }));
        }

        return this.parameterValues.get(param);
    }

    /**
     * @see Query#getParameters()
     * @since Java Persistence 2.0
     */
    public Set<Parameter<?>> getParameters() {
        entityManager.verifyOpen();//don't rollback transaction
        return new HashSet<>(getInternalParameters().values());
    }

    /**
     * @since Java Persistence 2.0
     */
    public Set<String> getSupportedHints() {
        return QueryHintsHandler.getSupportedHints();
    }

    /**
     * Unwrap the query into the JPA implementation classes/interfaces or the
     * underlying native EclipseLink query.
     *
     * @see Query#unwrap(Class)
     * @since Java Persistence 2.0
     */
    public <T> T unwrap(Class<T> cls) {
        if (cls.isAssignableFrom(this.getClass())) {
            // unwraps any proxy to Query, JPAQuery or EJBQueryImpl
            return (T) this;
        }
        if (cls.isAssignableFrom(getDatabaseQueryInternal().getClass())) {
            return (T) getDatabaseQueryInternal();
        }

        throw new PersistenceException(ExceptionLocalization.buildMessage("unable_to_unwrap_jpa", new String[]{Query.class.getName(), cls.getName()}));
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "(" + this.databaseQuery + ")";
    }
}

