001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: ApplyImports.java 469276 2006-10-30 21:09:47Z minchau $ 020 */ 021 022 package org.apache.xalan.xsltc.compiler; 023 024 import org.apache.bcel.generic.ConstantPoolGen; 025 import org.apache.bcel.generic.INVOKEVIRTUAL; 026 import org.apache.bcel.generic.InstructionList; 027 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 028 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 029 import org.apache.xalan.xsltc.compiler.util.Type; 030 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 031 import org.apache.xalan.xsltc.compiler.util.Util; 032 033 final class ApplyImports extends Instruction { 034 035 private QName _modeName; 036 private int _precedence; 037 038 public void display(int indent) { 039 indent(indent); 040 Util.println("ApplyTemplates"); 041 indent(indent + IndentIncrement); 042 if (_modeName != null) { 043 indent(indent + IndentIncrement); 044 Util.println("mode " + _modeName); 045 } 046 } 047 048 /** 049 * Returns true if this <xsl:apply-imports/> element has parameters 050 */ 051 public boolean hasWithParams() { 052 return hasContents(); 053 } 054 055 /** 056 * Determine the lowest import precedence for any stylesheet imported 057 * or included by the stylesheet in which this <xsl:apply-imports/> 058 * element occured. The templates that are imported by the stylesheet in 059 * which this element occured will all have higher import precedence than 060 * the integer returned by this method. 061 */ 062 private int getMinPrecedence(int max) { 063 // Move to root of include tree 064 Stylesheet includeRoot = getStylesheet(); 065 while (includeRoot._includedFrom != null) { 066 includeRoot = includeRoot._includedFrom; 067 } 068 069 return includeRoot.getMinimumDescendantPrecedence(); 070 } 071 072 /** 073 * Parse the attributes and contents of an <xsl:apply-imports/> element. 074 */ 075 public void parseContents(Parser parser) { 076 // Indicate to the top-level stylesheet that all templates must be 077 // compiled into separate methods. 078 Stylesheet stylesheet = getStylesheet(); 079 stylesheet.setTemplateInlining(false); 080 081 // Get the mode we are currently in (might not be any) 082 Template template = getTemplate(); 083 _modeName = template.getModeName(); 084 _precedence = template.getImportPrecedence(); 085 086 parseChildren(parser); // with-params 087 } 088 089 /** 090 * Type-check the attributes/contents of an <xsl:apply-imports/> element. 091 */ 092 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 093 typeCheckContents(stable); // with-params 094 return Type.Void; 095 } 096 097 /** 098 * Translate call-template. A parameter frame is pushed only if 099 * some template in the stylesheet uses parameters. 100 */ 101 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 102 final Stylesheet stylesheet = classGen.getStylesheet(); 103 final ConstantPoolGen cpg = classGen.getConstantPool(); 104 final InstructionList il = methodGen.getInstructionList(); 105 final int current = methodGen.getLocalIndex("current"); 106 107 // Push the arguments that are passed to applyTemplates() 108 il.append(classGen.loadTranslet()); 109 il.append(methodGen.loadDOM()); 110 il.append(methodGen.loadIterator()); 111 il.append(methodGen.loadHandler()); 112 il.append(methodGen.loadCurrentNode()); 113 114 // Push a new parameter frame in case imported template might expect 115 // parameters. The apply-imports has nothing that it can pass. 116 if (stylesheet.hasLocalParams()) { 117 il.append(classGen.loadTranslet()); 118 final int pushFrame = cpg.addMethodref(TRANSLET_CLASS, 119 PUSH_PARAM_FRAME, 120 PUSH_PARAM_FRAME_SIG); 121 il.append(new INVOKEVIRTUAL(pushFrame)); 122 } 123 124 // Get the [min,max> precedence of all templates imported under the 125 // current stylesheet 126 final int maxPrecedence = _precedence; 127 final int minPrecedence = getMinPrecedence(maxPrecedence); 128 final Mode mode = stylesheet.getMode(_modeName); 129 130 // Get name of appropriate apply-templates function for this 131 // xsl:apply-imports instruction 132 String functionName = mode.functionName(minPrecedence, maxPrecedence); 133 134 // Construct the translet class-name and the signature of the method 135 final String className = classGen.getStylesheet().getClassName(); 136 final String signature = classGen.getApplyTemplatesSigForImport(); 137 final int applyTemplates = cpg.addMethodref(className, 138 functionName, 139 signature); 140 il.append(new INVOKEVIRTUAL(applyTemplates)); 141 142 // Pop any parameter frame that was pushed above. 143 if (stylesheet.hasLocalParams()) { 144 il.append(classGen.loadTranslet()); 145 final int pushFrame = cpg.addMethodref(TRANSLET_CLASS, 146 POP_PARAM_FRAME, 147 POP_PARAM_FRAME_SIG); 148 il.append(new INVOKEVIRTUAL(pushFrame)); 149 } 150 } 151 152 }