/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2019 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
//     IBM - Bug 537795: CASE THEN and ELSE scalar expression Constants should not be casted to CASE operand type
package org.eclipse.persistence.internal.expressions;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.history.AsOfClause;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.queries.ReportItem;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.querykeys.ForeignReferenceQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.ReportQuery;

/**
 * Used for expressions that have 0 to n children.
 * These include not, between and all functions.
 */
public class FunctionExpression extends BaseExpression {
    protected Vector<Expression> children;
    protected ExpressionOperator operator;
    protected transient ExpressionOperator platformOperator;
    protected Class resultType;

    public FunctionExpression() {
        this.children = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(2);
        this.resultType = null;
    }

    /**
     * INTERNAL:
     * Return if the expression is equal to the other.
     * This is used to allow dynamic expression's SQL to be cached.
     * This must be over written by each subclass.
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (!super.equals(object)) {
            return false;
        }
        FunctionExpression expression = (FunctionExpression) object;
        if ((this.operator != expression.getOperator()) && ((this.operator == null) || (!this.operator.equals(expression.getOperator())))) {
            return false;
        }
        List<?> children = getChildren();
        List<?> otherChildren = expression.getChildren();
        int size = children.size();
        if (size != otherChildren.size()) {
            return false;
        }
        for (int index = 0; index < size; index++) {
            if (!children.get(index).equals(otherChildren.get(index))) {
                return false;
            }
        }
        return true;
    }

    /**
     * INTERNAL:
     * Compute a consistent hash-code for the expression.
     * This is used to allow dynamic expression's SQL to be cached.
     */
    @Override
    public int computeHashCode() {
        int hashCode = super.computeHashCode();
        if (this.operator != null) {
            hashCode = hashCode + this.operator.hashCode();
        }
        List<?> children = getChildren();
        int size = children.size();
        for (int index = 0; index < size; index++) {
            hashCode = hashCode + children.get(index).hashCode();
        }
        return hashCode;
    }

    public void addChild(Expression child) {
        getChildren().addElement(child);
    }

    /**
     * INTERNAL:
     * Find the alias for a given table
     */
    @Override
    public DatabaseTable aliasForTable(DatabaseTable table) {
        return getBaseExpression().aliasForTable(table);
    }

    @Override
    public Expression asOf(AsOfClause clause) {
        final AsOfClause finalClause = clause;
        ExpressionIterator iterator = new ExpressionIterator() {
            @Override
            public void iterate(Expression each) {
                if (each.isDataExpression()) {
                    each.asOf(finalClause);
                }
            }

            @Override
            public boolean shouldIterateOverSubSelects() {
                return true;
            }
        };
        iterator.iterateOn(this);
        return this;
    }

    /**
     * INTERNAL:
     */
    @Override
    public Expression create(Expression base, Object singleArgument, ExpressionOperator anOperator) {
        baseExpression = base;
        addChild(base);
        Expression localBase = base;
        if(anOperator.isFunctionOperator()) {
            ExpressionBuilder builder = getBuilder();
            if(builder != null) {
                localBase = builder;
            }
        }
        Expression arg = Expression.from(singleArgument, localBase);
        addChild(arg);
        setOperator(anOperator);
        return this;
    }

    /**
     * INTERNAL:
     * added for Trim support.  TRIM([trim_character FROM] string_primary)
     */
    @Override
    public Expression createWithBaseLast(Expression base, Object singleArgument, ExpressionOperator anOperator) {
        baseExpression = base;
        Expression localBase = base;
        if(anOperator.isFunctionOperator()) {
            ExpressionBuilder builder = getBuilder();
            if(builder != null) {
                localBase = builder;
            }
        }
        Expression arg = Expression.from(singleArgument, localBase);
        addChild(arg);
        addChild(base);
        setOperator(anOperator);
        return this;
    }

    /**
     * INTERNAL:
     */
    @Override
    public Expression create(Expression base, List arguments, ExpressionOperator anOperator) {
        this.baseExpression = base;
        setOperator(anOperator);
        addChild(base);
        Expression localBase = base;
        if (anOperator.isFunctionOperator()) {
            ExpressionBuilder builder = getBuilder();
            if (builder != null) {
                localBase = builder;
            }
        }
        for (Object argument : arguments) {
            Expression arg = Expression.from(argument, localBase);
            addChild(arg);
        }
        return this;
    }

    /**
     * INTERNAL:
     * Used for debug printing.
     */
    @Override
    public String descriptionOfNodeType() {
        return "Function";
    }

    /**
     * INTERNAL:
     * Check if the object conforms to the expression in memory.
     * This is used for in-memory querying.
     * If the expression in not able to determine if the object conform throw a not supported exception.
     */
    @Override
    public boolean doesConform(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean isObjectUnregistered) {
        int selector = this.operator.getSelector();

        // Must check for NOT and negate entire base expression.
        if (selector == ExpressionOperator.Not) {
            return !getBaseExpression().doesConform(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
        }

        // Conform between or in function.
        if ((selector == ExpressionOperator.Between) || (selector == ExpressionOperator.NotBetween)
                || (selector == ExpressionOperator.In) || (selector == ExpressionOperator.NotIn)
                || (selector == ExpressionOperator.Like) || (selector == ExpressionOperator.Regexp)
                || (selector == ExpressionOperator.NotLike)) {
            // Extract the value from the left side.
            Object leftValue = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);

            // Extract the value from the arguments, skip the first child which is the base.
            int size = this.children.size();
            Vector rightValue = new Vector(size);
            for (int index = 1; index < size; index++) {
                Object valueFromRight;
                Expression child = this.children.get(index);
                if (child instanceof Expression) {
                    valueFromRight = child.valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
                } else {
                    valueFromRight = child;
                }
                //If valueFromRight is a Vector, then there is only one child other than the base, e.g. valueFromRight is a collection of constants.
                //Then it should be the vector to be compared with.  Don't add it to another collection.
                if (valueFromRight instanceof Vector) {
                    rightValue = (Vector)valueFromRight;
                //Single values should be added to the rightValue, which will be compared with leftValue.
                } else {
                    rightValue.add(valueFromRight);
                }
            }

            // If left is anyof collection of values, check each one.
            // If the right had an anyof not supported will be thrown from the operator.
            if (leftValue instanceof Vector) {
                for (Object tempLeft : (Vector)leftValue) {
                    if (this.operator.doesRelationConform(tempLeft, rightValue)) {
                        return true;
                    }
                }

                // Only return false if none of the values match.
                return false;
            } else {
                return this.operator.doesRelationConform(leftValue, rightValue);
            }
        } else if ((selector == ExpressionOperator.IsNull) || (selector == ExpressionOperator.NotNull)) {
            // Extract the value from the left side.
            Object leftValue = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);

            // If left is anyof collection of values, check each one.
            if (leftValue instanceof Vector) {
                for (Object tempLeft : (Vector)leftValue) {
                    if (this.operator.doesRelationConform(tempLeft, null)) {
                        return true;
                    }
                }

                // Only return false if none of the values match.
                return false;
            } else {
                return this.operator.doesRelationConform(leftValue, null);
            }
        }

        // No other relation functions are supported.
        // Non-relation functions are supported through valueFromObject().
        throw QueryException.cannotConformExpression();
    }

    public Vector<Expression> getChildren() {
        return this.children;
    }

    /**
     * INTERNAL: Not to be confused with the public getField(String)
     * This returns a collection of all fields associated with this object. Really
     * only applies to query keys representing an object or to expression builders.
     *
     */
    @Override
    public List<DatabaseField> getFields() {
        return getBaseExpression().getFields();
    }

    /**
     * INTERNAL:
     */
    @Override
    public List<DatabaseField> getSelectionFields(ReadQuery query) {
        return getBaseExpression().getSelectionFields(query);
    }

    @Override
    public ExpressionOperator getOperator() {
        return operator;
    }

    public ExpressionOperator getPlatformOperator(DatabasePlatform platform) {
        if (platformOperator == null) {
            initializePlatformOperator(platform);
        }
        return platformOperator;
    }

    public Class getResultType() {
        return resultType;
    }

    public boolean hasResultType() {
        return resultType != null;
    }

    /**
     * INTERNAL:
     */
    public void initializePlatformOperator(DatabasePlatform platform) {
        if (this.operator.isComplete()) {
            platformOperator = this.operator;
            return;
        }
        platformOperator = platform.getOperator(this.operator.getSelector());
        if (platformOperator == null) {
            throw QueryException.invalidOperator(this.operator.toString());
        }
    }

    @Override
    public boolean isFunctionExpression() {
        return true;
    }

    /**
     * INTERNAL:
     * Return if the represents an object comparison.
     */
    protected boolean isObjectComparison() {
        int selector = this.operator.getSelector();
        if (((selector != ExpressionOperator.IsNull) && (selector != ExpressionOperator.NotNull)) || (this.children.size() != 1)) {
            if (((selector != ExpressionOperator.InSubQuery) && (selector != ExpressionOperator.NotInSubQuery))
                    || (this.children.size() != 2)) {
                return false;
            }
        }

        Expression base = getBaseExpression();
        //bug 384641 - check that directCollections are not treated as object comparisons
        return (base.isObjectExpression() && (!((ObjectExpression)base).isAttribute()) &&
                !((ObjectExpression)base).isDirectCollection() );
    }

    /**
     * INTERNAL:
     * For iterating using an inner class
     */
    @Override
    public void iterateOn(ExpressionIterator iterator) {
        super.iterateOn(iterator);
        for (Enumeration<Expression> childrenEnum = this.children.elements(); childrenEnum.hasMoreElements();) {
            Expression child = childrenEnum.nextElement();
            child.iterateOn(iterator);
        }
    }

    /**
     * INTERNAL:
     * Normalize into a structure that is printable.
     * Also compute printing information such as outer joins.
     * This checks for object isNull, notNull, in and notIn comparisons.
     */
    @Override
    public Expression normalize(ExpressionNormalizer normalizer) {
        //This method has no validation but we should still make the method call for consistency
        //bug # 2956674
        //validation is moved into normalize to ensure that expressions are valid before we attempt to work with them
        validateNode();
        if (this.children.isEmpty()) {
            return this;
        }

        // Ensure session has been set.
        ExpressionBuilder builder = getBuilder();
        if ((builder != null) && (builder.getSession() == null)) {
            builder.setSession(normalizer.getSession().getRootSession(null));
        }

        if (this.operator.getSelector() == ExpressionOperator.Count) {
            // Attempting to count an Entity and not an attribute.  Need to augment this expression.
            // This is normally normalized in ReportQuery, but can get to here in a having clause.
            prepareObjectAttributeCount(normalizer, null, null, null);
        }

        if (!isObjectComparison()) {
            for (int index = 0; index < this.children.size(); index++) {
                this.children.set(index, this.children.get(index).normalize(normalizer));
            }
            return this;
        } else {
            //if not normalizing we must still validate the corresponding node to make sure that they are valid
            //bug # 2956674
            for (int index = 0; index < this.children.size(); index++) {
                this.children.get(index).validateNode();
            }
        }

        // This code is executed only in the case of an is[not]Null, or [not]in on an
        // object attribute.
        ObjectExpression base = (ObjectExpression)getBaseExpression();

        // For cr2334, fix code so that normalize is first called on base expressions.
        // I.e. if base itself had a base expression this expression would not be normalized.
        if (base.getBaseExpression() != null) {
            base.getBaseExpression().normalize(normalizer);
        }

        // Check for IN with objects, "e IN (Select e2 from Employee e2)".
        if ((this.operator.getSelector() == ExpressionOperator.InSubQuery)
                || (this.operator.getSelector() == ExpressionOperator.NotInSubQuery)) {
            // Switch object comparison to compare on primary key.
            if (this.children.size() != 2) {
                throw QueryException.invalidExpression(this);
            }
            // Check if the left is for a 1-1 mapping, then optimize to compare on foreign key to avoid join.
            DatabaseMapping mapping = null;
            if (base.isQueryKeyExpression()) {
                mapping = base.getMapping();
            }
            List<DatabaseField> sourceFields = null;
            List<DatabaseField> targetFields = null;
            if ((mapping != null) && mapping.isOneToOneMapping()
                    && (!((OneToOneMapping)mapping).hasRelationTableMechanism())
                    && (!((OneToOneMapping)mapping).hasCustomSelectionQuery())) {
                base = (ObjectExpression)base.getBaseExpression();
                Map<DatabaseField, DatabaseField> targetToSourceKeyFields = ((OneToOneMapping)mapping).getTargetToSourceKeyFields();
                sourceFields = new ArrayList(targetToSourceKeyFields.size());
                targetFields = new ArrayList(targetToSourceKeyFields.size());
                for (Map.Entry<DatabaseField, DatabaseField> entry : targetToSourceKeyFields.entrySet()) {
                    sourceFields.add(entry.getValue());
                    targetFields.add(entry.getKey());
                }
            } else {
                mapping = null;
                sourceFields = base.getDescriptor().getPrimaryKeyFields();
                targetFields = sourceFields;
            }
            if (sourceFields.size() != 1) {
                base = (ObjectExpression)getBaseExpression();
                // For composite ids an exists and subselect is used.
                SubSelectExpression subSelectExp = (SubSelectExpression)this.children.get(1);
                ReportQuery subQuery = subSelectExp.getSubQuery();

                // some db (derby) require that in EXIST(SELECT...) subquery returns a single column
                subQuery.getItems().clear();
                subQuery.addItem("one", new ConstantExpression(1, subQuery.getExpressionBuilder()));

                Expression subSelectCriteria = subQuery.getSelectionCriteria();
                ExpressionBuilder subBuilder = subQuery.getExpressionBuilder();
                Expression newExp;
                // Any or Some
                if (this.operator.getSelector() == ExpressionOperator.InSubQuery) {
                    subSelectCriteria = subBuilder.equal(base).and(subSelectCriteria);
                } else {
                    subSelectCriteria = subBuilder.notEqual(base).and(subSelectCriteria);
                }
                subQuery.setSelectionCriteria(subSelectCriteria);
                newExp = builder.exists(subQuery);
                return newExp.normalize(normalizer);
            }
            Expression newBase = base.getField(sourceFields.get(0));
            setBaseExpression(newBase);
            this.children.set(0, newBase);
            Expression right = this.children.get(1);
            if (right.isSubSelectExpression()) {
                // Check for sub-select, need to replace sub-selects on object to select its id.
                ReportQuery query = ((SubSelectExpression)right).getSubQuery();
                if (query.getItems().size() != 1) {
                    throw QueryException.invalidExpression(this);
                }
                ReportItem item = query.getItems().get(0);
                item.setAttributeExpression(item.getAttributeExpression().getField(targetFields.get(0)));
            } else {
                throw QueryException.invalidExpression(this);
            }
            // Still need to normalize the children.
            for (int index = 0; index < this.children.size(); index++) {
                this.children.set(index, this.children.get(index).normalize(normalizer));
            }
            return this;
        }
        // else isNull/notNull

        Expression foreignKeyJoin = null;
        if (base.getMapping() == null) {
            // Is an expression builder, transform to a null primary key expression.
            foreignKeyJoin = base.getDescriptor().getObjectBuilder().buildPrimaryKeyExpressionFromKeys(null, getSession());
            foreignKeyJoin = foreignKeyJoin.rebuildOn(base);
        } else {
            // Switch to null foreign key comparison (i.e. get('c').isNull() to getField('C_ID').isNull()).
            // For bug 3105559 also must handle aggregates: get("period").isNull();
            foreignKeyJoin = base.getMapping().buildObjectJoinExpression(base, (Object)null, getSession());
        }

        if (this.operator.getSelector() == ExpressionOperator.NotNull) {
            foreignKeyJoin = foreignKeyJoin.not();
        }
        return foreignKeyJoin.normalize(normalizer);
    }

    /**
     * INTERNAL:
     * Used for cloning.
     */
    @Override
    protected void postCopyIn(Map alreadyDone) {
        super.postCopyIn(alreadyDone);
        Vector<Expression> oldChildren = this.children;
        this.children = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
        for (int i = 0; i < oldChildren.size(); i++) {
            addChild((oldChildren.elementAt(i).copiedVersionFrom(alreadyDone)));
        }
    }

    /**
     * INTERNAL:
     * Print SQL using the operator.
     */
    @Override
    public void printSQL(ExpressionSQLPrinter printer) {
        // If all children are parameters, some databases don't allow binding.
        if (printer.getPlatform().isDynamicSQLRequiredForFunctions() && !this.children.isEmpty()) {
            boolean allParams = true;
            for (Iterator<Expression> iterator = this.children.iterator(); iterator.hasNext(); ) {
                Expression child = iterator.next();
                if (!(child.isParameterExpression() || child.isConstantExpression())) {
                    allParams = false;
                }
            }
            if (allParams) {
                printer.getCall().setUsesBinding(false);
            }
        }
        ExpressionOperator realOperator;
        realOperator = getPlatformOperator(printer.getPlatform());
        realOperator.printCollection(this.children, printer);
    }

    /**
     * INTERNAL:
     * Print java for project class generation
     */
    @Override
    public void printJava(ExpressionJavaPrinter printer) {
        ExpressionOperator realOperator = getPlatformOperator(printer.getPlatform());
        realOperator.printJavaCollection(this.children, printer);
    }

    /**
     * INTERNAL:
     * This expression is built on a different base than the one we want. Rebuild it and
     * return the root of the new tree
     */
    @Override
    public Expression rebuildOn(Expression newBase) {
        Expression newLocalBase = getBaseExpression().rebuildOn(newBase);
        Vector newChildren = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(this.children.size());
        for (int i = 1; i < this.children.size(); i++) {// Skip the first one, since it's also the base
            newChildren.addElement(this.children.elementAt(i).rebuildOn(newBase));
        }
        newLocalBase.setSelectIfOrderedBy(getBaseExpression().selectIfOrderedBy());
        FunctionExpression rebuilt = (FunctionExpression) newLocalBase.performOperator(this.operator, newChildren);
        rebuilt.setResultType(this.getResultType()); //copy over result type.
        return rebuilt;
    }

    /**
     * INTERNAL:
     * Search the tree for any expressions (like SubSelectExpressions) that have been
     * built using a builder that is not attached to the query.  This happens in case of an Exists
     * call using a new ExpressionBuilder().  This builder needs to be replaced with one from the query.
     */
    @Override
    public void resetPlaceHolderBuilder(ExpressionBuilder queryBuilder){
        getBaseExpression().resetPlaceHolderBuilder(queryBuilder);
        for (int i = this.children.size()-1; i > 0; i--) {// Skip the first one, since it's also the base
            this.children.elementAt(i).resetPlaceHolderBuilder(queryBuilder);
        }
    }
    // Set the local base expression, ie the one on the other side of the operator
    // Most types will ignore this, since they don't need it.
    @Override
    public void setLocalBase(Expression exp) {
        getBaseExpression().setLocalBase(exp);
    }

    public void setOperator(ExpressionOperator theOperator) {
        operator = theOperator;
    }

    public void setResultType(Class resultType) {
        this.resultType = resultType;
    }

    /**
     * INTERNAL:
     * Rebuild myself against the base, with the values of parameters supplied by the context
     * expression. This is used for transforming a standalone expression (e.g. the join criteria of a mapping)
     * into part of some larger expression. You normally would not call this directly, instead calling twist
     * See the comment there for more details"
     */
    @Override
    public Expression twistedForBaseAndContext(Expression newBase, Expression context, Expression oldBase) {
        if (this.children.isEmpty()) {
            return (Expression)clone();
        }
        Vector newChildren = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(this.children.size());

        // For functions the base is the first child, we only want the arguments so start at the second.
        for (int index = 1; index < this.children.size(); index++) {
            newChildren.addElement(this.children.elementAt(index).twistedForBaseAndContext(newBase, context, oldBase));
        }

        // Aply the function to the twisted old base.
        Expression oldBaseExp = this.children.elementAt(0);
        return oldBaseExp.twistedForBaseAndContext(newBase, context, oldBase).performOperator(this.operator, newChildren);
    }

    /**
     * INTERNAL:
     * Return the value for in memory comparison.
     * This is only valid for valueable expressions.
     */
    @Override
    public Object valueFromObject(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean isObjectUnregistered) {
        Object baseValue = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
        Vector arguments = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(this.children.size());
        for (int index = 1; index < this.children.size(); index++) {
            if (this.children.elementAt(index) instanceof Expression) {
                arguments.addElement(this.children.elementAt(index).valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered));
            } else {
                arguments.addElement(this.children.elementAt(index));
            }
        }
        if (baseValue instanceof Vector) {// baseValue might be a vector, so the individual values must be extracted before applying the function call to them
            Vector baseVector = new Vector();
            for (Enumeration valuesToCompare = ((Vector)baseValue).elements();
                     valuesToCompare.hasMoreElements();) {
                Object baseObject = valuesToCompare.nextElement();
                if (baseObject == null) {
                    baseVector.addElement(null);
                } else {
                    baseVector.addElement(this.operator.applyFunction(baseObject, arguments));
                }
            }
            return baseVector;
        } else {
            // Do not apply functions to null, just leave as null.
            if (baseValue == null) {
                return null;
            } else {
                return this.operator.applyFunction(baseValue, arguments);
            }
        }
    }

    /**
     * INTERNAL:
     * Used to print a debug form of the expression tree.
     */
    @Override
    public void writeDescriptionOn(BufferedWriter writer) throws IOException {
        writer.write(operator.toString());
    }

    /**
     * INTERNAL: called from SQLSelectStatement.writeFieldsFromExpression(...)
     */
    @Override
    public void writeFields(ExpressionSQLPrinter printer, List<DatabaseField> newFields, SQLSelectStatement statement) {
        //print ", " before each selected field except the first one
        if (printer.isFirstElementPrinted()) {
            printer.printString(", ");
        } else {
            printer.setIsFirstElementPrinted(true);
        }

        if (getBaseExpression().isDataExpression()) {
            DatabaseField field = ((DataExpression)getBaseExpression()).getField();

            if (field == null) {
                // This means the select wants a *.
                field = new DatabaseField("*");
            } else {
                // Clone the field since we will change its type.
                field = field.clone();
            }

            // If the result type is set, use it.
            field.setSqlType(DatabaseField.NULL_SQL_TYPE);
            //we also cache the JDBC type now so reset it as well.
            if (hasResultType()) {
                field.setType(getResultType());
            } else {
                // If the function is anything but min or max, null out the
                // field type. The type will be calculated based on the
                // function.
                int selector = this.operator.getSelector();
                if (selector != ExpressionOperator.Maximum && selector != ExpressionOperator.Minimum) {
                    field.setType(null);
                }
            }

            newFields.add(field);
        } else {
            // This field is a complex function value so any name can be used.
            DatabaseField field = new DatabaseField("*");
            // If the result type is set, use it.
            field.setSqlType(DatabaseField.NULL_SQL_TYPE);
            field.setType(getResultType());
            newFields.add(field);
        }

        printSQL(printer);
    }

    /**
     * INTERNAL:
     * Used in SQL printing.
     */
    @Override
    public void writeSubexpressionsTo(BufferedWriter writer, int indent) throws IOException {
        if (baseExpression != null) {
            baseExpression.toString(writer, indent);
        }
    }

    /**
     * INTERNAL:
     * JPQL allows count([distinct] e), where e can be an object, not just a single field,
     * however the database only allows a single field, so object needs to be translated to a single field.
     * If the descriptor has a single pk, it is used, otherwise any pk is used if distinct, otherwise a subselect is used.
     * If the object was obtained through an outer join, then the subselect also will not work, so an error is thrown.
     */
    public void prepareObjectAttributeCount(ExpressionNormalizer normalizer, ReportItem item, ReportQuery query, Map clonedExpressions) {
        // ** Note that any of the arguments may be null depending on the caller.
        if (getOperator().getSelector() == ExpressionOperator.Count) {
            Expression baseExp = getBaseExpression();
            boolean distinctUsed = false;
            if (baseExp.isFunctionExpression() && (baseExp.getOperator().getSelector() == ExpressionOperator.Distinct)) {
                distinctUsed = true;
                baseExp = ((FunctionExpression)baseExp).getBaseExpression();
            }
            boolean outerJoin = false;
            ClassDescriptor newDescriptor = null;
            AbstractSession session = null;
            if (query != null) {
                session = query.getSession();
            } else {
                session = normalizer.getSession();
            }
            if (baseExp.isQueryKeyExpression()) {
                // now need to find out if it is a direct to field or something else.
                ClassDescriptor descriptor = null;
                if (query == null) {
                    descriptor = ((QueryKeyExpression) baseExp).getDescriptor();
                } else {
                    descriptor = query.getDescriptor();
                }
                DatabaseMapping mapping = baseExp.getLeafMapping(query, descriptor, session);
                if ((mapping != null) && !mapping.isAbstractDirectMapping()) {
                    outerJoin = ((QueryKeyExpression)baseExp).shouldUseOuterJoin();
                    if (mapping.isAggregateMapping()){
                        newDescriptor = mapping.getDescriptor();
                        baseExp = ((QueryKeyExpression)baseExp).getBaseExpression();
                    } else {
                        newDescriptor = mapping.getReferenceDescriptor();
                    }
                } else {
                    QueryKey queryKey = getLeafQueryKeyFor(query, baseExp, descriptor, session);
                    if ((queryKey != null) && queryKey.isForeignReferenceQueryKey()){
                        outerJoin = ((QueryKeyExpression) baseExp).shouldUseOuterJoin();
                        newDescriptor = session.getDescriptor(((ForeignReferenceQueryKey)queryKey).getReferenceClass());
                    }
                }
            } else if (baseExp.isExpressionBuilder()) {
                if (((ExpressionBuilder)baseExp).getQueryClass() == null) {
                    if (item != null) {
                        item.setResultType(ClassConstants.INTEGER);
                    }
                } else {
                    newDescriptor = session.getDescriptor(((ExpressionBuilder)baseExp).getQueryClass());
                }
            }

            if (newDescriptor != null) {
                // At this point we are committed to rewriting the query.
                if ((newDescriptor.getPrimaryKeyFields().size() == 1) || !distinctUsed) {
                    // case 1: single PK =>
                    // treat COUNT(entity) as COUNT(entity.pk)
                    Expression countArg = baseExp.getField(newDescriptor.getPrimaryKeyFields().get(0));
                    if (distinctUsed) {
                        countArg = countArg.distinct();
                    }
                    setBaseExpression(countArg);
                    getChildren().set(0, countArg);
                } else if (((DatabasePlatform)session.getPlatform(newDescriptor.getJavaClass())).supportsCountDistinctWithMultipleFields()) {
                    // case 3, is database allows multiple fields, then just print them
                    // treat COUNT(distinct entity) as COUNT(distinct entity.pk1, entity.pk2)
                    List args = new ArrayList(newDescriptor.getPrimaryKeyFields().size());
                    Expression firstField = null;
                    for (DatabaseField field : newDescriptor.getPrimaryKeyFields()) {
                        if (firstField == null) {
                            firstField = baseExp.getField(field);
                        } else {
                            args.add(baseExp.getField(field));
                        }
                    }

                    ExpressionOperator anOperator = new ExpressionOperator();
                    anOperator.setType(ExpressionOperator.FunctionOperator);
                    Vector v = NonSynchronizedVector.newInstance(args.size());
                    v.addElement("DISTINCT ");
                    for (int index = 0; index < args.size(); index++) {
                        v.add(", ");
                    }
                    v.add("");
                    anOperator.printsAs(v);
                    anOperator.bePrefix();
                    anOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
                    Expression distinctFunction = anOperator.expressionForArguments(firstField, args);

                    setBaseExpression(distinctFunction);
                    getChildren().set(0, distinctFunction);
                } else if (!outerJoin && (query != null)) {
                    // case 4: composite PK and DISTINCT, but no
                    // outer join => previous solution using
                    // COUNT(*) and EXISTS subquery
                    // TODO, this doesn't really work for most cases (joins, other things selected, group by),
                    // this should probably be removed and throw an error,
                    // or changed to just concat all the pks together.

                    // If this is a subselect baseExp is yet uncloned,
                    // and will miss out if moved now from items into a selection criteria.
                    if (clonedExpressions != null) {
                        if (clonedExpressions.get(baseExp.getBuilder()) != null) {
                            baseExp = baseExp.copiedVersionFrom(clonedExpressions);
                        } else {
                            baseExp = baseExp.rebuildOn(query.getExpressionBuilder());
                        }
                    }

                    // Now the reference class of the query needs to be reversed.
                    // See the bug description for an explanation.
                    ExpressionBuilder countBuilder = baseExp.getBuilder();
                    ExpressionBuilder outerBuilder ;

                    ReportQuery subSelect = new ReportQuery(query.getReferenceClass(), countBuilder);
                    query.getSession().getPlatform().retrieveFirstPrimaryKeyOrOne(subSelect);

                    // Make sure the outerBuilder does not appear on the left of the subselect.
                    // Putting a builder on the left is desirable to trigger an optimization.
                    if (query.getSelectionCriteria() != null) {
                        outerBuilder = new ExpressionBuilder(newDescriptor.getJavaClass());
                        query.setExpressionBuilder(outerBuilder);
                        subSelect.setSelectionCriteria(baseExp.equal(outerBuilder).and(query.getSelectionCriteria()));
                    } else {
                        outerBuilder = new ExpressionBuilder(newDescriptor.getJavaClass());
                        query.setExpressionBuilder(outerBuilder);
                        subSelect.setSelectionCriteria(baseExp.equal(outerBuilder));
                    }
                    query.setNonFetchJoinAttributeExpressions(null);
                    query.setSelectionCriteria(outerBuilder.exists(subSelect));
                    setBaseExpression(outerBuilder);
                    getChildren().set(0, outerBuilder);
                    query.setReferenceClass(newDescriptor.getJavaClass());
                    query.changeDescriptor(session);
                } else {
                    // case 4: composite PK, DISTINCT, outer join =>
                    // not supported, throw exception
                    DatabaseQuery reportQuery = query;
                    if (query == null) {
                        reportQuery = normalizer.getStatement().getQuery();
                    }
                    throw QueryException.distinctCountOnOuterJoinedCompositePK(newDescriptor, reportQuery);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Lookup the query key for this item.
     * If an aggregate of foreign mapping is found it is traversed.
     */
    protected QueryKey getLeafQueryKeyFor(DatabaseQuery query, Expression expression, ClassDescriptor rootDescriptor, AbstractSession session) throws QueryException {
        // Check for database field expressions or place holder
        if ((expression == null) || (expression.isFieldExpression())) {
            return null;
        }

        if (!(expression.isQueryKeyExpression())) {
            return null;
        }

        QueryKeyExpression qkExpression = (QueryKeyExpression)expression;
        Expression baseExpression = qkExpression.getBaseExpression();

        ClassDescriptor descriptor = baseExpression.getLeafDescriptor(query, rootDescriptor, session);
        return descriptor.getQueryKeyNamed(qkExpression.getName());
    }

    protected DatabaseMapping getMappingOfFirstPrimaryKey(ClassDescriptor descriptor) {
        if (descriptor != null) {
            for (Iterator<DatabaseMapping> i = descriptor.getMappings().iterator(); i.hasNext(); ) {
                DatabaseMapping m = (DatabaseMapping)i.next();
                if (m.isPrimaryKeyMapping()) {
                    return m;
                }
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Lookup the mapping for this item by traversing its expression recursively.
     */
    @Override
    public DatabaseMapping getLeafMapping(DatabaseQuery query, ClassDescriptor rootDescriptor, AbstractSession session) {
        int selector = this.operator.getSelector();

        //MAX and MIN functions require mappings for their result value. See JPA 2.1; section 4.8.5
        if (this.baseExpression != null && ((selector == ExpressionOperator.Maximum) || (selector == ExpressionOperator.Minimum))) {
            return this.baseExpression.getLeafMapping(query, rootDescriptor, session);
        }
        return super.getLeafMapping(query, rootDescriptor, session);
    }
}
