001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.nativequery.expr.build;
022:
023: import com.db4o.nativequery.expr.*;
024: import com.db4o.nativequery.expr.cmp.*;
025: import com.db4o.nativequery.expr.cmp.operand.*;
026:
027: public class ExpressionBuilder {
028: /**
029: * Optimizations: !(Bool)->(!Bool), !!X->X, !(X==Bool)->(X==!Bool)
030: */
031: public Expression not(Expression expr) {
032: if (expr.equals(BoolConstExpression.TRUE)) {
033: return BoolConstExpression.FALSE;
034: }
035: if (expr.equals(BoolConstExpression.FALSE)) {
036: return BoolConstExpression.TRUE;
037: }
038: if (expr instanceof NotExpression) {
039: return ((NotExpression) expr).expr();
040: }
041: if (expr instanceof ComparisonExpression) {
042: ComparisonExpression cmpExpr = (ComparisonExpression) expr;
043: if (cmpExpr.right() instanceof ConstValue) {
044: ConstValue rightConst = (ConstValue) cmpExpr.right();
045: if (rightConst.value() instanceof Boolean) {
046: Boolean boolVal = (Boolean) rightConst.value();
047: // new Boolean() instead of Boolean.valueOf() for .NET conversion
048: return new ComparisonExpression(cmpExpr.left(),
049: new ConstValue(new Boolean(!boolVal
050: .booleanValue())), cmpExpr.op());
051: }
052: }
053: }
054: return new NotExpression(expr);
055: }
056:
057: /**
058: * Optimizations: f&&X->f, t&&X->X, X&&X->X, X&&!X->f
059: */
060: public Expression and(Expression left, Expression right) {
061: if (left.equals(BoolConstExpression.FALSE)
062: || right.equals(BoolConstExpression.FALSE)) {
063: return BoolConstExpression.FALSE;
064: }
065: if (left.equals(BoolConstExpression.TRUE)) {
066: return right;
067: }
068: if (right.equals(BoolConstExpression.TRUE)) {
069: return left;
070: }
071: if (left.equals(right)) {
072: return left;
073: }
074: if (negatives(left, right)) {
075: return BoolConstExpression.FALSE;
076: }
077: return new AndExpression(left, right);
078: }
079:
080: /**
081: * Optimizations: X||t->t, f||X->X, X||X->X, X||!X->t
082: */
083: public Expression or(Expression left, Expression right) {
084: if (left.equals(BoolConstExpression.TRUE)
085: || right.equals(BoolConstExpression.TRUE)) {
086: return BoolConstExpression.TRUE;
087: }
088: if (left.equals(BoolConstExpression.FALSE)) {
089: return right;
090: }
091: if (right.equals(BoolConstExpression.FALSE)) {
092: return left;
093: }
094: if (left.equals(right)) {
095: return left;
096: }
097: if (negatives(left, right)) {
098: return BoolConstExpression.TRUE;
099: }
100: return new OrExpression(left, right);
101: }
102:
103: /**
104: * Optimizations: static bool roots
105: */
106: public BoolConstExpression constant(Boolean value) {
107: return BoolConstExpression.expr(value.booleanValue());
108: }
109:
110: public Expression ifThenElse(Expression cond, Expression truePath,
111: Expression falsePath) {
112: Expression expr = checkBoolean(cond, truePath, falsePath);
113: if (expr != null) {
114: return expr;
115: }
116: return or(and(cond, truePath), and(not(cond), falsePath));
117: }
118:
119: private Expression checkBoolean(Expression cmp,
120: Expression trueExpr, Expression falseExpr) {
121: if (cmp instanceof BoolConstExpression) {
122: return null;
123: }
124: if (trueExpr instanceof BoolConstExpression) {
125: boolean leftNegative = trueExpr
126: .equals(BoolConstExpression.FALSE);
127: if (!leftNegative) {
128: return or(cmp, falseExpr);
129: } else {
130: return and(not(cmp), falseExpr);
131: }
132: }
133: if (falseExpr instanceof BoolConstExpression) {
134: boolean rightNegative = falseExpr
135: .equals(BoolConstExpression.FALSE);
136: if (!rightNegative) {
137: return and(cmp, trueExpr);
138: } else {
139: return or(not(cmp), falseExpr);
140: }
141: }
142: if (cmp instanceof NotExpression) {
143: cmp = ((NotExpression) cmp).expr();
144: Expression swap = trueExpr;
145: trueExpr = falseExpr;
146: falseExpr = swap;
147: }
148: if (trueExpr instanceof OrExpression) {
149: OrExpression orExpr = (OrExpression) trueExpr;
150: Expression orLeft = orExpr.left();
151: Expression orRight = orExpr.right();
152: if (falseExpr.equals(orRight)) {
153: Expression swap = orRight;
154: orRight = orLeft;
155: orLeft = swap;
156: }
157: if (falseExpr.equals(orLeft)) {
158: return or(orLeft, and(cmp, orRight));
159: }
160: }
161: if (falseExpr instanceof AndExpression) {
162: AndExpression andExpr = (AndExpression) falseExpr;
163: Expression andLeft = andExpr.left();
164: Expression andRight = andExpr.right();
165: if (trueExpr.equals(andRight)) {
166: Expression swap = andRight;
167: andRight = andLeft;
168: andLeft = swap;
169: }
170: if (trueExpr.equals(andLeft)) {
171: return and(andLeft, or(cmp, andRight));
172: }
173: }
174: return null;
175: }
176:
177: private boolean negatives(Expression left, Expression right) {
178: return negativeOf(left, right) || negativeOf(right, left);
179: }
180:
181: private boolean negativeOf(Expression right, Expression left) {
182: return (right instanceof NotExpression)
183: && ((NotExpression) right).expr().equals(left);
184: }
185: }
|