/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * 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.
 */
/*
 * $Id: Mode.java,v 1.2.4.1 2005/09/19 05:18:11 pvedula Exp $
 */

package com.sun.org.apache.xalan.internal.xsltc.compiler;

import com.sun.org.apache.bcel.internal.generic.BranchHandle;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
import com.sun.org.apache.bcel.internal.generic.DUP;
import com.sun.org.apache.bcel.internal.generic.GOTO_W;
import com.sun.org.apache.bcel.internal.generic.IFLT;
import com.sun.org.apache.bcel.internal.generic.ILOAD;
import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
import com.sun.org.apache.bcel.internal.generic.ISTORE;
import com.sun.org.apache.bcel.internal.generic.Instruction;
import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
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.SWITCH;
import com.sun.org.apache.bcel.internal.generic.TargetLostException;
import com.sun.org.apache.bcel.internal.util.InstructionFinder;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NamedMethodGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
import com.sun.org.apache.xml.internal.dtm.Axis;
import com.sun.org.apache.xml.internal.dtm.DTM;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

/**
 * Mode gathers all the templates belonging to a given mode;
 * it is responsible for generating an appropriate
 * applyTemplates + (mode name) method in the translet.
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 * @author Morten Jorgensen
 * @author Erwin Bolwidt <ejb@klomp.org>
 * @author G. Todd Miller
 */
final class Mode implements Constants {

    /**
     * The name of this mode as defined in the stylesheet.
     */
    private final QName _name;

    /**
     * A reference to the stylesheet object that owns this mode.
     */
    private final Stylesheet _stylesheet;

    /**
     * The name of the method in which this mode is compiled.
     */
    private final String _methodName;

    /**
     * A vector of all the templates in this mode.
     */
    private Vector _templates;

    /**
     * Group for patterns with node()-type kernel and child axis.
     */
    private Vector _childNodeGroup = null;

    /**
     * Test sequence for patterns with node()-type kernel and child axis.
     */
    private TestSeq _childNodeTestSeq = null;

    /**
     * Group for patterns with node()-type kernel and attribute axis.
     */
    private Vector _attribNodeGroup = null;

    /**
     * Test sequence for patterns with node()-type kernel and attribute axis.
     */
    private TestSeq _attribNodeTestSeq = null;

    /**
     * Group for patterns with id() or key()-type kernel.
     */
    private Vector _idxGroup = null;

    /**
     * Test sequence for patterns with id() or key()-type kernel.
     */
    private TestSeq _idxTestSeq = null;

    /**
     * Group for patterns with any other kernel type.
     */
    private Vector[] _patternGroups;

    /**
     * Test sequence for patterns with any other kernel type.
     */
    private TestSeq[] _testSeq;


    /**
     * A mapping between templates and test sequences.
     */
    private Map<Template, Object> _neededTemplates = new HashMap<>();

    /**
     * A mapping between named templates and Mode objects.
     */
    private Map<Template, Mode> _namedTemplates = new HashMap<>();

    /**
     * A mapping between templates and instruction handles.
     */
    private Map<Template, InstructionHandle> _templateIHs = new HashMap<>();

    /**
     * A mapping between templates and instruction lists.
     */
    private Map<Template, InstructionList> _templateILs = new HashMap<>();

    /**
     * A reference to the pattern matching the root node.
     */
    private LocationPathPattern _rootPattern = null;

    /**
     * Stores ranges of template precendences for the compilation
     * of apply-imports.
     */
    private Map<Integer, Integer> _importLevels = null;

    /**
     * A mapping between key names and keys.
     */
    private Map<String, Key> _keys = null;

    /**
     * Variable index for the current node used in code generation.
     */
    private int _currentIndex;

    /**
     * Creates a new Mode.
     *
     * @param name A textual representation of the mode's QName
     * @param stylesheet The Stylesheet in which the mode occured
     * @param suffix A suffix to append to the method name for this mode
     *               (normally a sequence number - still in a String).
     */
    public Mode(QName name, Stylesheet stylesheet, String suffix) {
        _name = name;
        _stylesheet = stylesheet;
        _methodName = APPLY_TEMPLATES + suffix;
        _templates = new Vector();
        _patternGroups = new Vector[32];
    }

    /**
     * Returns the name of the method (_not_ function) that will be
     * compiled for this mode. Normally takes the form 'applyTemplates()'
     * or * 'applyTemplates2()'.
     *
     * @return Method name for this mode
     */
    public String functionName() {
        return _methodName;
    }

    public String functionName(int min, int max) {
        if (_importLevels == null) {
            _importLevels = new HashMap<>();
        }
        _importLevels.put(max, min);
        return _methodName + '_' + max;
    }

    /**
     * Shortcut to get the class compiled for this mode (will be inlined).
     */
    private String getClassName() {
        return _stylesheet.getClassName();
    }

    public Stylesheet getStylesheet() {
        return _stylesheet;
    }

    public void addTemplate(Template template) {
        _templates.addElement(template);
    }

    private Vector quicksort(Vector templates, int p, int r) {
        if (p < r) {
            final int q = partition(templates, p, r);
            quicksort(templates, p, q);
            quicksort(templates, q + 1, r);
        }
        return templates;
    }

    private int partition(Vector templates, int p, int r) {
        final Template x = (Template)templates.elementAt(p);
        int i = p - 1;
        int j = r + 1;
        while (true) {
            while (x.compareTo((Template)templates.elementAt(--j)) > 0);
            while (x.compareTo((Template)templates.elementAt(++i)) < 0);
            if (i < j) {
                templates.set(j, templates.set(i, templates.elementAt(j)));
            }
            else {
                return j;
            }
        }
    }

    /**
     * Process all the test patterns in this mode
     */
    public void processPatterns(Map<String, Key> keys) {
        _keys = keys;

/*
System.out.println("Before Sort " + _name);
for (int i = 0; i < _templates.size(); i++) {
    System.out.println("name = " + ((Template)_templates.elementAt(i)).getName());
    System.out.println("pattern = " + ((Template)_templates.elementAt(i)).getPattern());
    System.out.println("priority = " + ((Template)_templates.elementAt(i)).getPriority());
    System.out.println("position = " + ((Template)_templates.elementAt(i)).getPosition());
}
*/

        _templates = quicksort(_templates, 0, _templates.size() - 1);

/*
System.out.println("\n After Sort " + _name);
for (int i = 0; i < _templates.size(); i++) {
    System.out.println("name = " + ((Template)_templates.elementAt(i)).getName());
    System.out.println("pattern = " + ((Template)_templates.elementAt(i)).getPattern());
    System.out.println("priority = " + ((Template)_templates.elementAt(i)).getPriority());
    System.out.println("position = " + ((Template)_templates.elementAt(i)).getPosition());
}
*/

        // Traverse all templates
        final Enumeration templates = _templates.elements();
        while (templates.hasMoreElements()) {
            // Get the next template
            final Template template = (Template)templates.nextElement();

            /*
             * Add this template to a table of named templates if it has a name.
             * If there are multiple templates with the same name, all but one
             * (the one with highest priority) will be disabled.
             */
            if (template.isNamed() && !template.disabled()) {
                _namedTemplates.put(template, this);
            }

            // Add this template to a test sequence if it has a pattern
            final Pattern pattern = template.getPattern();
            if (pattern != null) {
                flattenAlternative(pattern, template, keys);
            }
        }
        prepareTestSequences();
    }

    /**
     * This method will break up alternative patterns (ie. unions of patterns,
     * such as match="A/B | C/B") and add the basic patterns to their
     * respective pattern groups.
     */
    private void flattenAlternative(Pattern pattern,
                                    Template template,
                                    Map<String, Key> keys) {
        // Patterns on type id() and key() are special since they do not have
        // any kernel node type (it can be anything as long as the node is in
        // the id's or key's index).
        if (pattern instanceof IdKeyPattern) {
            final IdKeyPattern idkey = (IdKeyPattern)pattern;
            idkey.setTemplate(template);
            if (_idxGroup == null) _idxGroup = new Vector();
            _idxGroup.add(pattern);
        }
        // Alternative patterns are broken up and re-processed recursively
        else if (pattern instanceof AlternativePattern) {
            final AlternativePattern alt = (AlternativePattern)pattern;
            flattenAlternative(alt.getLeft(), template, keys);
            flattenAlternative(alt.getRight(), template, keys);
        }
        // Finally we have a pattern that can be added to a test sequence!
        else if (pattern instanceof LocationPathPattern) {
            final LocationPathPattern lpp = (LocationPathPattern)pattern;
            lpp.setTemplate(template);
            addPatternToGroup(lpp);
        }
    }

    /**
     * Group patterns by NodeTests of their last Step
     * Keep them sorted by priority within group
     */
    private void addPatternToGroup(final LocationPathPattern lpp) {
        // id() and key()-type patterns do not have a kernel type
        if (lpp instanceof IdKeyPattern) {
            addPattern(-1, lpp);
        }
        // Otherwise get the kernel pattern from the LPP
        else {
            // kernel pattern is the last (maybe only) Step
            final StepPattern kernel = lpp.getKernelPattern();
            if (kernel != null) {
                addPattern(kernel.getNodeType(), lpp);
            }
            else if (_rootPattern == null ||
                     lpp.noSmallerThan(_rootPattern)) {
                _rootPattern = lpp;
            }
        }
    }

    /**
     * Adds a pattern to a pattern group
     */
    private void addPattern(int kernelType, LocationPathPattern pattern) {
        // Make sure the array of pattern groups is long enough
        final int oldLength = _patternGroups.length;
        if (kernelType >= oldLength) {
            Vector[] newGroups = new Vector[kernelType * 2];
            System.arraycopy(_patternGroups, 0, newGroups, 0, oldLength);
            _patternGroups = newGroups;
        }

        // Find the vector to put this pattern into
        Vector patterns;

        if (kernelType == DOM.NO_TYPE) {
            if (pattern.getAxis() == Axis.ATTRIBUTE) {
                patterns = (_attribNodeGroup == null) ?
                    (_attribNodeGroup = new Vector(2)) : _attribNodeGroup;
            }
            else {
                patterns = (_childNodeGroup == null) ?
                    (_childNodeGroup = new Vector(2)) : _childNodeGroup;
            }
        }
        else {
            patterns = (_patternGroups[kernelType] == null) ?
                (_patternGroups[kernelType] = new Vector(2)) :
                _patternGroups[kernelType];
        }

        if (patterns.size() == 0) {
            patterns.addElement(pattern);
        }
        else {
            boolean inserted = false;
            for (int i = 0; i < patterns.size(); i++) {
                final LocationPathPattern lppToCompare =
                    (LocationPathPattern)patterns.elementAt(i);

                if (pattern.noSmallerThan(lppToCompare)) {
                    inserted = true;
                    patterns.insertElementAt(pattern, i);
                    break;
                }
            }
            if (inserted == false) {
                patterns.addElement(pattern);
            }
        }
    }

    /**
     * Complete test sequences of a given type by adding all patterns
     * from a given group.
     */
    private void completeTestSequences(int nodeType, Vector patterns) {
        if (patterns != null) {
            if (_patternGroups[nodeType] == null) {
                _patternGroups[nodeType] = patterns;
            }
            else {
                final int m = patterns.size();
                for (int j = 0; j < m; j++) {
                    addPattern(nodeType,
                        (LocationPathPattern) patterns.elementAt(j));
                }
            }
        }
    }

    /**
     * Build test sequences. The first step is to complete the test sequences
     * by including patterns of "*" and "node()" kernel to all element test
     * sequences, and of "@*" to all attribute test sequences.
     */
    private void prepareTestSequences() {
        final Vector starGroup = _patternGroups[DTM.ELEMENT_NODE];
        final Vector atStarGroup = _patternGroups[DTM.ATTRIBUTE_NODE];

        // Complete test sequence for "text()" with "child::node()"
        completeTestSequences(DTM.TEXT_NODE, _childNodeGroup);

        // Complete test sequence for "*" with "child::node()"
        completeTestSequences(DTM.ELEMENT_NODE, _childNodeGroup);

        // Complete test sequence for "pi()" with "child::node()"
        completeTestSequences(DTM.PROCESSING_INSTRUCTION_NODE, _childNodeGroup);

        // Complete test sequence for "comment()" with "child::node()"
        completeTestSequences(DTM.COMMENT_NODE, _childNodeGroup);

        // Complete test sequence for "@*" with "attribute::node()"
        completeTestSequences(DTM.ATTRIBUTE_NODE, _attribNodeGroup);

        final Vector names = _stylesheet.getXSLTC().getNamesIndex();
        if (starGroup != null || atStarGroup != null ||
            _childNodeGroup != null || _attribNodeGroup != null)
        {
            final int n = _patternGroups.length;

            // Complete test sequence for user-defined types
            for (int i = DTM.NTYPES; i < n; i++) {
                if (_patternGroups[i] == null) continue;

                final String name = (String) names.elementAt(i - DTM.NTYPES);

                if (isAttributeName(name)) {
                    // If an attribute then copy "@*" to its test sequence
                    completeTestSequences(i, atStarGroup);

                    // And also copy "attribute::node()" to its test sequence
                    completeTestSequences(i, _attribNodeGroup);
                }
                else {
                    // If an element then copy "*" to its test sequence
                    completeTestSequences(i, starGroup);

                    // And also copy "child::node()" to its test sequence
                    completeTestSequences(i, _childNodeGroup);
                }
            }
        }

        _testSeq = new TestSeq[DTM.NTYPES + names.size()];

        final int n = _patternGroups.length;
        for (int i = 0; i < n; i++) {
            final Vector patterns = _patternGroups[i];
            if (patterns != null) {
                final TestSeq testSeq = new TestSeq(patterns, i, this);
// System.out.println("testSeq[" + i + "] = " + testSeq);
                testSeq.reduce();
                _testSeq[i] = testSeq;
                testSeq.findTemplates(_neededTemplates);
            }
        }

        if (_childNodeGroup != null && _childNodeGroup.size() > 0) {
            _childNodeTestSeq = new TestSeq(_childNodeGroup, -1, this);
            _childNodeTestSeq.reduce();
            _childNodeTestSeq.findTemplates(_neededTemplates);
        }

/*
        if (_attribNodeGroup != null && _attribNodeGroup.size() > 0) {
            _attribNodeTestSeq = new TestSeq(_attribNodeGroup, -1, this);
            _attribNodeTestSeq.reduce();
            _attribNodeTestSeq.findTemplates(_neededTemplates);
        }
*/

        if (_idxGroup != null && _idxGroup.size() > 0) {
            _idxTestSeq = new TestSeq(_idxGroup, this);
            _idxTestSeq.reduce();
            _idxTestSeq.findTemplates(_neededTemplates);
        }

        if (_rootPattern != null) {
            // doesn't matter what is 'put', only key matters
            _neededTemplates.put(_rootPattern.getTemplate(), this);
        }
    }

    private void compileNamedTemplate(Template template,
                                      ClassGenerator classGen) {
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = new InstructionList();
        String methodName = Util.escape(template.getName().toString());

        int numParams = 0;
        if (template.isSimpleNamedTemplate()) {
            Vector parameters = template.getParameters();
            numParams = parameters.size();
        }

        // Initialize the types and names arrays for the NamedMethodGenerator.
        com.sun.org.apache.bcel.internal.generic.Type[] types =
            new com.sun.org.apache.bcel.internal.generic.Type[4 + numParams];
        String[] names = new String[4 + numParams];
        types[0] = Util.getJCRefType(DOM_INTF_SIG);
        types[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
        types[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);
        types[3] = com.sun.org.apache.bcel.internal.generic.Type.INT;
        names[0] = DOCUMENT_PNAME;
        names[1] = ITERATOR_PNAME;
        names[2] = TRANSLET_OUTPUT_PNAME;
        names[3] = NODE_PNAME;

        // For simple named templates, the signature of the generated method
        // is not fixed. It depends on the number of parameters declared in the
        // template.
        for (int i = 4; i < 4 + numParams; i++) {
            types[i] = Util.getJCRefType(OBJECT_SIG);
            names[i] = "param" + String.valueOf(i-4);
        }

        NamedMethodGenerator methodGen =
                new NamedMethodGenerator(ACC_PUBLIC,
                                     com.sun.org.apache.bcel.internal.generic.Type.VOID,
                                     types, names, methodName,
                                     getClassName(), il, cpg);

        il.append(template.compile(classGen, methodGen));
        il.append(RETURN);

        classGen.addMethod(methodGen);
    }

    private void compileTemplates(ClassGenerator classGen,
                                  MethodGenerator methodGen,
                                  InstructionHandle next)
    {
        Set<Template> templates = _namedTemplates.keySet();
        for (Template template : templates) {
            compileNamedTemplate(template, classGen);
        }

        templates = _neededTemplates.keySet();
        for (Template template : templates) {
            if (template.hasContents()) {
                // !!! TODO templates both named and matched
                InstructionList til = template.compile(classGen, methodGen);
                til.append(new GOTO_W(next));
                _templateILs.put(template, til);
                _templateIHs.put(template, til.getStart());
            }
            else {
                // empty template
                _templateIHs.put(template, next);
            }
        }
    }

    private void appendTemplateCode(InstructionList body) {
        for (Template template : _neededTemplates.keySet()) {
            final InstructionList iList = _templateILs.get(template);
            if (iList != null) {
                body.append(iList);
            }

        }
    }

    private void appendTestSequences(InstructionList body) {
        final int n = _testSeq.length;
        for (int i = 0; i < n; i++) {
            final TestSeq testSeq = _testSeq[i];
            if (testSeq != null) {
                InstructionList il = testSeq.getInstructionList();
                if (il != null)
                    body.append(il);
                // else trivial TestSeq
            }
        }
    }

    public static void compileGetChildren(ClassGenerator classGen,
                                          MethodGenerator methodGen,
                                          int node) {
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = methodGen.getInstructionList();
        final int git = cpg.addInterfaceMethodref(DOM_INTF,
                                                  GET_CHILDREN,
                                                  GET_CHILDREN_SIG);
        il.append(methodGen.loadDOM());
        il.append(new ILOAD(node));
        il.append(new INVOKEINTERFACE(git, 2));
    }

    /**
     * Compiles the default handling for DOM elements: traverse all children
     */
    private InstructionList compileDefaultRecursion(ClassGenerator classGen,
                                                    MethodGenerator methodGen,
                                                    InstructionHandle next) {
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = new InstructionList();
        final String applyTemplatesSig = classGen.getApplyTemplatesSig();
        final int git = cpg.addInterfaceMethodref(DOM_INTF,
                                                  GET_CHILDREN,
                                                  GET_CHILDREN_SIG);
        final int applyTemplates = cpg.addMethodref(getClassName(),
                                                    functionName(),
                                                    applyTemplatesSig);
        il.append(classGen.loadTranslet());
        il.append(methodGen.loadDOM());

        il.append(methodGen.loadDOM());
        il.append(new ILOAD(_currentIndex));
        il.append(new INVOKEINTERFACE(git, 2));
        il.append(methodGen.loadHandler());
        il.append(new INVOKEVIRTUAL(applyTemplates));
        il.append(new GOTO_W(next));
        return il;
    }

    /**
     * Compiles the default action for DOM text nodes and attribute nodes:
     * output the node's text value
     */
    private InstructionList compileDefaultText(ClassGenerator classGen,
                                               MethodGenerator methodGen,
                                               InstructionHandle next) {
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = new InstructionList();

        final int chars = cpg.addInterfaceMethodref(DOM_INTF,
                                                    CHARACTERS,
                                                    CHARACTERS_SIG);
        il.append(methodGen.loadDOM());
        il.append(new ILOAD(_currentIndex));
        il.append(methodGen.loadHandler());
        il.append(new INVOKEINTERFACE(chars, 3));
        il.append(new GOTO_W(next));
        return il;
    }

    private InstructionList compileNamespaces(ClassGenerator classGen,
                                              MethodGenerator methodGen,
                                              boolean[] isNamespace,
                                              boolean[] isAttribute,
                                              boolean attrFlag,
                                              InstructionHandle defaultTarget) {
        final XSLTC xsltc = classGen.getParser().getXSLTC();
        final ConstantPoolGen cpg = classGen.getConstantPool();

        // Append switch() statement - namespace test dispatch loop
        final Vector namespaces = xsltc.getNamespaceIndex();
        final Vector names = xsltc.getNamesIndex();
        final int namespaceCount = namespaces.size() + 1;
        final int namesCount = names.size();

        final InstructionList il = new InstructionList();
        final int[] types = new int[namespaceCount];
        final InstructionHandle[] targets = new InstructionHandle[types.length];

        if (namespaceCount > 0) {
            boolean compiled = false;

            // Initialize targets for namespace() switch statement
            for (int i = 0; i < namespaceCount; i++) {
                targets[i] = defaultTarget;
                types[i] = i;
            }

            // Add test sequences for known namespace types
            for (int i = DTM.NTYPES; i < (DTM.NTYPES+namesCount); i++) {
                if ((isNamespace[i]) && (isAttribute[i] == attrFlag)) {
                    String name = (String)names.elementAt(i-DTM.NTYPES);
                    String namespace = name.substring(0,name.lastIndexOf(':'));
                    final int type = xsltc.registerNamespace(namespace);

                    if ((i < _testSeq.length) &&
                        (_testSeq[i] != null)) {
                        targets[type] =
                            (_testSeq[i]).compile(classGen,
                                                       methodGen,
                                                       defaultTarget);
                        compiled = true;
                    }
                }
            }

            // Return "null" if no test sequences were compiled
            if (!compiled) return(null);

            // Append first code in applyTemplates() - get type of current node
            final int getNS = cpg.addInterfaceMethodref(DOM_INTF,
                                                        "getNamespaceType",
                                                        "(I)I");
            il.append(methodGen.loadDOM());
            il.append(new ILOAD(_currentIndex));
            il.append(new INVOKEINTERFACE(getNS, 2));
            il.append(new SWITCH(types, targets, defaultTarget));
            return(il);
        }
        else {
            return(null);
        }
    }

   /**
     * Compiles the applyTemplates() method and adds it to the translet.
     * This is the main dispatch method.
     */
    public void compileApplyTemplates(ClassGenerator classGen) {
        final XSLTC xsltc = classGen.getParser().getXSLTC();
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final Vector names = xsltc.getNamesIndex();

        // Create the applyTemplates() method
        final com.sun.org.apache.bcel.internal.generic.Type[] argTypes =
            new com.sun.org.apache.bcel.internal.generic.Type[3];
        argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
        argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
        argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);

        final String[] argNames = new String[3];
        argNames[0] = DOCUMENT_PNAME;
        argNames[1] = ITERATOR_PNAME;
        argNames[2] = TRANSLET_OUTPUT_PNAME;

        final InstructionList mainIL = new InstructionList();
        final MethodGenerator methodGen =
            new MethodGenerator(ACC_PUBLIC | ACC_FINAL,
                                com.sun.org.apache.bcel.internal.generic.Type.VOID,
                                argTypes, argNames, functionName(),
                                getClassName(), mainIL,
                                classGen.getConstantPool());
        methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
        // Insert an extra NOP just to keep "current" from appearing as if it
        // has a value before the start of the loop.
        mainIL.append(NOP);


        // Create a local variable to hold the current node
        final LocalVariableGen current;
        current = methodGen.addLocalVariable2("current",
                                              com.sun.org.apache.bcel.internal.generic.Type.INT,
                                              null);
        _currentIndex = current.getIndex();

        // Create the "body" instruction list that will eventually hold the
        // code for the entire method (other ILs will be appended).
        final InstructionList body = new InstructionList();
        body.append(NOP);

        // Create an instruction list that contains the default next-node
        // iteration
        final InstructionList ilLoop = new InstructionList();
        ilLoop.append(methodGen.loadIterator());
        ilLoop.append(methodGen.nextNode());
        ilLoop.append(DUP);
        ilLoop.append(new ISTORE(_currentIndex));

        // The body of this code can get very large - large than can be handled
        // by a single IFNE(body.getStart()) instruction - need workaround:
        final BranchHandle ifeq = ilLoop.append(new IFLT(null));
        final BranchHandle loop = ilLoop.append(new GOTO_W(null));
        ifeq.setTarget(ilLoop.append(RETURN));  // applyTemplates() ends here!
        final InstructionHandle ihLoop = ilLoop.getStart();

        current.setStart(mainIL.append(new GOTO_W(ihLoop)));

        // Live range of "current" ends at end of loop
        current.setEnd(loop);

        // Compile default handling of elements (traverse children)
        InstructionList ilRecurse =
            compileDefaultRecursion(classGen, methodGen, ihLoop);
        InstructionHandle ihRecurse = ilRecurse.getStart();

        // Compile default handling of text/attribute nodes (output text)
        InstructionList ilText =
            compileDefaultText(classGen, methodGen, ihLoop);
        InstructionHandle ihText = ilText.getStart();

        // Distinguish attribute/element/namespace tests for further processing
        final int[] types = new int[DTM.NTYPES + names.size()];
        for (int i = 0; i < types.length; i++) {
            types[i] = i;
        }

        // Initialize isAttribute[] and isNamespace[] arrays
        final boolean[] isAttribute = new boolean[types.length];
        final boolean[] isNamespace = new boolean[types.length];
        for (int i = 0; i < names.size(); i++) {
            final String name = (String)names.elementAt(i);
            isAttribute[i + DTM.NTYPES] = isAttributeName(name);
            isNamespace[i + DTM.NTYPES] = isNamespaceName(name);
        }

        // Compile all templates - regardless of pattern type
        compileTemplates(classGen, methodGen, ihLoop);

        // Handle template with explicit "*" pattern
        final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE];
        InstructionHandle ihElem = ihRecurse;
        if (elemTest != null)
            ihElem = elemTest.compile(classGen, methodGen, ihRecurse);

        // Handle template with explicit "@*" pattern
        final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE];
        InstructionHandle ihAttr = ihText;
        if (attrTest != null)
            ihAttr = attrTest.compile(classGen, methodGen, ihAttr);

        // Do tests for id() and key() patterns first
        InstructionList ilKey = null;
        if (_idxTestSeq != null) {
            loop.setTarget(_idxTestSeq.compile(classGen, methodGen, body.getStart()));
            ilKey = _idxTestSeq.getInstructionList();
        }
        else {
            loop.setTarget(body.getStart());
        }

        // If there is a match on node() we need to replace ihElem
        // and ihText if the priority of node() is higher
        if (_childNodeTestSeq != null) {
            // Compare priorities of node() and "*"
            double nodePrio = _childNodeTestSeq.getPriority();
            int    nodePos  = _childNodeTestSeq.getPosition();
            double elemPrio = (0 - Double.MAX_VALUE);
            int    elemPos  = Integer.MIN_VALUE;

            if (elemTest != null) {
                elemPrio = elemTest.getPriority();
                elemPos  = elemTest.getPosition();
            }
            if (elemPrio == Double.NaN || elemPrio < nodePrio ||
                (elemPrio == nodePrio && elemPos < nodePos))
            {
                ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop);
            }

            // Compare priorities of node() and text()
            final TestSeq textTest = _testSeq[DTM.TEXT_NODE];
            double textPrio = (0 - Double.MAX_VALUE);
            int    textPos  = Integer.MIN_VALUE;

            if (textTest != null) {
                textPrio = textTest.getPriority();
                textPos  = textTest.getPosition();
            }
            if (textPrio == Double.NaN || textPrio < nodePrio ||
                (textPrio == nodePrio && textPos < nodePos))
            {
                ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop);
                _testSeq[DTM.TEXT_NODE] = _childNodeTestSeq;
            }
        }

        // Handle templates with "ns:*" pattern
        InstructionHandle elemNamespaceHandle = ihElem;
        InstructionList nsElem = compileNamespaces(classGen, methodGen,
                                                   isNamespace, isAttribute,
                                                   false, ihElem);
        if (nsElem != null) elemNamespaceHandle = nsElem.getStart();

        // Handle templates with "ns:@*" pattern
        InstructionHandle attrNamespaceHandle = ihAttr;
        InstructionList nsAttr = compileNamespaces(classGen, methodGen,
                                                   isNamespace, isAttribute,
                                                   true, ihAttr);
        if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart();

        // Handle templates with "ns:elem" or "ns:@attr" pattern
        final InstructionHandle[] targets = new InstructionHandle[types.length];
        for (int i = DTM.NTYPES; i < targets.length; i++) {
            final TestSeq testSeq = _testSeq[i];
            // Jump straight to namespace tests ?
            if (isNamespace[i]) {
                if (isAttribute[i])
                    targets[i] = attrNamespaceHandle;
                else
                    targets[i] = elemNamespaceHandle;
            }
            // Test first, then jump to namespace tests
            else if (testSeq != null) {
                if (isAttribute[i])
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 attrNamespaceHandle);
                else
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 elemNamespaceHandle);
            }
            else {
                targets[i] = ihLoop;
            }
        }


        // Handle pattern with match on root node - default: traverse children
        targets[DTM.ROOT_NODE] = _rootPattern != null
            ? getTemplateInstructionHandle(_rootPattern.getTemplate())
            : ihRecurse;

        // Handle pattern with match on root node - default: traverse children
        targets[DTM.DOCUMENT_NODE] = _rootPattern != null
            ? getTemplateInstructionHandle(_rootPattern.getTemplate())
            : ihRecurse;

        // Handle any pattern with match on text nodes - default: output text
        targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null
            ? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText)
            : ihText;

        // This DOM-type is not in use - default: process next node
        targets[DTM.NAMESPACE_NODE] = ihLoop;

        // Match unknown element in DOM - default: check for namespace match
        targets[DTM.ELEMENT_NODE] = elemNamespaceHandle;

        // Match unknown attribute in DOM - default: check for namespace match
        targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle;

        // Match on processing instruction - default: process next node
        InstructionHandle ihPI = ihLoop;
        if (_childNodeTestSeq != null) ihPI = ihElem;
        if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null)
            targets[DTM.PROCESSING_INSTRUCTION_NODE] =
                _testSeq[DTM.PROCESSING_INSTRUCTION_NODE].
                compile(classGen, methodGen, ihPI);
        else
            targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI;

        // Match on comments - default: process next node
        InstructionHandle ihComment = ihLoop;
        if (_childNodeTestSeq != null) ihComment = ihElem;
        targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null
            ? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment)
            : ihComment;

            // This DOM-type is not in use - default: process next node
        targets[DTM.CDATA_SECTION_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.ENTITY_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.NOTATION_NODE] = ihLoop;


        // Now compile test sequences for various match patterns:
        for (int i = DTM.NTYPES; i < targets.length; i++) {
            final TestSeq testSeq = _testSeq[i];
            // Jump straight to namespace tests ?
            if ((testSeq == null) || (isNamespace[i])) {
                if (isAttribute[i])
                    targets[i] = attrNamespaceHandle;
                else
                    targets[i] = elemNamespaceHandle;
            }
            // Match on node type
            else {
                if (isAttribute[i])
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 attrNamespaceHandle);
                else
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 elemNamespaceHandle);
            }
        }

        if (ilKey != null) body.insert(ilKey);

        // Append first code in applyTemplates() - get type of current node
        final int getType = cpg.addInterfaceMethodref(DOM_INTF,
                                                      "getExpandedTypeID",
                                                      "(I)I");
        body.append(methodGen.loadDOM());
        body.append(new ILOAD(_currentIndex));
        body.append(new INVOKEINTERFACE(getType, 2));

        // Append switch() statement - main dispatch loop in applyTemplates()
        InstructionHandle disp = body.append(new SWITCH(types, targets, ihLoop));

        // Append all the "case:" statements
        appendTestSequences(body);
        // Append the actual template code
        appendTemplateCode(body);

        // Append NS:* node tests (if any)
        if (nsElem != null) body.append(nsElem);
        // Append NS:@* node tests (if any)
        if (nsAttr != null) body.append(nsAttr);

        // Append default action for element and root nodes
        body.append(ilRecurse);
        // Append default action for text and attribute nodes
        body.append(ilText);

        // putting together constituent instruction lists
        mainIL.append(body);
        // fall through to ilLoop
        mainIL.append(ilLoop);

        peepHoleOptimization(methodGen);
        classGen.addMethod(methodGen);

        // Compile method(s) for <xsl:apply-imports/> for this mode
        if (_importLevels != null) {
            for (Map.Entry<Integer, Integer> entry : _importLevels.entrySet()) {
                compileApplyImports(classGen, entry.getValue(), entry.getKey());
            }
        }
    }

    private void compileTemplateCalls(ClassGenerator classGen,
                                      MethodGenerator methodGen,
                                      InstructionHandle next, int min, int max){
        for (Template template : _neededTemplates.keySet()) {
            final int prec = template.getImportPrecedence();
            if ((prec >= min) && (prec < max)) {
                if (template.hasContents()) {
                    InstructionList til = template.compile(classGen, methodGen);
                    til.append(new GOTO_W(next));
                    _templateILs.put(template, til);
                    _templateIHs.put(template, til.getStart());
                }
                else {
                    // empty template
                    _templateIHs.put(template, next);
                }
            }
        }
    }


    public void compileApplyImports(ClassGenerator classGen, int min, int max) {
        final XSLTC xsltc = classGen.getParser().getXSLTC();
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final Vector names      = xsltc.getNamesIndex();

        // Clear some datastructures
        _namedTemplates = new HashMap<>();
        _neededTemplates = new HashMap<>();
        _templateIHs = new HashMap<>();
        _templateILs = new HashMap<>();
        _patternGroups = new Vector[32];
        _rootPattern = null;

        // IMPORTANT: Save orignal & complete set of templates!!!!
        Vector oldTemplates = _templates;

        // Gather templates that are within the scope of this import
        _templates = new Vector();
        final Enumeration templates = oldTemplates.elements();
        while (templates.hasMoreElements()) {
            final Template template = (Template)templates.nextElement();
            final int prec = template.getImportPrecedence();
            if ((prec >= min) && (prec < max)) addTemplate(template);
        }

        // Process all patterns from those templates
        processPatterns(_keys);

        // Create the applyTemplates() method
        final com.sun.org.apache.bcel.internal.generic.Type[] argTypes =
            new com.sun.org.apache.bcel.internal.generic.Type[4];
        argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
        argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
        argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);
        argTypes[3] = com.sun.org.apache.bcel.internal.generic.Type.INT;

        final String[] argNames = new String[4];
        argNames[0] = DOCUMENT_PNAME;
        argNames[1] = ITERATOR_PNAME;
        argNames[2] = TRANSLET_OUTPUT_PNAME;
        argNames[3] = NODE_PNAME;

        final InstructionList mainIL = new InstructionList();
        final MethodGenerator methodGen =
            new MethodGenerator(ACC_PUBLIC | ACC_FINAL,
                                com.sun.org.apache.bcel.internal.generic.Type.VOID,
                                argTypes, argNames, functionName()+'_'+max,
                                getClassName(), mainIL,
                                classGen.getConstantPool());
        methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");

        // Create the local variable to hold the current node
        final LocalVariableGen current;
        current = methodGen.addLocalVariable2("current",
                                              com.sun.org.apache.bcel.internal.generic.Type.INT,
                                              null);
        _currentIndex = current.getIndex();

        mainIL.append(new ILOAD(methodGen.getLocalIndex(NODE_PNAME)));
        current.setStart(mainIL.append(new ISTORE(_currentIndex)));

        // Create the "body" instruction list that will eventually hold the
        // code for the entire method (other ILs will be appended).
        final InstructionList body = new InstructionList();
        body.append(NOP);

        // Create an instruction list that contains the default next-node
        // iteration
        final InstructionList ilLoop = new InstructionList();
        ilLoop.append(RETURN);
        final InstructionHandle ihLoop = ilLoop.getStart();

        // Compile default handling of elements (traverse children)
        InstructionList ilRecurse =
            compileDefaultRecursion(classGen, methodGen, ihLoop);
        InstructionHandle ihRecurse = ilRecurse.getStart();

        // Compile default handling of text/attribute nodes (output text)
        InstructionList ilText =
            compileDefaultText(classGen, methodGen, ihLoop);
        InstructionHandle ihText = ilText.getStart();

        // Distinguish attribute/element/namespace tests for further processing
        final int[] types = new int[DTM.NTYPES + names.size()];
        for (int i = 0; i < types.length; i++) {
            types[i] = i;
        }

        final boolean[] isAttribute = new boolean[types.length];
        final boolean[] isNamespace = new boolean[types.length];
        for (int i = 0; i < names.size(); i++) {
            final String name = (String)names.elementAt(i);
            isAttribute[i+DTM.NTYPES] = isAttributeName(name);
            isNamespace[i+DTM.NTYPES] = isNamespaceName(name);
        }

        // Compile all templates - regardless of pattern type
        compileTemplateCalls(classGen, methodGen, ihLoop, min, max);

        // Handle template with explicit "*" pattern
        final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE];
        InstructionHandle ihElem = ihRecurse;
        if (elemTest != null) {
            ihElem = elemTest.compile(classGen, methodGen, ihLoop);
        }

        // Handle template with explicit "@*" pattern
        final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE];
        InstructionHandle ihAttr = ihLoop;
        if (attrTest != null) {
            ihAttr = attrTest.compile(classGen, methodGen, ihAttr);
        }

        // Do tests for id() and key() patterns first
        InstructionList ilKey = null;
        if (_idxTestSeq != null) {
            ilKey = _idxTestSeq.getInstructionList();
        }

        // If there is a match on node() we need to replace ihElem
        // and ihText if the priority of node() is higher
        if (_childNodeTestSeq != null) {
            // Compare priorities of node() and "*"
            double nodePrio = _childNodeTestSeq.getPriority();
            int    nodePos  = _childNodeTestSeq.getPosition();
            double elemPrio = (0 - Double.MAX_VALUE);
            int    elemPos  = Integer.MIN_VALUE;

            if (elemTest != null) {
                elemPrio = elemTest.getPriority();
                elemPos  = elemTest.getPosition();
            }

            if (elemPrio == Double.NaN || elemPrio < nodePrio ||
                (elemPrio == nodePrio && elemPos < nodePos))
            {
                ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop);
            }

            // Compare priorities of node() and text()
            final TestSeq textTest = _testSeq[DTM.TEXT_NODE];
            double textPrio = (0 - Double.MAX_VALUE);
            int    textPos  = Integer.MIN_VALUE;

            if (textTest != null) {
                textPrio = textTest.getPriority();
                textPos  = textTest.getPosition();
            }

            if (textPrio == Double.NaN || textPrio < nodePrio ||
                (textPrio == nodePrio && textPos < nodePos))
            {
                ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop);
                _testSeq[DTM.TEXT_NODE] = _childNodeTestSeq;
            }
        }

        // Handle templates with "ns:*" pattern
        InstructionHandle elemNamespaceHandle = ihElem;
        InstructionList nsElem = compileNamespaces(classGen, methodGen,
                                                   isNamespace, isAttribute,
                                                   false, ihElem);
        if (nsElem != null) elemNamespaceHandle = nsElem.getStart();

        // Handle templates with "ns:@*" pattern
        InstructionList nsAttr = compileNamespaces(classGen, methodGen,
                                                   isNamespace, isAttribute,
                                                   true, ihAttr);
        InstructionHandle attrNamespaceHandle = ihAttr;
        if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart();

        // Handle templates with "ns:elem" or "ns:@attr" pattern
        final InstructionHandle[] targets = new InstructionHandle[types.length];
        for (int i = DTM.NTYPES; i < targets.length; i++) {
            final TestSeq testSeq = _testSeq[i];
            // Jump straight to namespace tests ?
            if (isNamespace[i]) {
                if (isAttribute[i])
                    targets[i] = attrNamespaceHandle;
                else
                    targets[i] = elemNamespaceHandle;
            }
            // Test first, then jump to namespace tests
            else if (testSeq != null) {
                if (isAttribute[i])
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 attrNamespaceHandle);
                else
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 elemNamespaceHandle);
            }
            else {
                targets[i] = ihLoop;
            }
        }

        // Handle pattern with match on root node - default: traverse children
        targets[DTM.ROOT_NODE] = _rootPattern != null
            ? getTemplateInstructionHandle(_rootPattern.getTemplate())
            : ihRecurse;
        // Handle pattern with match on root node - default: traverse children
        targets[DTM.DOCUMENT_NODE] = _rootPattern != null
            ? getTemplateInstructionHandle(_rootPattern.getTemplate())
            : ihRecurse;    // %HZ%:  Was ihLoop in XSLTC_DTM branch

        // Handle any pattern with match on text nodes - default: loop
        targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null
            ? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText)
            : ihText;

        // This DOM-type is not in use - default: process next node
        targets[DTM.NAMESPACE_NODE] = ihLoop;

        // Match unknown element in DOM - default: check for namespace match
        targets[DTM.ELEMENT_NODE] = elemNamespaceHandle;

        // Match unknown attribute in DOM - default: check for namespace match
        targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle;

        // Match on processing instruction - default: loop
        InstructionHandle ihPI = ihLoop;
        if (_childNodeTestSeq != null) ihPI = ihElem;
        if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null) {
            targets[DTM.PROCESSING_INSTRUCTION_NODE] =
                _testSeq[DTM.PROCESSING_INSTRUCTION_NODE].
                compile(classGen, methodGen, ihPI);
        }
        else {
            targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI;
        }

        // Match on comments - default: process next node
        InstructionHandle ihComment = ihLoop;
        if (_childNodeTestSeq != null) ihComment = ihElem;
        targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null
            ? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment)
            : ihComment;

                // This DOM-type is not in use - default: process next node
        targets[DTM.CDATA_SECTION_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.ENTITY_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop;

        // This DOM-type is not in use - default: process next node
        targets[DTM.NOTATION_NODE] = ihLoop;



        // Now compile test sequences for various match patterns:
        for (int i = DTM.NTYPES; i < targets.length; i++) {
            final TestSeq testSeq = _testSeq[i];
            // Jump straight to namespace tests ?
            if ((testSeq == null) || (isNamespace[i])) {
                if (isAttribute[i])
                    targets[i] = attrNamespaceHandle;
                else
                    targets[i] = elemNamespaceHandle;
            }
            // Match on node type
            else {
                if (isAttribute[i])
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 attrNamespaceHandle);
                else
                    targets[i] = testSeq.compile(classGen, methodGen,
                                                 elemNamespaceHandle);
            }
        }

        if (ilKey != null) body.insert(ilKey);

        // Append first code in applyTemplates() - get type of current node
        final int getType = cpg.addInterfaceMethodref(DOM_INTF,
                                                      "getExpandedTypeID",
                                                      "(I)I");
        body.append(methodGen.loadDOM());
        body.append(new ILOAD(_currentIndex));
        body.append(new INVOKEINTERFACE(getType, 2));

        // Append switch() statement - main dispatch loop in applyTemplates()
        InstructionHandle disp = body.append(new SWITCH(types,targets,ihLoop));

        // Append all the "case:" statements
        appendTestSequences(body);
        // Append the actual template code
        appendTemplateCode(body);

        // Append NS:* node tests (if any)
        if (nsElem != null) body.append(nsElem);
        // Append NS:@* node tests (if any)
        if (nsAttr != null) body.append(nsAttr);

        // Append default action for element and root nodes
        body.append(ilRecurse);
        // Append default action for text and attribute nodes
        body.append(ilText);

        // putting together constituent instruction lists
        mainIL.append(body);

        // Mark the end of the live range for the "current" variable
        current.setEnd(body.getEnd());

        // fall through to ilLoop
        mainIL.append(ilLoop);

        peepHoleOptimization(methodGen);
        classGen.addMethod(methodGen);

        // Restore original (complete) set of templates for this transformation
        _templates = oldTemplates;
    }

    /**
      * Peephole optimization.
      */
    private void peepHoleOptimization(MethodGenerator methodGen) {
        InstructionList il = methodGen.getInstructionList();
        InstructionFinder find = new InstructionFinder(il);
        InstructionHandle ih;
        String pattern;

        // LoadInstruction, POP => (removed)
        // pattern = "LoadInstruction POP";
        // changed to lower case - changing to all lower case although only the instruction with capital I
        // is creating a problem in the Turkish locale
        pattern = "loadinstruction pop";

        for (Iterator iter = find.search(pattern); iter.hasNext();) {
            InstructionHandle[] match = (InstructionHandle[]) iter.next();
            try {
                if (!match[0].hasTargeters() && !match[1].hasTargeters()) {
                    il.delete(match[0], match[1]);
                }
            }
            catch (TargetLostException e) {
                // TODO: move target down into the list
            }
        }

        // ILOAD_N, ILOAD_N, SWAP, ISTORE_N => ILOAD_N
        // pattern = "ILOAD ILOAD SWAP ISTORE";
        // changed to lower case - changing to all lower case although only the instruction with capital I
        // is creating a problem in the Turkish locale
        pattern = "iload iload swap istore";
        for (Iterator iter = find.search(pattern); iter.hasNext();) {
            InstructionHandle[] match = (InstructionHandle[]) iter.next();
            try {
                com.sun.org.apache.bcel.internal.generic.ILOAD iload1 =
                    (com.sun.org.apache.bcel.internal.generic.ILOAD) match[0].getInstruction();
                com.sun.org.apache.bcel.internal.generic.ILOAD iload2 =
                    (com.sun.org.apache.bcel.internal.generic.ILOAD) match[1].getInstruction();
                com.sun.org.apache.bcel.internal.generic.ISTORE istore =
                    (com.sun.org.apache.bcel.internal.generic.ISTORE) match[3].getInstruction();

                if (!match[1].hasTargeters() &&
                    !match[2].hasTargeters() &&
                    !match[3].hasTargeters() &&
                    iload1.getIndex() == iload2.getIndex() &&
                    iload2.getIndex() == istore.getIndex())
                {
                    il.delete(match[1], match[3]);
                }
            }
            catch (TargetLostException e) {
                // TODO: move target down into the list
            }
        }

        // LoadInstruction_N, LoadInstruction_M, SWAP => LoadInstruction_M, LoadInstruction_N
        // pattern = "LoadInstruction LoadInstruction SWAP";
        // changed to lower case - changing to all lower case although only the instruction with capital I
        // is creating a problem in the Turkish locale
        pattern = "loadinstruction loadinstruction swap";
        for (Iterator iter = find.search(pattern); iter.hasNext();) {
            InstructionHandle[] match = (InstructionHandle[])iter.next();
            try {
                if (!match[0].hasTargeters() &&
                    !match[1].hasTargeters() &&
                    !match[2].hasTargeters())
                {
                    Instruction load_m = match[1].getInstruction();
                    il.insert(match[0], load_m);
                    il.delete(match[1], match[2]);
                }
            }
            catch (TargetLostException e) {
                // TODO: move target down into the list
            }
        }

        // ALOAD_N ALOAD_N => ALOAD_N DUP
        // pattern = "ALOAD ALOAD";
        // changed to lower case - changing to all lower case although only the instruction with capital I
        // is creating a problem in the Turkish locale
        pattern = "aload aload";
        for (Iterator iter = find.search(pattern); iter.hasNext();) {
            InstructionHandle[] match = (InstructionHandle[])iter.next();
            try {
                if (!match[1].hasTargeters()) {
                    com.sun.org.apache.bcel.internal.generic.ALOAD aload1 =
                        (com.sun.org.apache.bcel.internal.generic.ALOAD) match[0].getInstruction();
                    com.sun.org.apache.bcel.internal.generic.ALOAD aload2 =
                        (com.sun.org.apache.bcel.internal.generic.ALOAD) match[1].getInstruction();

                    if (aload1.getIndex() == aload2.getIndex()) {
                        il.insert(match[1], new DUP());
                        il.delete(match[1]);
                    }
                }
            }
            catch (TargetLostException e) {
                // TODO: move target down into the list
            }
        }
    }

    public InstructionHandle getTemplateInstructionHandle(Template template) {
        return _templateIHs.get(template);
    }

    /**
     * Auxiliary method to determine if a qname is an attribute.
     */
    private static boolean isAttributeName(String qname) {
        final int col = qname.lastIndexOf(':') + 1;
        return (qname.charAt(col) == '@');
    }

    /**
     * Auxiliary method to determine if a qname is a namespace
     * qualified "*".
     */
    private static boolean isNamespaceName(String qname) {
        final int col = qname.lastIndexOf(':');
        return (col > -1 && qname.charAt(qname.length()-1) == '*');
    }
}
