mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			275 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			275 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* EqualityExpr.java --
 | |
|    Copyright (C) 2004 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package gnu.xml.xpath;
 | |
| 
 | |
| import java.util.Collection;
 | |
| import java.util.Iterator;
 | |
| import javax.xml.namespace.QName;
 | |
| import org.w3c.dom.Node;
 | |
| 
 | |
| /**
 | |
|  * Boolean equality expression.
 | |
|  *
 | |
|  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 | |
|  */
 | |
| final class EqualityExpr
 | |
|   extends Expr
 | |
| {
 | |
| 
 | |
|   final Expr lhs;
 | |
|   final Expr rhs;
 | |
|   final boolean invert;
 | |
| 
 | |
|   EqualityExpr(Expr lhs, Expr rhs, boolean invert)
 | |
|   {
 | |
|     this.lhs = lhs;
 | |
|     this.rhs = rhs;
 | |
|     this.invert = invert;
 | |
|   }
 | |
| 
 | |
|   @Override
 | |
|   public Object evaluate(Node context, int pos, int len)
 | |
|   {
 | |
|     boolean val = evaluateImpl(context, pos, len);
 | |
|     if (invert)
 | |
|       {
 | |
|         return val ? Boolean.FALSE : Boolean.TRUE;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         return val ? Boolean.TRUE : Boolean.FALSE;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   private boolean evaluateImpl(Node context, int pos, int len)
 | |
|   {
 | |
|     Object left = lhs.evaluate(context, pos, len);
 | |
|     Object right = rhs.evaluate(context, pos, len);
 | |
| 
 | |
|     /*
 | |
|      * If both objects to be compared are node-sets, then the comparison
 | |
|      * will be true if and only if there is a node in the first node-set and
 | |
|      * a node in the second node-set such that the result of performing the
 | |
|      * comparison on the string-values of the two nodes is true.
 | |
|      */
 | |
|     boolean flns = left instanceof Collection;
 | |
|     boolean frns = right instanceof Collection;
 | |
|     if (flns && frns)
 | |
|       {
 | |
|         /* Suppression is safe, as we know context produces Collection<Node> */
 | |
|         @SuppressWarnings("unchecked")
 | |
|           Collection<Node> lns = (Collection<Node>) left;
 | |
|         @SuppressWarnings("unchecked")
 | |
|           Collection<Node> rns = (Collection<Node>) right;
 | |
|         if (lns.isEmpty())
 | |
|           {
 | |
|             return false;
 | |
|           }
 | |
|         boolean all = true;
 | |
|         for (Node ltest : lns)
 | |
|           {
 | |
|             for (Node rtest : rns)
 | |
|               {
 | |
|                 if (ltest == rtest || ltest.equals(rtest))
 | |
|                   {
 | |
|                     // much shorter
 | |
|                     if (!invert)
 | |
|                       {
 | |
|                         return true;
 | |
|                       }
 | |
|                   }
 | |
|                 else if (stringValue(ltest).equals(stringValue(rtest)))
 | |
|                   {
 | |
|                     if (!invert)
 | |
|                       {
 | |
|                         return true;
 | |
|                       }
 | |
|                   }
 | |
|                 else
 | |
|                   {
 | |
|                     all = false;
 | |
|                   }
 | |
|               }
 | |
|           }
 | |
|         return all;
 | |
|       }
 | |
|     /*
 | |
|      * If one object to be compared is a node-set and the other is a number,
 | |
|      * then the comparison will be true if and only if there is a node in
 | |
|      * the node-set such that the result of performing the comparison on the
 | |
|      * number to be compared and on the result of converting the
 | |
|      * string-value of that node to a number using the number function is
 | |
|      * true.
 | |
|      */
 | |
|     boolean fln = left instanceof Double;
 | |
|     boolean frn = right instanceof Double;
 | |
|     if ((flns && frn) || (frns && fln))
 | |
|       {
 | |
|         /* Suppression is safe, as we know context produces Collection<Node> */
 | |
|         @SuppressWarnings("unchecked")
 | |
|           Collection<Node> ns = flns ? (Collection<Node>) left : (Collection<Node>) right;
 | |
|         double n = fln ? ((Double) left).doubleValue() :
 | |
|           ((Double) right).doubleValue();
 | |
|         boolean all = true;
 | |
|         for (Node test : ns)
 | |
|           {
 | |
|             double nn = _number(context, stringValue(test));
 | |
|             if (nn == n)
 | |
|               {
 | |
|                 if (!invert)
 | |
|                   {
 | |
|                     return true;
 | |
|                   }
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 all = false;
 | |
|               }
 | |
|           }
 | |
|         return invert ? all : false;
 | |
|       }
 | |
|     /*
 | |
|      * If one object to be compared is a node-set and the other is a
 | |
|      * string, then the comparison will be true if and only if there is a
 | |
|      * node in the node-set such that the result of performing the
 | |
|      * comparison on the string-value of the node and the other string is
 | |
|      * true.
 | |
|      */
 | |
|     boolean fls = left instanceof String;
 | |
|     boolean frs = right instanceof String;
 | |
|     if ((flns && frs) || (frns && fls))
 | |
|       {
 | |
|         /* Suppression is safe, as we know context produces Collection<Node> */
 | |
|         @SuppressWarnings("unchecked")
 | |
|           Collection<Node> ns = flns ? (Collection<Node>) left : (Collection<Node>) right;
 | |
|         String s = fls ? (String) left : (String) right;
 | |
|         boolean all = true;
 | |
|         for (Node test : ns)
 | |
|           {
 | |
|             if (stringValue(test).equals(s))
 | |
|               {
 | |
|                 if (!invert)
 | |
|                   {
 | |
|                     return true;
 | |
|                   }
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 all = false;
 | |
|               }
 | |
|           }
 | |
|         return invert ? all : false;
 | |
|       }
 | |
|     /*
 | |
|      * If one object to be compared is a node-set and the other is a
 | |
|      * boolean, then the comparison will be true if and only if the result
 | |
|      * of performing the comparison on the boolean and on the result of
 | |
|      * converting the node-set to a boolean using the boolean function is
 | |
|      * true.
 | |
|      */
 | |
|     boolean flb = left instanceof Boolean;
 | |
|     boolean frb = right instanceof Boolean;
 | |
|     if ((flns && frb) || (frns && flb))
 | |
|       {
 | |
|         /* Suppression is safe, as we know context produces Collection<Node> */
 | |
|         @SuppressWarnings("unchecked")
 | |
|           Collection<Node> ns = flns ? (Collection<Node>) left : (Collection<Node>) right;
 | |
|         boolean b = flb ? ((Boolean) left).booleanValue() :
 | |
|           ((Boolean) right).booleanValue();
 | |
|         return _boolean(context, ns) == b;
 | |
|       }
 | |
|     /*
 | |
|      * If at least one object to be compared is a boolean, then each object
 | |
|      * to be compared is converted to a boolean as if by applying the
 | |
|      * boolean function.
 | |
|      */
 | |
|     if (flb || frb)
 | |
|       {
 | |
|         boolean lb = flb ? ((Boolean) left).booleanValue() :
 | |
|           _boolean(context, left);
 | |
|         boolean rb = frb ? ((Boolean) right).booleanValue() :
 | |
|           _boolean(context, right);
 | |
|         return lb == rb;
 | |
|       }
 | |
|     /*
 | |
|      * Otherwise, if at least one object to be compared is
 | |
|      * a number, then each object to be compared is converted to a number as
 | |
|      * if by applying the number function.
 | |
|      */
 | |
|     if (fln || frn)
 | |
|       {
 | |
|         double ln = fln ? ((Double) left).doubleValue() :
 | |
|           _number(context, left);
 | |
|         double rn = frn ? ((Double) right).doubleValue() :
 | |
|           _number(context, right);
 | |
|         return ln == rn;
 | |
|       }
 | |
|     /*
 | |
|      * Otherwise, both objects to be
 | |
|      * compared are converted to strings as if by applying the string
 | |
|      * function.
 | |
|      */
 | |
|     String ls = fls ? (String) left : _string(context, left);
 | |
|     String rs = frs ? (String) right : _string(context, right);
 | |
|     return ls.equals(rs);
 | |
|   }
 | |
| 
 | |
|   public Expr clone(Object context)
 | |
|   {
 | |
|     return new EqualityExpr(lhs.clone(context), rhs.clone(context), invert);
 | |
|   }
 | |
| 
 | |
|   public boolean references(QName var)
 | |
|   {
 | |
|     return (lhs.references(var) || rhs.references(var));
 | |
|   }
 | |
| 
 | |
|   public String toString()
 | |
|   {
 | |
|     if (invert)
 | |
|       {
 | |
|         return lhs + " != " + rhs;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         return lhs + " = " + rhs;
 | |
|       }
 | |
|   }
 | |
| 
 | |
| }
 |