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