Callable

Introduction

Le concept de Callable est la base du support des fonctions, introduit avec MRules 1.9.0. Il est représenté par l’interface ICallable. Une Function est un Addon implémentant cette interface.

Les Callables sont portés par un ICallableRepository,  qui est implémenté par le RuleSet.

Enfin, un Addon est dédié à effectuer l’appel. Pour le moment, une seule implémentation est fournie, nommée Call. Elle permet d’invoquer une fonction via son nom et de lui fournir des paramètres. Une valeur de retour est possible, pouvant être utilisée pour les règles suivantes ou pour les données de sortie.

Utilisation

Un exemple est souvent plus parlant que de long discours. Nous allons donc voir ici comment construire un rule set simple utilisant une fonction.

Prenons le cas suivant : Un rule set va appeler une Fonction, avec un paramètre ayant la valeur « 0 ». Cette fonction va incrémenter le paramètre de « 1 » puis s’appeler elle-même récursivement.

Lorsque le paramètre est égal à la valeur d’entrée fournie au rule set, la valeur est renvoyée.

Nous allons nous assurer que la valeur récupérée par le programme Java est bien la valeur d’entrée.

Analysons la configuration suivante qui permet d’atteindre cet objectif :

<?xml version="1.0" encoding="UTF-8"?>
<rules implem="RULEEXECUTIONSET" name="test_function">
    <contextFactory implem="CONTEXT" classIn="Integer"/>
    
    <callable implem="FUNCTION" name="myFunction">
        <executable implem="RULE">
            <condition implem="EVAL" source="$parameter" operator="GTE" reference="#READBASE" />
            <then implem="RETURN" value="$parameter"/>
        </executable>
        <executable implem="RETURN">
            <value implem="CALL" callable="myFunction">
                <argument name="parameter">
                    <value implem="SUM">
                        <value implem="PROPERTY" property="$parameter" />
                        <value implem="VALUE" value="1" />
                    </value>
                </argument>
            </value>
        </executable>
    </callable>
    
    <executable implem="FLOWCONTROL" command="STOP">
        <returnValue implem="CALL" callable="myFunction" parameter="0" />
    </executable>
</rules>

Premièrement, nous déclarons la fabrique de contexte et le type d’input, un simple entier.

Ensuite, nous déclarons la fonction, qui évalue si le paramètre « parameter » est supérieur ou égal à la valeur READBASE (variables globale permettant de récupérer l’input fourni au rule set). Si oui, la valeur est retournée. Si non, la fonction fait un appel récursif en incrémentant la valeur du paramètre.

Enfin, la seule règle du rule set consiste à appeler la fonction et à renvoyer la valeur au programme appelant. Ceci est réalisé via une commande STOP de « Flow Control » avec un argument »returnValue ».

Ce rule set peut être testé avec ce code JUnit :

final InputStream xml = ResourceLoader.getResourceAsStream("function_test.xml");
final TestingRichXmlFactory factory = this.getFactory();
final IMruleExecutionSet eng = factory.read(xml);

final MExecutionContext<Integer> ctxt = new MExecutionContext<Integer>(eng);
ctxt.setInput(10);
IExecutionResult result = ctxt.execute();

Assert.assertEquals(Integer.valueOf(10), ConvertUtils.getDefaultInstance().cast(Integer.class,result.getReturnedValue()));

A noter le « cast » vers un Integer de la valeur retournée, car MRules travaille par défaut sur des BigDecimal pour les opérations sur les nombres.

Conclusion

Dans cette section, Vous avez appris l’utilisation des fonctions. Pour voir un usage plus avancé, vous pouvez télécharger la démo Sudoku, largement basée sur les fonctions et les appels récursifs pour résoudre les grilles.

Pour aller plus loin, les versions futures de MRules fourniront de nouvelles implémentations de Callable, afin de permettre par exemples d’exécuter des rule set externes et de chainer leur exécution.