View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: WithParam.java,v 1.2.4.1 2005/09/12 11:38:01 pvedula Exp $
22   */
23  
24  package com.sun.org.apache.xalan.internal.xsltc.compiler;
25  
26  import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
27  import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
28  import com.sun.org.apache.bcel.internal.generic.InstructionList;
29  import com.sun.org.apache.bcel.internal.generic.PUSH;
30  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
31  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
32  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
33  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType;
34  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
35  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
36  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
37  import com.sun.org.apache.xml.internal.utils.XML11Char;
38  
39  /**
40   * @author Jacek Ambroziak
41   * @author Santiago Pericas-Geertsen
42   * @author Morten Jorgensen
43   * @author John Howard <JohnH@schemasoft.com>
44   */
45  final class WithParam extends Instruction {
46  
47      /**
48       * Parameter's name.
49       */
50      private QName _name;
51  
52      /**
53       * The escaped qname of the with-param.
54       */
55      protected String _escapedName;
56  
57      /**
58       * Parameter's default value.
59       */
60      private Expression _select;
61  
62      /**
63       * %OPT% This is set to true when the WithParam is used in a CallTemplate
64       * for a simple named template. If this is true, the parameters are
65       * passed to the named template through method arguments rather than
66       * using the expensive Translet.addParameter() call.
67       */
68      private boolean _doParameterOptimization = false;
69  
70      /**
71       * Displays the contents of this element
72       */
73      public void display(int indent) {
74          indent(indent);
75          Util.println("with-param " + _name);
76          if (_select != null) {
77              indent(indent + IndentIncrement);
78              Util.println("select " + _select.toString());
79          }
80          displayContents(indent + IndentIncrement);
81      }
82  
83      /**
84       * Returns the escaped qname of the parameter
85       */
86      public String getEscapedName() {
87          return _escapedName;
88      }
89  
90      /**
91       * Return the name of this WithParam.
92       */
93      public QName getName() {
94          return _name;
95      }
96  
97      /**
98       * Set the name of the variable or paremeter. Escape all special chars.
99       */
100     public void setName(QName name) {
101         _name = name;
102         _escapedName = Util.escape(name.getStringRep());
103     }
104 
105     /**
106      * Set the do parameter optimization flag
107      */
108     public void setDoParameterOptimization(boolean flag) {
109         _doParameterOptimization = flag;
110     }
111 
112     /**
113      * The contents of a <xsl:with-param> elements are either in the element's
114      * 'select' attribute (this has precedence) or in the element body.
115      */
116     public void parseContents(Parser parser) {
117         final String name = getAttribute("name");
118         if (name.length() > 0) {
119             if (!XML11Char.isXML11ValidQName(name)) {
120                 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name,
121                                             this);
122                 parser.reportError(Constants.ERROR, err);
123             }
124             setName(parser.getQNameIgnoreDefaultNs(name));
125         }
126         else {
127             reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name");
128         }
129 
130         final String select = getAttribute("select");
131         if (select.length() > 0) {
132             _select = parser.parseExpression(this, "select", null);
133         }
134 
135         parseChildren(parser);
136     }
137 
138     /**
139      * Type-check either the select attribute or the element body, depending
140      * on which is in use.
141      */
142     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
143         if (_select != null) {
144             final Type tselect = _select.typeCheck(stable);
145             if (tselect instanceof ReferenceType == false) {
146                 _select = new CastExpr(_select, Type.Reference);
147             }
148         }
149         else {
150             typeCheckContents(stable);
151         }
152         return Type.Void;
153     }
154 
155     /**
156      * Compile the value of the parameter, which is either in an expression in
157      * a 'select' attribute, or in the with-param element's body
158      */
159     public void translateValue(ClassGenerator classGen,
160                                MethodGenerator methodGen) {
161         // Compile expression is 'select' attribute if present
162         if (_select != null) {
163             _select.translate(classGen, methodGen);
164             _select.startIterator(classGen, methodGen);
165         }
166         // If not, compile result tree from parameter body if present.
167         else if (hasContents()) {
168             compileResultTree(classGen, methodGen);
169         }
170         // If neither are present then store empty string in parameter slot
171         else {
172             final ConstantPoolGen cpg = classGen.getConstantPool();
173             final InstructionList il = methodGen.getInstructionList();
174             il.append(new PUSH(cpg, Constants.EMPTYSTRING));
175         }
176     }
177 
178     /**
179      * This code generates a sequence of bytecodes that call the
180      * addParameter() method in AbstractTranslet. The method call will add
181      * (or update) the parameter frame with the new parameter value.
182      */
183     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
184         final ConstantPoolGen cpg = classGen.getConstantPool();
185         final InstructionList il = methodGen.getInstructionList();
186 
187         // Translate the value and put it on the stack
188         if (_doParameterOptimization) {
189             translateValue(classGen, methodGen);
190             return;
191         }
192 
193         // Make name acceptable for use as field name in class
194         String name = Util.escape(getEscapedName());
195 
196         // Load reference to the translet (method is in AbstractTranslet)
197         il.append(classGen.loadTranslet());
198 
199         // Load the name of the parameter
200         il.append(new PUSH(cpg, name)); // TODO: namespace ?
201         // Generete the value of the parameter (use value in 'select' by def.)
202         translateValue(classGen, methodGen);
203         // Mark this parameter value is not being the default value
204         il.append(new PUSH(cpg, false));
205         // Pass the parameter to the template
206         il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
207                                                      ADD_PARAMETER,
208                                                      ADD_PARAMETER_SIG)));
209         il.append(POP); // cleanup stack
210     }
211 }