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 }