【入門】Droolsのサンプルプログラムを実行するまで


##当記事を投稿する動機

配送スケジュールなどの組み合わせ最適化を取り扱うOptaPlanner(※1)は、
ルール言語「DRL（Drools Rule Language）」というものを用いています。
OptaPlannerを使いこなすためには、このDroolsの理解が必要不可欠となります。

一方、日本国内にはDroolsの情報は自分が検索した限りでは多くない状況です。
しかし、参考情報として数少ないDroolsの入門記事(※2)がありましたので、自分の理解を深めるためにゼロから自分でDroolsプロジェクトを作成してみることにしました。
この作業内容をまとめたものが、初めてDroolsを導入する際に他の人が少しでも参考になってもらいたく記事を投稿することにしました。

- - - - - - - - - - - - - - - 
※1 参考：OptaPlannerの紹介記事
　[・オブジェクト広場 OptaPlannerによる組み合わせ最適化](
https://www.ogis-ri.co.jp/otc/hiroba/technical/optaplanner/chap1.html)
　[・株式会社日立ソリューションズ OSSプランニングエンジンOptaPlannerを使ってみよう！]
(https://www.obci.jp/wp-content/uploads/2015/08/04dae47e0e56976391ae2bd6dc41a5fe.pdf)

OpatPlannerだけでなくDroolsに触れている説明部分もあります。


※2:参考：
　[・赤帽エンジニアブログ](https://rheb.hatenablog.com/entry/drools-helloworld)
公式リファレンスを見ても情報量が多すぎて理解できなかった自分にとって、Droolsを理解するきっかけとなりました。非常に助かりました。

- - - 


#前提情報
####記事を読むにあたっての前提条件：
 ・Eclipseの基本操作を知っている人。
 ・「DRL（Drools Rule Language）」を新規プロジェクト作成から疎通用のプログラムを実行するまで分からない人


####動作環境
　- Linux Ubuntu 18.04.5.LTS
　- Eclipse Version: 2020-12 (4.18.0)


# EclipseでDroolsを使えるようにセットアップ

インストール手順はこちらを参考にして下さい。
細かく手順が説明されていてわかりやすいです。

参考：[オブジェクト広場 第3回：EclipseでOptaPlannerを動かしてみる](https://www.ogis-ri.co.jp/otc/hiroba/technical/optaplanner/chap3.html)



# Droolsプロジェクト新規作成

下記のWebページではサンプル資産が提供されていますが、Droolsの理解を深めるためにゼロからプロジェクトを作成してきたいと思います。

[Droolsブログ : 01 Drools HelloWorld]
(https://tokobayashi.hatenablog.com/entry/2019/04/23/172814)


Eclipseを立ち上げまして、新規プロジェクトを作成します。
"Drools Project"を探し出します。

![Screenshot from 2021-02-20 16-27-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/adb98d5f-b0cd-6ce6-dcb6-85388b213ad8.png)

”Drools Project”を選択して、次へ進みます。

新規作成するDroolsProjectの雛形を選択しろ、という画面が出ました。
とりあえず、一番上の空っぽ(empty project)を選択します。

![Screenshot from 2021-02-20 16-27-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/a34cc303-0698-aaae-adf5-6f3d85e60602.png)

作成するプロジェクトの設定画面２が出ましたが、
プロジェクト名、プロジェクトを格納する場所は適当にセットします。
よくわからないので、とりあえずMaven形式を選択しました。
完了ボタンを押下して、初期設定が完了です。

![Screenshot from 2021-02-20 16-28-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/abb886de-7fd4-6a90-ac76-44766614d89a.png)


初期設定が完了すると、下記のような画面が表示されます。
実装には不要となるので、この画面はクローズします。
![Screenshot from 2021-02-20 16-28-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/10564a2c-7b78-f518-0b2f-ce8b4faafc79.png)

Eclipse左側のパッケージエクスプローラを見ると、
自動的にフォルダの階層が作成されています。
![Screenshot from 2021-02-20 16-28-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/7c5a9606-bd6d-d254-077b-cd64679d0ecb.png)


# 実装
##処理全体の流れを説明

以下のルールが適用される処理を実装します。
・ある人の年齢が３０歳以上であれば、"30歳以上です"とメッセージを出力する。
・ある人の年齢が３０歳未満であれば、"30歳未満です"とメッセージを出力する。

実装する上で、主役は３つの資産となります。

●ルール適用するデータ：Personクラス
ルールには"ある人"とあるように、年齢の情報を持つPersonクラスが必要となります。
これが__ルール適用させるインプットデータ__となるクラスとなります。

●ルールファイル
ルールは"drl"という拡張子のファイルに定義されますが、簡単に説明してしまえば
手続き型言語で登場する __if** then** の塊を定義ファイルに集約したもの__、というイメージです。

●ルール適用処理を行うmainクラス
ルール適用するデータ、ルールファイルが作成したら、__ルールを実際に適用する処理__を実装します。


## ルールに適用させるインプットデータとなるクラスを作成

この後にルールを作成しますが、そのルール（条件判定して、マッチすれば何かするといった定義ファイル）に適用させるクラスを作成します。
ルール適用に必要なメンバ変数として年齢を定義します。名前のメンバ変数はおまけで定義しました。

![Screenshot from 2021-02-20 18-10-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/d68c245e-93e9-a708-785f-044e67e3365d.png)


##ルールの新規作成

パッケージエクスプローラの "src/main/resources/rules"　を選択し右クリックで
新規リソースを作成します。"Rule Resource"を選択して次へ進みます。

![Screenshot from 2021-02-20 17-24-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/3a9721f6-e221-68c6-4602-ed60b9759848.png)


ルールファイルの新規作成ワイザード画面が開きました。
ルールのファイル名とそのパッケージ名を入力します。

![rule作成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/bb57c7ad-7356-572a-9a47-e54f3af8100a.jpeg)

雛形のルールが新規されました。あとで、このルールファイルに追記していきます。
![Screenshot from 2021-02-20 17-34-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/27ececf7-2245-bbd2-7ce3-ce5317d232b0.png)


先に完成したものを提示致します。

![rule作成2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/f4467b97-6816-556d-43fb-7ddcaa979b83.jpeg)


#### ルール名を定義
ユニークなルール名を rule の後ろに文字列として記述します。

#### whenを定義
whenはif--then のifに対応する部分です。
今回作成するサンプルでは、Personクラスの年齢(age)が30歳以上の場合を条件として定義します。

```
  when
    $p:Person(age <= 30)
```

上記"Person"というのは、クラス名のPersonです。
__プロジェクト内で存在するクラス名を記述する必要があります。__(実行時エラーとなりますので、importするのをお忘れなく。)

上記”age"というのは、Personクラスのメンバ変数です。
__ルール適用するクラスに存在するメンバ変数をwhenの条件式で使うようにします。__

上記"$p"は、バインド変数と呼ばれるものです。
__whenでマッチしたPersonオブジェクトをthenの部分で参照することができます。__

```
 then
   System.out.println( "Under 30 ages :" + $p.getName() );
```

when部分でマッチした場合に実行する処理を記述します。
処理はJavaで記述しますので、サンプルのためsysoutをしています。


#### (新規作成における時留意点）不要な設定を削除

![Screenshot from 2021-02-20 18-18-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/20d51b6a-485e-9511-2962-3f4e712b2975.png)

ルールファイルを新規作成した際にテンプレとして３つのルールがありましたが、
そのルールが設定ファイル(kmodule.xml)に反映されたままになっています(kbaseという要素)。そのテンプルは不要なため削除済みですが、その設定も不要となりますので削除します。
削除しなれば上記のような実行時エラーになってしまうために、__設定ファイルkmodule.xmlから削除する必要があります。__


## mainの新規作成

ルール適用するデータ、ルールファイルが作成しましたので、ルールを実際に適用する処理を実装していきます。

![Screenshot from 2021-02-20 18-45-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224290/6328cd48-fe7e-a972-7207-a7fc9bd61cfe.png)

サンプル例では、
　・ジョン：３０歳
　・ポール：２９歳
というPersonクラスオブジェクトを生成して、年齢判定するルールを適用させています。
適用は"insert"メソッドに引数として渡します。
実際にルール適用の実行はfireAllRulesメソッドです。

気になって点として、ジョン→ポールという順番でinsertしていますが
コンソール画面を見るとポール→ジョンの順番でルール適用した場合の処理(then処理)が実行されいます。
__insertした順番と実際にルール適用処理の順番は一致しない__、ように見えます。





以上が、プロジェクト新規作成から簡単なサンプルプログラムを動作させるまでの作業手順となります。