【Drools DRL on YAML】YAMLで書いたルールを動かしてみる

## はじめに

Drools の 10.0.0 バージョンがリリースされていました。

https://kie.apache.org/docs/10.0.x/drools/drools/release-notes/index.html

新機能として、DRL (Drools Rule Language) を YAML で記述できる「DRL on YAML」というものが導入されています。

`experimental` とあるので今後も変更が入る可能性はありますが、ひとまずどんな感じかさわってみようと思います。

## DRL on YAML について

Drools の [Github](https://github.com/apache/incubator-kie-drools/tree/main/drools-drlonyaml-parent) をみると、「通常のDRL文法で書いたルール」 ⇔ 「YAMLで書いたルール」 の双方向変換ができるツールとして紹介されています。

今回は、[過去の記事](https://qiita.com/yagii/items/5c1ee8781dc16252d2a3)で題材にしたドリンク判定ルールを YAML で実装し、動かしてみたいと思います。

## サンプルコード紹介

ここからは検証に使ったコードを一部紹介していきます。
全量は Github にアップしています。

https://github.com/Hami1ton/study_brms/tree/main/drools/drlonyaml/drlonyaml-example

### 環境・バージョン情報など

windows 11
openjdk 17
Apache Maven 3.9.6
Drools 10.0.0

### データクラス

ルールで使用するデータクラスを定義しています。

```Drink.java
public class Drink {

    private String name;

    private int charge;
...
```

```Person.java
public class Person {

    private String name;

    private int age;

...
```

### ルール(YAML)

YAML で書いたルールは、次のようになります。

```DrinkRule.drl.yaml
name: org.example.drlonyaml
rules:
- name: Child
  when:
  - given: Person
    as: $person
    having:
      - age < 20
  - given: Drink
    as: $drink

  then: |
    $drink.setName( "Orange Juice" );
    $drink.setCharge( 100 );

- name: Adult
  when:
  - given: Person
    as: $person
    having:
      - age >= 20
  - given: Drink
    as: $drink

  then: |
    $drink.setName( "Beer" );
    $drink.setCharge( 200 );
```

年齢に応じてドリンクを判定するルールとなっており、20歳未満ならオレンジジュース、20歳以上ならビールを返却します。
ルールは`name`ブロック単位で記述し、`when`には条件、`then`には条件をみたしたときに動く処理を書いています。

### ルール実行コード

ルールはJUnitで実行します。

```DrinkRuleTest.java
    @Test
    public void test_drink() throws Exception {

        String yaml = readResourceFileAsString("org/example/drlonyaml/DrinkRule.drl.yaml");
        String drl = YAMLtoDrlDumper.yaml2drl(yaml);
        log.info("\n" + drl);

        KieBase kieBase = createKieBase(drl);
        KieSession kieSession = kieBase.newKieSession();

        try {
            // set up
            var person = new Person();
            person.setName("Taro");
            person.setAge(18);
            var drink = new Drink();

            kieSession.insert(person);
            kieSession.insert(drink);

            // exectute rule
            kieSession.fireAllRules();
            assertEquals("Orange Juice", drink.getName());

        } finally {
            // dispose
            kieSession.dispose();
        }
    }
```

`readResourceFileAsString`の箇所で、リソースパスの YAML ファイルを読み込んでいます。

```
String drl = YAMLtoDrlDumper.yaml2drl(yaml);
log.info("\n" + drl);
```
で「DRL on YAML」の機能を使い、YAML で書いたルールを翻訳しています。
結果はログに出力します。

以降は、通常の DRL で書いたルールを実行する処理なので、詳細は割愛します。

### 実行結果

今回は18歳の`Person`データを投入しているので、飲み物はオレンジジュースと判定され、テストが無事パスします。
テスト実行時、「DRL on YAML」で翻訳された DRL は下記のようにログ出力されています。

```
[main] INFO org.example.drlonyaml.DrinkRuleTest - 
// This file was automatically generated from a YAML representation.
package org.example.drlonyaml;

rule "Child"
when
  $person : Person(age < 20)
  $drink : Drink()
then
$drink.setName( "Orange Juice" );
$drink.setCharge( 100 );

end
rule "Adult"
when
  $person : Person(age >= 20)
  $drink : Drink()
then
$drink.setName( "Beer" );
$drink.setCharge( 200 );
end
```

YAMLから通常の DRL に翻訳されることと、変換後ルールが問題なく動くことを確認できました。


## 参考

Drools User Guide 10.0.0

https://kie.apache.org/docs/10.0.x/drools/drools/release-notes/index.html

drools-drlonyamlのリポジトリ

https://github.com/apache/incubator-kie-drools/tree/main/drools-drlonyaml-parent

今回紹介したサンプルコード

https://github.com/Hami1ton/study_brms/tree/main/drools/drlonyaml/drlonyaml-example