001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: KeyIterator.java 468645 2006-10-28 06:57:24Z minchau $
020 */
021 package org.apache.xalan.transformer;
022
023 import java.util.Vector;
024
025 import javax.xml.transform.TransformerException;
026
027 import org.apache.xalan.res.XSLMessages;
028 import org.apache.xalan.res.XSLTErrorResources;
029 import org.apache.xalan.templates.KeyDeclaration;
030 import org.apache.xml.dtm.Axis;
031 import org.apache.xml.dtm.DTMIterator;
032 import org.apache.xml.utils.QName;
033 import org.apache.xpath.XPath;
034 import org.apache.xpath.axes.OneStepIteratorForward;
035
036 /**
037 * This class implements an optimized iterator for
038 * "key()" patterns, matching each node to the
039 * match attribute in one or more xsl:key declarations.
040 * @xsl.usage internal
041 */
042 public class KeyIterator extends OneStepIteratorForward
043 {
044 static final long serialVersionUID = -1349109910100249661L;
045
046 /** Key name.
047 * @serial */
048 private QName m_name;
049
050 /**
051 * Get the key name from a key declaration this iterator will process
052 *
053 *
054 * @return Key name
055 */
056 public QName getName()
057 {
058 return m_name;
059 }
060
061 /** Vector of Key declarations in the stylesheet.
062 * @serial */
063 private Vector m_keyDeclarations;
064
065 /**
066 * Get the key declarations from the stylesheet
067 *
068 *
069 * @return Vector containing the key declarations from the stylesheet
070 */
071 public Vector getKeyDeclarations()
072 {
073 return m_keyDeclarations;
074 }
075
076 /**
077 * Create a KeyIterator object.
078 *
079 * @throws javax.xml.transform.TransformerException
080 */
081 KeyIterator(QName name, Vector keyDeclarations)
082 {
083 super(Axis.ALL);
084 m_keyDeclarations = keyDeclarations;
085 // m_prefixResolver = nscontext;
086 m_name = name;
087 }
088
089 /**
090 * Test whether a specified node is visible in the logical view of a
091 * TreeWalker or NodeIterator. This function will be called by the
092 * implementation of TreeWalker and NodeIterator; it is not intended to
093 * be called directly from user code.
094 *
095 * @param testNode The node to check to see if it passes the filter or not.
096 *
097 * @return a constant to determine whether the node is accepted,
098 * rejected, or skipped, as defined above .
099 */
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 }