Home | History | Annotate | Download | only in transformer
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: KeyIterator.java 468645 2006-10-28 06:57:24Z minchau $
     20  */
     21 package org.apache.xalan.transformer;
     22 
     23 import java.util.Vector;
     24 
     25 import javax.xml.transform.TransformerException;
     26 
     27 import org.apache.xalan.res.XSLMessages;
     28 import org.apache.xalan.res.XSLTErrorResources;
     29 import org.apache.xalan.templates.KeyDeclaration;
     30 import org.apache.xml.dtm.Axis;
     31 import org.apache.xml.dtm.DTMIterator;
     32 import org.apache.xml.utils.QName;
     33 import org.apache.xpath.XPath;
     34 import org.apache.xpath.axes.OneStepIteratorForward;
     35 
     36 /**
     37  * This class implements an optimized iterator for
     38  * "key()" patterns, matching each node to the
     39  * match attribute in one or more xsl:key declarations.
     40  * @xsl.usage internal
     41  */
     42 public class KeyIterator extends OneStepIteratorForward
     43 {
     44     static final long serialVersionUID = -1349109910100249661L;
     45 
     46   /** Key name.
     47    *  @serial           */
     48   private QName m_name;
     49 
     50   /**
     51    * Get the key name from a key declaration this iterator will process
     52    *
     53    *
     54    * @return Key name
     55    */
     56   public QName getName()
     57   {
     58     return m_name;
     59   }
     60 
     61   /** Vector of Key declarations in the stylesheet.
     62    *  @serial          */
     63   private Vector m_keyDeclarations;
     64 
     65   /**
     66    * Get the key declarations from the stylesheet
     67    *
     68    *
     69    * @return Vector containing the key declarations from the stylesheet
     70    */
     71   public Vector getKeyDeclarations()
     72   {
     73     return m_keyDeclarations;
     74   }
     75 
     76   /**
     77     * Create a KeyIterator object.
     78     *
     79     * @throws javax.xml.transform.TransformerException
     80     */
     81   KeyIterator(QName name, Vector keyDeclarations)
     82   {
     83     super(Axis.ALL);
     84     m_keyDeclarations = keyDeclarations;
     85     // m_prefixResolver = nscontext;
     86     m_name = name;
     87   }
     88 
     89   /**
     90    *  Test whether a specified node is visible in the logical view of a
     91    * TreeWalker or NodeIterator. This function will be called by the
     92    * implementation of TreeWalker and NodeIterator; it is not intended to
     93    * be called directly from user code.
     94    *
     95    * @param testNode  The node to check to see if it passes the filter or not.
     96    *
     97    * @return  a constant to determine whether the node is accepted,
     98    *   rejected, or skipped, as defined  above .
     99    */
    100   public short acceptNode(int testNode)
    101   {
    102     boolean foundKey = false;
    103     KeyIterator ki = (KeyIterator) m_lpi;
    104     org.apache.xpath.XPathContext xctxt = ki.getXPathContext();
    105     Vector keys = ki.getKeyDeclarations();
    106 
    107     QName name = ki.getName();
    108     try
    109     {
    110       // System.out.println("lookupKey: "+lookupKey);
    111       int nDeclarations = keys.size();
    112 
    113       // Walk through each of the declarations made with xsl:key
    114       for (int i = 0; i < nDeclarations; i++)
    115       {
    116         KeyDeclaration kd = (KeyDeclaration) keys.elementAt(i);
    117 
    118         // Only continue if the name on this key declaration
    119         // matches the name on the iterator for this walker.
    120         if (!kd.getName().equals(name))
    121           continue;
    122 
    123         foundKey = true;
    124         // xctxt.setNamespaceContext(ki.getPrefixResolver());
    125 
    126         // See if our node matches the given key declaration according to
    127         // the match attribute on xsl:key.
    128         XPath matchExpr = kd.getMatch();
    129         double score = matchExpr.getMatchScore(xctxt, testNode);
    130 
    131         if (score == kd.getMatch().MATCH_SCORE_NONE)
    132           continue;
    133 
    134         return DTMIterator.FILTER_ACCEPT;
    135 
    136       } // end for(int i = 0; i < nDeclarations; i++)
    137     }
    138     catch (TransformerException se)
    139     {
    140 
    141       // TODO: What to do?
    142     }
    143 
    144     if (!foundKey)
    145       throw new RuntimeException(
    146         XSLMessages.createMessage(
    147           XSLTErrorResources.ER_NO_XSLKEY_DECLARATION,
    148           new Object[] { name.getLocalName()}));
    149 
    150     return DTMIterator.FILTER_REJECT;
    151   }
    152 
    153 }
    154