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: import org.josql.QueryParseException;
020:
021: import org.josql.internal.Utilities;
022:
023: /**
024: * Represents a "BETWEEN x AND y" expression.
025: */
026: public class BetweenExpression extends BinaryExpression {
027:
028: private ValueExpression start = null;
029: private ValueExpression end = null;
030: private boolean not = false;
031: private boolean leftFR = false;
032: private boolean startFR = false;
033: private boolean endFR = false;
034: private Object leftFRVal = null;
035: private Object startFRVal = null;
036: private Object endFRVal = null;
037:
038: /**
039: * Inits the expression.
040: *
041: * @param q The Query object.
042: * @throws QueryParseException If the LHS, start or end cannot be inited.
043: */
044: public void init(Query q) throws QueryParseException {
045:
046: this .left.init(q);
047:
048: this .start.init(q);
049: this .end.init(q);
050:
051: this .leftFR = this .left.hasFixedResult(q);
052: this .startFR = this .start.hasFixedResult(q);
053: this .endFR = this .end.hasFixedResult(q);
054:
055: }
056:
057: /**
058: * Get the start expression.
059: *
060: * @return The start expression, is an instance of {@link ValueExpression}.
061: */
062: public Expression getStart() {
063:
064: return this .start;
065:
066: }
067:
068: /**
069: * Get the end expression.
070: *
071: * @return The end expression, is an instance of {@link ValueExpression}.
072: */
073: public Expression getEnd() {
074:
075: return this .end;
076:
077: }
078:
079: public void setEnd(ValueExpression e) {
080:
081: this .end = e;
082:
083: }
084:
085: public void setStart(ValueExpression s) {
086:
087: this .start = s;
088:
089: }
090:
091: public boolean isNot() {
092:
093: return this .not;
094:
095: }
096:
097: public void setNot(boolean v) {
098:
099: this .not = v;
100:
101: }
102:
103: /**
104: * Return whether this expression evaluates to <code>true</code>.
105: *
106: * Is equivalent to: LHS >= START AND LHS <= END. And of course if the
107: * expression is NOTed then it returns !(LHS >= START AND LHS <= END).
108: *
109: * @param o The object to perform the expression on.
110: * @param q The Query object.
111: * @return <code>true</code> if the LHS is between the start and end values.
112: * @throws QueryExecutionException If the expression cannot be executed.
113: */
114: public boolean isTrue(Object o, Query q)
115: throws QueryExecutionException {
116:
117: Object l = null;
118:
119: if (this .leftFR) {
120:
121: if (this .leftFRVal == null) {
122:
123: l = this .left.getValue(o, q);
124:
125: this .leftFRVal = l;
126:
127: } else {
128:
129: l = this .leftFRVal;
130:
131: }
132:
133: } else {
134:
135: l = this .left.getValue(o, q);
136:
137: if (this .leftFR) {
138:
139: this .leftFRVal = l;
140:
141: }
142:
143: }
144:
145: Object s = null;
146:
147: if (this .startFR) {
148:
149: if (this .startFRVal == null) {
150:
151: s = this .start.getValue(o, q);
152:
153: this .startFRVal = s;
154:
155: } else {
156:
157: s = this .startFRVal;
158:
159: }
160:
161: } else {
162:
163: s = this .start.getValue(o, q);
164:
165: if (this .startFR) {
166:
167: this .startFRVal = s;
168:
169: }
170:
171: }
172:
173: Object e = null;
174:
175: if (this .endFR) {
176:
177: if (this .endFRVal == null) {
178:
179: e = this .end.getValue(o, q);
180:
181: this .endFRVal = e;
182:
183: } else {
184:
185: e = this .endFRVal;
186:
187: }
188:
189: } else {
190:
191: e = this .end.getValue(o, q);
192:
193: if (this .endFR) {
194:
195: this .endFRVal = e;
196:
197: }
198:
199: }
200:
201: // See if the LHS is >= s.
202: boolean sb = Utilities.isGTEquals(l, s);
203:
204: boolean eb = Utilities.isLTEquals(l, e);
205:
206: if (!this .not && sb && eb) {
207:
208: return true;
209:
210: }
211:
212: if (this .not && (!sb || !eb)) {
213:
214: return true;
215:
216: }
217:
218: return false;
219:
220: }
221:
222: /**
223: * Returns a string version of this expression.
224: * Will return the form:
225: * <p>
226: * <pre>
227: * {@link Expression#toString() Expression} [ NOT ] BETWEEN {@link Expression#toString() Expression} AND {@link Expression#toString() Expression}
228: * </pre>
229: *
230: * @return A string version of the expression.
231: */
232: public String toString() {
233:
234: StringBuffer buf = new StringBuffer(this .left.toString());
235:
236: if (this .not) {
237:
238: buf.append(" NOT");
239:
240: }
241:
242: buf.append(" BETWEEN ");
243:
244: buf.append(this .start);
245: buf.append(" AND ");
246: buf.append(this .end);
247:
248: if (this .isBracketed()) {
249:
250: buf.insert(0, "(");
251:
252: buf.append(")");
253:
254: }
255:
256: return buf.toString();
257:
258: }
259:
260: }
|