KickJava   Java API By Example, From Geeks To Geeks.

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


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: SyntaxTreeNode.java,v 1.31 2004/12/10 18:46:42 santiagopg Exp $
18  */

19
20 package com.sun.org.apache.xalan.internal.xsltc.compiler;
21
22 import java.util.Enumeration JavaDoc;
23 import java.util.Hashtable JavaDoc;
24 import java.util.Vector JavaDoc;
25
26 import com.sun.org.apache.bcel.internal.generic.ANEWARRAY;
27 import com.sun.org.apache.bcel.internal.generic.BasicType;
28 import com.sun.org.apache.bcel.internal.generic.CHECKCAST;
29 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
30 import com.sun.org.apache.bcel.internal.generic.DUP_X1;
31 import com.sun.org.apache.bcel.internal.generic.GETFIELD;
32 import com.sun.org.apache.bcel.internal.generic.ICONST;
33 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
34 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
35 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
36 import com.sun.org.apache.bcel.internal.generic.InstructionList;
37 import com.sun.org.apache.bcel.internal.generic.NEW;
38 import com.sun.org.apache.bcel.internal.generic.NEWARRAY;
39 import com.sun.org.apache.bcel.internal.generic.PUSH;
40 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
41 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
42 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
43 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
44 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
45 import com.sun.org.apache.xalan.internal.xsltc.DOM;
46 import com.sun.org.apache.xalan.internal.xsltc.runtime.AttributeList;
47
48 import org.xml.sax.Attributes JavaDoc;
49
50
51
52 /**
53  * @author Jacek Ambroziak
54  * @author Santiago Pericas-Geertsen
55  * @author G. Todd Miller
56  * @author Morten Jorensen
57  * @author Erwin Bolwidt <ejb@klomp.org>
58  * @author John Howard <JohnH@schemasoft.com>
59  */

60 public abstract class SyntaxTreeNode implements Constants {
61
62     // Reference to the AST parser
63
private Parser _parser;
64
65     // AST navigation pointers
66
protected SyntaxTreeNode _parent; // Parent node
67
private Stylesheet _stylesheet; // Stylesheet ancestor node
68
private Template _template; // Template ancestor node
69
private final Vector JavaDoc _contents = new Vector JavaDoc(2); // Child nodes
70

71     // Element description data
72
protected QName _qname; // The element QName
73
private int _line; // Source file line number
74
protected AttributeList _attributes = null; // Attributes of this element
75
private Hashtable JavaDoc _prefixMapping = null; // Namespace declarations
76

77     // Sentinel - used to denote unrecognised syntaxt tree nodes.
78
protected static final SyntaxTreeNode Dummy = new AbsolutePathPattern(null);
79
80     // These two are used for indenting nodes in the AST (debug output)
81
protected static final int IndentIncrement = 4;
82     private static final char[] _spaces =
83     " ".toCharArray();
84
85     /**
86      * Creates a new SyntaxTreeNode with a 'null' QName and no source file
87      * line number reference.
88      */

89     public SyntaxTreeNode() {
90     _line = 0;
91     _qname = null;
92     }
93
94     /**
95      * Creates a new SyntaxTreeNode with a 'null' QName.
96      * @param line Source file line number reference
97      */

98     public SyntaxTreeNode(int line) {
99     _line = line;
100     _qname = null;
101     }
102
103     /**
104      * Creates a new SyntaxTreeNode with no source file line number reference.
105      * @param uri The element's namespace URI
106      * @param prefix The element's namespace prefix
107      * @param local The element's local name
108      */

109     public SyntaxTreeNode(String JavaDoc uri, String JavaDoc prefix, String JavaDoc local) {
110     _line = 0;
111     setQName(uri, prefix, local);
112     }
113
114     /**
115      * Set the source file line number for this element
116      * @param line The source file line number.
117      */

118     protected final void setLineNumber(int line) {
119     _line = line;
120     }
121
122     /**
123      * Get the source file line number for this element. If unavailable, lookup
124      * in ancestors.
125      *
126      * @return The source file line number.
127      */

128     public final int getLineNumber() {
129         if (_line > 0) return _line;
130         SyntaxTreeNode parent = getParent();
131         return (parent != null) ? parent.getLineNumber() : 0;
132     }
133
134     /**
135      * Set the QName for the syntax tree node.
136      * @param qname The QName for the syntax tree node
137      */

138     protected void setQName(QName qname) {
139     _qname = qname;
140     }
141
142     /**
143      * Set the QName for the SyntaxTreeNode
144      * @param uri The element's namespace URI
145      * @param prefix The element's namespace prefix
146      * @param local The element's local name
147      */

148     protected void setQName(String JavaDoc uri, String JavaDoc prefix, String JavaDoc localname) {
149     _qname = new QName(uri, prefix, localname);
150     }
151
152     /**
153      * Set the QName for the SyntaxTreeNode
154      * @param qname The QName for the syntax tree node
155      */

156     protected QName getQName() {
157     return(_qname);
158     }
159
160     /**
161      * Set the attributes for this SyntaxTreeNode.
162      * @param attributes Attributes for the element. Must be passed in as an
163      * implementation of org.xml.sax.Attributes.
164      */

165     protected void setAttributes(AttributeList attributes) {
166     _attributes = attributes;
167     }
168
169     /**
170      * Returns a value for an attribute from the source element.
171      * @param qname The QName of the attribute to return.
172      * @return The value of the attribute of name 'qname'.
173      */

174     protected String JavaDoc getAttribute(String JavaDoc qname) {
175     if (_attributes == null) {
176         return EMPTYSTRING;
177     }
178     final String JavaDoc value = _attributes.getValue(qname);
179     return (value == null || value.equals(EMPTYSTRING)) ?
180         EMPTYSTRING : value;
181     }
182     
183     protected String JavaDoc getAttribute(String JavaDoc prefix, String JavaDoc localName) {
184         return getAttribute(prefix + ':' + localName);
185     }
186
187     protected boolean hasAttribute(String JavaDoc qname) {
188     return (_attributes != null && _attributes.getValue(qname) != null);
189     }
190     
191     protected void addAttribute(String JavaDoc qname, String JavaDoc value) {
192         _attributes.add(qname, value);
193     }
194
195     /**
196      * Returns a list of all attributes declared for the element represented by
197      * this syntax tree node.
198      * @return Attributes for this syntax tree node
199      */

200     protected Attributes JavaDoc getAttributes() {
201     return(_attributes);
202     }
203
204     /**
205      * Sets the prefix mapping for the namespaces that were declared in this
206      * element. This does not include all prefix mappings in scope, so one
207      * may have to check ancestor elements to get all mappings that are in
208      * in scope. The prefixes must be passed in as a Hashtable that maps
209      * namespace prefixes (String objects) to namespace URIs (also String).
210      * @param mapping The Hashtable containing the mappings.
211      */

212     protected void setPrefixMapping(Hashtable JavaDoc mapping) {
213     _prefixMapping = mapping;
214     }
215
216     /**
217      * Returns a Hashtable containing the prefix mappings that were declared
218      * for this element. This does not include all prefix mappings in scope,
219      * so one may have to check ancestor elements to get all mappings that are
220      * in in scope.
221      * @return Prefix mappings (for this element only).
222      */

223     protected Hashtable JavaDoc getPrefixMapping() {
224     return _prefixMapping;
225     }
226
227     /**
228      * Adds a single prefix mapping to this syntax tree node.
229      * @param prefix Namespace prefix.
230      * @param uri Namespace URI.
231      */

232     protected void addPrefixMapping(String JavaDoc prefix, String JavaDoc uri) {
233     if (_prefixMapping == null)
234         _prefixMapping = new Hashtable JavaDoc();
235     _prefixMapping.put(prefix, uri);
236     }
237
238     /**
239      * Returns any namespace URI that is in scope for a given prefix. This
240      * method checks namespace mappings for this element, and if necessary
241      * for ancestor elements as well (ie. if the prefix maps to an URI in this
242      * scope then you'll definately get the URI from this method).
243      * @param prefix Namespace prefix.
244      * @return Namespace URI.
245      */

246     protected String JavaDoc lookupNamespace(String JavaDoc prefix) {
247     // Initialise the output (default is 'null' for undefined)
248
String JavaDoc uri = null;
249
250     // First look up the prefix/uri mapping in our own hashtable...
251
if (_prefixMapping != null)
252         uri = (String JavaDoc)_prefixMapping.get(prefix);
253     // ... but if we can't find it there we ask our parent for the mapping
254
if ((uri == null) && (_parent != null)) {
255         uri = _parent.lookupNamespace(prefix);
256         if ((prefix == Constants.EMPTYSTRING) && (uri == null))
257         uri = Constants.EMPTYSTRING;
258     }
259     // ... and then we return whatever URI we've got.
260
return(uri);
261     }
262
263     /**
264      * Returns any namespace prefix that is mapped to a prefix in the current
265      * scope. This method checks namespace mappings for this element, and if
266      * necessary for ancestor elements as well (ie. if the URI is declared
267      * within the current scope then you'll definately get the prefix from
268      * this method). Note that this is a very slow method and consequentially
269      * it should only be used strictly when needed.
270      * @param uri Namespace URI.
271      * @return Namespace prefix.
272      */

273     protected String JavaDoc lookupPrefix(String JavaDoc uri) {
274     // Initialise the output (default is 'null' for undefined)
275
String JavaDoc prefix = null;
276
277     // First look up the prefix/uri mapping in our own hashtable...
278
if ((_prefixMapping != null) &&
279         (_prefixMapping.contains(uri))) {
280         Enumeration JavaDoc prefixes = _prefixMapping.keys();
281         while (prefixes.hasMoreElements()) {
282         prefix = (String JavaDoc)prefixes.nextElement();
283         String JavaDoc mapsTo = (String JavaDoc)_prefixMapping.get(prefix);
284         if (mapsTo.equals(uri)) return(prefix);
285         }
286     }
287     // ... but if we can't find it there we ask our parent for the mapping
288
else if (_parent != null) {
289         prefix = _parent.lookupPrefix(uri);
290         if ((uri == Constants.EMPTYSTRING) && (prefix == null))
291         prefix = Constants.EMPTYSTRING;
292     }
293     return(prefix);
294     }
295
296     /**
297      * Set this node's parser. The parser (the XSLT parser) gives this
298      * syntax tree node access to the symbol table and XPath parser.
299      * @param parser The XSLT parser.
300      */

301     protected void setParser(Parser parser) {
302     _parser = parser;
303     }
304
305     /**
306      * Returns this node's XSLT parser.
307      * @return The XSLT parser.
308      */

309     public final Parser getParser() {
310     return _parser;
311     }
312
313     /**
314      * Set this syntax tree node's parent node
315      * @param parent The parent node.
316      */

317     protected void setParent(SyntaxTreeNode parent) {
318     if (_parent == null)
319         _parent = parent;
320     }
321
322     /**
323      * Returns this syntax tree node's parent node.
324      * @return The parent syntax tree node.
325      */

326     protected final SyntaxTreeNode getParent() {
327     return _parent;
328     }
329
330     /**
331      * Returns 'true' if this syntax tree node is the Sentinal node.
332      * @return 'true' if this syntax tree node is the Sentinal node.
333      */

334     protected final boolean isDummy() {
335         return this == Dummy;
336     }
337
338     /**
339      * Get the import precedence of this element. The import precedence equals
340      * the import precedence of the stylesheet in which this element occured.
341      * @return The import precedence of this syntax tree node.
342      */

343     protected int getImportPrecedence() {
344     Stylesheet stylesheet = getStylesheet();
345     if (stylesheet == null) return Integer.MIN_VALUE;
346     return stylesheet.getImportPrecedence();
347     }
348
349     /**
350      * Get the Stylesheet node that represents the <xsl:stylesheet/> element
351      * that this node occured under.
352      * @return The Stylesheet ancestor node of this node.
353      */

354     public Stylesheet getStylesheet() {
355     if (_stylesheet == null) {
356         SyntaxTreeNode parent = this;
357         while (parent != null) {
358         if (parent instanceof Stylesheet)
359             return((Stylesheet)parent);
360         parent = parent.getParent();
361         }
362         _stylesheet = (Stylesheet)parent;
363     }
364     return(_stylesheet);
365     }
366
367     /**
368      * Get the Template node that represents the <xsl:template/> element
369      * that this node occured under. Note that this method will return 'null'
370      * for nodes that represent top-level elements.
371      * @return The Template ancestor node of this node or 'null'.
372      */

373     protected Template getTemplate() {
374     if (_template == null) {
375         SyntaxTreeNode parent = this;
376         while ((parent != null) && (!(parent instanceof Template)))
377         parent = parent.getParent();
378         _template = (Template)parent;
379     }
380     return(_template);
381     }
382
383     /**
384      * Returns a reference to the XSLTC (XSLT compiler) in use.
385      * @return XSLTC - XSLT compiler.
386      */

387     protected final XSLTC getXSLTC() {
388     return _parser.getXSLTC();
389     }
390
391     /**
392      * Returns the XSLT parser's symbol table.
393      * @return Symbol table.
394      */

395     protected final SymbolTable getSymbolTable() {
396     return (_parser == null) ? null : _parser.getSymbolTable();
397     }
398
399     /**
400      * Parse the contents of this syntax tree nodes (child nodes, XPath
401      * expressions, patterns and functions). The default behaviour is to parser
402      * the syntax tree node's children (since there are no common expressions,
403      * patterns, etc. that can be handled in this base class.
404      * @param parser reference to the XSLT parser
405      */

406     public void parseContents(Parser parser) {
407     parseChildren(parser);
408     }
409
410     /**
411      * Parse all children of this syntax tree node. This method is normally
412      * called by the parseContents() method.
413      * @param parser reference to the XSLT parser
414      */

415     protected final void parseChildren(Parser parser) {
416
417     Vector JavaDoc locals = null; // only create when needed
418

419     final int count = _contents.size();
420     for (int i=0; i<count; i++) {
421         SyntaxTreeNode child = (SyntaxTreeNode)_contents.elementAt(i);
422         parser.getSymbolTable().setCurrentNode(child);
423         child.parseContents(parser);
424         // if variable or parameter, add it to scope
425
final QName varOrParamName = updateScope(parser, child);
426         if (varOrParamName != null) {
427         if (locals == null) {
428             locals = new Vector JavaDoc(2);
429         }
430         locals.addElement(varOrParamName);
431         }
432     }
433
434     parser.getSymbolTable().setCurrentNode(this);
435
436     // after the last element, remove any locals from scope
437
if (locals != null) {
438         final int nLocals = locals.size();
439         for (int i = 0; i < nLocals; i++) {
440         parser.removeVariable((QName)locals.elementAt(i));
441         }
442     }
443     }
444    
445     /**
446      * Add a node to the current scope and return name of a variable or
447      * parameter if the node represents a variable or a parameter.
448      */

449     protected QName updateScope(Parser parser, SyntaxTreeNode node) {
450     if (node instanceof Variable) {
451         final Variable var = (Variable)node;
452         parser.addVariable(var);
453         return var.getName();
454     }
455     else if (node instanceof Param) {
456         final Param param = (Param)node;
457         parser.addParameter(param);
458         return param.getName();
459     }
460     else {
461         return null;
462     }
463     }
464
465     /**
466      * Type check the children of this node. The type check phase may add
467      * coercions (CastExpr) to the AST.
468      * @param stable The compiler/parser's symbol table
469      */

470     public abstract Type typeCheck(SymbolTable stable) throws TypeCheckError;
471
472     /**
473      * Call typeCheck() on all child syntax tree nodes.
474      * @param stable The compiler/parser's symbol table
475      */

476     protected Type typeCheckContents(SymbolTable stable) throws TypeCheckError {
477     final int n = elementCount();
478     for (int i = 0; i < n; i++) {
479         SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
480         item.typeCheck(stable);
481     }
482     return Type.Void;
483     }
484
485     /**
486      * Translate this abstract syntax tree node into JVM bytecodes.
487      * @param classGen BCEL Java class generator
488      * @param methodGen BCEL Java method generator
489      */

490     public abstract void translate(ClassGenerator classGen,
491                    MethodGenerator methodGen);
492
493     /**
494      * Call translate() on all child syntax tree nodes.
495      * @param classGen BCEL Java class generator
496      * @param methodGen BCEL Java method generator
497      */

498     protected void translateContents(ClassGenerator classGen,
499                      MethodGenerator methodGen) {
500     // Call translate() on all child nodes
501
final int n = elementCount();
502     for (int i = 0; i < n; i++) {
503         final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
504         item.translate(classGen, methodGen);
505     }
506
507     // After translation, unmap any registers for any variables/parameters
508
// that were declared in this scope. Performing this unmapping in the
509
// same AST scope as the declaration deals with the problems of
510
// references falling out-of-scope inside the for-each element.
511
// (the cause of which being 'lazy' register allocation for references)
512
for (int i = 0; i < n; i++) {
513         if( _contents.elementAt(i) instanceof VariableBase) {
514         final VariableBase var = (VariableBase)_contents.elementAt(i);
515         var.unmapRegister(methodGen);
516         }
517     }
518     }
519     
520     /**
521      * Return true if the node represents a simple RTF.
522      *
523      * A node is a simple RTF if all children only produce Text value.
524      *
525      * @param node A node
526      * @return true if the node content can be considered as a simple RTF.
527      */

528     private boolean isSimpleRTF(SyntaxTreeNode node) {
529         
530         Vector JavaDoc contents = node.getContents();
531         for (int i = 0; i < contents.size(); i++) {
532             SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
533             if (!isTextElement(item, false))
534                 return false;
535         }
536         
537         return true;
538     }
539  
540      /**
541      * Return true if the node represents an adaptive RTF.
542      *
543      * A node is an adaptive RTF if each children is a Text element
544      * or it is <xsl:call-template> or <xsl:apply-templates>.
545      *
546      * @param node A node
547      * @return true if the node content can be considered as an adaptive RTF.
548      */

549     private boolean isAdaptiveRTF(SyntaxTreeNode node) {
550         
551         Vector JavaDoc contents = node.getContents();
552         for (int i = 0; i < contents.size(); i++) {
553             SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
554             if (!isTextElement(item, true))
555                 return false;
556         }
557         
558         return true;
559     }
560    
561     /**
562      * Return true if the node only produces Text content.
563      *
564      * A node is a Text element if it is Text, xsl:value-of, xsl:number,
565      * or a combination of these nested in a control instruction (xsl:if or
566      * xsl:choose).
567      *
568      * If the doExtendedCheck flag is true, xsl:call-template and xsl:apply-templates
569      * are also considered as Text elements.
570      *
571      * @param node A node
572      * @param doExtendedCheck If this flag is true, <xsl:call-template> and
573      * <xsl:apply-templates> are also considered as Text elements.
574      *
575      * @return true if the node of Text type
576      */

577     private boolean isTextElement(SyntaxTreeNode node, boolean doExtendedCheck) {
578         if (node instanceof ValueOf || node instanceof Number JavaDoc
579             || node instanceof Text)
580         {
581             return true;
582         }
583         else if (node instanceof If) {
584             return doExtendedCheck ? isAdaptiveRTF(node) : isSimpleRTF(node);
585         }
586         else if (node instanceof Choose) {
587             Vector JavaDoc contents = node.getContents();
588             for (int i = 0; i < contents.size(); i++) {
589                 SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
590                 if (item instanceof Text ||
591                      ((item instanceof When || item instanceof Otherwise)
592                      && ((doExtendedCheck && isAdaptiveRTF(item))
593                          || (!doExtendedCheck && isSimpleRTF(item)))))
594                     continue;
595                 else
596                     return false;
597             }
598             return true;
599         }
600         else if (doExtendedCheck &&
601                   (node instanceof CallTemplate
602                    || node instanceof ApplyTemplates))
603             return true;
604         else
605             return false;
606     }
607
608     /**
609      * Utility method used by parameters and variables to store result trees
610      * @param classGen BCEL Java class generator
611      * @param methodGen BCEL Java method generator
612      */

613     protected void compileResultTree(ClassGenerator classGen,
614                      MethodGenerator methodGen)
615     {
616     final ConstantPoolGen cpg = classGen.getConstantPool();
617     final InstructionList il = methodGen.getInstructionList();
618     final Stylesheet stylesheet = classGen.getStylesheet();
619
620     boolean isSimple = isSimpleRTF(this);
621     boolean isAdaptive = false;
622     if (!isSimple) {
623         isAdaptive = isAdaptiveRTF(this);
624     }
625     
626     int rtfType = isSimple ? DOM.SIMPLE_RTF
627                            : (isAdaptive ? DOM.ADAPTIVE_RTF : DOM.TREE_RTF);
628     
629     // Save the current handler base on the stack
630
il.append(methodGen.loadHandler());
631
632     final String JavaDoc DOM_CLASS = classGen.getDOMClass();
633
634     // Create new instance of DOM class (with RTF_INITIAL_SIZE nodes)
635
//int index = cpg.addMethodref(DOM_IMPL, "<init>", "(I)V");
636
//il.append(new NEW(cpg.addClass(DOM_IMPL)));
637

638     il.append(methodGen.loadDOM());
639     int index = cpg.addInterfaceMethodref(DOM_INTF,
640                  "getResultTreeFrag",
641                  "(IIZ)" + DOM_INTF_SIG);
642     il.append(new PUSH(cpg, RTF_INITIAL_SIZE));
643     il.append(new PUSH(cpg, rtfType));
644     il.append(new PUSH(cpg, stylesheet.callsNodeset()));
645     il.append(new INVOKEINTERFACE(index,4));
646     
647     il.append(DUP);
648
649     // Overwrite old handler with DOM handler
650
index = cpg.addInterfaceMethodref(DOM_INTF,
651                  "getOutputDomBuilder",
652                  "()" + TRANSLET_OUTPUT_SIG);
653
654     il.append(new INVOKEINTERFACE(index,1));
655     il.append(DUP);
656     il.append(methodGen.storeHandler());
657
658     // Call startDocument on the new handler
659
il.append(methodGen.startDocument());
660
661     // Instantiate result tree fragment
662
translateContents(classGen, methodGen);
663
664     // Call endDocument on the new handler
665
il.append(methodGen.loadHandler());
666     il.append(methodGen.endDocument());
667
668     // Check if we need to wrap the DOMImpl object in a DOMAdapter object.
669
// DOMAdapter is not needed if the RTF is a simple RTF and the nodeset()
670
// function is not used.
671
if (stylesheet.callsNodeset()
672         && !DOM_CLASS.equals(DOM_IMPL_CLASS)) {
673         // new com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter(DOMImpl,String[]);
674
index = cpg.addMethodref(DOM_ADAPTER_CLASS,
675                      "<init>",
676                      "("+DOM_INTF_SIG+
677                      "["+STRING_SIG+
678                      "["+STRING_SIG+
679                      "[I"+
680                      "["+STRING_SIG+")V");
681         il.append(new NEW(cpg.addClass(DOM_ADAPTER_CLASS)));
682         il.append(new DUP_X1());
683         il.append(SWAP);
684
685         /*
686          * Give the DOM adapter an empty type mapping if the nodeset
687          * extension function is never called.
688          */

689         if (!stylesheet.callsNodeset()) {
690         il.append(new ICONST(0));
691         il.append(new ANEWARRAY(cpg.addClass(STRING)));
692         il.append(DUP);
693         il.append(DUP);
694         il.append(new ICONST(0));
695         il.append(new NEWARRAY(BasicType.INT));
696         il.append(SWAP);
697         il.append(new INVOKESPECIAL(index));
698         }
699         else {
700         // Push name arrays on the stack
701
il.append(ALOAD_0);
702         il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
703                        NAMES_INDEX,
704                        NAMES_INDEX_SIG)));
705         il.append(ALOAD_0);
706         il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
707                        URIS_INDEX,
708                        URIS_INDEX_SIG)));
709         il.append(ALOAD_0);
710         il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
711                        TYPES_INDEX,
712                        TYPES_INDEX_SIG)));
713         il.append(ALOAD_0);
714         il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
715                        NAMESPACE_INDEX,
716                        NAMESPACE_INDEX_SIG)));
717
718         // Initialized DOM adapter
719
il.append(new INVOKESPECIAL(index));
720
721         // Add DOM adapter to MultiDOM class by calling addDOMAdapter()
722
il.append(DUP);
723         il.append(methodGen.loadDOM());
724         il.append(new CHECKCAST(cpg.addClass(classGen.getDOMClass())));
725         il.append(SWAP);
726         index = cpg.addMethodref(MULTI_DOM_CLASS,
727                      "addDOMAdapter",
728                      "(" + DOM_ADAPTER_SIG + ")I");
729         il.append(new INVOKEVIRTUAL(index));
730         il.append(POP); // ignore mask returned by addDOMAdapter
731
}
732     }
733
734     // Restore old handler base from stack
735
il.append(SWAP);
736     il.append(methodGen.storeHandler());
737     }
738
739     /**
740      * Returns true if this expression/instruction depends on the context. By
741      * default, every expression/instruction depends on the context unless it
742      * overrides this method. Currently used to determine if result trees are
743      * compiled using procedures or little DOMs (result tree fragments).
744      * @return 'true' if this node depends on the context.
745      */

746     protected boolean contextDependent() {
747     return true;
748     }
749
750     /**
751      * Return true if any of the expressions/instructions in the contents of
752      * this node is context dependent.
753      * @return 'true' if the contents of this node is context dependent.
754      */

755     protected boolean dependentContents() {
756     final int n = elementCount();
757     for (int i = 0; i < n; i++) {
758         final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
759         if (item.contextDependent()) {
760         return true;
761         }
762     }
763     return false;
764     }
765
766     /**
767      * Adds a child node to this syntax tree node.
768      * @param element is the new child node.
769      */

770     protected final void addElement(SyntaxTreeNode element) {
771     _contents.addElement(element);
772     element.setParent(this);
773     }
774
775     /**
776      * Inserts the first child node of this syntax tree node. The existing
777      * children are shifted back one position.
778      * @param element is the new child node.
779      */

780     protected final void setFirstElement(SyntaxTreeNode element) {
781     _contents.insertElementAt(element,0);
782     element.setParent(this);
783     }
784
785     /**
786      * Removed a child node of this syntax tree node.
787      * @param element is the child node to remove.
788      */

789     protected final void removeElement(SyntaxTreeNode element) {
790     _contents.remove(element);
791     element.setParent(null);
792     }
793
794     /**
795      * Returns a Vector containing all the child nodes of this node.
796      * @return A Vector containing all the child nodes of this node.
797      */

798     protected final Vector JavaDoc getContents() {
799     return _contents;
800     }
801
802     /**
803      * Tells you if this node has any child nodes.
804      * @return 'true' if this node has any children.
805      */

806     protected final boolean hasContents() {
807     return elementCount() > 0;
808     }
809
810     /**
811      * Returns the number of children this node has.
812      * @return Number of child nodes.
813      */

814     protected final int elementCount() {
815     return _contents.size();
816     }
817
818     /**
819      * Returns an Enumeration of all child nodes of this node.
820      * @return An Enumeration of all child nodes of this node.
821      */

822     protected final Enumeration JavaDoc elements() {
823     return _contents.elements();
824     }
825
826     /**
827      * Returns a child node at a given position.
828      * @param pos The child node's position.
829      * @return The child node.
830      */

831     protected final Object JavaDoc elementAt(int pos) {
832     return _contents.elementAt(pos);
833     }
834
835     /**
836      * Returns this element's last child
837      * @return The child node.
838      */

839     protected final SyntaxTreeNode lastChild() {
840     if (_contents.size() == 0) return null;
841     return (SyntaxTreeNode)_contents.lastElement();
842     }
843
844     /**
845      * Displays the contents of this syntax tree node (to stdout).
846      * This method is intended for debugging _only_, and should be overridden
847      * by all syntax tree node implementations.
848      * @param indent Indentation level for syntax tree levels.
849      */

850     public void display(int indent) {
851     displayContents(indent);
852     }
853
854     /**
855      * Displays the contents of this syntax tree node (to stdout).
856      * This method is intended for debugging _only_ !!!
857      * @param indent Indentation level for syntax tree levels.
858      */

859     protected void displayContents(int indent) {
860     final int n = elementCount();
861     for (int i = 0; i < n; i++) {
862         SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
863         item.display(indent);
864     }
865     }
866
867     /**
868      * Set the indentation level for debug output.
869      * @param indent Indentation level for syntax tree levels.
870      */

871     protected final void indent(int indent) {
872     System.out.print(new String JavaDoc(_spaces, 0, indent));
873     }
874
875     /**
876      * Report an error to the parser.
877      * @param element The element in which the error occured (normally 'this'
878      * but it could also be an expression/pattern/etc.)
879      * @param parser The XSLT parser to report the error to.
880      * @param error The error code (from util/ErrorMsg).
881      * @param message Any additional error message.
882      */

883     protected void reportError(SyntaxTreeNode element, Parser parser,
884                    String JavaDoc errorCode, String JavaDoc message) {
885     final ErrorMsg error = new ErrorMsg(errorCode, message, element);
886         parser.reportError(Constants.ERROR, error);
887     }
888
889     /**
890      * Report a recoverable error to the parser.
891      * @param element The element in which the error occured (normally 'this'
892      * but it could also be an expression/pattern/etc.)
893      * @param parser The XSLT parser to report the error to.
894      * @param error The error code (from util/ErrorMsg).
895      * @param message Any additional error message.
896      */

897     protected void reportWarning(SyntaxTreeNode element, Parser parser,
898                   String JavaDoc errorCode, String JavaDoc message) {
899     final ErrorMsg error = new ErrorMsg(errorCode, message, element);
900         parser.reportError(Constants.WARNING, error);
901     }
902
903 }
904
Popular Tags