Java Drools-如何找出所有规则都匹配?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19951880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 21:47:47  来源:igfitidea点击:

Drools- how to find out which all rules were matched?

javadroolsrule-engine

提问by gauravphoenix

I've one .DRL file which has say 10 rules. Once I insert a fact, some rules may be matched- how do I find out which rules were matched programmatically?

我有一个 .DRL 文件,里面有 10 条规则。一旦我插入一个事实,可能会匹配一些规则 - 我如何以编程方式找出哪些规则匹配?

采纳答案by Steve

Note that this answer is valid for versions of Drools up to 5.x. If you have moved on to 6 or above, then take a look at the modified answer from @melchtheitroad55. I haven't tested it myself, but I'll trust that it works.

请注意,此答案适用于最高 5.x 的 Drools 版本。如果您已升级到 6 或以上,请查看@melchtheitroad55 的修改后的答案。我自己没有测试过,但我相信它是有效的。

To keep track of rule activations, you can use an AgendaEventListener. Below is an example, as found here:

要跟踪规则激活,您可以使用 AgendaEventListener。下面是一个示例,如下所示:

https://github.com/gratiartis/sctrcd-payment-validation-web/blob/master/src/main/java/com/sctrcd/drools/util/TrackingAgendaEventListener.java

https://github.com/gratiartis/sctrcd-payment-validation-web/blob/master/src/main/java/com/sctrcd/drools/util/TrackingAgendaEventListener.java

You just need to create such a listener and attach it to the session like so:

您只需要创建这样一个侦听器并将其附加到会话中,如下所示:

ksession = kbase.newStatefulKnowledgeSession();
AgendaEventListener agendaEventListener = new TrackingAgendaEventListener();
ksession.addEventListener(agendaEventListener);
//...
ksession.fireAllRules();
//...
List<Activation> activations = agendaEventListener.getActivationList();

Note that there is also WorkingMemoryEventListener which enables you to do the same with tracking insertions, updates and retractions of facts.

请注意,还有 WorkingMemoryEventListener 使您能够对事实的插入、更新和撤回进行跟踪。

Code for a tracking & logging AgendaEventListener:

跟踪和记录 AgendaEventListener 的代码:

package com.sctrcd.drools.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.drools.definition.rule.Rule;
import org.drools.event.rule.DefaultAgendaEventListener;
import org.drools.event.rule.AfterActivationFiredEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A listener that will track all rule firings in a session.
 * 
 * @author Stephen Masters
 */
public class TrackingAgendaEventListener extends DefaultAgendaEventListener {

    private static Logger log = LoggerFactory.getLogger(TrackingAgendaEventListener.class);

    private List<Activation> activationList = new ArrayList<Activation>();

    @Override
    public void afterActivationFired(AfterActivationFiredEvent event) {
        Rule rule = event.getActivation().getRule();

        String ruleName = rule.getName();
        Map<String, Object> ruleMetaDataMap = rule.getMetaData();

        activationList.add(new Activation(ruleName));
        StringBuilder sb = new StringBuilder("Rule fired: " + ruleName);

        if (ruleMetaDataMap.size() > 0) {
            sb.append("\n  With [" + ruleMetaDataMap.size() + "] meta-data:");
            for (String key : ruleMetaDataMap.keySet()) {
                sb.append("\n    key=" + key + ", value="
                        + ruleMetaDataMap.get(key));
            }
        }

        log.debug(sb.toString());
    }

    public boolean isRuleFired(String ruleName) {
        for (Activation a : activationList) {
            if (a.getRuleName().equals(ruleName)) {
                return true;
            }
        }
        return false;
    }

    public void reset() {
        activationList.clear();
    }

    public final List<Activation> getActivationList() {
        return activationList;
    }

    public String activationsToString() {
        if (activationList.size() == 0) {
            return "No activations occurred.";
        } else {
            StringBuilder sb = new StringBuilder("Activations: ");
            for (Activation activation : activationList) {
                sb.append("\n  rule: ").append(activation.getRuleName());
            }
            return sb.toString();
        }
    }

}

回答by VinayVeluri

Change the dialect to JAVA in DRL file.

在 DRL 文件中将方言更改为 JAVA。

Insert a HashMap from the java file to DRL file (using Drools session concept), which should contain the rule name as key and boolean value as result.

将 HashMap 从 java 文件插入到 DRL 文件(使用 Drools 会话概念),其中应包含规则名称作为键和布尔值作为结果。

Follow this linkto know how to insert Map to the DRL file.

按照此链接了解如何将 Map 插入 DRL 文件。

You can now find which rule exactly matched.

您现在可以找到完全匹配的规则。

Hope this helps :)

希望这可以帮助 :)

回答by zenbeni

You can use a static logger factory which will log with your favorite logger the actions from your DRL file.

您可以使用静态记录器工厂,它将使用您最喜欢的记录器记录 DRL 文件中的操作。

For instance:

例如:

import org.drools.runtime.rule.RuleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class DRLLogger {

private DRLLogger() {
}

protected static Logger getLogger(final RuleContext drools) {
    final String category = drools.getRule().getPackageName() + "." + drools.getRule().getName();
    final Logger logger = LoggerFactory.getLogger(category);
    return logger;
}

public static void info(final RuleContext drools, final String message, final Object... parameters) {
    final Logger logger = getLogger(drools);
    logger.info(message, parameters);
}

public static void debug(final RuleContext drools, final String message, final Object... parameters) {
    final Logger logger = getLogger(drools);
    logger.debug(message, parameters);
}

public static void error(final RuleContext drools, final String message, final Object... parameters) {
    final Logger logger = getLogger(drools);
    logger.error(message, parameters);
}

}

Then from your DRL file:

然后从您的 DRL 文件中:

import function com.mycompany.DRLLogger.*

rule "myrule"
when
    $fact: Fact()
then
    info(drools, "Fact:{}", $fact);
end

回答by melchtheitroad55

Steve's answer is solid, but the major changes brought in drools 6 make the code obsolete. I am posting below a rewrite of Steve's code which takes into account the new api:

史蒂夫的回答是可靠的,但在 drools 6 中带来的主要变化使代码过时了。我在下面发布了考虑到新 api 的 Steve 代码的重写:

package your.preferred.package;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.drools.core.event.DefaultAgendaEventListener;
import org.kie.api.definition.rule.Rule;
import org.kie.api.event.rule.AfterMatchFiredEvent;
import org.kie.api.runtime.rule.Match;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A listener that will track all rule firings in a session.
 * 
 * @author Stephen Masters, Isaac Martin
 */
public class TrackingAgendaEventListener extends DefaultAgendaEventListener  {

    private static Logger log = LoggerFactory.getLogger(TrackingAgendaEventListener.class);

    private List<Match> matchList = new ArrayList<Match>();

    @Override
    public void afterMatchFired(AfterMatchFiredEvent event) {
        Rule rule = event.getMatch().getRule();

        String ruleName = rule.getName();
        Map<String, Object> ruleMetaDataMap = rule.getMetaData();

        matchList.add(event.getMatch());
        StringBuilder sb = new StringBuilder("Rule fired: " + ruleName);

        if (ruleMetaDataMap.size() > 0) {
            sb.append("\n  With [" + ruleMetaDataMap.size() + "] meta-data:");
            for (String key : ruleMetaDataMap.keySet()) {
                sb.append("\n    key=" + key + ", value="
                        + ruleMetaDataMap.get(key));
            }
        }

        log.debug(sb.toString());
    }

    public boolean isRuleFired(String ruleName) {
        for (Match a : matchList) {
            if (a.getRule().getName().equals(ruleName)) {
                return true;
            }
        }
        return false;
    }

    public void reset() {
        matchList.clear();
    }

    public final List<Match> getMatchList() {
        return matchList;
    }

    public String matchsToString() {
        if (matchList.size() == 0) {
            return "No matchs occurred.";
        } else {
            StringBuilder sb = new StringBuilder("Matchs: ");
            for (Match match : matchList) {
                sb.append("\n  rule: ").append(match.getRule().getName());
            }
            return sb.toString();
        }
    }

}

回答by Pranith Baggan

You can print info about rule executed from DRL file itself using RuleContext:drools

您可以使用 RuleContext:drools 打印有关从 DRL 文件本身执行的规则的信息

System.out.println(drools.getRule().getName())