View Javadoc
1   /*
2    * Copyright 2000-2002 bob mcwhirter & James Strachan.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    *   * Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the following disclaimer.
11   * 
12   *   * Redistributions in binary form must reproduce the above copyright
13   *     notice, this list of conditions and the following disclaimer in the
14   *     documentation and/or other materials provided with the distribution.
15   * 
16   *   * Neither the name of the Jaxen Project nor the names of its
17   *     contributors may be used to endorse or promote products derived 
18   *     from this software without specific prior written permission.
19   * 
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21   * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22   * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23   * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24   * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31   *
32   * ====================================================================
33   * This software consists of voluntary contributions made by many 
34   * individuals on behalf of the Jaxen Project and was originally 
35   * created by bob mcwhirter <bob@werken.com> and 
36   * James Strachan <jstrachan@apache.org>.  For more information on the 
37   * Jaxen Project, please see <https://github.com/jaxen-xpath/jaxen/>.
38   */
39  
40  
41  
42  package org.jaxen.expr;
43  
44  import java.util.Iterator;
45  import java.util.List;
46  import org.jaxen.Context;
47  import org.jaxen.JaxenException;
48  import org.jaxen.Navigator;
49  import org.jaxen.function.NumberFunction;
50  
51  abstract class DefaultRelationalExpr extends DefaultTruthExpr implements RelationalExpr 
52    {
53    DefaultRelationalExpr( Expr lhs, Expr rhs )
54      {
55      super( lhs, rhs );
56      }
57    
58    Object evaluateChain( List<Object> values, Context context ) throws JaxenException
59      {
60      Navigator nav = context.getNavigator();
61      Object lhsValue = values.get(values.size() - 1);
62      for (int i = values.size() - 2; i >= 0; i--)
63      {
64        lhsValue = evaluateComparison( lhsValue, values.get(i), nav );
65      }
66      return lhsValue;
67      }
68  
69    private Object evaluateSetSet( List lhsSet, List rhsSet, Navigator nav )
70      {
71      if( setIsEmpty( lhsSet ) || setIsEmpty( rhsSet ) ) // return false if either is null or empty
72        {
73        return Boolean.FALSE;
74        }    
75      
76      for( Iterator lhsIterator = lhsSet.iterator(); lhsIterator.hasNext(); )
77        {
78        Object lhs = lhsIterator.next();        
79        
80        for( Iterator rhsIterator = rhsSet.iterator(); rhsIterator.hasNext(); )
81          {
82          Object rhs = rhsIterator.next();
83          
84          if( evaluateObjectObject( lhs, rhs, nav ) )
85            {
86            return Boolean.TRUE;
87            }
88          }
89        }      
90      
91      return Boolean.FALSE;
92      }
93    
94    private boolean evaluateObjectObject( Object lhs, Object rhs, Navigator nav )
95      {
96      if( lhs == null || rhs == null )
97        {
98        return false;
99        }
100     
101     Double lhsNum = NumberFunction.evaluate( lhs, nav );
102     Double rhsNum = NumberFunction.evaluate( rhs, nav );      
103     
104     if( NumberFunction.isNaN( lhsNum ) || NumberFunction.isNaN( rhsNum ) )
105       {
106       return false;
107       }
108     
109     return evaluateDoubleDouble( lhsNum, rhsNum );
110     }
111   
112   private Boolean evaluateComparison( Object lhsValue, Object rhsValue, Navigator nav )
113     {
114     if( bothAreSets( lhsValue, rhsValue ) )
115       {
116       return (Boolean) evaluateSetSet( (List) lhsValue, (List) rhsValue, nav );
117       }
118     
119     if (isBoolean(rhsValue) && isSet(lhsValue)) {
120         List left = convertToList( lhsValue );
121         if (left.isEmpty()) {
122             return evaluateObjectObject(rhsValue, Boolean.FALSE, nav) ? Boolean.TRUE : Boolean.FALSE;
123         }
124         else {
125             return evaluateObjectObject(rhsValue, Boolean.TRUE, nav) ? Boolean.TRUE : Boolean.FALSE;
126         }
127     }
128     else if (isBoolean(lhsValue) && isSet(rhsValue)) {
129         List right = convertToList( rhsValue );
130         if (right.isEmpty()) {
131             return evaluateObjectObject(lhsValue, Boolean.FALSE, nav) ? Boolean.TRUE : Boolean.FALSE;
132         }
133         else {
134             return evaluateObjectObject(lhsValue, Boolean.TRUE, nav) ? Boolean.TRUE : Boolean.FALSE;
135         }
136     }
137     
138     if( eitherIsSet( lhsValue, rhsValue ) )
139       {
140       if( isSet( lhsValue ) )
141         {        
142         return (Boolean) evaluateSetSet( (List) lhsValue, convertToList( rhsValue ), nav );              
143         }
144       else
145         {
146         return (Boolean) evaluateSetSet( convertToList( lhsValue ), (List) rhsValue, nav );              
147         }
148       }
149     
150     return evaluateObjectObject( lhsValue, rhsValue, nav ) ? Boolean.TRUE : Boolean.FALSE;
151     }
152   
153   protected abstract boolean evaluateDoubleDouble( Double lhs, Double rhs );    
154   }