Подтвердить что ты не робот

Drools - как узнать, какие все правила были сопоставлены?

У меня есть один файл .DRL, который говорит 10 правил. Как только я вставляю факт, некоторые правила могут быть сопоставлены - как узнать, какие правила были сопоставлены программно?

4b9b3361

Ответ 1

Чтобы отслеживать активацию правил, вы можете использовать программу AgendaEventListener. Ниже приведен пример, который находится здесь:

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

Вам просто нужно создать такой прослушиватель и прикрепить его к сеансу следующим образом:

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

Обратите внимание, что есть также WorkMemoryEventListener, который позволяет вам делать то же самое со вставками отслеживания, обновлениями и сокращениями фактов.

Код для отслеживания и ведения журнала 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();
        }
    }

}

Ответ 2

Ответ Стива прочен, но основные изменения, вызванные слюноветкими 6, делают код устаревшим. Я публикую ниже код Стива, который учитывает новый api:

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();
        }
    }

}

Ответ 3

Вы можете использовать статический логгер factory, который будет записывать с вашим любимым регистратором действия из вашего файла DRL.

Например:

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);
}

}

Затем из вашего файла DRL:

import function com.mycompany.DRLLogger.*

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

Ответ 4

Измените диалект на JAVA в файле DRL.

Вставьте HashMap из java файла в файл DRL (используя концепцию сеанса Drools), который должен содержать имя правила как ключевое и логическое значение в качестве результата.

Следуйте этой ссылке, чтобы узнать, как вставить карту в файл DRL.

Теперь вы можете найти, какое правило точно соответствует.

Надеюсь, что это поможет:)