/*******************************************************************************
 * Copyright (c) 1998, 2014 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 v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * 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.*;

import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.descriptors.ClassDescriptor;

/**
 * <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.
     */
    protected void convertNodeToUseOuterJoin() {
        if ((this.operator.getSelector() == ExpressionOperator.Equal) && allChildrenAreFields()) {
            setOperator(getOperator(ExpressionOperator.EqualOuterJoin));
        }
    }

    /**
     * INTERNAL:
     * Used for debug printing.
     */
    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.
     */
    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 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 = ((AbstractColumnMapping)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 = ((AbstractColumnMapping)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 = ((AbstractColumnMapping)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 = ((AbstractColumnMapping)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 = Boolean.valueOf(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 = Boolean.valueOf(this.secondChild.isObjectExpression()
                            || this.secondChild.isValueExpression()
                            || this.secondChild.isSubSelectExpression()
                            || (this.secondChild.isFunctionExpression() && ((FunctionExpression)this.secondChild).operator.isAnyOrAll()));
                }
            }
        }
        return this.isObjectComparisonExpression.booleanValue();
    }

    /**
     * INTERNAL:
     */
    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.
     */
    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(Integer.valueOf(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(Integer.valueOf(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() && 
             (((QueryKeyExpression)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
     */
    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
     */
    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.
     */
    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());
        }
    }
}
