web-dev-qa-db-fra.com

Drools - comment savoir à quelles règles toutes les règles correspondent?

J'ai un fichier .DRL qui a dit 10 règles. Une fois que j'ai inséré un fait, certaines règles peuvent être mises en correspondance - comment savoir quelles règles ont été mises en correspondance par programme?

16
gauravphoenix

Notez que cette réponse est valable pour les versions de Drools jusqu'à 5.x. Si vous êtes passé à 6 ou plus, jetez un œil à la réponse modifiée de @ melchoir55. Je ne l'ai pas testé moi-même, mais j'espère que cela fonctionne.

Pour garder une trace des activations de règles, vous pouvez utiliser un AgendaEventListener. Ci-dessous un exemple, que l'on trouve ici:

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

Vous avez juste besoin de créer un tel écouteur et de le joindre à la session comme ceci:

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

Notez qu'il existe également WorkingMemoryEventListener qui vous permet de faire de même avec le suivi des insertions, des mises à jour et des rétractions de faits.

Code pour un AgendaEventListener de suivi et de journalisation:

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

}
24
Steve

La réponse de Steve est solide, mais les changements majeurs apportés dans bave 6 rendent le code obsolète. Je poste ci-dessous une réécriture du code de Steve qui prend en compte la nouvelle 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();
        }
    }

}
20
melchoir55

Vous pouvez utiliser une fabrique d'enregistreurs statiques qui enregistrera avec votre enregistreur préféré les actions de votre fichier DRL.

Par exemple:

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

}

Puis à partir de votre fichier DRL:

import function com.mycompany.DRLLogger.*

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

Vous pouvez imprimer des informations sur la règle exécutée à partir du fichier DRL lui-même à l'aide de RuleContext: drools

System.out.println(drools.getRule().getName())
0
Pranith Baggan

Changez le dialecte en Java dans le fichier DRL.

Insérez un HashMap du fichier Java dans le fichier DRL (en utilisant le concept de session Drools), qui doit contenir le nom de la règle comme clé et la valeur booléenne comme résultat.

Suivez ceci lien pour savoir comment insérer la carte dans le fichier DRL.

Vous pouvez maintenant trouver quelle règle correspond exactement.

J'espère que cela t'aides :)

0
VinayVeluri