/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2019, 2020 IBM Corporation. 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
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
//     10/01/2018: Will Dazey
//       - #253: Add support for embedded constructor results with CriteriaBuilder
package org.eclipse.persistence.queries;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.internal.expressions.FunctionExpression;
import org.eclipse.persistence.internal.expressions.MapEntryExpression;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.NonSynchronizedSubVector;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.queries.ReportItem;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.Association;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Session;

/**
 * <b>Purpose</b>: A single row (type) result for a ReportQuery<p>
 *
 * <b>Description</b>: Represents a single row of attribute values (converted using mapping) for
 * a ReportQuery. The attributes can be from various objects.
 *
 * <b>Responsibilities</b>:<ul>
 * <li> Converted field values into object attribute values.
 * <li> Provide access to values by index or item name
 * </ul>
 *
 * @author Doug Clarke
 * @since TOPLink/Java 2.0
 */
public class ReportQueryResult implements Serializable, Map {

    /** Item names to lookup result values */
    protected List<String> names;

    /** Actual converted attribute values */
    protected List<Object> results;

    /** Id value if the retrievPKs flag was set on the ReportQuery. These can be used to get the actual object */
    protected Object primaryKey;

    /** If an objectLevel distinct is used then generate unique key for this result */
    // GF_ISSUE_395
    protected StringBuffer key;

    /**
     * INTERNAL:
     * Used to create test results
     */
    public ReportQueryResult(List<Object> results, Object primaryKeyValues) {
        this.results = results;
        this.primaryKey = primaryKeyValues;
    }

    public ReportQueryResult(ReportQuery query, AbstractRecord row, Vector toManyResults) {
        super();
        this.names = query.getNames();
        buildResult(query, row, toManyResults);
    }

    /**
     * INTERNAL:
     * Create an array of attribute values (converted from raw field values using the mapping).
     */
    protected void buildResult(ReportQuery query, AbstractRecord row, Vector toManyData) {
        // GF_ISSUE_395
        if (query.shouldDistinctBeUsed() && (query.shouldFilterDuplicates())) {
            this.key = new StringBuffer();
        }

        if (query.shouldRetrievePrimaryKeys()) {
            setId(query.getDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(row, query.getSession()));
            // For bug 3115576 this is only used for EXISTS sub-selects so no result is needed.
        }

        List<Object> results = new ArrayList<>();
        for(ReportItem item: query.getItems()) {
            if (item.isConstructorItem()) {
                Object result = processConstructorItem(query, row, toManyData, (ConstructorReportItem) item);
                results.add(result);
            } else if (item.getAttributeExpression() != null && item.getAttributeExpression().isClassTypeExpression()) {
                Object value = processItem(query, row, toManyData, item);
                ClassDescriptor descriptor = ((org.eclipse.persistence.internal.expressions.ClassTypeExpression)item.getAttributeExpression()).getContainingDescriptor(query);
                if (descriptor != null && descriptor.hasInheritance()) {
                    value = descriptor.getInheritancePolicy().classFromValue(value, query.getSession());
                } else {
                    value = query.getSession().getDatasourcePlatform().convertObject(value, Class.class);
                }
                results.add(value);
            } else {
                // Normal items
                Object value = processItem(query, row, toManyData, item);
                results.add(value);
            }
        }

        setResults(results);
    }

    private Object processConstructorItem(ReportQuery query, AbstractRecord row, Vector toManyData, ConstructorReportItem constructorItem) {
        // For constructor items need to process each constructor argument.
        Class[] constructorArgTypes = constructorItem.getConstructorArgTypes();
        int numberOfArguments = constructorItem.getReportItems().size();
        Object[] constructorArgs = new Object[numberOfArguments];

        for (int argumentIndex = 0; argumentIndex < numberOfArguments; argumentIndex++) {
            ReportItem argumentItem = constructorItem.getReportItems().get(argumentIndex);
            Object result = null;
            if(argumentItem.isConstructorItem()) {
                result = processConstructorItem(query, row, toManyData, (ConstructorReportItem) argumentItem);
            } else {
                result = processItem(query, row, toManyData, argumentItem);
            }
            constructorArgs[argumentIndex] = ConversionManager.getDefaultManager().convertObject(result, constructorArgTypes[argumentIndex]);
        }
        try {
            Constructor constructor = constructorItem.getConstructor();
            Object returnValue = null;
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    returnValue = AccessController.doPrivileged(new PrivilegedInvokeConstructor(constructor, constructorArgs));
                } catch (PrivilegedActionException exception) {
                    throw QueryException.exceptionWhileUsingConstructorExpression(exception.getException(), query);
                }
            } else {
                returnValue = PrivilegedAccessHelper.invokeConstructor(constructor, constructorArgs);
            }
            return returnValue;
        } catch (ReflectiveOperationException exc) {
            throw QueryException.exceptionWhileUsingConstructorExpression(exc, query);
        }
    }

    private Object processItemFromMapping(ReportQuery query, AbstractRecord row, DatabaseMapping mapping, ReportItem item, int itemIndex) {
        Object value = null;

        // If mapping is not null then it must be a direct mapping - see Reportitem.init.
        // Check for non database (EIS) records to use normal get.
        if (row instanceof DatabaseRecord) {
            value = row.getValues().get(itemIndex);
        } else {
            value = row.get(mapping.getField());
        }

        //Bug 421056: JPA 2.1; section 4.8.5
        if(item.getAttributeExpression().isFunctionExpression()) {
            FunctionExpression exp = (FunctionExpression) item.getAttributeExpression();
            int selector = exp.getOperator().getSelector();
            //a value of null for max/min implies no rows could be applied
            //we want to return null, per the spec, here before the mapping gets to alter the value
            if (value == null && ((selector == ExpressionOperator.Maximum) || (selector == ExpressionOperator.Minimum))) {
                return value;
            }
        }

        //If the mapping was set on the ReportItem, then use the mapping to convert the value
        if (mapping.isAbstractColumnMapping()) {
            value = ((AbstractColumnMapping)mapping).getObjectValue(value, query.getSession());
        } else if (mapping.isDirectCollectionMapping()) {
            value = ((DirectCollectionMapping)mapping).getObjectValue(value, query.getSession());
        }
        return value;
    }

    /**
     * INTERNAL:
     * Return a value from an item and database row (converted from raw field values using the mapping).
     */
    protected Object processItem(ReportQuery query, AbstractRecord row, Vector toManyData, ReportItem item) {
        JoinedAttributeManager joinManager = null;
        if (item.hasJoining()) {
            joinManager = item.getJoinedAttributeManager();
            if (joinManager.isToManyJoin()) {
                // PERF: Only reset data-result if unset, must only occur once per item, not per row (n vs n^2).
                if (joinManager.getDataResults_() == null) {
                    joinManager.setDataResults(new ArrayList(toManyData), query.getSession());
                }
            }
        }

        Object value = null;
        int rowSize = row.size();
        int itemIndex = item.getResultIndex();

        DatabaseMapping mapping = item.getMapping();
        ClassDescriptor descriptor = item.getDescriptor();

        if (item.getAttributeExpression() != null) {
            if (descriptor == null && mapping != null) {
                descriptor = mapping.getReferenceDescriptor();
            }
            if (mapping != null && (mapping.isAbstractColumnMapping() || mapping.isDirectCollectionMapping())) {

                if (itemIndex >= rowSize) {
                    throw QueryException.reportQueryResultSizeMismatch(itemIndex + 1, rowSize);
                }

                value = processItemFromMapping(query, row, mapping, item, itemIndex);

                // GF_ISSUE_395+
                if (this.key != null) {
                    this.key.append(value);
                    this.key.append("_");
                }
            } else if (descriptor != null) {
                // Item is for an object result.
                int size = descriptor.getAllSelectionFields(query).size();
                if (itemIndex + size > rowSize) {
                    throw QueryException.reportQueryResultSizeMismatch(itemIndex + size, rowSize);
                }
                AbstractRecord subRow = row;
                // Check if at the start of the row, then avoid building a subRow.
                if (itemIndex > 0) {
                    Vector<DatabaseField> trimedFields = new NonSynchronizedSubVector<>(row.getFields(), itemIndex, rowSize);
                    Vector trimedValues = new NonSynchronizedSubVector(row.getValues(), itemIndex, rowSize);
                    subRow = new DatabaseRecord(trimedFields, trimedValues);
                }
                if (mapping != null && mapping.isAggregateObjectMapping()){
                    value = ((AggregateObjectMapping)mapping).buildAggregateFromRow(subRow, null, null, joinManager, query, false, query.getSession(), true);
                } else {
                    //TODO : Support prefrechedCacheKeys in report query
                    value = descriptor.getObjectBuilder().buildObject(query, subRow, joinManager);
                }

                // this covers two possibilities
                // 1. We want the actual Map.Entry from the table rather than the just the key
                // 2. The map key is extracted from the owning object rather than built with
                // a specific mapping.  This could happen in a MapContainerPolicy
                if (item.getAttributeExpression().isMapEntryExpression() && mapping.isCollectionMapping()){
                    Object rowKey = null;
                    if (mapping.getContainerPolicy().isMapPolicy() && !mapping.getContainerPolicy().isMappedKeyMapPolicy()){
                        rowKey = mapping.getContainerPolicy().keyFrom(value, query.getSession());
                    } else {
                        rowKey = mapping.getContainerPolicy().buildKey(subRow, query, null, query.getSession(), true);
                    }
                    if (((MapEntryExpression)item.getAttributeExpression()).shouldReturnMapEntry()){
                        value = new Association(rowKey, value);
                    } else {
                        value = rowKey;
                    }
                }
                // GF_ISSUE_395
                if (this.key != null) {
                    Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromRow(subRow, query.getSession());
                    if (primaryKey != null){//GF3233 NPE is caused by processing the null PK being extracted from referenced target with null values in database.
                        this.key.append(primaryKey);
                    }
                    this.key.append("_");
                }
            } else {
                value = row.getValues().get(itemIndex);
                // GF_ISSUE_395
                if (this.key != null) {
                    this.key.append(value);
                }
            }
        }
        return value;
    }

    /**
     * PUBLIC:
     * Clear the contents of the result.
     */
    @Override
    public void clear() {
        this.names = new ArrayList<>();
        this.results = new ArrayList<>();
    }

    /**
     * PUBLIC:
     * Check if the value is contained in the result.
     */
    public boolean contains(Object value) {
        return containsValue(value);
    }

    /**
     * PUBLIC:
     * Check if the key is contained in the result.
     */
    @Override
    public boolean containsKey(Object key) {
        return getNames().contains(key);
    }

    /**
     * PUBLIC:
     * Check if the value is contained in the result.
     */
    @Override
    public boolean containsValue(Object value) {
        return getResults().contains(value);
    }

    /**
     * PUBLIC:
     * Returns a set of the keys.
     */
    @Override
    public Set entrySet() {
        return new EntrySet();
    }


    /**
     * Defines the virtual entrySet.
     */
    protected class EntrySet extends AbstractSet {
        @Override
        public Iterator iterator() {
            return new EntryIterator();
        }
        @Override
        public int size() {
            return ReportQueryResult.this.size();
        }
        @Override
        public boolean contains(Object object) {
            if (!(object instanceof Entry)) {
                return false;
            }
            return ReportQueryResult.this.containsKey(((Entry)object).getKey());
        }
        @Override
        public boolean remove(Object object) {
            if (!(object instanceof Entry)) {
                return false;
            }
            ReportQueryResult.this.remove(((Entry)object).getKey());
            return true;
        }
        @Override
        public void clear() {
            ReportQueryResult.this.clear();
        }
    }

    /**
     * Entry class for implementing Map interface.
     */
    protected static class RecordEntry implements Entry {
        Object key;
        Object value;

        public RecordEntry(Object key, Object value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public Object getKey() {
            return key;
        }

        @Override
        public Object getValue() {
            return value;
        }

        @Override
        public Object setValue(Object value) {
            Object oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        @Override
        public boolean equals(Object object) {
            if (!(object instanceof Map.Entry)) {
                return false;
            }
            Map.Entry entry = (Map.Entry)object;
            return compare(key, entry.getKey()) && compare(value, entry.getValue());
        }

        @Override
        public int hashCode() {
            return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
        }

        @Override
        public String toString() {
            return key + "=" + value;
        }

        private boolean compare(Object object1, Object object2) {
            return (object1 == null ? object2 == null : object1.equals(object2));
        }
    }

    /**
     * Defines the virtual entrySet iterator.
     */
    protected class EntryIterator implements Iterator {
        int index;

        EntryIterator() {
            this.index = 0;
        }

        @Override
        public boolean hasNext() {
            return this.index < ReportQueryResult.this.size();
        }

        @Override
        public Object next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            this.index++;
            return new RecordEntry(getNames().get(this.index - 1), getResults().get(this.index - 1));
        }

        @Override
        public void remove() {
            if (this.index >= ReportQueryResult.this.size()) {
                throw new IllegalStateException();
            }
            ReportQueryResult.this.remove(getNames().get(this.index));
        }
    }

    /**
     * Defines the virtual keySet iterator.
     */
    protected class KeyIterator extends EntryIterator {
        @Override
        public Object next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            this.index++;
            return getNames().get(this.index - 1);
        }
    }

    /**
     * PUBLIC:
     * Compare if the two results are equal.
     */
    @Override
    public boolean equals(Object anObject) {
        if (anObject instanceof ReportQueryResult) {
            return equals((ReportQueryResult)anObject);
        }

        return false;
    }

    /**
     * INTERNAL:
     * Used in testing to compare if results are correct.
     */
    public boolean equals(ReportQueryResult result) {
        if (this == result) {
            return true;
        }
        if (!getResults().equals(result.getResults())) {
            return false;
        }

        // Compare PKs
        if (getId() != null) {
            if (result.getId() == null) {
                return false;
            }
            return getId().equals(getId());
        }

        return true;
    }

    @Override
    public int hashCode() {
        List<Object> results = getResults();
        Object id = getId();
        int result = results != null ? results.hashCode() : 0;
        result = 31 * result + (id != null ? id.hashCode() : 0);
        return result;
    }

    /**
     * PUBLIC:
     * Return the value for given item name.
     */
    @Override
    public Object get(Object name) {
        if (name instanceof String) {
            return get((String)name);
        }

        return null;
    }

    /**
     * PUBLIC:
     * Return the value for given item name.
     */
    public Object get(String name) {
        int index = getNames().indexOf(name);
        if (index == -1) {
            return null;
        }

        return getResults().get(index);
    }

    /**
     * PUBLIC:
     * Return the indexed value from result.
     */
    public Object getByIndex(int index) {
        return getResults().get(index);
    }

    /**
     * INTERNAL:
     * Return the unique key for this result
     */
    public String getResultKey(){
        if (this.key != null){
            return this.key.toString();
        }
        return null;
    }

    /**
     * PUBLIC:
     * Return the names of report items, provided to ReportQuery.
     */
    public List<String> getNames() {
        return names;
    }

    /**
     * PUBLIC:
     * Return the Id for the result or null if not requested.
     */
    public Object getId() {
        return primaryKey;
    }

    /**
     * PUBLIC:
     * Return the results.
     */
    public List<Object> getResults() {
        return results;
    }

    /**
     * PUBLIC:
     * Return if the result is empty.
     */
    @Override
    public boolean isEmpty() {
        return getNames().isEmpty();
    }

    /**
     * PUBLIC:
     * Returns a set of the keys.
     */
    @Override
    public Set keySet() {
        return new KeySet();
    }

    /**
     * Defines the virtual keySet.
     */
    protected class KeySet extends EntrySet {
        @Override
        public Iterator iterator() {
            return new KeyIterator();
        }
        @Override
        public boolean contains(Object object) {
        return ReportQueryResult.this.containsKey(object);
        }
        @Override
        public boolean remove(Object object) {
            return ReportQueryResult.this.remove(object) != null;
        }
    }

    /**
     * ADVANCED:
     * Set the value for given item name.
     */
    @Override
    public Object put(Object name, Object value) {
        int index = getNames().indexOf(name);
        if (index == -1) {
            getNames().add((String)name);
            getResults().add(value);
            return null;
        }

        Object oldValue = getResults().get(index);
        getResults().set(index, value);
        return oldValue;
    }

    /**
     * PUBLIC:
     * Add all of the elements.
     */
    @Override
    public void putAll(Map map) {
        Iterator entriesIterator = map.entrySet().iterator();
        while (entriesIterator.hasNext()) {
            Map.Entry entry = (Map.Entry)entriesIterator.next();
            put(entry.getKey(), entry.getValue());
        }
    }

    /**
     * PUBLIC:
     * If the PKs were retrieved with the attributes then this method can be used to read the real object from the database.
     */
    public Object readObject(Class javaClass, Session session) {
        if (getId() == null) {
            throw QueryException.reportQueryResultWithoutPKs(this);
        }

        ReadObjectQuery query = new ReadObjectQuery(javaClass);
        query.setSelectionId(getId());

        return session.executeQuery(query);
    }

    /**
     * INTERNAL:
     * Remove the name key and value from the result.
     */
    @Override
    public Object remove(Object name) {
        int index = getNames().indexOf(name);
        if (index >= 0) {
            getNames().remove(index);
            Object value = getResults().get(index);
            getResults().remove(index);
            return value;
        }
        return null;
    }

    protected void setNames(List<String> names) {
        this.names = names;
    }

    /**
     * INTERNAL:
     * Set the Id for the result row's object.
     */
    protected void setId(Object primaryKey) {
        this.primaryKey = primaryKey;
    }

    /**
     * INTERNAL:
     * Set the results.
     */
    public void setResults(List<Object> results) {
        this.results = results;
    }

    /**
     * PUBLIC:
     * Return the number of name/value pairs in the result.
     */
    @Override
    public int size() {
        return getNames().size();
    }

    /**
     * INTERNAL:
     * Converts the ReportQueryResult to a simple array of values.
     */
    public Object[] toArray(){
       List<Object> list = getResults();
       return (list == null) ? null : list.toArray();
    }

    /**
     * INTERNAL:
     * Converts the ReportQueryResult to a simple list of values.
     */
    public List toList(){
        return this.getResults();
    }

    @Override
    public String toString() {
        java.io.StringWriter writer = new java.io.StringWriter();
        writer.write("ReportQueryResult(");
        for (int index = 0; index < getResults().size(); index++) {
            Object resultObj = getResults().get(index);
            writer.write(String.valueOf(resultObj));
            writer.write(" <"
                         + (resultObj == null ? "null" : resultObj.getClass().getName())
                         + ">");
            if (index < (getResults().size() - 1)) {
                writer.write(", ");
            }
        }
        writer.write(")");
        return writer.toString();
    }

    /**
     * PUBLIC:
     * Returns an collection of the values.
     */
    @Override
    public Collection values() {
        return getResults();
    }
}
