001: /*
002: * $Id: Evaluation.java,v 1.1 2003/08/19 01:12:57 jonesde Exp $
003: *
004: * Copyright (c) 1999 Steven J. Metsker.
005: * Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
006: *
007: * Permission is hereby granted, free of charge, to any person obtaining a
008: * copy of this software and associated documentation files (the "Software"),
009: * to deal in the Software without restriction, including without limitation
010: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
011: * and/or sell copies of the Software, and to permit persons to whom the
012: * Software is furnished to do so, subject to the following conditions:
013: *
014: * The above copyright notice and this permission notice shall be included
015: * in all copies or substantial portions of the Software.
016: *
017: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
018: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
019: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
020: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
021: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
022: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
023: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
024: */
025:
026: package org.ofbiz.rules.engine;
027:
028: /**
029: * An Evaluation unifies a term with the value of another term.
030: * <p>
031: * For example,
032: *
033: * <blockquote><pre>
034: * NumberFact two = new NumberFact(2);
035: * ArithmeticOperator x, y;
036: * x = new ArithmeticOperator('*', two, two);
037: * y = new ArithmeticOperator('+', x, two);
038: *
039: * Variable result = new Variable("Result");
040: * Evaluation e = new Evaluation(result, y);
041: * System.out.println(e);
042: * System.out.println(e.canFindNextProof());
043: * System.out.println(result);
044: *
045: * </pre></blockquote>
046: *
047: * prints out:
048: *
049: * <blockquote><pre>
050: * #(Result, +(*(2.0, 2.0), 2.0))
051: * true
052: * 6.0
053: * </pre></blockquote>
054: *
055: * <p>
056: * Since an Evaluation <i>unifies</i> the first term with the
057: * arithmetic value, the second term may have a value before
058: * the Evaluation proves itself. In this case, the Evaluation
059: * checks that the second term's ground value equals the
060: * arithmetic value of the first term.
061: * <p>
062: * The Evaluation fails if the arithmetic value is invalid for
063: * any reason.
064: *
065: * @author Steven J. Metsker
066: * @version 1.0
067: */
068:
069: public class Evaluation extends Gateway {
070: Term term0;
071: Term term1;
072: protected Unification currentUnification;
073:
074: /**
075: * Constructs an Evaluation that will unify the first term
076: * with the second term during proofs.
077: *
078: * @param Term the first term to unify
079: *
080: * @param Term the term whose value should unify
081: * with the first term
082: */
083: public Evaluation(Term term0, Term term1) {
084: super ("#", new Term[] { term0, term1 });
085: this .term0 = term0;
086: this .term1 = term1;
087: }
088:
089: /**
090: * Returns true if this Evaluation can unify its first term
091: * with the value of its second term.
092: * <p>
093: * If the attempt to evaluate the second term causes an
094: * exception, this method swallows it and simply fails.
095: *
096: * @return <code>true<</code>, if this Evaluation can unify
097: * its first term with the arithmetic value of its
098: * second term
099: */
100: public boolean canProveOnce() {
101: Object o;
102:
103: try {
104: o = term1.eval();
105: } catch (EvaluationException e) {
106: return false;
107: }
108: currentUnification = term0.unify(new Atom(o));
109: return currentUnification != null;
110: }
111:
112: /**
113: * The superclass calls this after the evaluation has
114: * succeeded once, and rule is now failing backwards. The
115: * assigment needs to undo any binding it did on the way
116: * forward.
117: */
118: protected void cleanup() {
119: unbind();
120: }
121:
122: /**
123: * Create a copy that uses the provided scope.
124: *
125: * @param AxiomSource ignored
126: *
127: * @param Scope the scope to use for variables in the
128: * copy
129: *
130: * @return a copy that uses the provided scope
131: */
132: public Term copyForProof(AxiomSource ignored, Scope scope) {
133: return new Evaluation(term0.copyForProof(null, scope), term1
134: .copyForProof(null, scope));
135: }
136:
137: /**
138: * Releases the variable bindings that the last unification produced.
139: *
140: */
141: public void unbind() {
142: if (currentUnification != null) {
143: currentUnification.unbind();
144: }
145: currentUnification = null;
146: }
147: }
|