public void build(BuildContext context, BuildUtils utils, RuleConditionElement rce) { NamedConsequence namedConsequence = (NamedConsequence) rce; Timer timer = context.getRule().getTimer(); if (timer != null) { ReteooComponentBuilder builder = utils.getBuilderFor(Timer.class); builder.build(context, utils, context.getRule().getTimer()); } RuleTerminalNode terminalNode = buildTerminalNodeForNamedConsequence(context, namedConsequence); terminalNode.attach(context); terminalNode.networkUpdated(new UpdateContext()); // adds the terminal node to the list of nodes created/added by this sub-rule context.getNodes().add(terminalNode); if (timer != null) { context.setTupleSource(context.getTupleSource().getLeftTupleSource()); } context.setTerminated(namedConsequence.isTerminal()); }
/** * This returns true is the rule is effective. If the rule is not effective, it cannot activate. * * <p>This uses the dateEffective, dateExpires and enabled flag to decide this. */ public boolean isEffective(Tuple tuple, RuleTerminalNode rtn, WorkingMemory workingMemory) { if (!this.enabled.getValue(tuple, rtn.getEnabledDeclarations(), this, workingMemory)) { return false; } if (this.dateEffective == null && this.dateExpires == null) { return true; } else { Calendar now = Calendar.getInstance(); now.setTimeInMillis(workingMemory.getSessionClock().getCurrentTime()); if (this.dateEffective != null && this.dateExpires != null) { return (now.after(this.dateEffective) && now.before(this.dateExpires)); } else if (this.dateEffective != null) { return (now.after(this.dateEffective)); } else { return (now.before(this.dateExpires)); } } }
private int fire( InternalWorkingMemory wm, AgendaFilter filter, int fireCount, int fireLimit, LinkedList<StackEntry> outerStack, InternalAgenda agenda, boolean fireUntilHalt) { int localFireCount = 0; if (!tupleList.isEmpty()) { RuleTerminalNode rtn = (RuleTerminalNode) pmem.getNetworkNode(); if (!fireExitedEarly && isDeclarativeAgendaEnabled()) { // Network Evaluation can notify meta rules, which should be given a chance to fire first RuleAgendaItem nextRule = agenda.peekNextRule(); if (!isHighestSalience(nextRule, ruleAgendaItem.getSalience())) { fireExitedEarly = true; return localFireCount; } } while (!tupleList.isEmpty()) { LeftTuple leftTuple; if (queue != null) { leftTuple = (LeftTuple) queue.dequeue(); tupleList.remove(leftTuple); } else { leftTuple = tupleList.removeFirst(); ((Activation) leftTuple).setQueued(false); } rtn = (RuleTerminalNode) leftTuple .getSink(); // branches result in multiple RTN's for a given rule, so unwrap per // LeftTuple RuleImpl rule = rtn.getRule(); PropagationContext pctx = leftTuple.getPropagationContext(); pctx = RuleTerminalNode.findMostRecentPropagationContext(leftTuple, pctx); // check if the rule is not effective or // if the current Rule is no-loop and the origin rule is the same then return if (cancelAndContinue(wm, rtn, rule, leftTuple, pctx, filter)) { continue; } AgendaItem item = (AgendaItem) leftTuple; if (agenda.getActivationsFilter() != null && !agenda.getActivationsFilter().accept(item, wm, rtn)) { // only relevant for seralization, to not refire Matches already fired continue; } agenda.fireActivation(item); localFireCount++; if (rtn.getLeftTupleSource() == null) { break; // The activation firing removed this rule from the rule base } int salience = ruleAgendaItem.getSalience(); // dyanmic salience may have updated it, so get again. if (queue != null && !queue.isEmpty() && salience != queue.peek().getSalience()) { ruleAgendaItem.dequeue(); ruleAgendaItem.setSalience(queue.peek().getSalience()); ruleAgendaItem.getAgendaGroup().add(ruleAgendaItem); salience = ruleAgendaItem.getSalience(); } RuleAgendaItem nextRule = agenda.peekNextRule(); if (haltRuleFiring(nextRule, fireCount, fireLimit, localFireCount, agenda, salience)) { break; // another rule has high priority and is on the agenda, so evaluate it first } reEvaluateNetwork(wm, outerStack, fireUntilHalt); wm.executeQueuedActions(); if (tupleList.isEmpty() && !outerStack.isEmpty()) { // the outer stack is nodes needing evaluation, once all rule firing is done // such as window expiration, which must be done serially StackEntry entry = outerStack.removeFirst(); NETWORK_EVALUATOR.evalStackEntry(entry, outerStack, outerStack, this, wm); } } } removeRuleAgendaItemWhenEmpty(wm); fireExitedEarly = false; return localFireCount; }
public boolean isEnabled(Tuple tuple, RuleTerminalNode rtn, WorkingMemory workingMemory) { return this.enabled.getValue(tuple, rtn.getEnabledDeclarations(), this, workingMemory); }