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: UnionPattern.java,v 1.15 2005/01/23 01:08:22 mcnamara Exp $
018: */
019: package org.apache.xpath.patterns;
020:
021: import org.apache.xpath.Expression;
022: import org.apache.xpath.ExpressionOwner;
023: import org.apache.xpath.XPathContext;
024: import org.apache.xpath.XPathVisitor;
025: import org.apache.xpath.objects.XObject;
026:
027: /**
028: * This class represents a union pattern, which can have multiple individual
029: * StepPattern patterns.
030: * @xsl.usage advanced
031: */
032: public class UnionPattern extends Expression {
033: static final long serialVersionUID = -6670449967116905820L;
034:
035: /** Array of the contained step patterns to be tested.
036: * @serial */
037: private StepPattern[] m_patterns;
038:
039: /**
040: * No arguments to process, so this does nothing.
041: */
042: public void fixupVariables(java.util.Vector vars, int globalsSize) {
043: for (int i = 0; i < m_patterns.length; i++) {
044: m_patterns[i].fixupVariables(vars, globalsSize);
045: }
046: }
047:
048: /**
049: * Tell if this expression or it's subexpressions can traverse outside
050: * the current subtree.
051: *
052: * @return true if traversal outside the context node's subtree can occur.
053: */
054: public boolean canTraverseOutsideSubtree() {
055: if (null != m_patterns) {
056: int n = m_patterns.length;
057: for (int i = 0; i < n; i++) {
058: if (m_patterns[i].canTraverseOutsideSubtree())
059: return true;
060: }
061: }
062: return false;
063: }
064:
065: /**
066: * Set the contained step patterns to be tested.
067: *
068: *
069: * @param patterns the contained step patterns to be tested.
070: */
071: public void setPatterns(StepPattern[] patterns) {
072: m_patterns = patterns;
073: if (null != patterns) {
074: for (int i = 0; i < patterns.length; i++) {
075: patterns[i].exprSetParent(this );
076: }
077: }
078:
079: }
080:
081: /**
082: * Get the contained step patterns to be tested.
083: *
084: *
085: * @return an array of the contained step patterns to be tested.
086: */
087: public StepPattern[] getPatterns() {
088: return m_patterns;
089: }
090:
091: /**
092: * Test a node to see if it matches any of the patterns in the union.
093: *
094: * @param xctxt XPath runtime context.
095: *
096: * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
097: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
098: * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
099: * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
100: * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
101: *
102: * @throws javax.xml.transform.TransformerException
103: */
104: public XObject execute(XPathContext xctxt)
105: throws javax.xml.transform.TransformerException {
106:
107: XObject bestScore = null;
108: int n = m_patterns.length;
109:
110: for (int i = 0; i < n; i++) {
111: XObject score = m_patterns[i].execute(xctxt);
112:
113: if (score != NodeTest.SCORE_NONE) {
114: if (null == bestScore)
115: bestScore = score;
116: else if (score.num() > bestScore.num())
117: bestScore = score;
118: }
119: }
120:
121: if (null == bestScore) {
122: bestScore = NodeTest.SCORE_NONE;
123: }
124:
125: return bestScore;
126: }
127:
128: class UnionPathPartOwner implements ExpressionOwner {
129: int m_index;
130:
131: UnionPathPartOwner(int index) {
132: m_index = index;
133: }
134:
135: /**
136: * @see ExpressionOwner#getExpression()
137: */
138: public Expression getExpression() {
139: return m_patterns[m_index];
140: }
141:
142: /**
143: * @see ExpressionOwner#setExpression(Expression)
144: */
145: public void setExpression(Expression exp) {
146: exp.exprSetParent(UnionPattern.this );
147: m_patterns[m_index] = (StepPattern) exp;
148: }
149: }
150:
151: /**
152: * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
153: */
154: public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) {
155: visitor.visitUnionPattern(owner, this );
156: if (null != m_patterns) {
157: int n = m_patterns.length;
158: for (int i = 0; i < n; i++) {
159: m_patterns[i].callVisitors(new UnionPathPartOwner(i),
160: visitor);
161: }
162: }
163: }
164:
165: /**
166: * @see Expression#deepEquals(Expression)
167: */
168: public boolean deepEquals(Expression expr) {
169: if (!isSameClass(expr))
170: return false;
171:
172: UnionPattern up = (UnionPattern) expr;
173:
174: if (null != m_patterns) {
175: int n = m_patterns.length;
176: if ((null == up.m_patterns) || (up.m_patterns.length != n))
177: return false;
178:
179: for (int i = 0; i < n; i++) {
180: if (!m_patterns[i].deepEquals(up.m_patterns[i]))
181: return false;
182: }
183: } else if (up.m_patterns != null)
184: return false;
185:
186: return true;
187:
188: }
189:
190: }
|