KickJava   Java API By Example, From Geeks To Geeks.

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


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: Stylesheet.java,v 1.1.2.2 2006/10/05 17:10:34 spericas Exp $
18  */

19
20 package com.sun.org.apache.xalan.internal.xsltc.compiler;
21
22 import java.net.URL JavaDoc;
23 import java.net.MalformedURLException JavaDoc;
24
25 import java.util.Vector JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.Hashtable JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Properties JavaDoc;
30 import java.util.StringTokenizer JavaDoc;
31
32 import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
33 import com.sun.org.apache.bcel.internal.generic.ANEWARRAY;
34 import com.sun.org.apache.bcel.internal.generic.BasicType;
35 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
36 import com.sun.org.apache.bcel.internal.generic.FieldGen;
37 import com.sun.org.apache.bcel.internal.generic.GETFIELD;
38 import com.sun.org.apache.bcel.internal.generic.GETSTATIC;
39 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
40 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
41 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
42 import com.sun.org.apache.bcel.internal.generic.ISTORE;
43 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
44 import com.sun.org.apache.bcel.internal.generic.InstructionList;
45 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
46 import com.sun.org.apache.bcel.internal.generic.NEW;
47 import com.sun.org.apache.bcel.internal.generic.NEWARRAY;
48 import com.sun.org.apache.bcel.internal.generic.PUSH;
49 import com.sun.org.apache.bcel.internal.generic.PUTFIELD;
50 import com.sun.org.apache.bcel.internal.generic.PUTSTATIC;
51 import com.sun.org.apache.bcel.internal.generic.TargetLostException;
52 import com.sun.org.apache.bcel.internal.util.InstructionFinder;
53 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
54 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
55 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
56 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
57 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
58 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
59 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
60 import com.sun.org.apache.xml.internal.dtm.DTM;
61
62 /**
63  * @author Jacek Ambroziak
64  * @author Santiago Pericas-Geertsen
65  * @author Morten Jorgensen
66  */

67 public final class Stylesheet extends SyntaxTreeNode {
68
69     /**
70      * XSLT version defined in the stylesheet.
71      */

72     private String JavaDoc _version;
73     
74     /**
75      * Internal name of this stylesheet used as a key into the symbol table.
76      */

77     private QName _name;
78     
79     /**
80      * A URI that represents the system ID for this stylesheet.
81      */

82     private String JavaDoc _systemId;
83     
84     /**
85      * A reference to the parent stylesheet or null if topmost.
86      */

87     private Stylesheet _parentStylesheet;
88         
89     /**
90      * Contains global variables and parameters defined in the stylesheet.
91      */

92     private Vector JavaDoc _globals = new Vector JavaDoc();
93
94     /**
95      * Used to cache the result returned by <code>hasLocalParams()</code>.
96      */

97     private Boolean JavaDoc _hasLocalParams = null;
98
99     /**
100      * The name of the class being generated.
101      */

102     private String JavaDoc _className;
103     
104     /**
105       * Contains all templates defined in this stylesheet
106       */

107     private final Vector JavaDoc _templates = new Vector JavaDoc();
108     
109     /**
110      * Used to cache result of <code>getAllValidTemplates()</code>. Only
111      * set in top-level stylesheets that include/import other stylesheets.
112      */

113     private Vector JavaDoc _allValidTemplates = null;
114
115     /**
116      * Counter to generate unique mode suffixes.
117      */

118     private int _nextModeSerial = 1;
119     
120     /**
121      * Mapping between mode names and Mode instances.
122      */

123     private final Hashtable JavaDoc _modes = new Hashtable JavaDoc();
124     
125     /**
126      * A reference to the default Mode object.
127      */

128     private Mode _defaultMode;
129
130     /**
131      * Mapping between extension URIs and their prefixes.
132      */

133     private final Hashtable JavaDoc _extensions = new Hashtable JavaDoc();
134
135     /**
136      * Reference to the stylesheet from which this stylesheet was
137      * imported (if any).
138      */

139     public Stylesheet _importedFrom = null;
140     
141     /**
142      * Reference to the stylesheet from which this stylesheet was
143      * included (if any).
144      */

145     public Stylesheet _includedFrom = null;
146     
147     /**
148      * Array of all the stylesheets imported or included from this one.
149      */

150     private Vector JavaDoc _includedStylesheets = null;
151     
152     /**
153      * Import precendence for this stylesheet.
154      */

155     private int _importPrecedence = 1;
156     
157     /**
158      * Minimum precendence of any descendant stylesheet by inclusion or
159      * importation.
160      */

161     private int _minimumDescendantPrecedence = -1;
162     
163     /**
164      * Mapping between key names and Key objects (needed by Key/IdPattern).
165      */

166     private Hashtable JavaDoc _keys = new Hashtable JavaDoc();
167
168     /**
169      * A reference to the SourceLoader set by the user (a URIResolver
170      * if the JAXP API is being used).
171      */

172     private SourceLoader _loader = null;
173
174     /**
175      * Flag indicating if format-number() is called.
176      */

177     private boolean _numberFormattingUsed = false;
178
179     /**
180      * Flag indicating if this is a simplified stylesheets. A template
181      * matching on "/" must be added in this case.
182      */

183     private boolean _simplified = false;
184
185     /**
186      * Flag indicating if multi-document support is needed.
187      */

188     private boolean _multiDocument = false;
189     
190     /**
191      * Flag indicating if nodset() is called.
192      */

193     private boolean _callsNodeset = false;
194
195     /**
196      * Flag indicating if id() is called.
197      */

198     private boolean _hasIdCall = false;
199     
200     /**
201      * Set to true to enable template inlining optimization.
202      */

203     private boolean _templateInlining = true;
204
205     /**
206      * A reference to the last xsl:output object found in the styleshet.
207      */

208     private Output _lastOutputElement = null;
209     
210     /**
211      * Output properties for this stylesheet.
212      */

213     private Properties JavaDoc _outputProperties = null;
214     
215     /**
216      * Output method for this stylesheet (must be set to one of
217      * the constants defined below).
218      */

219     private int _outputMethod = UNKNOWN_OUTPUT;
220
221     // Output method constants
222
public static final int UNKNOWN_OUTPUT = 0;
223     public static final int XML_OUTPUT = 1;
224     public static final int HTML_OUTPUT = 2;
225     public static final int TEXT_OUTPUT = 3;
226     
227     /**
228      * Return the output method
229      */

230     public int getOutputMethod() {
231         return _outputMethod;
232     }
233     
234     /**
235      * Check and set the output method
236      */

237     private void checkOutputMethod() {
238         if (_lastOutputElement != null) {
239             String JavaDoc method = _lastOutputElement.getOutputMethod();
240             if (method != null) {
241                 if (method.equals("xml"))
242                     _outputMethod = XML_OUTPUT;
243                 else if (method.equals("html"))
244                     _outputMethod = HTML_OUTPUT;
245                 else if (method.equals("text"))
246                     _outputMethod = TEXT_OUTPUT;
247             }
248         }
249     }
250
251     public boolean getTemplateInlining() {
252         return _templateInlining;
253     }
254
255     public void setTemplateInlining(boolean flag) {
256         _templateInlining = flag;
257     }
258
259     public boolean isSimplified() {
260         return(_simplified);
261     }
262
263     public void setSimplified() {
264         _simplified = true;
265     }
266     
267     public void setHasIdCall(boolean flag) {
268         _hasIdCall = flag;
269     }
270     
271     public void setOutputProperty(String JavaDoc key, String JavaDoc value) {
272         if (_outputProperties == null) {
273             _outputProperties = new Properties JavaDoc();
274         }
275         _outputProperties.setProperty(key, value);
276     }
277
278     public void setOutputProperties(Properties JavaDoc props) {
279         _outputProperties = props;
280     }
281
282     public Properties JavaDoc getOutputProperties() {
283         return _outputProperties;
284     }
285
286     public Output getLastOutputElement() {
287         return _lastOutputElement;
288     }
289     
290     public void setMultiDocument(boolean flag) {
291         _multiDocument = flag;
292     }
293
294     public boolean isMultiDocument() {
295         return _multiDocument;
296     }
297
298     public void setCallsNodeset(boolean flag) {
299         if (flag) setMultiDocument(flag);
300         _callsNodeset = flag;
301     }
302
303     public boolean callsNodeset() {
304         return _callsNodeset;
305     }
306
307     public void numberFormattingUsed() {
308         _numberFormattingUsed = true;
309         /*
310          * Fix for bug 23046, if the stylesheet is included, set the
311          * numberFormattingUsed flag to the parent stylesheet too.
312          * AbstractTranslet.addDecimalFormat() will be inlined once for the
313          * outer most stylesheet.
314          */

315         Stylesheet parent = getParentStylesheet();
316         if (null != parent) parent.numberFormattingUsed();
317     }
318
319     public void setImportPrecedence(final int precedence) {
320         // Set import precedence for this stylesheet
321
_importPrecedence = precedence;
322
323         // Set import precedence for all included stylesheets
324
final Enumeration JavaDoc elements = elements();
325         while (elements.hasMoreElements()) {
326             SyntaxTreeNode child = (SyntaxTreeNode)elements.nextElement();
327             if (child instanceof Include) {
328                 Stylesheet included = ((Include)child).getIncludedStylesheet();
329                 if (included != null && included._includedFrom == this) {
330                     included.setImportPrecedence(precedence);
331                 }
332             }
333         }
334
335         // Set import precedence for the stylesheet that imported this one
336
if (_importedFrom != null) {
337             if (_importedFrom.getImportPrecedence() < precedence) {
338                 final Parser parser = getParser();
339                 final int nextPrecedence = parser.getNextImportPrecedence();
340                 _importedFrom.setImportPrecedence(nextPrecedence);
341             }
342         }
343         // Set import precedence for the stylesheet that included this one
344
else if (_includedFrom != null) {
345             if (_includedFrom.getImportPrecedence() != precedence)
346                 _includedFrom.setImportPrecedence(precedence);
347         }
348     }
349     
350     public int getImportPrecedence() {
351         return _importPrecedence;
352     }
353
354     /**
355      * Get the minimum of the precedence of this stylesheet, any stylesheet
356      * imported by this stylesheet and any include/import descendant of this
357      * stylesheet.
358      */

359     public int getMinimumDescendantPrecedence() {
360         if (_minimumDescendantPrecedence == -1) {
361             // Start with precedence of current stylesheet as a basis.
362
int min = getImportPrecedence();
363
364             // Recursively examine all imported/included stylesheets.
365
final int inclImpCount = (_includedStylesheets != null)
366                                           ? _includedStylesheets.size()
367                                           : 0;
368
369             for (int i = 0; i < inclImpCount; i++) {
370                 int prec = ((Stylesheet)_includedStylesheets.elementAt(i))
371                                               .getMinimumDescendantPrecedence();
372
373                 if (prec < min) {
374                     min = prec;
375                 }
376             }
377
378             _minimumDescendantPrecedence = min;
379         }
380         return _minimumDescendantPrecedence;
381     }
382     
383     public boolean checkForLoop(String JavaDoc systemId) {
384         // Return true if this stylesheet includes/imports itself
385
if (_systemId != null && _systemId.equals(systemId)) {
386             return true;
387         }
388         // Then check with any stylesheets that included/imported this one
389
if (_parentStylesheet != null)
390             return _parentStylesheet.checkForLoop(systemId);
391         // Otherwise OK
392
return false;
393     }
394     
395     public void setParser(Parser parser) {
396         super.setParser(parser);
397         _name = makeStylesheetName("__stylesheet_");
398     }
399     
400     public void setParentStylesheet(Stylesheet parent) {
401         _parentStylesheet = parent;
402     }
403     
404     public Stylesheet getParentStylesheet() {
405         return _parentStylesheet;
406     }
407
408     public void setImportingStylesheet(Stylesheet parent) {
409         _importedFrom = parent;
410         parent.addIncludedStylesheet(this);
411     }
412
413     public void setIncludingStylesheet(Stylesheet parent) {
414         _includedFrom = parent;
415         parent.addIncludedStylesheet(this);
416     }
417
418     public void addIncludedStylesheet(Stylesheet child) {
419         if (_includedStylesheets == null) {
420             _includedStylesheets = new Vector JavaDoc();
421         }
422         _includedStylesheets.addElement(child);
423     }
424
425     public void setSystemId(String JavaDoc systemId) {
426         if (systemId != null) {
427             _systemId = SystemIDResolver.getAbsoluteURI(systemId);
428         }
429     }
430     
431     public String JavaDoc getSystemId() {
432         return _systemId;
433     }
434
435     public void setSourceLoader(SourceLoader loader) {
436         _loader = loader;
437     }
438     
439     public SourceLoader getSourceLoader() {
440         return _loader;
441     }
442
443     private QName makeStylesheetName(String JavaDoc prefix) {
444         return getParser().getQName(prefix+getXSLTC().nextStylesheetSerial());
445     }
446
447     /**
448      * Returns true if this stylesheet has global vars or params.
449      */

450     public boolean hasGlobals() {
451         return _globals.size() > 0;
452     }
453
454     /**
455      * Returns true if at least one template in the stylesheet has params
456      * defined. Uses the variable <code>_hasLocalParams</code> to cache the
457      * result.
458      */

459     public boolean hasLocalParams() {
460         if (_hasLocalParams == null) {
461             Vector JavaDoc templates = getAllValidTemplates();
462             final int n = templates.size();
463             for (int i = 0; i < n; i++) {
464                 final Template template = (Template)templates.elementAt(i);
465                 if (template.hasParams()) {
466                     _hasLocalParams = new Boolean JavaDoc(true);
467                     return true;
468                 }
469             }
470             _hasLocalParams = new Boolean JavaDoc(false);
471             return false;
472         }
473         else {
474             return _hasLocalParams.booleanValue();
475         }
476     }
477
478     /**
479      * Adds a single prefix mapping to this syntax tree node.
480      * @param prefix Namespace prefix.
481      * @param uri Namespace URI.
482      */

483     protected void addPrefixMapping(String JavaDoc prefix, String JavaDoc uri) {
484         if (prefix.equals(EMPTYSTRING) && uri.equals(XHTML_URI)) return;
485         super.addPrefixMapping(prefix, uri);
486     }
487
488     /**
489      * Store extension URIs
490      */

491     private void extensionURI(String JavaDoc prefixes, SymbolTable stable) {
492         if (prefixes != null) {
493             StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(prefixes);
494             while (tokens.hasMoreTokens()) {
495                 final String JavaDoc prefix = tokens.nextToken();
496                 final String JavaDoc uri = lookupNamespace(prefix);
497                 if (uri != null) {
498                     _extensions.put(uri, prefix);
499                 }
500             }
501         }
502     }
503
504     public boolean isExtension(String JavaDoc uri) {
505         return (_extensions.get(uri) != null);
506     }
507
508     public void excludeExtensionPrefixes(Parser parser) {
509         final SymbolTable stable = parser.getSymbolTable();
510         final String JavaDoc excludePrefixes = getAttribute("exclude-result-prefixes");
511         final String JavaDoc extensionPrefixes = getAttribute("extension-element-prefixes");
512         
513         // Exclude XSLT uri
514
stable.excludeURI(Constants.XSLT_URI);
515         stable.excludeNamespaces(excludePrefixes);
516         stable.excludeNamespaces(extensionPrefixes);
517         extensionURI(extensionPrefixes, stable);
518     }
519
520     /**
521      * Parse the version and uri fields of the stylesheet and add an
522      * entry to the symbol table mapping the name <tt>__stylesheet_</tt>
523      * to an instance of this class.
524      */

525     public void parseContents(Parser parser) {
526         final SymbolTable stable = parser.getSymbolTable();
527
528         /*
529         // Make sure the XSL version set in this stylesheet
530         if ((_version == null) || (_version.equals(EMPTYSTRING))) {
531             reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR,"version");
532         }
533         // Verify that the version is 1.0 and nothing else
534         else if (!_version.equals("1.0")) {
535             reportError(this, parser, ErrorMsg.XSL_VERSION_ERR, _version);
536         }
537         */

538
539         // Add the implicit mapping of 'xml' to the XML namespace URI
540
addPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace");
541
542         // Report and error if more than one stylesheet defined
543
final Stylesheet sheet = stable.addStylesheet(_name, this);
544         if (sheet != null) {
545             // Error: more that one stylesheet defined
546
ErrorMsg err = new ErrorMsg(ErrorMsg.MULTIPLE_STYLESHEET_ERR,this);
547             parser.reportError(Constants.ERROR, err);
548         }
549
550         // If this is a simplified stylesheet we must create a template that
551
// grabs the root node of the input doc ( <xsl:template match="/"/> ).
552
// This template needs the current element (the one passed to this
553
// method) as its only child, so the Template class has a special
554
// method that handles this (parseSimplified()).
555
if (_simplified) {
556             stable.excludeURI(XSLT_URI);
557             Template template = new Template();
558             template.parseSimplified(this, parser);
559         }
560         // Parse the children of this node
561
else {
562             parseOwnChildren(parser);
563         }
564     }
565
566     /**
567      * Parse all direct children of the <xsl:stylesheet/> element.
568      */

569     public final void parseOwnChildren(Parser parser) {
570         final Vector JavaDoc contents = getContents();
571         final int count = contents.size();
572
573         // We have to scan the stylesheet element's top-level elements for
574
// variables and/or parameters before we parse the other elements
575
for (int i = 0; i < count; i++) {
576             SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
577             if ((child instanceof VariableBase) ||
578                 (child instanceof NamespaceAlias)) {
579                 parser.getSymbolTable().setCurrentNode(child);
580                 child.parseContents(parser);
581             }
582         }
583
584         // Now go through all the other top-level elements...
585
for (int i = 0; i < count; i++) {
586             SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
587             if (!(child instanceof VariableBase) &&
588                 !(child instanceof NamespaceAlias)) {
589                 parser.getSymbolTable().setCurrentNode(child);
590                 child.parseContents(parser);
591             }
592
593             // All template code should be compiled as methods if the
594
// <xsl:apply-imports/> element was ever used in this stylesheet
595
if (!_templateInlining && (child instanceof Template)) {
596                 Template template = (Template)child;
597                 String JavaDoc name = "template$dot$" + template.getPosition();
598                 template.setName(parser.getQName(name));
599             }
600         }
601     }
602
603     public void processModes() {
604         if (_defaultMode == null)
605             _defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
606         _defaultMode.processPatterns(_keys);
607         final Enumeration JavaDoc modes = _modes.elements();
608         while (modes.hasMoreElements()) {
609             final Mode mode = (Mode)modes.nextElement();
610             mode.processPatterns(_keys);
611         }
612     }
613         
614     private void compileModes(ClassGenerator classGen) {
615         _defaultMode.compileApplyTemplates(classGen);
616         final Enumeration JavaDoc modes = _modes.elements();
617         while (modes.hasMoreElements()) {
618             final Mode mode = (Mode)modes.nextElement();
619             mode.compileApplyTemplates(classGen);
620         }
621     }
622
623     public Mode getMode(QName modeName) {
624         if (modeName == null) {
625             if (_defaultMode == null) {
626                 _defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
627             }
628             return _defaultMode;
629         }
630         else {
631             Mode mode = (Mode)_modes.get(modeName);
632             if (mode == null) {
633                 final String JavaDoc suffix = Integer.toString(_nextModeSerial++);
634                 _modes.put(modeName, mode = new Mode(modeName, this, suffix));
635             }
636             return mode;
637         }
638     }
639
640     /**
641      * Type check all the children of this node.
642      */

643     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
644         final int count = _globals.size();
645         for (int i = 0; i < count; i++) {
646             final VariableBase var = (VariableBase)_globals.elementAt(i);
647             var.typeCheck(stable);
648         }
649         return typeCheckContents(stable);
650     }
651
652     /**
653      * Translate the stylesheet into JVM bytecodes.
654      */

655     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
656         translate();
657     }
658
659     private void addDOMField(ClassGenerator classGen) {
660         final FieldGen fgen = new FieldGen(ACC_PUBLIC,
661                                            Util.getJCRefType(DOM_INTF_SIG),
662                                            DOM_FIELD,
663                                            classGen.getConstantPool());
664         classGen.addField(fgen.getField());
665     }
666     
667     /**
668      * Add a static field
669      */

670     private void addStaticField(ClassGenerator classGen, String JavaDoc type,
671                                 String JavaDoc name)
672     {
673         final FieldGen fgen = new FieldGen(ACC_PROTECTED|ACC_STATIC,
674                                            Util.getJCRefType(type),
675                                            name,
676                                            classGen.getConstantPool());
677         classGen.addField(fgen.getField());
678
679     }
680
681     /**
682      * Translate the stylesheet into JVM bytecodes.
683      */

684     public void translate() {
685         _className = getXSLTC().getClassName();
686
687         // Define a new class by extending TRANSLET_CLASS
688
final ClassGenerator classGen =
689             new ClassGenerator(_className,
690                                TRANSLET_CLASS,
691                                Constants.EMPTYSTRING,
692                                ACC_PUBLIC | ACC_SUPER,
693                                null, this);
694         
695         addDOMField(classGen);
696
697         // Compile transform() to initialize parameters, globals & output
698
// and run the transformation
699
compileTransform(classGen);
700
701         // Translate all non-template elements and filter out all templates
702
final Enumeration JavaDoc elements = elements();
703         while (elements.hasMoreElements()) {
704             Object JavaDoc element = elements.nextElement();
705             // xsl:template
706
if (element instanceof Template) {
707                 // Separate templates by modes
708
final Template template = (Template)element;
709                 //_templates.addElement(template);
710
getMode(template.getModeName()).addTemplate(template);
711             }
712             // xsl:attribute-set
713
else if (element instanceof AttributeSet) {
714                 ((AttributeSet)element).translate(classGen, null);
715             }
716             else if (element instanceof Output) {
717                 // save the element for later to pass to compileConstructor
718
Output output = (Output)element;
719                 if (output.enabled()) _lastOutputElement = output;
720             }
721             else {
722                 // Global variables and parameters are handled elsewhere.
723
// Other top-level non-template elements are ignored. Literal
724
// elements outside of templates will never be output.
725
}
726         }
727
728         checkOutputMethod();
729         processModes();
730         compileModes(classGen);
731         compileStaticInitializer(classGen);
732         compileConstructor(classGen, _lastOutputElement);
733
734         if (!getParser().errorsFound()) {
735             getXSLTC().dumpClass(classGen.getJavaClass());
736         }
737     }
738
739     /**
740      * Compile the namesArray, urisArray and typesArray into
741      * the static initializer. They are read-only from the
742      * translet. All translet instances can share a single
743      * copy of this informtion.
744      */

745     private void compileStaticInitializer(ClassGenerator classGen) {
746         final ConstantPoolGen cpg = classGen.getConstantPool();
747         final InstructionList il = new InstructionList();
748
749         final MethodGenerator staticConst =
750             new MethodGenerator(ACC_PUBLIC|ACC_STATIC,
751                                 com.sun.org.apache.bcel.internal.generic.Type.VOID,
752                                 null, null, "<clinit>",
753                                 _className, il, cpg);
754
755         addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD);
756         addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD);
757         addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD);
758         addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD);
759         // Create fields of type char[] that will contain literal text from
760
// the stylesheet.
761
final int charDataFieldCount = getXSLTC().getCharacterDataCount();
762         for (int i = 0; i < charDataFieldCount; i++) {
763             addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG,
764                            STATIC_CHAR_DATA_FIELD+i);
765         }
766
767         // Put the names array into the translet - used for dom/translet mapping
768
final Vector JavaDoc namesIndex = getXSLTC().getNamesIndex();
769         int size = namesIndex.size();
770         String JavaDoc[] namesArray = new String JavaDoc[size];
771         String JavaDoc[] urisArray = new String JavaDoc[size];
772         int[] typesArray = new int[size];
773         
774         int index;
775         for (int i = 0; i < size; i++) {
776             String JavaDoc encodedName = (String JavaDoc)namesIndex.elementAt(i);
777             if ((index = encodedName.lastIndexOf(':')) > -1) {
778                 urisArray[i] = encodedName.substring(0, index);
779             }
780             
781             index = index + 1;
782             if (encodedName.charAt(index) == '@') {
783                 typesArray[i] = DTM.ATTRIBUTE_NODE;
784                 index++;
785             } else if (encodedName.charAt(index) == '?') {
786                 typesArray[i] = DTM.NAMESPACE_NODE;
787                 index++;
788             } else {
789                 typesArray[i] = DTM.ELEMENT_NODE;
790             }
791             
792             if (index == 0) {
793                 namesArray[i] = encodedName;
794             }
795             else {
796                 namesArray[i] = encodedName.substring(index);
797             }
798         }
799         
800         il.append(new PUSH(cpg, size));
801         il.append(new ANEWARRAY(cpg.addClass(STRING)));
802
803         for (int i = 0; i < size; i++) {
804             final String JavaDoc name = namesArray[i];
805             il.append(DUP);
806             il.append(new PUSH(cpg, i));
807             il.append(new PUSH(cpg, name));
808             il.append(AASTORE);
809         }
810         il.append(new PUTSTATIC(cpg.addFieldref(_className,
811                                                STATIC_NAMES_ARRAY_FIELD,
812                                                NAMES_INDEX_SIG)));
813
814         il.append(new PUSH(cpg, size));
815         il.append(new ANEWARRAY(cpg.addClass(STRING)));
816
817         for (int i = 0; i < size; i++) {
818             final String JavaDoc uri = urisArray[i];
819             il.append(DUP);
820             il.append(new PUSH(cpg, i));
821             il.append(new PUSH(cpg, uri));
822             il.append(AASTORE);
823         }
824         il.append(new PUTSTATIC(cpg.addFieldref(_className,
825                                                STATIC_URIS_ARRAY_FIELD,
826                                                URIS_INDEX_SIG)));
827
828         il.append(new PUSH(cpg, size));
829         il.append(new NEWARRAY(BasicType.INT));
830
831         for (int i = 0; i < size; i++) {
832             final int nodeType = typesArray[i];
833             il.append(DUP);
834             il.append(new PUSH(cpg, i));
835             il.append(new PUSH(cpg, nodeType));
836             il.append(IASTORE);
837         }
838         il.append(new PUTSTATIC(cpg.addFieldref(_className,
839                                                STATIC_TYPES_ARRAY_FIELD,
840                                                TYPES_INDEX_SIG)));
841
842         // Put the namespace names array into the translet
843
final Vector JavaDoc namespaces = getXSLTC().getNamespaceIndex();
844         il.append(new PUSH(cpg, namespaces.size()));
845         il.append(new ANEWARRAY(cpg.addClass(STRING)));
846
847         for (int i = 0; i < namespaces.size(); i++) {
848             final String JavaDoc ns = (String JavaDoc)namespaces.elementAt(i);
849             il.append(DUP);
850             il.append(new PUSH(cpg, i));
851             il.append(new PUSH(cpg, ns));
852             il.append(AASTORE);
853         }
854         il.append(new PUTSTATIC(cpg.addFieldref(_className,
855                                                STATIC_NAMESPACE_ARRAY_FIELD,
856                                                NAMESPACE_INDEX_SIG)));
857
858         // Grab all the literal text in the stylesheet and put it in a char[]
859
final int charDataCount = getXSLTC().getCharacterDataCount();
860         final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C");
861         for (int i = 0; i < charDataCount; i++) {
862             il.append(new PUSH(cpg, getXSLTC().getCharacterData(i)));
863             il.append(new INVOKEVIRTUAL(toCharArray));
864             il.append(new PUTSTATIC(cpg.addFieldref(_className,
865                                                STATIC_CHAR_DATA_FIELD+i,
866                                                STATIC_CHAR_DATA_FIELD_SIG)));
867         }
868
869         il.append(RETURN);
870
871         staticConst.stripAttributes(true);
872         staticConst.setMaxLocals();
873         staticConst.setMaxStack();
874         classGen.addMethod(staticConst.getMethod());
875         
876     }
877
878     /**
879      * Compile the translet's constructor
880      */

881     private void compileConstructor(ClassGenerator classGen, Output output) {
882
883         final ConstantPoolGen cpg = classGen.getConstantPool();
884         final InstructionList il = new InstructionList();
885
886         final MethodGenerator constructor =
887             new MethodGenerator(ACC_PUBLIC,
888                                 com.sun.org.apache.bcel.internal.generic.Type.VOID,
889                                 null, null, "<init>",
890                                 _className, il, cpg);
891
892         // Call the constructor in the AbstractTranslet superclass
893
il.append(classGen.loadTranslet());
894         il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS,
895                                                      "<init>", "()V")));
896         
897         il.append(classGen.loadTranslet());
898         il.append(new GETSTATIC(cpg.addFieldref(_className,
899                                                 STATIC_NAMES_ARRAY_FIELD,
900                                                 NAMES_INDEX_SIG)));
901         il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
902                                                NAMES_INDEX,
903                                                NAMES_INDEX_SIG)));
904         
905         il.append(classGen.loadTranslet());
906         il.append(new GETSTATIC(cpg.addFieldref(_className,
907                                                 STATIC_URIS_ARRAY_FIELD,
908                                                 URIS_INDEX_SIG)));
909         il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
910                                                URIS_INDEX,
911                                                URIS_INDEX_SIG)));
912
913         il.append(classGen.loadTranslet());
914         il.append(new GETSTATIC(cpg.addFieldref(_className,
915                                                 STATIC_TYPES_ARRAY_FIELD,
916                                                 TYPES_INDEX_SIG)));
917         il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
918                                                TYPES_INDEX,
919                                                TYPES_INDEX_SIG)));
920
921         il.append(classGen.loadTranslet());
922         il.append(new GETSTATIC(cpg.addFieldref(_className,
923                                                 STATIC_NAMESPACE_ARRAY_FIELD,
924                                                 NAMESPACE_INDEX_SIG)));
925         il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
926                                                NAMESPACE_INDEX,
927                                                NAMESPACE_INDEX_SIG)));
928
929         il.append(classGen.loadTranslet());
930         il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION));
931         il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
932                                                TRANSLET_VERSION_INDEX,
933                                                TRANSLET_VERSION_INDEX_SIG)));
934         
935         if (_hasIdCall) {
936             il.append(classGen.loadTranslet());
937             il.append(new PUSH(cpg, Boolean.TRUE));
938             il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
939                                                    HASIDCALL_INDEX,
940                                                    HASIDCALL_INDEX_SIG)));
941         }
942         
943         // Compile in code to set the output configuration from <xsl:output>
944
if (output != null) {
945             // Set all the output settings files in the translet
946
output.translate(classGen, constructor);
947         }
948
949         // Compile default decimal formatting symbols.
950
// This is an implicit, nameless xsl:decimal-format top-level element.
951
if (_numberFormattingUsed)
952             DecimalFormatting.translateDefaultDFS(classGen, constructor);
953
954         il.append(RETURN);
955
956         constructor.stripAttributes(true);
957         constructor.setMaxLocals();
958         constructor.setMaxStack();
959         classGen.addMethod(constructor.getMethod());
960     }
961
962     /**
963      * Compile a topLevel() method into the output class. This method is
964      * called from transform() to handle all non-template top-level elements.
965      * Returns the signature of the topLevel() method.
966      *
967      * Global variables/params and keys are first sorted to resolve
968      * dependencies between them. The XSLT 1.0 spec does not allow a key
969      * to depend on a variable. However, for compatibility with Xalan
970      * interpretive, that type of dependency is allowed. Note also that
971      * the buildKeys() method is still generated as it is used by the
972      * LoadDocument class, but it no longer called from transform().
973      */

974     private String JavaDoc compileTopLevel(ClassGenerator classGen) {
975
976         final ConstantPoolGen cpg = classGen.getConstantPool();
977
978         final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = {
979             Util.getJCRefType(DOM_INTF_SIG),
980             Util.getJCRefType(NODE_ITERATOR_SIG),
981             Util.getJCRefType(TRANSLET_OUTPUT_SIG)
982         };
983
984         final String JavaDoc[] argNames = {
985             DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME
986         };
987
988         final InstructionList il = new InstructionList();
989
990         final MethodGenerator toplevel =
991             new MethodGenerator(ACC_PUBLIC,
992                                 com.sun.org.apache.bcel.internal.generic.Type.VOID,
993                                 argTypes, argNames,
994                                 "topLevel", _className, il,
995                                 classGen.getConstantPool());
996
997         toplevel.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
998
999         // Define and initialize 'current' variable with the root node
1000
final LocalVariableGen current =
1001            toplevel.addLocalVariable("current",
1002                                    com.sun.org.apache.bcel.internal.generic.Type.INT,
1003                                    il.getEnd(), null);
1004
1005        final int setFilter = cpg.addInterfaceMethodref(DOM_INTF,
1006                               "setFilter",
1007                               "(Lcom/sun/org/apache/xalan/internal/xsltc/StripFilter;)V");
1008
1009        il.append(new PUSH(cpg, DTM.ROOT_NODE));
1010        il.append(new ISTORE(current.getIndex()));
1011
1012        // Create a new list containing variables/params + keys
1013
Vector JavaDoc varDepElements = new Vector JavaDoc(_globals);
1014        Enumeration JavaDoc elements = elements();
1015        while (elements.hasMoreElements()) {
1016            final Object JavaDoc element = elements.nextElement();
1017            if (element instanceof Key) {
1018                varDepElements.add(element);
1019            }
1020        }
1021        // Determine a partial order for the variables/params and keys
1022
varDepElements = resolveDependencies(varDepElements);
1023                
1024         // Translate vars/params and keys in the right order
1025
final int count = varDepElements.size();
1026
1027        for (int i = 0; i < count; i++) {
1028            final TopLevelElement tle = (TopLevelElement) varDepElements.elementAt(i);
1029            tle.translate(classGen, toplevel);
1030            if (tle instanceof Key) {
1031                final Key key = (Key) tle;
1032                _keys.put(key.getName(), key);
1033            }
1034        }
1035
1036        // Compile code for other top-level elements
1037
Vector JavaDoc whitespaceRules = new Vector JavaDoc();
1038        elements = elements();
1039        while (elements.hasMoreElements()) {
1040            final Object JavaDoc element = elements.nextElement();
1041            // xsl:decimal-format
1042
if (element instanceof DecimalFormatting) {
1043                ((DecimalFormatting)element).translate(classGen,toplevel);
1044            }
1045            // xsl:strip/preserve-space
1046
else if (element instanceof Whitespace) {
1047                whitespaceRules.addAll(((Whitespace)element).getRules());
1048            }
1049        }
1050
1051        // Translate all whitespace strip/preserve rules
1052
if (whitespaceRules.size() > 0) {
1053            Whitespace.translateRules(whitespaceRules,classGen);
1054        }
1055
1056        if (classGen.containsMethod(STRIP_SPACE, STRIP_SPACE_PARAMS) != null) {
1057            il.append(toplevel.loadDOM());
1058            il.append(classGen.loadTranslet());
1059            il.append(new INVOKEINTERFACE(setFilter, 2));
1060        }
1061
1062        il.append(RETURN);
1063
1064        // Compute max locals + stack and add method to class
1065
toplevel.stripAttributes(true);
1066        toplevel.setMaxLocals();
1067        toplevel.setMaxStack();
1068        toplevel.removeNOPs();
1069
1070        classGen.addMethod(toplevel.getMethod());
1071        
1072        return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V");
1073    }
1074
1075    /**
1076     * This method returns a vector with variables/params and keys in the
1077     * order in which they are to be compiled for initialization. The order
1078     * is determined by analyzing the dependencies between them. The XSLT 1.0
1079     * spec does not allow a key to depend on a variable. However, for
1080     * compatibility with Xalan interpretive, that type of dependency is
1081     * allowed and, therefore, consider to determine the partial order.
1082     */

1083    private Vector JavaDoc resolveDependencies(Vector JavaDoc input) {
1084
1085      /* DEBUG CODE IGNORE
1086      for (int i = 0; i < input.size(); i++) {
1087          final TopLevelElement e = (TopLevelElement) input.elementAt(i);
1088          System.out.println("e = " + e + " depends on:");
1089          Vector dep = e.getDependencies();
1090          for (int j = 0; j < (dep != null ? dep.size() : 0); j++) {
1091              System.out.println("\t" + dep.elementAt(j));
1092          }
1093      }
1094      System.out.println("=================================");
1095      */

1096
1097        Vector JavaDoc result = new Vector JavaDoc();
1098        while (input.size() > 0) {
1099            boolean changed = false;
1100            for (int i = 0; i < input.size(); ) {
1101                final TopLevelElement vde = (TopLevelElement) input.elementAt(i);
1102                final Vector JavaDoc dep = vde.getDependencies();
1103                if (dep == null || result.containsAll(dep)) {
1104                    result.addElement(vde);
1105                    input.remove(i);
1106                    changed = true;
1107                }
1108                else {
1109                    i++;
1110                }
1111            }
1112
1113            // If nothing was changed in this pass then we have a circular ref
1114
if (!changed) {
1115                ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR,
1116                                            input.toString(), this);
1117                getParser().reportError(Constants.ERROR, err);
1118                return(result);
1119            }
1120        }
1121
1122        /* DEBUG CODE - INGORE
1123        System.out.println("=================================");
1124        for (int i = 0; i < result.size(); i++) {
1125            TopLevelElement e = (TopLevelElement) result.elementAt(i);
1126            System.out.println("e = " + e);
1127        }
1128        */

1129
1130        return result;
1131    }
1132
1133    /**
1134     * Compile a buildKeys() method into the output class. Note that keys
1135     * for the input document are created in topLevel(), not in this method.
1136     * However, we still need this method to create keys for documents loaded
1137     * via the XPath document() function.
1138     */

1139    private String JavaDoc compileBuildKeys(ClassGenerator classGen) {
1140
1141        final ConstantPoolGen cpg = classGen.getConstantPool();
1142
1143        final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = {
1144            Util.getJCRefType(DOM_INTF_SIG),
1145            Util.getJCRefType(NODE_ITERATOR_SIG),
1146            Util.getJCRefType(TRANSLET_OUTPUT_SIG),
1147            com.sun.org.apache.bcel.internal.generic.Type.INT
1148        };
1149
1150        final String JavaDoc[] argNames = {
1151            DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME, "current"
1152        };
1153
1154        final InstructionList il = new InstructionList();
1155
1156        final MethodGenerator buildKeys =
1157            new MethodGenerator(ACC_PUBLIC,
1158                                com.sun.org.apache.bcel.internal.generic.Type.VOID,
1159                                argTypes, argNames,
1160                                "buildKeys", _className, il,
1161                                classGen.getConstantPool());
1162
1163        buildKeys.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
1164        
1165        final Enumeration JavaDoc elements = elements();
1166        while (elements.hasMoreElements()) {
1167            // xsl:key
1168
final Object JavaDoc element = elements.nextElement();
1169            if (element instanceof Key) {
1170                final Key key = (Key)element;
1171                key.translate(classGen, buildKeys);
1172                _keys.put(key.getName(),key);
1173            }
1174        }
1175        
1176        il.append(RETURN);
1177        
1178        // Compute max locals + stack and add method to class
1179
buildKeys.stripAttributes(true);
1180        buildKeys.setMaxLocals();
1181        buildKeys.setMaxStack();
1182        buildKeys.removeNOPs();
1183
1184        classGen.addMethod(buildKeys.getMethod());
1185        
1186        return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+"I)V");
1187    }
1188
1189    /**
1190     * Compile transform() into the output class. This method is used to
1191     * initialize global variables and global parameters. The current node
1192     * is set to be the document's root node.
1193     */

1194    private void compileTransform(ClassGenerator classGen) {
1195        final ConstantPoolGen cpg = classGen.getConstantPool();
1196
1197        /*
1198         * Define the the method transform with the following signature:
1199         * void transform(DOM, NodeIterator, HandlerBase)
1200         */

1201        final com.sun.org.apache.bcel.internal.generic.Type[] argTypes =
1202            new com.sun.org.apache.bcel.internal.generic.Type[3];
1203        argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
1204        argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
1205        argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);
1206
1207        final String JavaDoc[] argNames = new String JavaDoc[3];
1208        argNames[0] = DOCUMENT_PNAME;
1209        argNames[1] = ITERATOR_PNAME;
1210        argNames[2] = TRANSLET_OUTPUT_PNAME;
1211
1212        final InstructionList il = new InstructionList();
1213        final MethodGenerator transf =
1214            new MethodGenerator(ACC_PUBLIC,
1215                                com.sun.org.apache.bcel.internal.generic.Type.VOID,
1216                                argTypes, argNames,
1217                                "transform",
1218                                _className,
1219                                il,
1220                                classGen.getConstantPool());
1221        transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
1222
1223        // Define and initialize current with the root node
1224
final LocalVariableGen current =
1225            transf.addLocalVariable("current",
1226                                    com.sun.org.apache.bcel.internal.generic.Type.INT,
1227                                    il.getEnd(), null);
1228        final String JavaDoc applyTemplatesSig = classGen.getApplyTemplatesSig();
1229        final int applyTemplates = cpg.addMethodref(getClassName(),
1230                                                    "applyTemplates",
1231                                                    applyTemplatesSig);
1232        final int domField = cpg.addFieldref(getClassName(),
1233                                             DOM_FIELD,
1234                                             DOM_INTF_SIG);
1235
1236        // push translet for PUTFIELD
1237
il.append(classGen.loadTranslet());
1238        // prepare appropriate DOM implementation
1239

1240        if (isMultiDocument()) {
1241            il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS)));
1242            il.append(DUP);
1243        }
1244        
1245        il.append(classGen.loadTranslet());
1246        il.append(transf.loadDOM());
1247        il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
1248                                                     "makeDOMAdapter",
1249                                                     "("+DOM_INTF_SIG+")"+
1250                                                     DOM_ADAPTER_SIG)));
1251        // DOMAdapter is on the stack
1252

1253        if (isMultiDocument()) {
1254            final int init = cpg.addMethodref(MULTI_DOM_CLASS,
1255                                              "<init>",
1256                                              "("+DOM_INTF_SIG+")V");
1257            il.append(new INVOKESPECIAL(init));
1258            // MultiDOM is on the stack
1259
}
1260        
1261        //store to _dom variable
1262
il.append(new PUTFIELD(domField));
1263
1264        // continue with globals initialization
1265
il.append(new PUSH(cpg, DTM.ROOT_NODE));
1266        il.append(new ISTORE(current.getIndex()));
1267
1268        // Transfer the output settings to the output post-processor
1269
il.append(classGen.loadTranslet());
1270        il.append(transf.loadHandler());
1271        final int index = cpg.addMethodref(TRANSLET_CLASS,
1272                                           "transferOutputSettings",
1273                                           "("+OUTPUT_HANDLER_SIG+")V");
1274        il.append(new INVOKEVIRTUAL(index));
1275
1276        /*
1277         * Compile buildKeys() method. Note that this method is not
1278         * invoked here as keys for the input document are now created
1279         * in topLevel(). However, this method is still needed by the
1280         * LoadDocument class.
1281         */

1282        final String JavaDoc keySig = compileBuildKeys(classGen);
1283        final int keyIdx = cpg.addMethodref(getClassName(),
1284                                               "buildKeys", keySig);
1285
1286        // Look for top-level elements that need handling
1287
final Enumeration JavaDoc toplevel = elements();
1288        if (_globals.size() > 0 || toplevel.hasMoreElements()) {
1289            // Compile method for handling top-level elements
1290
final String JavaDoc topLevelSig = compileTopLevel(classGen);
1291            // Get a reference to that method
1292
final int topLevelIdx = cpg.addMethodref(getClassName(),
1293                                                     "topLevel",
1294                                                     topLevelSig);
1295            // Push all parameters on the stack and call topLevel()
1296
il.append(classGen.loadTranslet()); // The 'this' pointer
1297
il.append(classGen.loadTranslet());
1298            il.append(new GETFIELD(domField)); // The DOM reference
1299
il.append(transf.loadIterator());
1300            il.append(transf.loadHandler()); // The output handler
1301
il.append(new INVOKEVIRTUAL(topLevelIdx));
1302        }
1303        
1304
1305
1306
1307        // start document
1308
il.append(transf.loadHandler());
1309        il.append(transf.startDocument());
1310
1311        // push first arg for applyTemplates
1312
il.append(classGen.loadTranslet());
1313        // push translet for GETFIELD to get DOM arg
1314
il.append(classGen.loadTranslet());
1315        il.append(new GETFIELD(domField));
1316        // push remaining 2 args
1317
il.append(transf.loadIterator());
1318        il.append(transf.loadHandler());
1319        il.append(new INVOKEVIRTUAL(applyTemplates));
1320        // endDocument
1321
il.append(transf.loadHandler());
1322        il.append(transf.endDocument());
1323
1324        il.append(RETURN);
1325
1326        // Compute max locals + stack and add method to class
1327
transf.stripAttributes(true);
1328        transf.setMaxLocals();
1329        transf.setMaxStack();
1330        transf.removeNOPs();
1331
1332        classGen.addMethod(transf.getMethod());
1333    }
1334
1335    /**
1336     * Peephole optimization: Remove sequences of [ALOAD, POP].
1337     */

1338    private void peepHoleOptimization(MethodGenerator methodGen) {
1339        final String JavaDoc pattern = "`aload'`pop'`instruction'";
1340        final InstructionList il = methodGen.getInstructionList();
1341        final InstructionFinder find = new InstructionFinder(il);
1342        for(Iterator JavaDoc iter=find.search(pattern); iter.hasNext(); ) {
1343            InstructionHandle[] match = (InstructionHandle[])iter.next();
1344            try {
1345                il.delete(match[0], match[1]);
1346            }
1347            catch (TargetLostException e) {
1348                // TODO: move target down into the list
1349
}
1350        }
1351    }
1352
1353    public int addParam(Param param) {
1354        _globals.addElement(param);
1355        return _globals.size() - 1;
1356    }
1357
1358    public int addVariable(Variable global) {
1359        _globals.addElement(global);
1360        return _globals.size() - 1;
1361    }
1362
1363    public void display(int indent) {
1364        indent(indent);
1365        Util.println("Stylesheet");
1366        displayContents(indent + IndentIncrement);
1367    }
1368
1369    // do we need this wrapper ?????
1370
public String JavaDoc getNamespace(String JavaDoc prefix) {
1371        return lookupNamespace(prefix);
1372    }
1373
1374    public String JavaDoc getClassName() {
1375        return _className;
1376    }
1377
1378    public Vector JavaDoc getTemplates() {
1379        return _templates;
1380    }
1381
1382    public Vector JavaDoc getAllValidTemplates() {
1383        // Return templates if no imported/included stylesheets
1384
if (_includedStylesheets == null) {
1385            return _templates;
1386        }
1387        
1388        // Is returned value cached?
1389
if (_allValidTemplates == null) {
1390            Vector JavaDoc templates = new Vector JavaDoc();
1391             templates.addAll(templates);
1392            int size = _includedStylesheets.size();
1393            for (int i = 0; i < size; i++) {
1394                Stylesheet included =(Stylesheet)_includedStylesheets.elementAt(i);
1395                templates.addAll(included.getAllValidTemplates());
1396            }
1397            // templates.addAll(_templates);
1398

1399            // Cache results in top-level stylesheet only
1400
if (_parentStylesheet != null) {
1401                return templates;
1402            }
1403            _allValidTemplates = templates;
1404         }
1405        
1406        return _allValidTemplates;
1407    }
1408    
1409    protected void addTemplate(Template template) {
1410        _templates.addElement(template);
1411    }
1412}
1413
Popular Tags