/*
 * @(#)$Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Sun
 * Microsystems., http://www.sun.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 * @author G. Todd Miller
 * @author Morten Jorensen
 * @author Erwin Bolwidt <ejb@klomp.org>
 * @author John Howard <JohnH@schemasoft.com>
 *
 */

package org.apache.xalan.xsltc.compiler;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.apache.bcel.generic.ANEWARRAY;
import org.apache.bcel.generic.BasicType;
import org.apache.bcel.generic.CHECKCAST;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.DUP_X1;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.ICONST;
import org.apache.bcel.generic.INVOKEINTERFACE;
import org.apache.bcel.generic.INVOKESPECIAL;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.NEW;
import org.apache.bcel.generic.NEWARRAY;
import org.apache.bcel.generic.PUSH;
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.DOM;

import org.xml.sax.Attributes;


public abstract class SyntaxTreeNode implements Constants {

    // Reference to the AST parser
    private Parser _parser;

    // AST navigation pointers
    protected SyntaxTreeNode _parent;          // Parent node
    private Stylesheet       _stylesheet;      // Stylesheet ancestor node
    private Template         _template;        // Template ancestor node
    private final Vector _contents = new Vector(2); // Child nodes

    // Element description data
    protected QName _qname;                    // The element QName
    private int _line;                         // Source file line number
    protected Attributes _attributes = null;   // Attributes of this element
    private   Hashtable _prefixMapping = null; // Namespace declarations

    // Sentinel - used to denote unrecognised syntaxt tree nodes.
    protected static final SyntaxTreeNode Dummy = new AbsolutePathPattern(null);

    // These two are used for indenting nodes in the AST (debug output)
    protected static final int IndentIncrement = 4;
    private static final char[] _spaces = 
	"                                                       ".toCharArray();

    /**
     * Creates a new SyntaxTreeNode with a 'null' QName and no source file
     * line number reference.
     */
    public SyntaxTreeNode() {
	_line = 0;
	_qname = null;
    }

    /**
     * Creates a new SyntaxTreeNode with a 'null' QName.
     * @param line Source file line number reference
     */
    public SyntaxTreeNode(int line) {
	_line = line;
	_qname = null;
    }

    /**
     * Creates a new SyntaxTreeNode with no source file line number reference.
     * @param uri The element's namespace URI
     * @param prefix The element's namespace prefix
     * @param local The element's local name
     */
    public SyntaxTreeNode(String uri, String prefix, String local) {
	_line = 0;
	setQName(uri, prefix, local);
    }

    /**
     * Set the source file line number for this element
     * @param line The source file line number.
     */
    protected final void setLineNumber(int line) {
	_line = line;
    }

    /**
     * Get the source file line number for this element
     * @return The source file line number.
     */
    public final int getLineNumber() {
	return _line;
    }

    /**
     * Set the QName for the syntax tree node.
     * @param qname The QName for the syntax tree node
     */
    protected void setQName(QName qname) {
	_qname = qname;
    }

    /**
     * Set the QName for the SyntaxTreeNode
     * @param uri The element's namespace URI
     * @param prefix The element's namespace prefix
     * @param local The element's local name
     */
    protected void setQName(String uri, String prefix, String localname) {
	_qname = new QName(uri, prefix, localname);
    }

    /**
     * Set the QName for the SyntaxTreeNode
     * @param qname The QName for the syntax tree node
     */
    protected QName getQName() {
	return(_qname);
    }

    /**
     * Set the attributes for this SyntaxTreeNode.
     * @param attributes Attributes for the element. Must be passed in as an
     *                   implementation of org.xml.sax.Attributes.
     */
    protected void setAttributes(Attributes attributes) {
	_attributes = attributes;
    }

    /**
     * Returns a value for an attribute from the source element.
     * @param qname The QName of the attribute to return.
     * @return The value of the attribute of name 'qname'.
     */
    protected String getAttribute(String qname) {
	if (_attributes == null) {
	    return EMPTYSTRING;
	}
	final String value = _attributes.getValue(qname);
	return (value == null || value.equals(EMPTYSTRING)) ? 
	    EMPTYSTRING : value;
    }

    protected boolean hasAttribute(String qname) {
	return (_attributes != null && _attributes.getValue(qname) != null);
    }

    /**
     * Returns a list of all attributes declared for the element represented by
     * this syntax tree node.
     * @return Attributes for this syntax tree node
     */
    protected Attributes getAttributes() {
	return(_attributes);
    }

    /**
     * Sets the prefix mapping for the namespaces that were declared in this
     * element. This does not include all prefix mappings in scope, so one
     * may have to check ancestor elements to get all mappings that are in
     * in scope. The prefixes must be passed in as a Hashtable that maps
     * namespace prefixes (String objects) to namespace URIs (also String).
     * @param mapping The Hashtable containing the mappings.
     */
    protected void setPrefixMapping(Hashtable mapping) {
	_prefixMapping = mapping;
    }

    /**
     * Returns a Hashtable containing the prefix mappings that were declared
     * for this element. This does not include all prefix mappings in scope,
     * so one may have to check ancestor elements to get all mappings that are
     * in in scope. 
     * @return Prefix mappings (for this element only).
     */
    protected Hashtable getPrefixMapping() {
	return _prefixMapping;
    }

    /**
     * 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 (_prefixMapping == null)
	    _prefixMapping = new Hashtable();
	_prefixMapping.put(prefix, uri);
    }

    /**
     * Returns any namespace URI that is in scope for a given prefix. This
     * method checks namespace mappings for this element, and if necessary
     * for ancestor elements as well (ie. if the prefix maps to an URI in this
     * scope then you'll definately get the URI from this method).
     * @param prefix Namespace prefix.
     * @return Namespace URI.
     */
    protected String lookupNamespace(String prefix) {
	// Initialise the output (default is 'null' for undefined)
	String uri = null;

	// First look up the prefix/uri mapping in our own hashtable...
	if (_prefixMapping != null)
	    uri = (String)_prefixMapping.get(prefix);
	// ... but if we can't find it there we ask our parent for the mapping
	if ((uri == null) && (_parent != null)) {
	    uri = _parent.lookupNamespace(prefix);
	    if ((prefix == Constants.EMPTYSTRING) && (uri == null))
		uri = Constants.EMPTYSTRING;
	}
	// ... and then we return whatever URI we've got.
	return(uri);
    }

    /**
     * Returns any namespace prefix that is mapped to a prefix in the current
     * scope. This method checks namespace mappings for this element, and if
     * necessary for ancestor elements as well (ie. if the URI is declared
     * within the current scope then you'll definately get the prefix from
     * this method). Note that this is a very slow method and consequentially
     * it should only be used strictly when needed.
     * @param uri Namespace URI.
     * @return Namespace prefix.
     */
    protected String lookupPrefix(String uri) {
	// Initialise the output (default is 'null' for undefined)
	String prefix = null;

	// First look up the prefix/uri mapping in our own hashtable...
	if ((_prefixMapping != null) &&
	    (_prefixMapping.contains(uri))) {
	    Enumeration prefixes = _prefixMapping.keys();
	    while (prefixes.hasMoreElements()) {
		prefix = (String)prefixes.nextElement();
		String mapsTo = (String)_prefixMapping.get(prefix);
		if (mapsTo.equals(uri)) return(prefix);
	    }
	}
	// ... but if we can't find it there we ask our parent for the mapping
	else if (_parent != null) {
	    prefix = _parent.lookupPrefix(uri);
	    if ((uri == Constants.EMPTYSTRING) && (prefix == null))
		prefix = Constants.EMPTYSTRING;
	}
	return(prefix);
    }

    /**
     * Set this node's parser. The parser (the XSLT parser) gives this
     * syntax tree node access to the symbol table and XPath parser.
     * @param parser The XSLT parser.
     */
    protected void setParser(Parser parser) {
	_parser = parser;
    }

    /**
     * Returns this node's XSLT parser.
     * @return The XSLT parser.
     */
    public final Parser getParser() {
	return _parser;
    }

    /**
     * Set this syntax tree node's parent node
     * @param parent The parent node.
     */
    protected void setParent(SyntaxTreeNode parent) {
	if (_parent == null)
	    _parent = parent;
    }

    /**
     * Returns this syntax tree node's parent node.
     * @return The parent syntax tree node.
     */
    protected final SyntaxTreeNode getParent() {
	return _parent;
    }

    /**
     * Returns 'true' if this syntax tree node is the Sentinal node.
     * @return 'true' if this syntax tree node is the Sentinal node.
     */
    protected final boolean isDummy() {
        return this == Dummy;
    }

    /**
     * Get the import precedence of this element. The import precedence equals
     * the import precedence of the stylesheet in which this element occured.
     * @return The import precedence of this syntax tree node.
     */
    protected int getImportPrecedence() {
	Stylesheet stylesheet = getStylesheet();
	if (stylesheet == null) return Integer.MIN_VALUE;
	return stylesheet.getImportPrecedence();
    }

    /**
     * Get the Stylesheet node that represents the <xsl:stylesheet/> element
     * that this node occured under.
     * @return The Stylesheet ancestor node of this node.
     */
    public Stylesheet getStylesheet() {
	if (_stylesheet == null) {
	    SyntaxTreeNode parent = this;
	    while (parent != null) {
		if (parent instanceof Stylesheet)
		    return((Stylesheet)parent);
		parent = parent.getParent();
	    }
	    _stylesheet = (Stylesheet)parent;
	}
	return(_stylesheet);
    }

    /**
     * Get the Template node that represents the <xsl:template/> element
     * that this node occured under. Note that this method will return 'null'
     * for nodes that represent top-level elements.
     * @return The Template ancestor node of this node or 'null'.
     */
    protected Template getTemplate() {
	if (_template == null) {
	    SyntaxTreeNode parent = this;
	    while ((parent != null) && (!(parent instanceof Template)))
		parent = parent.getParent();
	    _template = (Template)parent;
	}
	return(_template);
    }

    /**
     * Returns a reference to the XSLTC (XSLT compiler) in use.
     * @return XSLTC - XSLT compiler.
     */
    protected final XSLTC getXSLTC() {
	return _parser.getXSLTC();
    }

    /**
     * Returns the XSLT parser's symbol table.
     * @return Symbol table.
     */
    protected final SymbolTable getSymbolTable() {
	return (_parser == null) ? null : _parser.getSymbolTable();
    }

    /**
     * Parse the contents of this syntax tree nodes (child nodes, XPath
     * expressions, patterns and functions). The default behaviour is to parser
     * the syntax tree node's children (since there are no common expressions,
     * patterns, etc. that can be handled in this base class.
     * @param parser reference to the XSLT parser
     */
    public void parseContents(Parser parser) {
	parseChildren(parser);
    }

    /**
     * Parse all children of this syntax tree node. This method is normally
     * called by the parseContents() method.
     * @param parser reference to the XSLT parser
     */
    protected final void parseChildren(Parser parser) {

	Vector locals = null;	// only create when needed
	
	final int count = _contents.size();
	for (int i=0; i<count; i++) {
	    SyntaxTreeNode child = (SyntaxTreeNode)_contents.elementAt(i);
	    parser.getSymbolTable().setCurrentNode(child);
	    child.parseContents(parser);
	    // if variable or parameter, add it to scope
	    final QName varOrParamName = updateScope(parser, child);
	    if (varOrParamName != null) {
		if (locals == null) {
		    locals = new Vector(2);
		}
		locals.addElement(varOrParamName);
	    }
	}

	parser.getSymbolTable().setCurrentNode(this);

	// after the last element, remove any locals from scope
	if (locals != null) {
	    final int nLocals = locals.size();
	    for (int i = 0; i < nLocals; i++) {
		parser.removeVariable((QName)locals.elementAt(i));
	    }
	}
    }
   
    /**
     * Add a node to the current scope and return name of a variable or
     * parameter if the node represents a variable or a parameter.
     */
    protected QName updateScope(Parser parser, SyntaxTreeNode node) {
	if (node instanceof Variable) {
	    final Variable var = (Variable)node;
	    parser.addVariable(var);
	    return var.getName();
	}
	else if (node instanceof Param) {
	    final Param param = (Param)node;
	    parser.addParameter(param);
	    return param.getName();
	}
	else {
	    return null;
	}
    }

    /**
     * Type check the children of this node. The type check phase may add
     * coercions (CastExpr) to the AST.
     * @param stable The compiler/parser's symbol table
     */
    public abstract Type typeCheck(SymbolTable stable) throws TypeCheckError;

    /**
     * Call typeCheck() on all child syntax tree nodes.
     * @param stable The compiler/parser's symbol table
     */
    protected Type typeCheckContents(SymbolTable stable) throws TypeCheckError {
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    item.typeCheck(stable);
	}
	return Type.Void;
    }

    /**
     * Translate this abstract syntax tree node into JVM bytecodes.
     * @param classGen BCEL Java class generator
     * @param methodGen BCEL Java method generator
     */
    public abstract void translate(ClassGenerator classGen,
				   MethodGenerator methodGen);

    /**
     * Call translate() on all child syntax tree nodes.
     * @param classGen BCEL Java class generator
     * @param methodGen BCEL Java method generator
     */
    protected void translateContents(ClassGenerator classGen,
				     MethodGenerator methodGen) {
	// Call translate() on all child nodes
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    item.translate(classGen, methodGen);
	}

	// After translation, unmap any registers for any variables/parameters
	// that were declared in this scope. Performing this unmapping in the
	// same AST scope as the declaration deals with the problems of
	// references falling out-of-scope inside the for-each element.
	// (the cause of which being 'lazy' register allocation for references)
	for (int i = 0; i < n; i++) {
	    if( _contents.elementAt(i) instanceof VariableBase) {
		final VariableBase var = (VariableBase)_contents.elementAt(i);
		var.unmapRegister(methodGen);
	    }
	}
    }
    
    /**
     * Return true if the node represents a simple RTF.
     *
     * A node is a simple RTF if all children only produce Text value.
     *
     * @param node A node
     * @return true if the node content can be considered as a simple RTF.
     */
    private boolean isSimpleRTF(SyntaxTreeNode node) {
        
        Vector contents = node.getContents();
        for (int i = 0; i < contents.size(); i++) {
            SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
            if (!isTextElement(item, false))
                return false;
        }
        
        return true;
    }
 
     /**
     * Return true if the node represents an adaptive RTF.
     *
     * A node is an adaptive RTF if each children is a Text element
     * or it is <xsl:call-template> or <xsl:apply-templates>.
     *
     * @param node A node
     * @return true if the node content can be considered as an adaptive RTF.
     */
    private boolean isAdaptiveRTF(SyntaxTreeNode node) {
        
        Vector contents = node.getContents();
        for (int i = 0; i < contents.size(); i++) {
            SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
            if (!isTextElement(item, true))
                return false;
        }
        
        return true;
    }
   
    /**
     * Return true if the node only produces Text content.
     *
     * A node is a Text element if it is Text, xsl:value-of, xsl:number, 
     * or a combination of these nested in a control instruction (xsl:if or
     * xsl:choose).
     *
     * If the doExtendedCheck flag is true, xsl:call-template and xsl:apply-templates
     * are also considered as Text elements.
     *
     * @param node A node
     * @param doExtendedCheck If this flag is true, <xsl:call-template> and 
     * <xsl:apply-templates> are also considered as Text elements.
     *
     * @return true if the node of Text type
     */
    private boolean isTextElement(SyntaxTreeNode node, boolean doExtendedCheck) {
        if (node instanceof ValueOf || node instanceof Number
            || node instanceof Text)
        {
            return true;
        }
        else if (node instanceof If) {
            return doExtendedCheck ? isAdaptiveRTF(node) : isSimpleRTF(node);
        }
        else if (node instanceof Choose) {
            Vector contents = node.getContents();
            for (int i = 0; i < contents.size(); i++) {
                SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i);
                if (item instanceof Text || 
                     ((item instanceof When || item instanceof Otherwise)
                     && ((doExtendedCheck && isAdaptiveRTF(item))
                         || (!doExtendedCheck && isSimpleRTF(item)))))
                    continue;
                else
                    return false;
            }
            return true;
        }
        else if (doExtendedCheck && 
                  (node instanceof CallTemplate
                   || node instanceof ApplyTemplates))
            return true;
        else
            return false;
    }

    /**
     * Utility method used by parameters and variables to store result trees
     * @param classGen BCEL Java class generator
     * @param methodGen BCEL Java method generator
     */
    protected void compileResultTree(ClassGenerator classGen,
				     MethodGenerator methodGen) 
    {
	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = methodGen.getInstructionList();
	final Stylesheet stylesheet = classGen.getStylesheet();

	boolean isSimple = isSimpleRTF(this);
	boolean isAdaptive = false;
	if (!isSimple) {
	    isAdaptive = isAdaptiveRTF(this);
	}
	
	int rtfType = isSimple ? DOM.SIMPLE_RTF
	                       : (isAdaptive ? DOM.ADAPTIVE_RTF : DOM.TREE_RTF);
	
	// Save the current handler base on the stack
	il.append(methodGen.loadHandler());

	final String DOM_CLASS = classGen.getDOMClass();

	// Create new instance of DOM class (with RTF_INITIAL_SIZE nodes)
	//int index = cpg.addMethodref(DOM_IMPL, "<init>", "(I)V");
	//il.append(new NEW(cpg.addClass(DOM_IMPL)));
	
	il.append(methodGen.loadDOM());
	int index = cpg.addInterfaceMethodref(DOM_INTF,
				 "getResultTreeFrag",
				 "(IIZ)" + DOM_INTF_SIG);
	il.append(new PUSH(cpg, RTF_INITIAL_SIZE));
	il.append(new PUSH(cpg, rtfType));
	il.append(new PUSH(cpg, stylesheet.callsNodeset()));
	il.append(new INVOKEINTERFACE(index,4));
	
	il.append(DUP);

	// Overwrite old handler with DOM handler
	index = cpg.addInterfaceMethodref(DOM_INTF,
				 "getOutputDomBuilder",
				 "()" + TRANSLET_OUTPUT_SIG);

	il.append(new INVOKEINTERFACE(index,1));
	il.append(DUP);
	il.append(methodGen.storeHandler());

	// Call startDocument on the new handler
	il.append(methodGen.startDocument());

	// Instantiate result tree fragment
	translateContents(classGen, methodGen);

	// Call endDocument on the new handler
	il.append(methodGen.loadHandler());
	il.append(methodGen.endDocument());

	// Check if we need to wrap the DOMImpl object in a DOMAdapter object.
	// DOMAdapter is not needed if the RTF is a simple RTF and the nodeset()
	// function is not used.
	if (stylesheet.callsNodeset()
	    && !DOM_CLASS.equals(DOM_IMPL_CLASS)) {
	    // new org.apache.xalan.xsltc.dom.DOMAdapter(DOMImpl,String[]);
	    index = cpg.addMethodref(DOM_ADAPTER_CLASS,
				     "<init>",
				     "("+DOM_INTF_SIG+
				     "["+STRING_SIG+
				     "["+STRING_SIG+
				     "[I"+
				     "["+STRING_SIG+")V");
	    il.append(new NEW(cpg.addClass(DOM_ADAPTER_CLASS)));
	    il.append(new DUP_X1());
	    il.append(SWAP);

	    /*
	     * Give the DOM adapter an empty type mapping if the nodeset
	     * extension function is never called.
	     */
	    if (!stylesheet.callsNodeset()) {
		il.append(new ICONST(0));
		il.append(new ANEWARRAY(cpg.addClass(STRING)));
		il.append(DUP);
		il.append(DUP);
		il.append(new ICONST(0));
		il.append(new NEWARRAY(BasicType.INT));
		il.append(SWAP);
		il.append(new INVOKESPECIAL(index));
	    }
	    else {
		// Push name arrays on the stack
		il.append(ALOAD_0);
		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
					   NAMES_INDEX,
					   NAMES_INDEX_SIG))); 
		il.append(ALOAD_0);
		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
					   URIS_INDEX,
					   URIS_INDEX_SIG))); 
		il.append(ALOAD_0);
		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
					   TYPES_INDEX,
					   TYPES_INDEX_SIG))); 
		il.append(ALOAD_0);
		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
					   NAMESPACE_INDEX,
					   NAMESPACE_INDEX_SIG)));

		// Initialized DOM adapter
		il.append(new INVOKESPECIAL(index));

		// Add DOM adapter to MultiDOM class by calling addDOMAdapter()
		il.append(DUP);
		il.append(methodGen.loadDOM());
		il.append(new CHECKCAST(cpg.addClass(classGen.getDOMClass())));
		il.append(SWAP);
		index = cpg.addMethodref(MULTI_DOM_CLASS,
					 "addDOMAdapter",
					 "(" + DOM_ADAPTER_SIG + ")I");
		il.append(new INVOKEVIRTUAL(index));
		il.append(POP);		// ignore mask returned by addDOMAdapter
	    }
	}

	// Restore old handler base from stack
	il.append(SWAP);
	il.append(methodGen.storeHandler());
    }

    /**
     * Returns true if this expression/instruction depends on the context. By 
     * default, every expression/instruction depends on the context unless it 
     * overrides this method. Currently used to determine if result trees are 
     * compiled using procedures or little DOMs (result tree fragments).
     * @return 'true' if this node depends on the context.
     */
    protected boolean contextDependent() {
	return true;
    }

    /**
     * Return true if any of the expressions/instructions in the contents of
     * this node is context dependent.
     * @return 'true' if the contents of this node is context dependent.
     */
    protected boolean dependentContents() {
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    if (item.contextDependent()) {
		return true;
	    }
	}
	return false;
    }

    /**
     * Adds a child node to this syntax tree node.
     * @param element is the new child node.
     */
    protected final void addElement(SyntaxTreeNode element) {
	_contents.addElement(element);
	element.setParent(this);
    }

    /**
     * Inserts the first child node of this syntax tree node. The existing
     * children are shifted back one position.
     * @param element is the new child node.
     */
    protected final void setFirstElement(SyntaxTreeNode element) {
	_contents.insertElementAt(element,0);
	element.setParent(this);
    }

    /**
     * Removed a child node of this syntax tree node.
     * @param element is the child node to remove.
     */
    protected final void removeElement(SyntaxTreeNode element) {
	_contents.remove(element);
	element.setParent(null);
    }

    /**
     * Returns a Vector containing all the child nodes of this node.
     * @return A Vector containing all the child nodes of this node.
     */
    protected final Vector getContents() {
	return _contents;
    }

    /**
     * Tells you if this node has any child nodes.
     * @return 'true' if this node has any children.
     */
    protected final boolean hasContents() {
	return elementCount() > 0;
    }

    /**
     * Returns the number of children this node has.
     * @return Number of child nodes.
     */
    protected final int elementCount() {
	return _contents.size();
    }

    /**
     * Returns an Enumeration of all child nodes of this node.
     * @return An Enumeration of all child nodes of this node.
     */
    protected final Enumeration elements() {
	return _contents.elements();
    }

    /**
     * Returns a child node at a given position.
     * @param pos The child node's position.
     * @return The child node.
     */
    protected final Object elementAt(int pos) {
	return _contents.elementAt(pos);
    }

    /**
     * Returns this element's last child
     * @return The child node.
     */
    protected final SyntaxTreeNode lastChild() {
	if (_contents.size() == 0) return null;
	return (SyntaxTreeNode)_contents.lastElement();
    }

    /**
     * Displays the contents of this syntax tree node (to stdout).
     * This method is intended for debugging _only_, and should be overridden
     * by all syntax tree node implementations.
     * @param indent Indentation level for syntax tree levels.
     */
    public void display(int indent) {
	displayContents(indent);
    }

    /**
     * Displays the contents of this syntax tree node (to stdout).
     * This method is intended for debugging _only_ !!!
     * @param indent Indentation level for syntax tree levels.
     */
    protected void displayContents(int indent) {
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    item.display(indent);
	}
    }

    /**
     * Set the indentation level for debug output.
     * @param indent Indentation level for syntax tree levels.
     */
    protected final void indent(int indent) {
	System.out.print(new String(_spaces, 0, indent));
    }

    /**
     * Report an error to the parser.
     * @param element The element in which the error occured (normally 'this'
     * but it could also be an expression/pattern/etc.)
     * @param parser The XSLT parser to report the error to.
     * @param error The error code (from util/ErrorMsg).
     * @param message Any additional error message.
     */
    protected void reportError(SyntaxTreeNode element, Parser parser,
			       String errorCode, String message) {
	final ErrorMsg error = new ErrorMsg(errorCode, message, element);
        parser.reportError(Constants.ERROR, error);
    }

    /**
     * Report a recoverable error to the parser.
     * @param element The element in which the error occured (normally 'this'
     * but it could also be an expression/pattern/etc.)
     * @param parser The XSLT parser to report the error to.
     * @param error The error code (from util/ErrorMsg).
     * @param message Any additional error message.
     */
    protected  void reportWarning(SyntaxTreeNode element, Parser parser,
				  String errorCode, String message) {
	final ErrorMsg error = new ErrorMsg(errorCode, message, element);
        parser.reportError(Constants.WARNING, error);
    }

}
