- /*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed 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: SyntaxTreeNode.java,v 1.29 2004/02/16 22:25:10 minchau Exp $
- */
-
- package com.sun.org.apache.xalan.internal.xsltc.compiler;
-
- import java.util.Enumeration;
- import java.util.Hashtable;
- import java.util.Vector;
-
- import com.sun.org.apache.bcel.internal.generic.ANEWARRAY;
- import com.sun.org.apache.bcel.internal.generic.BasicType;
- import com.sun.org.apache.bcel.internal.generic.CHECKCAST;
- import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
- import com.sun.org.apache.bcel.internal.generic.DUP_X1;
- import com.sun.org.apache.bcel.internal.generic.GETFIELD;
- import com.sun.org.apache.bcel.internal.generic.ICONST;
- import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
- import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
- import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
- import com.sun.org.apache.bcel.internal.generic.InstructionList;
- import com.sun.org.apache.bcel.internal.generic.NEW;
- import com.sun.org.apache.bcel.internal.generic.NEWARRAY;
- import com.sun.org.apache.bcel.internal.generic.PUSH;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
- import com.sun.org.apache.xalan.internal.xsltc.DOM;
-
- import org.xml.sax.Attributes;
-
-
- /**
- * @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>
- */
- 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. If unavailable, lookup
- * in ancestors.
- *
- * @return The source file line number.
- */
- public final int getLineNumber() {
- if (_line > 0) return _line;
- SyntaxTreeNode parent = getParent();
- return (parent != null) ? parent.getLineNumber() : 0;
- }
-
- /**
- * 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 com.sun.org.apache.xalan.internal.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);
- }
-
- }