001: package org.osbl.agent.model.condition;
002:
003: import org.osbl.agent.model.RuleContext;
004:
005: import ognl.Ognl;
006: import ognl.OgnlException;
007:
008: /**
009: * This class represents an operator which can be used in Conditions to evaluate the
010: * operands specified in them.
011: *
012: * It is defined abstract to allow different kinds of operators.
013: *
014: * At the time of evaluation the concrete class of the operator has to provide a valid
015: * Java expression by overriding {@link #getExpression(String, String)}. For constructing
016: * such expression, the implementation can (and generally will) use whatever is stored
017: * in the operatorCode.
018: *
019: * For presentation purposes (for example when adding it to a ComboBox) it is possible
020: * to assign a descriptive user friendly label to the operator.
021: *
022: * @author Sebastian Nozzi.
023: */
024: public abstract class Operator {
025:
026: /** Some piece of code that aids the operator class to construct its evaluating expression. */
027: private String operatorCode;
028:
029: /** A descriptive label for the operator. */
030: private String label;
031:
032: /** Wether the result of the evaluation should be negated or not. */
033: private boolean negated;
034:
035: /**
036: * Instantiates a new operator.
037: */
038: public Operator() {
039: }
040:
041: /**
042: * Instantiates a new operator with a given String, serving both for code and for label.
043: *
044: * @param operatorString the operator string.
045: */
046: public Operator(String operatorString) {
047: this (operatorString, operatorString);
048: }
049:
050: /**
051: * Instantiates a new operator, specifying label and code.
052: *
053: * @param label the label.
054: * @param operatorCode the operator code.
055: */
056: public Operator(String label, String operatorCode) {
057: setOperatorCode(operatorCode);
058: setLabel(label);
059: }
060:
061: /**
062: * Gets the a descriptive label of the operator.
063: *
064: * @return the label
065: */
066: public String getLabel() {
067: return label;
068: }
069:
070: /**
071: * Sets a descriptive label for the operator.
072: *
073: * @param label the new label.
074: */
075: public void setLabel(String label) {
076: this .label = label;
077: }
078:
079: /**
080: * Gets the operator code.
081: *
082: * @return the operator code.
083: */
084: public String getOperatorCode() {
085: return operatorCode;
086: }
087:
088: /**
089: * Sets the operator code, which aids the operator class to construct its evaluating expression.
090: *
091: * @param operatorCode the new operator code.
092: */
093: public void setOperatorCode(String operatorCode) {
094: this .operatorCode = operatorCode;
095: }
096:
097: /**
098: * Checks if the result of the evaluation will be negated.
099: *
100: * @return true, if result will be negated.
101: */
102: public boolean isNegated() {
103: return negated;
104: }
105:
106: /**
107: * Sets wether the result of the evaluation via this operator will be negated or not.
108: *
109: * @param negated true, if it should be negated, false if not.
110: */
111: public void setNegated(boolean negated) {
112: this .negated = negated;
113: }
114:
115: /**
116: * Two operators are equal if their classes match and their internal code matches (which
117: * is used in constructing the evaluating expression and therefor is a vital and
118: * differentiating part of an operator).
119: *
120: * If the classes don't match, the default implementation is used.
121: *
122: * @param obj the obj
123: *
124: * @return true, if equals
125: *
126: * @see java.lang.Object#equals(java.lang.Object)
127: */
128: public boolean equals(Object obj) {
129: // Two Operators are equal if...
130: if (getClass().equals(obj.getClass())) {
131: // ... the class is strictly the same and the operatorCode is the
132: // same (which is used for constructing the evaluation expression.
133: return ((Operator) obj).getOperatorCode() == this .operatorCode;
134: } else
135: return false;
136: }
137:
138: /**
139: * Uses the specified label to return a friendly String version.
140: *
141: * @return the string
142: *
143: * @see #setLabel(String)
144: * @see #getLabel()
145: * @see java.lang.Object#toString()
146: */
147: public String toString() {
148: return getLabel();
149: }
150:
151: /**
152: * Perform the defined evaluation in this operator. The passed parameters left and rightExpression
153: * are also implementation dependant. They would be typically the left and right operands.
154: *
155: * A "root object" also has to be specified, for which all references to methods and/or
156: * fields are relative to.
157: *
158: * @param leftExpression the left expression, or operand
159: * @param rightExpression the right expression, or operand
160: * @param context the context
161: *
162: * @return the boolean result if the evaluation was successful, false in case of error.
163: */
164: public boolean evaluate(String leftExpression,
165: String rightExpression, RuleContext context) {
166:
167: Object rootObject = context.getTargetObject();
168:
169: try {
170: // Get the expression that will be evaluated (provided by
171: // subclasses)
172: String expression = getExpression(leftExpression,
173: rightExpression);
174:
175: // If it should be negated, compare against "false"
176: if (isNegated())
177: expression = "(" + expression + ")==false";
178:
179: // Use OGNL to evaluate the expression.
180: // Our rootObject is the object to which the expression makes
181: // reference, for example, when refering to fields or methods.
182: return ((Boolean) Ognl.getValue(expression, context,
183: rootObject)).booleanValue();
184:
185: } catch (OgnlException e) {
186: e.printStackTrace();
187: return false;
188: }
189: }
190:
191: /**
192: * Subclasses override and implement this method, in which they should return a valid
193: * Java (actually OGNL) expression that is then evaluated.
194: *
195: * The implementation uses the given left and right parts and most certainly also
196: * the stored operatorCode (that defines more or less the nature of the operation).
197: *
198: * @param left the left part of the expression.
199: * @param right the right part of the expression.
200: *
201: * @return the expression as suitable for the concrete implemented operator.
202: */
203: protected abstract String getExpression(String left, String right);
204:
205: }
|