/*
 * 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
//     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
//     07/13/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
//     09/27/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
package org.eclipse.persistence.queries;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.sessions.DatabaseRecord;

/**
 * <p><b>Purpose</b>:
 * Concrete class to perform read using raw SQL and the SQLResultSetMapping.
 *
 * <p><b>Responsibilities</b>:
 * Execute a selecting raw SQL string.
 * Returns a List of results.  Each item in the list will be another list
 * consisting of the expected populated return types in the order they were
 * specified in the SQLResultSetMapping
 *
 * @see SQLResultSetMapping
 * @author Gordon Yorke
 * @since TopLink Java Essentials
 */
public class ResultSetMappingQuery extends ObjectBuildingQuery {
    protected boolean isExecuteCall;
    protected boolean returnNameValuePairs = false;
    protected Vector resultRows;

    protected List<String> resultSetMappingNames = new ArrayList<>();
    protected List<SQLResultSetMapping> resultSetMappings = new ArrayList<>();

    /**
     * PUBLIC:
     * Initialize the state of the query.
     */
    public ResultSetMappingQuery() {
        super();
   }

    /**
     * PUBLIC:
     * Initialize the query to use the specified call.
     */
    public ResultSetMappingQuery(Call call) {
        this();
        setCall(call);
    }

    /**
     * PUBLIC:
     * Initialize the query to use the specified call and SQLResultSetMapping
     */
    public ResultSetMappingQuery(Call call, String sqlResultSetMappingName) {
        this();
        setCall(call);
        this.resultSetMappingNames.add(sqlResultSetMappingName);
    }

    /**
     * PUBLIC:
     * This will be the SQLResultSetMapping that is used by this query to process
     * the database results
     */
    public void addSQLResultSetMapping(SQLResultSetMapping resultSetMapping){
        this.resultSetMappings.add(resultSetMapping);
        this.resultSetMappingNames.add(resultSetMapping.getName());
    }

    /**
     * PUBLIC:
     * Add a SQLResultSetMapping that is used by this query to process the
     * database results.
     */
    public void addSQLResultSetMappingName(String name){
        if (name == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_sqlresultsetmapping_in_query"));
        }

        this.resultSetMappingNames.add(name);
    }

    /**
     * INTERNAL:
     * <P> This method is called by the object builder when building an original.
     * It will cause the original to be cached in the query results if the query
     * is set to do so.
     */
    @Override
    public void cacheResult(Object unwrappedOriginal) {
        Object cachableObject = unwrappedOriginal;
        if (shouldUseWrapperPolicy()){
            cachableObject = getSession().wrapObject(unwrappedOriginal);
        }
        setTemporaryCachedQueryResults(cachableObject);
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this ResultSetMapping to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        for (SQLResultSetMapping mapping : this.resultSetMappings) {
            mapping.convertClassNamesToClasses(classLoader);
        }
    }

    /**
     * Indicates whether or not to return populated DatabaseRecord(s)
     * as opposed to raw data when an SQLResultSetMapping is not set.
     */
    public boolean shouldReturnNameValuePairs() {
        return returnNameValuePairs;
    }

    /**
     * Set the flag that indicates whether or not to return populated
     * DatabaseRecord(s) as opposed to raw data when an
     * SQLResultSetMapping is not set.
     */
    public void setShouldReturnNameValuePairs(boolean returnNameValuePairs) {
        this.returnNameValuePairs = returnNameValuePairs;
    }

    /**
     * PUBLIC:
     * This will be the SQLResultSetMapping that is used by this query to process
     * the database results
     */
    public void setSQLResultSetMapping(SQLResultSetMapping resultSetMapping) {
        addSQLResultSetMapping(resultSetMapping);
    }

    /**
     * PUBLIC:
     * This will be the SQLResultSetMappings that are used by this query to
     * process the database results
     */
    public void setSQLResultSetMappings(List<SQLResultSetMapping> resultSetMappings) {
        this.resultSetMappings = resultSetMappings;
    }

    /**
     * PUBLIC:
     * This will be the SQLResultSetMapping that is used by this query to process
     * the database results
     */
    public void setSQLResultSetMappingName(String name) {
        addSQLResultSetMappingName(name);
    }

    /**
     * PUBLIC:
     * This will be the SQLResult
     */
    public void setSQLResultSetMappingNames(List<String> names) {
        if (names.isEmpty()) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_sqlresultsetmapping_in_query"));
        }

        this.resultSetMappingNames = names;
    }

    /**
     * INTERNAL:
     * This method is used to build the results. Interpreting the
     * SQLResultSetMapping(s).
     */
    public List buildObjectsFromRecords(List databaseRecords){
        if (getSQLResultSetMappings().size() > 1) {
            int numberOfRecords = databaseRecords.size();
            List results = new ArrayList(numberOfRecords);

            for (int recordIndex = 0; recordIndex < numberOfRecords; recordIndex++) {
                Object records = databaseRecords.get(recordIndex);

                if (records instanceof Map) {
                    // We have a map keyed on named ref_cursors
                    Map recordsMap = (Map) records;

                    for (Object list : recordsMap.values()) {
                        results.add(buildObjectsFromRecords((List) list, getSQLResultSetMappings().get(recordIndex)));
                        recordIndex++;
                    }
                } else {
                    // Regular list of records, iterate through them.
                    results.add(buildObjectsFromRecords((List) records, getSQLResultSetMappings().get(recordIndex)));
                }
            }

            return results;
        } else {
            return buildObjectsFromRecords(databaseRecords, getSQLResultSetMapping());
        }
    }

    /**
     * INTERNAL:
     * This method is used to build the results with the SQLResultSetMapping
     * at the given index.
     */
    public List buildObjectsFromRecords(List databaseRecords, int index){
        if (getSQLResultSetMappings().isEmpty()) {
            return buildObjectsFromRecords(databaseRecords, null);
        } else {
            return buildObjectsFromRecords(databaseRecords, getSQLResultSetMappings().get(index));
        }
    }

    /**
     * INTERNAL:
     * This method is used to build the results. Interpreting the SQLResultSetMapping.
     */
    protected List buildObjectsFromRecords(List databaseRecords, SQLResultSetMapping mapping) {
        int numberOfRecords = databaseRecords.size();
        List results = new ArrayList(numberOfRecords);

        if (mapping == null) {
            if (shouldReturnNameValuePairs()) {
                return databaseRecords;
            }
            for (Iterator iterator = databaseRecords.iterator(); iterator.hasNext();) {
                DatabaseRecord record = (DatabaseRecord)iterator.next();
                results.add(record.values().toArray());
            }
        } else {
            for (Iterator iterator = databaseRecords.iterator(); iterator.hasNext();) {
                if (mapping.getResults().size() > 1) {
                    Object[] resultElement = new Object[mapping.getResults().size()];
                    DatabaseRecord record = (DatabaseRecord)iterator.next();
                    for (int i = 0; i < mapping.getResults().size(); i++) {
                        resultElement[i] = mapping.getResults().get(i).getValueFromRecord(record, this);
                    }
                    results.add(resultElement);
                } else if (mapping.getResults().size() == 1) {
                    DatabaseRecord record = (DatabaseRecord)iterator.next();
                    results.add(mapping.getResults().get(0).getValueFromRecord(record, this));
                } else {
                    return results;
                }
            }
        }

        return results;
    }

    /**
     * INTERNAL:
     * Executes the prepared query on the datastore.
     */
    @Override
    public Object executeDatabaseQuery() throws DatabaseException {
        if (getSession().isUnitOfWork()) {
            UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)getSession();

            // Note if a nested unit of work this will recursively start a
            // transaction early on the parent also.
            if (isLockQuery()) {
                if ((!unitOfWork.getCommitManager().isActive()) && (!unitOfWork.wasTransactionBegunPrematurely())) {
                    unitOfWork.beginTransaction();
                    unitOfWork.setWasTransactionBegunPrematurely(true);
                }
            }
            if (unitOfWork.isNestedUnitOfWork()) {
                // execute in parent UOW then register normally here.
                UnitOfWorkImpl nestedUnitOfWork = (UnitOfWorkImpl)getSession();
                setSession(nestedUnitOfWork.getParent());
                Object result = executeDatabaseQuery();
                setSession(nestedUnitOfWork);
                Object clone = registerIndividualResult(result, null, unitOfWork, null, null);

                if (shouldUseWrapperPolicy()) {
                    clone = getDescriptor().getObjectBuilder().wrapObject(clone, unitOfWork);
                }
                return clone;
            }
        }
        session.validateQuery(this);// this will update the query with any settings

        if (getQueryId() == 0) {
            setQueryId(getSession().getNextQueryId());
        }

        if (getCall().isExecuteUpdate()) {
            DatabaseCall call = ((StoredProcedureCall) getQueryMechanism().execute());
            setExecutionTime(System.currentTimeMillis());
            return call;
        } else {
            Vector rows = getQueryMechanism().executeSelect();
            setExecutionTime(System.currentTimeMillis());
            // If using 1-m joins, must set all rows.
            return buildObjectsFromRecords(rows);
        }
    }

    /**
     * PUBLIC:
     * Return true if there are results set mappings associated with this query.
     */
    public boolean hasResultSetMappings() {
        return ! getSQLResultSetMappings().isEmpty();
    }

    /**
     * PUBLIC: Return true if this is a result set mapping query.
     */
    @Override
    public boolean isResultSetMappingQuery() {
        return true;
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    @Override
    protected void prepare() {
        if ((!shouldMaintainCache()) && shouldRefreshIdentityMapResult()) {
            throw QueryException.refreshNotPossibleWithoutCache(this);
        }

        getQueryMechanism().prepare();

        if (isExecuteCall) {
            getQueryMechanism().prepareExecute();
        } else {
            getQueryMechanism().prepareExecuteSelect();
        }
    }

    /**
     * PUBLIC:
     * This will be the SQLResultSetMapping that is used by this query to process
     * the database results
     */
    public SQLResultSetMapping getSQLResultSetMapping() {
        if (resultSetMappings.isEmpty()) {
            if (resultSetMappingNames.isEmpty()) {
                return null;
            } else {
                return getSession().getProject().getSQLResultSetMapping(resultSetMappingNames.get(0));
            }
        }

        return resultSetMappings.get(0);
    }

    /**
     * PUBLIC:
     * This will be the SQLResultSetMapping that is used by this query to process
     * the database results
     */
    public List<SQLResultSetMapping> getSQLResultSetMappings() {
        if (this.resultSetMappings.isEmpty()) {
            ArrayList<SQLResultSetMapping> list = new ArrayList<>();
            for (String resultSetMappingName : this.resultSetMappingNames) {
                list.add(getSession().getProject().getSQLResultSetMapping(resultSetMappingName));
            }

            return list;
        } else {
            return resultSetMappings;
        }
    }

    /**
     * PUBLIC:
     * Return the result set mapping name.
     */
    public String getSQLResultSetMappingName() {
        return this.resultSetMappingNames.get(0);
    }

    /**
     * PUBLIC:
     * Return the result set mapping name.
     */
    public List<String> getSQLResultSetMappingNames() {
        return this.resultSetMappingNames;
    }

    /**
     * PUBLIC:
     * Set to true if you the actual jdbc result set returned from query
     * execution. This will unprepare the query in case it was executed
     * previously for a getResultList() call instead (or vice versa)
     */
    public void setIsExecuteCall(boolean isExecuteCall) {
        this.isExecuteCall = isExecuteCall;

        // Force the query to prepare.
        setIsPrepared(false);
    }
}
