KickJava   Java API By Example, From Geeks To Geeks.

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


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: XslAttribute.java,v 1.24 2004/02/24 03:55:48 zongaro Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import java.util.Vector JavaDoc;
23
24 import org.apache.bcel.generic.ALOAD;
25 import org.apache.bcel.generic.ASTORE;
26 import org.apache.bcel.generic.ConstantPoolGen;
27 import org.apache.bcel.generic.GETFIELD;
28 import org.apache.bcel.generic.INVOKESTATIC;
29 import org.apache.bcel.generic.INVOKEVIRTUAL;
30 import org.apache.bcel.generic.InstructionList;
31 import org.apache.bcel.generic.LocalVariableGen;
32 import org.apache.bcel.generic.PUSH;
33 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
34 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
35 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
36 import org.apache.xalan.xsltc.compiler.util.Type;
37 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
38 import org.apache.xalan.xsltc.compiler.util.Util;
39 import org.apache.xml.utils.XMLChar;
40
41 import org.apache.xml.serializer.ElemDesc;
42 import org.apache.xml.serializer.SerializationHandler;
43
44 /**
45  * @author Jacek Ambroziak
46  * @author Santiago Pericas-Geertsen
47  * @author Morten Jorgensen
48  * @author Erwin Bolwidt <ejb@klomp.org>
49  * @author Gunnlaugur Briem <gthb@dimon.is>
50  */

51 final class XslAttribute extends Instruction {
52
53     private String JavaDoc _prefix;
54     private AttributeValue _name; // name treated as AVT (7.1.3)
55
private AttributeValueTemplate _namespace = null;
56     private boolean _ignore = false;
57     private boolean _isLiteral = false; // specified name is not AVT
58

59     /**
60      * Returns the name of the attribute
61      */

62     public AttributeValue getName() {
63     return _name;
64     }
65
66     /**
67      * Displays the contents of the attribute
68      */

69     public void display(int indent) {
70     indent(indent);
71     Util.println("Attribute " + _name);
72     displayContents(indent + IndentIncrement);
73     }
74         
75     /**
76      * Parses the attribute's contents. Special care taken for namespaces.
77      */

78     public void parseContents(Parser parser) {
79     boolean generated = false;
80     final SymbolTable stable = parser.getSymbolTable();
81
82     String JavaDoc name = getAttribute("name");
83     String JavaDoc namespace = getAttribute("namespace");
84     QName qname = parser.getQName(name, false);
85     final String JavaDoc prefix = qname.getPrefix();
86
87         if (((prefix != null) && (prefix.equals(XMLNS_PREFIX)))||(name.equals(XMLNS_PREFIX))) {
88         reportError(this, parser, ErrorMsg.ILLEGAL_ATTR_NAME_ERR, name);
89         return;
90     }
91   
92         _isLiteral = Util.isLiteral(name);
93         if (_isLiteral) {
94             if (!XMLChar.isValidQName(name)) {
95                 reportError(this, parser, ErrorMsg.ILLEGAL_ATTR_NAME_ERR, name);
96                 return;
97             }
98         }
99
100     // Ignore attribute if preceeded by some other type of element
101
final SyntaxTreeNode parent = getParent();
102     final Vector JavaDoc siblings = parent.getContents();
103     for (int i = 0; i < parent.elementCount(); i++) {
104         SyntaxTreeNode item = (SyntaxTreeNode)siblings.elementAt(i);
105         if (item == this) break;
106
107         // These three objects result in one or more attribute output
108
if (item instanceof XslAttribute) continue;
109         if (item instanceof UseAttributeSets) continue;
110         if (item instanceof LiteralAttribute) continue;
111         if (item instanceof Text) continue;
112
113         // These objects _can_ result in one or more attribute
114
// The output handler will generate an error if not (at runtime)
115
if (item instanceof If) continue;
116         if (item instanceof Choose) continue;
117         if (item instanceof CopyOf) continue;
118         if (item instanceof VariableBase) continue;
119
120         // Report warning but do not ignore attribute
121
reportWarning(this, parser, ErrorMsg.STRAY_ATTRIBUTE_ERR, name);
122     }
123
124     // Get namespace from namespace attribute?
125
if (namespace != null && namespace != Constants.EMPTYSTRING) {
126         _prefix = lookupPrefix(namespace);
127         _namespace = new AttributeValueTemplate(namespace, parser, this);
128     }
129     // Get namespace from prefix in name attribute?
130
else if (prefix != null && prefix != Constants.EMPTYSTRING) {
131         _prefix = prefix;
132         namespace = lookupNamespace(prefix);
133         if (namespace != null) {
134         _namespace = new AttributeValueTemplate(namespace, parser, this);
135         }
136     }
137     
138     // Common handling for namespaces:
139
if (_namespace != null) {
140         // Generate prefix if we have none
141
if (_prefix == null || _prefix == Constants.EMPTYSTRING) {
142         if (prefix != null) {
143             _prefix = prefix;
144         }
145         else {
146             _prefix = stable.generateNamespacePrefix();
147             generated = true;
148         }
149         }
150         else if (prefix != null && !prefix.equals(_prefix)) {
151         _prefix = prefix;
152         }
153
154         name = _prefix + ":" + qname.getLocalPart();
155
156         /*
157          * TODO: The namespace URI must be passed to the parent
158          * element but we don't yet know what the actual URI is
159          * (as we only know it as an attribute value template).
160          */

161         if ((parent instanceof LiteralElement) && (!generated)) {
162         ((LiteralElement)parent).registerNamespace(_prefix,
163                                namespace,
164                                stable, false);
165         }
166     }
167
168     if (parent instanceof LiteralElement) {
169         ((LiteralElement)parent).addAttribute(this);
170     }
171
172     _name = AttributeValue.create(this, name, parser);
173     parseChildren(parser);
174     }
175     
176     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
177     if (!_ignore) {
178         _name.typeCheck(stable);
179         if (_namespace != null) {
180         _namespace.typeCheck(stable);
181         }
182         typeCheckContents(stable);
183     }
184     return Type.Void;
185     }
186
187     /**
188      *
189      */

190     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
191     final ConstantPoolGen cpg = classGen.getConstantPool();
192     final InstructionList il = methodGen.getInstructionList();
193
194     if (_ignore) return;
195     _ignore = true;
196
197     // Compile code that emits any needed namespace declaration
198
if (_namespace != null) {
199         // public void attribute(final String name, final String value)
200
il.append(methodGen.loadHandler());
201         il.append(new PUSH(cpg,_prefix));
202         _namespace.translate(classGen,methodGen);
203         il.append(methodGen.namespace());
204     }
205     
206         if (!_isLiteral) {
207             // if the qname is an AVT, then the qname has to be checked at runtime if it is a valid qname
208
LocalVariableGen nameValue = methodGen.addLocalVariable2("nameValue",
209                     Util.getJCRefType(STRING_SIG),
210                     il.getEnd());
211                     
212             // store the name into a variable first so _name.translate only needs to be called once
213
_name.translate(classGen, methodGen);
214             il.append(new ASTORE(nameValue.getIndex()));
215             il.append(new ALOAD(nameValue.getIndex()));
216             
217             // call checkQName if the name is an AVT
218
final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "checkAttribQName",
219                             "("
220                             +STRING_SIG
221                             +")V");
222             il.append(new INVOKESTATIC(check));
223             
224             // Save the current handler base on the stack
225
il.append(methodGen.loadHandler());
226             il.append(DUP); // first arg to "attributes" call
227

228             // load name value again
229
il.append(new ALOAD(nameValue.getIndex()));
230         } else {
231             // Save the current handler base on the stack
232
il.append(methodGen.loadHandler());
233             il.append(DUP); // first arg to "attributes" call
234

235             // Push attribute name
236
_name.translate(classGen, methodGen);// 2nd arg
237

238         }
239
240     // Push attribute value - shortcut for literal strings
241
if ((elementCount() == 1) && (elementAt(0) instanceof Text)) {
242         il.append(new PUSH(cpg, ((Text)elementAt(0)).getText()));
243     }
244     else {
245         il.append(classGen.loadTranslet());
246         il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
247                            "stringValueHandler",
248                            STRING_VALUE_HANDLER_SIG)));
249         il.append(DUP);
250         il.append(methodGen.storeHandler());
251         // translate contents with substituted handler
252
translateContents(classGen, methodGen);
253         // get String out of the handler
254
il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_VALUE_HANDLER,
255                              "getValue",
256                              "()" + STRING_SIG)));
257     }
258
259     SyntaxTreeNode parent = getParent();
260     if (parent instanceof LiteralElement
261         && ((LiteralElement)parent).allAttributesUnique()) {
262             int flags = 0;
263         ElemDesc elemDesc = ((LiteralElement)parent).getElemDesc();
264         
265         // Set the HTML flags
266
if (elemDesc != null && _name instanceof SimpleAttributeValue) {
267             String JavaDoc attrName = ((SimpleAttributeValue)_name).toString();
268             if (elemDesc.isAttrFlagSet(attrName, ElemDesc.ATTREMPTY)) {
269                 flags = flags | SerializationHandler.HTML_ATTREMPTY;
270             }
271             else if (elemDesc.isAttrFlagSet(attrName, ElemDesc.ATTRURL)) {
272                 flags = flags | SerializationHandler.HTML_ATTRURL;
273             }
274         }
275         il.append(new PUSH(cpg, flags));
276         il.append(methodGen.uniqueAttribute());
277     }
278     else {
279         // call "attribute"
280
il.append(methodGen.attribute());
281     }
282             
283     // Restore old handler base from stack
284
il.append(methodGen.storeHandler());
285     
286
287         
288     }
289
290 }
291
Popular Tags