001: package org.ofbiz.rules.engine;
002:
003: /**
004: * <p><b>Title:</b> Comparison
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>A Comparison object applies a comparison operator to its
029: * terms in order to prove itself.
030: * <p>
031: * The functor of a comparison must be one of the strings, "<",
032: * ">", "<=", ">=", "=", or "!=", indicating comparison this
033: * object will perform during a proof. Any other functor will
034: * cause the comparison to always be false.
035: * <p>
036: * Here is an example of a comparison:
037: * <blockquote><pre>
038: * Atom alpha = new Atom("alpha");
039: * Atom beta = new Atom("beta");
040: * Comparison c = new Comparison("<=", alpha, beta);
041: * System.out.println(c + ", " + c.canFindNextProof());
042: * </pre></blockquote>
043: * This prints out:
044: * <blockquote><pre>
045: * <=(alpha, beta), true
046: * </pre></blockquote
047: *
048: * @author Steven J. Metsker
049: * @version 1.0
050: */
051: public class Comparison extends Gateway implements BooleanTerm {
052: String operator;
053: ComparisonTerm term0;
054: ComparisonTerm term1;
055:
056: /**
057: * Create a comparison with the specified operator and
058: * comparison terms.
059: *
060: * @param String the comparison operator
061: *
062: * @param ComparisonTerm the first term
063: *
064: * @param ComparisonTerm the second term
065: */
066: public Comparison(String operator, ComparisonTerm term0,
067: ComparisonTerm term1) {
068:
069: super (operator, new Term[] { term0, term1 });
070: this .operator = operator;
071: this .term0 = term0;
072: this .term1 = term1;
073: }
074:
075: /**
076: * Returns true if the comparison operator holds true between
077: * the values of this comparison's terms.
078: *
079: * @return <code>true</code> if the comparison operator holds
080: * true between the values of this comparison's terms.
081: */
082: public boolean canProveOnce() {
083: Object p0 = term0.eval();
084: Object p1 = term1.eval();
085:
086: if (!compare(p0, p1)) {
087: return false;
088: }
089: return true;
090: }
091:
092: /**
093: * Returns the result of comparing two objects, using the
094: * indicated comparison operator.
095: *
096: * @param Object a string or number to compare
097: *
098: * @param Object a string or number to compare
099: *
100: * @return the result of comparing two objects
101: */
102: protected boolean compare(Object obj0, Object obj1) {
103: if (obj0 instanceof Number && obj1 instanceof Number) {
104: return compareNumber((Number) obj0, (Number) obj1);
105: }
106: if (obj0 instanceof String && obj1 instanceof String) {
107: return compareString((String) obj0, (String) obj1);
108: }
109: return false;
110:
111: }
112:
113: /**
114: * Returns the result of comparing two Numbers, using the
115: * indicated comparison operator.
116: *
117: * @param Number a Number to compare
118: *
119: * @param Number a Number to compare
120: *
121: * @return the result of comparing the two numbers
122: */
123: protected boolean compareNumber(Number n0, Number n1) {
124:
125: double d0 = n0.doubleValue();
126: double d1 = n1.doubleValue();
127:
128: if (operator.equals(">")) {
129: return d0 > d1;
130: }
131: if (operator.equals("<")) {
132: return d0 < d1;
133: }
134: if (operator.equals("=")) {
135: return d0 == d1;
136: }
137: if (operator.equals(">=")) {
138: return d0 >= d1;
139: }
140: if (operator.equals("<=")) {
141: return d0 <= d1;
142: }
143: if (operator.equals("!=")) {
144: return d0 != d1;
145: }
146: return false;
147: }
148:
149: /**
150: * Returns the result of comparing two Strings, using the
151: * indicated comparison operator.
152: *
153: * @param String a String to compare
154: *
155: * @param String a String to compare
156: *
157: * @return the result of comparing the two strings
158: */
159: protected boolean compareString(String s0, String s1) {
160:
161: int comparison = s0.compareTo(s1);
162:
163: if (operator.equals(">")) {
164: return comparison > 0;
165: }
166: if (operator.equals("<")) {
167: return comparison < 0;
168: }
169: if (operator.equals("=")) {
170: return comparison == 0;
171: }
172: if (operator.equals(">=")) {
173: return comparison >= 0;
174: }
175: if (operator.equals("<=")) {
176: return comparison <= 0;
177: }
178: if (operator.equals("!=")) {
179: return comparison != 0;
180: }
181: return false;
182: }
183:
184: /**
185: * Create a copy that uses the provided scope.
186: *
187: * @param AxiomSource ignored
188: *
189: * @param Scope the scope to use for variables in the
190: * copy
191: *
192: * @return a copy that uses the provided scope
193: */
194: public Term copyForProof(AxiomSource ignored, Scope scope) {
195: return new Comparison(operator, (ComparisonTerm) term0
196: .copyForProof(null, scope), (ComparisonTerm) term1
197: .copyForProof(null, scope));
198: }
199:
200: /**
201: * Returns <code>Boolean.TRUE</code> if the comparison
202: * operator holds true between the values of the two
203: * terms.
204: *
205: * @return <code>Boolean.TRUE</code> if the comparison
206: * operator holds true between the values of the two
207: * terms.
208: */
209: public Object eval() {
210: return new Boolean(canProveOnce());
211: }
212: }
|