001: package org.osbl.agent.model.condition;
002:
003: import org.osbl.agent.model.Condition;
004: import org.osbl.agent.model.RuleContext;
005:
006: import bsh.EvalError;
007: import bsh.Interpreter;
008:
009: /**
010: * This Condition class executes a beanshell script and evaluates to <code>true</code> if
011: * the script's last expression is either <code>true</code> (primitive or wrapper class)
012: * or, for any other type, not null.
013: *
014: * At evaluation time, a variable <code>subject</code> is bound to the subjectInstance of
015: * the runtime context, so that beanshell scripts can refer to this value.
016: *
017: * @see http://www.beanshell.org/
018: * @author Sebastian Nozzi.
019: */
020: public class BeanShellCondition implements Condition {
021:
022: /** The beanshell script source-code. */
023: private String script;
024:
025: /**
026: * Instantiates a new beanshell condition with an initial script source-code.
027: *
028: * @param script the script
029: */
030: public BeanShellCondition(String script) {
031: this .script = script;
032: }
033:
034: /**
035: * Instantiates a new beanshell condition.
036: */
037: public BeanShellCondition() {
038: }
039:
040: /**
041: * Gets the script's source-code.
042: *
043: * @return the script's souce-code.
044: */
045: public String getScript() {
046: return script;
047: }
048:
049: /**
050: * Sets the script source-code.
051: *
052: * @param script the new script's souce-code.
053: */
054: public void setScript(String script) {
055: this .script = script;
056: }
057:
058: /**
059: * *
060: * Evaluates the beanshell script and returns <code>true</code> if the last
061: * expression of the script evaluates to <code>true<code> or, in case its
062: * type is neither boolean or Boolean, the last expression is not null.
063: *
064: * In case the script is empty, not set or has errors, it returns false.
065: *
066: * @param context the context
067: *
068: * @return true, if evaluate
069: *
070: * @see org.osbl.agent.model.condition.Condition#evaluate(org.osbl.agent.model.RuleContext)
071: */
072: public boolean evaluate(RuleContext context) {
073:
074: // Only evaluate if there is a script to execute
075: if (script != null && script.equals("") == false) {
076:
077: // Instantiate a BeanShell interpreter.
078: Interpreter bsh = new Interpreter();
079:
080: try {
081: // Make "subject" a predefined variable in the interpreter's context.
082: // "subject" will refer to our subjectInstance...
083: bsh.set("subject", context.getTargetObject());
084:
085: // Finally, evaluate script.
086: Object result = bsh.eval(script);
087:
088: if (result != null) {
089:
090: // If the script evaluated to a primitive "boolean" (not Boolean), Beanshell
091: // will return the result as a bsh.Primitive. By calling getValue() on it
092: // we get the corresponging Java wrapper class (and maybe Boolean).
093: // The test for "Boolean" is done below anyway...
094: if (result instanceof bsh.Primitive)
095: result = ((bsh.Primitive) result).getValue();
096:
097: // If the result is a valid Boolean...
098: if (result instanceof Boolean)
099: // ...return its booleanValue.
100: return ((Boolean) result).booleanValue();
101: }
102:
103: // If we got here the result was either "null" or not a boolean.
104: // We'll evaluate to "false" only if the evaluation is explicitly "false"
105: // or "null"...
106: return result != null;
107:
108: } catch (EvalError e) {
109: e.printStackTrace();
110: }
111: }
112:
113: // If there was no script to evaluate, return our default behaviour.
114: return false;
115: }
116:
117: /* (non-Javadoc)
118: * @see java.lang.Object#equals(java.lang.Object)
119: */
120: public boolean equals(Object obj) {
121:
122: if (this == obj)
123: return true;
124:
125: if (obj instanceof BeanShellCondition == false)
126: return false;
127:
128: BeanShellCondition other = (BeanShellCondition) obj;
129:
130: return (script.equals(other.script));
131: }
132: }
|