Home | History | Annotate | Download | only in patterns
      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    */
     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    */
     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    */
     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    */
     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    */
    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 }
    219