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.optimization;
022:
023: import java.lang.reflect.*;
024:
025: import com.db4o.instrumentation.core.*;
026: import com.db4o.nativequery.*;
027: import com.db4o.nativequery.expr.cmp.*;
028: import com.db4o.nativequery.expr.cmp.operand.*;
029:
030: final class ComparisonQueryGeneratingVisitor implements
031: ComparisonOperandVisitor {
032: private Object _predicate;
033:
034: private Object _value = null;
035:
036: private NativeClassFactory classSource;
037:
038: public Object value() {
039: return _value;
040: }
041:
042: public void visit(ConstValue operand) {
043: _value = operand.value();
044: }
045:
046: public void visit(FieldValue operand) {
047: operand.parent().accept(this );
048: Class clazz = ((operand.parent() instanceof StaticFieldRoot) ? (Class) _value
049: : _value.getClass());
050: try {
051: Field field = ReflectUtil.fieldFor(clazz, operand
052: .fieldName());
053: _value = field.get(_value); // arg is ignored for static
054: } catch (Exception exc) {
055: exc.printStackTrace();
056: }
057: }
058:
059: Object add(Object a, Object b) {
060: if (a instanceof Double || b instanceof Double) {
061: return new Double(((Double) a).doubleValue()
062: + ((Double) b).doubleValue());
063: }
064: if (a instanceof Float || b instanceof Float) {
065: return new Float(((Float) a).floatValue()
066: + ((Float) b).floatValue());
067: }
068: if (a instanceof Long || b instanceof Long) {
069: return new Long(((Long) a).longValue()
070: + ((Long) b).longValue());
071: }
072: return new Integer(((Integer) a).intValue()
073: + ((Integer) b).intValue());
074: }
075:
076: Object subtract(Object a, Object b) {
077: if (a instanceof Double || b instanceof Double) {
078: return new Double(((Double) a).doubleValue()
079: - ((Double) b).doubleValue());
080: }
081: if (a instanceof Float || b instanceof Float) {
082: return new Float(((Float) a).floatValue()
083: - ((Float) b).floatValue());
084: }
085: if (a instanceof Long || b instanceof Long) {
086: return new Long(((Long) a).longValue()
087: - ((Long) b).longValue());
088: }
089: return new Integer(((Integer) a).intValue()
090: - ((Integer) b).intValue());
091: }
092:
093: Object multiply(Object a, Object b) {
094: if (a instanceof Double || b instanceof Double) {
095: return new Double(((Double) a).doubleValue()
096: * ((Double) b).doubleValue());
097: }
098: if (a instanceof Float || b instanceof Float) {
099: return new Float(((Float) a).floatValue()
100: * ((Float) b).floatValue());
101: }
102: if (a instanceof Long || b instanceof Long) {
103: return new Long(((Long) a).longValue()
104: * ((Long) b).longValue());
105: }
106: return new Integer(((Integer) a).intValue()
107: * ((Integer) b).intValue());
108: }
109:
110: Object divide(Object a, Object b) {
111: if (a instanceof Double || b instanceof Double) {
112: return new Double(((Double) a).doubleValue()
113: / ((Double) b).doubleValue());
114: }
115: if (a instanceof Float || b instanceof Float) {
116: return new Float(((Float) a).floatValue()
117: / ((Float) b).floatValue());
118: }
119: if (a instanceof Long || b instanceof Long) {
120: return new Long(((Long) a).longValue()
121: / ((Long) b).longValue());
122: }
123: return new Integer(((Integer) a).intValue()
124: / ((Integer) b).intValue());
125: }
126:
127: public void visit(ArithmeticExpression operand) {
128: operand.left().accept(this );
129: Object left = _value;
130: operand.right().accept(this );
131: Object right = _value;
132: switch (operand.op().id()) {
133: case ArithmeticOperator.ADD_ID:
134: _value = add(left, right);
135: break;
136: case ArithmeticOperator.SUBTRACT_ID:
137: _value = subtract(left, right);
138: break;
139: case ArithmeticOperator.MULTIPLY_ID:
140: _value = multiply(left, right);
141: break;
142: case ArithmeticOperator.DIVIDE_ID:
143: _value = divide(left, right);
144: break;
145: }
146: }
147:
148: public void visit(CandidateFieldRoot root) {
149: }
150:
151: public void visit(PredicateFieldRoot root) {
152: _value = _predicate;
153: }
154:
155: public void visit(StaticFieldRoot root) {
156: try {
157: _value = classSource.forName(root.className());
158: } catch (ClassNotFoundException e) {
159: e.printStackTrace();
160: }
161: }
162:
163: public void visit(ArrayAccessValue operand) {
164: operand.parent().accept(this );
165: Object parent = _value;
166: operand.index().accept(this );
167: Integer index = (Integer) _value;
168: _value = Array.get(parent, index.intValue());
169: }
170:
171: public void visit(MethodCallValue operand) {
172: operand.parent().accept(this );
173: Object receiver = _value;
174: Object[] params = new Object[operand.args().length];
175: for (int paramIdx = 0; paramIdx < operand.args().length; paramIdx++) {
176: operand.args()[paramIdx].accept(this );
177: params[paramIdx] = _value;
178: }
179: Class clazz = receiver.getClass();
180: if (operand.parent().root() instanceof StaticFieldRoot
181: && clazz.equals(Class.class)) {
182: clazz = (Class) receiver;
183: }
184: Method method = ReflectUtil.methodFor(clazz, operand
185: .methodName(), operand.paramTypes());
186: try {
187: _value = method.invoke(receiver, params);
188: } catch (Exception exc) {
189: exc.printStackTrace();
190: _value = null;
191: }
192: }
193:
194: public ComparisonQueryGeneratingVisitor(Object predicate,
195: NativeClassFactory classSource) {
196: super();
197: this._predicate = predicate;
198: this.classSource = classSource;
199: }
200:
201: }
|