001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: FunctionPattern.java,v 1.15 2005/01/23 01:08:22 mcnamara Exp $
018: */
019: package org.apache.xpath.patterns;
020:
021: import org.apache.xml.dtm.DTM;
022: import org.apache.xml.dtm.DTMIterator;
023: import org.apache.xpath.Expression;
024: import org.apache.xpath.ExpressionOwner;
025: import org.apache.xpath.XPathContext;
026: import org.apache.xpath.XPathVisitor;
027: import org.apache.xpath.objects.XNumber;
028: import org.apache.xpath.objects.XObject;
029:
030: /**
031: * Match pattern step that contains a function.
032: * @xsl.usage advanced
033: */
034: public class FunctionPattern extends StepPattern {
035: static final long serialVersionUID = -5426793413091209944L;
036:
037: /**
038: * Construct a FunctionPattern from a
039: * {@link org.apache.xpath.functions.Function expression}.
040: *
041: * NEEDSDOC @param expr
042: */
043: public FunctionPattern(Expression expr, int axis, int predaxis) {
044:
045: super (0, null, null, axis, predaxis);
046:
047: m_functionExpr = expr;
048: }
049:
050: /**
051: * Static calc of match score.
052: */
053: public final void calcScore() {
054:
055: m_score = SCORE_OTHER;
056:
057: if (null == m_targetString)
058: calcTargetString();
059: }
060:
061: /**
062: * Should be a {@link org.apache.xpath.functions.Function expression}.
063: * @serial
064: */
065: Expression m_functionExpr;
066:
067: /**
068: * This function is used to fixup variables from QNames to stack frame
069: * indexes at stylesheet build time.
070: * @param vars List of QNames that correspond to variables. This list
071: * should be searched backwards for the first qualified name that
072: * corresponds to the variable reference qname. The position of the
073: * QName in the vector from the start of the vector will be its position
074: * in the stack frame (but variables above the globalsTop value will need
075: * to be offset to the current stack frame).
076: */
077: public void fixupVariables(java.util.Vector vars, int globalsSize) {
078: super .fixupVariables(vars, globalsSize);
079: m_functionExpr.fixupVariables(vars, globalsSize);
080: }
081:
082: /**
083: * Test a node to see if it matches the given node test.
084: *
085: * @param xctxt XPath runtime context.
086: *
087: * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
088: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
089: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
090: * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
091: * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
092: *
093: * @throws javax.xml.transform.TransformerException
094: */
095: public XObject execute(XPathContext xctxt, int context)
096: throws javax.xml.transform.TransformerException {
097:
098: DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
099: XNumber score = SCORE_NONE;
100:
101: if (null != nl) {
102: int n;
103:
104: while (DTM.NULL != (n = nl.nextNode())) {
105: score = (n == context) ? SCORE_OTHER : SCORE_NONE;
106:
107: if (score == SCORE_OTHER) {
108: context = n;
109:
110: break;
111: }
112: }
113:
114: // nl.detach();
115: }
116: nl.detach();
117:
118: return score;
119: }
120:
121: /**
122: * Test a node to see if it matches the given node test.
123: *
124: * @param xctxt XPath runtime context.
125: *
126: * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
127: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
128: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
129: * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
130: * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
131: *
132: * @throws javax.xml.transform.TransformerException
133: */
134: public XObject execute(XPathContext xctxt, int context, DTM dtm,
135: int expType)
136: throws javax.xml.transform.TransformerException {
137:
138: DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
139: XNumber score = SCORE_NONE;
140:
141: if (null != nl) {
142: int n;
143:
144: while (DTM.NULL != (n = nl.nextNode())) {
145: score = (n == context) ? SCORE_OTHER : SCORE_NONE;
146:
147: if (score == SCORE_OTHER) {
148: context = n;
149:
150: break;
151: }
152: }
153:
154: nl.detach();
155: }
156:
157: return score;
158: }
159:
160: /**
161: * Test a node to see if it matches the given node test.
162: *
163: * @param xctxt XPath runtime context.
164: *
165: * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
166: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
167: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
168: * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
169: * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
170: *
171: * @throws javax.xml.transform.TransformerException
172: */
173: public XObject execute(XPathContext xctxt)
174: throws javax.xml.transform.TransformerException {
175:
176: int context = xctxt.getCurrentNode();
177: DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
178: XNumber score = SCORE_NONE;
179:
180: if (null != nl) {
181: int n;
182:
183: while (DTM.NULL != (n = nl.nextNode())) {
184: score = (n == context) ? SCORE_OTHER : SCORE_NONE;
185:
186: if (score == SCORE_OTHER) {
187: context = n;
188:
189: break;
190: }
191: }
192:
193: nl.detach();
194: }
195:
196: return score;
197: }
198:
199: class FunctionOwner implements ExpressionOwner {
200: /**
201: * @see ExpressionOwner#getExpression()
202: */
203: public Expression getExpression() {
204: return m_functionExpr;
205: }
206:
207: /**
208: * @see ExpressionOwner#setExpression(Expression)
209: */
210: public void setExpression(Expression exp) {
211: exp.exprSetParent(FunctionPattern.this );
212: m_functionExpr = exp;
213: }
214: }
215:
216: /**
217: * Call the visitor for the function.
218: */
219: protected void callSubtreeVisitors(XPathVisitor visitor) {
220: m_functionExpr.callVisitors(new FunctionOwner(), visitor);
221: super.callSubtreeVisitors(visitor);
222: }
223:
224: }
|