/** * forward an execute request a rule identified by its unique key * * @param key a string key identifying the rule instance to be fired * @param recipient the recipient of the method from which execution of the rule was triggered or * null if it was a static method * @param args the arguments of the method from which execution of the rule was triggered */ public static void execute(String key, Object recipient, Object[] args) throws ExecuteException { boolean enabled = isTriggeringEnabled(); if (!enabled) { // we don't trigger code while we are doing rule housekeeping return; } // disable triggering until we get into actual rule code disableTriggersInternal(); try { Rule rule = ruleKeyMap.get(key); if (Transformer.isVerbose()) { System.out.println("Rule.execute called for " + key); } // if the key is no longer present it just means the rule has been decommissioned so return if (rule == null) { if (Transformer.isVerbose()) { System.out.println("Rule.execute for decommissioned key " + key); } return; } rule.execute(recipient, args); } finally { // restore the status quo -- we must have been enabled if we got to this method enableTriggers(); } }
public Object interpret(HelperAdapter helper) throws ExecuteException { Object recipientValue = null; try { if (recipient != null) { recipientValue = recipient.interpret(helper); if (recipientValue == null) { throw new ExecuteException( "MethodExpression.interpret : null recipient for method " + token.getText() + getPos()); } } int argCount = arguments.size(); Object[] argValues = new Object[argCount]; for (int i = 0; i < argCount; i++) { argValues[i] = arguments.get(i).interpret(helper); } // execute setTriggering directly rather than via reflection // that way rule code switch off triggering for a rule injected // into code used by Method.invoke() if (method.equals(setTriggeringMethod)) { boolean setting = (Boolean) argValues[0]; if (setting) { Rule.enableTriggers(); } else { Rule.disableTriggers(); } return true; } // we have to enable triggers whenever we call out to a method in case it contians a trigger // point // TODO - do we do this if the method is a built-in? i.e. if the target is an instance of the // helper class // TODO - this breaks the user disable option so fix it! Rule.enableTriggersInternal(); return method.invoke(recipientValue, argValues); } catch (InvocationTargetException e) { Throwable th = e.getCause(); if (th instanceof ExecuteException) { throw (ExecuteException) th; } else { throw new ExecuteException( "MethodExpression.interpret : exception invoking method " + token.getText() + getPos(), th); } } catch (ExecuteException e) { throw e; } catch (Exception e) { throw new ExecuteException( "MethodExpression.interpret : exception invoking method " + token.getText() + getPos(), e); } finally { // disable triggers again Rule.disableTriggersInternal(); } }