001: /*
002: * Copyright 2004-2007 Gary Bentley
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may
005: * not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015: package org.josql.expressions;
016:
017: import org.josql.Query;
018: import org.josql.QueryExecutionException;
019:
020: import org.josql.internal.Utilities;
021:
022: /**
023: * This class represents an "=" or "!=" expression. This class also provides the
024: * ability for the developer to prefix the "=" or "!=" with "$" to indicate that a
025: * case-insensitive comparison should be made, in which case the LHS and RHS
026: * are converted to strings first.
027: */
028: public class EqualsExpression extends BinaryExpression {
029:
030: private boolean not = false;
031:
032: public boolean ignoreCase = false;
033:
034: public void setIgnoreCase(boolean v) {
035:
036: this .ignoreCase = v;
037:
038: }
039:
040: public boolean isIgnoreCase() {
041:
042: return this .ignoreCase;
043:
044: }
045:
046: public boolean isNot() {
047:
048: return this .not;
049:
050: }
051:
052: public void setNot(boolean v) {
053:
054: this .not = v;
055:
056: }
057:
058: /**
059: * Return whether this expression evaluates to <code>true</code>.
060: *
061: * @param o The current object to perform the expression on.
062: * @param q The Query object.
063: * @return <code>true</code> if the expression evaluates to <code>true</code>, <code>false</code>
064: * otherwise.
065: * @throws QueryExecutionException If the expression cannot be evaluated.
066: */
067: public boolean isTrue(Object o, Query q)
068: throws QueryExecutionException {
069:
070: // Get the value for the lhs.
071: Object l = null;
072:
073: try {
074:
075: l = this .left.getValue(o, q);
076:
077: } catch (Exception e) {
078:
079: throw new QueryExecutionException(
080: "Unable to get value for LHS of expression: "
081: + this , e);
082:
083: }
084:
085: Object r = null;
086:
087: try {
088:
089: r = this .right.getValue(o, q);
090:
091: } catch (Exception e) {
092:
093: throw new QueryExecutionException(
094: "Unable to get value for RHS of expression: "
095: + this , e);
096:
097: }
098:
099: if ((l == null) && (r == null)) {
100:
101: // Debatable about whether 2 nulls make a true...
102: if (this .not) {
103:
104: return false;
105:
106: }
107:
108: return true;
109:
110: }
111:
112: if ((l == null) || (r == null)) {
113:
114: if (this .not) {
115:
116: return true;
117:
118: }
119:
120: // One of them is null, can't do any checking...
121: return false;
122:
123: }
124:
125: // If we are here then both are NOT NULL.
126: return Utilities.matches(l, r, this .ignoreCase, 4, this .not);
127:
128: /*
129: if (this.ignoreCase)
130: {
131:
132: // This means that we convert to a String for both and
133: // compare case-insensitive.
134: String ls = l.toString ();
135:
136: String rs = r.toString ();
137:
138: if ((ls == null)
139: ||
140: (rs == null)
141: )
142: {
143:
144: // Can't compare nulls.
145: return false;
146:
147: }
148:
149: boolean eq = ls.equalsIgnoreCase (rs);
150:
151: if ((this.not)
152: &&
153: (!eq)
154: )
155: {
156:
157: return true;
158:
159: }
160:
161: if (eq)
162: {
163:
164: return true;
165:
166: }
167:
168: return false;
169:
170: }
171:
172: // See if one of the sides is a number.
173: boolean ln = Utilities.isNumber (l);
174: boolean rn = Utilities.isNumber (r);
175:
176: if (ln
177: &&
178: rn
179: )
180: {
181:
182: // They are numbers...
183: double ld = Utilities.getDouble (l);
184: double rd = Utilities.getDouble (r);
185:
186: if (ld == rd)
187: {
188:
189: if (this.not)
190: {
191:
192: return false;
193:
194: }
195:
196: return true;
197:
198: }
199:
200: if (this.not)
201: {
202:
203: return true;
204:
205: }
206:
207: return false;
208:
209: }
210:
211: // See if the 2 sides are "comparable".
212: // Need to check to see if they are the "same" type... otherwise a CCE will result.
213: if ((l instanceof Comparable)
214: &&
215: (r instanceof Comparable)
216: &&
217: (l.getClass ().isAssignableFrom (r.getClass ()))
218: )
219: {
220:
221: Comparable lc = (Comparable) l;
222: Comparable rc = (Comparable) r;
223:
224: boolean eq = lc.compareTo (rc) == 0;
225:
226: if ((this.not)
227: &&
228: (!eq)
229: )
230: {
231:
232: return true;
233:
234: }
235:
236: if (eq)
237: {
238:
239: return true;
240:
241: }
242:
243: return false;
244:
245: }
246:
247: // If we are here then one or more of the items does NOT implement Comparable.
248: // Force a string comparison.
249:
250: String ls = l.toString ();
251:
252: String rs = r.toString ();
253:
254: if (ls == null)
255: {
256:
257: ls = "";
258:
259: }
260:
261: if (rs == null)
262: {
263:
264: rs = "";
265:
266: }
267:
268: boolean eq = false;
269:
270: if (this.ignoreCase)
271: {
272:
273: eq = ls.equalsIgnoreCase (rs);
274:
275: } else {
276:
277: eq = ls.equals (rs);
278:
279: }
280:
281: if (eq)
282: {
283:
284: if (this.not)
285: {
286:
287: return false;
288:
289: }
290:
291: return true;
292:
293: } else {
294:
295: if (this.not)
296: {
297:
298: return true;
299:
300: }
301:
302: return false;
303:
304: }
305: */
306:
307: }
308:
309: /**
310: * Return a string version of the expression.
311: * In the form: {@link Expression#toString() Expression} [ $ ] [ ! ] = {@link Expression#toString() Expression}
312: *
313: * @return The string version.
314: */
315: public String toString() {
316:
317: String pred = "=";
318:
319: if (this .not) {
320:
321: pred = "!=";
322:
323: }
324:
325: if (this .ignoreCase) {
326:
327: pred = "$" + pred;
328:
329: }
330:
331: if (this .isBracketed()) {
332:
333: return "(" + this .left.toString() + " " + pred + " "
334: + this .right.toString() + ")";
335:
336: }
337:
338: return this .left.toString() + " " + pred + " "
339: + this.right.toString();
340:
341: }
342:
343: }
|