Package org.apache.xalan.xsltc.compiler

Source Code of org.apache.xalan.xsltc.compiler.Stylesheet

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the  "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: Stylesheet.java 577935 2007-09-20 21:35:20Z minchau $
*/

package org.apache.xalan.xsltc.compiler;

import java.util.Vector;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.xml.utils.SystemIDResolver;
import org.apache.bcel.generic.ANEWARRAY;
import org.apache.bcel.generic.BasicType;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.FieldGen;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.GETSTATIC;
import org.apache.bcel.generic.INVOKEINTERFACE;
import org.apache.bcel.generic.INVOKESPECIAL;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.ISTORE;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LocalVariableGen;
import org.apache.bcel.generic.NEW;
import org.apache.bcel.generic.NEWARRAY;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.PUTFIELD;
import org.apache.bcel.generic.PUTSTATIC;
import org.apache.bcel.generic.TargetLostException;
import org.apache.bcel.util.InstructionFinder;
import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
import org.apache.xalan.xsltc.compiler.util.Type;
import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
import org.apache.xalan.xsltc.compiler.util.Util;
import org.apache.xalan.xsltc.runtime.AbstractTranslet;
import org.apache.xml.dtm.DTM;

public final class Stylesheet extends SyntaxTreeNode {

    /**
     * XSLT version defined in the stylesheet.
     */
    private String _version;
   
    /**
     * Internal name of this stylesheet used as a key into the symbol table.
     */
    private QName _name;
   
    /**
     * A URI that represents the system ID for this stylesheet.
     */
    private String _systemId;
   
    /**
     * A reference to the parent stylesheet or null if topmost.
     */
    private Stylesheet _parentStylesheet;
 
    /**
     * Contains global variables and parameters defined in the stylesheet.
     */
    private Vector _globals = new Vector();

    /**
     * Used to cache the result returned by <code>hasLocalParams()</code>.
     */
    private Boolean _hasLocalParams = null;

    /**
     * The name of the class being generated.
     */
    private String _className;
   
    /**
      * Contains all templates defined in this stylesheet
      */
    private final Vector _templates = new Vector();
   
    /**
     * Used to cache result of <code>getAllValidTemplates()</code>. Only
     * set in top-level stylesheets that include/import other stylesheets.
     */
    private Vector _allValidTemplates = null;

    private Vector _elementsWithNamespacesUsedDynamically = null;

    /**
     * Counter to generate unique mode suffixes.
     */
    private int _nextModeSerial = 1;
   
    /**
     * Mapping between mode names and Mode instances.
     */
    private final Hashtable _modes = new Hashtable();
   
    /**
     * A reference to the default Mode object.
     */
    private Mode _defaultMode;

    /**
     * Mapping between extension URIs and their prefixes.
     */
    private final Hashtable _extensions = new Hashtable();

    /**
     * Reference to the stylesheet from which this stylesheet was
     * imported (if any).
     */
    public Stylesheet _importedFrom = null;
   
    /**
     * Reference to the stylesheet from which this stylesheet was
     * included (if any).
     */
    public Stylesheet _includedFrom = null;
   
    /**
     * Array of all the stylesheets imported or included from this one.
     */
    private Vector _includedStylesheets = null;
   
    /**
     * Import precendence for this stylesheet.
     */
    private int _importPrecedence = 1;

    /**
     * Minimum precendence of any descendant stylesheet by inclusion or
     * importation.
     */
    private int _minimumDescendantPrecedence = -1;

    /**
     * Mapping between key names and Key objects (needed by Key/IdPattern).
     */
    private Hashtable _keys = new Hashtable();

    /**
     * A reference to the SourceLoader set by the user (a URIResolver
     * if the JAXP API is being used).
     */
    private SourceLoader _loader = null;

    /**
     * Flag indicating if format-number() is called.
     */
    private boolean _numberFormattingUsed = false;

    /**
     * Flag indicating if this is a simplified stylesheets. A template
     * matching on "/" must be added in this case.
     */
    private boolean _simplified = false;

    /**
     * Flag indicating if multi-document support is needed.
     */
    private boolean _multiDocument = false;
   
    /**
     * Flag indicating if nodset() is called.
     */
    private boolean _callsNodeset = false;

    /**
     * Flag indicating if id() is called.
     */
    private boolean _hasIdCall = false;
   
    /**
     * Set to true to enable template inlining optimization.
     * @see XSLTC#_templateInlining
     */
    private boolean _templateInlining = false;

    /**
     * A reference to the last xsl:output object found in the styleshet.
     */
    private Output  _lastOutputElement = null;
   
    /**
     * Output properties for this stylesheet.
     */
    private Properties _outputProperties = null;
   
    /**
     * Output method for this stylesheet (must be set to one of
     * the constants defined below).
     */
    private int _outputMethod = UNKNOWN_OUTPUT;

    // Output method constants
    public static final int UNKNOWN_OUTPUT = 0;
    public static final int XML_OUTPUT     = 1;
    public static final int HTML_OUTPUT    = 2;
    public static final int TEXT_OUTPUT    = 3;
   
    /**
     * Return the output method
     */
    public int getOutputMethod() {
      return _outputMethod;
    }
   
    /**
     * Check and set the output method
     */
    private void checkOutputMethod() {
  if (_lastOutputElement != null) {
      String method = _lastOutputElement.getOutputMethod();
      if (method != null) {
          if (method.equals("xml"))
              _outputMethod = XML_OUTPUT;
          else if (method.equals("html"))
              _outputMethod = HTML_OUTPUT;
          else if (method.equals("text"))
              _outputMethod = TEXT_OUTPUT;
      }
  }
    }

    public boolean getTemplateInlining() {
  return _templateInlining;
    }

    public void setTemplateInlining(boolean flag) {
  _templateInlining = flag;
    }

    public boolean isSimplified() {
  return(_simplified);
    }

    public void setSimplified() {
  _simplified = true;
    }
   
    public void setHasIdCall(boolean flag) {
        _hasIdCall = flag;
    }

    public void setOutputProperty(String key, String value) {
  if (_outputProperties == null) {
      _outputProperties = new Properties();
  }
  _outputProperties.setProperty(key, value);
    }

    public void setOutputProperties(Properties props) {
  _outputProperties = props;
    }

    public Properties getOutputProperties() {
  return _outputProperties;
    }

    public Output getLastOutputElement() {
      return _lastOutputElement;
    }
   
    public void setMultiDocument(boolean flag) { 
  _multiDocument = flag;
    }

    public boolean isMultiDocument() {
  return _multiDocument;
    }

    public void setCallsNodeset(boolean flag) {
  if (flag) setMultiDocument(flag);
  _callsNodeset = flag;
    }

    public boolean callsNodeset() {
  return _callsNodeset;
    }

    public void numberFormattingUsed() {
  _numberFormattingUsed = true;
        /*
         * Fix for bug 23046, if the stylesheet is included, set the
         * numberFormattingUsed flag to the parent stylesheet too.
         * AbstractTranslet.addDecimalFormat() will be inlined once for the
         * outer most stylesheet.
         */
        Stylesheet parent = getParentStylesheet();
        if (null != parent) parent.numberFormattingUsed();       
    }

    public void setImportPrecedence(final int precedence) {
  // Set import precedence for this stylesheet
  _importPrecedence = precedence;

  // Set import precedence for all included stylesheets
  final Enumeration elements = elements();
  while (elements.hasMoreElements()) {
      SyntaxTreeNode child = (SyntaxTreeNode)elements.nextElement();
      if (child instanceof Include) {
    Stylesheet included = ((Include)child).getIncludedStylesheet();
    if (included != null && included._includedFrom == this) {
        included.setImportPrecedence(precedence);
    }
      }
  }

  // Set import precedence for the stylesheet that imported this one
  if (_importedFrom != null) {
      if (_importedFrom.getImportPrecedence() < precedence) {
    final Parser parser = getParser();
    final int nextPrecedence = parser.getNextImportPrecedence();
    _importedFrom.setImportPrecedence(nextPrecedence);
      }
  }
  // Set import precedence for the stylesheet that included this one
  else if (_includedFrom != null) {
      if (_includedFrom.getImportPrecedence() != precedence)
    _includedFrom.setImportPrecedence(precedence);
  }
    }
   
    public int getImportPrecedence() {
  return _importPrecedence;
    }

    /**
     * Get the minimum of the precedence of this stylesheet, any stylesheet
     * imported by this stylesheet and any include/import descendant of this
     * stylesheet.
     */
    public int getMinimumDescendantPrecedence() {
        if (_minimumDescendantPrecedence == -1) {
            // Start with precedence of current stylesheet as a basis.
            int min = getImportPrecedence();

            // Recursively examine all imported/included stylesheets.
            final int inclImpCount = (_includedStylesheets != null)
                                          ? _includedStylesheets.size()
                                          : 0;

            for (int i = 0; i < inclImpCount; i++) {
                int prec = ((Stylesheet)_includedStylesheets.elementAt(i))
                                              .getMinimumDescendantPrecedence();

                if (prec < min) {
                    min = prec;
                }
            }

            _minimumDescendantPrecedence = min;
        }
        return _minimumDescendantPrecedence;
    }

    public boolean checkForLoop(String systemId) {
  // Return true if this stylesheet includes/imports itself
  if (_systemId != null && _systemId.equals(systemId)) {
      return true;
  }
  // Then check with any stylesheets that included/imported this one
  if (_parentStylesheet != null)
      return _parentStylesheet.checkForLoop(systemId);
  // Otherwise OK
  return false;
    }
   
    public void setParser(Parser parser) {
  super.setParser(parser);
  _name = makeStylesheetName("__stylesheet_");
    }
   
    public void setParentStylesheet(Stylesheet parent) {
  _parentStylesheet = parent;
    }
   
    public Stylesheet getParentStylesheet() {
  return _parentStylesheet;
    }

    public void setImportingStylesheet(Stylesheet parent) {
  _importedFrom = parent;
  parent.addIncludedStylesheet(this);
    }

    public void setIncludingStylesheet(Stylesheet parent) {
  _includedFrom = parent;
  parent.addIncludedStylesheet(this);
    }

    public void addIncludedStylesheet(Stylesheet child) {
      if (_includedStylesheets == null) {
          _includedStylesheets = new Vector();
      }
      _includedStylesheets.addElement(child);
    }

    public void setSystemId(String systemId) {
        if (systemId != null) {
            _systemId = SystemIDResolver.getAbsoluteURI(systemId);
        }
    }
   
    public String getSystemId() {
  return _systemId;
    }

    public void setSourceLoader(SourceLoader loader) {
  _loader = loader;
    }
   
    public SourceLoader getSourceLoader() {
  return _loader;
    }

    private QName makeStylesheetName(String prefix) {
  return getParser().getQName(prefix+getXSLTC().nextStylesheetSerial());
    }

    /**
     * Returns true if this stylesheet has global vars or params.
     */
    public boolean hasGlobals() {
  return _globals.size() > 0;
    }

    /**
     * Returns true if at least one template in the stylesheet has params
     * defined. Uses the variable <code>_hasLocalParams</code> to cache the
     * result.
     */
    public boolean hasLocalParams() {
  if (_hasLocalParams == null) {
      Vector templates = getAllValidTemplates();
      final int n = templates.size();
      for (int i = 0; i < n; i++) {
    final Template template = (Template)templates.elementAt(i);
    if (template.hasParams()) {
        _hasLocalParams = Boolean.TRUE;
        return true;
    }
      }
      _hasLocalParams = Boolean.FALSE;
      return false;
  }
  else {
      return _hasLocalParams.booleanValue();
  }
    }

    /**
     * Adds a single prefix mapping to this syntax tree node.
     * @param prefix Namespace prefix.
     * @param uri Namespace URI.
     */
    protected void addPrefixMapping(String prefix, String uri) {
  if (prefix.equals(EMPTYSTRING) && uri.equals(XHTML_URI)) return;
  super.addPrefixMapping(prefix, uri);
    }

    /**
     * Store extension URIs
     */
    private void extensionURI(String prefixes, SymbolTable stable) {
  if (prefixes != null) {
      StringTokenizer tokens = new StringTokenizer(prefixes);
      while (tokens.hasMoreTokens()) {
    final String prefix = tokens.nextToken();
    final String uri = lookupNamespace(prefix);
    if (uri != null) {
        _extensions.put(uri, prefix);
    }
      }
  }
    }

    public boolean isExtension(String uri) {
  return (_extensions.get(uri) != null);
    }

    public void excludeExtensionPrefixes(Parser parser) {
  final SymbolTable stable = parser.getSymbolTable();
      final String excludePrefixes = getAttribute("exclude-result-prefixes");
  final String extensionPrefixes = getAttribute("extension-element-prefixes");
 
  // Exclude XSLT uri
  stable.excludeURI(Constants.XSLT_URI);
  stable.excludeNamespaces(excludePrefixes);
  stable.excludeNamespaces(extensionPrefixes);
  extensionURI(extensionPrefixes, stable);
    }

    /**
     * Parse the version and uri fields of the stylesheet and add an
     * entry to the symbol table mapping the name <tt>__stylesheet_</tt>
     * to an instance of this class.
     */
    public void parseContents(Parser parser) {
  final SymbolTable stable = parser.getSymbolTable();

  /*
  // Make sure the XSL version set in this stylesheet
  if ((_version == null) || (_version.equals(EMPTYSTRING))) {
      reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR,"version");
  }
  // Verify that the version is 1.0 and nothing else
  else if (!_version.equals("1.0")) {
      reportError(this, parser, ErrorMsg.XSL_VERSION_ERR, _version);
  }
  */

  // Add the implicit mapping of 'xml' to the XML namespace URI
  addPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace");

  // Report and error if more than one stylesheet defined
  final Stylesheet sheet = stable.addStylesheet(_name, this);
  if (sheet != null) {
      // Error: more that one stylesheet defined
      ErrorMsg err = new ErrorMsg(ErrorMsg.MULTIPLE_STYLESHEET_ERR,this);
      parser.reportError(Constants.ERROR, err);
  }

  // If this is a simplified stylesheet we must create a template that
  // grabs the root node of the input doc ( <xsl:template match="/"/> ).
  // This template needs the current element (the one passed to this
  // method) as its only child, so the Template class has a special
  // method that handles this (parseSimplified()).
  if (_simplified) {
      stable.excludeURI(XSLT_URI);
      Template template = new Template();
      template.parseSimplified(this, parser);
  }
  // Parse the children of this node
  else {
      parseOwnChildren(parser);
  }
    }

    /**
     * Parse all direct children of the <xsl:stylesheet/> element.
     */
    public final void parseOwnChildren(Parser parser) {
  final Vector contents = getContents();
  final int count = contents.size();

  // We have to scan the stylesheet element's top-level elements for
  // variables and/or parameters before we parse the other elements
  for (int i = 0; i < count; i++) {
      SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
      if ((child instanceof VariableBase) ||
    (child instanceof NamespaceAlias)) {
    parser.getSymbolTable().setCurrentNode(child);
    child.parseContents(parser);
      }
  }

  // Now go through all the other top-level elements...
  for (int i = 0; i < count; i++) {
      SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
      if (!(child instanceof VariableBase) &&
    !(child instanceof NamespaceAlias)) {
    parser.getSymbolTable().setCurrentNode(child);
    child.parseContents(parser);
      }

      // All template code should be compiled as methods if the
      // <xsl:apply-imports/> element was ever used in this stylesheet
      if (!_templateInlining && (child instanceof Template)) {
    Template template = (Template)child;
    String name = "template$dot$" + template.getPosition();
    template.setName(parser.getQName(name));
      }
  }
    }

    public void processModes() {
  if (_defaultMode == null)
      _defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
  _defaultMode.processPatterns(_keys);
  final Enumeration modes = _modes.elements();
  while (modes.hasMoreElements()) {
      final Mode mode = (Mode)modes.nextElement();
      mode.processPatterns(_keys);
  }
    }
 
    private void compileModes(ClassGenerator classGen) {
  _defaultMode.compileApplyTemplates(classGen);
  final Enumeration modes = _modes.elements();
  while (modes.hasMoreElements()) {
      final Mode mode = (Mode)modes.nextElement();
      mode.compileApplyTemplates(classGen);
  }
    }

    public Mode getMode(QName modeName) {
  if (modeName == null) {
      if (_defaultMode == null) {
    _defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
      }
      return _defaultMode;
  }
  else {
      Mode mode = (Mode)_modes.get(modeName);
      if (mode == null) {
    final String suffix = Integer.toString(_nextModeSerial++);
    _modes.put(modeName, mode = new Mode(modeName, this, suffix));
      }
      return mode;
  }
    }

    /**
     * Type check all the children of this node.
     */
    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  final int count = _globals.size();
  for (int i = 0; i < count; i++) {
      final VariableBase var = (VariableBase)_globals.elementAt(i);
      var.typeCheck(stable);
  }
  return typeCheckContents(stable);
    }

    /**
     * Translate the stylesheet into JVM bytecodes.
     */
    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  translate();
    }

    private void addDOMField(ClassGenerator classGen) {
  final FieldGen fgen = new FieldGen(ACC_PUBLIC,
             Util.getJCRefType(DOM_INTF_SIG),
             DOM_FIELD,
             classGen.getConstantPool());
  classGen.addField(fgen.getField());
    }
   
    /**
     * Add a static field
     */
    private void addStaticField(ClassGenerator classGen, String type,
                                String name)
    {
        final FieldGen fgen = new FieldGen(ACC_PROTECTED|ACC_STATIC,
                                           Util.getJCRefType(type),
                                           name,
                                           classGen.getConstantPool());
        classGen.addField(fgen.getField());

    }

    /**
     * Translate the stylesheet into JVM bytecodes.
     */
    public void translate() {
  _className = getXSLTC().getClassName();

  // Define a new class by extending TRANSLET_CLASS
  final ClassGenerator classGen =
      new ClassGenerator(_className,
             TRANSLET_CLASS,
             Constants.EMPTYSTRING,
             ACC_PUBLIC | ACC_SUPER,
             null, this);
 
  addDOMField(classGen);

  // Compile transform() to initialize parameters, globals & output
  // and run the transformation
  compileTransform(classGen);

  // Translate all non-template elements and filter out all templates
  final Enumeration elements = elements();
  while (elements.hasMoreElements()) {
      Object element = elements.nextElement();
      // xsl:template
      if (element instanceof Template) {
    // Separate templates by modes
    final Template template = (Template)element;
    //_templates.addElement(template);
    getMode(template.getModeName()).addTemplate(template);
      }
      // xsl:attribute-set
      else if (element instanceof AttributeSet) {
    ((AttributeSet)element).translate(classGen, null);
      }
      else if (element instanceof Output) {
    // save the element for later to pass to compileConstructor
    Output output = (Output)element;
    if (output.enabled()) _lastOutputElement = output;
      }
      else {
    // Global variables and parameters are handled elsewhere.
    // Other top-level non-template elements are ignored. Literal
    // elements outside of templates will never be output.
      }
  }

  checkOutputMethod();
  processModes();
  compileModes(classGen);
        compileStaticInitializer(classGen);
  compileConstructor(classGen, _lastOutputElement);

  if (!getParser().errorsFound()) {
      getXSLTC().dumpClass(classGen.getJavaClass());
  }
    }

    /**
     * <p>Compile the namesArray, urisArray, typesArray, namespaceArray,
     * namespaceAncestorsArray, prefixURIsIdxArray and prefixURIPairsArray into
     * the static initializer. They are read-only from the
     * translet. All translet instances can share a single
     * copy of this informtion.</p>
     * <p>The <code>namespaceAncestorsArray</code>,
     * <code>prefixURIsIdxArray</code> and <code>prefixURIPairsArray</code>
     * contain namespace information accessible from the stylesheet:
     * <dl>
     * <dt><code>namespaceAncestorsArray</code></dt>
     * <dd>Array indexed by integer stylesheet node IDs containing node IDs of
     * the nearest ancestor node in the stylesheet with namespace
     * declarations or <code>-1</code> if there is no such ancestor.  There
     * can be more than one disjoint tree of nodes - one for each stylesheet
     * module</dd>
     * <dt><code>prefixURIsIdxArray</code></dt>
     * <dd>Array indexed by integer stylesheet node IDs containing the index
     * into <code>prefixURIPairsArray</code> of the first namespace prefix
     * declared for the node.  The values are stored in ascending order, so
     * the next value in this array (if any) can be used to find the last such
     * prefix-URI pair</dd>
     * <dt>prefixURIPairsArray</dt>
     * <dd>Array of pairs of namespace prefixes and URIs.  A zero-length
     * string represents the default namespace if it appears as a prefix and
     * a namespace undeclaration if it appears as a URI.</dd>
     * </dl>
     * </p>
     * <p>For this stylesheet
     * <pre><code>
     * &lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt;
     *   &lt;xsl:template match="/"&gt;
     *     &lt;xsl:for-each select="*" xmlns:foo="foouri"&gt;
     *       &lt;xsl:element name="{n}" xmlns:foo="baruri"&gt;
     *     &lt;/xsl:for-each&gt;
     *     &lt;out xmlns="lumpit"/&gt;
     *     &lt;xsl:element name="{n}" xmlns="foouri"/&gt;
     *     &lt;xsl:element name="{n}" namespace="{ns}" xmlns="limpit"/gt;
     *   &lt;/xsl:template&gt;
     * &lt;/xsl:stylesheet&gt;
     * </code></pre>
     * there will be four stylesheet nodes whose namespace information is
     * needed, and
     * <ul>
     * <li><code>namespaceAncestorsArray</code> will have the value
     * <code>[-1,0,1,0]</code>;</li>
     * <li><code>prefixURIsIdxArray</code> will have the value
     * <code>[0,4,6,8]</code>; and</li>
     * <li><code>prefixURIPairsArray</code> will have the value
     * <code>["xml","http://www.w3.org/XML/1998/namespace",
     *        "xsl","http://www.w3.org/1999/XSL/Transform"
     *        "foo","foouri","foo","baruri","","foouri"].</code></li>
     * </ul>
     * </p>
     */
    private void compileStaticInitializer(ClassGenerator classGen) {
  final ConstantPoolGen cpg = classGen.getConstantPool();
  final InstructionList il = new InstructionList();

  final MethodGenerator staticConst =
      new MethodGenerator(ACC_PUBLIC|ACC_STATIC,
        org.apache.bcel.generic.Type.VOID,
        null, null, "<clinit>",
        _className, il, cpg);

  addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD);
  addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD);
  addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD);
  addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD);
        // Create fields of type char[] that will contain literal text from
        // the stylesheet.
        final int charDataFieldCount = getXSLTC().getCharacterDataCount();
        for (int i = 0; i < charDataFieldCount; i++) {
            addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG,
                           STATIC_CHAR_DATA_FIELD+i);
        }

  // Put the names array into the translet - used for dom/translet mapping
  final Vector namesIndex = getXSLTC().getNamesIndex();
  int size = namesIndex.size();
  String[] namesArray = new String[size];
  String[] urisArray = new String[size];
  int[] typesArray = new int[size];
 
  int index;
  for (int i = 0; i < size; i++) {
      String encodedName = (String)namesIndex.elementAt(i);
      if ((index = encodedName.lastIndexOf(':')) > -1) {
          urisArray[i] = encodedName.substring(0, index);
      }
     
      index = index + 1;
      if (encodedName.charAt(index) == '@') {
        typesArray[i] = DTM.ATTRIBUTE_NODE;
        index++;
      } else if (encodedName.charAt(index) == '?') {
        typesArray[i] = DTM.NAMESPACE_NODE;
        index++;
      } else {
          typesArray[i] = DTM.ELEMENT_NODE;
      }
     
      if (index == 0) {
          namesArray[i] = encodedName;
      }
      else {
          namesArray[i] = encodedName.substring(index);
      }     
  }

        staticConst.markChunkStart();
  il.append(new PUSH(cpg, size));
  il.append(new ANEWARRAY(cpg.addClass(STRING)));   
        int namesArrayRef = cpg.addFieldref(_className,
                    STATIC_NAMES_ARRAY_FIELD,
              NAMES_INDEX_SIG);
  il.append(new PUTSTATIC(namesArrayRef));
        staticConst.markChunkEnd();

  for (int i = 0; i < size; i++) {
      final String name = namesArray[i];
            staticConst.markChunkStart();
      il.append(new GETSTATIC(namesArrayRef));
      il.append(new PUSH(cpg, i));
      il.append(new PUSH(cpg, name));
      il.append(AASTORE);
            staticConst.markChunkEnd();
  }

        staticConst.markChunkStart();
  il.append(new PUSH(cpg, size));
  il.append(new ANEWARRAY(cpg.addClass(STRING)));   
        int urisArrayRef = cpg.addFieldref(_className,
             STATIC_URIS_ARRAY_FIELD,
             URIS_INDEX_SIG);
  il.append(new PUTSTATIC(urisArrayRef));
        staticConst.markChunkEnd();

  for (int i = 0; i < size; i++) {
      final String uri = urisArray[i];
            staticConst.markChunkStart();
      il.append(new GETSTATIC(urisArrayRef));
      il.append(new PUSH(cpg, i));
      il.append(new PUSH(cpg, uri));
      il.append(AASTORE);
            staticConst.markChunkEnd();
  }

        staticConst.markChunkStart();
  il.append(new PUSH(cpg, size));
  il.append(new NEWARRAY(BasicType.INT));   
        int typesArrayRef = cpg.addFieldref(_className,
              STATIC_TYPES_ARRAY_FIELD,
              TYPES_INDEX_SIG);
  il.append(new PUTSTATIC(typesArrayRef));
        staticConst.markChunkEnd();

  for (int i = 0; i < size; i++) {
      final int nodeType = typesArray[i];
            staticConst.markChunkStart();
      il.append(new GETSTATIC(typesArrayRef));
      il.append(new PUSH(cpg, i));
      il.append(new PUSH(cpg, nodeType));
      il.append(IASTORE);
            staticConst.markChunkEnd();
  }

  // Put the namespace names array into the translet
  final Vector namespaces = getXSLTC().getNamespaceIndex();
        staticConst.markChunkStart();
  il.append(new PUSH(cpg, namespaces.size()));
  il.append(new ANEWARRAY(cpg.addClass(STRING)));   
        int namespaceArrayRef = cpg.addFieldref(_className,
                  STATIC_NAMESPACE_ARRAY_FIELD,
                  NAMESPACE_INDEX_SIG);
  il.append(new PUTSTATIC(namespaceArrayRef));
        staticConst.markChunkEnd();

  for (int i = 0; i < namespaces.size(); i++) {
      final String ns = (String)namespaces.elementAt(i);
            staticConst.markChunkStart();
      il.append(new GETSTATIC(namespaceArrayRef));
      il.append(new PUSH(cpg, i));
      il.append(new PUSH(cpg, ns));
      il.append(AASTORE);
            staticConst.markChunkEnd();
  }

        // Put the tree of stylesheet namespace declarations into the translet
        final Vector namespaceAncestors = getXSLTC().getNSAncestorPointers();
        if (namespaceAncestors != null && namespaceAncestors.size() != 0) {
            addStaticField(classGen, NS_ANCESTORS_INDEX_SIG,
                           STATIC_NS_ANCESTORS_ARRAY_FIELD);
            staticConst.markChunkStart();
            il.append(new PUSH(cpg, namespaceAncestors.size()));
            il.append(new NEWARRAY(BasicType.INT));
            int namespaceAncestorsArrayRef =
                    cpg.addFieldref(_className, STATIC_NS_ANCESTORS_ARRAY_FIELD,
                                    NS_ANCESTORS_INDEX_SIG);
            il.append(new PUTSTATIC(namespaceAncestorsArrayRef));
            staticConst.markChunkEnd();
            for (int i = 0; i < namespaceAncestors.size(); i++) {
                int ancestor = ((Integer) namespaceAncestors.get(i)).intValue();
                staticConst.markChunkStart();
                il.append(new GETSTATIC(namespaceAncestorsArrayRef));
                il.append(new PUSH(cpg, i));
                il.append(new PUSH(cpg, ancestor));
                il.append(IASTORE);
                staticConst.markChunkEnd();
            }
        }
        // Put the array of indices into the namespace prefix/URI pairs array
        // into the translet
        final Vector prefixURIPairsIdx = getXSLTC().getPrefixURIPairsIdx();
        if (prefixURIPairsIdx != null && prefixURIPairsIdx.size() != 0) {
            addStaticField(classGen, PREFIX_URIS_IDX_SIG,
                           STATIC_PREFIX_URIS_IDX_ARRAY_FIELD);
            staticConst.markChunkStart();
            il.append(new PUSH(cpg, prefixURIPairsIdx.size()));
            il.append(new NEWARRAY(BasicType.INT));
            int prefixURIPairsIdxArrayRef =
                        cpg.addFieldref(_className,
                                        STATIC_PREFIX_URIS_IDX_ARRAY_FIELD,
                                        PREFIX_URIS_IDX_SIG);
            il.append(new PUTSTATIC(prefixURIPairsIdxArrayRef));
            staticConst.markChunkEnd();
            for (int i = 0; i < prefixURIPairsIdx.size(); i++) {
                int idx = ((Integer) prefixURIPairsIdx.get(i)).intValue();
                staticConst.markChunkStart();
                il.append(new GETSTATIC(prefixURIPairsIdxArrayRef));
                il.append(new PUSH(cpg, i));
                il.append(new PUSH(cpg, idx));
                il.append(IASTORE);
                staticConst.markChunkEnd();
            }
        }

        // Put the array of pairs of namespace prefixes and URIs into the
        // translet
        final Vector prefixURIPairs = getXSLTC().getPrefixURIPairs();
        if (prefixURIPairs != null && prefixURIPairs.size() != 0) {
            addStaticField(classGen, PREFIX_URIS_ARRAY_SIG,
                    STATIC_PREFIX_URIS_ARRAY_FIELD);

            staticConst.markChunkStart();
            il.append(new PUSH(cpg, prefixURIPairs.size()));
            il.append(new ANEWARRAY(cpg.addClass(STRING)));
            int prefixURIPairsRef =
                        cpg.addFieldref(_className,
                                        STATIC_PREFIX_URIS_ARRAY_FIELD,
                                        PREFIX_URIS_ARRAY_SIG);
            il.append(new PUTSTATIC(prefixURIPairsRef));
            staticConst.markChunkEnd();
            for (int i = 0; i < prefixURIPairs.size(); i++) {
                String prefixOrURI = (String) prefixURIPairs.get(i);
                staticConst.markChunkStart();
                il.append(new GETSTATIC(prefixURIPairsRef));
                il.append(new PUSH(cpg, i));
                il.append(new PUSH(cpg, prefixOrURI));
                il.append(AASTORE);
                staticConst.markChunkEnd();
            }
        }

        // Grab all the literal text in the stylesheet and put it in a char[]
        final int charDataCount = getXSLTC().getCharacterDataCount();
        final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C");
        for (int i = 0; i < charDataCount; i++) {
            staticConst.markChunkStart();
            il.append(new PUSH(cpg, getXSLTC().getCharacterData(i)));
            il.append(new INVOKEVIRTUAL(toCharArray));
            il.append(new PUTSTATIC(cpg.addFieldref(_className,
                                               STATIC_CHAR_DATA_FIELD+i,
                                               STATIC_CHAR_DATA_FIELD_SIG)));
            staticConst.markChunkEnd();
        }

  il.append(RETURN);

  classGen.addMethod(staticConst);
     
    }

    /**
     * Compile the translet's constructor
     */
    private void compileConstructor(ClassGenerator classGen, Output output) {

  final ConstantPoolGen cpg = classGen.getConstantPool();
  final InstructionList il = new InstructionList();

  final MethodGenerator constructor =
      new MethodGenerator(ACC_PUBLIC,
        org.apache.bcel.generic.Type.VOID,
        null, null, "<init>",
        _className, il, cpg);

  // Call the constructor in the AbstractTranslet superclass
  il.append(classGen.loadTranslet());
  il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS,
                 "<init>", "()V")));
 
        constructor.markChunkStart();
  il.append(classGen.loadTranslet());
  il.append(new GETSTATIC(cpg.addFieldref(_className,
                                          STATIC_NAMES_ARRAY_FIELD,
                                          NAMES_INDEX_SIG)));
  il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
                                         NAMES_INDEX,
                                         NAMES_INDEX_SIG)));
        constructor.markChunkEnd();
 
        constructor.markChunkStart();
  il.append(classGen.loadTranslet());
  il.append(new GETSTATIC(cpg.addFieldref(_className,
                                          STATIC_URIS_ARRAY_FIELD,
                                          URIS_INDEX_SIG)));
  il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
                                         URIS_INDEX,
                                         URIS_INDEX_SIG)));
        constructor.markChunkEnd();

        constructor.markChunkStart();
  il.append(classGen.loadTranslet());
  il.append(new GETSTATIC(cpg.addFieldref(_className,
                                          STATIC_TYPES_ARRAY_FIELD,
                                          TYPES_INDEX_SIG)));
  il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
                                         TYPES_INDEX,
                                         TYPES_INDEX_SIG)));
        constructor.markChunkEnd();

        constructor.markChunkStart();
  il.append(classGen.loadTranslet());
  il.append(new GETSTATIC(cpg.addFieldref(_className,
                                          STATIC_NAMESPACE_ARRAY_FIELD,
                                          NAMESPACE_INDEX_SIG)));
  il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
                                         NAMESPACE_INDEX,
                                         NAMESPACE_INDEX_SIG)));
        constructor.markChunkEnd();

        constructor.markChunkStart();
  il.append(classGen.loadTranslet());
        il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION));
  il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
                                         TRANSLET_VERSION_INDEX,
                                         TRANSLET_VERSION_INDEX_SIG)));
        constructor.markChunkEnd();
 
  if (_hasIdCall) {
            constructor.markChunkStart();
      il.append(classGen.loadTranslet());
      il.append(new PUSH(cpg, Boolean.TRUE));
      il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
                     HASIDCALL_INDEX,
                     HASIDCALL_INDEX_SIG)));
            constructor.markChunkEnd();
  }
 
        // Compile in code to set the output configuration from <xsl:output>
  if (output != null) {
      // Set all the output settings files in the translet
            constructor.markChunkStart();
      output.translate(classGen, constructor);
            constructor.markChunkEnd();
  }

  // Compile default decimal formatting symbols.
  // This is an implicit, nameless xsl:decimal-format top-level element.
  if (_numberFormattingUsed) {
            constructor.markChunkStart();
      DecimalFormatting.translateDefaultDFS(classGen, constructor);
            constructor.markChunkEnd();
        }

  il.append(RETURN);

  classGen.addMethod(constructor);
    }

    /**
     * Compile a topLevel() method into the output class. This method is
     * called from transform() to handle all non-template top-level elements.
     * Returns the signature of the topLevel() method.
     *
     * Global variables/params and keys are first sorted to resolve
     * dependencies between them. The XSLT 1.0 spec does not allow a key
     * to depend on a variable. However, for compatibility with Xalan
     * interpretive, that type of dependency is allowed. Note also that
     * the buildKeys() method is still generated as it is used by the
     * LoadDocument class, but it no longer called from transform().
     */
    private String compileTopLevel(ClassGenerator classGen) {
  final ConstantPoolGen cpg = classGen.getConstantPool();

  final org.apache.bcel.generic.Type[] argTypes = {
      Util.getJCRefType(DOM_INTF_SIG),
      Util.getJCRefType(NODE_ITERATOR_SIG),
      Util.getJCRefType(TRANSLET_OUTPUT_SIG)
  };

  final String[] argNames = {
      DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME
  };

  final InstructionList il = new InstructionList();

  final MethodGenerator toplevel =
      new MethodGenerator(ACC_PUBLIC,
        org.apache.bcel.generic.Type.VOID,
        argTypes, argNames,
        "topLevel", _className, il,
        classGen.getConstantPool());

  toplevel.addException("org.apache.xalan.xsltc.TransletException");

  // Define and initialize 'current' variable with the root node
  final LocalVariableGen current =
      toplevel.addLocalVariable("current",
              org.apache.bcel.generic.Type.INT,
              null, null);

  final int setFilter = cpg.addInterfaceMethodref(DOM_INTF,
             "setFilter",
             "(Lorg/apache/xalan/xsltc/StripFilter;)V");

  final int gitr = cpg.addInterfaceMethodref(DOM_INTF,
              "getIterator",
              "()"+NODE_ITERATOR_SIG);
  il.append(toplevel.loadDOM());
  il.append(new INVOKEINTERFACE(gitr, 1));
        il.append(toplevel.nextNode());
  current.setStart(il.append(new ISTORE(current.getIndex())));

    // Create a new list containing variables/params + keys
    Vector varDepElements = new Vector(_globals);       
    Enumeration elements = elements();
    while (elements.hasMoreElements()) {
        final Object element = elements.nextElement();
        if (element instanceof Key) {
            varDepElements.add(element);
        }
    }
           
    // Determine a partial order for the variables/params and keys
    varDepElements = resolveDependencies(varDepElements);
   
    // Translate vars/params and keys in the right order
    final int count = varDepElements.size();
    for (int i = 0; i < count; i++) {
        final TopLevelElement tle = (TopLevelElement) varDepElements.elementAt(i);           
        tle.translate(classGen, toplevel);           
        if (tle instanceof Key) {
            final Key key = (Key) tle;
            _keys.put(key.getName(), key);
        }
    }

    // Compile code for other top-level elements
    Vector whitespaceRules = new Vector();
    elements = elements();
  while (elements.hasMoreElements()) {
      final Object element = elements.nextElement();
      // xsl:decimal-format
      if (element instanceof DecimalFormatting) {
    ((DecimalFormatting)element).translate(classGen,toplevel);
      }
      // xsl:strip/preserve-space
      else if (element instanceof Whitespace) {
    whitespaceRules.addAll(((Whitespace)element).getRules());
      }
  }

  // Translate all whitespace strip/preserve rules
  if (whitespaceRules.size() > 0) {
      Whitespace.translateRules(whitespaceRules,classGen);
  }

  if (classGen.containsMethod(STRIP_SPACE, STRIP_SPACE_PARAMS) != null) {
      il.append(toplevel.loadDOM());
      il.append(classGen.loadTranslet());
      il.append(new INVOKEINTERFACE(setFilter, 2));
  }

  il.append(RETURN);

  // Compute max locals + stack and add method to class
  classGen.addMethod(toplevel);
 
  return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V");
    }
   
    /**
     * This method returns a vector with variables/params and keys in the
     * order in which they are to be compiled for initialization. The order
     * is determined by analyzing the dependencies between them. The XSLT 1.0
     * spec does not allow a key to depend on a variable. However, for
     * compatibility with Xalan interpretive, that type of dependency is
     * allowed and, therefore, consider to determine the partial order.
     */
    private Vector resolveDependencies(Vector input) {
  /* DEBUG CODE - INGORE
  for (int i = 0; i < input.size(); i++) {
      final TopLevelElement e = (TopLevelElement) input.elementAt(i);
      System.out.println("e = " + e + " depends on:");
            Vector dep = e.getDependencies();
            for (int j = 0; j < (dep != null ? dep.size() : 0); j++) {
                System.out.println("\t" + dep.elementAt(j));
            }
  }
  System.out.println("================================="); 
        */

  Vector result = new Vector();
  while (input.size() > 0) {
      boolean changed = false;
      for (int i = 0; i < input.size(); ) {
    final TopLevelElement vde = (TopLevelElement) input.elementAt(i);
    final Vector dep = vde.getDependencies();
    if (dep == null || result.containsAll(dep)) {
        result.addElement(vde);
        input.remove(i);
        changed = true;
    }
    else {
        i++;
    }
      }

      // If nothing was changed in this pass then we have a circular ref
      if (!changed) {
    ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR,
              input.toString(), this);
    getParser().reportError(Constants.ERROR, err);
    return(result);
      }
  }

  /* DEBUG CODE - INGORE
  System.out.println("=================================");
  for (int i = 0; i < result.size(); i++) {
      final TopLevelElement e = (TopLevelElement) result.elementAt(i);
      System.out.println("e = " + e);
  }
        */

  return result;
    }

    /**
     * Compile a buildKeys() method into the output class. Note that keys
     * for the input document are created in topLevel(), not in this method.
     * However, we still need this method to create keys for documents loaded
     * via the XPath document() function.
     */
    private String compileBuildKeys(ClassGenerator classGen) {
  final ConstantPoolGen cpg = classGen.getConstantPool();

  final org.apache.bcel.generic.Type[] argTypes = {
      Util.getJCRefType(DOM_INTF_SIG),
      Util.getJCRefType(NODE_ITERATOR_SIG),
      Util.getJCRefType(TRANSLET_OUTPUT_SIG),
      org.apache.bcel.generic.Type.INT
  };

  final String[] argNames = {
      DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME, "current"
  };

  final InstructionList il = new InstructionList();

  final MethodGenerator buildKeys =
      new MethodGenerator(ACC_PUBLIC,
        org.apache.bcel.generic.Type.VOID,
        argTypes, argNames,
        "buildKeys", _className, il,
        classGen.getConstantPool());

  buildKeys.addException("org.apache.xalan.xsltc.TransletException");
 
  final Enumeration elements = elements();
  while (elements.hasMoreElements()) {
      // xsl:key
      final Object element = elements.nextElement();
      if (element instanceof Key) {
    final Key key = (Key)element;
    key.translate(classGen, buildKeys);
    _keys.put(key.getName(),key);
      }
  }
 
  il.append(RETURN);
 
  // Add method to class
        classGen.addMethod(buildKeys);
 
  return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+"I)V");
    }

    /**
     * Compile transform() into the output class. This method is used to
     * initialize global variables and global parameters. The current node
     * is set to be the document's root node.
     */
    private void compileTransform(ClassGenerator classGen) {
  final ConstantPoolGen cpg = classGen.getConstantPool();

  /*
   * Define the the method transform with the following signature:
   * void transform(DOM, NodeIterator, HandlerBase)
   */
  final org.apache.bcel.generic.Type[] argTypes =
      new org.apache.bcel.generic.Type[3];
  argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
  argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
  argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);

  final String[] argNames = new String[3];
  argNames[0] = DOCUMENT_PNAME;
  argNames[1] = ITERATOR_PNAME;
  argNames[2] = TRANSLET_OUTPUT_PNAME;

  final InstructionList il = new InstructionList();
  final MethodGenerator transf =
      new MethodGenerator(ACC_PUBLIC,
        org.apache.bcel.generic.Type.VOID,
        argTypes, argNames,
        "transform",
        _className,
        il,
        classGen.getConstantPool());
  transf.addException("org.apache.xalan.xsltc.TransletException");

  // Define and initialize current with the root node
  final LocalVariableGen current =
      transf.addLocalVariable("current",
            org.apache.bcel.generic.Type.INT,
            null, null);
  final String applyTemplatesSig = classGen.getApplyTemplatesSig();
  final int applyTemplates = cpg.addMethodref(getClassName(),
                "applyTemplates",
                applyTemplatesSig);
  final int domField = cpg.addFieldref(getClassName(),
               DOM_FIELD,
               DOM_INTF_SIG);

  // push translet for PUTFIELD
  il.append(classGen.loadTranslet());
  // prepare appropriate DOM implementation
 
  if (isMultiDocument()) {
      il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS)));
      il.append(DUP);
  }
 
  il.append(classGen.loadTranslet());
  il.append(transf.loadDOM());
  il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
                 "makeDOMAdapter",
                 "("+DOM_INTF_SIG+")"+
                 DOM_ADAPTER_SIG)));
  // DOMAdapter is on the stack

  if (isMultiDocument()) {
      final int init = cpg.addMethodref(MULTI_DOM_CLASS,
                "<init>",
                "("+DOM_INTF_SIG+")V");
      il.append(new INVOKESPECIAL(init));
      // MultiDOM is on the stack
  }
 
  //store to _dom variable
  il.append(new PUTFIELD(domField));

  // continue with globals initialization
  final int gitr = cpg.addInterfaceMethodref(DOM_INTF,
              "getIterator",
              "()"+NODE_ITERATOR_SIG);
  il.append(transf.loadDOM());
  il.append(new INVOKEINTERFACE(gitr, 1));
        il.append(transf.nextNode());
  current.setStart(il.append(new ISTORE(current.getIndex())));

  // Transfer the output settings to the output post-processor
  il.append(classGen.loadTranslet());
  il.append(transf.loadHandler());
  final int index = cpg.addMethodref(TRANSLET_CLASS,
             "transferOutputSettings",
             "("+OUTPUT_HANDLER_SIG+")V");
  il.append(new INVOKEVIRTUAL(index));

        /*
         * Compile buildKeys() method. Note that this method is not
         * invoked here as keys for the input document are now created
         * in topLevel(). However, this method is still needed by the
         * LoadDocument class.
         */       
        final String keySig = compileBuildKeys(classGen);
        final int keyIdx = cpg.addMethodref(getClassName(),
                                               "buildKeys", keySig);
               
        // Look for top-level elements that need handling
  final Enumeration toplevel = elements();
  if (_globals.size() > 0 || toplevel.hasMoreElements()) {
      // Compile method for handling top-level elements
      final String topLevelSig = compileTopLevel(classGen);
      // Get a reference to that method
      final int topLevelIdx = cpg.addMethodref(getClassName(),
                 "topLevel",
                 topLevelSig);
      // Push all parameters on the stack and call topLevel()
      il.append(classGen.loadTranslet()); // The 'this' pointer
      il.append(classGen.loadTranslet());
      il.append(new GETFIELD(domField))// The DOM reference
      il.append(transf.loadIterator());
      il.append(transf.loadHandler());    // The output handler
      il.append(new INVOKEVIRTUAL(topLevelIdx));
 

  // start document
  il.append(transf.loadHandler());
  il.append(transf.startDocument());

  // push first arg for applyTemplates
  il.append(classGen.loadTranslet());
  // push translet for GETFIELD to get DOM arg
  il.append(classGen.loadTranslet());
  il.append(new GETFIELD(domField));
  // push remaining 2 args
  il.append(transf.loadIterator());
  il.append(transf.loadHandler());
  il.append(new INVOKEVIRTUAL(applyTemplates));
  // endDocument
  il.append(transf.loadHandler());
  il.append(transf.endDocument());

  il.append(RETURN);

  // Compute max locals + stack and add method to class
  classGen.addMethod(transf);
    }

    /**
     * Peephole optimization: Remove sequences of [ALOAD, POP].
     */
    private void peepHoleOptimization(MethodGenerator methodGen) {
  final String pattern = "`aload'`pop'`instruction'";
  final InstructionList il = methodGen.getInstructionList();
  final InstructionFinder find = new InstructionFinder(il);
  for(Iterator iter=find.search(pattern); iter.hasNext(); ) {
      InstructionHandle[] match = (InstructionHandle[])iter.next();
      try {
    il.delete(match[0], match[1]);
      }
      catch (TargetLostException e) {
              // TODO: move target down into the list
            }
  }
    }

    public int addParam(Param param) {
  _globals.addElement(param);
  return _globals.size() - 1;
    }

    public int addVariable(Variable global) {
  _globals.addElement(global);
  return _globals.size() - 1;
    }

    public void display(int indent) {
  indent(indent);
  Util.println("Stylesheet");
  displayContents(indent + IndentIncrement);
    }

    // do we need this wrapper ?????
    public String getNamespace(String prefix) {
  return lookupNamespace(prefix);
    }

    public String getClassName() {
  return _className;
    }

    public Vector getTemplates() {
  return _templates;
    }

    public Vector getAllValidTemplates() {
        // Return templates if no imported/included stylesheets
        if (_includedStylesheets == null) {
            return _templates;
        }
       
        // Is returned value cached?
        if (_allValidTemplates == null) {
           Vector templates = new Vector();
            int size = _includedStylesheets.size();
            for (int i = 0; i < size; i++) {
                Stylesheet included =(Stylesheet)_includedStylesheets.elementAt(i);
                templates.addAll(included.getAllValidTemplates());
            }
            templates.addAll(_templates);

            // Cache results in top-level stylesheet only
            if (_parentStylesheet != null) {
                return templates;
            }
            _allValidTemplates = templates;
         }
       
        return _allValidTemplates;
    }
   
    protected void addTemplate(Template template) {
        _templates.addElement(template);
    }
}
TOP

Related Classes of org.apache.xalan.xsltc.compiler.Stylesheet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.