/*******************************************************************************
 * Copyright (c) 2013 Oracle. 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:
 *     11/06/2013-2.5.1 Chris Delahunt  
 *       - 374771 : TREAT support
 ******************************************************************************/ 
package org.eclipse.persistence.internal.expressions;

import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.history.DecoratedDatabaseTable;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.platform.database.DB2MainframePlatform;

/**
 * Holder class storing a QueryKeyExpression representing an outer join
 * plus some data calculated by method appendFromClauseForOuterJoin.
 */
public class OuterJoinExpressionHolder implements Comparable, Serializable
{
    final ObjectExpression joinExpression;
    DatabaseTable targetTable;
    DatabaseTable sourceTable;
    DatabaseTable targetAlias;
    DatabaseTable sourceAlias;
    List<DatabaseTable> additionalTargetTables;
    List<DatabaseTable> additionalTargetAliases;
    List<Expression> additionalJoinOnExpression;
    List<Boolean> additionalTargetIsDescriptorTable;
    Boolean hasInheritance;
    List<Integer> indexList;
    // if it's a map then an additional holder created for the key.
    // mapKeyHolder is not used in sorting because there can be no outer joins out of it,
    // the main reason for it to exist is its printAdditionalJoins method.
    OuterJoinExpressionHolder mapKeyHolder;
    // indicates whether it's a mapKeyHolder
    boolean isMapKeyHolder;

    Expression outerJoinedMappingCriteria;
    
    // table join expressions keyed by the tables
    Map<DatabaseTable, Expression> outerJoinedAdditionalJoinCriteria;
    // used in case no corresponding outerJoinExpression is provided - 
    // only multi-table inheritance should be outer joined
    ClassDescriptor descriptor;

    SQLSelectStatement statement;

    public OuterJoinExpressionHolder(SQLSelectStatement statement, ObjectExpression joinExpression, Expression outerJoinedMappingCriteria,
            Map<DatabaseTable, Expression> outerJoinedAdditionalJoinCriteria, ClassDescriptor descriptor) {
        this.statement = statement;
        this.joinExpression = joinExpression;

        this.outerJoinedMappingCriteria = outerJoinedMappingCriteria;
        this.outerJoinedAdditionalJoinCriteria = outerJoinedAdditionalJoinCriteria;
        this.descriptor = descriptor;
    }

    /*
     * Used for MapKeys
     */
    public OuterJoinExpressionHolder(OuterJoinExpressionHolder holder) {
        this.joinExpression = holder.joinExpression;

        this.outerJoinedMappingCriteria = holder.outerJoinedMappingCriteria;
        this.outerJoinedAdditionalJoinCriteria = holder.outerJoinedAdditionalJoinCriteria;
        this.descriptor = holder.descriptor;
    }

    protected void process(boolean usesHistory) {
        process(usesHistory, false);
    }
    
    protected void process(boolean usesHistory, boolean isMapKeyHolder) {
        this.isMapKeyHolder = isMapKeyHolder;
        if (this.joinExpression instanceof QueryKeyExpression) {
            QueryKeyExpression expression = (QueryKeyExpression)this.joinExpression;
            if (isMapKeyHolder) {
                descriptor = expression.getMapKeyDescriptor();
                this.targetTable = descriptor.getTables().get(0);
                this.targetAlias = outerJoinedMappingCriteria.aliasForTable(this.targetTable);
            } else {
                // this is a map - create a holder for the key
                if(expression.isMapKeyObjectRelationship()) {
                    this.mapKeyHolder = new OuterJoinExpressionHolder(this);
                    this.mapKeyHolder.process(usesHistory, true);
                }
                // in DirectCollection case descriptor is null
                descriptor = expression.getDescriptor();
                this.targetTable = expression.getReferenceTable();
                this.targetAlias = expression.aliasForTable(this.targetTable);
            }
            this.sourceTable = expression.getSourceTable();
            this.sourceAlias = expression.getBaseExpression().aliasForTable(this.sourceTable);
        } else if (this.joinExpression != null) {
            this.sourceTable = ((ObjectExpression)this.joinExpression.getJoinSource()).getDescriptor().getTables().get(0);
            this.sourceAlias = this.joinExpression.getJoinSource().aliasForTable(this.sourceTable);
            this.targetTable = this.joinExpression.getDescriptor().getTables().get(0);
            this.targetAlias = this.joinExpression.aliasForTable(this.targetTable);                
        } else {
            // absence of join expression means that this holder used for multitable inheritance:
            //   ReadAllQuery query = new ReadAllQuery(Project.class);
            //   query.setShouldOuterJoinSubclasses(true);
            // will produce: 
            //   SELECT ... FROM PROJECT t0 LEFT OUTER JOIN LPROJECT t1 ON (t1.PROJ_ID = t0.PROJ_ID)
            sourceTable = descriptor.getTables().get(0);
            targetTable = descriptor.getInheritancePolicy().getChildrenTables().get(0);
            Expression exp = outerJoinedAdditionalJoinCriteria.get(targetTable);
            sourceAlias = exp.aliasForTable(sourceTable);
            targetAlias = exp.aliasForTable(targetTable);
        }
        if(usesHistory) {
            sourceTable = getTableAliases().get(sourceAlias);
            targetTable = getTableAliases().get(targetAlias);
        }

        if(outerJoinedAdditionalJoinCriteria != null && !outerJoinedAdditionalJoinCriteria.isEmpty()) {
            if(descriptor == null) {
                descriptor = joinExpression.getDescriptor();
            }
            List targetTables = descriptor.getTables();
            int nDescriptorTables = targetTables.size();
            hasInheritance = descriptor.hasInheritance(); 
            if(hasInheritance) {
                targetTables = descriptor.getInheritancePolicy().getAllTables();
            }
            int tablesSize = targetTables.size();
            // skip main table - start with i=1
            for(int i=1; i < tablesSize; i++) {
                DatabaseTable table = (DatabaseTable)targetTables.get(i);
                Expression onExpression = outerJoinedAdditionalJoinCriteria.get(table);
                if (onExpression != null) {
                    DatabaseTable alias = onExpression.aliasForTable(table);
                    if (usesHistory) {
                        table = getTableAliases().get(alias);
                    }
                    if (this.additionalTargetAliases == null) {
                        this.additionalTargetAliases = new ArrayList();
                        this.additionalTargetTables = new ArrayList();
                        this.additionalJoinOnExpression = new ArrayList();
                        this.additionalTargetIsDescriptorTable = new ArrayList();
                    }
                    this.additionalTargetAliases.add(alias);
                    this.additionalTargetTables.add(table);
                    this.additionalJoinOnExpression.add(onExpression);
                    // if it's the descriptor's own table - true; otherwise (it's the child's table) - false.
                    this.additionalTargetIsDescriptorTable.add(i < nDescriptorTables);
                }
            }
        }
    }

    public boolean hasAdditionalJoinExpressions() {
        return this.additionalTargetTables != null;
    }

    public boolean hasMapKeyHolder() {
        return this.mapKeyHolder != null;
    }

    public void createIndexList(Map<DatabaseTable, OuterJoinExpressionHolder> targetAliasToHolders, Map<DatabaseTable, Integer> aliasToIndexes) {
        if(this.indexList != null) {
            // indexList has been already created
            return;
        }

        this.indexList = new ArrayList();
        OuterJoinExpressionHolder baseHolder = targetAliasToHolders.get(this.sourceAlias);
        if(baseHolder != null) {
            baseHolder.createIndexList(targetAliasToHolders, aliasToIndexes);
            this.indexList.addAll(baseHolder.indexList);
        } else {
            this.indexList.add(aliasToIndexes.get(this.sourceAlias));
        }
        this.indexList.add(aliasToIndexes.get(this.targetAlias));
    }

    /*
     * The method should be called only on instances of OuterJoinExpressionHolder
     * and only after the indexList has been created.
     * Loop through both lists comparing the members corresponding to the same index
     * until not equal members are found.
     * If all the members are the same, but one of the lists is shorter then it's less.
     * Examples:
     * {2, 1} < {2, 2}; {2, 1} < {3}; {2, 1} > {2}
     */
    public int compareTo(Object other) {
        if(other == this) {
            return 0;
        }
        List<Integer> otherIndexList = ((OuterJoinExpressionHolder)other).indexList;
        int nMinSize = this.indexList.size();
        int nCompare = -1;
        int nOtherSize = otherIndexList.size();
        if(nMinSize > nOtherSize) {
            nMinSize = nOtherSize;
            nCompare = 1;
        } else if(nMinSize == nOtherSize) {
            nCompare = 0;
        }
        for(int i=0; i < nMinSize; i++) {
            int index = indexList.get(i);
            int otherIndex = otherIndexList.get(i);
            if(index < otherIndex) {
                return -1;
            } else if(index > otherIndex) {
                return 1;
            }
        }
        return nCompare;
    }

    void printAdditionalJoins(ExpressionSQLPrinter printer, List<DatabaseTable> outerJoinedAliases, Collection aliasesOfTablesToBeLocked, boolean shouldPrintUpdateClauseForAllTables)  throws IOException {
        Writer writer = printer.getWriter();
        AbstractSession session = printer.getSession();

        int size = this.additionalTargetAliases.size();
        for(int i=0; i < size; i++) {
            DatabaseTable table = this.additionalTargetTables.get(i);
            if(this.additionalTargetIsDescriptorTable.get(i)) {
                // it's descriptor's own table
                if (!session.getPlatform().supportsANSIInnerJoinSyntax()) {
                    // if the DB does not support 'JOIN', do a:
                    if (this.hasInheritance) {
                        // right outer join instead. This will give the same
                        // result because the right table has no rows that
                        // are not in the left table (left table maps to the
                        // main class, right table to a subclass in an
                        // inheritance mapping with a joined subclass
                        // strategy).
                        writer.write(" RIGHT OUTER");
                    } else {
                        // left outer join instead. This will give the same
                        // result because the left table has no rows that
                        // are not in the right table (left table is either
                        // a join table or it is joining secondary tables to
                        // a primary table).
                        writer.write(" LEFT OUTER");
                    }
                }
                writer.write(" JOIN ");
            } else {
                // it's child's table
                writer.write(" LEFT OUTER JOIN ");
            }
            DatabaseTable alias = this.additionalTargetAliases.get(i);
            table.printSQL(printer);
            writer.write(" ");
            if (alias.isDecorated()) {
                ((DecoratedDatabaseTable)alias).getAsOfClause().printSQL(printer);
                writer.write(" ");
            }
            outerJoinedAliases.add(alias);
            alias.printSQL(printer);
            if (shouldPrintUpdateClauseForAllTables || (aliasesOfTablesToBeLocked != null && aliasesOfTablesToBeLocked.remove(alias))) {
                getForUpdateClause().printSQL(printer, statement/*SQLSelectStatement.this*/);
            }
            writer.write(" ON ");
            if (session.getPlatform() instanceof DB2MainframePlatform) {
                ((RelationExpression)this.additionalJoinOnExpression.get(i)).printSQLNoParens(printer);
            } else {
                this.additionalJoinOnExpression.get(i).printSQL(printer);
            }
        }
    }

    /**
     * INTERNAL:
     * Return the aliases used.
     */
    public Map<DatabaseTable, DatabaseTable> getTableAliases() {
        return statement.getTableAliases();
    }

    protected ForUpdateClause getForUpdateClause() {
        return statement.getForUpdateClause();
    }
}
