📄 syntaxtreenode.java
字号:
/* * 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.6 2006/06/06 22:34:33 spericas 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 com.sun.org.apache.xalan.internal.xsltc.runtime.AttributeList;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 AttributeList _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(AttributeList 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 String getAttribute(String prefix, String localName) { return getAttribute(prefix + ':' + localName); } protected boolean hasAttribute(String qname) { return (_attributes != null && _attributes.getValue(qname) != null); } protected void addAttribute(String qname, String value) { _attributes.add(qname, value); } /** * 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, if unset. For * re-parenting just use <code>node._parent = newparent</code>. * * @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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -