private void updateSalience(int currentSalience) {
   // the queue may be emtpy if no more matches are left, so reset it to default salience 0
   int newSalience =
       queue.isEmpty() ? SalienceInteger.DEFAULT_SALIENCE.getValue() : queue.peek().getSalience();
   if (currentSalience != newSalience) {
     // salience changed, so the RuleAgendaItem needs to be removed and re-added, for sorting
     ruleAgendaItem.remove();
   }
   if (!ruleAgendaItem.isQueued()) {
     ruleAgendaItem.setSalience(newSalience);
     ruleAgendaItem.getAgendaGroup().add(ruleAgendaItem);
   }
 }
  private boolean haltRuleFiring(
      RuleAgendaItem nextRule,
      int fireCount,
      int fireLimit,
      int localFireCount,
      InternalAgenda agenda,
      int salience) {

    return !agenda.continueFiring(0)
        || ((nextRule != null)
            && (!ruleAgendaItem.getRule().getAgendaGroup().equals(nextRule.getAgendaGroup())
                || !isHighestSalience(nextRule, salience)))
        || (fireLimit >= 0 && (localFireCount + fireCount >= fireLimit));
  }
 public void removeRuleAgendaItemWhenEmpty(InternalWorkingMemory wm) {
   if (!dirty && tupleList.isEmpty()) {
     // dirty check, before doing the synced check and removal
     synchronized (ruleAgendaItem) {
       if (!dirty && tupleList.isEmpty()) {
         if (log.isTraceEnabled()) {
           log.trace("Removing RuleAgendaItem " + ruleAgendaItem);
         }
         ruleAgendaItem.remove();
         if (ruleAgendaItem.getRule().isEager()) {
           ((InternalAgenda) wm.getAgenda()).removeEagerRuleAgendaItem(ruleAgendaItem);
         }
       }
     }
   }
 }
 public RuleExecutor(
     final PathMemory pmem, RuleAgendaItem ruleAgendaItem, boolean declarativeAgendaEnabled) {
   this.pmem = pmem;
   this.ruleAgendaItem = ruleAgendaItem;
   this.tupleList = new LeftTupleList();
   this.declarativeAgendaEnabled = declarativeAgendaEnabled;
   if (ruleAgendaItem.getRule().getSalience().isDynamic()) {
     queue = new BinaryHeapQueue(SalienceComparator.INSTANCE);
   }
 }
 public boolean isHighestSalience(RuleAgendaItem nextRule, int currentSalience) {
   return nextRule.getSalience() <= currentSalience;
 }
  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;
  }