rulebook-core/src/main/java/com/deliveredtechnologies/rulebook/StandardRule.java
@Override
  @SuppressWarnings("unchecked")
  public void run(Object... otherArgs) {
    try {
      //only use facts of the specified type
      FactMap<T> typeFilteredFacts = new FactMap<T>((Map<String, NameValueReferable<T>>)_facts.values().stream()
          .filter((Object fact) -> _factType.isAssignableFrom(((Fact)fact).getValue().getClass()))
          .collect(Collectors.toMap(fact -> ((Fact)fact).getName(), fact -> (Fact<T>)fact)));
      //invoke then() action(s) if when() is true or if when() was never specified
      if (getWhen() == null || getWhen().test(typeFilteredFacts)) {

        //iterate through the then() actions specified
        List<Object> actionList = getThen();
        for (int i = 0; i < (getThen()).size(); i++) {
          Object action = actionList.get(i);
          List<String> factNames = _factNameMap.get(i);

          //if using() fact names were specified for the specific then(), use only those facts specified
          FactMap<T> usingFacts;
          if (factNames != null) {
            usingFacts = new FactMap<T>(factNames.stream()
                .filter(typeFilteredFacts::containsKey)
                .collect(Collectors.toMap(name -> name, name -> _facts.get(name))));
          } else {
            usingFacts = typeFilteredFacts;
          }

          //invoke the action
          Stream.of(action.getClass().getMethods())
              .filter(method -> method.getName().equals("accept"))
              .findFirst()
              .ifPresent(method -> {
                try {
                  method.setAccessible(true);
                  method.invoke(action,
                      ArrayUtils.combine(new Object[]{usingFacts}, otherArgs, method.getParameterCount()));
                } catch (IllegalAccessException | InvocationTargetException err) {
                  LOGGER.error("Error invoking action on " + action.getClass(), err);
                }
              });
        }

        //if stop() was invoked, stop the rule chain after then is finished executing
        if (_ruleState == BREAK) {
          return;
        }
      }
    } catch (Exception ex) {

      //catch errors in case something like one rule was chained expecting a Fact that doesn't exist
      //eventually, we'll have to resolve that kind of issue ahead of time
      LOGGER.error("Error occurred when trying to evaluate rule!", ex);
    }

    //continue down the rule chain
    _nextRule.ifPresent(rule -> rule.given(_facts));
    _nextRule.ifPresent(Rule::run);
  }
@Override
  @SuppressWarnings("unchecked")
  public void run(Object... otherArgs) {
    try {
      //only use facts of the specified type
      FactMap<T> typeFilteredFacts = new FactMap<T>((Map<String, NameValueReferable<T>>)_facts.values().stream()
          .filter((Object fact) -> _factType.isAssignableFrom(((Fact)fact).getValue().getClass()))
          .collect(Collectors.toMap(fact -> ((Fact)fact).getName(), fact -> (Fact<T>)fact)));
      //invoke then() action(s) if when() is true or if when() was never specified
      if (getWhen() == null || getWhen().test(typeFilteredFacts)) {

        //iterate through the then() actions specified
        List<Object> actionList = getThen();
        for (int i = 0; i < (getThen()).size(); i++) {
          Object action = actionList.get(i);
          List<String> factNames = _factNameMap.get(i);

          //if using() fact names were specified for the specific then(), use only those facts specified
          FactMap<T> usingFacts;
          if (factNames != null) {
            usingFacts = new FactMap<T>(factNames.stream()
                .filter(typeFilteredFacts::containsKey)
                .collect(Collectors.toMap(name -> name, name -> _facts.get(name))));
          } else {
            usingFacts = typeFilteredFacts;
          }

          //invoke the action
          Stream.of(action.getClass().getMethods())
              .filter(method -> method.getName().equals("accept"))
              .findFirst()
              .ifPresent(method -> {
                try {
                  method.setAccessible(true);
                  method.invoke(action,
                      ArrayUtils.combine(new Object[]{usingFacts}, otherArgs, method.getParameterCount()));
                } catch (IllegalAccessException | InvocationTargetException err) {
                  LOGGER.error("Error invoking action on " + action.getClass(), err);
                }
              });
        }

        //if stop() was invoked, stop the rule chain after then is finished executing
        if (_ruleState == BREAK) {
          return;
        }
      }
    } catch (Exception ex) {

      //catch errors in case something like one rule was chained expecting a Fact that doesn't exist
      //eventually, we'll have to resolve that kind of issue ahead of time
      LOGGER.error("Error occurred when trying to evaluate rule!", ex);
    }

    //continue down the rule chain
    _nextRule.ifPresent(rule -> rule.given(_facts));
    _nextRule.ifPresent(Rule::run);
  }
The run(Object[]) method runs the {@link Predicate} supplied by the when() method. <br/>
If it evaluates to true then the action(s) supplied by the then() method(s) are executed. <br/>
If the stop() method was invoked then no further rules are evaluated. <br/>
Otherwise, the next rule in the chain is evaluated.