1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  23 
  24 import java.util.Enumeration;
  25 
  26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  27 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
  28 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  29 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  30 import com.sun.org.apache.bcel.internal.generic.NEW;
  31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  36 
  37 final class ApplyImports extends Instruction {
  38 
  39     private QName      _modeName;
  40     private int        _precedence;
  41 
  42     public void display(int indent) {
  43         indent(indent);
  44         Util.println("ApplyTemplates");
  45         indent(indent + IndentIncrement);
  46         if (_modeName != null) {
  47             indent(indent + IndentIncrement);
  48             Util.println("mode " + _modeName);
  49         }
  50     }
  51 
  52     /**
  53      * Returns true if this <xsl:apply-imports/> element has parameters
  54      */
  55     public boolean hasWithParams() {
  56         return hasContents();
  57     }
  58 
  59     /**
  60      * Determine the lowest import precedence for any stylesheet imported
  61      * or included by the stylesheet in which this <xsl:apply-imports/>
  62      * element occured. The templates that are imported by the stylesheet in
  63      * which this element occured will all have higher import precedence than
  64      * the integer returned by this method.
  65      */
  66     private int getMinPrecedence(int max) {
  67         // Move to root of include tree
  68         Stylesheet includeRoot = getStylesheet();
  69         while (includeRoot._includedFrom != null) {
  70             includeRoot = includeRoot._includedFrom;
  71         }
  72 
  73         return includeRoot.getMinimumDescendantPrecedence();
  74     }
  75 
  76     /**
  77      * Parse the attributes and contents of an <xsl:apply-imports/> element.
  78      */
  79     public void parseContents(Parser parser) {
  80         // Indicate to the top-level stylesheet that all templates must be
  81         // compiled into separate methods.
  82         Stylesheet stylesheet = getStylesheet();
  83         stylesheet.setTemplateInlining(false);
  84 
  85         // Get the mode we are currently in (might not be any)
  86         Template template = getTemplate();
  87         _modeName = template.getModeName();
  88         _precedence = template.getImportPrecedence();
  89 
  90         // Get the method name for <xsl:apply-imports/> in this mode
  91         stylesheet = parser.getTopLevelStylesheet();
  92 
  93         parseChildren(parser);  // with-params
  94     }
  95 
  96     /**
  97      * Type-check the attributes/contents of an <xsl:apply-imports/> element.
  98      */
  99     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
 100         typeCheckContents(stable);              // with-params
 101         return Type.Void;
 102     }
 103 
 104     /**
 105      * Translate call-template. A parameter frame is pushed only if
 106      * some template in the stylesheet uses parameters.
 107      */
 108     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
 109         final Stylesheet stylesheet = classGen.getStylesheet();
 110         final ConstantPoolGen cpg = classGen.getConstantPool();
 111         final InstructionList il = methodGen.getInstructionList();
 112         final int current = methodGen.getLocalIndex("current");
 113 
 114         // Push the arguments that are passed to applyTemplates()
 115         il.append(classGen.loadTranslet());
 116         il.append(methodGen.loadDOM());
 117     il.append(methodGen.loadIterator());
 118         il.append(methodGen.loadHandler());
 119     il.append(methodGen.loadCurrentNode());
 120 
 121         // Push a new parameter frame in case imported template might expect
 122         // parameters.  The apply-imports has nothing that it can pass.
 123         if (stylesheet.hasLocalParams()) {
 124             il.append(classGen.loadTranslet());
 125             final int pushFrame = cpg.addMethodref(TRANSLET_CLASS,
 126                                                    PUSH_PARAM_FRAME,
 127                                                    PUSH_PARAM_FRAME_SIG);
 128             il.append(new INVOKEVIRTUAL(pushFrame));
 129         }
 130 
 131         // Get the [min,max> precedence of all templates imported under the
 132         // current stylesheet
 133         final int maxPrecedence = _precedence;
 134         final int minPrecedence = getMinPrecedence(maxPrecedence);
 135         final Mode mode = stylesheet.getMode(_modeName);
 136 
 137         // Get name of appropriate apply-templates function for this
 138         // xsl:apply-imports instruction
 139         String functionName = mode.functionName(minPrecedence, maxPrecedence);
 140 
 141         // Construct the translet class-name and the signature of the method
 142         final String className = classGen.getStylesheet().getClassName();
 143         final String signature = classGen.getApplyTemplatesSigForImport();
 144         final int applyTemplates = cpg.addMethodref(className,
 145                                                     functionName,
 146                                                     signature);
 147         il.append(new INVOKEVIRTUAL(applyTemplates));
 148 
 149         // Pop any parameter frame that was pushed above.
 150         if (stylesheet.hasLocalParams()) {
 151             il.append(classGen.loadTranslet());
 152             final int pushFrame = cpg.addMethodref(TRANSLET_CLASS,
 153                                                    POP_PARAM_FRAME,
 154                                                    POP_PARAM_FRAME_SIG);
 155             il.append(new INVOKEVIRTUAL(pushFrame));
 156         }
 157     }
 158 
 159 }