/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */
/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed 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.
 */
/*
 * $Id: Predicate.java,v 1.2.4.1 2005/09/12 11:02:18 pvedula Exp $
 */

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);
        }
    }
}
