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: UnionPattern.java 468655 2006-10-28 07:12:06Z minchau $ 20 */ 21 package org.apache.xpath.patterns; 22 23 import org.apache.xpath.Expression; 24 import org.apache.xpath.ExpressionOwner; 25 import org.apache.xpath.XPathContext; 26 import org.apache.xpath.XPathVisitor; 27 import org.apache.xpath.objects.XObject; 28 29 /** 30 * This class represents a union pattern, which can have multiple individual 31 * StepPattern patterns. 32 * @xsl.usage advanced 33 */ 34 public class UnionPattern extends Expression 35 { 36 static final long serialVersionUID = -6670449967116905820L; 37 38 /** Array of the contained step patterns to be tested. 39 * @serial */ 40 private StepPattern[] m_patterns; 41 42 /** 43 * No arguments to process, so this does nothing. 44 */ fixupVariables(java.util.Vector vars, int globalsSize)45 public void fixupVariables(java.util.Vector vars, int globalsSize) 46 { 47 for (int i = 0; i < m_patterns.length; i++) 48 { 49 m_patterns[i].fixupVariables(vars, globalsSize); 50 } 51 } 52 53 54 /** 55 * Tell if this expression or it's subexpressions can traverse outside 56 * the current subtree. 57 * 58 * @return true if traversal outside the context node's subtree can occur. 59 */ canTraverseOutsideSubtree()60 public boolean canTraverseOutsideSubtree() 61 { 62 if(null != m_patterns) 63 { 64 int n = m_patterns.length; 65 for (int i = 0; i < n; i++) 66 { 67 if(m_patterns[i].canTraverseOutsideSubtree()) 68 return true; 69 } 70 } 71 return false; 72 } 73 74 /** 75 * Set the contained step patterns to be tested. 76 * 77 * 78 * @param patterns the contained step patterns to be tested. 79 */ setPatterns(StepPattern[] patterns)80 public void setPatterns(StepPattern[] patterns) 81 { 82 m_patterns = patterns; 83 if(null != patterns) 84 { 85 for(int i = 0; i < patterns.length; i++) 86 { 87 patterns[i].exprSetParent(this); 88 } 89 } 90 91 } 92 93 /** 94 * Get the contained step patterns to be tested. 95 * 96 * 97 * @return an array of the contained step patterns to be tested. 98 */ getPatterns()99 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 */ execute(XPathContext xctxt)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 UnionPathPartOwner(int index)148 UnionPathPartOwner(int index) 149 { 150 m_index = index; 151 } 152 153 /** 154 * @see ExpressionOwner#getExpression() 155 */ getExpression()156 public Expression getExpression() 157 { 158 return m_patterns[m_index]; 159 } 160 161 162 /** 163 * @see ExpressionOwner#setExpression(Expression) 164 */ setExpression(Expression exp)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 */ callVisitors(ExpressionOwner owner, XPathVisitor visitor)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 */ deepEquals(Expression expr)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 } 219