OSDN Git Service

Initial revision
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / xml / xpath / EqualityExpr.java
1 /* EqualityExpr.java -- 
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package gnu.xml.xpath;
39
40 import java.util.Collection;
41 import java.util.Iterator;
42 import javax.xml.namespace.QName;
43 import org.w3c.dom.Node;
44
45 /**
46  * Boolean equality expression.
47  *
48  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
49  */
50 final class EqualityExpr
51   extends Expr
52 {
53
54   final Expr lhs;
55   final Expr rhs;
56   final boolean invert;
57
58   EqualityExpr(Expr lhs, Expr rhs, boolean invert)
59   {
60     this.lhs = lhs;
61     this.rhs = rhs;
62     this.invert = invert;
63   }
64
65   public Object evaluate(Node context, int pos, int len)
66   {
67     boolean val = evaluateImpl(context, pos, len);
68     if (invert)
69       {
70         return val ? Boolean.FALSE : Boolean.TRUE;
71       }
72     else
73       {
74         return val ? Boolean.TRUE : Boolean.FALSE;
75       }
76   }
77
78   private boolean evaluateImpl(Node context, int pos, int len)
79   {
80     Object left = lhs.evaluate(context, pos, len);
81     Object right = rhs.evaluate(context, pos, len);
82
83     /*
84      * If both objects to be compared are node-sets, then the comparison
85      * will be true if and only if there is a node in the first node-set and
86      * a node in the second node-set such that the result of performing the
87      * comparison on the string-values of the two nodes is true.
88      */
89     boolean flns = left instanceof Collection;
90     boolean frns = right instanceof Collection;
91     if (flns && frns)
92       {
93         Collection lns = (Collection) left;
94         Collection rns = (Collection) right;
95         if (lns.isEmpty())
96           {
97             return false;
98           }
99         boolean all = true;
100         for (Iterator i = lns.iterator(); i.hasNext(); )
101           {
102             Node ltest = (Node) i.next();
103             for (Iterator j = rns.iterator(); j.hasNext(); )
104               {
105                 Node rtest = (Node) j.next();
106                 if (ltest == rtest || ltest.equals(rtest))
107                   {
108                     // much shorter
109                     if (!invert)
110                       {
111                         return true;
112                       }
113                   }
114                 else if (stringValue(ltest).equals(stringValue(rtest)))
115                   {
116                     if (!invert)
117                       {
118                         return true;
119                       }
120                   }
121                 else
122                   {
123                     all = false;
124                   }
125               }
126           }
127         return all;
128       }
129     /* 
130      * If one object to be compared is a node-set and the other is a number,
131      * then the comparison will be true if and only if there is a node in
132      * the node-set such that the result of performing the comparison on the
133      * number to be compared and on the result of converting the
134      * string-value of that node to a number using the number function is
135      * true.
136      */
137     boolean fln = left instanceof Double;
138     boolean frn = right instanceof Double;
139     if ((flns && frn) || (frns && fln))
140       {
141         Collection ns = flns ? (Collection) left : (Collection) right;
142         double n = fln ? ((Double) left).doubleValue() :
143           ((Double) right).doubleValue();
144         boolean all = true;
145         for (Iterator i = ns.iterator(); i.hasNext(); )
146           {
147             Node test = (Node) i.next();
148             double nn = _number(context, stringValue(test));
149             if (nn == n)
150               {
151                 if (!invert)
152                   {
153                     return true;
154                   }
155               }
156             else
157               {
158                 all = false;
159               }
160           }
161         return invert ? all : false;
162       }
163     /*
164      * If one object to be compared is a node-set and the other is a
165      * string, then the comparison will be true if and only if there is a
166      * node in the node-set such that the result of performing the
167      * comparison on the string-value of the node and the other string is
168      * true.
169      */
170     boolean fls = left instanceof String;
171     boolean frs = right instanceof String;
172     if ((flns && frs) || (frns && fls))
173       {
174         Collection ns = flns ? (Collection) left : (Collection) right;
175         String s = fls ? (String) left : (String) right;
176         boolean all = true;
177         for (Iterator i = ns.iterator(); i.hasNext(); )
178           {
179             Node test = (Node) i.next();
180             if (stringValue(test).equals(s))
181               {
182                 if (!invert)
183                   {
184                     return true;
185                   }
186               }
187             else
188               {
189                 all = false;
190               }
191           }
192         return invert ? all : false;
193       }
194     /*
195      * If one object to be compared is a node-set and the other is a
196      * boolean, then the comparison will be true if and only if the result
197      * of performing the comparison on the boolean and on the result of
198      * converting the node-set to a boolean using the boolean function is
199      * true.
200      */
201     boolean flb = left instanceof Boolean;
202     boolean frb = right instanceof Boolean;
203     if ((flns && frb) || (frns && flb))
204       {
205         Collection ns = flns ? (Collection) left : (Collection) right;
206         boolean b = flb ? ((Boolean) left).booleanValue() :
207           ((Boolean) right).booleanValue();
208         return _boolean(context, ns) == b;
209       }
210     /*
211      * If at least one object to be compared is a boolean, then each object
212      * to be compared is converted to a boolean as if by applying the
213      * boolean function.
214      */
215     if (flb || frb)
216       {
217         boolean lb = flb ? ((Boolean) left).booleanValue() :
218           _boolean(context, left);
219         boolean rb = frb ? ((Boolean) right).booleanValue() :
220           _boolean(context, right);
221         return lb == rb;
222       }
223     /*
224      * Otherwise, if at least one object to be compared is
225      * a number, then each object to be compared is converted to a number as
226      * if by applying the number function.
227      */
228     if (fln || frn)
229       {
230         double ln = fln ? ((Double) left).doubleValue() :
231           _number(context, left);
232         double rn = frn ? ((Double) right).doubleValue() :
233           _number(context, right);
234         return ln == rn;
235       }
236     /*
237      * Otherwise, both objects to be
238      * compared are converted to strings as if by applying the string
239      * function.
240      */
241     String ls = fls ? (String) left : _string(context, left);
242     String rs = frs ? (String) right : _string(context, right);
243     return ls.equals(rs);
244   }
245
246   public Expr clone(Object context)
247   {
248     return new EqualityExpr(lhs.clone(context), rhs.clone(context), invert);
249   }
250
251   public boolean references(QName var)
252   {
253     return (lhs.references(var) || rhs.references(var));
254   }
255
256   public String toString()
257   {
258     if (invert)
259       {
260         return lhs + " != " + rhs;
261       }
262     else
263       {
264         return lhs + " = " + rhs;
265       }
266   }
267   
268 }