/*
 * 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
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
package org.eclipse.persistence.internal.expressions;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
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.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.internal.helper.DatabaseField;
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.queries.ReportQuery;

/**
 * <p><b>Purpose</b>:Used for all relation operators except for between.
 */
public class RelationExpression extends CompoundExpression {
    /** PERF: Cache if the expression is an object comparison expression. */
    protected Boolean isObjectComparisonExpression;

    public RelationExpression() {
        super();
    }

    /**
     * Test that both of our children are field nodes
     */
    protected boolean allChildrenAreFields() {
        return (this.firstChild.getFields().size() == 1) && (this.secondChild.getFields().size() == 1);

    }

    /**
     * INTERNAL:
     * Modify this individual expression node to use outer joins wherever there are
     * equality operations between two field nodes.
     */
    @Override
    protected void convertNodeToUseOuterJoin() {
        if ((this.operator.getSelector() == ExpressionOperator.Equal) && allChildrenAreFields()) {
            setOperator(getOperator(ExpressionOperator.EqualOuterJoin));
        }
    }

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

    /**
     * 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) {
        if ((this.secondChild.getBuilder().getSession() == null) || (this.firstChild.getBuilder().getSession() == null)) {
            // Parallel selects are not supported in memory.
            throw QueryException.cannotConformExpression();
        }

        // Extract the value from the right side.
        //CR 3677 integration of valueHolderPolicy
        Object rightValue =
            this.secondChild.valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);

        // Extract the value from the object.
        //CR 3677 integration of valueHolderPolicy
        Object leftValue =
            this.firstChild.valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);

        // The right value may be a Collection of values from an anyof, or an in.
        if (rightValue instanceof Collection) {
            // Vector may mean anyOf, or an IN.
            // CR#3240862, code for IN was incorrect, and was check for between which is a function not a relation.
            // Must check for IN and NOTIN, currently object comparison is not supported.
            // IN must be handled separately because right is always a vector of values, vector never means anyof.
            if ((this.operator.getSelector() == ExpressionOperator.In) ||
                (this.operator.getSelector() == ExpressionOperator.NotIn)) {
                if (isObjectComparison(session)) {
                    // In object comparisons are not currently supported, in-memory or database.
                    throw QueryException.cannotConformExpression();
                } else {
                    // Left may be single value or anyof vector.
                    if (leftValue instanceof Vector) {
                        return doesAnyOfLeftValuesConform((Vector)leftValue, rightValue, session);
                    } else {
                        return this.operator.doesRelationConform(leftValue, rightValue);
                    }
                }
            }

            // Otherwise right vector means an anyof on right, so must check each value.
            for (Enumeration rightEnum = ((Vector)rightValue).elements(); rightEnum.hasMoreElements(); ) {
                Object tempRight = rightEnum.nextElement();

                // Left may also be an anyof some must check each left with each right.
                if (leftValue instanceof Vector) {
                    // If anyof the left match return true, otherwise keep checking.
                    if (doesAnyOfLeftValuesConform((Vector)leftValue, tempRight, session)) {
                        return true;
                    }
                }
                if (doValuesConform(leftValue, tempRight, session)) {
                    return true;
                }
            }

            // None of the value conform.
            return false;
        }

        // Otherwise the left may also be a vector of values from an anyof.
        if (leftValue instanceof Vector) {
            return doesAnyOfLeftValuesConform((Vector)leftValue, rightValue, session);
        }

        // Otherwise it is a simple value to value comparison, or simple object to object comparison.
        return doValuesConform(leftValue, rightValue, session);
    }

    /**
     * Conform in-memory the collection of left values with the right value for this expression.
     * This is used for anyOf support when the left side is a collection of values.
     */
    protected boolean doesAnyOfLeftValuesConform(Vector leftValues, Object rightValue, AbstractSession session) {
        // Check each left value with the right value.
        for (int index = 0; index < leftValues.size(); index++) {
            Object leftValue = leftValues.get(index);
            if (doValuesConform(leftValue, rightValue, session)) {
                // Return true if any value matches.
                return true;
            }
        }

        // Return false only if none of the values match.
        return false;
    }

    /**
     * Conform in-memory the two values.
     */
    protected boolean doValuesConform(Object leftValue, Object rightValue, AbstractSession session) {
        // Check for object comparison.
        if (isObjectComparison(session)) {
            return doesObjectConform(leftValue, rightValue, session);
        } else {
            return this.operator.doesRelationConform(leftValue, rightValue);
        }
    }

    /**
     * INTERNAL:
     * Check if the object conforms to the expression in memory.
     * This is used for in-memory querying across object relationships.
     */
    public boolean doesObjectConform(Object leftValue, Object rightValue, AbstractSession session) {
        if ((leftValue == null) && (rightValue == null)) {
            return performSelector(true);
        }
        if ((leftValue == null) || (rightValue == null)) {
            //both are not null.
            return performSelector(false);
        }

        Class<? extends Object> javaClass = leftValue.getClass();
        if (javaClass != rightValue.getClass()) {
            return performSelector(false);
        }

        ClassDescriptor descriptor = session.getDescriptor(javaClass);
        // Currently cannot conform aggregate comparisons in-memory.
        if (descriptor.isAggregateDescriptor()) {
            throw QueryException.cannotConformExpression();
        }
        Object leftPrimaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(leftValue, session);
        Object rightPrimaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(rightValue, session);

        return performSelector(leftPrimaryKey.equals(rightPrimaryKey));

    }

    /**
     * INTERNAL:
     * Extract the values from the expression into the row.
     * Ensure that the query is querying the exact primary key.
     * @param requireExactMatch refers to the primary key extracted gaurenteeing the result,
     * if not exact it is a heuristic and the cache hit will be conformed to the expression after the lookup
     * Return false if not on the primary key.
     */
    @Override
    public boolean extractValues(boolean primaryKeyOnly, boolean requireExactMatch, ClassDescriptor descriptor, AbstractRecord primaryKeyRow, AbstractRecord translationRow) {
        // If an exact match is required then the operator must be equality.
        if (requireExactMatch && (!(this.operator.getSelector() == ExpressionOperator.Equal))) {
            return false;
        }

        // If not an exact match only =, <, <=, >=, >,... are allowed but not IN which has a different type
        if ((!requireExactMatch) && (this.operator.getSelector() == ExpressionOperator.In)) {
            return false;
        }

        DatabaseField field = null;

        Object value = null;
        if (this.secondChild.isConstantExpression()) {
            value = ((ConstantExpression)this.secondChild).getValue();
        } else if (this.secondChild.isParameterExpression() && (translationRow != null)) {
            value = translationRow.get(((ParameterExpression)this.secondChild).getField());
        } else if (this.firstChild.isConstantExpression()) {
            value = ((ConstantExpression)this.firstChild).getValue();
        } else if (this.firstChild.isParameterExpression() && (translationRow != null)) {
            value = translationRow.get(((ParameterExpression)this.firstChild).getField());
        }
        if (value == null) {
            return false;
        }

        // Descriptor to use for child query key
        ClassDescriptor descriptorForChild = null;

        // Ensure that the primary key is being queried on.
        if (this.firstChild.isFieldExpression()) {
            FieldExpression child = (FieldExpression)this.firstChild;
            // Only get value for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            field = child.getField();
        } else if (this.firstChild.isQueryKeyExpression()) {
            QueryKeyExpression child = (QueryKeyExpression)this.firstChild;
            // Only get value for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            descriptorForChild = ((ExpressionBuilder)child.getBaseExpression()).getDescriptor();
            if (descriptorForChild == null) {
                descriptorForChild = descriptor;
            }
            DatabaseMapping mapping = descriptorForChild.getObjectBuilder().getMappingForAttributeName(child.getName());

            if (mapping != null) {
                if (primaryKeyOnly && !mapping.isPrimaryKeyMapping()) {
                    return false;
                }
                // Only support referencing limited number of relationship types.
                if (mapping.isObjectReferenceMapping() || mapping.isAggregateObjectMapping()) {
                    mapping.writeFromAttributeIntoRow(value, primaryKeyRow, getSession());
                    return true;
                }

                if (!mapping.isAbstractColumnMapping()) {
                    return false;
                }
                field = mapping.getField();
            } else {
                // Only get field for the source object.
                field = descriptorForChild.getObjectBuilder().getFieldForQueryKeyName(child.getName());
            }
        } else if (this.secondChild.isFieldExpression()) {
            FieldExpression child = (FieldExpression)this.secondChild;
            // Only get field for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            field = child.getField();
        } else if (this.secondChild.isQueryKeyExpression()) {
            QueryKeyExpression child = (QueryKeyExpression)this.secondChild;
            // Only get value for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            descriptorForChild = ((ExpressionBuilder)child.getBaseExpression()).getDescriptor();
            if (descriptorForChild == null) {
                descriptorForChild = descriptor;
            }
            DatabaseMapping mapping = descriptorForChild.getObjectBuilder().getMappingForAttributeName(child.getName());

            // Only support referencing limited number of relationship types.
            if (mapping != null) {
                if (primaryKeyOnly && !mapping.isPrimaryKeyMapping()) {
                    return false;
                }
                if (mapping.isObjectReferenceMapping() || mapping.isAggregateObjectMapping()) {
                    mapping.writeFromAttributeIntoRow(value, primaryKeyRow, getSession());
                    return true;
                }
                if (!mapping.isAbstractColumnMapping()) {
                    return false;
                }
                field = mapping.getField();
            } else {
                field = descriptorForChild.getObjectBuilder().getFieldForQueryKeyName(child.getName());
            }
        } else {
            return false;
        }
        if (field == null) {
            return false;
        }
        // Check child descriptor's primary key fields if the passed descriptor does not contain the field
        if (primaryKeyOnly && !descriptor.getPrimaryKeyFields().contains(field)) {
            if (descriptorForChild != null && descriptorForChild != descriptor && descriptorForChild.getPrimaryKeyFields().contains(field)) {
                // Child descriptor's pk fields contains the field, return true.
                // Do not add the field from the query key's descriptor to the primaryKeyRow
                return true;
            } else {
                return false;
            }
        }
        // Do not replace the field in the row with the same field
        if (primaryKeyRow.get(field) != null) {
            return false;
        }
        primaryKeyRow.put(field, value);
        return true;
    }

    /**
     * INTERNAL:
     * Return if the expression is not a valid primary key expression and add all primary key fields to the set.
     */
    @Override
    public boolean extractFields(boolean requireExactMatch, boolean primaryKey, ClassDescriptor descriptor, List<DatabaseField> searchFields, Set<DatabaseField> foundFields) {
        // If an exact match is required then the operator must be equality.
        if (requireExactMatch && (!(this.operator.getSelector() == ExpressionOperator.Equal))) {
            return false;
        }
        // If not an exact match only =, <, <=, >=, >,... are allowed but not IN which has a different type
        if ((!requireExactMatch) && (this.operator.getSelector() == ExpressionOperator.In)) {
            return false;
        }
        DatabaseField field = null;
        if (!(this.secondChild.isConstantExpression() || this.secondChild.isParameterExpression())
                && !(this.firstChild.isConstantExpression() || (this.firstChild.isParameterExpression()))) {
            return false;
        }
        // Ensure that the primary key is being queried on.
        if (this.firstChild.isFieldExpression()) {
            FieldExpression child = (FieldExpression)this.firstChild;
            // Only get value for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            field = child.getField();
        } else if (this.firstChild.isQueryKeyExpression()) {
            QueryKeyExpression child = (QueryKeyExpression)this.firstChild;
            // Only get value for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForAttributeName(child.getName());
            if (mapping != null) {
                if (primaryKey && !mapping.isPrimaryKeyMapping()) {
                    return false;
                }
                // Only support referencing limited number of relationship types.
                if (mapping.isObjectReferenceMapping() || mapping.isAggregateObjectMapping()) {
                    for (DatabaseField mappingField : mapping.getFields()) {
                        if (searchFields.contains(mappingField)) {
                            foundFields.add(mappingField);
                        }
                    }
                    return true;
                }

                if (!mapping.isAbstractColumnMapping()) {
                    return false;
                }
                field = mapping.getField();
            } else {
                // Only get field for the source object.
                field = descriptor.getObjectBuilder().getFieldForQueryKeyName(child.getName());
            }
        } else if (this.secondChild.isFieldExpression()) {
            FieldExpression child = (FieldExpression)this.secondChild;
            // Only get field for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            field = child.getField();
        } else if (this.secondChild.isQueryKeyExpression()) {
            QueryKeyExpression child = (QueryKeyExpression)this.secondChild;
            // Only get value for the source object.
            if (!child.getBaseExpression().isExpressionBuilder()) {
                return false;
            }
            DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForAttributeName(child.getName());
            // Only support referencing limited number of relationship types.
            if (mapping != null) {
                if (!mapping.isPrimaryKeyMapping()) {
                    return false;
                }
                if (mapping.isObjectReferenceMapping() || mapping.isAggregateObjectMapping()) {
                    for (DatabaseField mappingField : mapping.getFields()) {
                        if (searchFields.contains(mappingField)) {
                            foundFields.add(mappingField);
                        }
                    }
                    return true;
                }
                if (!mapping.isAbstractColumnMapping()) {
                    return false;
                }
                field = mapping.getField();
            } else {
                field = descriptor.getObjectBuilder().getFieldForQueryKeyName(child.getName());
            }
        } else {
            return false;
        }
        if ((field == null) || (!searchFields.contains(field))) {
            return false;
        }
        foundFields.add(field);
        return true;
    }

    /**
     * Check if the expression is an equal null expression, these must be handle in a special way in SQL.
     */
    public boolean isEqualNull(ExpressionSQLPrinter printer) {
        if (isObjectComparison(printer.getSession())) {
            return false;
        } else if (this.operator.getSelector() != ExpressionOperator.Equal) {
            return false;
        } else if (this.secondChild.isConstantExpression() && (((ConstantExpression)this.secondChild).getValue() == null)) {
            return true;
        } else if (this.secondChild.isParameterExpression() && (printer.getTranslationRow() != null) &&
            (((ParameterExpression)this.secondChild).getValue(printer.getTranslationRow(), printer.getSession()) == null)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Check if the expression is an equal null expression, these must be handle in a special way in SQL.
     */
    public boolean isNotEqualNull(ExpressionSQLPrinter printer) {
        if (isObjectComparison(printer.getSession())) {
            return false;
        } else if (this.operator.getSelector() != ExpressionOperator.NotEqual) {
            return false;
        } else if (this.secondChild.isConstantExpression() && (((ConstantExpression)this.secondChild).getValue() == null)) {
            return true;
        } else if (this.secondChild.isParameterExpression() && (printer.getTranslationRow() != null) &&
            (((ParameterExpression)this.secondChild).getValue(printer.getTranslationRow(), printer.getSession()) == null)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * INTERNAL:
     * Return if the represents an object comparison.
     */
    protected boolean isObjectComparison(AbstractSession session) {
        if (this.isObjectComparisonExpression == null) {
            // PERF: direct-access.
            // Base must have a session set in its builder to call getMapping, isAttribute
            if (this.firstChild.getBuilder().getSession() == null) {
                this.firstChild.getBuilder().setSession(session.getRootSession(null));
            }
            if (this.secondChild.getBuilder().getSession() == null) {
                this.secondChild.getBuilder().setSession(session.getRootSession(null));
            }
            if ((!this.firstChild.isObjectExpression()) || ((ObjectExpression)this.firstChild).isAttribute()) {
                if ((this.secondChild.isObjectExpression()) && !((ObjectExpression)this.secondChild).isAttribute()) {
                    DatabaseMapping mapping = ((ObjectExpression)this.secondChild).getMapping();
                    if ((mapping != null) && (mapping.isDirectCollectionMapping()) && !(this.secondChild.isMapEntryExpression())) {
                        this.isObjectComparisonExpression = Boolean.FALSE;
                    } else {
                        this.isObjectComparisonExpression = this.firstChild.isObjectExpression()
                                || this.firstChild.isValueExpression()
                                || this.firstChild.isSubSelectExpression()
                                || (this.firstChild.isFunctionExpression() && ((FunctionExpression) this.firstChild).operator.isAnyOrAll());
                    }
                } else {
                    this.isObjectComparisonExpression = Boolean.FALSE;
                }
            } else {
                DatabaseMapping mapping = ((ObjectExpression)this.firstChild).getMapping();
                if ((mapping != null) && (mapping.isDirectCollectionMapping()) && !(this.firstChild.isMapEntryExpression())) {
                    this.isObjectComparisonExpression = Boolean.FALSE;
                } else {
                    this.isObjectComparisonExpression = this.secondChild.isObjectExpression()
                            || this.secondChild.isValueExpression()
                            || this.secondChild.isSubSelectExpression()
                            || (this.secondChild.isFunctionExpression() && ((FunctionExpression) this.secondChild).operator.isAnyOrAll());
                }
            }
        }
        return this.isObjectComparisonExpression;
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isRelationExpression() {
        return true;
    }

    /**
     * PERF: Optimize out unnecessary joins.
     * Check for relation based on foreign keys, i.e. emp.address.id = :id, and avoid join.
     * @return null if cannot be optimized, otherwise the optimized normalized expression.
     */
    protected Expression checkForeignKeyJoinOptimization(Expression first, Expression second, ExpressionNormalizer normalizer) {
        if (first.isQueryKeyExpression()
                && (((QueryKeyExpression)first).getBaseExpression() != null)
                && ((QueryKeyExpression)first).getBaseExpression().isQueryKeyExpression()) {
            // Do not optimize for subselect if it is using parent builder, and needs to clone.
            if(normalizer.getStatement().isSubSelect() && normalizer.getStatement().getParentStatement().getBuilder().equals(first.getBuilder())) {
                return null;
            }
            QueryKeyExpression mappingExpression = (QueryKeyExpression)((QueryKeyExpression)first).getBaseExpression();
            if ((mappingExpression.getBaseExpression() != null)
                    && mappingExpression.getBaseExpression().isObjectExpression()
                    && (!mappingExpression.shouldUseOuterJoin())) {
                // Must ensure it has been normalized first.
                mappingExpression.getBaseExpression().normalize(normalizer);
                DatabaseMapping mapping = mappingExpression.getMapping();
                if ((mapping != null) && mapping.isOneToOneMapping()
                        && (!((OneToOneMapping)mapping).hasCustomSelectionQuery())
                        && ((OneToOneMapping)mapping).isForeignKeyRelationship()
                        && (second.isConstantExpression() || second.isParameterExpression())) {
                    DatabaseField targetField = ((QueryKeyExpression)first).getField();
                    DatabaseField sourceField = ((OneToOneMapping)mapping).getTargetToSourceKeyFields().get(targetField);
                    if (sourceField != null) {
                        Expression optimizedExpression = this.operator.expressionFor(mappingExpression.getBaseExpression().getField(sourceField), second);
                        // Ensure the base still applies the correct conversion.
                        second.setLocalBase(first);
                        return optimizedExpression.normalize(normalizer);
                    }
                }
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Check for object comparison as this requires for the expression to be replaced by the object comparison.
     */
    @Override
    public Expression normalize(ExpressionNormalizer normalizer) {
        // PERF: Optimize out unnecessary joins.
        Expression optimizedExpression = checkForeignKeyJoinOptimization(this.firstChild, this.secondChild, normalizer);
        if (optimizedExpression == null) {
            optimizedExpression = checkForeignKeyJoinOptimization(this.secondChild, this.firstChild, normalizer);
        }
        if (optimizedExpression != null) {
            return optimizedExpression;
        }
        if (!isObjectComparison(normalizer.getSession())) {
            return super.normalize(normalizer);
        } else {
            //bug # 2956674
            //validation is moved into normalize to ensure that expressions are valid before we attempt to work with them
            // super.normalize will call validateNode as well.
            validateNode();
        }
        if ((this.operator.getSelector() != ExpressionOperator.Equal) &&
                (this.operator.getSelector() != ExpressionOperator.NotEqual) &&
                (this.operator.getSelector() != ExpressionOperator.In) &&
                (this.operator.getSelector() != ExpressionOperator.NotIn)) {
            throw QueryException.invalidOperatorForObjectComparison(this);
        }

        // Check for IN with objects, "object IN :objects", "objects IN (:object1, :object2 ...)", "object IN aList"
        if ((this.operator.getSelector() == ExpressionOperator.In) || (this.operator.getSelector() == ExpressionOperator.NotIn)) {
            // Switch object comparison to compare on primary key.
            Expression left = this.firstChild;
            if (!left.isObjectExpression()) {
                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 (left.isQueryKeyExpression()) {
                ((ObjectExpression)left).getBaseExpression().normalize(normalizer);
                mapping = ((ObjectExpression)left).getMapping();
            }
            ClassDescriptor descriptor = null;
            List<DatabaseField> sourceFields = null;
            List<DatabaseField> targetFields = null;
            if ((mapping != null) && mapping.isOneToOneMapping()
                    && (!((OneToOneMapping)mapping).hasRelationTableMechanism())
                    && (!((OneToOneMapping)mapping).hasCustomSelectionQuery())) {
                left = ((ObjectExpression)left).getBaseExpression();
                descriptor = mapping.getReferenceDescriptor();
                left = left.normalize(normalizer);
                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;
                left = left.normalize(normalizer);
                descriptor = ((ObjectExpression)left).getDescriptor();
                sourceFields = descriptor.getPrimaryKeyFields();
                targetFields = sourceFields;
            }
            boolean composite = sourceFields.size() > 1;
            DatabaseField sourceField = sourceFields.get(0);
            DatabaseField targetField = targetFields.get(0);
            Expression newLeft = null;
            if (composite) {
                // For composite ids an array comparison is used, this only works on some databases.
                List fieldExpressions = new ArrayList();
                for (DatabaseField field : sourceFields) {
                    fieldExpressions.add(left.getField(field));
                }
                newLeft = getBuilder().value(sourceFields);
            } else {
               newLeft = left.getField(sourceField);
            }
            setFirstChild(newLeft);
            Expression right = this.secondChild;
            if (right.isConstantExpression()) {
                // Check for a constant with a List of objects, need to collect the ids (also allow a list of ids).
                ConstantExpression constant = (ConstantExpression)right;
                if (constant.getValue() instanceof Collection) {
                    Collection objects = (Collection)constant.getValue();
                    List newObjects = new ArrayList(objects.size());
                    for (Object object : objects) {
                        if (object instanceof Expression) {
                            if (composite) {
                                // For composite ids an array comparison is used, this only works on some databases.
                                List values = new ArrayList();
                                for (DatabaseField field : targetFields) {
                                    values.add(((Expression)object).getField(field));
                                }
                                object = getBuilder().value(values);
                            } else {
                                object = ((Expression)object).getField(targetField);
                            }
                        } else if (descriptor.getJavaClass().isInstance(object)) {
                            if (composite) {
                                // For composite ids an array comparison is used, this only works on some databases.
                                List values = new ArrayList();
                                for (DatabaseField field : targetFields) {
                                    values.add(descriptor.getObjectBuilder().extractValueFromObjectForField(object, field, normalizer.getSession()));
                                }
                                object = getBuilder().value(values);
                            } else {
                                object = descriptor.getObjectBuilder().extractValueFromObjectForField(object, targetField, normalizer.getSession());
                            }
                        } else {
                            // Assume it is an id, so leave it.
                        }
                        newObjects.add(object);
                    }
                    constant.setValue(newObjects);
                } else {
                    throw QueryException.invalidExpression(this);
                }
            } else if (right.isParameterExpression()) {
                // Parameters must be handled when the call is executed.
            } else {
                throw QueryException.invalidExpression(this);
            }
            return super.normalize(normalizer);
        }
        ObjectExpression first = null;
        Expression second = null;
        // One side must be an object expression.
        if (this.firstChild.isObjectExpression()) {
            first = (ObjectExpression)this.firstChild;
            second = this.secondChild;
        } else {
            first = (ObjectExpression)this.secondChild;
            second = this.firstChild;
        }

        // Check for sub-selects, "object = ALL(Select object...) or ANY(Select object...), or "object = (Select object..)"
        if (second.isFunctionExpression()) {
            FunctionExpression funcExp = (FunctionExpression)second;
            if (funcExp.operator.isAnyOrAll()) {
                SubSelectExpression subSelectExp = (SubSelectExpression)funcExp.getChildren().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();

                ExpressionBuilder builder = first.getBuilder();

                Expression newExp;
                if (funcExp.operator.isAny()) {
                    // Any or Some
                    if (this.operator.getSelector() == ExpressionOperator.Equal) {
                        subSelectCriteria = subBuilder.equal(first).and(subSelectCriteria);
                    } else {
                        subSelectCriteria = subBuilder.notEqual(first).and(subSelectCriteria);
                    }
                    subQuery.setSelectionCriteria(subSelectCriteria);
                    newExp = builder.exists(subQuery);
                } else {
                    // All
                    if (this.operator.getSelector() == ExpressionOperator.Equal) {
                        subSelectCriteria = subBuilder.notEqual(first).and(subSelectCriteria);
                    } else {
                        subSelectCriteria = subBuilder.equal(first).and(subSelectCriteria);
                    }
                    subQuery.setSelectionCriteria(subSelectCriteria);
                    newExp = builder.notExists(subQuery);
                }
                return newExp.normalize(normalizer);
            }
        } else if (second.isSubSelectExpression()) {
            SubSelectExpression subSelectExp = (SubSelectExpression)second;
            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();

            ExpressionBuilder builder = first.getBuilder();

            Expression newExp;
            // Any or Some
            if (this.operator.getSelector() == ExpressionOperator.Equal) {
                subSelectCriteria = subBuilder.equal(first).and(subSelectCriteria);
            } else {
                subSelectCriteria = subBuilder.notEqual(first).and(subSelectCriteria);
            }
            subQuery.setSelectionCriteria(subSelectCriteria);
            newExp = builder.exists(subQuery);
            return newExp.normalize(normalizer);
        }

        // This can either be comparison to another object, null or another expression reference.
        // Object comparisons can be done on other object builders, 1:1 or 1:m m:m mappings,
        // 1:m/m:m must twist the primary key expression,
        // 1:1 must not join into the target but become the foreign key expression.
        // The value may be a constant or another expression.
        Expression foreignKeyJoin = null;

        // OPTIMIZATION 1: IDENTITY for CR#2456 / bug 2778339
        // Most exists subqueries have something like projBuilder.equal(empBuilder.anyOf("projects"))
        // to correlate the subquery to the enclosing query.
        // TopLink can produce SQL with one less join by not mapping projBuilder and
        // anyOf("projects") to separate tables and equating them, but by treating
        // them as one and the same thing: as identical.
        // This trick can be pulled off by giving both the same TableAliasLookup,
        // but needs to be done very conservatively.
        // the equal() will be replaced directly with the mappingCriteria() of the anyOf("projects")
        // Example.  emp.equal(emp.get("manager")) will now produce this SQL:
        // SELECT ... FROM EMPLOYEE t0 WHERE (t0.EMP_ID = t0.MANAGER_ID) not:
        // SELECT ... FROM EMPLOYEE t0, EMPLOYEE t1 WHERE ((t0.EMP_ID = t1.EMP_ID)
        //                                        AND (t0.MANAGER_ID = t1.EMP_ID))
        if // If setting two query keys to equal the user probably intends a proper join.
            //.equal(anyOf() or get())
            (first.isExpressionBuilder() && second.isQueryKeyExpression()
                    &&  (!((QueryKeyExpression)second).hasDerivedExpressions()) // The right side is not used for anything else.
                    && normalizer.getSession().getPlatform().shouldPrintInnerJoinInWhereClause()) {
            first = (ExpressionBuilder)first.normalize(normalizer);

            // If FK joins go in the WHERE clause, want to get hold of it and
            // not put it in normalizer.additionalExpressions.
            List<Expression> foreignKeyJoinPointer = new ArrayList(1);
            QueryKeyExpression queryKey = (QueryKeyExpression)second;

            // If inside an OR the foreign key join must be on both sides.
            if (queryKey.hasBeenNormalized()) {
                queryKey.setHasBeenNormalized(false);
            }
            queryKey = (QueryKeyExpression)queryKey.normalize(normalizer, first, foreignKeyJoinPointer);
            if (!foreignKeyJoinPointer.isEmpty()) {
                foreignKeyJoin = foreignKeyJoinPointer.get(0);
                // Will make left and right identical in the SQL.
                if (first.getTableAliases() == null) {
                    TableAliasLookup tableAliases = new TableAliasLookup();
                    first.setTableAliases(tableAliases);
                    queryKey.setTableAliases(tableAliases);
                } else {
                    queryKey.setTableAliases(first.getTableAliases());
                }
            }
        }
        // OPTIMIZATION 2: for 1-1 mappings and get(...).equal(null)
        // Imagine you had addr1 = emp.get("address"); then addr1.equal(addr2);
        // One could go (addr1.ADDRESS_ID = addr2.ADDRESS_ID) and (emp.ADDR_ID = addr1.ADDRESS_ID) (foreign key join).
        // The optimization is to drop addr1 and instead have: (emp.ADDR_ID = addr2.ADDRESS_ID).
        // Since emp can have only 1 address (OneToOne) the addr1.equal(addr2) is
        // implicit.  This way if addr1 is used only for the comparison it can
        // be optimized out.
        // Also if addr2 were NULL there must be no join, just (emp.ADDR_ID = NULL)
        // For bug 3105559 handle AggregateObject case (emp.get("period").equal(period2)
        // which always falls into this case.
        else if // For bug 2718460, some QueryKeyExpressions have a query key but no mapping.
            // An example is the "back-ref" query key for batch reads.  Must not
            // attempt the optimization for these.
            (!first.isExpressionBuilder() && !((QueryKeyExpression)first).shouldQueryToManyRelationship() &&
             (first.getMapping() != null)) {
            // Normalize firstChild's base only, as firstChild will be optimized out.
            if (first.getBaseExpression() != null) {
                first.setBaseExpression(first.getBaseExpression().normalize(normalizer));
            }

            if (second.isConstantExpression()) {
                Object targetObject = ((ConstantExpression)second).getValue();
                foreignKeyJoin = first.getMapping().buildObjectJoinExpression(first, targetObject, getSession());
            } else if (second.isObjectExpression() || second.isParameterExpression()) {
                foreignKeyJoin = first.getMapping().buildObjectJoinExpression(first, second, getSession());
            } else {
                throw QueryException.invalidUseOfToManyQueryKeyInExpression(this);
            }
        }

        // DEFAULT:  Left and right are separate entities, and the
        // equal() will be replaced with a comparison by primary key.
        if (foreignKeyJoin == null) {
            first = (ObjectExpression)first.normalize(normalizer);

            // A ConstantExpression stores a selection object.  Compare the primary
            // keys of the first expression and the selection object.
            if (second.isConstantExpression()) {
                Object value = ((ConstantExpression)second).getValue();
                Expression keyExpression =
                    first.getDescriptor().getObjectBuilder().buildPrimaryKeyExpressionFromObject(value, getSession());

                foreignKeyJoin = first.twist(keyExpression, first);

                // Each expression will represent a separate table, so compare the primary
                // keys of the first and second expressions.
            } else if (second.isObjectExpression() || second.isParameterExpression()) {
                foreignKeyJoin =
                        first.twist(first.getDescriptor().getObjectBuilder().getPrimaryKeyExpression(), second);
            } else {
                throw QueryException.invalidUseOfToManyQueryKeyInExpression(this);
            }
        }
        if (this.operator.getSelector() == ExpressionOperator.NotEqual) {
            foreignKeyJoin = foreignKeyJoin.not();
        }

        return foreignKeyJoin.normalize(normalizer);
    }

    /**
     * INTERNAL:
     * Check if the object conforms to the expression in memory.
     * This is used for in-memory querying across object relationships.
     */
    public boolean performSelector(boolean areValuesEqual) {
        if (this.operator.getSelector() == ExpressionOperator.Equal) {
            return areValuesEqual;
        } else if (this.operator.getSelector() == ExpressionOperator.NotEqual) {
            return !areValuesEqual;
        } else {
            throw QueryException.cannotConformExpression();
        }
    }

    /**
     * INTERNAL:
     * Print SQL
     */
    @Override
    public void printSQL(ExpressionSQLPrinter printer) {
        // If both sides are parameters, some databases don't allow binding.
        if (printer.getPlatform().isDynamicSQLRequiredForFunctions()
                && ((this.firstChild.isParameterExpression() || this.firstChild.isConstantExpression())
                        && (this.secondChild.isParameterExpression() || this.secondChild.isConstantExpression()))) {
            printer.getCall().setUsesBinding(false);
        }
        if (isEqualNull(printer)) {
            this.firstChild.isNull().printSQL(printer);
        } else if (isNotEqualNull(printer)) {
            this.firstChild.notNull().printSQL(printer);
        } else {
            super.printSQL(printer);
        }
    }

    /**
     * INTERNAL:
     * Print java for project class generation
     */
    @Override
    public void printJava(ExpressionJavaPrinter printer) {
        ExpressionOperator realOperator = getPlatformOperator(printer.getPlatform());
        Expression tempFirstChild = this.firstChild;
        Expression tempSecondChild = this.secondChild;
        realOperator.printJavaDuo(tempFirstChild, tempSecondChild, printer);
    }

    /**
     * INTERNAL:
     * Print SQL without adding parentheses (for DB2 outer joins).
     */
    public void printSQLNoParens(ExpressionSQLPrinter printer) {
        ExpressionOperator realOperator = getPlatformOperator(printer.getPlatform());
        realOperator.printDuo(this.firstChild, this.secondChild, printer);
    }

    /**
     * Do any required validation for this node. Throw an exception if it's incorrect.
     */
    @Override
    public void validateNode() {
        if (this.firstChild.isTableExpression()) {
            throw QueryException.cannotCompareTablesInExpression(((TableExpression)this.firstChild).getTable());
        }
        if (this.secondChild.isTableExpression()) {
            throw QueryException.cannotCompareTablesInExpression(((TableExpression)this.secondChild).getTable());
        }
    }
}
