1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xpath.internal.patterns; 22 23 import com.sun.org.apache.xml.internal.utils.QName; 24 import com.sun.org.apache.xpath.internal.Expression; 25 import com.sun.org.apache.xpath.internal.ExpressionOwner; 26 import com.sun.org.apache.xpath.internal.XPathContext; 27 import com.sun.org.apache.xpath.internal.XPathVisitor; 28 import com.sun.org.apache.xpath.internal.objects.XObject; 29 import java.util.List; 30 31 /** 32 * This class represents a union pattern, which can have multiple individual 33 * StepPattern patterns. 34 * @xsl.usage advanced 35 * @LastModified: Oct 2017 36 */ 37 public class UnionPattern extends Expression 38 { 39 static final long serialVersionUID = -6670449967116905820L; 40 41 /** Array of the contained step patterns to be tested. 42 * @serial */ 43 private StepPattern[] m_patterns; 44 45 /** 46 * No arguments to process, so this does nothing. 47 */ 48 public void fixupVariables(List<QName> vars, int globalsSize) 49 { 50 for (int i = 0; i < m_patterns.length; i++) 51 { 52 m_patterns[i].fixupVariables(vars, globalsSize); 53 } 54 } 55 56 57 /** 58 * Tell if this expression or it's subexpressions can traverse outside 59 * the current subtree. 60 * 61 * @return true if traversal outside the context node's subtree can occur. 62 */ 63 public boolean canTraverseOutsideSubtree() 64 { 65 if(null != m_patterns) 66 { 67 int n = m_patterns.length; 68 for (int i = 0; i < n; i++) 69 { 70 if(m_patterns[i].canTraverseOutsideSubtree()) 71 return true; 72 } 73 } 74 return false; 75 } 76 77 /** 78 * Set the contained step patterns to be tested. 79 * 80 * 81 * @param patterns the contained step patterns to be tested. 82 */ 83 public void setPatterns(StepPattern[] patterns) 84 { 85 m_patterns = patterns; 86 if(null != patterns) 87 { 88 for(int i = 0; i < patterns.length; i++) 89 { 90 patterns[i].exprSetParent(this); 91 } 92 } 93 94 } 95 96 /** 97 * Get the contained step patterns to be tested. 98 * 99 * 100 * @return an array of the contained step patterns to be tested. 101 */ 102 public StepPattern[] getPatterns() 103 { 104 return m_patterns; 105 } 106 107 /** 108 * Test a node to see if it matches any of the patterns in the union. 109 * 110 * @param xctxt XPath runtime context. 111 * 112 * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST}, 113 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE}, 114 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD}, 115 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or 116 * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_OTHER}. 117 * 118 * @throws javax.xml.transform.TransformerException 119 */ 120 public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException 121 { 122 123 XObject bestScore = null; 124 int n = m_patterns.length; 125 126 for (int i = 0; i < n; i++) 127 { 128 XObject score = m_patterns[i].execute(xctxt); 129 130 if (score != NodeTest.SCORE_NONE) 131 { 132 if (null == bestScore) 133 bestScore = score; 134 else if (score.num() > bestScore.num()) 135 bestScore = score; 136 } 137 } 138 139 if (null == bestScore) 140 { 141 bestScore = NodeTest.SCORE_NONE; 142 } 143 144 return bestScore; 145 } 146 147 class UnionPathPartOwner implements ExpressionOwner 148 { 149 int m_index; 150 151 UnionPathPartOwner(int index) 152 { 153 m_index = index; 154 } 155 156 /** 157 * @see ExpressionOwner#getExpression() 158 */ 159 public Expression getExpression() 160 { 161 return m_patterns[m_index]; 162 } 163 164 165 /** 166 * @see ExpressionOwner#setExpression(Expression) 167 */ 168 public void setExpression(Expression exp) 169 { 170 exp.exprSetParent(UnionPattern.this); 171 m_patterns[m_index] = (StepPattern)exp; 172 } 173 } 174 175 /** 176 * @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor) 177 */ 178 public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) 179 { 180 visitor.visitUnionPattern(owner, this); 181 if(null != m_patterns) 182 { 183 int n = m_patterns.length; 184 for(int i = 0; i < n; i++) 185 { 186 m_patterns[i].callVisitors(new UnionPathPartOwner(i), visitor); 187 } 188 } 189 } 190 191 /** 192 * @see Expression#deepEquals(Expression) 193 */ 194 public boolean deepEquals(Expression expr) 195 { 196 if(!isSameClass(expr)) 197 return false; 198 199 UnionPattern up = (UnionPattern)expr; 200 201 if(null != m_patterns) 202 { 203 int n = m_patterns.length; 204 if((null == up.m_patterns) || (up.m_patterns.length != n)) 205 return false; 206 207 for(int i = 0; i < n; i++) 208 { 209 if(!m_patterns[i].deepEquals(up.m_patterns[i])) 210 return false; 211 } 212 } 213 else if(up.m_patterns != null) 214 return false; 215 216 return true; 217 218 } 219 220 221 }