/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */
/*
 * 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 com.sun.org.apache.xalan.internal.xsltc.compiler;

import java.util.ArrayList;

import com.sun.org.apache.bcel.internal.classfile.Field;
import com.sun.org.apache.bcel.internal.generic.ASTORE;
import com.sun.org.apache.bcel.internal.generic.CHECKCAST;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
import com.sun.org.apache.bcel.internal.generic.GETFIELD;
import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
import com.sun.org.apache.bcel.internal.generic.InstructionList;
import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.sun.org.apache.bcel.internal.generic.PUSH;
import com.sun.org.apache.bcel.internal.generic.PUTFIELD;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.BooleanType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.FilterGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.IntType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NumberType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TestGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
import com.sun.org.apache.xalan.internal.xsltc.runtime.Operators;

/**
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 * @author Morten Jorgensen
 */
final class Predicate extends Expression implements Closure {

    /**
     * The predicate's expression.
     */
    private Expression _exp = null;

    /**
     * This flag indicates if optimizations are turned on. The
     * method <code>dontOptimize()</code> can be called to turn
     * optimizations off.
     */
    private boolean _canOptimize = true;

    /**
     * Flag indicatig if the nth position optimization is on. It
     * is set in <code>typeCheck()</code>.
     */
    private boolean _nthPositionFilter = false;

    /**
     * Flag indicatig if the nth position descendant is on. It
     * is set in <code>typeCheck()</code>.
     */
    private boolean _nthDescendant = false;

    /**
     * Cached node type of the expression that owns this predicate.
     */
    int _ptype = -1;

    /**
     * Name of the inner class.
     */
    private String _className = null;

    /**
     * List of variables in closure.
     */
    private ArrayList _closureVars = null;

    /**
     * Reference to parent closure.
     */
    private Closure _parentClosure = null;

    /**
     * Cached value of method <code>getCompareValue()</code>.
     */
    private Expression _value = null;

    /**
     * Cached value of method <code>getCompareValue()</code>.
     */
    private Step _step = null;

    /**
     * Initializes a predicate.
     */
    public Predicate(Expression exp) {
        _exp = exp;
        _exp.setParent(this);

    }

    /**
     * Set the parser for this expression.
     */
    public void setParser(Parser parser) {
        super.setParser(parser);
        _exp.setParser(parser);
    }

    /**
     * Returns a boolean value indicating if the nth position optimization
     * is on. Must be call after type checking!
     */
    public boolean isNthPositionFilter() {
        return _nthPositionFilter;
    }

    /**
     * Returns a boolean value indicating if the nth descendant optimization
     * is on. Must be call after type checking!
     */
    public boolean isNthDescendant() {
        return _nthDescendant;
    }

    /**
     * Turns off all optimizations for this predicate.
     */
    public void dontOptimize() {
        _canOptimize = false;
    }

    /**
     * Returns true if the expression in this predicate contains a call
     * to position().
     */
    public boolean hasPositionCall() {
        return _exp.hasPositionCall();
    }

    /**
     * Returns true if the expression in this predicate contains a call
     * to last().
     */
    public boolean hasLastCall() {
        return _exp.hasLastCall();
    }

    // -- Begin Closure interface --------------------

    /**
     * Returns true if this closure is compiled in an inner class (i.e.
     * if this is a real closure).
     */
    public boolean inInnerClass() {
        return (_className != null);
    }

    /**
     * Returns a reference to its parent closure or null if outermost.
     */
    public Closure getParentClosure() {
        if (_parentClosure == null) {
            SyntaxTreeNode node = getParent();
            do {
                if (node instanceof Closure) {
                    _parentClosure = (Closure) node;
                    break;
                }
                if (node instanceof TopLevelElement) {
                    break;      // way up in the tree
                }
                node = node.getParent();
            } while (node != null);
        }
        return _parentClosure;
    }

    /**
     * Returns the name of the auxiliary class or null if this predicate
     * is compiled inside the Translet.
     */
    public String getInnerClassName() {
        return _className;
    }

    /**
     * Add new variable to the closure.
     */
    public void addVariable(VariableRefBase variableRef) {
        if (_closureVars == null) {
            _closureVars = new ArrayList();
        }

        // Only one reference per variable
        if (!_closureVars.contains(variableRef)) {
            _closureVars.add(variableRef);

            // Add variable to parent closure as well
            Closure parentClosure = getParentClosure();
            if (parentClosure != null) {
                parentClosure.addVariable(variableRef);
            }
        }
    }

    // -- End Closure interface ----------------------

    /**
     * Returns the node type of the expression owning this predicate. The
     * return value is cached in <code>_ptype</code>.
     */
    public int getPosType() {
        if (_ptype == -1) {
            SyntaxTreeNode parent = getParent();
            if (parent instanceof StepPattern) {
                _ptype = ((StepPattern)parent).getNodeType();
            }
            else if (parent instanceof AbsoluteLocationPath) {
                AbsoluteLocationPath path = (AbsoluteLocationPath)parent;
                Expression exp = path.getPath();
                if (exp instanceof Step) {
                    _ptype = ((Step)exp).getNodeType();
                }
            }
            else if (parent instanceof VariableRefBase) {
                final VariableRefBase ref = (VariableRefBase)parent;
                final VariableBase var = ref.getVariable();
                final Expression exp = var.getExpression();
                if (exp instanceof Step) {
                    _ptype = ((Step)exp).getNodeType();
                }
            }
            else if (parent instanceof Step) {
                _ptype = ((Step)parent).getNodeType();
            }
        }
        return _ptype;
    }

    public boolean parentIsPattern() {
        return (getParent() instanceof Pattern);
    }

    public Expression getExpr() {
        return _exp;
    }

    public String toString() {
        return "pred(" + _exp + ')';
    }

    /**
     * Type check a predicate expression. If the type of the expression is
     * number convert it to boolean by adding a comparison with position().
     * Note that if the expression is a parameter, we cannot distinguish
     * at compile time if its type is number or not. Hence, expressions of
     * reference type are always converted to booleans.
     *
     * This method may be called twice, before and after calling
     * <code>dontOptimize()</code>. If so, the second time it should honor
     * the new value of <code>_canOptimize</code>.
     */
    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
        Type texp = _exp.typeCheck(stable);

        // We need explicit type information for reference types - no good!
        if (texp instanceof ReferenceType) {
            _exp = new CastExpr(_exp, texp = Type.Real);
        }

        // A result tree fragment should not be cast directly to a number type,
        // but rather to a boolean value, and then to a numer (0 or 1).
        // Ref. section 11.2 of the XSLT 1.0 spec
        if (texp instanceof ResultTreeType) {
            _exp = new CastExpr(_exp, Type.Boolean);
            _exp = new CastExpr(_exp, Type.Real);
            texp = _exp.typeCheck(stable);
        }

        // Numerical types will be converted to a position filter
        if (texp instanceof NumberType) {
            // Cast any numerical types to an integer
            if (texp instanceof IntType == false) {
                _exp = new CastExpr(_exp, Type.Int);
            }

            if (_canOptimize) {
                // Nth position optimization. Expression must not depend on context
                _nthPositionFilter =
                    !_exp.hasLastCall() && !_exp.hasPositionCall();

                // _nthDescendant optimization - only if _nthPositionFilter is on
                if (_nthPositionFilter) {
                    SyntaxTreeNode parent = getParent();
                    _nthDescendant = (parent instanceof Step) &&
                        (parent.getParent() instanceof AbsoluteLocationPath);
                    return _type = Type.NodeSet;
                }
            }

           // Reset optimization flags
            _nthPositionFilter = _nthDescendant = false;

           // Otherwise, expand [e] to [position() = e]
           final QName position =
                getParser().getQNameIgnoreDefaultNs("position");
           final PositionCall positionCall =
                new PositionCall(position);
           positionCall.setParser(getParser());
           positionCall.setParent(this);

           _exp = new EqualityExpr(Operators.EQ, positionCall,
                                    _exp);
           if (_exp.typeCheck(stable) != Type.Boolean) {
               _exp = new CastExpr(_exp, Type.Boolean);
           }
           return _type = Type.Boolean;
        }
        else {
            // All other types will be handled as boolean values
            if (texp instanceof BooleanType == false) {
                _exp = new CastExpr(_exp, Type.Boolean);
            }
            return _type = Type.Boolean;
        }
    }

    /**
     * Create a new "Filter" class implementing
     * <code>CurrentNodeListFilter</code>. Allocate registers for local
     * variables and local parameters passed in the closure to test().
     * Notice that local variables need to be "unboxed".
     */
    private void compileFilter(ClassGenerator classGen,
                               MethodGenerator methodGen) {
        TestGenerator testGen;
        LocalVariableGen local;
        FilterGenerator filterGen;

        _className = getXSLTC().getHelperClassName();
        filterGen = new FilterGenerator(_className,
                                        "java.lang.Object",
                                        toString(),
                                        ACC_PUBLIC | ACC_SUPER,
                                        new String[] {
                                            CURRENT_NODE_LIST_FILTER
                                        },
                                        classGen.getStylesheet());

        final ConstantPoolGen cpg = filterGen.getConstantPool();
        final int length = (_closureVars == null) ? 0 : _closureVars.size();

        // Add a new instance variable for each var in closure
        for (int i = 0; i < length; i++) {
            VariableBase var = ((VariableRefBase) _closureVars.get(i)).getVariable();

            filterGen.addField(new Field(ACC_PUBLIC,
                                        cpg.addUtf8(var.getEscapedName()),
                                        cpg.addUtf8(var.getType().toSignature()),
                                        null, cpg.getConstantPool()));
        }

        final InstructionList il = new InstructionList();
        testGen = new TestGenerator(ACC_PUBLIC | ACC_FINAL,
                                    com.sun.org.apache.bcel.internal.generic.Type.BOOLEAN,
                                    new com.sun.org.apache.bcel.internal.generic.Type[] {
                                        com.sun.org.apache.bcel.internal.generic.Type.INT,
                                        com.sun.org.apache.bcel.internal.generic.Type.INT,
                                        com.sun.org.apache.bcel.internal.generic.Type.INT,
                                        com.sun.org.apache.bcel.internal.generic.Type.INT,
                                        Util.getJCRefType(TRANSLET_SIG),
                                        Util.getJCRefType(NODE_ITERATOR_SIG)
                                    },
                                    new String[] {
                                        "node",
                                        "position",
                                        "last",
                                        "current",
                                        "translet",
                                        "iterator"
                                    },
                                    "test", _className, il, cpg);

        // Store the dom in a local variable
        local = testGen.addLocalVariable("document",
                                         Util.getJCRefType(DOM_INTF_SIG),
                                         null, null);
        final String className = classGen.getClassName();
        il.append(filterGen.loadTranslet());
        il.append(new CHECKCAST(cpg.addClass(className)));
        il.append(new GETFIELD(cpg.addFieldref(className,
                                               DOM_FIELD, DOM_INTF_SIG)));
        local.setStart(il.append(new ASTORE(local.getIndex())));

        // Store the dom index in the test generator
        testGen.setDomIndex(local.getIndex());

        _exp.translate(filterGen, testGen);
        il.append(IRETURN);

        filterGen.addEmptyConstructor(ACC_PUBLIC);
        filterGen.addMethod(testGen);

        getXSLTC().dumpClass(filterGen.getJavaClass());
    }

    /**
     * Returns true if the predicate is a test for the existance of an
     * element or attribute. All we have to do is to get the first node
     * from the step, check if it is there, and then return true/false.
     */
    public boolean isBooleanTest() {
        return (_exp instanceof BooleanExpr);
    }

    /**
     * Method to see if we can optimise the predicate by using a specialised
     * iterator for expressions like '/foo/bar[@attr = $var]', which are
     * very common in many stylesheets
     */
    public boolean isNodeValueTest() {
        if (!_canOptimize) return false;
        return (getStep() != null && getCompareValue() != null);
    }

   /**
     * Returns the step in an expression of the form 'step = value'.
     * Null is returned if the expression is not of the right form.
     * Optimization if off if null is returned.
     */
    public Step getStep() {
        // Returned cached value if called more than once
        if (_step != null) {
            return _step;
        }

        // Nothing to do if _exp is null
        if (_exp == null) {
            return null;
        }

        // Ignore if not equality expression
        if (_exp instanceof EqualityExpr) {
            EqualityExpr exp = (EqualityExpr)_exp;
            Expression left = exp.getLeft();
            Expression right = exp.getRight();

            // Unwrap and set _step if appropriate
            if (left instanceof CastExpr) {
                left = ((CastExpr) left).getExpr();
            }
            if (left instanceof Step) {
                _step = (Step) left;
            }

            // Unwrap and set _step if appropriate
            if (right instanceof CastExpr) {
                right = ((CastExpr)right).getExpr();
            }
            if (right instanceof Step) {
                _step = (Step)right;
            }
        }
        return _step;
    }

    /**
     * Returns the value in an expression of the form 'step = value'.
     * A value may be either a literal string or a variable whose
     * type is string. Optimization if off if null is returned.
     */
    public Expression getCompareValue() {
        // Returned cached value if called more than once
        if (_value != null) {
            return _value;
        }

        // Nothing to to do if _exp is null
        if (_exp == null) {
            return null;
        }

        // Ignore if not an equality expression
        if (_exp instanceof EqualityExpr) {
            EqualityExpr exp = (EqualityExpr) _exp;
            Expression left = exp.getLeft();
            Expression right = exp.getRight();

            // Return if left is literal string
            if (left instanceof LiteralExpr) {
                _value = left;
                return _value;
            }
            // Return if left is a variable reference of type string
            if (left instanceof VariableRefBase &&
                left.getType() == Type.String)
            {
                _value = left;
                return _value;
            }

            // Return if right is literal string
            if (right instanceof LiteralExpr) {
                _value = right;
                return _value;
            }
            // Return if left is a variable reference whose type is string
            if (right instanceof VariableRefBase &&
                right.getType() == Type.String)
            {
                _value = right;
                return _value;
            }
        }
        return null;
    }

    /**
     * Translate a predicate expression. This translation pushes
     * two references on the stack: a reference to a newly created
     * filter object and a reference to the predicate's closure.
     */
    public void translateFilter(ClassGenerator classGen,
                                MethodGenerator methodGen)
    {
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = methodGen.getInstructionList();

        // Compile auxiliary class for filter
        compileFilter(classGen, methodGen);

        // Create new instance of filter
        il.append(new NEW(cpg.addClass(_className)));
        il.append(DUP);
        il.append(new INVOKESPECIAL(cpg.addMethodref(_className,
                                                     "<init>", "()V")));

        // Initialize closure variables
        final int length = (_closureVars == null) ? 0 : _closureVars.size();

        for (int i = 0; i < length; i++) {
            VariableRefBase varRef = (VariableRefBase) _closureVars.get(i);
            VariableBase var = varRef.getVariable();
            Type varType = var.getType();

            il.append(DUP);

            // Find nearest closure implemented as an inner class
            Closure variableClosure = _parentClosure;
            while (variableClosure != null) {
                if (variableClosure.inInnerClass()) break;
                variableClosure = variableClosure.getParentClosure();
            }

            // Use getfield if in an inner class
            if (variableClosure != null) {
                il.append(ALOAD_0);
                il.append(new GETFIELD(
                    cpg.addFieldref(variableClosure.getInnerClassName(),
                        var.getEscapedName(), varType.toSignature())));
            }
            else {
                // Use a load of instruction if in translet class
                il.append(var.loadInstruction());
            }

            // Store variable in new closure
            il.append(new PUTFIELD(
                    cpg.addFieldref(_className, var.getEscapedName(),
                        varType.toSignature())));
        }
    }

    /**
     * Translate a predicate expression. If non of the optimizations apply
     * then this translation pushes two references on the stack: a reference
     * to a newly created filter object and a reference to the predicate's
     * closure. See class <code>Step</code> for further details.
     */
    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {

        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = methodGen.getInstructionList();

        if (_nthPositionFilter || _nthDescendant) {
            _exp.translate(classGen, methodGen);
        }
        else if (isNodeValueTest() && (getParent() instanceof Step)) {
            _value.translate(classGen, methodGen);
            il.append(new CHECKCAST(cpg.addClass(STRING_CLASS)));
            il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp()));
        }
        else {
            translateFilter(classGen, methodGen);
        }
    }
}
