KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > 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.18 2004/02/24 02:57:28 zongaro Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import org.apache.bcel.generic.ALOAD;
23 import org.apache.bcel.generic.ASTORE;
24 import org.apache.bcel.generic.ConstantPoolGen;
25 import org.apache.bcel.generic.INVOKEVIRTUAL;
26 import org.apache.bcel.generic.InstructionList;
27 import org.apache.bcel.generic.LocalVariableGen;
28 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
29 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
30 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
31 import org.apache.xalan.xsltc.compiler.util.Type;
32 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
33 import org.apache.xalan.xsltc.compiler.util.Util;
34 import org.apache.xml.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         Stylesheet stylesheet = getXSLTC().getStylesheet();
188         Vector JavaDoc templates = stylesheet.getAllValidTemplates();
189         
190         int size = templates.size();
191         for (int i = 0; i < size; i++) {
192             Template t = (Template)templates.elementAt(i);
193             if (t.getName() == _name && t.isSimpleNamedTemplate()) {
194                 return t;
195             }
196         }
197         return null;
198     }
199     
200     /**
201      * Build the list of effective parameters in this CallTemplate.
202      * The parameters of the called template are put into the array first.
203      * Then we visit the WithParam children of this CallTemplate and replace
204      * the Param with a corresponding WithParam having the same name.
205      */

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