/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.pig.test;

import java.util.List;

import org.apache.pig.data.DataType;
import org.apache.pig.impl.logicalLayer.FrontendException;
import org.apache.pig.impl.util.MultiMap;
import org.apache.pig.newplan.DepthFirstWalker;
import org.apache.pig.newplan.Operator;
import org.apache.pig.newplan.OperatorPlan;
import org.apache.pig.newplan.logical.expression.AndExpression;
import org.apache.pig.newplan.logical.expression.ConstantExpression;
import org.apache.pig.newplan.logical.expression.EqualExpression;
import org.apache.pig.newplan.logical.expression.LogicalExpressionPlan;
import org.apache.pig.newplan.logical.expression.LogicalExpressionVisitor;
import org.apache.pig.newplan.logical.expression.ProjectExpression;
import org.apache.pig.newplan.logical.optimizer.AllExpressionVisitor;
import org.apache.pig.newplan.logical.optimizer.AllSameRalationalNodesVisitor;
import org.apache.pig.newplan.logical.optimizer.ProjectionPatcher;
import org.apache.pig.newplan.logical.optimizer.SchemaPatcher;
import org.apache.pig.newplan.logical.relational.LOFilter;
import org.apache.pig.newplan.logical.relational.LOJoin;
import org.apache.pig.newplan.logical.relational.LOLoad;
import org.apache.pig.newplan.logical.relational.LogicalPlan;
import org.apache.pig.newplan.logical.relational.LogicalRelationalOperator;
import org.apache.pig.newplan.logical.relational.LogicalSchema;
import org.apache.pig.newplan.logical.relational.LOJoin.JOINTYPE;
import org.apache.pig.newplan.logical.relational.LogicalSchema.LogicalFieldSchema;
import org.junit.Before;
import org.junit.Test;

import junit.framework.TestCase;

/**
 * Tests for PlanTransformListerns
 *
 */
public class TestNewPlanListener extends TestCase {
    
    private LogicalPlan lp;
    private LogicalPlan changedPlan;

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    @Before
    protected void setUp() throws Exception {
        super.setUp();
        
        // Build a plan that looks like it has just been transformed
        // It is roughly the logical plan for
        // A = load 'bla' as (x);
        // B = load 'morebla' as (y);
        // C = join A on x, B on y;
        // D = filter C by y > 0;
        // The plan is built with the filter having been pushed above the join
        // but the listners not yet having been called.
        // A = load
        lp = new LogicalPlan();
        LogicalSchema aschema = new LogicalSchema();
        aschema.addField(new LogicalSchema.LogicalFieldSchema(
            "x", null, DataType.INTEGER));
        aschema.getField(0).uid = 1;
        LOLoad A = new LOLoad(null, lp);
        A.neverUseForRealSetSchema(aschema);
        lp.add(A);
        
        // B = load
        LogicalSchema bschema = new LogicalSchema();
        bschema.addField(new LogicalSchema.LogicalFieldSchema(
            "y", null, DataType.INTEGER));
        bschema.getField(0).uid = 2;
        LOLoad B = new LOLoad(null, lp);
        B.neverUseForRealSetSchema(bschema);
        lp.add(B);
        
        // C = join
        LogicalSchema cschema = new LogicalSchema();
        cschema.addField(new LogicalSchema.LogicalFieldSchema(
            "x", null, DataType.INTEGER));
        cschema.addField(new LogicalSchema.LogicalFieldSchema(
            "y", null, DataType.INTEGER));
        cschema.getField(0).uid = 1;
        cschema.getField(1).uid = 2;

        MultiMap<Integer, LogicalExpressionPlan> mm = 
            new MultiMap<Integer, LogicalExpressionPlan>();
        LOJoin C = new LOJoin(lp, mm, JOINTYPE.HASH, new boolean[] {true, true});
        
        LogicalExpressionPlan aprojplan = new LogicalExpressionPlan();
        ProjectExpression x = new ProjectExpression(aprojplan, 0, 0, C);
        x.neverUseForRealSetFieldSchema(new LogicalFieldSchema(null, null,
                DataType.INTEGER, 1));
        LogicalExpressionPlan bprojplan = new LogicalExpressionPlan();
        ProjectExpression y = new ProjectExpression(bprojplan, 1, 0, C);
        y.neverUseForRealSetFieldSchema(new LogicalFieldSchema(null, null,
                DataType.INTEGER, 2));
        mm.put(0, aprojplan);
        mm.put(1, bprojplan);
        
        C.neverUseForRealSetSchema(cschema);
        // Don't add it to the plan quite yet
        
        // D = filter
        LogicalExpressionPlan filterPlan = new LogicalExpressionPlan();
        LOFilter D = new LOFilter(lp, filterPlan);
        ProjectExpression fy = new ProjectExpression(filterPlan, 0, 1, D);
        fy.neverUseForRealSetFieldSchema(new LogicalFieldSchema(null, null,
                DataType.INTEGER, 2));
        ConstantExpression fc = new ConstantExpression(filterPlan, new Integer(0));
        new EqualExpression(filterPlan, fy, fc);
        
        D.neverUseForRealSetSchema(cschema);
        // Connect D to B, since the transform has happened.
        lp.add(D);
        lp.connect(B, D);
        
        // Now add in C, connected to A and D.
        lp.add(C);
        lp.connect(A, C);
        lp.connect(D, C);
        
        changedPlan = new LogicalPlan();
        changedPlan.add(D);
        changedPlan.add(C);
        changedPlan.connect(D, C);
    }
    
    private static class SillySameVisitor extends AllSameRalationalNodesVisitor {
        StringBuffer buf = new StringBuffer();

        SillySameVisitor(OperatorPlan plan) throws FrontendException {
            super(plan, new DepthFirstWalker(plan));
        }
        
        @Override
        protected void execute(LogicalRelationalOperator op) throws FrontendException {
            buf.append(op.getName());
            buf.append(" ");
        }
        
        @Override
        public String toString() {
            return buf.toString();
        }
        
    }
    
    // Test that the AllSameVisitor calls execute on every node
    // in the plan.
    @Test
    public void testAllSameVisitor() throws FrontendException {
        SillySameVisitor v = new SillySameVisitor(lp);
        v.visit();
        assertTrue("LOLoad LOJoin(HASH) LOLoad LOFilter ".equals(v.toString()) ||
            "LOLoad LOFilter LOJoin(HASH) LOLoad ".equals(v.toString()));
        
    }
    
    private static class SillyExpressionVisitor extends LogicalExpressionVisitor {
        StringBuffer buf;

        protected SillyExpressionVisitor(OperatorPlan p, StringBuffer b) throws FrontendException {
            super(p, new DepthFirstWalker(p));
            buf = b;
        }
        
        @Override
        public void visit(AndExpression andExpr) throws FrontendException {
            buf.append("and ");
        }
        
        @Override
        public void visit(EqualExpression equal) throws FrontendException {
            buf.append("equal ");
        }
        
        @Override
        public void visit(ProjectExpression p) throws FrontendException {
            buf.append("proj ");
        }
        
        @Override
        public void visit(ConstantExpression c) throws FrontendException {
            buf.append("const ");
        }
    }
    
    private static class SillyAllExpressionVisitor extends AllExpressionVisitor {
        StringBuffer buf = new StringBuffer();

        public SillyAllExpressionVisitor(OperatorPlan plan) throws FrontendException {
            super(plan, new DepthFirstWalker(plan));
        }
     

        @Override
        protected LogicalExpressionVisitor getVisitor(LogicalExpressionPlan expr) throws FrontendException {
            return new SillyExpressionVisitor(expr, buf);
        }   
        
        @Override
        public String toString() {
            return buf.toString();
        }
    }
    
    // Test that the AllExpressionVisitor executes on every
    // expression in the plan
    @Test
    public void testAllExpressionVisitor() throws FrontendException {
        SillyAllExpressionVisitor v = new SillyAllExpressionVisitor(lp);
        v.visit();
        assertTrue("proj proj equal proj const ".equals(v.toString()) ||
            "equal proj const proj proj ".equals(v.toString()));
    }
    
    // Test that schemas are patched up after a transform
    @Test
    public void testSchemaPatcher() throws FrontendException {
        SchemaPatcher patcher = new SchemaPatcher();
        patcher.transformed(lp, changedPlan);
        
        // Check that the filter now has the proper schema.
        List<Operator> roots = changedPlan.getSources();
        assertEquals(1, roots.size());
        LOFilter D = (LOFilter)roots.get(0);
        assertNotNull(D);
        LogicalSchema dschema = D.getSchema();
        assertEquals(1, dschema.size());
        LogicalSchema.LogicalFieldSchema y = dschema.getField(0);
        assertEquals("y", y.alias);
        assertEquals(2, y.uid);
    }
    
    // Test that projections are patched up after a transform
    @Test
    public void testProjectionPatcher() throws FrontendException {
        ProjectionPatcher patcher = new ProjectionPatcher();
        patcher.transformed(lp, changedPlan);
        
        // Check that the projections in filter are now set properly
        List<Operator> roots = changedPlan.getSources();
        assertEquals(1, roots.size());
        LOFilter D = (LOFilter)roots.get(0);
        assertNotNull(D);
        LogicalExpressionPlan filterPlan = D.getFilterPlan();
        List<Operator> leaves = filterPlan.getSinks();
        assertEquals(2, leaves.size());
        ProjectExpression proj = null;
        for (Operator leaf : leaves) {
            if (leaf instanceof ProjectExpression) {
                proj = (ProjectExpression)leaf;
                break;
            }
        }
        assertNotNull(proj);
        assertEquals(0, proj.getInputNum());
        assertEquals(0, proj.getColNum());
    }

}

