KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > compiler > XslElement


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: XslElement.java,v 1.23 2004/02/24 03:55:48 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.ICONST;
26 import org.apache.bcel.generic.INVOKESTATIC;
27 import org.apache.bcel.generic.InstructionList;
28 import org.apache.bcel.generic.LocalVariableGen;
29 import org.apache.bcel.generic.PUSH;
30 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
31 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
32 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
33 import org.apache.xalan.xsltc.compiler.util.Type;
34 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
35 import org.apache.xalan.xsltc.compiler.util.Util;
36 import org.apache.xml.utils.XMLChar;
37
38 /**
39  * @author Jacek Ambroziak
40  * @author Santiago Pericas-Geertsen
41  * @author Morten Jorgensen
42  */

43 final class XslElement extends Instruction {
44
45     private String JavaDoc _prefix;
46     private boolean _ignore = false;
47     private boolean _isLiteralName = true;
48     private AttributeValueTemplate _name;
49     private AttributeValueTemplate _namespace;
50
51     /**
52      * Displays the contents of the element
53      */

54     public void display(int indent) {
55     indent(indent);
56     Util.println("Element " + _name);
57     displayContents(indent + IndentIncrement);
58     }
59
60     /**
61      * This method is now deprecated. The new implemation of this class
62      * never declares the default NS.
63      */

64     public boolean declaresDefaultNS() {
65     return false;
66     }
67
68     public void parseContents(Parser parser) {
69     final SymbolTable stable = parser.getSymbolTable();
70
71     // Handle the 'name' attribute
72
String JavaDoc name = getAttribute("name");
73     if (name == EMPTYSTRING) {
74         ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
75                     name, this);
76         parser.reportError(WARNING, msg);
77         parseChildren(parser);
78         _ignore = true; // Ignore the element if the QName is invalid
79
return;
80     }
81
82     // Get namespace attribute
83
String JavaDoc namespace = getAttribute("namespace");
84
85     // Optimize compilation when name is known at compile time
86
_isLiteralName = Util.isLiteral(name);
87     if (_isLiteralName) {
88             if (!XMLChar.isValidQName(name)) {
89         ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
90                         name, this);
91         parser.reportError(WARNING, msg);
92         parseChildren(parser);
93         _ignore = true; // Ignore the element if the QName is invalid
94
return;
95         }
96
97         final QName qname = parser.getQNameSafe(name);
98         String JavaDoc prefix = qname.getPrefix();
99         String JavaDoc local = qname.getLocalPart();
100         
101         if (prefix == null) {
102         prefix = EMPTYSTRING;
103         }
104
105         if (!hasAttribute("namespace")) {
106         namespace = lookupNamespace(prefix);
107         if (namespace == null) {
108             ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
109                         prefix, this);
110             parser.reportError(WARNING, err);
111             parseChildren(parser);
112             _ignore = true; // Ignore the element if prefix is undeclared
113
return;
114         }
115         _prefix = prefix;
116         _namespace = new AttributeValueTemplate(namespace, parser, this);
117         }
118         else {
119         if (prefix == EMPTYSTRING) {
120                 if (Util.isLiteral(namespace)) {
121             prefix = lookupPrefix(namespace);
122             if (prefix == null) {
123                 prefix = stable.generateNamespacePrefix();
124             }
125             }
126
127             // Prepend prefix to local name
128
final StringBuffer JavaDoc newName = new StringBuffer JavaDoc(prefix);
129             if (prefix != EMPTYSTRING) {
130             newName.append(':');
131             }
132             name = newName.append(local).toString();
133         }
134         _prefix = prefix;
135         _namespace = new AttributeValueTemplate(namespace, parser, this);
136         }
137     }
138     else {
139         _namespace = (namespace == EMPTYSTRING) ? null :
140              new AttributeValueTemplate(namespace, parser, this);
141     }
142
143     _name = new AttributeValueTemplate(name, parser, this);
144
145     final String JavaDoc useSets = getAttribute("use-attribute-sets");
146     if (useSets.length() > 0) {
147             if (!Util.isValidQNames(useSets)) {
148                 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, useSets, this);
149                 parser.reportError(Constants.ERROR, err);
150             }
151         setFirstElement(new UseAttributeSets(useSets, parser));
152     }
153
154     parseChildren(parser);
155     }
156
157     /**
158      * Run type check on element name & contents
159      */

160     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
161     if (!_ignore) {
162         _name.typeCheck(stable);
163         if (_namespace != null) {
164         _namespace.typeCheck(stable);
165         }
166     }
167     typeCheckContents(stable);
168     return Type.Void;
169     }
170
171     /**
172      * This method is called when the name of the element is known at compile time.
173      * In this case, there is no need to inspect the element name at runtime to
174      * determine if a prefix exists, needs to be generated, etc.
175      */

176     public void translateLiteral(ClassGenerator classGen, MethodGenerator methodGen) {
177     final ConstantPoolGen cpg = classGen.getConstantPool();
178     final InstructionList il = methodGen.getInstructionList();
179
180     if (!_ignore) {
181         il.append(methodGen.loadHandler());
182         _name.translate(classGen, methodGen);
183         il.append(DUP2);
184         il.append(methodGen.startElement());
185
186         if (_namespace != null) {
187         il.append(methodGen.loadHandler());
188         il.append(new PUSH(cpg, _prefix));
189         _namespace.translate(classGen,methodGen);
190         il.append(methodGen.namespace());
191         }
192     }
193
194     translateContents(classGen, methodGen);
195
196     if (!_ignore) {
197         il.append(methodGen.endElement());
198     }
199     }
200
201     /**
202      * At runtime the compilation of xsl:element results in code that: (i)
203      * evaluates the avt for the name, (ii) checks for a prefix in the name
204      * (iii) generates a new prefix and create a new qname when necessary
205      * (iv) calls startElement() on the handler (v) looks up a uri in the XML
206      * when the prefix is not known at compile time (vi) calls namespace()
207      * on the handler (vii) evaluates the contents (viii) calls endElement().
208      */

209     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
210     LocalVariableGen local = null;
211     final ConstantPoolGen cpg = classGen.getConstantPool();
212     final InstructionList il = methodGen.getInstructionList();
213
214     // Optimize translation if element name is a literal
215
if (_isLiteralName) {
216         translateLiteral(classGen, methodGen);
217         return;
218     }
219
220     if (!_ignore) {
221        
222             // if the qname is an AVT, then the qname has to be checked at runtime if it is a valid qname
223
LocalVariableGen nameValue = methodGen.addLocalVariable2("nameValue",
224                     Util.getJCRefType(STRING_SIG),
225                     il.getEnd());
226                     
227             // store the name into a variable first so _name.translate only needs to be called once
228
_name.translate(classGen, methodGen);
229             il.append(new ASTORE(nameValue.getIndex()));
230             il.append(new ALOAD(nameValue.getIndex()));
231             
232             // call checkQName if the name is an AVT
233
final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "checkQName",
234                             "("
235                             +STRING_SIG
236                             +")V");
237             il.append(new INVOKESTATIC(check));
238             
239             // Push handler for call to endElement()
240
il.append(methodGen.loadHandler());
241             
242             // load name value again
243
il.append(new ALOAD(nameValue.getIndex()));
244                     
245         if (_namespace != null) {
246         _namespace.translate(classGen, methodGen);
247         }
248         else {
249         il.append(ACONST_NULL);
250         }
251
252         // Push additional arguments
253
il.append(methodGen.loadHandler());
254         il.append(methodGen.loadDOM());
255         il.append(methodGen.loadCurrentNode());
256         
257             // Invoke BasisLibrary.startXslElemCheckQName()
258
il.append(new INVOKESTATIC(
259             cpg.addMethodref(BASIS_LIBRARY_CLASS, "startXslElement",
260                     "(" + STRING_SIG
261                     + STRING_SIG
262                     + TRANSLET_OUTPUT_SIG
263                     + DOM_INTF_SIG + "I)" + STRING_SIG)));
264
265
266     }
267
268     translateContents(classGen, methodGen);
269
270     if (!_ignore) {
271         il.append(methodGen.endElement());
272     }
273     }
274
275     /**
276      * Override this method to make sure that xsl:attributes are not
277      * copied to output if this xsl:element is to be ignored
278      */

279     public void translateContents(ClassGenerator classGen,
280                   MethodGenerator methodGen) {
281     final int n = elementCount();
282     for (int i = 0; i < n; i++) {
283         final SyntaxTreeNode item =
284         (SyntaxTreeNode)getContents().elementAt(i);
285         if (_ignore && item instanceof XslAttribute) continue;
286         item.translate(classGen, methodGen);
287     }
288     }
289
290 }
291
Popular Tags