| /* |
| * 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$ |
| */ |
| |
| package org.apache.xalan.xsltc.compiler; |
| |
| import org.apache.bcel.generic.ConstantPoolGen; |
| import org.apache.bcel.generic.INVOKEVIRTUAL; |
| import org.apache.bcel.generic.InstructionList; |
| import org.apache.xalan.xsltc.compiler.util.ClassGenerator; |
| import org.apache.xalan.xsltc.compiler.util.MethodGenerator; |
| import org.apache.xalan.xsltc.compiler.util.Type; |
| import org.apache.xalan.xsltc.compiler.util.TypeCheckError; |
| import org.apache.xalan.xsltc.compiler.util.Util; |
| |
| final class ApplyImports extends Instruction { |
| |
| private QName _modeName; |
| private int _precedence; |
| |
| public void display(int indent) { |
| indent(indent); |
| Util.println("ApplyTemplates"); |
| indent(indent + IndentIncrement); |
| if (_modeName != null) { |
| indent(indent + IndentIncrement); |
| Util.println("mode " + _modeName); |
| } |
| } |
| |
| /** |
| * Returns true if this <xsl:apply-imports/> element has parameters |
| */ |
| public boolean hasWithParams() { |
| return hasContents(); |
| } |
| |
| /** |
| * Determine the lowest import precedence for any stylesheet imported |
| * or included by the stylesheet in which this <xsl:apply-imports/> |
| * element occured. The templates that are imported by the stylesheet in |
| * which this element occured will all have higher import precedence than |
| * the integer returned by this method. |
| */ |
| private int getMinPrecedence(int max) { |
| // Move to root of include tree |
| Stylesheet includeRoot = getStylesheet(); |
| while (includeRoot._includedFrom != null) { |
| includeRoot = includeRoot._includedFrom; |
| } |
| |
| return includeRoot.getMinimumDescendantPrecedence(); |
| } |
| |
| /** |
| * Parse the attributes and contents of an <xsl:apply-imports/> element. |
| */ |
| public void parseContents(Parser parser) { |
| // Indicate to the top-level stylesheet that all templates must be |
| // compiled into separate methods. |
| Stylesheet stylesheet = getStylesheet(); |
| stylesheet.setTemplateInlining(false); |
| |
| // Get the mode we are currently in (might not be any) |
| Template template = getTemplate(); |
| _modeName = template.getModeName(); |
| _precedence = template.getImportPrecedence(); |
| |
| parseChildren(parser); // with-params |
| } |
| |
| /** |
| * Type-check the attributes/contents of an <xsl:apply-imports/> element. |
| */ |
| public Type typeCheck(SymbolTable stable) throws TypeCheckError { |
| typeCheckContents(stable); // with-params |
| return Type.Void; |
| } |
| |
| /** |
| * Translate call-template. A parameter frame is pushed only if |
| * some template in the stylesheet uses parameters. |
| */ |
| public void translate(ClassGenerator classGen, MethodGenerator methodGen) { |
| final Stylesheet stylesheet = classGen.getStylesheet(); |
| final ConstantPoolGen cpg = classGen.getConstantPool(); |
| final InstructionList il = methodGen.getInstructionList(); |
| final int current = methodGen.getLocalIndex("current"); |
| |
| // Push the arguments that are passed to applyTemplates() |
| il.append(classGen.loadTranslet()); |
| il.append(methodGen.loadDOM()); |
| il.append(methodGen.loadIterator()); |
| il.append(methodGen.loadHandler()); |
| il.append(methodGen.loadCurrentNode()); |
| |
| // Push a new parameter frame in case imported template might expect |
| // parameters. The apply-imports has nothing that it can pass. |
| if (stylesheet.hasLocalParams()) { |
| il.append(classGen.loadTranslet()); |
| final int pushFrame = cpg.addMethodref(TRANSLET_CLASS, |
| PUSH_PARAM_FRAME, |
| PUSH_PARAM_FRAME_SIG); |
| il.append(new INVOKEVIRTUAL(pushFrame)); |
| } |
| |
| // Get the [min,max> precedence of all templates imported under the |
| // current stylesheet |
| final int maxPrecedence = _precedence; |
| final int minPrecedence = getMinPrecedence(maxPrecedence); |
| final Mode mode = stylesheet.getMode(_modeName); |
| |
| // Get name of appropriate apply-templates function for this |
| // xsl:apply-imports instruction |
| String functionName = mode.functionName(minPrecedence, maxPrecedence); |
| |
| // Construct the translet class-name and the signature of the method |
| final String className = classGen.getStylesheet().getClassName(); |
| final String signature = classGen.getApplyTemplatesSigForImport(); |
| final int applyTemplates = cpg.addMethodref(className, |
| functionName, |
| signature); |
| il.append(new INVOKEVIRTUAL(applyTemplates)); |
| |
| // Pop any parameter frame that was pushed above. |
| if (stylesheet.hasLocalParams()) { |
| il.append(classGen.loadTranslet()); |
| final int pushFrame = cpg.addMethodref(TRANSLET_CLASS, |
| POP_PARAM_FRAME, |
| POP_PARAM_FRAME_SIG); |
| il.append(new INVOKEVIRTUAL(pushFrame)); |
| } |
| } |
| |
| } |