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 }