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