001: package org.ofbiz.rules.engine;
002:
003: /**
004: * <p><b>Title:</b> Arithmetic Operator
005: * <p><b>Description:</b> None
006: * <p>Copyright (c) 1999 Steven J. Metsker.
007: * <p>Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
008: *
009: * <p>Permission is hereby granted, free of charge, to any person obtaining a
010: * copy of this software and associated documentation files (the "Software"),
011: * to deal in the Software without restriction, including without limitation
012: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
013: * and/or sell copies of the Software, and to permit persons to whom the
014: * Software is furnished to do so, subject to the following conditions:
015: *
016: * <p>The above copyright notice and this permission notice shall be included
017: * in all copies or substantial portions of the Software.
018: *
019: * <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
020: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
021: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
022: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
023: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
024: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
025: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
026: *
027: * <br>
028: * <p>An ArithmeticOperator represents an arithmetic operation
029: * that will perform itself as part of a proof.
030: * <p>
031: * An ArithmeticOperator has an operator and two terms. The
032: * operator must be '+', '-', '/', '*' or '%', or else the
033: * eval() value of this object will always be 0. The
034: * terms may be other arithmetic operators, variables, or
035: * number structures.
036: * <p>
037: * For example, an ArithmeticOperator might be appear in a
038: * comparison, as follows:
039: * <blockquote><pre>
040: * >(+(X, 3), 42)
041: * </pre></blockquote>
042: * The arithmetic operator will have a valid value if X is
043: * instantiated to a NumberStructure object. If X is
044: * instantiated to, say, 40, then the arithmetic operator's
045: * reply to eval() will be 47, and the comparison
046: * will succeed.
047: *
048: * @author Steven J. Metsker
049: * @version 1.0
050: */
051:
052: public class ArithmeticOperator extends Structure implements
053: ArithmeticTerm {
054: protected char operator;
055: protected ArithmeticTerm term0;
056: protected ArithmeticTerm term1;
057:
058: /**
059: * Constructs an arithmetic operator with the indicated operator and
060: * terms.
061: * <p>
062: * The operator must be '+', '-', '/', '*' or '%', or else the
063: * eval() value of this object will always be 0. The terms must be
064: * other arithmetic operators, variables, or number structures. If either
065: * term is invalid, this object will throw an EvaluationException during a
066: * proof.
067: *
068: * @param char the operator
069: *
070: * @param ArithmeticTerm the first term
071: *
072: * @param ArithmeticTerm the second term
073: *
074: */
075: public ArithmeticOperator(char operator, ArithmeticTerm term0,
076: ArithmeticTerm term1) {
077: super (new Character(operator), new Term[] { term0, term1 });
078: this .operator = operator;
079: this .term0 = term0;
080: this .term1 = term1;
081: }
082:
083: /** Do the math. */
084: protected Object arithmeticValue(double d0, double d1) {
085: double result = 0;
086:
087: switch (operator) {
088: case '+':
089: result = d0 + d1;
090: break;
091:
092: case '-':
093: result = d0 - d1;
094: break;
095:
096: case '*':
097: result = d0 * d1;
098: break;
099:
100: case '/':
101: result = d0 / d1;
102: break;
103:
104: case '%':
105: result = d0 % d1;
106: break;
107:
108: default:
109: result = 0.0;
110: }
111: return new Double(result);
112: }
113:
114: /**
115: * Create a copy using the supplied scope for variables.
116: *
117: * @param AxiomSource ignored
118: *
119: * @param Scope the scope to use for variables
120: *
121: * @return a copy with variables from the supplied scope
122: */
123: public Term copyForProof(AxiomSource ignored, Scope scope) {
124: return new ArithmeticOperator(operator, (ArithmeticTerm) term0
125: .copyForProof(null, scope), (ArithmeticTerm) term1
126: .copyForProof(null, scope));
127: }
128:
129: /**
130: * Returns the result of applying this object's operator
131: * against the arithmetic values of its two terms. For
132: * example,
133: *
134: * <blockquote><pre>
135: * NumberStructure two = new NumberStructure(2);
136: * ArithmeticOperator x, y;
137: * x = new ArithmeticOperator('*', two, two);
138: * y = new ArithmeticOperator('+', x, two);
139: * System.out.println(y + " = " + y.eval());
140: * </pre></blockquote>
141: *
142: * prints out:
143: *
144: * <blockquote><pre>
145: * +(*(2, 2), 2) = 6.0
146: * </pre></blockquote>
147: *
148: * @return the result of applying this object's operator to
149: * the arithmetic value of its two terms
150: *
151: * @exception EvaluationException if either term is not a
152: * valid arithmetic value
153: */
154: public Object eval() {
155:
156: double d0 = eval(term0);
157: double d1 = eval(term1);
158:
159: return arithmeticValue(d0, d1);
160: }
161:
162: /** get the "double" value of this term */
163: protected double eval(ArithmeticTerm t) {
164: Object o = t.eval();
165:
166: if (o == null) {
167: throw new EvaluationException(t + " is undefined in "
168: + this );
169: }
170: if (!(o instanceof Number)) {
171: throw new EvaluationException(t + " is not a number in "
172: + this );
173: }
174: Number n = (Number) o;
175:
176: return n.doubleValue();
177: }
178: }
|