KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xalan > internal > xsltc > compiler > CallTemplate


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: CallTemplate.java,v 1.1.2.2 2006/11/10 20:25:17 spericas Exp $
18  */

19
20 package com.sun.org.apache.xalan.internal.xsltc.compiler;
21
22 import com.sun.org.apache.bcel.internal.generic.ALOAD;
23 import com.sun.org.apache.bcel.internal.generic.ASTORE;
24 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
25 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
26 import com.sun.org.apache.bcel.internal.generic.InstructionList;
27 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
34 import com.sun.org.apache.xml.internal.utils.XMLChar;
35
36 import java.util.Vector JavaDoc;
37
38 /**
39  * @author Jacek Ambroziak
40  * @author Santiago Pericas-Geertsen
41  * @author Erwin Bolwidt <ejb@klomp.org>
42  */

43 final class CallTemplate extends Instruction {
44     
45     /**
46      * Name of template to call.
47      */

48     private QName _name;
49     
50     /**
51      * The array of effective parameters in this CallTemplate. An object in
52      * this array can be either a WithParam or a Param if no WithParam
53      * exists for a particular parameter.
54      */

55     private Object JavaDoc[] _parameters = null;
56         
57     /**
58      * The corresponding template which this CallTemplate calls.
59      */

60     private Template _calleeTemplate = null;
61     
62     public void display(int indent) {
63     indent(indent);
64     System.out.print("CallTemplate");
65     Util.println(" name " + _name);
66     displayContents(indent + IndentIncrement);
67     }
68         
69     public boolean hasWithParams() {
70     return elementCount() > 0;
71     }
72
73     public void parseContents(Parser parser) {
74         final String JavaDoc name = getAttribute("name");
75         if (name.length() > 0) {
76             if (!XMLChar.isValidQName(name)) {
77                 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name, this);
78                 parser.reportError(Constants.ERROR, err);
79             }
80             _name = parser.getQNameIgnoreDefaultNs(name);
81         }
82         else {
83             reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name");
84         }
85     parseChildren(parser);
86     }
87         
88     /**
89      * Verify that a template with this name exists.
90      */

91     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
92     final Template template = stable.lookupTemplate(_name);
93     if (template != null) {
94         typeCheckContents(stable);
95     }
96     else {
97         ErrorMsg err = new ErrorMsg(ErrorMsg.TEMPLATE_UNDEF_ERR,_name,this);
98         throw new TypeCheckError(err);
99     }
100     return Type.Void;
101     }
102
103     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
104     final Stylesheet stylesheet = classGen.getStylesheet();
105     final ConstantPoolGen cpg = classGen.getConstantPool();
106     final InstructionList il = methodGen.getInstructionList();
107
108         // If there are Params in the stylesheet or WithParams in this call?
109
if (stylesheet.hasLocalParams() || hasContents()) {
110         _calleeTemplate = getCalleeTemplate();
111         
112         // Build the parameter list if the called template is simple named
113
if (_calleeTemplate != null) {
114             buildParameterList();
115         }
116         // This is only needed when the called template is not
117
// a simple named template.
118
else {
119             // Push parameter frame
120
final int push = cpg.addMethodref(TRANSLET_CLASS,
121                               PUSH_PARAM_FRAME,
122                               PUSH_PARAM_FRAME_SIG);
123             il.append(classGen.loadTranslet());
124             il.append(new INVOKEVIRTUAL(push));
125             translateContents(classGen, methodGen);
126         }
127     }
128
129         // Generate a valid Java method name
130
final String JavaDoc className = stylesheet.getClassName();
131         String JavaDoc methodName = Util.escape(_name.toString());
132
133         // Load standard arguments
134
il.append(classGen.loadTranslet());
135     il.append(methodGen.loadDOM());
136     il.append(methodGen.loadIterator());
137     il.append(methodGen.loadHandler());
138     il.append(methodGen.loadCurrentNode());
139         
140         // Initialize prefix of method signature
141
StringBuffer JavaDoc methodSig = new StringBuffer JavaDoc("(" + DOM_INTF_SIG
142             + NODE_ITERATOR_SIG + TRANSLET_OUTPUT_SIG + NODE_SIG);
143     
144         // If calling a simply named template, push actual arguments
145
if (_calleeTemplate != null) {
146         Vector JavaDoc calleeParams = _calleeTemplate.getParameters();
147         int numParams = _parameters.length;
148         
149         for (int i = 0; i < numParams; i++) {
150             SyntaxTreeNode node = (SyntaxTreeNode)_parameters[i];
151                 methodSig.append(OBJECT_SIG); // append Object to signature
152

153                 // Push 'null' if Param to indicate no actual parameter specified
154
if (node instanceof Param) {
155                     il.append(ACONST_NULL);
156                 }
157                 else { // translate WithParam
158
node.translate(classGen, methodGen);
159                 }
160             }
161         }
162
163         // Complete signature and generate invokevirtual call
164
methodSig.append(")V");
165     il.append(new INVOKEVIRTUAL(cpg.addMethodref(className,
166                              methodName,
167                              methodSig.toString())));
168     
169     // Do not need to call Translet.popParamFrame() if we are
170
// calling a simple named template.
171
if (_calleeTemplate == null && (stylesheet.hasLocalParams() || hasContents())) {
172         // Pop parameter frame
173
final int pop = cpg.addMethodref(TRANSLET_CLASS,
174                          POP_PARAM_FRAME,
175                          POP_PARAM_FRAME_SIG);
176         il.append(classGen.loadTranslet());
177         il.append(new INVOKEVIRTUAL(pop));
178     }
179     }
180     
181     /**
182      * Return the simple named template which this CallTemplate calls.
183      * Return false if there is no matched template or the matched
184      * template is not a simple named template.
185      */

186     public Template getCalleeTemplate() {
187         Template foundTemplate
188             = getXSLTC().getParser().getSymbolTable().lookupTemplate(_name);
189
190         return foundTemplate.isSimpleNamedTemplate() ? foundTemplate : null;
191     }
192     
193     /**
194      * Build the list of effective parameters in this CallTemplate.
195      * The parameters of the called template are put into the array first.
196      * Then we visit the WithParam children of this CallTemplate and replace
197      * the Param with a corresponding WithParam having the same name.
198      */

199     private void buildParameterList() {
200         // Put the parameters from the called template into the array first.
201
// This is to ensure the order of the parameters.
202
Vector JavaDoc defaultParams = _calleeTemplate.getParameters();
203         int numParams = defaultParams.size();
204         _parameters = new Object JavaDoc[numParams];
205         for (int i = 0; i < numParams; i++) {
206             _parameters[i] = defaultParams.elementAt(i);
207         }
208                     
209         // Replace a Param with a WithParam if they have the same name.
210
int count = elementCount();
211         for (int i = 0; i < count; i++) {
212             Object JavaDoc node = elementAt(i);
213             
214             // Ignore if not WithParam
215
if (node instanceof WithParam) {
216                 WithParam withParam = (WithParam)node;
217                 QName name = withParam.getName();
218                 
219                 // Search for a Param with the same name
220
for (int k = 0; k < numParams; k++) {
221                     Object JavaDoc object = _parameters[k];
222                     if (object instanceof Param
223                         && ((Param)object).getName() == name) {
224                         withParam.setDoParameterOptimization(true);
225                         _parameters[k] = withParam;
226                         break;
227                     }
228                     else if (object instanceof WithParam
229                         && ((WithParam)object).getName() == name) {
230                         withParam.setDoParameterOptimization(true);
231                         _parameters[k] = withParam;
232                         break;
233                     }
234                 }
235             }
236         }
237      }
238 }
239     
240
Popular Tags