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: /**
021: * Represents either an <code>AND</code> expression or a <code>OR</code> expression.
022: * Lazy evaluation is employed here such if the expression is: <code>LHS OR RHS</code>
023: * and LHS = true then the RHS is NOT evaluated, if the expression is: <code>LHS AND RHS</code>
024: * and LHS = false then the RHS is NOT evaluated (see {@link #isTrue(Object,Query)}). This is important to note if you expect
025: * side-effects to occur in the RHS (bad practice anyway so don't do it!).
026: */
027: public class AndOrExpression extends BinaryExpression {
028:
029: private boolean and = false;
030:
031: public boolean isAnd() {
032:
033: return this .and;
034:
035: }
036:
037: public void setAnd(boolean v) {
038:
039: this .and = v;
040:
041: }
042:
043: /**
044: * Evaulates the expression and returns true if the expression evaulates to <code>true</code>.
045: * <p>
046: * <table border="1" cellpadding="3" cellspacing="0">
047: * <tr>
048: * <th>Type</th>
049: * <th>LHS</th>
050: * <th>RHS</th>
051: * <th>Result</th>
052: * <th>Notes</th>
053: * </tr>
054: * <tr>
055: * <td>AND</td>
056: * <td>true</td>
057: * <td>true</td>
058: * <td>true</td>
059: * <td>Both LHS and RHS are evaulated.</td>
060: * </tr>
061: * <tr>
062: * <td>AND</td>
063: * <td>true</td>
064: * <td>false</td>
065: * <td>false</td>
066: * <td>Both LHS and RHS are evaulated.</td>
067: * </tr>
068: * <tr>
069: * <td>AND</td>
070: * <td>false</td>
071: * <td>unknown or false</td>
072: * <td>false</td>
073: * <td>Only the LHS is evaulated.</td>
074: * </tr>
075: * <tr>
076: * <td>OR</td>
077: * <td>true</td>
078: * <td>unknown</td>
079: * <td>true</td>
080: * <td>Only the LHS is evaulated.</td>
081: * </tr>
082: * <tr>
083: * <td>OR</td>
084: * <td>false</td>
085: * <td>true</td>
086: * <td>true</td>
087: * <td>Both the LHS and RHS are evaulated.</td>
088: * </tr>
089: * <tr>
090: * <td>OR</td>
091: * <td>false</td>
092: * <td>false</td>
093: * <td>false</td>
094: * <td>Both the LHS and RHS are evaulated.</td>
095: * </tr>
096: * </table>
097: * <p>
098: * In general what this means is that you should "left-weight" your expressions so that
099: * the expression that returns <code>true</code> most often (or more likely to return
100: * <code>true</code>) should be on the LHS.
101: *
102: * @param o The current object to perform the expression on.
103: * @param q The query object.
104: * @return <code>true</code> if the expression evaulates to <code>true</code>, <code>false</code>
105: * otherwise.
106: * @throws QueryExecutionException If the expression cannot be evaulated.
107: */
108: public boolean isTrue(Object o, Query q)
109: throws QueryExecutionException {
110:
111: // Execute left first.
112: boolean l = this .left.isTrue(o, q);
113:
114: // See what our predicate is...
115: if (this .and) {
116:
117: if (!l) {
118:
119: return false;
120:
121: }
122:
123: boolean r = this .right.isTrue(o, q);
124:
125: return l && r;
126:
127: }
128:
129: if (l) {
130:
131: return true;
132:
133: }
134:
135: boolean r = this .right.isTrue(o, q);
136:
137: return r;
138:
139: }
140:
141: /**
142: * Return a string version of this expression.
143: * Note: any formatting of the statement (such as line breaks) will be removed.
144: *
145: * @return A string version of the expression.
146: */
147: public String toString() {
148:
149: String pred = " OR ";
150:
151: if (this .and) {
152:
153: pred = " AND ";
154:
155: }
156:
157: if (this .isBracketed()) {
158:
159: return "(" + this .left.toString() + pred
160: + this .right.toString() + ")";
161:
162: }
163:
164: return this.left.toString() + pred + this.right.toString();
165:
166: }
167:
168: }
|