KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > 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.29 2004/02/16 22:25:10 minchau Exp $
18  */

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

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

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

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

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

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

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

116     protected final void setLineNumber(int line) {
117     _line = line;
118     }
119
120     /**
121      * Get the source file line number for this element
122      * @return The source file line number.
123      */

124     public final int getLineNumber() {
125     return _line;
126     }
127
128     /**
129      * Set the QName for the syntax tree node.
130      * @param qname The QName for the syntax tree node
131      */

132     protected void setQName(QName qname) {
133     _qname = qname;
134     }
135
136     /**
137      * Set the QName for the SyntaxTreeNode
138      * @param uri The element's namespace URI
139      * @param prefix The element's namespace prefix
140      * @param local The element's local name
141      */

142     protected void setQName(String JavaDoc uri, String JavaDoc prefix, String JavaDoc localname) {
143     _qname = new QName(uri, prefix, localname);
144     }
145
146     /**
147      * Set the QName for the SyntaxTreeNode
148      * @param qname The QName for the syntax tree node
149      */

150     protected QName getQName() {
151     return(_qname);
152     }
153
154     /**
155      * Set the attributes for this SyntaxTreeNode.
156      * @param attributes Attributes for the element. Must be passed in as an
157      * implementation of org.xml.sax.Attributes.
158      */

159     protected void setAttributes(Attributes JavaDoc attributes) {
160     _attributes = attributes;
161     }
162
163     /**
164      * Returns a value for an attribute from the source element.
165      * @param qname The QName of the attribute to return.
166      * @return The value of the attribute of name 'qname'.
167      */

168     protected String JavaDoc getAttribute(String JavaDoc qname) {
169     if (_attributes == null) {
170         return EMPTYSTRING;
171     }
172     final String JavaDoc value = _attributes.getValue(qname);
173     return (value == null || value.equals(EMPTYSTRING)) ?
174         EMPTYSTRING : value;
175     }
176
177     protected boolean hasAttribute(String JavaDoc qname) {
178     return (_attributes != null && _attributes.getValue(qname) != null);
179     }
180
181     /**
182      * Returns a list of all attributes declared for the element represented by
183      * this syntax tree node.
184      * @return Attributes for this syntax tree node
185      */

186     protected Attributes JavaDoc getAttributes() {
187     return(_attributes);
188     }
189
190     /**
191      * Sets the prefix mapping for the namespaces that were declared in this
192      * element. This does not include all prefix mappings in scope, so one
193      * may have to check ancestor elements to get all mappings that are in
194      * in scope. The prefixes must be passed in as a Hashtable that maps
195      * namespace prefixes (String objects) to namespace URIs (also String).
196      * @param mapping The Hashtable containing the mappings.
197      */

198     protected void setPrefixMapping(Hashtable JavaDoc mapping) {
199     _prefixMapping = mapping;
200     }
201
202     /**
203      * Returns a Hashtable containing the prefix mappings that were declared
204      * for this element. This does not include all prefix mappings in scope,
205      * so one may have to check ancestor elements to get all mappings that are
206      * in in scope.
207      * @return Prefix mappings (for this element only).
208      */

209     protected Hashtable JavaDoc getPrefixMapping() {
210     return _prefixMapping;
211     }
212
213     /**
214      * Adds a single prefix mapping to this syntax tree node.
215      * @param prefix Namespace prefix.
216      * @param uri Namespace URI.
217      */

218     protected void addPrefixMapping(String JavaDoc prefix, String JavaDoc uri) {
219     if (_prefixMapping == null)
220         _prefixMapping = new Hashtable JavaDoc();
221     _prefixMapping.put(prefix, uri);
222     }
223
224     /**
225      * Returns any namespace URI that is in scope for a given prefix. This
226      * method checks namespace mappings for this element, and if necessary
227      * for ancestor elements as well (ie. if the prefix maps to an URI in this
228      * scope then you'll definately get the URI from this method).
229      * @param prefix Namespace prefix.
230      * @return Namespace URI.
231      */

232     protected String JavaDoc lookupNamespace(String JavaDoc prefix) {
233     // Initialise the output (default is 'null' for undefined)
234
String JavaDoc uri = null;
235
236     // First look up the prefix/uri mapping in our own hashtable...
237
if (_prefixMapping != null)
238         uri = (String JavaDoc)_prefixMapping.get(prefix);
239     // ... but if we can't find it there we ask our parent for the mapping
240
if ((uri == null) && (_parent != null)) {
241         uri = _parent.lookupNamespace(prefix);
242         if ((prefix == Constants.EMPTYSTRING) && (uri == null))
243         uri = Constants.EMPTYSTRING;
244     }
245     // ... and then we return whatever URI we've got.
246
return(uri);
247     }
248
249     /**
250      * Returns any namespace prefix that is mapped to a prefix in the current
251      * scope. This method checks namespace mappings for this element, and if
252      * necessary for ancestor elements as well (ie. if the URI is declared
253      * within the current scope then you'll definately get the prefix from
254      * this method). Note that this is a very slow method and consequentially
255      * it should only be used strictly when needed.
256      * @param uri Namespace URI.
257      * @return Namespace prefix.
258      */

259     protected String JavaDoc lookupPrefix(String JavaDoc uri) {
260     // Initialise the output (default is 'null' for undefined)
261
String JavaDoc prefix = null;
262
263     // First look up the prefix/uri mapping in our own hashtable...
264
if ((_prefixMapping != null) &&
265         (_prefixMapping.contains(uri))) {
266         Enumeration JavaDoc prefixes = _prefixMapping.keys();
267         while (prefixes.hasMoreElements()) {
268         prefix = (String JavaDoc)prefixes.nextElement();
269         String JavaDoc mapsTo = (String JavaDoc)_prefixMapping.get(prefix);
270         if (mapsTo.equals(uri)) return(prefix);
271         }
272     }
273     // ... but if we can't find it there we ask our parent for the mapping
274
else if (_parent != null) {
275         prefix = _parent.lookupPrefix(uri);
276         if ((uri == Constants.EMPTYSTRING) && (prefix == null))
277         prefix = Constants.EMPTYSTRING;
278     }
279     return(prefix);
280     }
281
282     /**
283      * Set this node's parser. The parser (the XSLT parser) gives this
284      * syntax tree node access to the symbol table and XPath parser.
285      * @param parser The XSLT parser.
286      */

287     protected void setParser(Parser parser) {
288     _parser = parser;
289     }
290
291     /**
292      * Returns this node's XSLT parser.
293      * @return The XSLT parser.
294      */

295     public final Parser getParser() {
296     return _parser;
297     }
298
299     /**
300      * Set this syntax tree node's parent node
301      * @param parent The parent node.
302      */

303     protected void setParent(SyntaxTreeNode parent) {
304     if (_parent == null)
305         _parent = parent;
306     }
307
308     /**
309      * Returns this syntax tree node's parent node.
310      * @return The parent syntax tree node.
311      */

312     protected final SyntaxTreeNode getParent() {
313     return _parent;
314     }
315
316     /**
317      * Returns 'true' if this syntax tree node is the Sentinal node.
318      * @return 'true' if this syntax tree node is the Sentinal node.
319      */

320     protected final boolean isDummy() {
321         return this == Dummy;
322     }
323
324     /**
325      * Get the import precedence of this element. The import precedence equals
326      * the import precedence of the stylesheet in which this element occured.
327      * @return The import precedence of this syntax tree node.
328      */

329     protected int getImportPrecedence() {
330     Stylesheet stylesheet = getStylesheet();
331     if (stylesheet == null) return Integer.MIN_VALUE;
332     return stylesheet.getImportPrecedence();
333     }
334
335     /**
336      * Get the Stylesheet node that represents the <xsl:stylesheet/> element
337      * that this node occured under.
338      * @return The Stylesheet ancestor node of this node.
339      */

340     public Stylesheet getStylesheet() {
341     if (_stylesheet == null) {
342         SyntaxTreeNode parent = this;
343         while (parent != null) {
344         if (parent instanceof Stylesheet)
345             return((Stylesheet)parent);
346         parent = parent.getParent();
347         }
348         _stylesheet = (Stylesheet)parent;
349     }
350     return(_stylesheet);
351     }
352
353     /**
354      * Get the Template node that represents the <xsl:template/> element
355      * that this node occured under. Note that this method will return 'null'
356      * for nodes that represent top-level elements.
357      * @return The Template ancestor node of this node or 'null'.
358      */

359     protected Template getTemplate() {
360     if (_template == null) {
361         SyntaxTreeNode parent = this;
362         while ((parent != null) && (!(parent instanceof Template)))
363         parent = parent.getParent();
364         _template = (Template)parent;
365     }
366     return(_template);
367     }
368
369     /**
370      * Returns a reference to the XSLTC (XSLT compiler) in use.
371      * @return XSLTC - XSLT compiler.
372      */

373     protected final XSLTC getXSLTC() {
374     return _parser.getXSLTC();
375     }
376
377     /**
378      * Returns the XSLT parser's symbol table.
379      * @return Symbol table.
380      */

381     protected final SymbolTable getSymbolTable() {
382     return (_parser == null) ? null : _parser.getSymbolTable();
383     }
384
385     /**
386      * Parse the contents of this syntax tree nodes (child nodes, XPath
387      * expressions, patterns and functions). The default behaviour is to parser
388      * the syntax tree node's children (since there are no common expressions,
389      * patterns, etc. that can be handled in this base class.
390      * @param parser reference to the XSLT parser
391      */

392     public void parseContents(Parser parser) {
393     parseChildren(parser);
394     }
395
396     /**
397      * Parse all children of this syntax tree node. This method is normally
398      * called by the parseContents() method.
399      * @param parser reference to the XSLT parser
400      */

401     protected final void parseChildren(Parser parser) {
402
403     Vector JavaDoc locals = null; // only create when needed
404

405     final int count = _contents.size();
406     for (int i=0; i<count; i++) {
407         SyntaxTreeNode child = (SyntaxTreeNode)_contents.elementAt(i);
408         parser.getSymbolTable().setCurrentNode(child);
409         child.parseContents(parser);
410         // if variable or parameter, add it to scope
411
final QName varOrParamName = updateScope(parser, child);
412         if (varOrParamName != null) {
413         if (locals == null) {
414             locals = new Vector JavaDoc(2);
415         }
416         locals.addElement(varOrParamName);
417         }
418     }
419
420     parser.getSymbolTable().setCurrentNode(this);
421
422     // after the last element, remove any locals from scope
423
if (locals != null) {
424         final int nLocals = locals.size();
425         for (int i = 0; i < nLocals; i++) {
426         parser.removeVariable((QName)locals.elementAt(i));
427         }
428     }
429     }
430    
431     /**
432      * Add a node to the current scope and return name of a variable or
433      * parameter if the node represents a variable or a parameter.
434      */

435     protected QName updateScope(Parser parser, SyntaxTreeNode node) {
436     if (node instanceof Variable) {
437         final Variable var = (Variable)node;
438         parser.addVariable(var);
439         return var.getName();
440     }
441     else if (node instanceof Param) {
442         final Param param = (Param)node;
443         parser.addParameter(param);
444         return param.getName();
445     }
446     else {
447         return null;
448     }
449     }
450
451     /**
452      * Type check the children of this node. The type check phase may add
453      * coercions (CastExpr) to the AST.
454      * @param stable The compiler/parser's symbol table
455      */

456     public abstract Type typeCheck(SymbolTable stable) throws TypeCheckError;
457
458     /**
459      * Call typeCheck() on all child syntax tree nodes.
460      * @param stable The compiler/parser's symbol table
461      */

462     protected Type typeCheckContents(SymbolTable stable) throws TypeCheckError {
463     final int n = elementCount();
464     for (int i = 0; i < n; i++) {
465         SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
466         item.typeCheck(stable);
467     }
468     return Type.Void;
469     }
470
471     /**
472      * Translate this abstract syntax tree node into JVM bytecodes.
473      * @param classGen BCEL Java class generator
474      * @param methodGen BCEL Java method generator
475      */

476     public abstract void translate(ClassGenerator classGen,
477                    MethodGenerator methodGen);
478
479     /**
480      * Call translate() on all child syntax tree nodes.
481      * @param classGen BCEL Java class generator
482      * @param methodGen BCEL Java method generator
483      */

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

514     private boolean isSimpleRTF(SyntaxTreeNode node) {
515         
516         Vector JavaDoc contents = node.getContents();
517         for (int i = 0; i < contents.size(); i++) {
518             SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
519             if (!isTextElement(item, false))
520                 return false;
521         }
522         
523         return true;
524     }
525  
526      /**
527      * Return true if the node represents an adaptive RTF.
528      *
529      * A node is an adaptive RTF if each children is a Text element
530      * or it is <xsl:call-template> or <xsl:apply-templates>.
531      *
532      * @param node A node
533      * @return true if the node content can be considered as an adaptive RTF.
534      */

535     private boolean isAdaptiveRTF(SyntaxTreeNode node) {
536         
537         Vector JavaDoc contents = node.getContents();
538         for (int i = 0; i < contents.size(); i++) {
539             SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
540             if (!isTextElement(item, true))
541                 return false;
542         }
543         
544         return true;
545     }
546    
547     /**
548      * Return true if the node only produces Text content.
549      *
550      * A node is a Text element if it is Text, xsl:value-of, xsl:number,
551      * or a combination of these nested in a control instruction (xsl:if or
552      * xsl:choose).
553      *
554      * If the doExtendedCheck flag is true, xsl:call-template and xsl:apply-templates
555      * are also considered as Text elements.
556      *
557      * @param node A node
558      * @param doExtendedCheck If this flag is true, <xsl:call-template> and
559      * <xsl:apply-templates> are also considered as Text elements.
560      *
561      * @return true if the node of Text type
562      */

563     private boolean isTextElement(SyntaxTreeNode node, boolean doExtendedCheck) {
564         if (node instanceof ValueOf || node instanceof Number JavaDoc
565             || node instanceof Text)
566         {
567             return true;
568         }
569         else if (node instanceof If) {
570             return doExtendedCheck ? isAdaptiveRTF(node) : isSimpleRTF(node);
571         }
572         else if (node instanceof Choose) {
573             Vector JavaDoc contents = node.getContents();
574             for (int i = 0; i < contents.size(); i++) {
575                 SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
576                 if (item instanceof Text ||
577                      ((item instanceof When || item instanceof Otherwise)
578                      && ((doExtendedCheck && isAdaptiveRTF(item))
579                          || (!doExtendedCheck && isSimpleRTF(item)))))
580                     continue;
581                 else
582                     return false;
583             }
584             return true;
585         }
586         else if (doExtendedCheck &&
587                   (node instanceof CallTemplate
588                    || node instanceof ApplyTemplates))
589             return true;
590         else
591             return false;
592     }
593
594     /**
595      * Utility method used by parameters and variables to store result trees
596      * @param classGen BCEL Java class generator
597      * @param methodGen BCEL Java method generator
598      */

599     protected void compileResultTree(ClassGenerator classGen,
600                      MethodGenerator methodGen)
601     {
602     final ConstantPoolGen cpg = classGen.getConstantPool();
603     final InstructionList il = methodGen.getInstructionList();
604     final Stylesheet stylesheet = classGen.getStylesheet();
605
606     boolean isSimple = isSimpleRTF(this);
607     boolean isAdaptive = false;
608     if (!isSimple) {
609         isAdaptive = isAdaptiveRTF(this);
610     }
611     
612     int rtfType = isSimple ? DOM.SIMPLE_RTF
613                            : (isAdaptive ? DOM.ADAPTIVE_RTF : DOM.TREE_RTF);
614     
615     // Save the current handler base on the stack
616
il.append(methodGen.loadHandler());
617
618     final String JavaDoc DOM_CLASS = classGen.getDOMClass();
619
620     // Create new instance of DOM class (with RTF_INITIAL_SIZE nodes)
621
//int index = cpg.addMethodref(DOM_IMPL, "<init>", "(I)V");
622
//il.append(new NEW(cpg.addClass(DOM_IMPL)));
623

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

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

732     protected boolean contextDependent() {
733     return true;
734     }
735
736     /**
737      * Return true if any of the expressions/instructions in the contents of
738      * this node is context dependent.
739      * @return 'true' if the contents of this node is context dependent.
740      */

741     protected boolean dependentContents() {
742     final int n = elementCount();
743     for (int i = 0; i < n; i++) {
744         final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
745         if (item.contextDependent()) {
746         return true;
747         }
748     }
749     return false;
750     }
751
752     /**
753      * Adds a child node to this syntax tree node.
754      * @param element is the new child node.
755      */

756     protected final void addElement(SyntaxTreeNode element) {
757     _contents.addElement(element);
758     element.setParent(this);
759     }
760
761     /**
762      * Inserts the first child node of this syntax tree node. The existing
763      * children are shifted back one position.
764      * @param element is the new child node.
765      */

766     protected final void setFirstElement(SyntaxTreeNode element) {
767     _contents.insertElementAt(element,0);
768     element.setParent(this);
769     }
770
771     /**
772      * Removed a child node of this syntax tree node.
773      * @param element is the child node to remove.
774      */

775     protected final void removeElement(SyntaxTreeNode element) {
776     _contents.remove(element);
777     element.setParent(null);
778     }
779
780     /**
781      * Returns a Vector containing all the child nodes of this node.
782      * @return A Vector containing all the child nodes of this node.
783      */

784     protected final Vector JavaDoc getContents() {
785     return _contents;
786     }
787
788     /**
789      * Tells you if this node has any child nodes.
790      * @return 'true' if this node has any children.
791      */

792     protected final boolean hasContents() {
793     return elementCount() > 0;
794     }
795
796     /**
797      * Returns the number of children this node has.
798      * @return Number of child nodes.
799      */

800     protected final int elementCount() {
801     return _contents.size();
802     }
803
804     /**
805      * Returns an Enumeration of all child nodes of this node.
806      * @return An Enumeration of all child nodes of this node.
807      */

808     protected final Enumeration JavaDoc elements() {
809     return _contents.elements();
810     }
811
812     /**
813      * Returns a child node at a given position.
814      * @param pos The child node's position.
815      * @return The child node.
816      */

817     protected final Object JavaDoc elementAt(int pos) {
818     return _contents.elementAt(pos);
819     }
820
821     /**
822      * Returns this element's last child
823      * @return The child node.
824      */

825     protected final SyntaxTreeNode lastChild() {
826     if (_contents.size() == 0) return null;
827     return (SyntaxTreeNode)_contents.lastElement();
828     }
829
830     /**
831      * Displays the contents of this syntax tree node (to stdout).
832      * This method is intended for debugging _only_, and should be overridden
833      * by all syntax tree node implementations.
834      * @param indent Indentation level for syntax tree levels.
835      */

836     public void display(int indent) {
837     displayContents(indent);
838     }
839
840     /**
841      * Displays the contents of this syntax tree node (to stdout).
842      * This method is intended for debugging _only_ !!!
843      * @param indent Indentation level for syntax tree levels.
844      */

845     protected void displayContents(int indent) {
846     final int n = elementCount();
847     for (int i = 0; i < n; i++) {
848         SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
849         item.display(indent);
850     }
851     }
852
853     /**
854      * Set the indentation level for debug output.
855      * @param indent Indentation level for syntax tree levels.
856      */

857     protected final void indent(int indent) {
858     System.out.print(new String JavaDoc(_spaces, 0, indent));
859     }
860
861     /**
862      * Report an error to the parser.
863      * @param element The element in which the error occured (normally 'this'
864      * but it could also be an expression/pattern/etc.)
865      * @param parser The XSLT parser to report the error to.
866      * @param error The error code (from util/ErrorMsg).
867      * @param message Any additional error message.
868      */

869     protected void reportError(SyntaxTreeNode element, Parser parser,
870                    String JavaDoc errorCode, String JavaDoc message) {
871     final ErrorMsg error = new ErrorMsg(errorCode, message, element);
872         parser.reportError(Constants.ERROR, error);
873     }
874
875     /**
876      * Report a recoverable 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 reportWarning(SyntaxTreeNode element, Parser parser,
884                   String JavaDoc errorCode, String JavaDoc message) {
885     final ErrorMsg error = new ErrorMsg(errorCode, message, element);
886         parser.reportError(Constants.WARNING, error);
887     }
888
889 }
890
Popular Tags