keytable.java

来自「java jdk 1.4的源码」· Java 代码 · 共 298 行

JAVA
298
字号
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999 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) 1999, Lotus * Development Corporation., http://www.lotus.com.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */package org.apache.xalan.transformer;import java.util.Hashtable;import java.util.Vector;import javax.xml.transform.TransformerException;import org.apache.xml.utils.NodeVector;import org.apache.xml.utils.PrefixResolver;import org.apache.xml.utils.QName;import org.apache.xml.utils.XMLString;import org.apache.xml.utils.WrappedRuntimeException;import org.apache.xml.dtm.DTM;import org.apache.xml.dtm.DTMIterator;import org.apache.xpath.XPathContext;import org.apache.xpath.objects.XNodeSet;import org.apache.xpath.objects.XObject;import org.apache.xpath.objects.XNull;import org.apache.xalan.templates.KeyDeclaration;/** * <meta name="usage" content="advanced"/> * Table of element keys, keyed by document node.  An instance of this * class is keyed by a Document node that should be matched with the * root of the current context. */public class KeyTable{  /**   * The document key.  This table should only be used with contexts   * whose Document roots match this key.   */  private int m_docKey;  /**   * Vector of KeyDeclaration instances holding the key declarations.   */  private Vector m_keyDeclarations;  /**   * Hold a cache of key() function result for each ref.   * Key is XMLString, the ref value   * Value is XNodeSet, the key() function result for the given ref value.   */  private Hashtable m_refsTable = null;  /**   * Get the document root matching this key.     *   * @return the document root matching this key   */  public int getDocKey()  {    return m_docKey;  }  /**    * The main iterator that will walk through the source     * tree for this key.   */  private XNodeSet m_keyNodes;    KeyIterator getKeyIterator()  {  	return (KeyIterator)(m_keyNodes.getContainedIter());  }  /**   * Build a keys table.   * @param doc The owner document key.   * @param nscontext The stylesheet's namespace context.   * @param name The key name   * @param keyDeclarations The stylesheet's xsl:key declarations.   * @param xmlLiaison The parser liaison for support of getNodeData(useNode).   *   * @throws javax.xml.transform.TransformerException   */  public KeyTable(          int doc, PrefixResolver nscontext, QName name, Vector keyDeclarations, XPathContext xctxt)            throws javax.xml.transform.TransformerException  {    m_docKey = doc;    m_keyDeclarations = keyDeclarations;    KeyIterator ki = new KeyIterator(name, keyDeclarations);    m_keyNodes = new XNodeSet(ki);    m_keyNodes.allowDetachToRelease(false);    m_keyNodes.setRoot(doc, xctxt);  }  /**   * Given a valid element key, return the corresponding node list.   *    * @param name The name of the key, which must match the 'name' attribute on xsl:key.   * @param ref The value that must match the value found by the 'match' attribute on xsl:key.   * @return a set of nodes referenced by the key named <CODE>name</CODE> and the reference <CODE>ref</CODE>. If no node is referenced by this key, an empty node set is returned.   */  public XNodeSet getNodeSetDTMByKey(QName name, XMLString ref)  {    XNodeSet refNodes = (XNodeSet) getRefsTable().get(ref);    // clone wiht reset the node set   try    {      if (refNodes != null)      {         refNodes = (XNodeSet) refNodes.cloneWithReset();       }    }    catch (CloneNotSupportedException e)    {      refNodes = null;    }    if (refNodes == null) {     //  create an empty XNodeSet      KeyIterator ki = (KeyIterator) (m_keyNodes).getContainedIter();      XPathContext xctxt = ki.getXPathContext();      refNodes = new XNodeSet(xctxt.getDTMManager()) {        public void setRoot(int nodeHandle, Object environment) {          // Root cannot be set on non-iterated node sets. Ignore it.        }      };      refNodes.reset();    }    return refNodes;  }  /**   * Get Key Name for this KeyTable     *   * @return Key name   */  public QName getKeyTableName()  {    return getKeyIterator().getName();  }  /**   * @return key declaration for the key associated to this KeyTable   */  private KeyDeclaration getKeyDeclaration() {    int nDeclarations = m_keyDeclarations.size();    // Walk through each of the declarations made with xsl:key    for (int i = 0; i < nDeclarations; i++)    {      KeyDeclaration kd = (KeyDeclaration) m_keyDeclarations.elementAt(i);      // Only continue if the name on this key declaration      // matches the name on the iterator for this walker.      if (kd.getName().equals(getKeyTableName()))      {        return kd;      }    }    // should never happen    return null;  }  /**   * @return lazy initialized refs table associating evaluation of key function   *         with a XNodeSet   */  private Hashtable getRefsTable()  {    if (m_refsTable == null)    {      m_refsTable = new Hashtable(89);  // initial capacity set to a prime number to improve hash algorithm performance      KeyIterator ki = (KeyIterator) (m_keyNodes).getContainedIter();      XPathContext xctxt = ki.getXPathContext();      KeyDeclaration keyDeclaration = getKeyDeclaration();      int currentNode;      m_keyNodes.reset();      while (DTM.NULL != (currentNode = m_keyNodes.nextNode()))      {        try        {          XObject xuse = keyDeclaration.getUse().execute(xctxt, currentNode, ki.getPrefixResolver());          if (xuse.getType() != xuse.CLASS_NODESET)          {            XMLString exprResult = xuse.xstr();            addValueInRefsTable(xctxt, exprResult, currentNode);          }          else          {            DTMIterator i = ((XNodeSet)xuse).iterRaw();            int currentNodeInUseClause;            while (DTM.NULL != (currentNodeInUseClause = i.nextNode()))            {              DTM dtm = xctxt.getDTM(currentNodeInUseClause);              XMLString exprResult = dtm.getStringValue(currentNodeInUseClause);              addValueInRefsTable(xctxt, exprResult, currentNode);            }          }        }        catch (TransformerException te)        {          throw new WrappedRuntimeException(te);        }      }    }    return m_refsTable;  }  /**   * Add an association between a ref and a node in the m_refsTable.   * Requires that m_refsTable != null   * @param xctxt XPath context   * @param ref the value of the use clause of the current key for the given node   * @param node the node to reference   */  private void addValueInRefsTable(XPathContext xctxt, XMLString ref, int node) {        XNodeSet nodes = (XNodeSet) m_refsTable.get(ref);    if (nodes == null)    {      nodes = new XNodeSet(node, xctxt.getDTMManager());      nodes.nextNode();      m_refsTable.put(ref, nodes);    }    else    {      // Nodes are passed to this method in document order.  Since we need to      // suppress duplicates, we only need to check against the last entry      // in each nodeset.  We use nodes.nextNode after each entry so we can      // easily compare node against the current node.      if (nodes.getCurrentNode() != node) {          nodes.mutableNodeset().addNode(node);          nodes.nextNode();      }        }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?