...

JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド

by user

on
Category: Documents
83

views

Report

Comments

Transcript

JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
JBoss Enterprise BRMS Platform
5
JBoss Rules 5 リファレンスガイド
開発者向け
エディッション 5.3.1
David Le Sage
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
開発者向け
エディッション 5.3.1
David Le Sage
Red Hat Engineering Co ntent Services
[email protected] m
法律上の通知
Copyright © 2014 Red Hat, Inc..
T his document is licensed by Red Hat under the Creative Commons Attribution-ShareAlike 3.0 Unported
License. If you distribute this document, or a modified version of it, you must provide attribution to Red
Hat, Inc. and provide a link to the original. If the document is modified, all Red Hat trademarks must be
removed.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section
4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo,
and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux ® is the registered trademark of Linus T orvalds in the United States and other countries.
Java ® is a registered trademark of Oracle and/or its affiliates.
XFS ® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States
and/or other countries.
MySQL ® is a registered trademark of MySQL AB in the United States, the European Union and other
countries.
Node.js ® is an official trademark of Joyent. Red Hat Software Collections is not formally related to or
endorsed by the official Joyent Node.js open source or commercial project.
T he OpenStack ® Word Mark and OpenStack Logo are either registered trademarks/service marks or
trademarks/service marks of the OpenStack Foundation, in the United States and other countries and
are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or
sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
概要
本書では、開発者向けに JBoss Rules を説明します。
目次
目次
.前書き
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
............
1. 本書の表記規則
12
1.1. 書体の表記規則
12
1.2. 引用文の表記規則
13
1.3. 注記および警告
14
2. サポート、およびフィードバックのお願い
14
2.1. サポートが必要ですか?
14
2.2. フィードバックをお願いします
15
. . .1章
第
. . . .はじめに
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
............
1.1. 対象読者
16
1.2. 本書の目的
16
. . .2章
第
. . . .クイックスタート
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
............
2.1. JBoss Rules
17
2.2. JBoss Rules エンジン
17
2.3. プロダクションルール
17
2.4. 推論エンジン
17
2.5. ReteOO
17
2.6. プロダクションメモリ
17
2.7. ワーキングメモリ
17
2.8. 競合解消 (Conflict Resolution) 戦略
18
2.9. ハイブリッドルールシステム
18
2.10. 前向き連鎖
18
2.11. 後向き連鎖
18
2.12. 推論機能
18
2.13. エキスパートシステム
19
2.14. Rete Root ノード
19
2.15. ObjectT ypeNode
19
2.16. AlphaNodes
19
2.17. ハッシュ
19
2.18. BetaNodes
20
2.19. アルファメモリ
20
2.20. ベータメモリ
20
2.21. BetaNodes を用いたルックアップ
20
2.22. LeftInputNodeAdapters
20
2.23. 終端ノード
20
2.24. ノード共有
20
2.25. ノード共有の例
21
2.26. 疎結合
21
2.27. 密結合
21
2.28. 宣言型プログラミング
21
2.29. 論理とデータの分離
21
2.30. ナレッジベース
22
. . .3章
第
. . . ユーザーガイド
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23
...........
3.1. ステートレスナレッジセッション
23
3.2. ステートレスセッションでのルールの設定
23
3.3. 複数のオブジェクトを使用したルールの設定
24
3.4. ステートフルセッション
26
3.5. ステートフルセッションセッションの一般的なユースケース
26
3.6. ステートフルセッションの監査の例
27
1
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
3.7. 一階論理
3.8. 一階論理を使ったルール設定
3.9. ルールシステムの設定サンプル
3.10. JBoss Rules のメソッド
3.11. メソッドの例
3.12. ルールの例
3.13. クロスプロダクト
3.14. クロスプロダクトの制約
3.15. 推論エンジン
3.16. 推論の例
3.17. 論理アサーション
3.18. 記述 (stated) 挿入
3.19. 正当化 (Justified) 挿入
3.20. WM_BEHAVIOR_PRESERVE 設定
3.21. 記述挿入のフローチャート
3.22. 論理挿入のフローチャート
3.23. 真理維持システム
3.24. insertLogical ファクト
3.25. 推論と T MS の使用
28
28
29
30
30
30
31
31
31
32
32
32
32
32
33
33
34
34
35
. . .4.章
第
. . .決定表
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .37
...........
4.1. 決定表
37
4.2. スプレッドシート
37
4.3. Open Office の例
37
4.4. ルールとスプレッドシート
38
4.5. RuleT able のキーワード
38
4.6. RuleSet キーワード
38
4.7. ルールテンプレートの例
39
4.8. データ定義セル
40
4.9. ルールテーブルの列
40
4.10. ルールセットのエントリ
41
4.11. ルールセットエリアのエントリ
41
4.12. ルールセットエリアのルール属性エントリ
42
4.13. RuleT able のセル
43
4.14. 列タイプ
44
4.15. ルールテーブルの列ヘッダー
44
4.16. 条件の要素
44
4.17. Action ステートメント
45
4.18. Metadata ステートメント
46
4.19. セルデータ補間の例
46
4.20. セル内での作業する際のヒント
46
4.21. SpreadsheetCompiler クラス
47
4.22. スプレッドシートベースの決定表の使用
47
4.23. Lists
47
4.24. 改訂管理
47
4.25. 表形式のデータソース
47
4.26. ルールテンプレートの機能
48
4.27. ルールテンプレートの例
48
4.28. ルールテンプレートの実行
49
4.29. Changeset の展開例
49
4.30. Changeset およびディレクトリの例
50
4.31. ナレッジエージェント
50
4.32. ナレッジエージェントの例
50
4.33. KnowledgeAgent オブジェクト
51
4.34. ポーリングサービスの開始
51
4.35. KnowledgeBuilder 向けのカスタムの Classloader
51
2
目次
4.36. KnowledgeBase ClassLoader の再利用
4.37. KnowledgeAgentConfiguration の例
4.38. newInstance プロパティ
4.39. newInstance プロパティの使用
4.40. newInstance の例
4.41. リモートの HT T P リソースキャッシュ
4.42. 再起動後のリソースキャッシュのリストア
51
51
52
52
52
52
53
. . .5章
第
. . . .処理
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
............
5.1. アジェンダ
54
5.2. アジェンダの処理
54
5.3. デフォルトの競合解消戦略
54
5.4. AgendaGroup
55
5.5. setFocus()
55
5.6. setFocus() の例
55
5.7. ActivationGroup
55
5.8. ActivationGroup の例
55
5.9. RuleFlowGroup
56
5.10. RuleFlowGroup の例
56
5.11. ルールとメソッドの違い
56
5.12. クロスプロダクトの例
56
5.13. アクティベーション、アジェンダ、コンフリクトの例
57
5.14. 競合解消戦略
59
5.15. 競合解消戦略の例
59
5.16. トリガーの例
59
5.17. ruleflow-group の例
59
5.18. 推論の例
60
5.19. 推論および T ruthMaintenance の実装
60
. . .6章
第
. . . .ルール言語
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .63
...........
6.1. KnowledgeBuilder
63
6.2. ResourceFactory
63
6.3. 新しい KnowledgeBuilder の作成
63
6.4. DRL リソースの追加
63
6.5. KnowledgeBuilder 結果の確認方法
64
6.6. KnowledgePackages の取得
64
6.7. KnowledgeBuilder の展開例
64
6.8. バッチモードでの KnowledgeBuilder の使用
65
6.9. 最後に追加した DRL ビルドの破棄
65
6.10. 設定および ChangeSet XML を使用した構築
65
6.11. ChangeSet XML の XML スキーマ (標準ではない)
66
. . .7章
第
. . . .ChangeSet
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
............
7.1. Changeset
69
7.2. changeset の例
69
7.3. ChangeSet XML の例
69
7.4. ChangeSet プロトコル
70
7.5. ChangeSet XML のロード
70
7.6. リソース設定を持つ ChangeSet XML の例
70
7.7. ChangeSet XML およびディレクトリ
71
. . .8章
第
. . . .構築
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
............
8.1. ビルド結果の重要度
72
8.2. デフォルトのビルド結果の重要度設定
72
8.3. KnowledgePackage
72
8.4. 新しい KnowledgeBase の作成
73
3
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
8.5. インプロセス構築およびデプロイ
8.6. KnowledgeBase への KnowledgePackages の追加
8.7. 別のプロセスでの構築およびデプロイメント
8.8. OutputStream への KnowledgePackage の記述
8.9. InputStream から KnowledgePackage の読み取り
8.10. JBoss Rules 管理システム
8.11. StatefulknowledgeSessions および KnowledgeBase の変更
8.12. 新たな knowledgeAgent
8.13. OutputStream への KnowledgePackage の記述
8.14. スキャンと通知サービスの開始
8.15. ResourceChangeScanner
8.16. スキャン間隔の変更
8.17. ナレッジエージェントとナレッジベース間の対話
8.18. 既存の KnowledgeBase の使用
8.19. applyChangeSet() メソッド
8.20. ディレクトリのコンテンツを追加するための ChangeSet XML
8.21. KnowledgeAgentConfiguration プロパティ
8.22. スキャン動作の変更
73
73
73
73
74
74
74
74
74
75
75
75
75
76
76
76
77
77
. . .9章
第
. . . .セッション
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
............
9.1. JBoss Rules のセッション
78
9.2. KnowledgeBase からの StatefulKnowledgeSession の作成
78
9.3. WorkingMemoryEntryPoint メソッド
78
9.4. KnowledgeRuntime インターフェース
78
9.5. ファクトの挿入
78
9.6. FactHandle トークン
78
9.7. FactHandle の例
79
9.8. アイデンティティと等価
79
9.9. 取り消し
79
9.10. 取り消しの例
80
9.11. update() メソッド
80
9.12. update() の例
80
9.13. クエリ
80
9.14. クエリの例
81
9.15. ライブクエリ
81
9.16. ViewChangedEventListener の実装例
81
9.17. KnowledgeRuntime
82
. . .10章
第
. . . . .オブジェクトとインターフェース
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .83
...........
10.1. グローバル (Global)
83
10.2. Global との連携
83
10.3. Global の解決
83
10.4. Session Scoped Global の例
84
10.5. StatefulRuleSessions
84
10.6. AgendaFilter オブジェクト
84
10.7. AgendaFilter の使用
84
10.8. ルールエンジンのフェーズ
84
10.9. イベントモデル
85
10.10. KnowlegeRuntimeEventManager
85
10.11. WorkingMemoryEventManager
85
10.12. AgendaEventListener の追加
85
10.13. ワーキングメモリのイベントの出力
86
10.14. KnowlegeRuntimeEvents
86
10.15. KnowledgeRuntimeEvent インターフェースに対応のイベント
86
10.16. KnowledgeRuntimeLogger
86
10.17. FileLogger の有効化
87
4
目次
10.18. JBoss Rules での StatelessKnowledgeSession の使用
10.19. コレクションを使用した StatelessKnowledgeSession の実行
10.20. InsertElements コマンドを使用した StatelessKnowledgeSession の実行
10.21. BatchExecutionHelper
10.22. CommandExecutor インターフェース
10.23. Out 識別子
87
87
88
88
88
88
. . .11章
第
. . . . .モードとメソッド
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
............
11.1. シーケンシャルモード
90
11.2. シーケンシャルモードのオプション
90
11.3. シーケンシャルモードの有効化
90
11.4. CommandFactory
90
11.5. 対応の CommandFactory オプション
91
11.6. 挿入コマンド
91
11.7. 挿入コマンドの例
91
11.8. 実行メソッド
91
11.9. 実行メソッドの例
91
11.10. BatchExecution コマンド
92
11.11. FireAllRules コマンド
92
11.12. Out 識別子
92
11.13. Out 識別子の例
92
11.14. 実行 XML の例
93
11.15. 実行マーシャリングの例
93
11.16. Batch-execution とコマンドの例
94
11.17. MarshallerFactory
97
11.18. マーシャラーの例
97
11.19. マーシャリングのオプション
97
11.20. IdentityMarshallingStrategy の例
97
11.21. ObjectMarshallingStrategyAcceptor
98
11.22. ClassFilterAcceptor の実装
98
11.23. アクセプターを使用した IdentityMarshallingStrategy の例
98
11.24. JBoss Rules の永続性とトランザクション
98
11.25. トランザクション例
99
11.26. JPA の使用
99
11.27. JPA を持つ StatefulKnowledgeSession のロード
99
11.28. JPA の設定
99
11.29. JT A DataSource の設定
100
11.30. JNDI プロパティ
100
11.31. KnowledgeBase 名前空間
101
. . .12章
第
. . . . .Using
. . . . . . Spreadsheet
. . . . . . . . . . . . . .Decision
.........T
. .ables
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
.............
12.1. ハードキーワード
102
12.2. ソフトキーワード
102
12.3. ソフトキーワードのリスト
102
12.4. コメント
103
12.5. 1 行コメントの例
103
12.6. 複数行コメントの例
103
12.7. エラーメッセージ
104
12.8. パッケージ
105
12.9. Import ステートメント
105
12.10. Global の使用
105
12.11. From 要素
105
12.12. e-メールサービスでの Global の使用
106
. . .13章
第
. . . . .関数
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
.............
13.1. 関数
107
5
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
13.2. 関数宣言の例
13.3. 静的メソッドを使用する関数宣言の例
13.4. 関数宣言呼び出しの例
13.5. 型宣言
13.6. 型宣言のロール
13.7. 新しい型の宣言
13.8. 新しいファクト型の宣言例
13.9. 新しいファクト型の宣言の追加例
13.10. Import の使用例
13.11. 生成された Java クラス
13.12. 生成 Java クラスの例
13.13. ルールでの宣言型の使用例
13.14. メタデータの宣言
13.15. メタデータ属性との連携
13.16. ファクト型でのメタデータ属性の宣言例
13.17. @position 属性
13.18. @position の例
13.19. 事前定義済みのクラスレベルアノテーション
13.20. @key 属性関数
13.21. @key 宣言の例
13.22. キーコンストラクターでのインスタンスの作成例
13.23. 位置引数
13.24. 位置引数の例
13.25. @Position アノテーション
13.26. パターンの例
107
107
107
108
108
108
108
109
109
109
109
110
110
110
111
111
111
111
112
112
113
113
113
113
113
. . .14
第
. .章
. . .その他の宣言
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
.............
14.1. 既存のタイプのメタデータの宣言
115
14.2. 既存型へのメタデータの宣言例
115
14.3. 完全修飾クラス名を使用したメタデータの宣言例
115
14.4. 宣言型に対してパラメーター化されたコンストラクトの例
115
14.5. 型安全でないクラス
116
14.6. アプリケーションコードからの宣言済みタイプへのアクセス
116
14.7. 型の宣言
116
14.8. API を使用して宣言されたファクト型を処理する例
116
14.9. 型宣言の extends
117
14.10. 型宣言の extends 例
117
14.11. T rait
118
14.12. T rait の例
118
14.13. コアオブジェクトと trait
118
14.14. @T raitable の例
118
14.15. T rait でのルールの記述
119
14.16. T rait とルールの例
119
14.17. 隠しフィールド
119
14.18. 二部プロキシ (two-part proxy)
119
14.19. ラッパー
119
14.20. ラッパーの例
120
14.21. isA アノテーションを使用したラッパー例
120
14.22. T rait の削除
120
14.23. ルール構文の例
121
14.24. タイマー属性の例
121
14.25. タイマー
121
14.26. Cron タイマーの例
121
14.27. カレンダー
122
14.28. Quartz カレンダーの例
122
14.29. カレンダーの登録
122
6
目次
14.30. 左辺部 (LHS)
14.31. 条件の要素
14.32. 条件要素なしのルールの例
123
123
123
. . .15章
第
. . . . .パターン
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .124
.............
15.1. パターン
124
15.2. パターンの例
124
15.3. パターン一致
124
15.4. パターンのバインディング
124
15.5. 変数でバインドしたパターンの例
125
15.6. 制約
125
. . .16章
第
. . . . .要素と変数
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
.............
16.1. Java Bean でのプロパティアクセス (POJO)
126
16.2. POJO の例
126
16.3. POJO との連携
126
16.4. POJO フォールバック
127
16.5. フォールバックの例
127
16.6. Java 表現
127
16.7. コンマ区切りの演算子
129
16.8. コンマ区切りの演算子例
129
16.9. バインド変数
129
16.10. バインド変数の例
130
16.11. ユニフィケーション
130
16.12. ユニフィケーションの例
130
16.13. JBoss Rules のオプションと演算子
130
16.14. 演算子の優先順位
133
16.15. 粒度の高いプロパティ変更リスナー
134
16.16. 粒度の高いプロパティ変更リスナーの例
134
16.17. 粒度の高いプロパティ変更リスナーとの連携
135
16.18. @watch でのパターンの使用
135
16.19. @watch の例
135
16.20. @PropertySpecificOption の使用
136
16.21. 基本的な条件要素
136
16.22. 条件要素 Forall
139
16.23. Forall の例
139
16.24. 条件要素 From
140
16.25. From の例
141
16.26. 条件要素 collect
142
16.27. 条件要素 Accumulate
142
16.28. 条件要素 accumulate の構文
142
16.29. 条件要素 accumulate の関数
143
16.30. 条件要素 accumulate およびプラガビリティ
143
16.31. 条件要素 accumulate とプラガビリティの例
144
16.32. 条件要素 accumulate 関数のコード
146
16.33. インライン式のカスタムコードを使用した accumulate
147
16.34. インライン式のカスタムコードを使用した accumulate の例
148
16.35. 条件要素 eval
148
16.36. 条件要素 eval の例
149
16.37. 右辺部 (RHS)
149
16.38. RHS コンビニエンスメソッド
149
16.39. Drools 変数を使用したコンビニエンスメソッド
150
16.40. kcontext 変数を使用したコンビニエンスメソッド
150
16.41. modify ステートメント
151
16.42. クエリーの例
151
16.43. QueryResults の例
152
7
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
16.44. 他のクエリを呼び出すクエリ
16.45. 他のクエリを呼び出すクエリ例
16.46. 派生クエリのユニフィケーション
152
153
153
. . .17章
第
. . . . .ドメイン固有言語
. . . . . . . . . . . . . . . . . .(DSL)
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
.............
17.1. ドメイン固有言語
155
17.2. DSL の使用
155
17.3. DSL の例
155
17.4. DSL パーサーの仕組み
155
17.5. DSL コンパイラー
156
17.6. DSL 構文の例
156
17.7. DSL 表現の連鎖
158
17.8. ファクトへの制約の追加
158
17.9. DSL 開発のヒント
160
17.10. DSL および DSLR 参照
160
17.11. DSL エントリの構成
161
17.12. DSL 拡張のデバッグオプション
161
17.13. DSL 定義の例
162
17.14. DSLR ファイルの変換
162
17.15. 文字列変換関数
163
17.16. 文字列 DSL 変換関数
163
. . .18章
第
. . . . .XML
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
.............
18.1. XML 形式
165
18.2. XML ルールの例
165
18.3. XML 要素
169
18.4. ルール要素の詳細
169
18.5. XML ルールの要素
170
18.6. XML と DRL 間の自動変換
171
18.7. XML と DRL 間の自動変換用のクラス
171
. . .19章
第
. . . . .Java
. . . . . ルールエンジンアプリケーションプログラミングインターフェース
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
.............
19.1. JSR94
172
19.2. Javax.rules インターフェース
172
19.3. Javax.rules クラス
173
19.4. Javax.rules の例外
173
19.5. ルールサービスプロバイダーの使用
174
19.6. Javax.rules.admin インターフェース
174
19.7. Javax.rules.admin の例外
174
19.8. RuleServiceProvider
175
19.9. RuleServiceProviderManager
175
19.10. RuleServiceProvider 自動登録の例
175
19.11. LocalRuleExecutionSet を RuleAdministrator API で登録
175
19.12. ステートフルおよびステートレス RuleSessions
177
19.13. JSR94 での Global の使用
177
19.14. JSR94 で Global を使用した例
177
19.15. JSR94 に関する参考資料
178
. . .20章
第
. . . . .JBoss
. . . . . . .Developer
. . . . . . . . . . .Studio
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
.............
20.1. ルールの統合開発環境 (IDE)
179
20.2. Rules IDE 機能
179
20.3. JBoss Rules ランタイム
179
20.4. JBoss Rules ランタイムの定義
180
20.5. JBoss Rules プロジェクトに対するランタイムの選択
180
20.6. Rule ファイルの例
181
20.7. JBoss Rules Builder
181
8
目次
20.8. 新規ルールの作成
20.9. ルールエディター
20.10. JBoss ルールビュー
20.11. JBoss Rules ビューの使用
20.12. Show Logical Structure
20.13. 監査ログの作成
20.14. 監査ビューのイベントアイコン
20.15. 原因取得のメソッド
20.16. DSL エディター
20.17. ルール言語マッピング
20.18. ルール言語マッピングでの作業
20.19. DSL 変換コンポーネント
20.20. 大きな DRL ファイルで作業する際のヒント
20.21. ブレークポイントの作成
20.22. JBoss Rules アプリケーションとしてのデバッグ
20.23. Rules IDE の設定
181
182
182
183
183
183
183
184
184
184
185
185
185
186
186
187
. . .21章
第
. . . . .Hello
. . . . . .World
. . . . . .の例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
.............
21.1. HelloWorld の例: KnowledgeBase とセッションの作成
188
21.2. HelloWorld の例: イベントのロギングと監査
188
21.3. HelloWorld の例: Message クラス
189
21.4. HelloWorld の例: 実行
189
21.5. HelloWorld の例: コンソールウィンドウでの System.out
190
21.6. HelloWorld の例: ルール "Hello World"
190
21.7. HelloWorld の例: "Debug as..." オプションの使用
191
21.8. HelloWorld の例: ルール "Good Bye"
191
. . .22章
第
. . . . .Salience
. . . . . . . . . ステータスの例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
.............
22.1. Salience ステータスの例: State クラスの例
192
22.2. Salience ステータスの例: 実行
192
22.3. Salience ステータスの例: アプリケーションの実行
192
22.4. Salience ステータスの例: オペレーションのある監査ロギングを使用
193
22.5. Salience ステータスの例: ルール "Bootstrap"
193
22.6. Salience ステータスの例: ルール "B to C"
194
22.7. Salience ステータスの例: ルール "B to D"
194
22.8. Salience ステータスの例: 動的ファクトの挿入
194
22.9. Salience ステータスの例: PropertyChangeSupport を持つセッター
195
22.10. Salience ステータスの例: グループルール "B to C"
195
22.11. Salience ステータスの例: グループルール "B to D"
196
22.12. Salience ステータスの例: グループルール "D to E"
196
. . .23章
第
. . . . .フィボナッチの例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
.............
23.1. フィボナッチの例: クラス
197
23.2. フィボナッチの例: 実行
197
23.3. フィボナッチの例: 実行の詳細
198
23.4. Fibonacci の例: Recurse ルール
198
23.5. Fibonacci の例: Bootstrap ルール
199
23.6. Fibonacci の例: Calculate ルール
199
. . .24
第
. .章
. . .バンキングの例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
.............
24.1. バンキングの例: RuleRunner
201
24.2. バンキングの例: Example1.drl のルール
201
24.3. バンキングの例: Java の例 2
202
24.4. バンキングの例: Example2.drl のルール
202
24.5. バンキングの例: Example3.java
203
24.6. バンキングの例: Example3.drl のルール
203
9
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
24.7. バンキングの例: Cashflow クラス
24.8. バンキングの例: Example4.java
24.9. バンキングの例: SimpleDate クラス
24.10. バンキングの例: Example4.drl のルール
24.11. バンキングの例: T ypedCashflow クラス
24.12. バンキングの例: Example5.java
24.13. バンキングの例: Account クラス
24.14. バンキングの例: AllocatedCashflow クラス
24.15. バンキングの例: Example5.java の継承
24.16. バンキングの例: Example6.drl のルール
204
204
205
205
206
207
208
208
209
210
. . .25章
第
. . . . .価格設定ルールの例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
.............
25.1. 価格設定ルールの例: 価格設定ルールの実行例
213
25.2. 価格設定ルールの例: 決定テーブルの設定
213
25.3. 価格設定ルールの例: 基本価格の算出例
214
25.4. 価格設定ルールの例: 割引の算出例
215
. . .26章
第
. . . . .ペットショップの例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
.............
26.1. ペットショップの例
217
26.2. ペットショップの例: PetStore.main での PetStore RuleBase 作成
217
26.3. ペットショップの例: CheckoutCallBack.checkout() からのルールの発火
218
26.4. ペットショップの例: PetStore.drl からのパッケージ、インポート、グローバル、方言
218
26.5. ペットショップの例: PetStore.drl からの抽出された Java 関数
219
26.6. ペットショップの例: PetStore.drl からワーキングメモリへのアイテム追加
221
26.7. ペットショップの例: PetStore.drl から GUI のアイテムを表示
221
26.8. ペットショップの例: PetStore.drl からのアジェンダグループの評価
222
26.9. ペットショップの例: PetStore.drl からチェックアウトを抽出
223
26.10. ペットショップの例: PetStore.drl からチェックアウトルール
223
26.11. ペットショップの例: PetStore.java の実行
224
26.12. ペットショップの例: チェックアウトルールの実行
225
. . .27章
第
. . . . .数独の例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
.............
27.1. 数独の例: 例の読み込み
226
27.2. 数独の例: 壊れた内容のデバッグ例
226
27.3. 数独の例: Java ソースおよびルール
227
27.4. 数独の例: Cell オブジェクト
227
27.5. 数独の例: クラスとオブジェクト
228
27.6. 数独の例: Validate.drl
228
27.7. 数独の例: Sudoku.drl
228
. . .28章
第
. . . . .数字当ての例
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
.............
28.1. 数字当ての例: サンプルの読み込み
230
28.2. 数字当ての例: RuleFlow の開始
230
28.3. 数字当ての例: クラスとメソッド
230
28.4. 数字当ての例: RuleFlow の確認
231
28.5. 数字当ての例: RuleFlow ノード
231
28.6. 数当ての例: NumberGuess.drl の特定のポイントでのルールの発火
232
28.7. 数字当ての例: RuleFlow の制約の確認
232
28.8. 数字当ての例: コンソールの出力
233
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
改訂履歴
.............
10
目次
11
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
前書き
1. 本 書 の 表 記 規 則
本ガイドでは、一部の単語や語句を強調して、特定の情報に対する読者の注意を促すために、以下のよう
な表記規則を採用しています。
本ガイドの PDF および紙書籍版では、Liberation フォントセットの書体を使用しています。また、
Liberation フォントセットがご使用のシステムにインストールされている場合には、HT ML 版もこの書体
で表示されます。インストールされていない場合には、別の対応する書体で表示されます。なお、Red
Hat Enterprise Linux 5 以降のバージョンでは、Liberation フォントセットがデフォルトでインストールさ
れる点に注意してください。
1.1. 書体の表記規則
本ガイドでは、特定の単語や語句に対する注意を促すために、4 つの書体表記規則を採用しています。こ
れらの表記規則および適用される状況は、以下のとおりです。
太字の等幅フォント
シェルコマンド、ファイル名、パスなど、システムへの入力を強調するために使用します。また、キー名
やキーの組み合わせを強調するのにも使用します。以下が例となります。
作業ディレクトリ内の m y_next_bestselling_novel というファイルの内容を表示する
には、シェルプロンプトで cat m y_next_bestselling_novel というコマンドを入力し
て Enter キーを押し、そのコマンドを実行します。
上記の例には、ファイル名、シェルコマンド、キー名が含まれており、すべて太字の等幅フォントで表示
されていますが、文脈で区別することができます。
キーの組み合わせは、プラス記号 (+) で各キーがつながれているので、個別のキーと区別することができ
ます。以下が例となります。
Enter を押してコマンドを実行します。
Ctrl+Alt+F2 を押して仮想ターミナルに切り替えます。
第 1 の例では、押すべき特定のキー名が強調されています。第 2 の例では、3 つのキーを同時に押す、
キーの組み合わせが強調されています。
ソースコードを記載する場合、その段落で言及されるクラス名、メソッド、関数、変数名、戻り値は上記
のように 太字の等幅フォント で表示されます。以下が例となります。
ファイル関連のクラスには、filesystem (ファイルシステム)、file (ファイル)、dir
(ディレクトリ) などがあります。各クラスにそれぞれ独自のパーミッションセットが関連付
けられています。
太字の可変幅フォント
この書体は、アプリケーション名、ダイアログボックスのテキスト、ラベル付きボタン、チェックボック
ス/ラジオボタンのラベル、メニュータイトル、サブメニュータイトルなど、システムで表示される単語や
語句であることを示します。以下が例となります。
メインメニューバーから システム → 設定 → マウス の順で選択し、マウスの設定 を起動
します。全般 タブで 左利き のラジオボタンを選択して 閉じる をクリックし、マウスの主
12
前書き
ボタンを左から右へ切り替えます (左利きのユーザーが使用するのに適切な設定に変更しま
す)。
gedit ファイルに特殊文字を入力するには、メインのメニューバーから アプリケーション
→ アクセサリ → 文字マップ の順に選択します。次に 文字マップ のメニューバーから 検
索 → 検索 … の順に選択して 検索 フィールドに文字名を入力し、次を検索 をクリックしま
す。検索対象の文字が 文字テーブル に強調表示されます。その文字をダブルクリックして
コピーする文字列 のフィールドに表示されたら、コピー ボタンをクリックします。この後
に編集中のドキュメントに戻り、gedit のメニューバーから 編集 → 貼り付け の順で選択し
ます。
上記のテキストには、アプリケーション名、システム全体のメニュー名と項目、アプリケーション固有の
メニュー名、GUI インターフェースで使用されているボタンおよびテキストが含まれており、これらはす
べて、太字の可変幅フォントで表示されていますが、文脈で区別することができます。
太字斜体の等幅フォント または 太字斜体の可変幅フォント
太字の等幅フォントおよび太字の可変幅フォントに斜体を使用した場合には、いずれも置き換え可能な可
変テキストであることを意味します。斜体は、記載されている通りには入力しないテキスト、あるいは状
況によって変化するテキストを示します。以下が例となります。
ssh を使用してリモートマシンに接続するには、シェルプロンプトで ssh
username@ domain.name と入力します。リモートマシンが exam ple.com で、そのマシン
上のユーザー名が john である場合には、ssh john@ exam ple.com と入力してください。
m ount -o rem ount file-system のコマンドは、指定したファイルシステムを再マウン
トします。たとえば、/hom e ファイルシステムを再マウントするコマンドは m ount -o
rem ount /hom e となります。
現在インストール済みのパッケージのバージョンを確認するには、rpm -q package のコマ
ンドを使用します。その結果、次のような出力が返されます: package-version-release
ユーザー名、ドメイン名、ファイルシステム、パッケージ、バージョン、およびリリースが太字のイタ
リック体で表示されている点に注意してください。これらの語句はプレースホルダーで、コマンドを発行
する際に入力するテキストまたはシステムによって表示されるテキストのいずれかです。
斜体は、著作物のタイトルを表すという標準的な用途の他に、重要な用語の初出時にも使用されます。以
下が例となります。
Publican は DocBook の出版システムです。
1.2. 引用文の表記規則
端末の出力とソースコードは、周囲のテキストとは視覚的に区切られて表示されます。
端末に送信される出力は、ローマン体の等幅フォント を使用して以下のように表示されます。
books
books_tests
Desktop
Desktop1
documentation
downloads
drafts
images
mss
notes
photos
scripts
stuff
svgs
svn
ソースコードの表示にも ローマン体の等幅フォント が使用されますが、以下のような構文強調表示が追
加されます。
13
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
package org.jboss.book.jca.ex1;
import javax.naming.InitialContext;
public class ExClient
{
public static void main(String args[])
throws Exception
{
InitialContext iniCtx = new InitialContext();
Object
ref
= iniCtx.lookup("EchoBean");
EchoHome
home
= (EchoHome) ref;
Echo
echo
= home.create();
System.out.println("Created Echo");
System.out.println("Echo.echo('Hello') = " + echo.echo("Hello"));
}
}
1.3. 注記および警告
本ガイドでは、見落としがちな情報に注意を促すために、次にあげる 3 つの視覚的スタイルを使用してい
ます。
注記
注記には、対象のタスクに関するヒント、ショートカット、その他のアプローチなどを記載してい
ます。注記を無視しても、悪影響はありませんが、作業を効率的に行うためのコツを見逃してしま
う可能性があります。
重要
重要の欄には、現行セッションのみに適用される設定の変更や、更新を適用するのに再起動が必要
なサービスなど、見落としがちな情報を記載しています。「重要」と記載された事項を無視して
も、データ損失などには至りませんが、作業が思ったようにスムーズに進まなくなる可能性があり
ます。
警告
警告は、無視しないでください。警告を無視すると、データ損失が発生する可能性が非常に高くな
ります。
2. サ ポ ー ト 、 お よ び フ ィ ー ド バ ッ ク の お 願 い
2.1. サポートが必要ですか?
本書に説明してある手順で問題があれば、Red Hat カスタマーポータル(http://access.redhat.com)をご覧
ください。カスタマーポータルでは以下を行うことができます。
14
前書き
Red Hat 製品に関する技術的なサポートの記載をナレッジベースで検索、閲覧することができます。
サポートケースを Red Hat グローバルサポートサービス(GSS)に提出することができます。
他の製品文書を参照することができます。
また、Red Hat は Red Hat のソフトウェアやテクノロジーに関するディスカッションの場として多くの
メーリングリストを設置しています。公開されているメーリングリストについて
はhttps://www.redhat.com/mailman/listinfoで一覧を参照してください。メーリングリストをサブスクライ
ブする、またはメーリングリストのアーカイブを参照する場合はそのメーリングリスト名をクリックしま
す。
2.2. フィードバックをお願いします
誤植、本ガイドの改善案がある場合、ご意見お待ちしております。製品JBoss Enterprise BRMS
Platform 5、コンポーネントDocum entationとしBugzilla から報告してください。以下のリン
クhttps://bugzilla.redhat.com/から、あらかじめ記入が施されている本製品のバグレポートへ移動できま
す。
Bugzilla のDescription フィールドにある以下のテンプレートに記載してください。できるだけ具体的
に問題を説明していただけると、迅速に問題解決へ向けた取り組みが行いやすくなります。
文書URL:
項、項のタイトル:
問題の説明:
改善案:
追加情報:
問題報告の功績が認められるよう、名前を記載するのを忘れないようにしてください 。
15
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 1章 はじめに
1.1. 対 象 読 者
本書は、JBoss Rules のツールの使用方法を学習したいシステム管理者を対象としています。新規プロ
ジェクトの作成、プロジェクトのデバッグ、エディターの使用方法について説明しています。
バグを報告する
1.2. 本 書 の 目 的
本書は、JBoss Rules の使用方法に関する概要を説明することを目的としています。また、基本用語を詳
しく説明するとともに、1 からルールを作成する方法も説明しています。プロジェクトのルール作成を支
援するチュートリアルも複数含まれています。
バグを報告する
16
第2章 クイックスタート
第 2章 クイックスタート
2.1. JBoss Rules
JBoss Rules は、JBoss Enterprise SOA Platform 製品に同梱されているビジネルルールエンジンの名称
です。
バグを報告する
2.2. JBoss Rules エ ン ジ ン
JBoss Rules エンジンは、ルールを適用して知識表現と推論 (KRR: Knowledge Representation and
Reasoning) 機能を開発者に提供するコンピュータープログラムです。
バグを報告する
2.3. プ ロ ダ ク シ ョ ン ル ー ル
プロダクションルールは、二部構成となっており、ナレッジの表現に一階論理を使用します。このルール
は、以下の形式を取ります。
when
<conditions>
then
<actions>
バグを報告する
2.4. 推 論 エ ン ジ ン
推論エンジンは、JBoss Rules エンジンに含まれているエンジンで、プロダクションのファクトとデータ
をルールと照合します。その後、情報からの推測をもとにアクションを実行します。プロダクションルー
ルシステムの推論エンジンはステートフルで、真理維持を行います。
バグを報告する
2.5. ReteOO
JBoss Rules で使用される Rete 実装は、ReteOO と呼ばれ、オブジェクト指向システム向けに Rete ア
ルゴリズムを拡張、最適化した実装です。
バグを報告する
2.6. プ ロ ダ ク シ ョ ン メ モ リ
プロダクションメモリ とは、ルールを保存する場所のことです。
バグを報告する
2.7. ワ ー キ ン グ メ モ リ
17
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ワーキングメモリ は、JBoss Rules エンジンの一部でファクトがアサートされるところです。ここか
ら、ファクトを変更または削除することができます。
バグを報告する
2.8. 競 合 解 消 (Conflict Resolution) 戦 略
競合解消は、アジェンダに複数のルールがある場合に必要です。ルールを発火 (fire) すると、ワーキング
メモリに悪影響が及ぶ可能性があるため、ルールエンジンはルールを発火する順番を把握しておく必要が
あります (例えば、ルール A を発火するとルール B がアジェンダから削除されてしまう可能性があるな
ど)。
バグを報告する
2.9. ハ イ ブ リ ッ ド ル ー ル シ ス テ ム
ハイブリッドルールシステムは、前向き連鎖と後向き連鎖の両方を使用してルールを処理します。
バグを報告する
2.10. 前 向 き 連 鎖
前向き連鎖はプロダクションルールのシステムのことです。前向き連鎖は、渡されたデータに反応する
データ駆動型となっています。ファクトがワーキングメモリに挿入され、1 つまたは複数のルールが true
となります。その後、アジェンダで実行されるようにスケジュールに設定されます。
JBoss Rules は前向き連鎖エンジンです。
バグを報告する
2.11. 後 向 き 連 鎖
後向き連鎖のルールシステムは結論駆動型で、システムはエンジンが充足しようとする結論から開始しま
す。結論を充足できない場合、サブゴール (現在のゴールの一部を完結する結論) を探します。このプロセ
スは、最初の結論が充足されるか、充足されていないサブゴールがなくなるまで継続します。Prolog は
後向き連鎖エンジンの一例になります。
後向き連鎖
後向き連鎖は、JBoss BRMS 5.2 で実装されました。
バグを報告する
2.12. 推 論 機 能
JBoss Rules は、後向き連鎖の推論機能を使用してデータからどのルールを適用するかを推論しやすくし
ます。
バグを報告する
18
第2章 クイックスタート
2.13. エ キ ス パ ー ト シ ス テ ム
エキスパートシステムは、プロダクションルールシステムというフレームワークでドメインを表現するた
めのオントロジモデルを使用して、ナレッジの獲得や説明の機能を含めることで形成されると言われてい
ます。
バグを報告する
2.14. Rete Root ノ ー ド
Rete 00 を使用する場合、全オブジェクトがネットワークに入る場所が root ノードとなっています。ここ
から、ObjectT ypeNode にすぐ移動します。
バグを報告する
2.15. ObjectTypeNode
ObjectTypeNode は、ルールエンジンのワークロードを減らすのに役立ちます。オブジェクトが複数あ
り、ルールエンジンがオブジェクト毎にノードを 1 つずつ評価しようとする場合、多くのサイクルが無駄
になります。効率化を図るため、ObjectT ypeNode を使用してエンジンがオブジェクトの型に合うノード
にのみオブジェクトを渡すようにします。こうすることで、アプリケーションが新しいアカウントをア
サートしても、Order オブジェクトにはこのノードは伝播されません。
JBoss Rules では、アサートされたオブジェクトは、HashMap のルックアップを利用して有効な
ObjectT ypesNodes の一覧をオブジェクトのクラスから取得します。この一覧が存在しない場合、
ObjectT ypeNodes のをすべてスキャンして、マッチする有効な結果を探し出し一覧にキャッシュしま
す。こうすることで、instanceof チェックとマッチするクラス型はどれでも JBoss Rules で照合する
ことができるようになります。
バグを報告する
2.16. AlphaNodes
AlphaNodes は、リテラル条件を評価する際に使用します。1 つのオブジェクト型に対して複数のリテラ
ル条件がルール内に含まれる場合、これらのリテラル条件は関連付けられます。つまり、アプリケーショ
ンがアカウントオブジェクトをアサートした場合、最初のリテラル条件を充足してからでないと次の
AlphaNode に進むことができなくなっています。
AlphaNodes は ObjectT ypeNodes で伝播されます。
バグを報告する
2.17. ハ ッ シ ュ
JBoss Rules は ObjectT ypeNode から AlphaNode への伝播を最適化することでハッシュを使用して Rete
を拡張します。AlphaNode が ObjectT ypeNode に追加されるたびに、キーとしてのリテラル値を、値と
して AlphaNode を持つ HashMap に追加します。新しいインスタンスが ObjectT ype ノードに入ると、各
AlphaNode に伝播せずに HashMap から正しい AlphaNode を取得して、必要のないリテラルチェックを
回避します。
バグを報告する
19
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
2.18. BetaNodes
BetaNodes は、2 つのオブジェクトとそのフィールドを比較する際に使用します。これらのオブジェクト
の型は、同じ場合も、違う場合もあります。
バグを報告する
2.19. ア ル フ ァ メ モ リ
アルファメモリは、BetaNode への右からの入力を指します。JBoss Rules では、この入力により、入っ
てきたオブジェクトをすべて記憶します。
バグを報告する
2.20. ベ ー タ メ モ リ
ベータメモリは、BetaNoe の左側の入力を指します。このメモリは、入ってくるタプルをすべて記憶しま
す。
バグを報告する
2.21. BetaNodes を 用 い た ル ッ ク ア ッ プ
ファクトが片方から入った場合、ハッシュルックアップを行い有効な候補を返します (インデックス)。ど
の時点であっても有効な結合が見つかった場合は、タプルはオブジェクトと結合して (一部合致)、次の
ノードに伝播します。
バグを報告する
2.22. LeftInputNodeAdapters
LeftInputNodeAdapter は、オブジェクトを入力として受け入れ、1 つのオブジェクトタプルとして伝播し
ます。
バグを報告する
2.23. 終 端 ノ ー ド
終端ノードは、ある単一ルールが全条件に合致したこと (つまり、ルールに完全合致があったこと) を示す
のに使用します。or 条件の分離結合のあるルールでは、考えられる論理分岐ごとにサブルールが生成され
ることになります。これにより、1 つのルールに複数の終端ノードを含めることができます。
バグを報告する
2.24. ノ ー ド 共 有
ノード共有は、不必要な冗長性を避けるために使用されます。多くのルールは同じパターンを繰り返すた
め、ノード共有があるとこのようなパターンを減らして、インスタンスごとに再評価しなくてもよくなり
ます。
バグを報告する
20
第2章 クイックスタート
2.25. ノ ー ド 共 有 の 例
以下では 2 つのルールが最初のパターンを共有していますが、最後のパターンは共有していません。
rule
when
vehicle( $car : name == "car" )
$driver: Driver( typeCar == $sedan )
then
System.out.println( $driver.getName() + " drives sedan" );
end
rule
when
Vehicle( $sedan : name == "sedan" )
$driver : Driver( typeCar != $sedan )
then
System.out.println( $driver.getName() + " does not drive sedan" );
end
バグを報告する
2.26. 疎 結 合
疎結合は、ルール同士を緩く関連付け、1 つのルールが実行されても別のルールが実行されないようにし
ます。
一般的に、より柔軟性のある疎結合の設計が推奨されます。ルールがすべて密結合されている場合、柔軟
性に欠けることが多くなります。さらに、このような状況でのルールエンジンのデプロイは過剰対応であ
ることが分かります。
バグを報告する
2.27. 密 結 合
密結合は、ルールを関連付ける方法の 1 つです。ルールが密結合されている場合、1 つのルールを実行す
ると他の実行が引き起こされることになります。つまり、明確な論理的つながりがあるということです
(明確な連鎖は、決定木を使用してハードコード化するか、実装することができます)。
バグを報告する
2.28. 宣 言 型 プ ロ グ ラ ミ ン グ
宣言型プログラミングは、「どのようにするか」ではなく「何をするか」をルールエンジンが宣言できる
ように手段を指します。宣言プログラミングの主な利点は、ルールを使用すると困難な問題に対して解決
策を簡単に提示でき、結果的にこれらの解決策を検証できます。また、ルールはコードを解読するよりも
はるかに簡単です。
バグを報告する
2.29. 論 理 と デ ー タ の 分 離
論理とデータの分離は、論理とデータのコンポーネントの結合を切り離すプロセスのことです。この手法
を使用して、論理を多数のドメインオブジェクトやコントローラーに展開し、1 つまたは複数の分離ルー
21
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ルファイルですべてを整理することができます。
バグを報告する
2.30. ナ レ ッ ジ ベ ー ス
ナレッジベースは、KnowledgeBuilder でコンパイルされたルールの集まりで、アプリケーションのナ
レッジ定義すべてに対するレポジトリでもあります。ナレッジベースには、ルール、プロセス、関数、型
モデルなどが含まれている場合があります。ナレッジベース自体には、(ファクトとして知られる) インス
タンスデータは含まれておらず、代わりに、データの挿入やプロセスインスタンスの開始が可能なナレッ
ジベースからセッションが作成されます。セッションの作成を繰り返し行えるように、ナレッジベースを
キャッシュできるようにすることが推奨されます。
バグを報告する
22
第3章 ユーザーガイド
第 3章 ユーザーガイド
3.1. ス テ ー ト レ ス ナ レ ッ ジ セ ッ シ ョ ン
ステートレスナレッジセッションは、推論なしのセッションのことです。ステートレスセッションは、
セッションを使用してデータを渡し、結果を再度受け取るという点から関数のようであると言われます。
ステートレスナレッジセッションは、バリデーション、演算、ルーティング、フィルタリングを必要とす
る場合に便利です。
バグを報告する
3.2. ス テ ー ト レ ス セ ッ シ ョ ン で の ル ー ル の 設 定
手順 3.1 タスク
1. 以下の運転免許証の例のようにデータモデルを作成します。
public class Applicant {
private String name;
private int age;
private boolean valid;
// getter and setter methods here
}
2. 最初のルールを記述していきます。この例では、18 歳未満の申請者を拒否するためのルールを追加
しています。
package com.company.license
rule "Is of valid age"
when
$a : Applicant( age < 18 )
then
$a.setValid( false );
end
3. Applicant オブジェクトがルールエンジンに挿入されると、各ルールの制約がそのオブジェクト
を評価して一致があるか検索します (「オブジェクト型」には常に暗黙的な制約があり、それ以降
は明示的なフィールド制約をいくつでも存在させることができます)。
Is of valid age ルールでは、以下の 2 つの制約があります。
一致するファクトは、Applicant 型である必要があります。
Age の値は 18 未満である必要があります。
$a はバインド変数で、これを設定することで、ルールの結果 (ここからオブジェクトのプロパティ
を更新可能) 内の一致オブジェクトへ参照ができるようになります。
注記
ドル記号 ($) の使用はオプションです。これを使用すると、変数名とフィールド名を区別で
きます。
23
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
注記
ルールがクラスと同じフォルダー内にある場合、クラスパスのリソースローダーを使用して
最初のナレッジベースを構築することができます。
4. 以下のように、KnowledgeBuilder を使用してルール一覧をナレッジベースにコンパイルします。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClassPathResource( "licenseApplication.drl",
getClass() ), ResourceType.DRL );
if ( kbuilder.hasErrors() ) {
System.err.println( kbuilder.getErrors().toString() );
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
上記のコードスニペットは、newClassPathResource() メソッドを使用して、クラスパス内の
licenseApplication.drl ファイルを検索します (リソースのタイプは Drools ルール言語
(DRL: Drools Rule Language) です)。
5. KnowledgeBuider にエラーがないか確認してください。エラーがない場合は、セッションを構築で
きます。
6. ルールに対してデータを実行します (申請者は 18 歳未満であるため、申請は「無効」とマークされ
ます)。
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
Applicant applicant = new Applicant( "Mr John Smith", 16 );
assertTrue( applicant.isValid() );
ksession.execute( applicant );
assertFalse( applicant.isValid() );
結果
先ほどのコードは、ルールに対してデータを実行しました。申請者が 18 歳未満であるため、この申請は
無効とマークされました。
バグを報告する
3.3. 複 数 の オ ブ ジ ェ ク ト を 使 用 し た ル ー ル の 設 定
手順 3.2 タスク
1. オブジェクト実装 iterable (コレクションなど) に対してルールを実行するには、以下のコード
サンプルに記載しているように別のクラスを追加します。
24
第3章 ユーザーガイド
public class Applicant {
private String name;
private int age;
// getter and setter methods here
}
public class Application {
private Date dateApplied;
private boolean valid;
// getter and setter methods here
}
2. 申請が正規の時間枠内に行われたことを確認するために、以下のルールを追加します。
package com.company.license
rule "Is of valid age"
when
Applicant( age < 18 )
$a : Application()
then
$a.setValid( false );
end
rule "Application was made this year"
when
$a : Application( dateApplied > "01-jan-2009" )
then
$a.setValid( false );
end
3. JDK コンバーターを使用して、iterable インターフェースを実装します (このメソッドは
Arrays.asList(...) という行で始まります)。以下のコードは、iterable リストに対してルール
を実行しています。全コレクション要素は、一致するルールが発火される前に挿入されます。
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
Applicant applicant = new Applicant( "Mr John Smith", 16 );
Application application = new Application();
assertTrue( application.isValid() );
ksession.execute( Arrays.asList( new Object[] { application, applicant } ) );
assertFalse( application.isValid() );
注記
実は、execute(Object object) と execute(Iterable objects) メソッドは、
BatchExecutor インターフェースからの execute(Com m and com m and) と呼ばれる別
のメソッドの周りにある「ラッパー」です。
4. Com m andFactory を使用して指示を作成し、以下が execute( Iterable it ) と同じになる
ようにします。
ksession.execute( CommandFactory.newInsertIterable( new Object[] {
application, applicant } ) );
25
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
5. 違うコマンドや結果出力の識別子を多数使用する場合は、BatchExecutor と
Com m andFactory を使用します。
List<Command> cmds = new ArrayList<Command>();
cmds.add( CommandFactory.newInsert( new Person( "Mr John Smith" ), "mrSmith"
);
cmds.add( CommandFactory.newInsert( new Person( "Mr John Doe" ), "mrDoe" );
BatchExecutionResults results = ksession.execute(
CommandFactory.newBatchExecution( cmds ) );
assertEquals( new Person( "Mr John Smith" ), results.getValue( "mrSmith" ) );
注記
Com m andFactory は、BatchExecutor で使用可能な他のコマンドを多数サポートして
います。例えば、StartProcess、Query、SetGlobal などです。
バグを報告する
3.4. ス テ ー ト フ ル セ ッ シ ョ ン
ステートフルセッションは、反復的な変更をファクトに継続して加えることができま
す。StatelessKnowledgeSession では、StatefulKnowledgeSession は BatchExecutor イ
ンターフェースをサポートしています。唯一の相違点は、最後に FireAllRules コマンドが自動的に呼
び出されない点です。
警告
必ず、dispose() メソッドは、ステートフルセッションの実行後に呼び出すようにしてくださ
い。こうすることで、メモリリークが確実になくします。これは、ナレッジベースの作成時にナ
レッジベースがステートフルナレッジセッションへの参照を取得するのが原因です。
バグを報告する
3.5. ス テ ー ト フ ル セ ッ シ ョ ン セ ッ シ ョ ン の 一 般 的 な ユ ー ス ケ ー ス
モニタリング
例えば、株式市場の監視や購入プロセスの自動化が可能です。
診断
ステートフルセッションは、障害検出プロセスを実行するために使用できます。また、医療診断
プロセスでも利用可能です。
輸送関係
例えば、小包追跡や配送提供に関する問題にも適用できます。
コンプライアンスの確保
例えば、市場取引の合法性を検証するために使用できます。
26
第3章 ユーザーガイド
バグを報告する
3.6. ス テ ー ト フ ル セ ッ シ ョ ン の 監 査 の 例
手順 3.3 タスク
1. 監査対象のモデルを作成します。火災報知に関するこの例では、家の中の部屋がリストアップされ
ています。各部屋にはスプリンクラーがあり、火災はどの部屋からでも発生する可能性がありま
す。
public class Room
{
private String name
// getter and setter methods here
}
public class Sprinkler
{
private Room room;
private boolean on;
// getter and setter methods here
}
public class Fire
{
private Room room;
// getter and setter methods here
}
public class Alarm
{
}
2. このルールは、(特定の部屋のスプリンクラーの存在などを定義するため) 複数のオブジェクト間の
関係を表記する必要があります。これには変数のバインドをパターンの制約として使用します。結
果、クロスプロダクトになります。
3. Fire クラスのインスタンスを作成して、セッションに挿入します。
以下のルールは、Fire オブジェクトの room フィールドへバインドを追加して照合条件に制約を
加え、その部屋のスプリンクラーのみがチェックされるようにします。このルールが発火して結果
が実行されると、スプリンクラーが作動します。
rule "When there is a fire turn on the sprinkler"
when
Fire($room : room)
$sprinkler : Sprinkler( room == $room, on == false )
then
modify( $sprinkler ) { setOn( true ) };
System.out.println("Turn on the sprinkler for room "+$room.getName());
end
ステートレスセッションは標準の Java 構文を使用してフィールドを変更しましたが、上記のルー
ルは m odify ステートメントを使用します ("with" ステートメントのように動作します)。
バグを報告する
27
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
3.7. 一 階 論 理
一階論理では、個別のインスタンスではなくデータセットを参照することができます。
バグを報告する
3.8. 一 階 論 理 を 使 っ た ル ー ル 設 定
手順 3.4 タスク
1. キーワード Not で特徴づけられるパターンを設定します。一階論理は、他のキーワードがない場合
にのみルールの照合が行われるようにします。この例でのルールは、鎮火されるとスプリンクラー
をオフにします。
rule "When the fire is gone turn off the sprinkler"
when
$room : Room( )
$sprinkler : Sprinkler( room == $room, on == true )
not Fire( room == $room )
then
modify( $sprinkler ) { setOn( false ) };
System.out.println("Turn off the sprinkler for room "+$room.getName());
end
2. Alarm オブジェクトは、火災発生時に作成されますが、火災の数に関係なく建物全体で必要な
Alarm は 1 つのみです。Not の補完である exists を使用できるようになりました。これは、カ
テゴリの 1 つまたは複数のインスタンスとマッチします。
rule "Raise the alarm when we have one or more fires"
when
exists Fire()
then
insert( new Alarm() );
System.out.println( "Raise the alarm" );
end
3. すべて鎮火された場合はアラームを解除する必要があります。アラームをオフにするには Not を使
用します。
rule "Cancel the alarm when all the fires have gone"
when
not Fire()
$alarm : Alarm()
then
retract( $alarm );
System.out.println( "Cancel the alarm" );
end
4. このこーをを使用して、アプリケーションの初回起動時、アラームの解除時、全スプリンクラーの
解除時に一般的なヘルスステータスのメッセージを出力します。
28
第3章 ユーザーガイド
rule "Status output when things are ok"
when
not Alarm()
not Sprinkler( on == true )
then
System.out.println( "Everything is ok" );
end
5. fireAlarm .drl と呼ばれるファイルにルールを格納して、このファイルをクラスパスのサブディ
レクトリに保存します。
6. 最後に、新しい名前 fireAlarm .drl を使用して、knowledge base をビルドします。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClassPathResource( "fireAlarm.drl",
getClass() ), ResourceType.DRL );
if ( kbuilder.hasErrors() )
System.err.println( kbuilder.getErrors().toString() );
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
バグを報告する
3.9. ル ー ル シ ス テ ム の 設 定 サ ン プ ル
手順 3.5 タスク
1. ksession.fireAllRules() を挿入します。これにより、合致するルールの実行パーミッション
を割り当てましたが、この例では火災が起こっていないため、ヘルスメッセージのみを生成しま
す。
String[] names = new String[]{"kitchen","bedroom","office","livingroom"};
Map<String,Room> name2room = new HashMap<String,Room>();
for( String name: names )
{
Room room = new Room( name );
name2room.put( name, room );
ksession.insert( room );
Sprinkler sprinkler = new Sprinkler( room );
ksession.insert( sprinkler );
}
ksession.fireAllRules();
結果として出力されるメッセージは以下のとおりです。
> Everything is okay
2. 火災を 2 つ作成、挿入します (ファクトハンドルは保持されます)。
3. エンジンに火災があるため、fireAllRules() を呼び出します。火災報知機が作動して、該当す
るスプリンクラーがオンになります。
29
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
Fire kitchenFire = new Fire( name2room.get( "kitchen" ) );
Fire officeFire = new Fire( name2room.get( "office" ) );
FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
FactHandle officeFireHandle = ksession.insert( officeFire );
ksession.fireAllRules();
結果として出力されるメッセージは以下のとおりです。
> Raise the alarm
> Turn on the sprinkler for room kitchen
> Turn on the sprinkler for room office
4. 鎮火すると火災オブジェクトが取り消され、スプリンクラーがオフになります。この時点で火災報
知器はキャンセルされ、ヘルスメッセージがもう一度表示されます。
ksession.retract( kitchenFireHandle );
ksession.retract( officeFireHandle );
ksession.fireAllRules();
結果として出力されるメッセージは以下のとおりです。
>
>
>
>
Turn off the sprinkler for room office
Turn off the sprinkler for room kitchen
Cancel the alarm
Everything is okay
バグを報告する
3.10. JBoss Rules の メ ソ ッ ド
メソッドはルールとは違います。メソッドは直接呼び出され、個別のインスタンスを渡すために使用され
ます。呼び出しが 1 つの場合は、実行数も 1 つとなります。
バグを報告する
3.11. メ ソ ッ ド の 例
メソッドは、以下のように記述されます。
public void helloWorld(Person person) {
if ( person.getName().equals( "Chuck" ) ) {
System.out.println( "Hello Chuck" );
}
}
バグを報告する
3.12. ル ー ル の 例
ルールは以下のように記述されます。
30
第3章 ユーザーガイド
rule "Hello World"
when
Person( name == "Chuck" )
then
System.out.println( "Hello Chuck" );
end
バグを報告する
3.13. ク ロ ス プ ロ ダ ク ト
2 つ以上のデータセットを組み合わせた場合、その結果はクロスプロダクトと呼ばれます。
バグを報告する
3.14. ク ロ ス プ ロ ダ ク ト の 制 約
手順 3.6 タスク
ルールが大量のクロスプロダクトを出力しないように、クロスプロダクト自体を制約する必要があり
ます。以下のような変数制約を使用して、クロスプロダクトの制約を行います。
rule
when
$room : Room()
$sprinkler : Sprinkler( room == $room )
then
System.out.println( "room:" + $room.getName() +
" sprinkler:" + $sprinkler.getRoom().getName() );
end
以下の出力が表示されます。
room:office sprinkler:office
room:kitchen sprinkler:kitchen
room:livingroom sprinkler:livingroom
room:bedroom sprinkler:bedroom
結果
4 行のみの出力で、部屋ごとに正しいスプリンクラーが表示されます。この変数がないと、Room テーブ
ルの行と、Sprinkler テーブルの行が結合され、結果、行が多数出力されることになります。
バグを報告する
3.15. 推 論 エ ン ジ ン
推論エンジンは、JBoss Rules エンジンに含まれているエンジンで、プロダクションのファクトとデータ
をルールと照合します。その後、情報からの推測をもとにアクションを実行します。プロダクションルー
ルシステムの推論エンジンはステートフルで、真理維持を行います。
バグを報告する
31
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
3.16. 推 論 の 例
この例では、年齢フィールドと年齢ポリシー制御を行うルールを持つ Person ファクトを使用していま
す。推論を使用して、Person が成人か未成年かを判断し、その結果に対してアクションを実施します。
rule "Infer Adult"
when
$p : Person( age >= 18 )
then
insert( new IsAdult( $p ) )
end
上記のスニペットでは、18 歳以上の人には IsAdult というインスタンスが挿入されています。このファク
トは特別なもので、「関係」と呼ばれるものです。どのようなルールにおいても、この推論関係を使用す
ることができます。
$p : Person()
IsAdult( person == $p )
バグを報告する
3.17. 論 理 ア サ ー シ ョ ン
標準のオブジェクト挿入の後、明示的にファクトの取り消しを行う必要があります。論理アサーションで
は、最初にアサートした条件が true でなくなると、アサートされたファクトは自動的に取り消されます。
論理アサーションをサポートする単一条件がない場合のみ、取り消されます。
バグを報告する
3.18. 記 述 (stated) 挿 入
通常の挿入は、「ファクトの記述」という意味で記述挿入と呼ばれています。HashMap とカウンターを
使用して、特定の等価が何回、記述されたのかを追跡できます。つまり、同等なインスタンスがいくつあ
るかカウントすることができます。
バグを報告する
3.19. 正 当 化 (Justified) 挿 入
オブジェクトが論理的に挿入されることを正当化 (justified) と呼びます。発火ルールにより正当化されま
す。各論理挿入に、等価のオブジェクトが 1 つのみあり、それ以降に等価の論理挿入があると、この論理
アサーションに対する正当化カウンターの数が増えます。ルールの LHS の作成が true でなくなると正当
化が削除され、カウンターの数もそれにあわせて減少します。正当化がなくなると、論理オブジェクトが
自動的に取り消されます。
バグを報告する
3.20. WM_BEHAVIOR_PRESERVE 設 定
等価の記述 (stated) オブジェクトがある場合に論理的にオブジェクトを挿入すると失敗して null を返しま
す。正当化 (justified) された既存の等価オブジェクトを記述するとファクトを上書きすることになりま
す。WM_BEHAVIOR_PRESERVE 設定により、どのように上書きが行われるかが決定します。プロパティ
が discard に設定されている場合、既存のハンドルを使用して既存のインスタンスが新しいオブジェク
32
第3章 ユーザーガイド
トで置き換えられます。これはデフォルトの動作となっています。設定されていない場合は、これを記述
(stated) に置き換えてつつも、新しい FactHandle を作成する必要があります。
バグを報告する
3.21. 記 述 挿 入 の フ ロ ー チ ャ ー ト
バグを報告する
3.22. 論 理 挿 入 の フ ロ ー チ ャ ー ト
33
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
図 3.1 論理挿入フローチャートのスクリーンショット
バグを報告する
3.23. 真 理 維 持 シ ス テ ム
JBoss Rules 真理維持システム (T MS: T ruth Maintenance System) とは、信念とナレッジベースにあるそ
の信念に関する依存関係や正当化を表現する方法です。
重要
真理維持 (および論理アサーション) を機能させるには、Fact オブジェクトが equals と hashCode
メソッドを正しくオーバーライドする必要があります。真理維持システムは、2 つの違った物理オ
ブジェクトが等価であることを把握している必要があるため、Java 規格に従って、equals と
hashCode の両方を正しくオーバーライドする必要があります。
equals メソッドがそれぞれに true を返し、hashCode メソッドが同じ値を返す場合のみ、2 つの
オブジェクトは等価となります。equals と hashCode の両方をオーバーライドする必要がありま
す。
バグを報告する
3.24. insertLogical フ ァ ク ト
insertLogical ファクトは、JBoss Rules T MS の一部です。このファクトは、ルールが状況にあわせ
て機能して、変更されるように「論理を挿入」します。例えば、insertLogical ファクトはルールセッ
トに追加され、ルールが false になった場合自動的にそのファクトが削除されるようになっています。
バグを報告する
34
第3章 ユーザーガイド
3.25. 推 論 と TMS の 使 用
手順 3.7 タスク
1. この例では、バスの定期券発行のシステムを使用します。以下のコードスニペットを参照してくだ
さい。
rule "Issue Child Bus Pass" when
$p : Person( age < 16 )
then
insert(new ChildBusPass( $p ) );
end
rule "Issue Adult Bus Pass" when
$p : Person( age >= 16 )
then
insert(new AdultBusPass( $p ) );
end
2. 推論を含めるために、insertLogical プロパティを挿入します。
rule "Infer Child" when
$p : Person( age < 16 )
then
insertLogical( new IsChild( $p ) )
end
rule "Infer Adult" when
$p : Person( age >= 16 )
then
insertLogical( new IsAdult( $p ) )
end
3. コードを再度入力して定期券の発行を行います。T MS は、削除のカスケードセットができるように
論理挿入の連鎖に対応しているため、これらの 2 つの設定は論理的に挿入することができます。
rule "Issue Child Bus Pass" when
$p : Person( )
IsChild( person == $p )
then
insertLogical(new ChildBusPass( $p ) );
end
rule "Issue Adult Bus Pass" when
$p : Person( age >= 16 )
IsAdult( person =$p )
then
insertLogical(new AdultBusPass( $p ) );
end
その人の (年齢) が 15 から 16 に変わると、IsChild のファクトとその人の ChildBusPass の
ファクトの両方が自動的に削除されます。
4. オプションで、not の条件要素を挿入して通知の処理を行います (この例では定期券の返却依頼に
ついてです)。T MS が自動的に ChildBusPass オブジェクトを削除して、このルールがその人に
対する依頼をトリガーして送信します。
35
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
rule "Return ChildBusPass Request "when
$p : Person( )
not( ChildBusPass( person == $p ) )
then
requestChildBusPass( $p );
end
バグを報告する
36
第4章 決定表
第 4章 決定表
4.1. 決 定 表
決定表とは、条件論理を表現する手段の 1 つです。決定表は、ビジネスレベルのルールに非常に適してい
ます。
バグを報告する
4.2. ス プ レ ッ ド シ ー ト
JBoss Rules は、スプレッドシート形式でルールを管理します。対応の形式は、Excel (XLS) と CSV で
す。つまり、様々なスプレッドシートプログラム (Microsoft Excel、OpenOffice.org、Calc など) に対応し
ています。
バグを報告する
4.3. Open Office の 例
図 4 .1 Open Office のスクリーンショット
上記の例では、決定表の技術的な部分は (スプレッドシートの標準機能を使用して) 非表示にしています。
37
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ルールは行 17 から始まり、行はそれぞれルールとなります。条件は列 C、D、E などに設定し、アクショ
ンは今回は表示されていません。値の意味は、行 16 に記載されています (列 B は (条件ではなく) 単なる
説明となっています)。
注記
決定表は上から順番に処理しているように見えますが、必ずしもそうであるとは限りません。ルー
ルは行の順番など関係なしに作成するのが理想的です。こうすることで、常に行を移動させる必要
がないため、メンテナンスが簡単になります。
バグを報告する
4.4. ル ー ル と ス プ レ ッ ド シ ー ト
行に挿入されるルール
各行はルールであるため、記述したコードと同じ原則が適用されます。このルールエンジンは
ファクトを処理するため、合致するルールはすべて発火されます。
アジェンダ
ルールが発火され、非常に単純な決定表 (最初に合致したもののみがアクションを引き起こすも
の) をシミュレートするとアジェンダが削除されます。
複数の表
1 つのスプレッドシートに複数のテーブルを含めることができます。こうすることで、共通のテ
ンプレートを共有するルールをグループ化することができます。ただ、これらのルールはすべ
て、依然として 1 つのルールパッケージに組み込まれています。
バグを報告する
4.5. RuleTable の キ ー ワ ー ド
決定表を使用すると、スプレッドシートはルール表の開始地点を示す RuleTable キーワードを検索します
(開始する行と列の両方)。
重要
キーワードはすべて同じ列に含まれている必要があります。
バグを報告する
4.6. RuleSet キ ー ワ ー ド
RuleSet キーワードは、全ルールを含むルールパッケージで使用する名前を指します。デフォルトでは、
名前はオプションですが、すぐ右のセルに RuleSet キーワードを設定する必要があります。
バグを報告する
38
第4章 決定表
4.7. ル ー ル テ ン プ レ ー ト の 例
図 4 .2 ルールテンプレート
RuleSet キーワードは、全ルールを含むルールパッケージで使用する名前を指します。デフォルトで
は、名前はオプションですが、すぐ右のセルに RuleSet キーワードを設定する必要があります。C 列
に表示されているその他のキーワードは import と Sequential です。
RuleT able キーワードの後には名前が来ますが、この名前は生成されるルールの名前の接頭辞として
使用されます。ルール名が必ず一意の名前となるように、行の番号が追加されます。
RuleT able の行は、ルールの開始する行を指します。左側の行は無視されます。
行番号 14 (RuleT able 直後の行) を見てみると、キーワード CONDIT ION と ACT ION は、下の列の
データがルールの LHS 部分または RHS 部分のいずれかに対するものであることが分かります。この
ようにオプションとしても設定できる他の属性もルールには存在しています。
行番号 15 には、ObjectTypes の宣言が含まれます。この行の内容はオプションですが、このオプショ
ンが使用されてない場合、行は空白のままにする必要があります。この行を使用する場合、下のセル
(行番号 16) の値はそのオブジェクトタイプに対する制約となります。上記の場合
は、Person(age=="4 2") と Cheese(type=="stilton") (42 と stilton は行番号 18 から来てい
ます) が生成されます。上記の例では、"==" は暗黙的です。フィールド名だけが指定されている場合
は、完全一致を生成するように、トランスレーターは推測します。
行番号 16 にはルールテンプレート自体が含まれています。"$param" プレースホルダーを使用して、
下のセルからのデータを補間すべき場所を指定することができます (挿入が複数ある場合は "$1"、
"$2" などを使用し、下のセルのコンマ区切りの一覧からパラメーターを指定します)。行番号 17 は無
視されますが、ここには列の目的に関する説明が記載されている場合があります)。
行番号 18 と 19 はデータを表示します。このデータは、行番号 15 のテンプレートと統合 (補間) さ
れ、ルールを生成します。セルにデータが含まれていない場合、そのテンプレートは無視されます (つ
まり、条件やアクションによってはそのルールの行に該当しないものもあるということです)。ルール
の行は、空白の行に到達するまで、読み込まれます。シート内に複数の RuleT ables を設置することも
可能です。
行番号 20 には別のキーワードや値が含まれます。このように、キーワードの行の位置は関係ありませ
ん (大抵の場合は一番上に設定します)。ただし、その列に関しては、RuleT able または RuleSet の
キーワードが表示される箇所と同じものでなければなりません。ここでは、列番号 C が選択されてい
ますが、他の列を使用することもできます。
39
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
注記
ObjectT ype 宣言は (マージされたセルを使用して) 複数の列をつなげることができます。つまり、
同じ ObjectT ype がマージされていないセルに含まれているものの、最終的に別種/同種のファク
トと一部合致するといった別のパターンが出来上がるのではなく、マージされた範囲のすぐ下にあ
る列はすべて、制約セットとして、毎回 1 つのファクトと合致する単一パターンに統合されます。
上記の例では、ルールは以下のようにレンダリングされます ("ObjectT ype" 行を使用)。
//row 18
rule "Cheese_fans_18"
when
Person(age=="42")
Cheese(type=="stilton")
then
list.add("Old man stilton");
end
注記
上記のセルの該当の ObjectT ype に追加するには、age=="4 2" と type=="stilton" の制約は
1 つの制約と解釈されます。上記のセルがつながっている場合、1 つの「列」に複数の制約が存在
することになります。
警告
非常に大きな決定表は、メモリ要件が非常に高くなる可能性があります。
バグを報告する
4.8. デ ー タ 定 義 セ ル
DRL ファイルを生成するために使用する長方形のエリアデータ定義には 2 種類あります。1 つは
RuleSet と呼ばれるセルで、ルール以外の DRL アイテムをすべて定義します。もう 1 つは反復して発生
して、RuleT able で始まるコンテンツのセルの右および下にあります。これらのエリアは実際の決定表
を表しており、各エリアは同様の構造を持つルールを含みます。
RuleSet のエリアにはセルのペアを含めることができ、1 つは RuleSet セルの下にあり、このセルには
もう片方のセル (同じ列で次に来るセル) に含まれる値の種類を指定するキーワードが含まれています。
バグを報告する
4.9. ル ー ル テ ー ブ ル の 列
ルールテーブルエリアの列は、ルールの左側にあるパターンと制約、ルール結果に対するアクション、個
別のルール属性の値を定義します。ルールテーブルエリアには、列 1 つ以上、条件とアクション両方、
ルール属性に対する任意の選択肢、それぞれに対して最大 1 つの列を含める必要がありま
す。RuleT able というセルの行の後にくる最初の 4 つの行は、ヘッダーエリアとして割り当てられ、多
40
第4章 決定表
くの場合ルール構築のためのコード定義に使用されます。この 4 つのヘッダー行の下に追加された行で別
のルールを生成し、そのデータを使用してルールテーブルヘッダーで定義されているコードのバリエー
ションを提供します。
注記
キーワードはすべて大文字と小文字の区別をします。
最初のワークシートのみが決定表用に検証されます。
バグを報告する
4.10. ル ー ル セ ッ ト の エ ン ト リ
ルールセットエリアのエントリは、DRL コンストラクト (ルール以外) を定義して、ルール属性を指定す
ることができます。コンストラクトのエントリは繰返し使用して、各ルール属性は最大 1 回指定でき、
ルールテーブルエリアで定義された同じ属性により却下されない限りすべてのルールに適用されます。
エントリは、セルのペアを縦に積み上げた順番に指定する必要があります。最初のものにキーワードが、
その右側のものに値が含まれます。セルのペアのこの順番は、RuleSet でマークがついた行がキーワー
ドを含むものである限り、空の行またはルールテーブルにより中断可能です。
バグを報告する
4.11. ル ー ル セ ッ ト エ リ ア の エ ン ト リ
41
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 4 .1 ルールセットエリアのエントリ
キーワード
値
使用法
RuleSet
生成 DRL ファイルのパッケージ
名。オプション。デフォルトは
rule_table
最初のエントリでなければなり
ません。
Sequential
T rue または False。T rue の場
合、Salience (優先順位) を使用
してルールが上から下へ順番に
発火されるようにします。
オプション。最大 1 回。省略さ
れると、発火順が課されます。
EscapeQuotes
T rue または False。T rue の場
合、引用符はエスケープされ、
DRL にそのまま表示されるよう
にします。
オプション。最大 1 回。省略す
ると、引用符はエスケープされ
ます。
Import
インポートする Java クラスのコ
ンマ区切りの一覧
オプション。繰り返し可能
Variables
DRL global の宣言。変数名の後
にくる型のこと。複数のグロー
バル定義はコンマで区切る必要
があります。
オプション。繰り返し可能
Functions
DRL 構文に沿った 1 つまたは複
数の関数定義
オプション。繰り返し可能
Queries
DRL 構文に沿った 1 つまたは複
数の定義
オプション。繰り返し可能
Declare
DRL 構文に沿った 1 つまたは複
数の宣言型
オプション。繰り返し可能
バグを報告する
4.12. ル ー ル セ ッ ト エ リ ア の ル ー ル 属 性 エ ン ト リ
42
第4章 決定表
表 4 .2 ルールセットエリアのルール属性エントリ
キーワード
イニシャル
値
PRIORIT Y
P
ルールの "salience" 値を定義す
る整数。"sequential" フラグで
オーバーライドされます。
DURAT ION
D
ルールの "duration" の値を定義
する long 整数値
T IMER
T
タイマーの定義。"タイマーおよ
びカレンダー"を参照してくださ
い。
CALENDARS
E
カレンダーの定義。"タイマーお
よびカレンダー"を参照してくだ
さい。
NO-LOOP
U
ブール値。"true" は、返された
結果により変更が加えられたこ
とで発生するルールのループを
防止します。
LOCK-ON-ACT IVE
L
ブール値。"true" は同じルール
フローやアジェンダグループ内
にこのフラグを設定して、ルー
ルすべてを追加でアクティブ化
しないようにします。
AUT O-FOCUS
F
ブール値。アジェンダグループ
内のルールに"true" を設定する
と、ルールをアクティブ化し
て、自動的にこのグループに
フォーカスが当たるようにしま
す。
ACT IVAT ION-GROUP
X
アクティベーション (または
XOR) グループを特定する文字
列。アクティベーショングルー
プ内のルール 1 つのみが発火さ
れます。最初に発火したルール
により、同じグループ内の他の
ルールですでにアクティブ化さ
れているものがすべてキャンセ
ルされます。
AGENDA-GROUP
G
アジェンダグループを特定する
文字列。このアジェンダグルー
プはフォーカスを当てることで
アクティブ化する必要があり、
ルールのグループ間のフローを
制御する 1 つの方法です。
RULEFLOW-GROUP
R
ルールフローグループを特定す
る文字列
バグを報告する
4.13. RuleTable の セ ル
43
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ルールテーブルはすべて、"RuleT able"が含まれているセルから開始され、オプションでその後に同じセ
ル内の文字列が続きます。この文字列は、このルールテーブルから由来のすべてのルールに対する名前の
最初の部分として使用されます (このように自動的に指定された名前は、NAME 列を使用して上書きする
ことができます)。このルールテーブルのルールを定義するその他のセルはすべて、このセルの下または右
側に来ることになります。
バグを報告する
4.14. 列 タ イ プ
RuleT able セルの次の行は、列タイプを定義します。各列は、条件または結果の一部となるか、ルール属
性、ルール名またはコメントを提供します。各属性列は、1 回まで使用することができます。
バグを報告する
4.15. ル ー ル テ ー ブ ル の 列 ヘ ッ ダ ー
表 4 .3 ルールテーブルの列ヘッダー
キーワード
イニシャル
Value
使用法
NAME
N
その行から生成された
ルールの名前を提供し
ます。デフォルトは、
RuleT able タグと行番
号の後にくるテキスト
から構築されます。
最大 1 列
DESCRIPT ION
I
生成されたルール内の
コメントとなるテキス
ト。
最大 1 列
CONDIT ION
C
条件内のパターンにあ
る制約を構築するため
のコードスニペットお
よび補間値
ルールテーブルごとに
少なくとも 1 つ
ACT ION
A
ルールの結果に対する
アクションを構築する
ためのコードスニペッ
トおよび補間値
ルールテーブルごとに
少なくとも 1 つ
MET ADAT A
@
ルールに対するメタ
データエントリを構築
するためのコードスニ
ペットおよび補間値
オプション。列いくつ
でも OK
バグを報告する
4.16. 条 件 の 要 素
CONDIT ION とのヘッダーがついた列の場合、その後の行にあるセルは条件要素となります。
CONDIT ION の下の最初のセルにあるテキストは、次の行のスニペットが制約となり、ルール条件のパ
ターンへと発展します。セルが周辺のセル 1 つまたは複数とマージされると、複数の制約を持つ 1 つ
のパターンが形成されます。すべての制約は括弧のリストとなり、このセルのテキストに追加されま
44
第4章 決定表
す。セルは空の状態でも問題ありません。空の場合、次の行のコードスニペットはそれだけで有効な
条件要素になります。
制約なしのパターンを含めるには、テキストの前にパターンを記述して別のパターンを作成します。
パターンは、空の括弧ペアの有無に拘らず記述可能です。'from' 句はこのパターンに追加することがで
きます。
パターンが 'eval' で終わる場合、コードスニペットは 'eval' の後の括弧ペアに含めるようにブール値の
式を生成するはずです。
CONDIT ION 配下で 2 番目にくるテキストは、2 段階の手順で処理されます。
1. このセルのコードスニペットは、その列のさらに下にあるセルからの値を補間することで変更し
ます。下のセルからの値と "==" を使用して比較を含む制約を作成する場合、フィールドセレク
ターだけで十分です。それ以外の比較演算子は、スニペット内の最後のアイテムとして指定する
必要があり、下のセルからの値は追加されます。その他すべての制約フォームについて
は、$param のシンボルでセルの内容を含めるために位置を印付けする必要がありま
す。$1、$2 などのシンボルを使用し、下のセルで値をコンマで区切ってリストすることで、複
数の挿入も可能です。
パターン forall(delimiter){snippet} に従ったテキストは、配下のセルにあるコンマ区切りの
値それぞれに対して 1 回ずつ スニペットを繰り返して (この際、$ シンボルの場所に値を挿入し
ます)、指定の区切り文字でこれらの拡張を結合することで拡張されます。forall コンストラクト
は、他のテキストで囲むことができます。
2. 前の行にあるセルが空でない場合、完全なコードスニペットがそのセルから条件要素に追加され
ます。括弧のペアと、(複数の制約がマージされたセルのパターンに追加されている場合) 区切り
コンマが自動的に提供されます。
上のセルが空の場合、補間結果がそのまま使用されます。
CONDIT ION の 3 つ下のセルのテキストは、例示のみを目的として提示されています。人が解読でき
るように列の目的を指定するために使用されます。
4 行目以降は、空でないエントリは上記の通り、補間データとして提供されます。空のセルは、この
ルールの制約や条件要素を省略することになります。
バグを報告する
4.17. Action ス テ ー ト メ ン ト
ACT ION とのヘッダーがついた列の場合、その後の行にあるセルは Action 要素となります。
ACT ION の 1 つ下のセルにあるテキストはオプションです。テキストがある場合、オブジェクト参照
して解釈されます。
ACT ION 配下で 2 番目にくるテキストは、2 段階の手順で処理されます。
1. このセルのコードスニペットは、その列のさらに下にあるセルからの値を補間することで変更し
ます。挿入が 1 つの場合、$param のシンボルでセルの内容を含めるために位置を印付けしま
す。$1、$2 などのシンボルを使用し下のセルで値をコンマで区切ってリストすることで、複数
の挿入も可能です。
マーカーシンボルのないテキストを使うことで、補間なしでメソッドを呼び出すことができま
す。この場合、配下の行に空でないエントリを使用してステートメントを含めます。
Forall コンストラクトはこちらでも使用できます。
2. 最初のセルが空でない場合、テキスト、その後に来るピリオド、2 番目のセルのテキスト、終わ
りを示すセミコロンが 1 列に並べられ、メソッドを呼び出して Action ステートメントとして結
果に追加されます。
上のセルが空の場合、補間結果がそのまま使用されます。
ACT ION の 3 つ下のセルのテキストは、例示のみを目的として提示されています。人が解読できるよ
45
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
うに列の目的を指定するために使用されます。
4 行目以降は、空でないエントリは上記の通り、補間データとして提供されます。空のセルは、この
ルールの Action ステートメントを省略することになります。
注記
置き換えテキストにコンマが含まれている場合、$param の代わりに $1 を使用できません。
バグを報告する
4.18. Metadata ス テ ー ト メ ン ト
MET ADAT A とのヘッダーがついた列の場合、その後の行にあるセルは生成ルールに対するメタデータの
アノテーションとなります。
MET ADAT A の 1 つ下のセルにあるテキストは無視されます。
MET ADAT A の 2 つ下にあるセルのテキストはルールの行のセルからの値を使用しますが、上記の通
り補間により左右されます。メタデータマーカー文字 @ は自動的に接頭辞として追加され、このセル
のテキストとして含めるべきではありません。
MET ADAT A の 3 つ下のセルのテキストは、例示のみを目的として提示されています。人が解読でき
るかたちで列の目的を指定するために使用されます。
4 行目以降は、空でないエントリは上記の通り、補間データとして提供されます。空のセルは、この
ルールのメタデータのアノテーションを省略することになります。
バグを報告する
4.19. セ ル デ ー タ 補 間 の 例
テンプレートが Foo(bar == $param ) でセルが 4 2 の場合、結果は Foo(bar == 4 2) となりま
す。
テンプレートが Foo(bar < $1, baz == $2) でセルに 4 2,4 3 が含まれる場合、結果は
Foo(bar < 4 2, baz ==4 3) になります。
テンプレートが forall(& & ){bar != $} でセルに 4 2,4 3 が含まれる場合、bar != 4 2 & &
bar != 4 3 との結果になります。
バグを報告する
4.20. セ ル 内 で の 作 業 す る 際 の ヒ ン ト
同じセル内に複数のパッケージ名がある場合、コンマで区切る必要があります。
型と変数名のペアはコンマで区切る必要があります。
関数は、DRL ファイルに表示されるとおりに記述して、"RuleSet" キーワードと同じ列に表示する必
要があります。関数は、全ルールの行の上部、真ん中、または下部に設定することができます。
複数の定義を 1 つのセルにパッキングするのではなく、Import、Variables、Functions、Queries を繰
り返して使用することができます。
末尾の挿入マーカーは省略可能です。
バインディング変数を定義することができます。
46
第4章 決定表
オブジェクト型の行に何でも設定することができます。バインディング変数の定義以外は、リテラル
に挿入するための追加パターンとすることも可能です。
ACT ION ヘッダーの下にあるセルは空のままでも結構です。このスタイルを使用すると、メソッド呼
び出し 1 つだけでなく、何でも結果に使用できます (同じ手法を CONDIT ION 列でも適用できます)。
バグを報告する
4.21. SpreadsheetCompiler ク ラ ス
SpreadsheetCom piler クラスは、drools-decisiontables モジュールの API スプレッドシートベース
の決定表で使用する主なクラスです。このクラスは、様々な形式でスプレッドシートを使用して DRL で
ルールを生成します。
SpreadsheetCom piler を使用して部分的なルールファイルを生成して、ファクトの後に完全なルール
パッケージをアセンブルすることができます。こうすることで、必要に応じて技術的なものとそうでない
ものを分けることができます。
バグを報告する
4.22. ス プ レ ッ ド シ ー ト ベ ー ス の 決 定 表 の 使 用
手順 4 .1 タスク
1. ベースとして使用可能なサンプルのスプレッドシートを生成します。
2. Rule Workbench IDE プラグインを使用する場合、ウィザードを使用してテンプレートからスプ
レッドシートを生成します。
3. XSL 互換のスプレッドシートエディターを使用して XSL を変更します。
バグを報告する
4.23. Lists
Excel では、値の lists を作成できます。これらの Lists は他のワークシートに保存して、セルに対して
有効な値のリストを提供することができます。
バグを報告する
4.24. 改 訂 管 理
ルールに変更が加えられると、より古いバージョンはアーカイブされます。JBoss Rules のアプリケー
ションによっては、履歴変更を保存する機能に制限があるものありますが、別の改訂管理の手段を使用す
るよう推奨しています。
バグを報告する
4.25. 表 形 式 の デ ー タ ソ ー ス
テーブル形式のデータソースは、ルールデータのソースとして使用することができ、また多数のルールを
生成するためのテンプレートを作成することができます。これにより、スプレッドシートや既存のデータ
ベースのルールなどをさらに柔軟にすることができます (テンプレートを先に開発することでルールを生
成)。
47
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
バグを報告する
4.26. ル ー ル テ ン プ レ ー ト の 機 能
ルールテンプレートを使用すると、データをルールと分離することができ、ルールのどの部分がデータ駆
動型なのかといった制約がなくなります。そのため、決定表の機能をすべて利用することもできますが、
以下も可能になります。
データベース (やその他の形式) へデータを格納すること
データの値を元にルールを条件付きで作成すること
ルールのあらゆる部分のデータを使用すること (例:条件演算子、クラス名、プロパティ名)
同じデータに対して違ったテンプレートを実行すること
バグを報告する
4.27. ル ー ル テ ン プ レ ー ト の 例
以下は、ルールテンプレートがどのように使用されているか示しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template header
age
type
log
package org.drools.examples.templates;
global java.util.List list;
template "employees"
rule "Current employee_@{row.rowNumber}"
when
Name(location == @{location})
role(type == "@{type}")
then
list.add("@{log}");
end
end template
上記の例がどのようなもので構成されているか、以下に示しています。
行 1: テンプレートはすべて tem plate header で開始されます。
行 2-4: ヘッダーの後は列のリストで、データに表示される順番に並んでいます。この場合、最初の列
location、2 番目の列 type、3 番目の列 log を呼び出しています。
行 5: 空の行は列の定義の終わりを指定します。
行 6-9: 標準のルールヘッダーテキスト。これは、標準のルール DRL で生成した DRL の一番上に表示
されます。パッケージステートメント、import、global、function の定義をこの部分に挿入します。
行 10: キーワード tem plate はルールテンプレートの最初であるとのシグナルをだします。テンプ
レートファイルに 1 つ以上のテンプレートがある場合もありますが、各テンプレートは一意の名前を
持っています。
行 11-18: ルールテンプレート
行 20: キーワード end tem plate はテンプレートの最後を指定します。
48
第4章 決定表
以下のテンプレート例は、以下のルールを生成します。
package org.drools.examples.templates;
global java.util.List list;
rule "Current employee_1"
when
Person(location == Melbourne)
role(type == "receptionist")
then
list.add("melbourne admin");
end
rule "Current employee_2"
when
Person(location == Sydney)
Cheese(type == "recruiter")
then
list.add("sydney HR");
end
バグを報告する
4.28. ル ー ル テ ン プ レ ー ト の 実 行
手順 4 .2 タスク
このコードを実行してルールテンプレートを実行します。
DecisionTableConfiguration dtableconfiguration =
KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtableconfiguration.setInputType( DecisionTableInputType.XLS );
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClassPathResource( getSpreadsheetName(),
getClass() ),
ResourceType.DTABLE,
dtableconfiguration );
バグを報告する
4.29. Changeset の 展 開 例
以下の例は、http URL のロケーションからルールを、クラスパスから Excel の決定表をrロードするため
に展開されています。
49
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd
http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/droolsapi/src/main/resources/change-set-1.0.0.xsd' ><add><resource
source='http:org/domain/myrules.drl' type='DRL' /><resource
source='classpath:data/IntegrationExampleTest.xls' type="DTABLE"><decisiontableconf input-type="XLS" worksheet-name="Tables_2" /></resource></add></change-set>
バグを報告する
4.30. Changeset お よ び デ ィ レ ク ト リ の 例
コンテンツを入れるためのディレクトリを指定することができます。ファイル名拡張から型を推測できな
いため、すべてのファイルは指定の型でなければなりません。
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd
http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/droolsapi/src/main/resources/change-set-1.0.0.xsd' ><add><resource
source='file://myfolder/' type='DRL' /></add></change-set>
バグを報告する
4.31. ナ レ ッ ジ エ ー ジ ェ ン ト
ナレッジエージェントは自動ロード、リソースのキャッシュ、リロードを行い、ナレッジベースのプロパ
ティファイルから設定します。エージェントは、使用するリソースに変更があると、ナレッジエージェン
トがナレッジベースを更新または再構築します。これの戦略は、ファクトリで指定した設定により決定さ
れますが、通常は標準のポーリングを使用したプルベースとなっています。
バグを報告する
4.32. ナ レ ッ ジ エ ー ジ ェ ン ト の 例
以下は、ナレッジエージェントがどのように使用されているかを示しています。
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "MyAgent" );
kagent.applyChangeSet( ResourceFactory.newUrlResource( url ) );
KnowledgeBase kbase = kagent.getKnowledgeBase();
バグを報告する
50
第4章 決定表
4.33. KnowledgeAgent オ ブ ジ ェ ク ト
KnowledgeAgent オブジェクトは、60 秒の間隔というデフォルトのポーリングを使用してすべてのリ
ソースを継続的にスキャンします。変更日が更新されると、新しいリソースを使用してキャッシュされた
ナレッジベースに変更を適用します。以前の KnowledgeBase の参照はまだ存在しており、新しく構築
された KnowledgeBase にアクセスするには getKnowledgeBase() を呼び出す必要があります。ディ
レクトリが変更セットの一部として指定された場合、ディレクトリの全コンテンツをスキャンして変更が
ないか確かめます。変更の適用方法は、エージェントに渡される KnowledgeAgentConfiguration オブジェ
クトの中の drools.agent.newInstance プロパティにより左右されます。
バグを報告する
4.34. ポ ー リ ン グ サ ー ビ ス の 開 始
手順 4 .3 タスク
ポーリングを行うにはポーリングサービスと通知サービスを開始する必要があります。以下のコード
を使用します。
ResourceFactory.getResourceChangeNotifierService().start();
ResourceFactory.getResourceChangeScannerService().start();
バグを報告する
4.35. KnowledgeBuilder 向 け の カ ス タ ム の Classloader
手順 4 .4 タスク
1. KnowledgeBuilderConfiguration を開き、カスタムのクラスローダーを指定します。
2. カスタム設定をこれらのコンパイラーに渡す必要がある場合、 KnowledgeBuilderConfiguration オ
ブジェクトを KnowledgeAgentFactory.newKnowledgeAgent() に送ります。
バグを報告する
4.36. KnowledgeBase ClassLoader の 再 利 用
多くの場合、ルールを実行できるように、リモートリソースのコンパイルプロセスで使用するクラスロー
ダーは、ナレッジエージェントの kbase で必要なものと同じとなっています。
この手法を使用する場合、希望の ClassLoader をエージェント kbase に設定して、
KnowledgeAgentConfiguration オブジェクトの
drools.agent.useKBaseClassLoaderForCom piling プロパティを使用する必要があります。
この手法では、エージェントの kbase が使用するクラスローダーを変更することで、エージェントの
kbuilder classloader をランタイム時に変更することができます。これは、Changeset の漸増処理を使用
しない場合も機能します。kbase が再作成されると、その設定が再利用されクラスローダーは保持されま
す。
バグを報告する
4.37. KnowledgeAgentConfiguration の 例
以下は、KnowledgeAgentConfiguration プロパティの例です。
51
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
KnowledgeBaseConfiguration kbaseConfig =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null, customClassLoader);
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(kbaseConfig); //kbase with custom
classloader
KnowledgeAgentConfiguration aconf =
KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty("drools.agent.newInstance", "false"); //incremental change set
processing enabled
aconf.setProperty("drools.agent.useKBaseClassLoaderForCompiling", "true");
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
"test agent", kbase, aconf);
バグを報告する
4.38. newInstance プ ロ パ テ ィ
newInstance プロパティは、変更セットの処理をサポートします。
ナレッジエージェントは、1) 新しい変更セットが処理されるたびにナレッジベースを再作成するか、2)
キャッシュされたナレッジベースを壊すことなく変更セットに適用するかの 2 種類の方法で、変更セット
を処理することができます。この動作は、Agent のコンストラクターに渡される際は
KnowedgeAgentConfiguration オブジェクトの newInstance プロパティで制御されます。
バグを報告する
4.39. newInstance プ ロ パ テ ィ の 使 用
newInstance が true (デフォルト値) に設定されている場合、エージェントはエージェント内のキャッシュ
ナレッジベースを破棄し、Change set の変更を含む新しいものを作成します。newInstance が false に設
定されている場合、Change set は直接キャッシュされたナレッジベースに適用されます。Change set の
リソースで変更されなかったルールは、ナレッジベースで置き換えられず、変更または削除されたルール
がキャッシュナレッジベースから変更または削除されます。Functions、Queries、Definition 型は、変更
の有無に拘らず常にキャッシュナレッジベースで置き換えられます。
バグを報告する
4.40. newInstance の 例
以下のコードスニペットは、newInstance プロパティを false に設定して、新しいナレッジエージェント
を作成します。
KnowledgeAgentConfiguration aconf =
KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty("drools.agent.newInstance", "false");
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent("test agent", null,
aconf);
バグを報告する
4.41. リ モ ー ト の HTTP リ ソ ー ス キ ャ ッ シ ュ
ナレッジエージェントは、http(s) URL からリソースをリモートから「プル」することができます。
52
第4章 決定表
バグを報告する
4.42. 再 起 動 後 の リ ソ ー ス キ ャ ッ シ ュ の リ ス ト ア
手順 4 .5 タスク
リソースがリモートですでに利用できなくなっている場合 (例:リモートのサーバーが再起動された場
合) に再起動に耐えるようにするには、システムプロパティ drools.resource.urlcache を設定
します (アプリケーションの書き込み権限があるディレクトリに設定するようにしてください)。ナ
レッジエージェントは、そのディレクトリ内にリモートリソースのコピーをキャッシュします。
例えば、java コマンドライン Ddrools.resource.urlcache=/users/som eone/KnowledgeCache を使用すると、再起動さ
れてもエージェントが使用できるように、リソースのローカルコピー (ルール、パッケージなど) をそ
のディレクトリに保存します (リモートのリソースが利用できるようになり、更新されると、自動的に
ローカルのキャッシュコピーを更新されます)。
バグを報告する
53
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 5章 処理
5.1. ア ジ ェ ン ダ
アジェンダは Rete 機能です。WorkingMem ory のアクション中に、ルールが完全合致して実行できるよ
うになる場合があります。ワーキングメモリのアクション 1 つで、複数のルールが実行できるようになる
可能性があります。ルールが完全合致すると、アクティベーションが作成され、ルールと合致ファクトを
参照して、アジェンダに設定します。アジェンダは、競合解消戦略を使用して、これらのアクティベー
ションの実行の順番を管理します。
バグを報告する
5.2. ア ジ ェ ン ダ の 処 理
エンジンは、以下の 2 つのフェーズのサイクルを繰り返します。
1. ワーキングメモリアクション。これは、Consequence (RHS 自体) か 主な Java アプリケーション
のプロセスなど、作業が実行される場所です。Consequence が終了するか、主要なアプリケー
ションプロセスが fireAllRules() を呼び出すと、エンジンはアジェンダ評価フェースに切り替
えられます。
2. アジェンダ評価。これは、発火するルールの選択を試みます。ルールが見つからなかった場合、そ
のまま存在して、見つかった場合はそのルールを発火し、このフェーズを再度ワーキングメモリア
クションに切り替えます。
このプロセスは、アジェンダがなくなるまで繰り返されます。アジェンダがなくなると、呼び出し中のア
プリケーションに制御が返されます。ワーキングメモリアクションが実行されている間は、ルールは発火
されません。
バグを報告する
5.3. デ フ ォ ル ト の 競 合 解 消 戦 略
Salience (優先順位 )
他のルールよりも特定のルールのほうが優先度が (大きい数字を割り当てます) 高いことを指定で
きます。この場合は、高い salience を持つルールが優先されます。
LIFO (Last In, First Out)
LIFO 優先順位は、割り当てられたワーキングメモリアクションのカウンター値をベースにしてい
ます。この際、同じアクションが同じ値を受け取ると作成されるルールをすべて使用します。同
じ優先順位を持つ発火セットの実行順は任意です。
注記
一般的なルールとして、特定の順番で発火されるルールに依存したり、フローを気にせずルールを
作成したりするのはよくありません。しかし、フローが必要な場合は、アジェンダグループ、ルー
ルフローグループ、アクティベーショングループ、コントロール/セマフォファクト (を含むがこれ
に限らない) などの可能性が多数存在します。この点については後のセクションで説明します。
54
第5章 処理
バグを報告する
5.4. AgendaGroup
アジェンダグループとは、アジェンダでルールを分割する方法です。「フォーカス」があるのは、1回に
1 つのグループのみになります。つまり、そのグループ内のルールに対してのみアクティベーションが有
効になります。また、「自動フォーカス」のルールを持たせることも可能です。これは、ルールの条件が
true の場合にそのアジェンダグループにフォーカスが当たるようになっています。
アジェンダグループは、CLIPS の用語では「モジュール」として知られています。アジェンダグループ
は、分類されたルールの間のフローを作成する方法を提供します。ルールエンジンや API を使用して、
フォーカスが当たっているグループを切り替えることができます。ルールに、複数のフェーズや処理の順
番が必要であるとはっきり分かっている場合は、この目的でアジェンダグループの使用を検討してくださ
い。
バグを報告する
5.5. setFocus()
setFocus() が呼び出されるたびに、指定のアジェンダグループをスタックにプッシュします。フォーカ
スグループが空の場合スタックから取り出され、一番上にあるフォーカスグループが評価されます。ア
ジェンダグループはスタックの複数の箇所で現れます。デフォルトのアジェンダグループは "MAIN" で、
アジェンダグループが指定されていないルールはすべてこのグループに入っています。また、このグルー
プは常にスタックの最初に来て、デフォルトで最初にフォーカスがあたっています。
バグを報告する
5.6. setFocus() の 例
以下は、setFocus()要素がどのように使用されているかを示しています。
ksession.getAgenda().getAgendaGroup( "Group A" ).setFocus();
バグを報告する
5.7. ActivationGroup
アクティベーショングループは、同じ "activation-group" ルール属性を持つルール同士をバインドした
セットのことです。このグループ内で 1 つのルールのみが発火でき、そのルールが発火されると、それ以
外のすべてのルールはアジェンダから取り消されます。発火の順番が来る前にすべてのアクティベーショ
ンを取り消す clear() メソッドは、いつでも呼び出すことができます。
バグを報告する
5.8. ActivationGroup の 例
以下は、ActivationGroup がどのように使用されているか示しています。
ksession.getAgenda().getActivationGroup( "Group B" ).clear();
バグを報告する
55
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
5.9. RuleFlowGroup
ルールフローグループは、"ruleflow-group" ルール属性に紐付けされたルールのグループです。これらの
ルールは、グループがアクティブな状態でないと発火できず、グループ自体は、グループを表すノードに
ruleflow の図が到達してからでなければアクティブにはなりません。ここでも、アジェンダに残っている
アクティベーションをすべてキャンセルするために、clear() メソッドをいつでも呼び出すことができ
ます。
バグを報告する
5.10. RuleFlowGroup の 例
これは、RuleFlowGroup プロパティがどのように使用されているかを示しています。
ksession.getAgenda().getRuleFlowGroup( "Group C" ).clear();
バグを報告する
5.11. ル ー ル と メ ソ ッ ド の 違 い
メソッドは直接呼び出される。
特定のインスタンスを渡す。
1 つの呼び出しで実行されるのは 1 つである。
ルールは、エンジンに挿入される限りデータを照合していき実行される。
ルールは直接呼び出すことができない。
特定のインスタンスがルールに渡されることはない。
一致内容に応じて、ルールは 1 回または複数回発火することができ、また全く発火しないこともでき
る。
バグを報告する
5.12. ク ロ ス プ ロ ダ ク ト の 例
以下で、制約のない火災報知機の状態のルールについて表示しています。
rule
when
$room : Room()
$sprinkler : Sprinkler()
then
System.out.println( "room:" + $room.getName() +
" sprinkler:" + $sprinkler.getRoom().getName() );
end
SQL の用語では、select * from Room , Sprinkler を実行しているのとよく似ており、Room
テーブルのすべての行は Sprinkler テーブルのすべての行と結合され、以下のような出力となります。
56
第5章 処理
room:office sprinkler:office
room:office sprinkler:kitchen
room:office sprinkler:livingroom
room:office sprinkler:bedroom
room:kitchen sprinkler:office
room:kitchen sprinkler:kitchen
room:kitchen sprinkler:livingroom
room:kitchen sprinkler:bedroom
room:livingroom sprinkler:office
room:livingroom sprinkler:kitchen
room:livingroom sprinkler:livingroom
room:livingroom sprinkler:bedroom
room:bedroom sprinkler:office
room:bedroom sprinkler:kitchen
room:bedroom sprinkler:livingroom
room:bedroom sprinkler:bedroom
このようなクロスプロダクトは大きくなり、擬似データを含む場合もあります。変数制約を使ってクロス
プロダクトに制約を加えて、このような状況を回避することができます。
rule
when
$room : Room()
$sprinkler : Sprinkler( room == $room )
then
System.out.println( "room:" + $room.getName() +
" sprinkler:" + $sprinkler.getRoom().getName() );
end
結果、Room ごとに正しい Sprinkler を持つ 4 行分のデータだけが残ります。SQL (実際は HQL) では、該
当のクエリは select * from Room , Sprinkler where Room == Sprinkler.room となりま
す。
room:office sprinkler:office
room:kitchen sprinkler:kitchen
room:livingroom sprinkler:livingroom
room:bedroom sprinkler:bedroom
バグを報告する
5.13. ア ク テ ィ ベ ー シ ョ ン 、 ア ジ ェ ン ダ 、 コ ン フ リ ク ト の 例
この例では、キャッシュフロー算出システムについて見ていきます。以下に、実装されたクラスを 3 つ示
しています。
57
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
public class CashFlow {
private Date
date;
private double amount;
private int
type;
long
accountNo;
// getter and setter methods here
}
public class Account {
private long
accountNo;
private double balance;
// getter and setter methods here
}
public AccountPeriod {
private Date start;
private Date end;
// getter and setter methods here
}
2 津のルールを使用してその四半期の貸方と借方判断して勘定残高を更新することができます。以下の 2
つのルールは、指定の期間アカウントのキャッシュフローに制約を加えます。ショートカット構文を使用
してフィールド名が 2 回繰り返されないようにする "&&" に注目してください。
rule "increase balance for credits"
when
ap : AccountPeriod()
acc : Account( $accountNo :
accountNo )
CashFlow( type == CREDIT,
accountNo == $accountNo,
date >= ap.start &&<=
ap.end,
$amount : amount )
then
acc.balance += $amount;
end
rule "decrease balance for debits"
when
ap : AccountPeriod()
acc : Account( $accountNo :
accountNo )
CashFlow( type == DEBIT,
accountNo == $accountNo,
date >= ap.start &&<=
ap.end,
$amount : amount )
then
acc.balance -= $amount;
end
AccountPeriod が最初の四半期に設定されている場合、"increase balance for credits" のルールに制約
を加えデータ 2 行に対して発火して、"decrease balance for debits" で、データ 1 行に対してアクション
を行います。
データは挿入段階で称号され、fireAllRules() が呼び出されてから発火されます。その間、ルールと
合致データはアジェンダに置かれ、アクティベーションとして参照されます。アジェンダは、
fireAllRules() が呼び出されてすぐに発火可能でその結果を実行できるアクティベーションテーブルです。
アジェンダのアクティベーションは順番に実行されます。これまでの実行の順番は任意となっている点に
注目してください。
上記のアクティベーションがすべて発火されると、勘定残高は -25 になります。
AccountPeriod が第 2 四半期に更新されると、合致データの行は 1 つになるため、アジェンダのアク
ティベーションも 1 つだけとなります。
アクティベーションを発火すると、残高は 25 になります。
バグを報告する
58
第5章 処理
5.14. 競 合 解 消 戦 略
アジェンダに 1 つ以上のアクティベーションがあることをコンフリクト状態と呼び、競合解消戦略を使用
して実行順位を決定します。最も簡単なのは、デフォルトの戦略が Salience を使用してルールの優先順位
を決定します。
バグを報告する
5.15. 競 合 解 消 戦 略 の 例
各ルールのデフォルト値は 0 で、値が高いと優先順位も高くなります。これを例示するために、勘定残高
の印刷をするためのルールを 1 つ追加します。目的は、ルールが借方、貸方すべてが全勘定に適用されて
からルールを実行することです。これは、マイナスの salience をこのルールに割り当て、salience がデ
フォルトの 0 となっている全ルールの後にこのルールが発火されるようにします。
rule "Print balance for AccountPeriod"
salience -50
when
ap : AccountPeriod()
acc : Account()
then
System.out.println( acc.accountNo + " : " + acc.balance );
end
バグを報告する
5.16. ト リ ガ ー の 例
表 5.1 トリガーの例
ルールビュー
ビューのトリガー
select * from Account acc,
Cashflow cf,
AccountPeriod ap
where acc.accountNo == cf.accountNo
and
cf.type == CREDIT and
cf.date >= ap.start and
cf.date <= ap.end
select * from Account acc,
Cashflow cf,
AccountPeriod ap
where acc.accountNo == cf.accountNo
and
cf.type == DEBIT and
cf.date >= ap.start and
cf.date <= ap.end
trigger : acc.balance += cf.amount
trigger : acc.balance -= cf.amount
バグを報告する
5.17. ruleflow-group の 例
ルールの ruleflow-group 属性の使用について以下に示しています。
59
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
rule "increase balance for credits"
ruleflow-group "calculation"
when
ap : AccountPeriod()
acc : Account( $accountNo : accountNo )
CashFlow( type == CREDIT,
accountNo == $accountNo,
date >= ap.start &&<= ap.end,
$amount : amount )
then
acc.balance += $amount;
end
rule "Print balance for AccountPeriod"
ruleflow-group "report"
when
ap : AccountPeriod()
acc : Account()
then
System.out.println( acc.accountNo +
" : " + acc.balance );
end
バグを報告する
5.18. 推 論 の 例
以下の例では、IsAdult プロパティを使用して、年齢を推測します。
rule "Infer Adult"
when
$p : Person( age >= 18 )
then
insert( new IsAdult( $p ) )
end
この推論関係は、どのルールでも利用できます。
$p : Person()
IsAdult( person == $p )
さらに、ナレッジプロセスを切り離すことで、データリークや第三者が情報を変更する機会を減らしま
す。
バグを報告する
5.19. 推 論 お よ び TruthMaintenance の 実 装
手順 5.1 タスク
1. ルールセットを開きます。この例では、バス定期券発行システムを使用します。
60
第5章 処理
rule "Issue Child Bus Pass" when
$p : Person( age < 16 )
then
insert(new ChildBusPass( $p ) );
end
rule "Issue Adult Bus Pass" when
$p : Person( age >= 16 )
then
insert(new AdultBusPass( $p ) );
end
2. insertLogical ファクトを挿入して、推論する用語を追加します。
rule "Infer Child" when
$p : Person( age < 16 )
then
insertLogical( new IsChild( $p ) )
end
rule "Infer Adult" when
$p : Person( age >= 16 )
then
insertLogical( new IsAdult( $p ) )
end
ファクトが論理的に挿入されました。このファクトは、When 句が true かどうかにより左右されま
す。つまり、ルールが false の場合、ファクトは自動的に削除されます。2 つのルールは相互排他
的であるため、これは特にうまく機能します。上記のルールでは、子供が 16 歳未満であると、
IsChild ファクトが挿入されます。その人が 16 歳以上になると自動的に削除され、IsAdult ファクト
が挿入されます。
3. 定期券を発行するコードを挿入します。これらは、T MS ではカスケードされた取り消しに対して論
理挿入の連鎖ができるため、論理的に挿入することもできます。
rule "Issue Child Bus Pass" when
$p : Person( )
IsChild( person == $p )
then
insertLogical(new ChildBusPass( $p ) );
end
rule "Issue Adult Bus Pass" when
$p : Person( age >= 16 )
IsAdult( person =$p )
then
insertLogical(new AdultBusPass( $p ) );
end
この人が 15 歳から 16 歳になると、IsChild ファクトが自動的に取り消されるだけでなく、
ChildBussPass ファクトも取り消されます。
4. 'not' 条件要素を挿入して通知を処理します (この場合、定期券返却の依頼)。T MS が自動的に
ChildBussPass オブジェクトを取り消すと、このルールがトリガーして、この人に依頼が送信され
ます。
61
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
rule "Return ChildBusPass Request "when
$p : Person( )
not( ChildBusPass( person == $p ) )
then
requestChildBusPass( $p );
end
バグを報告する
62
第6章 ルール言語
第 6章 ルール言語
6.1. KnowledgeBuilder
KnowledgeBuilder は、DRL ファイルや Excel ファイルなどのソースファイルを取得して、ナレッジベー
スが消費可能なルールやプロセス定義のナレッジパッケージに変換します。ResourceT ype クラスは、
ビルダーが処理するように依頼されたリソース型を示します。
バグを報告する
6.2. ResourceFactory
ResourceFactory には、java.io.Reader、classpath、URL、java.io.File やバイト配列などの複数のソー
スからリソースをロードする機能があります。決定表 (Excel の .xls ファイル) などのバイナリファイル
は、Reader で渡してはいけません。これは、テキストベースのテキストのみに適しています。
バグを報告する
6.3. 新 し い KnowledgeBuilder の 作 成
手順 6.1 タスク
1. KnowledgeBuilderFactory を開きます。
2. 新規のデフォルト設定を作成します。
3. 以下を設定に入力します。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
最初のパラメーターは任意でプロパティ用です。空白のままにすると、デフォルトオプションが使
用されます。オプションのパラメーターは、方言の変更や新規の accumulator 関数の登録などに使
用することができます。
4. カスタムの ClassLoader で KnowledgeBuilder を追加するには、以下のコードを使用します。
KnowledgeBuilderConfiguration kbuilderConf =
KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, classLoader );
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder(kbuilderConf);
バグを報告する
6.4. DRL リ ソ ー ス の 追 加
手順 6.2 タスク
1. 型のリソースは反復的に追加することができます。以下は、DRL ファイルを追加しています。ナ
レッジビルダーは、複数の名前空間を処理できるため、名前空間が何であってもリソースを組み合
わせることができます。
kbuilder.add( ResourceFactory.newFileResource( "/project/myrules.drl" ),
ResourceType.DRL);
2. リソールの追加のたびに、コンパイルの結果を確認します。KnowledgeBuilder は 3 種類の重要度
63
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
(ERROR、WARNING、INFO) とのコンパイル結果のレポートを出します。
ERROR は、リソースのコンパイルに失敗したことを指します。エラーがある場合、リソースの
追加や、ナレッジパッケージの取得をこれ以上行わないようにしてください。エラーがない場
合、getKnowledgePackages() は何も返しません。
WARNING および INFO の結果は無視しても構いませんが、検証用に提供されています。
バグを報告する
6.5. KnowledgeBuilder 結 果 の 確 認 方 法
KnowledgeBuilder API は、重要度一覧に関するビルドの結果を確認、取得するために複数のメソッドを提
供しています。
/**
* Return the knowledge builder results for the listed severities.
* @param severities
* @return
*/
KnowledgeBuilderResults getResults(ResultSeverity... severities);
/**
* Checks if the builder generated any results of the listed severities
* @param severities
* @return
*/
boolean hasResults(ResultSeverity... severities ;
KnowledgeBuilder API は、hasErrors() および getErrors() のエラーのみを確認する helper メソッ
ドが 2 つ含まれています。
if( kbuilder.hasErrors() ) {
System.out.println( kbuilder.getErrors() );
return;
}
バグを報告する
6.6. KnowledgePackages の 取 得
リソースがすべて追加され、エラーがない場合、ナレッジパッケージのコレクションを取得できます。
パッケージの名前空間ごとに KnowledgePackage が 1 つあるため、java.util.Collection となっています。
これらのナレッジパッケージは直列化可能で、デプロイメントの 1 ユニットとして使用されます。
以下は、KnowledgePakcage の取得の例をです。
Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
バグを報告する
6.7. KnowledgeBuilder の 展 開 例
以下は、KnowledgeBuilder のパッケージ全体例となります。
64
第6章 ルール言語
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
if( kbuilder.hasErrors() ) {
System.out.println( kbuilder.getErrors() );
return;
}
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newFileResource( "/project/myrules1.drl" ),
ResourceType.DRL);
kbuilder.add( ResourceFactory.newFileResource( "/project/myrules2.drl" ),
ResourceType.DRL);
if( kbuilder.hasErrors() ) {
System.out.println( kbuilder.getErrors() );
return;
}
Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
バグを報告する
6.8. バ ッ チ モ ー ド で の KnowledgeBuilder の 使 用
KnowledgeBuilder には、Fluent interfance (流れるようなインターフェース) を使用するバッチモードがあ
ります。KnowledgeBuilder は以下の例のように、1 度に複数の DRL を構築することができます。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.batch()
.add( ResourceFactory.newFileResource( "/project/myrules1.drl" ),
ResourceType.DRL )
.add( ResourceFactory.newFileResource( "/project/myrules2.drl" ),
ResourceType.DRL )
.add( ResourceFactory.newFileResource( "/project/mytypes1.drl" ),
ResourceType.DRL )
.build();
バグを報告する
6.9. 最 後 に 追 加 し た DRL ビ ル ド の 破 棄
KnowledgeBuilder (バッチモードの使用の有無に拘らず) を使って、最後の DRL ビルドで追加されたもの
を破棄することができます。これは、KnowledgeBuilder にエラーのある DRL ビルドを追加した状態から
リカバリします。以下の例を確認してください。
kbuilder.add( ResourceFactory.newFileResource( "/project/wrong.drl" ),
ResourceType.DRL );
if ( kbuilder.hasErrors() ) {
kbuilder.undo();
}
バグを報告する
6.10. 設 定 お よ び ChangeSet XML を 使 用 し た 構 築
ChangeSet XML 内の設定を使用して定義を作成します。単純な XML ファイルは add、remove、modify
65
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
の 3 つの要素をサポートします。これらはそれぞれ、設定エンティティを定義する <resource> サブ要素
の配列が含まれています。
バグを報告する
6.11. ChangeSet XML の XML ス キ ー マ (標 準 で は な い )
以下は、標準ではない ChangeSet のスキーマです。
66
第6章 ルール言語
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://drools.org/drools-5.0/change-set"
targetNamespace="http://drools.org/drools-5.0/change-set"><xs:element
name="change-set" type="ChangeSet"/><xs:complexType name="ChangeSet"><xs:choice
maxOccurs="unbounded"><xs:element name="add"
type="Operation"/><xs:element
name="remove" type="Operation"/><xs:element name="modify"
type="Operation"/></xs:choice></xs:complexType><xs:complexType
name="Operation"><xs:sequence><xs:element name="resource" type="Resource"
maxOccurs="unbounded"/></xs:sequence></xs:complexType><xs:complexType
name="Resource"><xs:sequence><!-- To be used with <resource type="DTABLE"...> -><xs:element name="decisiontable-conf" type="DecTabConf"
minOccurs="0"/></xs:sequence><!-- java.net.URL, plus "classpath"
protocol -->
<xs:attribute name="source" type="xs:string"/><xs:attribute name="type"
type="ResourceType"/></xs:complexType><xs:complexType
name="DecTabConf"><xs:attribute name="input-type"
type="DecTabInpType"/><xs:attribute name="worksheet-name" type="xs:string"
use="optional"/></xs:complexType><!-- according to
org.drools.builder.ResourceType --><xs:simpleType
name="ResourceType"><xs:restriction base="xs:string"><xs:enumeration
value="DRL"/><xs:enumeration value="XDRL"/><xs:enumeration
value="DSL"/><xs:enumeration value="DSLR"/><xs:enumeration
value="DRF"/><xs:enumeration value="DTABLE"/><xs:enumeration
value="PKG"/><xs:enumeration value="BRL"/><xs:enumeration
value="CHANGE_SET"/></xs:restriction></xs:simpleType><!-- according to
org.drools.builder.DecisionTableInputType --><xs:simpleType
name="DecTabInpType"><xs:restriction base="xs:string"><xs:enumeration
value="XLS"/><xs:enumeration
value="CSV"/></xs:restriction></xs:simpleType></xs:schema>
67
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
バグを報告する
68
第7章 ChangeSet
第 7章 ChangeSet
7.1. Changeset
changeset 機能により、API を使用しないナレッジベースの構築がスムーズに行えるようになります。
Changeset には、多数のリソースを含めることができ、追加の設定情報 (現在は決定表でのみ必要ですが)
もサポートすることが可能です。
changeset.xm l ファイルには、これに関するリソースの一覧が含まれています。このファイルから別の
changeset XML ファイルに再帰的に参照することも可能です。
バグを報告する
7.2. changeset の 例
プロトコルを指定するプリフィックスを使用するリソースのアプローチが採用されています。"file" や
"http"、追加の "classpath" などの java.net.URL で提供されているすべてのプロトコルに対応していま
す。型属性はファイル名の拡張から推測できないため,現在、リソース毎に必ず型属性を指定する必要が
あります。これについて、以下に例で示しています。
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set
http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/droolsapi/src/main/resources/change-set-1.0.0.xsd' ><add><resource
source='http:org/domain/myrules.drl' type='DRL' /></add></change-set>
上記の例は、リソース型を CHANGE_SET に変更して使用することができます。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClasspathResource( "myChangeSet.xml", getClass()
),
ResourceType.CHANGE_SET );
if ( kbuilder.hasErrors() ) {
System.err.println( builder.getErrors().toString() );
}
バグを報告する
7.3. ChangeSet XML の 例
以下は、基本的な ChangeSet XML スキーマの例です。
69
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd
http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/droolsapi/src/main/resources/change-set-1.0.0.xsd' ><add><resource
source='file:/project/myrules.drl' type='DRL' /></add></change-set>
バグを報告する
7.4. ChangeSet プ ロ ト コ ル
ChangeSet は、"file"、"http"、追加の "Classpath" など java.net.URL が提供する全プロトコルに対応して
います。型属性はファイル名の拡張から推測できないため、現在、リソース毎に必ず型属性を指定する必
要があります。
file: プレフィックスを使用して、リソースのプロトコルに意味をもたせます。
注記
XML スキーマを使用する場合、ChangeSet XML 自体が ClassPath リソースによりロードされない
限り、ナレッジビルダーが使用するクラスローダーにデフォルト設定されます。この場合、そのリ
ソースに対して指定されたクラスローダーを使用します。
バグを報告する
7.5. ChangeSet XML の ロ ー ド
手順 7.1 タスク
1. ChangeSet をロードするには API を使用します。
2. 以下のコードを使用して、ChangeSet XML にアクセスします。
kbuilder.add( ResourceFactory.newUrlResource( url ), ResourceType.CHANGE_SET
);
バグを報告する
7.6. リ ソ ー ス 設 定 を 持 つ ChangeSet XML の 例
以下の例は、お使いの ChangeSet にどのようにリソース設定を組み込むのかを提示しています。
70
第7章 ChangeSet
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd
http://anonsvn.jboss.org/repos/labs/labs/drools/trunk/droolsapi/src/main/resources/change-set-1.0.0.xsd' ><add><resource
source='http:org/domain/myrules.drl' type='DRL' /><resource
source='classpath:data/IntegrationExampleTest.xls' type="DTABLE"><decisiontableconf input-type="XLS" worksheet-name="Tables_2" /></resource></add></change-set>
バグを報告する
7.7. ChangeSet XML お よ び デ ィ レ ク ト リ
以下のコードは、ディレクトリのコンテンツを ChangeSet に追加することができます。
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd
http://anonsvn.jboss.org/repos/labs/labs/drools/trunk/droolsapi/src/main/resources/change-set-1.0.0.xsd' ><add><resource
source='file:/projects/myproject/myrules' type='DRL' /></add></change-set>
注記
現在、フォルダー内のリソースはすべて同じ型である必要があります。ナレッジエージェントを使
用している場合、追加、変更、削除されたリソースがないか継続的にスキャンして、キャッシュの
ナレッジベースを再構築します。
バグを報告する
71
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 8章 構築
8.1. ビ ル ド 結 果 の 重 要 度
ビルドテストの型が持つデフォルトの重要度を変更することができます。例えば、既存ルールで名前が重
複している新しいルールをパッケージに追加する場合などに便利です (この場合、デフォルトの動作は、
古いルールを新しいルールで置き換え、INFO としてレポートします)。デプロイメントによっては、ルー
ルの更新を避け、エラーとしてレポートしたほうがいい場合もあります。
バグを報告する
8.2. デ フ ォ ル ト の ビ ル ド 結 果 の 重 要 度 設 定
手順 8.1 タスク
1. システムプロパティまたは設定ファイルを使用して重要度を設定するには、以下のプロパティを挿
入します。
// sets the severity of rule updates
drools.kbuilder.severity.duplicateRule = <INFO|WARNING|ERROR>
// sets the severity of function updates
drools.kbuilder.severity.duplicateFunction = <INFO|WARNING|ERROR>
2. API を使用して重要度を変更するには、以下のコードを使用します。
KnowledgeBuilderConfiguration kbconf = ...
// sets the severity of rule updates to error
kbconf.setOption( KBuilderSeverityOption.get(
"drools.kbuilder.severity.duplicateRule", ResultSeverity.ERROR ) );
// sets the severity of function updates to error
kbconf.setOption( KBuilderSeverityOption.get(
"drools.kbuilder.severity.duplicateFunction", ResultSeverity.ERROR ) );
バグを報告する
8.3. KnowledgePackage
ナレッジパッケージは、ルールやプロセスなどナレッジ定義の集まりです。ナレッジビルダーによりナ
レッジパッケージは作成されます。ナレッジパッケージは、埋め込み型で直列化可能です。現在、この
パッケージにより基本的なデプロイメントユニットを形成します。
注記
ナレッジパッケージインスタンスは、ナレッジベースに追加した後は再利用できません。別のナ
レッジベースにインスタンスを追加する必要がある場合、直列化して「クローン作成した」結果を
使用します。
バグを報告する
72
第8章 構築
8.4. 新 し い KnowledgeBase の 作 成
手順 8.2 タスク
1. このデフォルト設定を使用して新しい KnowledgeBase を作成します。
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
2. カスタムのクラスローダーが KnowledgeBuilder で使用してデフォルトのクラスローダー以外
で型を解決する場合、KnowledgeBase に設定する必要があります。この手法
は、KnowledgeBuilder と同じで以下のようになります。
KnowledgeBaseConfiguration kbaseConf =
KnowledgeBaseFactory.createKnowledgeBaseConfiguration( null, cl );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( kbaseConf );
バグを報告する
8.5. イ ン プ ロ セ ス 構 築 お よ び デ プ ロ イ
プロセス内の構築は最も単純なデプロイメントの形式です。ナレッジ定義をコンパイルして、同じ JVM
内のナレッジベースにこれらの定義を追加します。このアプローチでは、クラスパスに置くには
drools-core.jar および drools-com piler.jar が必要です。
バグを報告する
8.6. KnowledgeBase へ の KnowledgePackages の 追 加
手順 8.3 タスク
KnowledgePackages を KnowledgeBase に追加するには、以下のコードを使用します。
Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kpkgs );
addKnowledgePackages(kpkgs) メソッドは、繰り返し呼び出してさらにナレッジを追加するこ
とができます。
バグを報告する
8.7. 別 の プ ロ セ ス で の 構 築 お よ び デ プ ロ イ メ ン ト
KnowledgeBase および KnowledgePackage はどちらもデプロイメントユニットで直列化可能です。
つまり、必要な構築を 1 台のマシンで行い (drools-com piler.jar が必要)、他のマシンですべてを
デプロイ、実行します (drools-core.jar のみが必要)。
バグを報告する
8.8. OutputStream へ の KnowledgePackage の 記 述
これは OutputStream へ KnowledgePackage を記述するコードです。
73
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( fileName )
);
out.writeObject( kpkgs );
out.close();
バグを報告する
8.9. InputStream か ら KnowledgePackage の 読 み 取 り
以下のコードを使用して、InputStream から KnowledgePackage を読み取ります。
ObjectInputStream in = new ObjectInputStream( new FileInputStream( fileName ) );
// The input stream might contain an individual
// package or a collection.
@SuppressWarnings( "unchecked" )
Collection<KnowledgePackage> kpkgs =
()in.readObject( Collection<KnowledgePackage> );
in.close();
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kpkgs );
バグを報告する
8.10. JBoss Rules 管 理 シ ス テ ム
JBoss Rules 管理システムは KnowledgeBases のリポジトリで、多数のルールセットを保持します。
また、システムは直列化されたナレッジパッケージをコンパイルして URL に公開し、これを使用して
パッケージをロードします。
バグを報告する
8.11. StatefulknowledgeSessions お よ び KnowledgeBase の 変 更
KnowledgeBase は StatefulKnowledgeSession オブジェクトを作成して返し、オプションでこれ
らのオブジェクトへ参照することも可能です。
KnowledgeBase が変更されると、セッション内のデータに適用されます。この参照は弱参照で、これも
オプションです。Boolean フラグにより制御されます。
バグを報告する
8.12. 新 た な knowledgeAgent
以下は、新規 KnowlegeAgent を作成するコードです。
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "MyAgent" );
バグを報告する
8.13. OutputStream へ の KnowledgePackage の 記 述
74
第8章 構築
以下は、OutputStream へ KnowledgePackage を記述する方法です。
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "MyAgent" );
kagent.applyChangeSet( ResourceFactory.newUrlResource( url ) );
KnowledgeBase kbase = kagent.getKnowledgeBase();
注記
リソースのスキャンはデフォルトでは有効ではないため、開始する必要があります。これは通知に
も該当します。ResourceFactory 経由で両方とも有効にすることができます。
バグを報告する
8.14. ス キ ャ ン と 通 知 サ ー ビ ス の 開 始
以下はスキャンと通知サービスを開始するためのコードです。
ResourceFactory.getResourceChangeNotifierService().start();
ResourceFactory.getResourceChangeScannerService().start();
バグを報告する
8.15. ResourceChangeScanner
ResourceChangeScanner は、サービスをスキャンにするために使用します。デフォルトのリソースス
キャンの期間は、ResourceChangeScannerService 経由で変更することができます。適切に更新さ
れた ResourceChangeScannerConfiguration オブジェクトは、サービスの configure() メ
ソッドに渡され、サービスがオンデマンドで再構成できるようにします。
バグを報告する
8.16. ス キ ャ ン 間 隔 の 変 更
以下は、スキャンの間隔を変更する際に使用するコードです。
ResourceChangeScannerConfiguration sconf =
ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfigura
tion();
// Set the disk scanning interval to 30s, default is 60s.
sconf.setProperty( "drools.resource.scanner.interval", "30" );
ResourceFactory.getResourceChangeScannerService().configure( sconf );
バグを報告する
8.17. ナ レ ッ ジ エ ー ジ ェ ン ト と ナ レ ッ ジ ベ ー ス 間 の 対 話
ナレッジエージェントは、空のナレッジベースや生成したナレッジベースを処理することができます。生
成したナレッジベースが指定された場合、ナレッジエージェントはナレッジベースからイテレーターを実
行して、見つかったリソースにサブスクライブします。ナレッジビルダーがディレクトリ内で見つかった
リソースをすべて構築できるだけでなく、その情報はナレッジビルダーにより消され、これらのディレク
75
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
トリが継続してスキャンされないようにします。applyChangeSet(Resource) メソッドの一部として
指定されたディレクトリのみ、モニタリングされます。
スタートポイントとして KnowledgeBase を指定する利点は、KnowledgeBaseConfiguration でそ
れを提供できる点です。リソースの変更が検出され新しい KnowledgeBase オブジェクトがインスタン
ス化されると、以前の KnowledgeBase の KnowledgeBaseConfiguration を使用します。
バグを報告する
8.18. 既 存 の KnowledgeBase の 使 用
以下は、既存の KnowledgeBase を活用するコードです。
KnowledgeBaseConfiguration kbaseConf =
KnowledgeBaseFactory.createKnowledgeBaseConfiguration( null, cl );
KnowledgeBase kbase KnowledgeBaseFactory.newKnowledgeBase( kbaseConf );
// Populate kbase with resources here.
KnowledgeAgent kagent =
KnowledgeAgentFactory.newKnowledgeAgent( "MyAgent", kbase );
KnowledgeBase kbase = kagent.getKnowledgeBase();
上記の例では getKnowledgeBase() はリソースの変更が検出され新しいナレッジベースが構築される
まで指定の同じ kbase インスタンスを返します。新しいナレッジベースが構築される際は、以前の
KnowledgeBase に提供された KnowledgeBaseConfiguration を使って行われます。
バグを報告する
8.19. applyChangeSet() メ ソ ッ ド
ChangeSet XML と applyChangeSet() メソッドとを合わせて使用すると、スキャンプロセスにディレ
クトリを追加します。ディレクトリのスキャンで追加のファイルが検出されると、そのファイルはナレッ
ジベースに追加されます。削除されたファイルも、変更されたファイルも、ナレッジベースから削除され
ます。
バグを報告する
8.20. デ ィ レ ク ト リ の コ ン テ ン ツ を 追 加 す る た め の ChangeSet
XML
この XML を使用して、ディレクトリのコンテンツを ChangeSet に追加します。
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd'
><add><resource source='file:/projects/myproject/myrules' type='PKG'
/></add></change-set>
76
第8章 構築
注記
リソース型 PKG は、drools-compiler の依存関係が必要ではない点に注意してください。ナレッジ
エージェントは drools-core だけでこれらを処理することができます。
バグを報告する
8.21. KnowledgeAgentConfiguration プ ロ パ テ ィ
KnowledgeAgentConfiguration は、ナレッジエージェントのデフォルトの動作を変更するために使
用します。これを使用して、ディレクトリからリソースをロードし、そのディレクトリへの変更を加え継
続的なスキャンを阻止します。
バグを報告する
8.22. ス キ ャ ン 動 作 の 変 更
以下のコードを使用してスキャンの動作を変更します。
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
KnowledgeAgentConfiguration kaconf =
KnowledgeAgentFactory.newKnowledgeAgentConfiguation();
// Do not scan directories, just files.
kaconf.setProperty( "drools.agent.scanDirectories", "false" );
KnowledgeAgent kagent =
KnowledgeAgentFactory.newKnowledgeAgent( "test agent", kaconf );
バグを報告する
77
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 9章 セッション
9.1. JBoss Rules の セ ッ シ ョ ン
セッションは、データを挿入することができプロセスインスタンスを開始できる KnowledgeBase から
作成されます。KnowledgeBase の作成はリソースを集中的に使用する場合がありますが、セッションの
作成はそうではありません。このような理由から、できる限り KnowledgeBases をキャッシュして、繰
り返してセッションを作成できるようにするよう推奨されています。
バグを報告する
9.2. KnowledgeBase か ら の StatefulKnowledgeSession の 作 成
以下は、KnowledgeBase から新しい StateefulKnowledgeSession を作成するコードです。
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
バグを報告する
9.3. WorkingMemoryEntryPoint メ ソ ッ ド
WorkingMem oryEntryPoint は、ファクトの挿入、更新、取得関連のメソッドを提供します。「エン
トリポイント」という用語は、ワーキングメモリ内にある複数のパーティションのどの部分に挿入するか
選択できるということに関連しています。ほとんどのルールベースのアプリケーションは、デフォルトの
エントリポイントだけで機能します。
バグを報告する
9.4. KnowledgeRuntime イ ン タ ー フ ェ ー ス
KnowledgeRuntim e インターフェースは、主にエンジンとの対話を行い、ルールの結論部やプロセスア
クションで利用できます。KnowledgeRuntim e は、WorkingMem ory および ProcessRuntim e 両方
からのメソッドを継承して、統合された API を提供してプロセスとルールと連携します。ルールと連携す
ると、KnowledgeRuntim e は
WorkingMem oryEntryPoint、WorkingMem ory、KnowledgeRuntim e 自体の 3 つのインター
フェースで形成されます。
バグを報告する
9.5. フ ァ ク ト の 挿 入
挿入とは、ファクトに関して WorkingMem ory に通知する行為のことです。例え
ば、ksession.insert(yourObject) を使用して挿入を行うことができます。ファクトを挿入して、
ルールに合致がないか検証します。つまり、ルールの発火を行うかどうかを決定する作業のすべてが挿入
時に行われます。しかし、ファクトの挿入が完了した後に呼び出す fireAllRules() を呼び出すまで、
ルールは実行されません。
バグを報告する
9.6. FactHandle ト ー ク ン
78
第9章 セッション
オブジェクトが挿入されると、FactHandle が返されます。この FactHandle は、WorkingMem ory
内に挿入されたオブジェクトを表すために使用するトークンです。このトークンは、オブジェクトの削除
や変更の際に WorkingMem ory と対話をする際にも使用されます。
バグを報告する
9.7. FactHandle の 例
Job accountant = new Job("accountant");
FactHandle accountantHandle = ksession.insert( accountant );
バグを報告する
9.8. ア イ デ ン テ ィ テ ィ と 等 価
これらは、ワーキングメモリにより使用される 2 つのアサーションノードです。
アイデンティティ
アイデンティティとは、ワーキングメモリが IdentityHashMap を使用してアサートされたオ
ブジェクトをすべて保存するという意味です。新しいインスタンスアサーションは常に、新しい
FactHandle を返すことになりますが、インスタンスが再度アサートされると、元のファクト
ハンドルを返します (つまり、同じオブジェクトに対する挿入の繰り返しを無視するということ
です)。
等価
等価とは、ワーキングメモリが HashMap を使用してアサートしたオブジェクトすべてを保存す
るという意味です。挿入されたオブジェクトが (equal メソッドによると) 既存のファクトと等
価でない場合、オブジェクトインスタンスのアサーションは、新しい FactHandle のみを返し
ます。
注記
新しいインスタンスアサーションは常に、新しい FactHandle を返すことになりますが、インス
タンスが再度アサートされると、元のファクトハンドルを返します (つまり、同じオブジェクトに
対する挿入の繰り返しを無視するということです)。
バグを報告する
9.9. 取 り 消 し
取り消しとは、ワーキングメモリからファクトを取り除くことです。つまり、これ以上ファクトのトラッ
キングと照合は行われず、アクティブ化されそのファクトに依存するルールはすべてキャンセルされると
いうことです。ファクトがないことに依存するルールもありえます。ファクトを取り消すとルールがアク
ティブ化されるきっかけとなる場合があります。挿入コールにより返された FactHandle を使用して、
取り消しを行うことができます。ルールの右側では、retract ステートメントを使用して、シンプルな
オブジェクト参照と連携します。
バグを報告する
79
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
9.10. 取 り 消 し の 例
Job accountant = new Job("accountant");
FactHandle accountantHandle = ksession.insert( accountant );
....
ksession.retract( accountantHandle );
バグを報告する
9.11. update() メ ソ ッ ド
ルールエンジンは、再処理ができるようにファクトが変更されたことを通知する必要がありま
す。update() メソッドを使用して、WorkingMem ory 自体の通知ができないオブジェクトのために、
オブジェクトが変更されたことを WorkingMem ory に通知することができます。update() メソッドは
常に、変更されたオブジェクトを 2 番目のパラメーターとして取り、イミュータブルオブジェクトに新し
いインスタンスを指定することができるようになります。
注記
ルールの右側部分には、単一のステートメントでエンジンの変更と通知を行うため、m odify ス
テートメントが推奨されます。あるいは、setter メソッドを呼び出してファクトオブジェクトの
フィールド値を変更した後、すぐに update を呼び出す必要があります。すぐ呼び出しがされない
と、他のファクトを変更する前でも、ルールエンジン内のインデックスに問題が発生する可能性が
あります。modify ステートメントはこの問題を回避することができます。
バグを報告する
9.12. update() の 例
Job accountant = new Job("accountant");
FactHandle accountantHandle = workingMemory.insert( accountant );
...
accountant.setSalary( 45000 );
workingMemory.update( accountantHandle, accountant );
バグを報告する
9.13. ク エ リ
クエリは、ルールで使用されているようにパターンをベースとしてファクトセットを取得するために使用
します。パターンがオプションのパラメーターを活用する場合もあります。クエリはナレッジベースで定
義でき、ナレッジベースから合致した結果を戻すためにクエリを呼び出します。結果のコレクションが繰
り返し行われている間、get メソッドを引数としてバイドした変数の名前で呼び出すことで、クエリでバ
インドされた識別子を使用して該当のファクトまたはファクトフィールドにアクセスすることができま
す。このバインドがファクトオブジェクトを参照している場合、パラメーターとして変数の名前を再度使
用して getFactHandle を呼び出すことで FactHandle を取得できます。
バグを報告する
80
第9章 セッション
9.14. ク エ リ の 例
QueryResults results =
ksession.getQueryResults( "my query", new Object[] { "string" } );
for ( QueryResultsRow row : results ) {
System.out.println( row.get( "varName" ) );
}
バグを報告する
9.15. ラ イ ブ ク エ リ
クエリを呼び出して、返されたセットを反復して結果を処理するのは、変更のモニタリングに適した方法
ではありません。
これを軽減するために JBoss Rules は反復可能な結果セットを返すのではなくリスナーが接続されたライ
ブクエリを提供しています。これらのライブクエリは、ビューを作成してこのビューのコンテンツ向けに
変更イベントを公開することでオープンの状態を保ちます。アクティブ化するには、パラメーターでクエ
リを開始して結果ビューの変更をリッスンします。dispose メソッドはクエリを終了して、この反応型
のシナリオを中断します。
バグを報告する
9.16. ViewChangedEventListener の 実 装 例
final List updated = new ArrayList();
final List removed = new ArrayList();
final List added = new ArrayList();
ViewChangedEventListener listener = new ViewChangedEventListener() {
public void rowUpdated(Row row) {
updated.add( row.get( "$price" ) );
}
public void rowRemoved(Row row) {
removed.add( row.get( "$price" ) );
}
public void rowAdded(Row row) {
added.add( row.get( "$price" ) );
}
};
// Open the LiveQuery
LiveQuery query = ksession.openLiveQuery( "cars",
new Object[] { "sedan", "hatchback" },
listener );
...
...
query.dispose() // calling dispose to terminate the live query
81
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
注記
ライブクエリの Glazed Lists 統合の例については、http://blog.athico.com/2010/07/glazed-listsexamples-for-drools-live.html を確認してください。
バグを報告する
9.17. KnowledgeRuntime
KnowledgeRuntim e は、グローバルの設定やチャネルの登録など、ルール、プロセス両方に適用可能な
メソッドをさらに提供します ("Exit point" は "channel" と同義で以前使用されていた用語です)。
バグを報告する
82
第10章 オブジェクトとインターフェース
第 10章 オブジェクトとインターフェース
10.1. グ ロ ー バ ル (Global)
グローバル (Global) はルールエンジンに公開する名前付きのオブジェクトですが、ファクトと違って
global をバックアップするオブジェクトに変更があってもルールの再評価はトリガーされません。Global
はルールの RHS で使用されるサービスを提供するオブジェクトとして、ルールエンジンからオブジェク
トを返す手段として、静的な情報を提供する際に便利です。
バグを報告する
10.2. Global と の 連 携
手順 10.1 タスク
1. Global をワーキングメモリに実装開始するには、ルールファイルに global を宣言して、Java オブ
ジェクトでバックアップします。
global java.util.List list
2. ナレッジベースは global の識別子とその型を認識するようになったため、Global の名前とオブジェ
クトで ksession.setGlobal() を呼び出して、global とオブジェクトを関連付けることができ
ます。
List list = new ArrayList();
ksession.setGlobal("list", list);
重要
Global の型と識別子を DRL コードで宣言しなかった場合は、この呼び出しから例外が送出
されます。
3. ルールの評価をする前に Global を設定するようにしてください。そうでない
と、NullPointerException が送出されてしまいます。
バグを報告する
10.3. Global の 解 決
Global は 3 つの方法で解決することができます。
getGlobals()
Stateless Knowledge Session メソッド getGlobals() は、セッションの global へアクセスで
きるようにする Global インスタンスを返します。これらは、実行呼び出しすべてに共有されま
す。別のスレッドで同時に実行呼び出しが実行される場合がありますので、ミュータブル global
には注意してください。
Delegates
Global の解決を行う別の方法には、delegate の使用が挙げられます。global
(setGlobal(String, Object) で) に値を割り当てると、識別子を値にマッピングする内部
83
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
コレクション内に値が格納されます。この内部コレクションの識別子は、提供した delegate よ
りも優先されます。識別子がこの内部コレクションで見つからない場合、delegate global が使用
されます (あれば)。
Execution
Execution scoped global は Com m and を使用して global を設定し、Com m andExecutor に渡
されます。
バグを報告する
10.4. Session Scoped Global の 例
以下は、Session Scoped Global の例です。
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
// Set a global hbnSession, that can be used for DB interactions in the rules.
ksession.setGlobal( "hbnSession", hibernateSession );
// Execute while being able to resolve the "hbnSession" identifier.
ksession.execute( collection );
バグを報告する
10.5. StatefulRuleSessions
StatefulRuleSession プロパティは、StatefulKnowledgeSession が継承して、エンジン外部か
ら該当するルール関連のメソッドを提供します。
バグを報告する
10.6. AgendaFilter オ ブ ジ ェ ク ト
AgendaFilter オブジェクトは、フィルターインターフェースのオプション実装です。これを使用して
アクティベーションの発火の許可または拒否を行うことが可能になります。フィルタリング対象は、実装
により左右されます。
バグを報告する
10.7. AgendaFilter の 使 用
手順 10.2 タスク
フィルターを使用するには、fireAllRules() を呼び出す際に指定します。以下の例では、文字列
"T est" で終わるルールのみが許可され、それ以外はフィルタリングされ除外されてしまいます。
ksession.fireAllRules( new RuleNameEndsWithAgendaFilter( "Test" ) );
バグを報告する
10.8. ル ー ル エ ン ジ ン の フ ェ ー ズ
84
第10章 オブジェクトとインターフェース
エンジンは、以下の 2 つのフェーズのサイクルを繰り返します。
ワーキングメモリのアクション
これは、Consequence (RHS 自体) か 主な Java アプリケーションのプロセスなど、作業が実行
される場所です。Consequence が終了するか、主要なアプリケーションプロセスが
fireAllRules() を呼び出すと、エンジンはアジェンダ評価フェースに切り替えられます。
アジェンダ評価
これは、発火するルールの選択を試みます。ルールが見つからなかった場合、そのまま存在し
て、見つかった場合はそのルールを発火し、このフェーズを再度ワーキングメモリアクションに
切り替えます。
このプロセスは、アジェンダがなくなるまで繰り返されます。アジェンダがなくなると、呼び出し中のア
プリケーションに制御が返されます。ワーキングメモリアクションが実行されている間は、ルールは発火
されません。
バグを報告する
10.9. イ ベ ン ト モ デ ル
イベントパッケージは、ルールの発火、アサートされたオブジェクトなど、ルールエンジンイベントを通
知する手段を提供します。これにより、例えばロギングや監査のアクティビティと、アプリケーションの
主要部 (およびルール) を分割することができます。
バグを報告する
10.10. KnowlegeRuntimeEventManager
KnowlegeRuntim eEventManager インターフェースは、KnowledgeRuntim e で実装さ
れ、WorkingMem oryEventManager と ProcessEventManager の 2 つのインターフェースを提供
します。
バグを報告する
10.11. WorkingMemoryEventManager
WorkingMem oryEventManager により、リスナーの追加や削除が可能になり、ワーキングメモリのイ
ベントやアジェンダをリッスンすることができます。
バグを報告する
10.12. AgendaEventListener の 追 加
以下のコードスニペットは、どのようにシンプルなアジェンダーリスナーが宣言されセッションに接続さ
れるかを示しています。発火後にアクティベーションを出力します。
85
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ksession.addEventListener( new DefaultAgendaEventListener() {
public void afterActivationFired(AfterActivationFiredEvent event) {
super.afterActivationFired( event );
System.out.println( event );
}
});
バグを報告する
10.13. ワ ー キ ン グ メ モ リ の イ ベ ン ト の 出 力
以下のコードにより、リスナーを追加することですべてのワーキングメモリのイベントを出力することが
できます。
ksession.addEventListener( new DebugWorkingMemoryEventListener() );
バグを報告する
10.14. KnowlegeRuntimeEvents
出されたイベントはすべて、KnowlegeRuntim eEvent インターフェースを実装し、このインター
フェースを使用してイベントが出された実際の KnowlegeRuntim e を取得することができます。
バグを報告する
10.15. KnowledgeRuntimeEvent イ ン タ ー フ ェ ー ス に 対 応 の イ ベ
ント
現在サポートされているイベント:
ActivationCreatedEvent
ActivationCancelledEvent
BeforeActivationFiredEvent
AfterActivationFiredEvent
AgendaGroupPushedEvent
AgendaGroupPoppedEvent
ObjectInsertEvent
ObjectRetractedEvent
ObjectUpdatedEvent
ProcessCompletedEvent
ProcessNodeLeftEvent
ProcessNodeT riggeredEvent
ProcessStartEvent
バグを報告する
10.16. KnowledgeRuntimeLogger
KnowledgeRuntimeLogger は、JBoss Rules の統合イベントシステムで監査ログを作成します。後に
86
第10章 オブジェクトとインターフェース
Eclipse 監査ビューワーなどのツールで検証できるように、この監査ログを使用してアプリケーションの
実行ログを取ることができます。
バグを報告する
10.17. FileLogger の 有 効 化
FileLogger を有効にしてファイルをトラッキングするには、以下のコードを使用します。
KnowledgeRuntimeLogger logger =
KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "logdir/mylogfile");
...
logger.close();
バグを報告する
10.18. JBoss Rules で の StatelessKnowledgeSession の 使 用
StatelessKnowledgeSession は拡張する代わりに StatefulKnowledgeSession をラップしま
す。これは、主に決定サービスタイプのシナリオに焦点を当てており、dispose() を呼び出す必要がな
くなります。ステートレスセッションは、反復挿入や Java コードからの fireAllRules() メソッド呼
び出しはサポートしていません。execute() を呼び出す行為はワンショットメソッド
で、StatefulKnowledgeSession を内部でインスタンス化し、すべてのユーザーデータを追加して
ユーザコマンドを実行し、fireAllRules() を呼び出した後、dispose() を呼び出します。このクラ
スと連携するための主な方法は、Com m andExecutor でサポートされているように BatchExecution
(Com m and のサブインターフェース) を使用することですが、単純なオブジェクトの挿入だけが必要な場
合のために、便利な 2 つのメソッドが提供されています。Com m andExecutor および
BatchExecution は、それぞれのセクションで詳しく説明します。
バグを報告する
10.19. コ レ ク シ ョ ン を 使 用 し た StatelessKnowledgeSession の 実
行
以下のコードは、コレクションを使った StatelessKnowledgeSession の実行例です。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newFileSystemResource( fileName ), ResourceType.DRL
);
if (kbuilder.hasErrors() ) {
System.out.println( kbuilder.getErrors() );
} else {
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
ksession.execute( collection );
}
バグを報告する
87
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
10.20. InsertElements コ マ ン ド を 使 用 し た
StatelessKnowledgeSession の 実 行
以下は、InsertElements コマンドを使用して StatelessKnowledgeSession を実行したコードです。
ksession.execute( CommandFactory.newInsertElements( collection ) );
注記
コレクションと個別の要素を挿入するには、Com m andFactory.newInsert(collection) を
使用します。
バグを報告する
10.21. BatchExecutionHelper
Com m andFactory のメソッドは、対応のコマンドを作成して、XStream とBatchExecutionHelper
を使用してすべてをマーシャリングすることができます。BatchExecutionHelper は、XML 形式の詳
細および BatchExecution および ExecutionResults のマーシャリングを自動化する JBoss Rules
Pipuline の使用方法を提供します。
バグを報告する
10.22. CommandExecutor イ ン タ ー フ ェ ー ス
Com m andExecutor インターフェースは、"out" パラメーターを使用してデータのエクスポートができる
ようにします。つまり、挿入したファクト、Global、クエリの結果はすべてこのインターフェースを使用
して返されることになります。
バグを報告する
10.23. Out 識 別 子
以下は、Out 識別子の例です。
// Set up
List cmds
cmds.add(
cmds.add(
cmds.add(
a list of commands
= new ArrayList();
CommandFactory.newSetGlobal( "list1", new ArrayList(), true ) );
CommandFactory.newInsert( new Person( "jon", 102 ), "person" ) );
CommandFactory.newQuery( "Get People" "getPeople" );
// Execute the list
ExecutionResults results =
ksession.execute( CommandFactory.newBatchExecution( cmds ) );
// Retrieve the ArrayList
results.getValue( "list1" );
// Retrieve the inserted Person fact
results.getValue( "person" );
// Retrieve the query as a QueryResults instance.
results.getValue( "Get People" );
88
第10章 オブジェクトとインターフェース
バグを報告する
89
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 11章 モードとメソッド
11.1. シ ー ケ ン シ ャ ル モ ー ド
JBoss Rules のシーケンシャルモードを使用すると、より簡単な方法でエンジンを使用することができま
す。ユーザーがステートレスセッションで作用してデータが初期のデータセットからアサートまたは変更
されない場合、再評価の必要性なしにルールを使用できます。
バグを報告する
11.2. シ ー ケ ン シ ャ ル モ ー ド の オ プ シ ョ ン
シーケンシャルモードを使用時に選べるオプションがいくつかあります。
1. ルールセット内の salience (優先順位) および位置でルールの順番を決める (ルールの終端ノードで
sequence 属性を設定)。
2. 配列の作成 (ルールアクティベーション候補ごとに 1 要素)。要素の位置は発火順位を示す。
3. right-input オブジェクトメモリ以外のノードのメモリをすべて無効にする。
4. Left Input Adapter ノードの伝播を切断して、オブジェクトとノードがコマンドオブジェクトで参照
されるようにする。これは後に実行できるようにワーキングメモリのリストに追加される。
5. すべてオブジェクトをアサート。すべてのアサートが終了して、right-input ノードのメモリが生成
されると、コマンドリストを確認して順番に実行してく。
6. 結果となるすべてのアクティベーションは、決定されたルールの順番をベースに配列内に設定され
る必要がある。最初と最後に生成された要素を記録して反復の幅を減らす。
7. アクティベーションの配列を繰り返して、生成した要素を順番に実行する。
8. ルール実行の最大回数がある場合、ネットワーク評価を早く終了して配列内でルールをすべて発火
する。
バグを報告する
11.3. シ ー ケ ン シ ャ ル モ ー ド の 有 効 化
手順 11.1 タスク
1. ステートレスセッションを開始します。
2. シーケンシャルモードはデフォルトで無効になっています。有効にするに
は、RuleBaseConfiguration.setSequential(true) を呼び出すか、rulebase 設定プロパ
ティ drools.sequential を true に設定します。
3. シーケンシャルモードが動的アジェンダに分類できるように、 SequentialAgenda.DYNAMIC で
setSequentialAgenda を呼び出します。
4. オプションで、JBossRules.sequential.agenda プロパティを sequential または
dynam ic に設定します。
バグを報告する
11.4. CommandFactory
Com m andFactory オブジェクトは、コマンドがステートレスセッションで実行できるようにします。完
了すると、セッションを破棄する前にファクトリが fireAllRules() を実行します。
90
第11章 モードとメソッド
バグを報告する
11.5. 対 応 の CommandFactory オ プ シ ョ ン
これらのオプションはすべて CommandFactory と互換性があります。
FireAllRules
GetGlobal
SetGlobal
InsertObject
InsertElements
Query
StartProcess
BatchExecution
バグを報告する
11.6. 挿 入 コ マ ン ド
InsertObject は、オプションの "out" 識別子で単一のオブジェクトを挿入します。InsertElem ents
は Iterable を反復して各要素を挿入します。こうすることで、ステートレスナレッジセッションがクエリ
をあらゆる順序で処理、実行することができます。
バグを報告する
11.7. 挿 入 コ マ ン ド の 例
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
ExecutionResults bresults =
ksession.execute( CommandFactory.newInsert( new Car( "sedan" ), "sedan_id" ) );
Sedan sedan = bresults.getValue( "sedan_id" );
バグを報告する
11.8. 実 行 メ ソ ッ ド
実行メソッドを使用して、1 度に 1 つのコマンドを実行します。常にこのメソッドは
ExecutionResults インスタンスを返して、stilton_id などの out 識別子を指定している場合、コ
マンドの結果にアクセスできるようになります。
バグを報告する
11.9. 実 行 メ ソ ッ ド の 例
91
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
Command cmd = CommandFactory.newInsertElements( Arrays.asList( Object[] {
new Car( "sedan" ),
new Car( "hatchback" ),
new Car( "convertible" ),
});
ExecutionResults bresults = ksession.execute( cmd );
バグを報告する
11.10. BatchExecution コ マ ン ド
BatchExecution コマンドにより、複数のコマンドを 1 度に実行することができます。これは、コマン
ドリストから作成された複合コマンドのことを指します。Execute はリストの項目を繰り返して順番にコ
マンドを実行します。つまり、 execute(...) 呼び出し 1 つで、オブジェクトを挿入、プロセスを開
始、fireAllRules を呼び出し、クエリを実行することができます。
バグを報告する
11.11. FireAllRules コ マ ン ド
FireAllRules コマンドは、最後にルールを自動的に実行します。手動でオバーライドする関数型で
す。
バグを報告する
11.12. Out 識 別 子
コマンドは Out 識別子に対応しています。Out 識別子が設定されているコマンドは、結果を返された
ExecutionResults インスタンスに追加します。
バグを報告する
11.13. Out 識 別 子 の 例
以下の例は、BatchExecution コマンドを使用して Out 識別子がどのように機能するか示しています。
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
List cmds = new ArrayList();
cmds.add( CommandFactory.newInsertObject( new Car( "red", 1), "red") );
cmds.add( CommandFactory.newStartProcess( "process cars" ) );
cmds.add( CommandFactory.newQuery( "cars" ) );
ExecutionResults bresults = ksession.execute( CommandFactory.newBatchExecution(
cmds ) );
Car red = ( Car ) bresults.getValue( "red" );
QueryResults qresults = ( QueryResults ) bresults.getValue( "cars" );
上記の例では、複数のコマンドが実行されます。これらの内 2 つは ExecutionResults を生成しま
す。クエリコマンドはデフォルトで同じ識別子をクエリ名として使用しますが、別の識別子にマッピング
することもできます。
バグを報告する
92
第11章 モードとメソッド
11.14. 実 行 XML の 例
カスタムの XStream マーシャラーは、JBoss Rules Pipelin と併用して XML スクリプトが実現できサービ
スに適しています。これに関して 2 つの例を以下に示しています。
BatchExecution XML:
<batch-execution><insert outidentifier='outRed'><org.drools.Car><type>red</type><price>25000</price><oldPrice
>0</oldPrice></org.drools.Car></insert></batch-execution>
ExecutionResults XML:
<execution-results><result
identifier='outBlue'><org.drools.Car><type>Blue</type><oldPrice>25</oldPrice><pri
ce>30000</price></org.drools.Car></result></execution-results>
バグを報告する
11.15. 実 行 マ ー シ ャ リ ン グ の 例
以下は XML にマーシャリングされた BatchExecution の例です。
<batch-execution><insert outidentifier="sedan"><org.drools.Car><type>sedan</type><price>1</price><oldPrice>0<
/oldPrice></org.drools.Car></insert><query out-identifier='cars2'
name='carsWithParams'><string>hatchback</string><string>sedan</string></query></bat
ch-execution>
93
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
Com m andExecutor は ExecutionResults を返して、パイプラインコードスニペットで処理されま
す。上記の <batch-execution> XML サンプルと似た出力は以下のようになります。
<execution-results><result
identifier="sedan"><org.drools.Car><type>sedan</type><price>2</price></org.drools.
Car></result><result identifier='cars2'><queryresults><identifiers><identifier>car</identifier></identifiers><row><org.drools.Ca
r><type>hatchback</type><price>2</price><oldPrice>0</oldPrice></org.drools.Car></
row><row><org.drools.Car><type>hatchback</type><price>1</price><oldPrice>0</oldPr
ice></org.drools.Car></row></query-results></result></execution-results>
バグを報告する
11.16. Batch-execution と コ マ ン ド の 例
1. 現在、スキーマ検証をサポートする XML スキーマはありません。以下が基本的なフォーマットと
なっています。Root 要素は、<batch-execution> で、0 またはそれ以上のコマンド要素を含めるこ
とができます。
<batch-execution>
...
</batch-execution>
2. 挿入要素には、"out-identifier" 属性が含まれているため、挿入されたオブジェクトは結果ペイロー
ドの一部として返されます。
94
第11章 モードとメソッド
<batch-execution><insert out-identifier='userVar'>
...
</insert></batch-execution>
3. <insert-elements> 要素を使用してオブジェクトのコレクションを挿入することも可能です。この
コマンドは、out-identifier には対応していません。org.dom ain.UserClass は XStream が直列
化するユーザーオブジェクトの事例として使用しています。
<batch-execution><insert-elements><org.domain.UserClass>
...
</org.domain.UserClass><org.domain.UserClass>
...
</org.domain.UserClass><org.domain.UserClass>
...
</org.domain.UserClass></insert-elements></batch-execution>
4. <set-global> 要素は、セッションに Global を設定します。
<batch-execution><set-global identifier='userVar'><org.domain.UserClass>
...
</org.domain.UserClass></set-global></batch-execution>
5. <set-global> は、他に out と out-identifier の 2 つのオプション属性にも対応していま
す。ブール型 out の true 値は、identifier 属性かの名前を使用して Global を <batchexecution-results> ペイロードに追加します。 out-identifier は out のように機能しま
すが、<batch-execution-results> ペイロードで使用した識別子をオーバーライドできま
す。
<batch-execution><set-global identifier='userVar1'
out='true'><org.domain.UserClass>
...
</org.domain.UserClass></set-global><set-global identifier='userVar2'
out-identifier='alternativeUserVar2'><org.domain.UserClass>
...
</org.domain.UserClass></set-global></batch-execution>
6. コンテンツのない <get-global> 要素があり、out-identifier 属性のみが含まれています。
95
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
値の取得が <get-global> 要素の唯一の目的であるため、out 属性は必要ありません。
<batch-execution><get-global identifier='userVar1' /><get-global
identifier='userVar2' out-identifier='alternativeUserVar2'/></batch-execution>
7. query コマンドは、パラメータークエリもパラメーターなしのクエリにも対応しています。nam e
属性は呼び出すクエリ名で、out-identifier は <execution-results> ペイロードのクエリ
結果で使用される識別子です。
<batch-execution><query out-identifier='cars' name='cars'/><query outidentifier='cars2'
name='carsWithParams'><string>red</string><string>blue</string></query></batch
-execution>
8. <start-process> コマンドは、オプションのパラメーターも受け入れます。
<batch-execution><startProcess processId='org.drools.actions'><parameter
identifier='person'><org.drools.TestVariable><name>John
Doe</name></org.drools.TestVariable></parameter></startProcess></batchexecution
9. signal event コマンドでプロセスの特定が可能になります。
<signal-event process-instance-id='1' eventtype='MyEvent'><string>MyValue</string></signal-event>
10. complete work item コマンドは、プロセスが完了するとユーザーに通知します。
<complete-work-item id='" + workItem.getId() + "' ><result
identifier='Result'><string>SomeOtherString</string></result></complete-workitem>
11. abort work item コマンドで、実行中にプロセスを取り消すことができます。
96
第11章 モードとメソッド
<abort-work-item id='21' />
バグを報告する
11.17. MarshallerFactory
MarshallerFactory は、ステートフルナレッジセッションのマーシャリングとアンマーシャリングに
使用します。
バグを報告する
11.18. マ ー シ ャ ラ ー の 例
以下は、実際のマーシャーラーの例です。
// ksession is the StatefulKnowledgeSession
// kbase is the KnowledgeBase
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Marshaller marshaller = MarshallerFactory.newMarshaller( kbase );
marshaller.marshall( baos, ksession );
baos.close();
バグを報告する
11.19. マ ー シ ャ リ ン グ の オ プ シ ョ ン
表 11.1 マーシャリングのオプション
オプション
説明
ObjectMarshallingStrategy
このインターフェースは、マーシャリングの実装
用に提供され、柔軟性が増します。
SerializeMarshallingStrategy
これは、ユーザーインターフェースで
Serializable または Externalizable メ
ソッドを呼び出すデフォルトのストラテジです。
IdentityMarshallingStrategy
このストラテジは、各ユーザーオブジェクトに整
数の id を作成してマップに格納し、この id はス
トリームに書き込まれます。
アンマーシャリングする
と、IdentityMarshallingStrategy マップ
にアクセスしてインスタンスを取得します。つま
り、IdentityMarshallingStrategy を使用
する場合、Marshaller インスタンスが存続する間
ステートフルで、ID を作成してマーシャルしよう
とするオブジェクトすべてに対する参照を保持し
ます。
バグを報告する
11.20. IdentityMarshallingStrategy の 例
97
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
以下は、IdentityMarshallingStrategy を使用するためのコード例です。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectMarshallingStrategy oms = MarshallerFactory.newIdentityMarshallingStrategy()
Marshaller marshaller =
MarshallerFactory.newMarshaller( kbase, new ObjectMarshallingStrategy[]{ oms } );
marshaller.marshall( baos, ksession );
baos.close();
バグを報告する
11.21. ObjectMarshallingStrategyAcceptor
ObjectMarshallingStrategyAcceptor は、オブジェクトのマーシャリング戦略に含まれるイン
ターフェースです。ユーザーオブジェクトの読み取りまたは書き込みを試行すると、
ObjectMarshallingStrategyAcceptor を使用してユーザーオブジェクトのマーシャリングに使用されるかど
うか決定するために使用します。
バグを報告する
11.22. ClassFilterAcceptor の 実 装
ClassFilterAcceptor の実装は、文字列やワイルドカードを使用してクラス名の照合ができるように
します。デフォルトは "*.*" です。
バグを報告する
11.23. ア ク セ プ タ ー を 使 用 し た IdentityMarshallingStrategy の 例
以下は、アクセプターと IdentityMarshallingStrategy を使用した例です。承諾確認の順番は提供された配
列の自然な順番で行われている点に注意してください。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectMarshallingStrategyAcceptor identityAcceptor =
MarshallerFactory.newClassFilterAcceptor( new String[] { "org.domain.pkg1.*" } );
ObjectMarshallingStrategy identityStrategy =
MarshallerFactory.newIdentityMarshallingStrategy( identityAcceptor );
ObjectMarshallingStrategy sms =
MarshallerFactory.newSerializeMarshallingStrategy();
Marshaller marshaller =
MarshallerFactory.newMarshaller( kbase,
new ObjectMarshallingStrategy[]{
identityStrategy, sms } );
marshaller.marshall( baos, ksession );
baos.close();
バグを報告する
11.24. JBoss Rules の 永 続 性 と ト ラ ン ザ ク シ ョ ン
JBoss Rules では、Java Persistence API (JPA) を使用して、カスタマイズなしで長期的に永続性を保つ
ことができます。Java T ransaction API (JT A) の実装をインストールする必要があります。設定が簡単で
埋め込みに対応しているため、開発目的では Bitronix T ransaction Manager を使用することができます。
実稼働環境では、JBoss T ransactions を推奨しています。
98
第11章 モードとメソッド
バグを報告する
11.25. ト ラ ン ザ ク シ ョ ン 例
以下は、トランザクションの実行がどのように行われるか示しています。
Environment env = KnowledgeBaseFactory.newEnvironment();
env.set( EnvironmentName.ENTITY_MANAGER_FACTORY,
Persistence.createEntityManagerFactory( "emf-name" ) );
env.set( EnvironmentName.TRANSACTION_MANAGER,
TransactionManagerServices.getTransactionManager() );
// KnowledgeSessionConfiguration may be null, and a default will be used
StatefulKnowledgeSession ksession =
JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
int sessionId = ksession.getId();
UserTransaction ut =
(UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
ksession.insert( data1 );
ksession.insert( data2 );
ksession.startProcess( "process1" );
ut.commit();
バグを報告する
11.26. JPA の 使 用
手順 11.2 タスク
1. 環境は EntityManagerFactory と T ransactionManager の両方で設定するようにします。
2. GUI またはコマンドから JPA を起動します。
3. ID を使用して以前に永続化したステートフルナレッジセッションをロードします。ロールバックが
発生すると ksession のステートもロールバックされるため、ロールバック後もそのまま使用を続
けることができます。
バグを報告する
11.27. JPA を 持 つ StatefulKnowledgeSession の ロ ー ド
以下は、JPA を実装する StatefulKnowledgeSession をロードするコードです。
StatefulKnowledgeSession ksession =
JPAKnowledgeService.loadStatefulKnowledgeSession( sessionId, kbase, null, env );
バグを報告する
11.28. JPA の 設 定
永続性を有効にするには、以下の例のように複数のクラスを persistence.xml に追加する必要がありま
す。
99
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
<persistence-unit name="org.drools.persistence.jpa" transactiontype="JTA"><provider>org.hibernate.ejb.HibernatePersistence</provider><jta-datasource>jdbc/BitronixJTADataSource</jta-datasource><class>org.drools.persistence.session.SessionInfo</class><class>org.drools.p
ersistence.processinstance.ProcessInstanceInfo</class><class>org.drools.persistence.
processinstance.ProcessInstanceEventInfo</class><class>org.drools.persistence.proces
sinstance.WorkItemInfo</class><properties><property name="hibernate.dialect"
value="org.hibernate.dialect.H2Dialect"/><property
name="hibernate.max_fetch_depth" value="3"/><property
name="hibernate.hbm2ddl.auto" value="update" /><property name="hibernate.show_sql"
value="true" /><property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.BTMTransactionManagerLookup"
/></properties></persistence-unit>
バグを報告する
11.29. JTA DataSource の 設 定
如何は、JT A DataSource の設定コードです。
PoolingDataSource ds = new PoolingDataSource();
ds.setUniqueName( "jdbc/BitronixJTADataSource" );
ds.setClassName( "org.h2.jdbcx.JdbcDataSource" );
ds.setMaxPoolSize( 3 );
ds.setAllowLocalTransactions( true );
ds.getDriverProperties().put( "user", "sa" );
ds.getDriverProperties().put( "password", "sasa" );
ds.getDriverProperties().put( "URL", "jdbc:h2:mem:mydb" );
ds.init();
バグを報告する
11.30. JNDI プ ロ パ テ ィ
Bitronix は単純な埋め込み JNDI サービスを提供しますが、これはテスト目的で理想的です。使用するに
は、jndi.properties ファイルを MET A-INF に追加して、以下の行をそのファイルに追加します。
java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory
バグを報告する
100
第11章 モードとメソッド
11.31. KnowledgeBase 名 前 空 間
以下は、構築目的で KnowledgeBase に追加できる名前空間のリストです。
deftemplate
defrule
deffunction
and/or/not/exists/test 条件要素
Literal、Variable、Return Value および Predicate フィールド制約
バグを報告する
101
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 12章 Using Spreadsheet Decision Tables
12.1. ハ ー ド キ ー ワ ー ド
ハードキーワードは、ルールテキストで使用されるドメインオブジェクト、プロパティ、関数、その他の
要素をネーミングする際に使用できないワードのことです。ハードキーワードは、true、false などの
単語ですが、コマンドとすぐに間違えられる可能性があります。
バグを報告する
12.2. ソ フ ト キ ー ワ ー ド
ソフトキーワードは、ドメインプロジェクト、プロパティ、メソッド、関数、その他の要素のネーミング
に使用することができます。ルールエンジンは、それらのコンテキストを認識してそれに合わせて処理し
ます。
バグを報告する
12.3. ソ フ ト キ ー ワ ー ド の リ ス ト
lock-on-active
date-effective
date-expires
no-loop
auto-focus
activation-group
agenda-group
ruleflow-group
entry-point
duration
package
im port
dialect
salience
enabled
attributes
rule
extend
when
then
tem plate
query
declare
function
global
102
第12章 Using Spreadsheet D ecision Tables
eval
not
in
or
and
exists
forall
accumulate
collect
from
action
reverse
result
end
over
init
バグを報告する
12.4. コ メ ン ト
コメントとは、ルールエンジンが無視するテキストのセクションです。このセクションに遭遇した場合は
省略されます。セマンティックコードブロック内にある場合 (ルールの RHS など) は例外です。
バグを報告する
12.5. 1 行 コ メ ン ト の 例
これは、1 行コメントの例です。1 行コメントを作成するには、'//' を使用します。パーサーは、コメント
記号と同じ行にあり、コメント記号より後ろに来るものをすべて無視します。
rule "Testing Comments"
when
// this is a single line comment
eval( true ) // this is a comment in the same line of a pattern
then
// this is a comment inside a semantic code block
end
バグを報告する
12.6. 複 数 行 コ メ ン ト の 例
これが複数行コメントの例です。この設定は、セマンティックコードブロックの内部、外部両方にあるテ
キストのブロックをコメントアウトします。
103
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
rule "Test Multi-line Comments"
when
/* this is a multi-line comment
in the left hand side of a rule */
eval( true )
then
/* and this is a multi-line comment
in the right hand side of a rule */
end
バグを報告する
12.7. エ ラ ー メ ッ セ ー ジ
101: No viable alternative
パーサーが決定ポイントに到達したが選択肢を特定できない場合に表示されます。
[ERR 101] Line 3:2 no viable alternative at input 'WHEN'
このメッセージは、不正な場所に設定されているトークン WHEN (ハードキーワード) にパーサー
が遭遇したこと (ルール名が抜けているため) を意味します。
[ERR 101] Line 0:-1 no viable alternative at input '<eof>' in rule simple_rule in pattern
[name]
引用符、アポストロフィ、括弧が正しく挿入されていない (閉じられていない) ことを表します。
102: Mismatched input
現在の入力位置で終わるはずの特定のシンボルを、パーサーが探していることを示します。
[ERR 102] Line 0:-1 mismatched input '<eof>' expecting ')' in rule simple_rule in pattern
[name]
不完全なルールステートメントが原因でこのエラーが発生しています。通常、0:-1 ポジションを
取得すると、パーサーがソースの最後に到達したことを意味します。
103: Failed predicate
False と評価された意味述語をバリデートしています。通常、これらの意味述語はソフトキー
ワードを特定する際に使用します。
104 : T railing semi-colon not allowed
このエラーは、式がセミコロンで完了してはいけない eval 句に関連しています。
105: Early Exit
recognizer が提示のキーワードに最低でも 1 回合致する必要のある文法のサブルールに到達した
にも関わらず、サブルールに合致がありませんでした。
バグを報告する
104
第12章 Using Spreadsheet D ecision Tables
12.8. パ ッ ケ ー ジ
パッケージとは、import や global などルールやその他関連するコンストラクトのコレクションのことで
す。パッケージメンバーは通常、HR ルールなどのように相互に関連しあっています。パッケージは名前
空間を表し、名前空間はルールの集まりごとに一意に保つことが理想です。パッケージ名自体が名前空間
で、ファイルやフォルダーには全く関係ありません。
複数のルールソースから各種ルールを組み立て、これらすべてのルールを格納する最上位のパッケージ設
定を 1 つ持たせることができます (ルール組み立て時)。別の名前で宣言されているパッケージリソース
は、同じものであってもマージすることはできません。しかし、単一の Rulebase には組み込みの複数
パッケージを含めることができます。パッケージ宣言として同じファイル内にパッケージのルールをすべ
て含めるというのが一般的な構造です (これにより完全埋め込み式になります)。
バグを報告する
12.9. Import ス テ ー ト メ ン ト
Import ステートメントは Java の import ステートメントと同様に動作します。ルールで使用するオブジェ
クトに対して完全修飾パスとタイプ名を指定する必要があります。JBoss Rules は同じ名前の Java パッ
ケージとパッケージ java.lang からクラスを自動的にインポートします。
バグを報告する
12.10. Global の 使 用
Global を使用するには、以下を行う必要があります。
1. ルールファイルでグローバル変数を宣言してルールで使用します。以下に例を示します。
global java.util.List myGlobalList;
rule "Using a global"
when
eval( true )
then
myGlobalList.add( "Hello World" );
end
2. ワーキングメモリでグローバル値を設定します。ワーキングメモリにファクトをアサートする前
に、すべてのグローバル値を設定することが推奨されます。以下に例を示します。
List list = new ArrayList();
WorkingMemory wm = rulebase.newStatefulSession();
wm.setGlobal( "myGlobalList", list );
バグを報告する
12.11. From 要 素
from 要素は、グローバルとして Hibernate セッションを指定することができます。また名前付きの
Hibernate クエリからデータをプルすることも可能です。
バグを報告する
105
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
12.12. e-メ ー ル サ ー ビ ス で の Global の 使 用
手順 12.1 タスク
1. ルールエンジンを呼び出す統合コードを開きます。
2. emailService オブジェクトを取得してから、ワーキングメモリに設定します。
3. DRL で、emailService 型のグルーバルがあり、名前を "email" と指定することを宣言します。
4. ルールの結果で、email.sendSMS(number, message) などを使用することができます。
警告
グローバルはルール間でデータを共有するよう設計されておらず、このために使用すべきで
はありません。ルールは常に作業メモリーステータスに対して理由付けし、反応します。し
たがって、データをルール間で渡す場合は、データをファクトとして作業メモリーにアサー
トします。
重要
ルール内部からグローバル値を設定または変更しないでください。常にワーキングメモリー
インターフェースを使用してアプリケーションから値を設定することが推奨されます。
バグを報告する
106
第13章 関数
第 13章 関数
13.1. 関 数
関数 は、通常の Java クラスではなく、ルールソースファイルにセマンティックコードを入れる手段で
す。ルールで関数を使用する主な利点は、1 つの場所ですべてのロジックを保持することができる点で
す。必要に応じて関数を変更することができます。
関数は、ルールの結果 (then) 部分に対してアクションを呼び出す際に最も便利です (特に、その特定のア
クションを繰り返して使用する場合)。
バグを報告する
13.2. 関 数 宣 言 の 例
典型的な関数宣言は、以下のようになります。
function String hello(String name) {
return "Hello "+name+"!";
}
注記
正確には Java の一部でないにも拘らず、function キーワードが使用されている点に注目してく
ださい。この関数へのパラメーターは、メソッドで定義されています。必要がなければパラメー
ターを設定する必要はありません。戻り型は通常のメソッドのように定義されます。
バグを報告する
13.3. 静 的 メ ソ ッ ド を 使 用 す る 関 数 宣 言 の 例
関数宣言の以下の例は、ヘルパークラス (Foo.hello()) の静的メソッドを示しています。JBoss Rules
は、関数 import の使用に対応しているため、以下を入力するために必要なコードは、以下のコードのみで
す。
import function my.package.Foo.hello
バグを報告する
13.4. 関 数 宣 言 呼 び 出 し の 例
関数が定義またはインポートされる方法を問わず、結果内またはセマンティックコードブロック内で名前
で呼び出して関数を使用します。これについて以下に例を示しています。
rule "using a static function"
when
eval( true )
then
System.out.println( hello( "Bob" ) );
end
107
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
バグを報告する
13.5. 型 宣 言
型宣言には、ルールエンジンでの目的が主に 2 つあり、それは 1) 新しい型の宣言を許可することと、2)
型のメタデータの宣言を許可することです。
バグを報告する
13.6. 型 宣 言 の ロ ー ル
表 13.1 型宣言のロール
ロール
説明
新しい型の宣言
JBoss Rules には、ファクトとしてプレーンな
Java オブジェクトが同梱されています。しかし、
ルールエンジンに直接モデルを定義するには、新
しい型を宣言することで定義できます。また、す
でにドメインモデルが構築されている場合にも使
用できますが、理由付けプロセスに主に使用する
追加のエンティティをこのモデルに補足する必要
があります。
メタデータの宣言
ファクトにはメタ情報を関連付けることができま
す。メタ情報の例には、ファクト属性で表現され
ないデータや、そのファクト型の全インスタンス
で一貫しているデータが含まれます。このメタ情
報はランタイム時にエンジンからクエリを受け、
理由付けのプロセスで使用されます。
バグを報告する
13.7. 新 し い 型 の 宣 言
declare のキーワード、その後にフィールドのリスト、キーワード end を使用して、新しい型を宣言し
ます。新しいファクトにはフィールドのリストがなければならず、リストがない場合はエンジンはクラス
パス内に既存のファクトがないか検索して、ファクトが見つからない場合はエラーが出されます。
バグを報告する
13.8. 新 し い フ ァ ク ト 型 の 宣 言 例
以下の例では、Address という新しいファクト型が使用されています。このファクト型には
num ber、streetNam e、city の 3 つの属性が含まれています。各属性には、ユーザーが作成した他の
クラスや以前に宣言されたファクト型といった有効な Java 型などが含まれています。
declare Address
number : int
streetName : String
city : String
end
108
第13章 関数
バグを報告する
13.9. 新 し い フ ァ ク ト 型 の 宣 言 の 追 加 例
このファクト型の宣言では、Person の例を使用しています。dateOfBirth は java.util.Date 型
(Java API) で、address はファクト型 Address です。
declare Person
name : String
dateOfBirth : java.util.Date
address : Address
end
バグを報告する
13.10. Import の 使 用 例
以下の例は、im port 機能を使用して完全修飾クラス名を使用せずに済ませる方法を示しています。
import java.util.Date
declare Person
name : String
dateOfBirth : Date
address : Address
end
バグを報告する
13.11. 生 成 さ れ た Java ク ラ ス
新しいファクト型を宣言すると、JBoss Rules は、ファクト型を表す Java クラスを実装するバイトコー
ドを生成します。生成した Java クラスは、型定義に 1 対 1 の Java Bean マッピングを行います。
バグを報告する
13.12. 生 成 Java ク ラ ス の 例
以下は、Person ファクト型を使用した生成 Java クラスの例です。
109
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
public class Person implements Serializable {
private String name;
private java.util.Date dateOfBirth;
private Address address;
// empty constructor
public Person() {...}
// constructor with all fields
public Person( String name, Date dateOfBirth, Address address ) {...}
// if keys are defined, constructor with keys
public Person( ...keys... ) {...}
// getters and setters
// equals/hashCode
// toString
}
バグを報告する
13.13. ル ー ル で の 宣 言 型 の 使 用 例
生成クラスは単純な Java クラスであるため、他のファクトと同様に透過的にルールで使用できます。
rule "Using a declared Type"
when
$p : Person( name == "Bob" )
then// Insert Mark, who is Bob's manager.
Person mark = new Person();
mark.setName("Mark");
insert( mark );
end
バグを報告する
13.14. メ タ デ ー タ の 宣 言
メタデータは、JBoss Rules ではファクト型、ファクト属性、ルールなど複数の異なるコンストラクショ
ンに割り当てることができます。JBoss Rules は '@' マークを使用してメタデータを導入しますが、常に
以下の形式を使用します。
@metadata_key( metadata_value )
括弧内の metadata_value はオプションです。
バグを報告する
13.15. メ タ デ ー タ 属 性 と の 連 携
JBoss Rules では、任意のメタデータ属性を宣言できますが、一部はエンジンに対して特別な意味を持
ち、一部はランタイム時の問い合わせに利用できます。また、JBoss Rules では、ファクト型とファクト
属性両方に対してメタデータを宣言できます。ファクト型の属性の前に宣言されたメタデータはファクト
型に割り当てられ、属性の後に宣言されたメタデータはその特定の属性に割り当てられます。
110
第13章 関数
バグを報告する
13.16. フ ァ ク ト 型 で の メ タ デ ー タ 属 性 の 宣 言 例
以下は、ファクト型と属性のメタデータ属性を宣言する例です。このファクト型に対して宣言したメタ
データが 2 つ (@ author および @ dateOfCreation) と名前属性に対して定義したメタデータが 2 つ
(@ key および @ m axLength) あります。@ key メタデータには必須の値がないため、括弧や値は省略され
ました。
import java.util.Date
declare Person
@author( Bob )
@dateOfCreation( 01-Feb-2009 )
name : String @key @maxLength( 30 )
dateOfBirth : Date
address : Address
end
バグを報告する
13.17. @position 属 性
@ position 属性は、フィールドの位置を宣言するために使用し、デフォルトで宣言された順番よりも優
先させることができます。これは、パターンでの位置制約に使用されます。
バグを報告する
13.18. @position の 例
以下は、@position 属性の使用例です。
declare Cheese
name : String @position(1)
shop : String @position(2)
price : int @position(0)
end
バグを報告する
13.19. 事 前 定 義 済 み の ク ラ ス レ ベ ル ア ノ テ ー シ ョ ン
111
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 13.2 事前定義済みのクラスレベルアノテーション
アノテーション
説明
@role( <fact | event> )
この属性は、ファクトやイベントにロールを割り
当てる際に使用します。
@typesafe( <boolean> )
デフォルトでは、型安全が有効な状態ですべての
型宣言はコンパイルされています。@ typesafe(
false ) は、型安全ではない評価 (すべての制約
が、MVEL 制約として生成され動的に実行される)
へのフォールバックを許可してこの動作をオー
バーライドする手段を提供します。これは、一般
的な型コレクションや型が混合されているコレク
ションを処理する際に便利です。
@timestamp( <attribute name> )
タイムスタンプを作成します。
@duration( <attribute name> )
属性の実装期間を設定します。
@expires( <time interval> )
属性が失効する時間を定義することができます。
@propertyChangeSupport
Javabean 仕様に定義されているプロパティの変
更のサポートを実装するファクトをアノテーショ
ンで追加できるようになり、エンジン自体がファ
クトプロパティでの変更をリッスンできるように
なっています。
@propertyReactive
型プロパティを反応型にします。
バグを報告する
13.20. @key 属 性 関 数
キー属性として属性を宣言すると、主に生成型に 2 種類の影響があります。
1. この属性はその型のキー識別子として使用されるため、生成クラスは、この型のインスタンスを比
較する際にはこの属性を考慮に入れて、equals() と hashCode() メソッドを実装します。
2. JBoss Rules は、すべてのキー属性をパラメーターとして使用してコンストラクターを生成しま
す。
バグを報告する
13.21. @key 宣 言 の 例
以下は、型に対する @key 宣言の例です。JBoss Rules は、equals() と hashCode() メソッドを生成し、
firstName と lastName 属性をチェックして Person の 2 つのインスタンスがそれぞれ同じであるかを判
断します。ただし、age 属性はチェックしません。firstName と lastName をパラメーターとして取るこ
とでコンストラクターも生成します。
declare Person
firstName : String @key
lastName : String @key
age : int
end
バグを報告する
112
第13章 関数
13.22. キ ー コ ン ス ト ラ ク タ ー で の イ ン ス タ ン ス の 作 成 例
以下は、キーコンストラクターを使用してインスタンスを作成する例です。
Person person = new Person( "John", "Doe" );
バグを報告する
13.23. 位 置 引 数
パターンは型宣言への位置引数をサポートし、@ position 属性で定義されます。
位置引数は、フィールド名を指定する必要がない場合に既知の名前付きフィールドへの位置マッピングを
行います (つまり、Person( name == "mark" ) は Person( "mark"; ) で書き換えることができます)。エン
ジンが位置引数の前のすべてのアイテムを把握するようにするため、セミコロン ';' は重要です。セミコロ
ン ';' で区切ることで、パターンに位置引数と名前引数の両方を併用することができます。バインドされて
いない位置で使用する変数は、フィールドにバインドされその位置にマッピングされます。
バグを報告する
13.24. 位 置 引 数 の 例
以下の例を見てみましょう。
declare Cheese
name : String
shop : String
price : int
end
デフォルトの順番は宣言の順番ですが、@position を使用してオーバーライドできます。
declare Cheese
name : String @position(1)
shop : String @position(2)
price : int @position(0)
end
バグを報告する
13.25. @Position ア ノ テ ー シ ョ ン
@Position アノテーションは、クラスパスの元の POJO にアノテーションをつけるために使用できます。
現在、クラスのフィールドのみアノテーションをつけることができます。クラスの継承に対応しています
が、メソッドのインターフェースには対応していません。
バグを報告する
13.26. パ タ ー ン の 例
これらのパターンの例には、2 つの制約とバインディングが含まれています。セミコロン ';' を使用して、
位置のセクションと名前の引数のセクションを分けています。リテラルのみを使用する変数、リテラル、
式は対応していますが、変数を使用したものには対応していません。
113
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
Cheese(
Cheese(
Cheese(
Cheese(
"stilton", "Cheese
"stilton", "Cheese
"stilton"; shop ==
name == "stilton";
バグを報告する
114
Shop", p; )
Shop"; p : price )
"Cheese Shop", p : price )
shop == "Cheese Shop", p : price )
第14章 その他の宣言
第 14章 その他の宣言
14.1. 既 存 の タ イ プ の メ タ デ ー タ の 宣 言
JBoss Rules では、新しいファクト型に対してメタデータ属性を宣言する場合と同様に既存の型のメタ
データ属性を宣言できます。唯一の相違点は、その宣言にフィールドがないことです。
バグを報告する
14.2. 既 存 型 へ の メ タ デ ー タ の 宣 言 例
以下の例は、既存の型にメタデータを宣言する方法を示しています。
import org.drools.examples.Person
declare Person
@author( Bob )
@dateOfCreation( 01-Feb-2009 )
end
バグを報告する
14.3. 完 全 修 飾 ク ラ ス 名 を 使 用 し た メ タ デ ー タ の 宣 言 例
以下の例は、import アノテーションではなく、完全修飾クラス名を使用してメタデータを宣言する方法を
示しています。
declare org.drools.examples.Person
@author( Bob )
@dateOfCreation( 01-Feb-2009 )
end
バグを報告する
14.4. 宣 言 型 に 対 し て パ ラ メ ー タ ー 化 さ れ た コ ン ス ト ラ ク ト の 例
宣言型:
declare Person
firstName : String @key
lastName : String @key
age : int
end
コンパイラーは、暗黙的に 3 つのコンストラクターを生成します。1 つはパラメーターなし、1 つは
@key フィールドのあるもの、1 つはすべてフィールドのあるものです。
Person() // parameterless constructor
Person( String firstName, String lastName )
Person( String firstName, String lastName, int age )
バグを報告する
115
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
14.5. 型 安 全 で な い ク ラ ス
@typesafe( <boolean>) アノテーションが型宣言に追加されています。デフォルトでは、すべての型宣言
は型安全が有効な状態でコンパイルされています。@typesafe( false ) は、型安全ではない評価 (すべての
制約が、MVEL 制約として生成され動的に実行される) へのフォールバックを許可してこの動作をオー
バーライドする手段を提供します。これは、一般的な型コレクションや型が混合されているコレクション
を処理する際に便利です。
バグを報告する
14.6. ア プ リ ケ ー シ ョ ン コ ー ド か ら の 宣 言 済 み タ イ プ へ の ア ク セ
ス
アプリケーションは時には、宣言型からファクトにアクセスして処理する必要があります。このような場
合、JBoss Rules はアプリケーションが実行する最も一般的なファクト処理に対して簡素化された API を
提供します。宣言ファクトはそのファクトが宣言されたパッケージに所属します。
バグを報告する
14.7. 型 の 宣 言
以下は、型を宣言するプロセスについて例示しています。
package org.drools.examples
import java.util.Date
declare Person
name : String
dateOfBirth : Date
address : Address
end
バグを報告する
14.8. API を 使 用 し て 宣 言 さ れ た フ ァ ク ト 型 を 処 理 す る 例
以下の例では、API で宣言されたファクト型を処理しています。
116
第14章 その他の宣言
// get a reference to a knowledge base with a declared type:
KnowledgeBase kbase = ...
// get the declared FactType
FactType personType = kbase.getFactType( "org.drools.examples",
"Person" );
// handle the type as necessary:
// create instances:
Object bob = personType.newInstance();
// set attributes values
personType.set( bob,
"name",
"Bob" );
personType.set( bob,
"age",
42 );
// insert fact into a session
StatefulKnowledgeSession ksession = ...
ksession.insert( bob );
ksession.fireAllRules();
// read attributes
String name = personType.get( bob, "name" );
int age = personType.get( bob, "age" );
バグを報告する
14.9. 型 宣 言 の extends
型宣言は継承用に "extends" というキーワードをサポートしています。DRL 宣言のサブタイ部で Java で
宣言された型を継承するには、フィールドなしの宣言ステートメントでスーパータイプを繰り返します。
バグを報告する
14.10. 型 宣 言 の extends 例
以下では、extends アノテーションの使用例を示しています。
import org.people.Person
declare Person
end
declare Student extends Person
school : String
end
declare LongTermStudent extends Student
years : int
course : String
end
バグを報告する
117
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
14.11. Trait
Traits により、クラス階層に自然に当てはまらない複数の動的な型をモデル化することができます。trait
は、ランタイム時に個別のオブジェクトに適用できる (最終的に削除) インターフェースです。インター
フェースから trait を作成するには、@ form at(trait) アノテーションを DRL の宣言に追加します。
バグを報告する
14.12. Trait の 例
declare GoldenCustomer
@format(trait)
// fields will map to getters/setters
code
: String
balance : long
discount : int
maxExpense : long
end
T rait をオブジェクトに適用するには、新しい don キーワードを追加します。
when
$c : Customer()
then
GoldenCustomer gc = don( $c, Customer.class );
end
バグを報告する
14.13. コ ア オ ブ ジ ェ ク ト と trait
コアオブジェクトが trait に don すると、プロキシクラスがオンザフライで作成されます (このようなクラ
スは、コア/trait クラスの組み合わせごとに遅延して生成されます)。コアオブジェクトをラップして trait
インターフェースを実装するプロキシインスタンスは、自動的に挿入され、他のルールをアクティブ化す
ることもあります。インターフェースの宣言と使用や実装プロキシをエンジンから解放する利点は、複数
の継承階層がルール記述時に活用できる点です。しかし、コアクラスは静的にこれらのインターフェース
を実装する必要がなく、コアとしてレガシークラスの使用がスムーズに行えるようにします。オブジェク
トは trait を don することができます。ただし、効率の問題で、@T raitable アノテーションを宣言 bean
クラスに追加して、コンパイラーが生成する必要のあるグルーコードの量を減らすことができます。これ
はオプションで、エンジンの動作を変更するわけではありません。
バグを報告する
14.14. @Traitable の 例
以下では、@T raitable アノテーションの使用例を示しています。
118
第14章 その他の宣言
declare Customer
@Traitable
code
: String
balance : long
end
バグを報告する
14.15. Trait で の ル ー ル の 記 述
コアクラスと trait インターフェースは唯一プロキシレベルでつながっています (つまり、trait はコアクラ
スに特別に紐付けられているわけではありません)。つまり、同じ trait を完全に違うオブジェクトに適用
することができます。こういった理由から、trait はコアオブジェクトのフォールドを透過的に公開しない
のです。T rait インターフェースを使用してルールを記述すると、通常通りこのインターフェースのフィー
ルドのみが利用できます。しかし、コアオブジェクトフィールドに該当するインターフェースのフィール
ドはプロキシクラスによりマッピングされます。
バグを報告する
14.16. Trait と ル ー ル の 例
以下の例は、T rait インターフェースがフィールドにマッピングされる例です。
when
$o: OrderItem( $p : price, $code : custCode )
$c: GoldenCustomer( code == $code, $a : balance, $d: discount )
then
$c.setBalance( $a - $p*$d );
end
バグを報告する
14.17. 隠 し フ ィ ー ル ド
隠しフィールドとは、インターフェースに公開されていないコアクラスのフィールドです。
バグを報告する
14.18. 二 部 プ ロ キ シ (two-part proxy)
二部プロキシは、直感的に処理されないソフトフィールドや隠しフィールドを処理するために開発されま
した。内部ではプロキシは、適切なプロキシとラッパーで構成されています。プロキシはインターフェー
スを実装して、ラッパーはコアオブジェクトフィールドを管理し、名前/値マップをソフトフィールドに
マッピングします。プロキシは必要に応じ、コアオブジェクトとマップラッパーの両方を使用してイン
ターフェースを実装します。
バグを報告する
14.19. ラ ッ パ ー
ラッパーは、ルール記述の際により疎性な型指定ができるようになります。しかし、他にも用途がありま
す。ラッパーは、オブジェクトに追加された trait の数に拘らず、ラップするオブジェクトに固有のものと
なります。同じオブジェクトのプロキシはすべて、同じラッパーを共有します。さらに、ラッパーには、
119
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ラップされたオブジェクトに添付されたプロキシすべてに対する後方参照が含まれており、trait がお互い
を効果的に参照できるようにしています。
バグを報告する
14.20. ラ ッ パ ー の 例
以下は、ラッパーの使用例です。
when
$sc : GoldenCustomer( $c : code, // hard getter
$maxExpense : maxExpense > 1000 // soft getter
)
then
$sc.setDiscount( ... ); // soft setter
end
バグを報告する
14.21. isA ア ノ テ ー シ ョ ン を 使 用 し た ラ ッ パ ー 例
以下は、isA アノテーションを使ったラッパーの例です。
$sc : GoldenCustomer( $maxExpense : maxExpense > 1000,
this isA "SeniorCustomer"
)
バグを報告する
14.22. Trait の 削 除
ビジネスロジックでは、ラップされたオブジェクトから trait を削除する必要がある場合もあります。削除
の方法は 2 種類あります。
Logical don
T rait オペレーションを行うことでプロキシを論理的に挿入します。
then
don( $x, // core object
Customer.class, // trait class
true // optional flag for logical insertion
)
shed キーワード
shed キーワードは、指定の引数型に該当するプロキシを削除します。
then
Thing t = shed( $x, GoldenCustomer.class )
このオペレーションは、org.drools.factmodel.traits.T hing インターフェースを実装する別のプロ
キシを返します。ここでは、getFields() と getCore() メソッドが定義されます。内部では、宣言
された trait がすべて生成されこのインターフェースを継承します (指定された他のインター
120
第14章 その他の宣言
フェースだけでなく)。こうすることで、通常はなくなってしまうソフトフィールドを持ったラッ
パーを保存することができます。
バグを報告する
14.23. ル ー ル 構 文 の 例
以下は、ルール作成時に使用すべき構文の例を示しています。
rule "<name>"
<attribute>*
when
<conditional element>*
then
<action>*
end
バグを報告する
14.24. タ イ マ ー 属 性 の 例
以下は、tim er 属性の例です。
timer ( int: <initial delay><repeat interval>? )
timer ( int: 30s )
timer ( int: 30s 5m )
timer ( cron: <cron expression> )
timer ( cron:* 0/15 * * * ? )
バグを報告する
14.25. タ イ マ ー
以下は JBoss Rules で使用可能なタイマーです。
Interval
Interval ("int:" で指定) タイマーは、java.util.T imer オブジェクトのセマンティクスに従います
が、このタイマーは最初の遅延とオプションでその間隔を繰り返します。
Cron
Cron ("cron:" で指定) タイマーは標準の Unix cron 式に従います。
バグを報告する
14.26. Cron タ イ マ ー の 例
以下は Cron タイマーの例です。
121
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
rule "Send SMS every 15 minutes"
timer (cron:* 0/15 * * * ?)
when
$a : Alarm( on == true )
then
channels[ "sms" ].insert( new Sms( $a.mobileNumber, "The alarm is still on" );
end
バグを報告する
14.27. カ レ ン ダ ー
カレンダーは、ルールが発火できるタイミングを制御する際に使用します。JBoss Rules は Quartz カレ
ンダーを使用します。
バグを報告する
14.28. Quartz カ レ ン ダ ー の 例
以下は、Quartz カレンダーの例です。
Calendar weekDayCal = QuartzHelper.quartzCalendarAdapter(org.quartz.Calendar
quartzCal)
バグを報告する
14.29. カ レ ン ダ ー の 登 録
手順 14 .1 タスク
1. StatefulKnowledgeSession を開始します。
2. 以下のコードを使用してカレンダーを登録します。
ksession.getCalendars().set( "weekday", weekDayCal );
3. カレンダーとタイマーを合わせて使用する場合、以下のコードを使用します。
rule "weekdays are high priority"
calendars "weekday"
timer (int:0 1h)
when
Alarm()
then
send( "priority high - we have an alarm” );
end
rule "weekend are low priority"
calendars "weekend"
timer (int:0 4h)
when
Alarm()
then
send( "priority low - we have an alarm” );
end
122
第14章 その他の宣言
バグを報告する
14.30. 左 辺 部 (LHS)
左辺部 (LHS: Left Hand Side) はルールの条件部分に使用される一般的な名前です。LHS は 0 個またそれ
以上の条件要素で構成されます。LHS が空の場合、常に T rue となる条件要素として考慮され、新しい
WorkingMemory セッションが作成されると 1 度だけアクティブ化されます。
バグを報告する
14.31. 条 件 の 要 素
条件要素は、1 つまたは複数のパターンで動作します。最も一般的な条件要素は and で、何も接続されて
いないルールの LHS に複数のパターンがある場合、この条件要素は暗黙的に示されます。
バグを報告する
14.32. 条 件 要 素 な し の ル ー ル の 例
以下は、条件要素がないルールの例です。
rule "no CEs"
when
// empty
then
... // actions (executed once)
end
// The above rule is internally rewritten as:
rule "eval(true)"
when
eval( true )
then
... // actions (executed once)
end
バグを報告する
123
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 15章 パターン
15.1. パ タ ー ン
パターン要素は、最も重要な条件要素です。ワーキングメモリに挿入された各ファクトにマッチする可能
性があります。パターンには制約が含まれており、オプションでパターンのバインディングがあります。
バグを報告する
15.2. パ タ ー ン の 例
以下は、パターンの例です。
rule "2 unconnected patterns"
when
Pattern1()
Pattern2()
then
... // actions
end
// The above rule is internally rewritten as:
rule "2 and connected patterns"
when
Pattern1()
and Pattern2()
then
... // actions
end
注記
and は、主導宣言バインディングを持つことができません。これは、宣言は 1 回に 1 つのファク
トしか参照できないためで、and が満たされると両方のファクトと合致します。
バグを報告する
15.3. パ タ ー ン 一 致
パターンは、指定の型のファクトと照合されます。この型は、ファクトオブジェクトの実際のクラスであ
る必要はありません。パターンは、スーパークラスかインターフェースを参照でき、そこで違った種類の
クラス多数からファクトが合致する可能性があります。制約は括弧内で定義されます。
バグを報告する
15.4. パ タ ー ン の バ イ ン デ ィ ン グ
パターンは、合致するオブジェクトにバインドすることができます。これは、$p などのパターンバイン
ディング変数を使用することで可能です。
バグを報告する
124
第15章 パターン
15.5. 変 数 で バ イ ン ド し た パ タ ー ン の 例
以下は、変数を使用したパターンバインディングの例です。
rule ...
when
$p : Person()
then
System.out.println( "Person " + $p );
end
注記
接頭辞のドル記号 ($) は必須ではありません。
バグを報告する
15.6. 制 約
制約は、true または false を返す式です。たとえば、5 は 6 よりも小さいという制約を指定することが
できます。
バグを報告する
125
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 16章 要素と変数
16.1. Java Bean で の プ ロ パ テ ィ ア ク セ ス (POJO)
bean プロパティは直接使用することができます。bean プロパティは、引数を取らずに何かを返す標準の
Java bean ゲッター (getMyProperty() メソッド (またはプリミティブブール型 isMyProperty()) を
使用して公開します。
JBoss Rules は標準の JDK Introspector クラスを使用して、このマッピングを行いますので、標準の
Java bean 使用に準拠します。
警告
プロパティアクセサーは、ルールに影響を与える可能性のある形でオブジェクトのステータスを変
更してはいけません。ルールエンジンは、呼び出しと呼び出しの間で合致した結果を効率的に
キャッシュして処理を早めます。
バグを報告する
16.2. POJO の 例
以下は、bean プロパティの例です。
Person( age == 50 )
// this is the same as:
Person( getAge() == 50 )
age プロパティ
age プロパティは getAge() ゲッターの代わりに、DRL の age として記述します。
プロパティアクセサー
フィールドのインデックス化にによりパフォーマンスを向上するため、明示的にゲッター
(getAge()) ではなくプロパティアクセス (age) を使用することができます。
バグを報告する
16.3. POJO と の 連 携
手順 16.1 タスク
1. 以下の例を参照してください。
public int getAge() {
Date now = DateUtil.now(); // Do NOT do this
return DateUtil.differenceInYears(now, birthday);
}
2. これを解決するには、現在の日付をラップするファクトをワーキングメモリに挿入して、必要に応
126
第16章 要素と変数
じて fireAllRules 間のファクトを更新します。
バグを報告する
16.4. POJO フ ォ ー ル バ ッ ク
POJO と連携する場合 fallback メソッドが適用されます。プロパティのゲッターが見つからない場合、コ
ンパイラーは、メソッド名にプロパティ名を引数なしで使用して再度ソートします。ネスト化したプロパ
ティもインデックス化されます。
バグを報告する
16.5. フ ォ ー ル バ ッ ク の 例
以下は、フォールバック実装時にどのようになるかを示しています。
Person( age == 50 )
// If Person.getAge() does not exists, this falls back to:
Person( age() == 50 )
以下は、ネスト化したプロパティの場合どのようになるかを示しています。
Person( address.houseNumber == 50 )
// this is the same as:
Person( getAddress().getHouseNumber() == 50 )
警告
ステートフルセッションでは、ワーキングメモリはネスト化された値を認識せず、変化があっても
分からないので、ネスト化されたアクセサーの使用時には注意が必要です。親参照がワーキングメ
モリに挿入される場合は、これらは不変であると考えてください。ネスト化された値を変更する場
合、すべての外部ファクトは更新済みであるとマークする必要があります。上記の例で
は、houseNum ber が変わると、その Address を持つ Person は更新済とマークする必要があ
ります。
バグを報告する
16.6. Java 表 現
127
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 16.1 Java 表現
機能
例
パターンの括弧内にある制約として boolean を
返す Java 表現を使用できます。Java 表現は、プ
ロパティアクセスなど他の表現と合わせて利用す
ることができます。
ロジックや数式のように括弧を使用して、評価優
先度を変更することができます。
Person( age == 50 )
Person( age > 100 && ( age % 10 == 0
) )
Java メソッドを再利用できます。
Person( Math.round( weight / ( height
* height ) ) < 25.0 )
フィールドや値が違う型の場合、型強制が常に試
行されます。不正に型の強制が行われると例外が
送出されます。
Person( age == "10" ) // "10" is
coerced to 10
警告
メソッドはルールに影響を与える可能性のある形式でオブジェクトのステータスを変更してはいけ
ません。LHS のファクトで実行するメソッドは 読み取り専用のメソッドでなければなりません。
警告
(これらのファクトが変更があるたびにワーキングメモリで更新済とマークされない限り) ファクト
のステータスは、ルールの呼び出しと呼び出しの間で変更してはいけません。
Person( System.currentTimeMillis() % 1000 == 0 ) // Do NOT do this
128
第16章 要素と変数
重要
== と != 以外のすべての演算子は、通常の Java セマンティクスを使用します。
== 演算子は null セーフの equals() セマンティクスを持ちます。
// Similar to: java.util.Objects.equals(person.getFirstName(), "John")
// so (because "John" is not null) similar to:
// "John".equals(person.getFirstName())
Person( firstName == "John" )
!= 演算子は null セーフの !equals() セマンティクスを持ちます。
// Similar to: !java.util.Objects.equals(person.getFirstName(), "John")
Person( firstName != "John" )
バグを報告する
16.7. コ ン マ 区 切 り の 演 算 子
コンマ文字 (',') は制約グループを区切るために使用し、この文字には暗黙的で接続的なセマンティクスが
あります。
コンマ演算子は、読み取りがより簡単でエンジンが最適化できるため、上位の制約で使用されます。
バグを報告する
16.8. コ ン マ 区 切 り の 演 算 子 例
以下は、暗黙的かつ接続的なセマンティクスを持つコンマ区切りのシナリオです。
// Person is at least 50 and weighs at least 80 kg
Person( age > 50, weight > 80 )
// Person is at least 50, weighs at least 80 kg and is taller than 2 meter.
Person( age > 50, weight > 80, height > 2 )
注記
コンマ (,) 演算子は、括弧などの複合制約の表現に組み込むことはできません。
バグを報告する
16.9. バ イ ン ド 変 数
JBoss Rules では変数にプロパティをバインドすることができます。こうすることで実行速度が早まりパ
フォーマンスを向上することができます。
バグを報告する
129
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
16.10. バ イ ン ド 変 数 の 例
以下は、変数にバインドされたプロパティの例です。
// 2 persons of the same age
Person( $firstAge : age ) // binding
Person( age == $firstAge ) // constraint expression
注記
後方互換性の理由で、制約バインディングと制約表現を以下のように混合することが可能です (推
奨はされていません)。
// Not recommended
Person( $age : age * 2 < 100 )
// Recommended (separates bindings and constraint expressions)
Person( age * 2 < 100, $age : age )
バグを報告する
16.11. ユ ニ フ ィ ケ ー シ ョ ン
複数のプロパティの間で引数を統一化することができます。位置引数は常にユニフィケーションで処理さ
れ、名前付きの引数にはユニフィケーションの記号':=' が存在します。
バグを報告する
16.12. ユ ニ フ ィ ケ ー シ ョ ン の 例
以下は、2 つの引数を統一化した例です。
Person( $age := age )
Person( $age := age)
バグを報告する
16.13. JBoss Rules の オ プ シ ョ ン と 演 算 子
130
第16章 要素と変数
表 16.2 JBoss Rules のオプションと演算子
オプション
説明
日付リテラル
dd-m m m -yyyy の日付形式はデ
フォルトでサポートされていま
す。drools.dateform at と
いう名前の別の日付形式マスク
を指定してカスタマイズするこ
とができます。さらなる制御が
必要な場合は制限を使用しま
す。
List および Map アクセス
値キー
略記組合せ比較条件
インデックスにより List の値
に直接アクセスできます。
キーにより Map の値に直接アク
セスできます。
これは、& & または || を使用す
ることでフィールドの制限を複
数設置できるようになります。
括弧を使ったグループ化も可能
で、結果的に再帰的構文パター
ンになります。
例
Cheese( bestBefore <
"27-Oct-2009" )
// Same as
childList(0).getAge()
== 18
Person(
childList[0].age == 18
)
// Same as
credentialMap.get("jsmi
th").isValid()
Person(
credentialMap["jsmith"]
.valid )
// Simple abbreviated
combined relation
condition using a
single &&
Person( age > 30 &&< 40
)
// Complex abbreviated
combined relation using
groupings
Person( age ( (> 30 &&<
40) ||
(> 20
&&< 25) ) )
// Mixing abbreviated
combined relation with
constraint connectives
Person( age > 30 &&< 40
|| location == "london"
)
演算子
演算子は、自然な順序でプロパ
ティに対して使用することがで
きます。例えば、日付フィール
ド < は String フィールドの
Person( firstName <
$otherFirstName )
131
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ド < は String フィールドの
前に来ます。アルファベット順
でこちらのほうが早いためで
す。
演算子 matches
演算子 not matches
演算子 contains
演算子 not contains
演算子 memberOf
演算子 not memberOf
演算子 soundslike
132
有効な Java regular
expression とフィールドを照
合します。通常、正規表現は文
字列リテラルですが、有効な正
規表現を解決する変数も使用可
能です。String プロパティに
対してのみ適用されます。null
値に m atches を使用すると、
常に false と評価されます。
この演算子は、文字列が正規表
現に一致しない場合に true を返
します。同じルールは m atches
演算子に適用されます。String
プロパティにのみ適用されま
す。
contains の演算子は、 コレク
ションまたは配列に指定の値が
含まれているかどうか確認する
ために使用しま
す。Collection プロパティに
のみ適用されます。
not contains の演算子は、コ
レクション または配列に指定の
値が含まれていないかどうか確
認するために使用しま
す。Collection プロパティに
のみ適用されます。
演算子 m em berOf は、フィー
ルドがコレクションまたは配列
のメンバーかどうかを確認する
ために使用します。コレクショ
ンは変数でなければなりませ
ん。
演算子 not m em berOf は、
フィールドがコレクションまた
は配列のメンバーでないかどう
かを確認するために使用しま
す。コレクションは変数でなけ
ればなりません。
この演算子は m atches に似て
Person( birthDate <
$otherBirthDate )
Cheese( type matches
"(Buffalo)?
\\S*Mozarella" )
Cheese( type not
matches "(Buffulo)?
\\S*Mozarella" )
CheeseCounter( cheeses
contains "stilton" ) //
contains with a String
literal
CheeseCounter( cheeses
contains $var ) //
contains with a
variable
CheeseCounter( cheeses
not contains "cheddar"
) // not contains with a
String literal
CheeseCounter( cheeses
not contains $var ) //
not contains with a
variable
CheeseCounter( cheese
memberOf
$matureCheeses )
CheeseCounter( cheese
not memberOf
$matureCheeses )
第16章 要素と変数
演算子 soundslike
演算子 str
この演算子は m atches に似て
いますが、指定の値とよく似た
音 (英語の発音) であるかどうか
を確認します。
演算子 str は、String の
フィールドが特定の値で開始、
終了するかどうかを確認するた
めに使用します。文字列の長さ
を確認するためにも使用できま
す。
// match cheese "fubar"
or "foobar"
Cheese( name soundslike
'foobar' )
Message( routingValue
str[startsWith] "R1" )
Message( routingValue
str[endsWith] "R2" )
Message( routingValue
str[length] 17 )
複合値制約
複合値制約は、合致する値が複
数ある可能性がある場合に使用
します。現在 in と not in の
エバリュエーターのみがこれに
対応しています。この演算子の
2 つ目のオペランドは、括弧で
くくりコンマで区切った値のリ
ストでなければなりません。値
は変数、リテラル、戻り値、修
飾 ID として指定できます。いず
れのエバリュエーターも実は
syntactic sugar で、!= および
== の演算子を使用して複数の制
限一覧を内部的に再度記述しま
す。
Person( $cheese :
favouriteCheese )
Cheese( type in (
"stilton", "cheddar",
$cheese ) )
バグを報告する
16.14. 演 算 子 の 優 先 順 位
133
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 16.3 演算子の優先順位
演算子の型
演算子
備考
(ネスト化された) プロパティア
クセス
.
通常の Java セマンティクスでは
ない
List/Map アクセス
[ ]
通常の Java セマンティクスでは
ない
制約バインディング
:
通常の Java セマンティクスでは
ない
乗算
* /%
加算
+-
変換
<<>>>>>
リレーショナル
<><=>=instanceof
同等
==!=
非短絡演算子 AND
&
非短絡演算子の排他的論理和
OR
^
非短絡演算子の包含的論理和
OR
|
論理積 AND
&&
論理和 OR
||
三項演算子
? :
コンマ区切りの AND
,
通常の Java (not) 同等 セマン
ティクスを使用せず、(not) 等
価セマンティクスを使用しま
す。
通常の Java セマンティクスでは
ない
バグを報告する
16.15. 粒 度 の 高 い プ ロ パ テ ィ 変 更 リ ス ナ ー
これは、指定のパターン内に実際に制約またはバインドされたプロパティへの変更に対応するためだけの
パターン合致機能です。これにより、擬似的なオブジェクトの分割を避け、パフォーマンスの向上と再帰
をしやすくします。
注記
デフォルトでは、ルールエンジンの動作が以前のリリースと後方互換を保つために、この機能はオ
フになっています。特定の bean でこの機能をアクティブ化するには、 @propertyReactive のアノ
テーションをつける必要があります。
バグを報告する
16.16. 粒 度 の 高 い プ ロ パ テ ィ 変 更 リ ス ナ ー の 例
DRL の例
134
第16章 要素と変数
declare Person
@propertyReactive
firstName : String
lastName : String
end
Java クラスの例
@PropertyReactive
public static class Person {
private String firstName;
private String lastName;
}
バグを報告する
16.17. 粒 度 の 高 い プ ロ パ テ ィ 変 更 リ ス ナ ー と の 連 携
このリスナーを使用すると、無限の反復を避けるために no-loop 属性を実装する必要がなくなります。エ
ンジンは、ルールの RHS が他のプロパティを変更しつつ、プロパティ上でパターン合致が行われている
ことを認識します。Java クラスでは、呼び出しが実際に他のプロパティを変更したことを通知するため
に、メソッドのアノテーションも可能です。
バグを報告する
16.18. @watch で の パ タ ー ン の 使 用
@watch のアノテーションをパターンにつけることで、プロパティの推論セットを変更してそのパターン
を削除することができます。@watch アノテーションで名前が付けられたプロパティは、自動的に推論さ
れたものに追加されます。! で名前を開始することで、1 つまたは複数のパターンを明示的に除外するこ
とができます。また、パターンの中で使用されているタイプのプロパティすべてをリッスンするまたはし
ないというパターンを指定するには、それぞれワイルドカード * および !* を使用します。
バグを報告する
16.19. @watch の 例
以下は、ルールの LHS の @watch アノテーションです。
// listens for changes on both firstName (inferred) and lastName
Person( firstName == $expectedFirstName ) @watch( lastName )
// listens for all the properties of the Person bean
Person( firstName == $expectedFirstName ) @watch( * )
// listens for changes on lastName and explicitly exclude firstName
Person( firstName == $expectedFirstName ) @watch( lastName, !firstName )
// listens for changes on all the properties except the age one
Person( firstName == $expectedFirstName ) @watch( *, !age )
135
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
注記
@PropertyReactive のアノテーションがついた型を使用して、あるパターンにこのアノテーション
を使用するのは意味がないため、ルールコンパイラーはコンパイルエラーを出します。また、
@watch (例:@watch( firstName, ! firstName ) など) で同じプロパティを重複して使用するとコン
パイルエラーが発生します。
バグを報告する
16.20. @PropertySpecificOption の 使 用
デフォルトで @watch を有効にするか、KnowledgeBuilderConfiguration の on オプションを使用してこ
のアノテーションを利用できなくします。新しい PropertySpecificOption は、以下の 3 つの値を取ること
ができます。
- DISABLED => the feature is turned off and all the other related annotations are
just ignored
- ALLOWED => this is the default behavior: types are not property
reactive unless they are not annotated with @PropertySpecific
- ALWAYS => all types are property reactive by default
バグを報告する
16.21. 基 本 的 な 条 件 要 素
136
第16章 要素と変数
表 16.4 基本的な条件要素
名前
説明
and
条件要素 and は、他の
条件要素を組み合わせ
て論理的に連携しま
す。JBoss Rules は接
頭辞 and、接中辞 and
の両方に対応していま
す。また、括弧で明示
的にグループ化するこ
ともできます。また。
従来の接中辞、接頭辞
and も使用できます。
or
これは、2 つ以上のよく
似たルールを生成する
ショートカットです。
JBoss Rules は接頭辞
or と接中辞 or の両方
に対応しています。従
来の接頭辞、接中辞、
括弧の明示的グループ
化を使用することがで
きます。
例
//infixAnd
Cheese(
cheeseType :
type ) and
Person(
favouriteCheese
== cheeseType )
//infixAnd with
grouping
( Cheese(
cheeseType :
type ) and
( Person(
favouriteCheese
== cheeseType )
or
Person(
favouriteCheese
== cheeseType )
)
//infixOr
Cheese(
cheeseType :
type ) or
Person(
favouriteCheese
== cheeseType )
//infixOr with
grouping
( Cheese(
cheeseType :
type ) or
( Person(
favouriteCheese
== cheeseType )
and
Person(
favouriteCheese
== cheeseType )
)
追加のオプション
接頭辞 and にも対応し
ています。
(and Cheese(
cheeseType :
type )
Person(
favouriteCheese
== cheeseType )
)
LHS の root 要素は暗黙
的な接頭辞 and で、指
定する必要はありませ
ん。
when
Cheese(
cheeseType :
type )
Person(
favouriteCheese
== cheeseType )
then
...
オプションのパターン
バインディングを可能
にします。各パターン
は、eponymous 変数を
使用して、個別にバイ
ンドする必要がありま
す。
pensioner : (
Person( sex ==
"f", age > 60 )
or Person( sex
== "m", age >
65 ) )
137
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
(or Person(
== "f", age
60 )
Person(
== "m", age
65 )
not
exists
これは、absent と指定
されたオブジェクトが
ワーキングメモリに含
まれていないことを確
認します。適用される
条件要素を囲む括弧が
後にくる場合もありま
す (単一のパターンの場
合は括弧を省略するこ
とができます)。
これは、指定のアイテ
ムが存在するかどう
か、ワーキングメモリ
をチェックします。適
用される CE を囲む括
弧がキーワード exists
の後に来る必要があり
ます (単一のパターンの
場合は括弧を省略する
ことができます)。
sex
>
// Brackets are
optional:
not Bus(color ==
"red")
// Brackets are
optional:
not ( Bus(color
== "red",
number == 42) )
// "not" with
nested infix and
- two patterns,
// brackets are
requires:
not ( Bus(color
== "red") and
Bus(color
== "blue") )
exists Bus(color
== "red")
// brackets are
optional:
exists (
Bus(color ==
"red", number
== 42) )
// "exists" with
nested infix
and,
// brackets are
required:
exists (
Bus(color ==
"red") and
Bus(color ==
"blue") )
138
sex
>
第16章 要素と変数
注記
条件要素 or の動作は、フィールド制約の制約や制限に対する接続演算子 || とは違います。エン
ジンは、条件要素 or を解釈することができません。代わりに、or を持つルールは多くのサブ
ルールで再記述されます。このプロセスは最終的に root ノードに or を 1 つと CE ごとにサブルー
ル 1 つ持つルールとなります。サブルールはそれぞれ通常のルールのようにアクティブ化して発火
することができます。これらのサブルールの間での特別な動作や対話はありません。
バグを報告する
16.22. 条 件 要 素 Forall
この要素は、最初のパターンと合致したすべてのファクトが残りのパターンすべてと一致する場合、T rue
と評価されます。これはスコープデリミターです。そのため、以前にバインドされた変数を使用できます
が、条件要素内にバインドされた変数は、要素の外側で使用することができません。
Forall は、他の条件要素内にネスト化することができます。例えば、forall は not 条件要素内で使
用できます。単一パターンにはオプションで括弧が使用されますが、ネスト化された forall では括弧を
必ず使用してください。
バグを報告する
16.23. Forall の 例
T rue に評価
rule "All English buses are red"
when
forall( $bus : Bus( type == 'english')
Bus( this == $bus, color = 'red' ) )
then
// all English buses are red
end
単一パターン forall
rule "All Buses are Red"
when
forall( Bus( color == 'red' ) )
then
// all Bus facts are red
end
複数パターン forall
139
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
rule "all employees have health and dental care programs"
when
forall( $emp : Employee()
HealthCare( employee == $emp )
DentalCare( employee == $emp )
)
then
// all employees have health and dental care
end
ネスト化された forall
rule "not all employees have health and dental care"
when
not ( forall( $emp : Employee()
HealthCare( employee == $emp )
DentalCare( employee == $emp ) )
)
then
// not all employees have health and dental care
end
バグを報告する
16.24. 条 件 要 素 From
条件要素 from は、LHS パターンと照合させる任意のデータのソースを指定できます。これにより、エン
ジンがワーキングメモリではなくデータから推論することができます。このデータソースは、バインド変
数にあるサブフィールドか、メソッド呼び出しの結果のいずれかが可能です。他のアプリケーションのコ
ンポーネントやフレームワークとカスタマイズなしに統合できる、力強い構造となっています。一般的な
例として、hibernate の名前がついたクエリを使用して、データベースからオンデマンドででリトリーブ
したデータと統合ができます。
オブジェクトソースを定義するために使用した表現は、通常の MVEL 構文に準拠しています。そのため、
オブジェクトのプロパティナビゲーションを簡単に使用し、メソッドの呼び出しを行い、マップやコレク
ション要素へアクセスすることができます。
重要
lock-on-active と from を使用すると、ルールが発火されない可能性があります。
この問題に対処するには、複数の方法があります。
前ファクトをワーキングメモリーにアサートできる場合は from の使用をさけるか、制約表現
でネスト化されたオブジェクト参照を使用します (以下参照)。
条件内 (LHS) の最後の文章として modify ブロックで使用するために割り当てられた変数を配置
します。
同じ rule-flow グループでルールのアクティベーションをどのように行うか明示的に管理できる
場合、lock-on-active を使用しないようにします。
バグを報告する
14 0
第16章 要素と変数
16.25. From の 例
パターンでの推論およびバインディング
rule "validate zipcode"
when
Person( $personAddress : address )
Address( zipcode == "23920W") from $personAddress
then
// zip code is ok
end
グラフ表記の使用
rule "validate zipcode"
when
$p : Person( )
$a : Address( zipcode == "23920W") from $p.address
then
// zip code is ok
end
すべてのオブジェクトで反復
rule "apply 10% discount to all items over US$ 100,00 in an order"
when
$order : Order()
$item : OrderItem( value > 100 ) from $order.items
then
// apply discount to $item
end
lock-on-active と併用
rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
when
$p : Person(address.state == "NC" )
then
modify ($p) {} // Assign person to sales region 1 in a modify block
end
rule "Apply a discount to people in the city of Raleigh"
ruleflow-group "test"
lock-on-active true
when
$p : Person(address.city == "Raleigh" )
then
modify ($p) {} //Apply discount to person in a modify block
end
14 1
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
バグを報告する
16.26. 条 件 要 素 collect
条件要素 collect は、ルールが指定のソースかワーキングメモリーから取得したオブジェクトのコレク
ションから推測できるようにします。一階述語論理の用語では、これがカーディナリティ (cardinality) 数
量子です。
java.util.Collection インターフェースを実装してデフォルトの no-arg パブリックコンストラクタ
を提供する具体的なクラスが、collect の結果パターンとなりえます。java.util.Collection を実
装してデフォルトの no-arg パブリックコンストラクタを提供する限り、ArrayList、LinkedList、HashSet
などの Java コレクションや独自のクラスを使用することができます。
collect 条件要素の前にバインドされた変数は、ソースおよび結果パターンの両方のスコープ内である
ため、これらを使用してお使いのソースや結果パターンを制約することができます。collect 内でバイ
ンドされた場合 collect 条件要素外では使用できません。
バグを報告する
16.27. 条 件 要 素 Accumulate
条件要素 accum ulate は collect の機能だけでなく collect で達成できない結果を達成できるた
め、collect がより柔軟で力強くなったものであるといえます。オブジェクトのコレクションで反復し
て、各要素にカスタムのアクションを実行することができます。最終的に、結果オブジェクトを返しま
す。
Accumulate は、事前定義済みの accumulate 関数もインラインのカスタムコードの使用にも対応していま
す。ただし、ルール作成者によるコードの管理が困難でコードの重複が頻繁に起こるため、インラインの
カスタムコードは避けるべきです。Accumulate 関数のほうがテストや再利用も簡単です。
Accumulate 条件要素は、複数の違った構文にも対応しています。推奨されている構文は以下に記載の
トップレベルの accumulate ですが、その他の構文にも後方互換を確保するため対応しています。
バグを報告する
16.28. 条 件 要 素 accumulate の 構 文
トップレベルの accumulate 構文
accumulate( <source pattern>; <functions> [;<constraints>] )
構文の例
14 2
第16章 要素と変数
rule "Raise alarm"
when
$s : Sensor()
accumulate( Reading( sensor == $s, $temp : temperature );
$min : min( $temp ),
$max : max( $temp ),
$avg : average( $temp );
$min < 20, $avg > 70 )
then
// raise the alarm
end
上記の例では、min、max、average が Accumulate 関数で、センサーが読み取ったすべての気温
の値について最小値、最大値、平均値を算出します。
バグを報告する
16.29. 条 件 要 素 accumulate の 関 数
average
min
max
count
sum
collectList
collectSet
これらの一般的な関数は入力値として任意の式を受け取ります。たとえば、注文した全アイテムの平均利
益を計算する場合、以下のように average 関数を使用してルールを記述することができます。
rule "Average profit"
when
$order : Order()
accumulate( OrderItem( order == $order, $cost : cost, $price : price );
$avgProfit : average( 1 - $cost / $price ) )
then
// average profit for $order is $avgProfit
end
バグを報告する
16.30. 条 件 要 素 accumulate お よ び プ ラ ガ ビ リ テ ィ
Accumulate 関数はすべてプラグインができます。つまり、必要であれば、カスタムのドメイン固有の関
数を簡単にエンジンに追加でき、ルールは制限なしにすぐにそれらの関数を使用することができます。新
しい Accumulate 関数を実装するには、org.drools.runtim e.rule.T ypedAccum ulateFunction
インターフェースを実装する Java クラスを作成して設定ファイルに 1 行追加するか、エンジンに新しい
関数を通知するためのシステムプロパティを設定します。
バグを報告する
14 3
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
16.31. 条 件 要 素 accumulate と プ ラ ガ ビ リ テ ィ の 例
Accumulate 関数の実装例として、以下に average 関数の実装を示しています。
14 4
第16章 要素と変数
/**
* An implementation of an accumulator capable of calculating average values
*/
public class AverageAccumulateFunction implements
org.drools.runtime.rule.TypedAccumulateFunction {
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public static class AverageData implements Externalizable {
public int
count = 0;
public double total = 0;
public AverageData() {}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
count
= in.readInt();
total
= in.readDouble();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(count);
out.writeDouble(total);
}
}
/* (non-Javadoc)
* @see org.drools.base.accumulators.AccumulateFunction#createContext()
*/
public Serializable createContext() {
return new AverageData();
}
/* (non-Javadoc)
* @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
*/
public void init(Serializable context) throws Exception {
AverageData data = (AverageData) context;
data.count = 0;
data.total = 0;
}
/* (non-Javadoc)
* @see
org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object,
java.lang.Object)
*/
public void accumulate(Serializable context,
Object value) {
AverageData data = (AverageData) context;
data.count++;
data.total += ((Number) value).doubleValue();
14 5
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
}
/* (non-Javadoc)
* @see
org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object,
java.lang.Object)
*/
public void reverse(Serializable context,
Object value) throws Exception {
AverageData data = (AverageData) context;
data.count--;
data.total -= ((Number) value).doubleValue();
}
/* (non-Javadoc)
* @see
org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
*/
public Object getResult(Serializable context) throws Exception {
AverageData data = (AverageData) context;
return new Double( data.count == 0 ? 0 : data.total / data.count );
}
/* (non-Javadoc)
* @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
*/
public boolean supportsReverse() {
return true;
}
/**
* {@inheritDoc}
*/
public Class< ? > getResultType() {
return Number.class;
}
}
バグを報告する
16.32. 条 件 要 素 accumulate 関 数 の コ ー ド
プラグイン関数のコード (設定ファイルに入力 )
jbossrules.accumulate.function.average =
org.jbossrules.base.accumulators.AverageAccumulateFunction
その他の構文:戻り型を持つ単一関数
14 6
第16章 要素と変数
rule "Apply 10% discount to orders over US$ 100,00"
when
$order : Order()
$total : Number( doubleValue > 100 )
from accumulate( OrderItem( order == $order, $value : value
),
sum( $value ) )
then
# apply discount to $order
end
バグを報告する
16.33. イ ン ラ イ ン 式 の カ ス タ ム コ ー ド を 使 用 し た accumulate
警告
インライン式のカスタムコードと accumulate を使用するのは、これを使うルールの保守とテスト
が困難でコードの再利用ができないなど、複数の理由により適切とは言えません。独自の
accumulate 関数を実装することで、テストが簡素化されます。この形式の accumulate は後方互換
用にサポートされています。
インライン式のカスタムコードを使用した accum ulate 条件要素の一般的な構文は以下のとおりです。
<result pattern>from accumulate(<source pattern>,init(<init
code>),action(<action code>),reverse(<reverse code>),result(<result
expression>) )
以下に、各要素の意味を説明をしています。
<source pattern>: このソースパターンは、エンジンがソースオブジェクトと照合する際の通常のパ
ターンのことです。
<init code>: これは、選択したダイアレクトのコードのセマンティックブロックであり、ソースオブ
ジェクトに対する繰り返し処理が行われる前に各 T uple に対して一度実行されます。
<action code>: これは、選択したダイアレクトのコードのセマンティックブロックであり、各ソースオ
ブジェクトに対して実行されます。
<reverse code>: これは選択したダイアレクトのコードのセマンティックブロック (任意) で、これが指
定されている場合はソースパターンに合致しなくなった各ソースオブジェクトに対して実行されま
す。このコードブロックの目的は、ソースオブジェクトが変更または削除された際にエンジンがデク
リメント演算を実行できるように <action code> ブロックで行われた演算を元に戻すことでこれらの
演算を大幅に改善することです。
<result expression>: これは選択したダイアレクトのセマンティック式で、すべてのソースオブジェク
トに対して繰り返し処理が実行された後に実行されます。
<result pattern>: <result expression> から返されたオブジェクトに対してエンジンが照合を行う通常の
14 7
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
パターンです。合致があると、accum ulate 条件要素は true と評価され、エンジンはルール内の次
の条件要素を評価に進みます。合致がない場合は、accum ulate 条件要素が false と評価され、エン
ジンはそのルールの条件要素の評価を終了します。
バグを報告する
16.34. イ ン ラ イ ン 式 の カ ス タ ム コ ー ド を 使 用 し た accumulate の
例
インライン式のカスタムコード
rule "Apply 10% discount to orders over US$ 100,00"
when
$order : Order()
$total : Number( doubleValue > 100 )
from accumulate( OrderItem( order == $order, $value : value
),
init( double total = 0; ),
action( total += $value; ),
reverse( total -= $value; ),
result( total ) )
then
# apply discount to $order
end
上記の例では、ワーキングメモリーの各 Order に対してエンジンは init code を実行してすべて
の変数をゼロに初期化します。次に、その順番で OrderItem オブジェクトすべてで反復を行
い、それぞれに対してアクションを実行します (この例では、全アイテムの値を合計して total 変
数にします)。全 OrderItem オブジェクトで反復した後、result expression に該当する値を返
します (上記の例では変数 total の値)。最後に、エンジンはその結果と Num ber パターンを照
合して、double value が 100 以上であればルールが発火されます。
カスタムオブジェクトのインスタンス化と生成
rule "Accumulate using custom objects"
when
$person
: Person( $likes : likes )
$cheesery : Cheesery( totalAmount > 100 )
from accumulate( $cheese : Cheese( type == $likes ),
init( Cheesery cheesery = new Cheesery();
),
action( cheesery.addCheese( $cheese ); ),
reverse( cheesery.removeCheese( $cheese
); ),
result( cheesery ) );
then
// do something
end
バグを報告する
16.35. 条 件 要 素 eval
14 8
第16章 要素と変数
条件要素 eval は基本的にキャッチオールの条件要素で、どのセマンティックコードでも実行できます
(プリミティブブール型を返します)。このコードは、ルールの LHS でバインドされた変数とルールパッ
ケージの関数を参照できます。eval を使用しすぎると、ルールの宣言性が減少しエンジンのパフォーマン
スが下がる可能性があります。eval はパターンのどこでも使用できますが、ベストプラクティスはルー
ルの LHS 内で最後の条件要素として追加することです。
eval はインデックス化ができないため、フィールド制約ほど効率的ではありません。しかし、関数が時間
をかけて変化する値を返す場合などフィールド制約では許容できないため、このような場合は eval の使用
が理想的です。
バグを報告する
16.36. 条 件 要 素 eval の 例
以下は eval の使用例です。
p1 : Parameter()
p2 : Parameter()
eval( p1.getList().containsKey( p2.getItem() ) )
p1 : Parameter()
p2 : Parameter()
// call function isValid in the LHS
eval( isValid( p1, p2 ) )
バグを報告する
16.37. 右 辺 部 (RHS)
右辺部 (RHS: Right Hand Side) はルールの結果またはアクション部を指す一般的な名称でうs。RHS の主
な目的は、ワーキングメモリーのデータを挿入、削除、変更することです。この部分には、実行するアク
ションのリストを含める必要があります。ルールの RHS 部は小さく保つことで、宣言性を確保して読み
取りやすくします。
注記
RHS に命令および条件コードが必要な場合、複数のルールに分割します。
バグを報告する
16.38. RHS コ ン ビ ニ エ ン ス メ ソ ッ ド
14 9
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 16.5 RHS コンビニエンスメソッド
名前
説明
update(object, handle);
エンジンにオブジェクトが変更し (LHS で何かに
バインドされているたもの)、ルールを再検討する
必要があると通知します。
update(object);
update() を使用して、ナレッジヘルパーは渡さ
れたオブジェクトのアイデンティティチェックを
して facthandle を検索します (エンジンに挿入す
る Java bean にプロパティ変更リスナーを渡した
場合、オブジェクトの変更があっても update()
を呼び出す必要はありません)。ファクトのフィー
ルド値が変更すると、他のファクトを変更する前
に update を呼び出す必要があります。呼び出さ
ないと、ルールエンジン内のインデックス化に問
題が出てくる可能性があります。modify キーワー
ドを使用することでこの問題を回避できます。
insert(newobject());
独自に作成した新しいオブジェクトをワーキング
メモリーに設定します。
insertLogical(newobject());
挿入に似ていますが、現在ルールを発火している
真理をサポートするファクトがこれ以上ない場
合、オブジェクトは自動的に削除されます
retract(handle);
ワーキングメモリーからオブジェクトを削除しま
す。
バグを報告する
16.39. Drools 変 数 を 使 用 し た コ ン ビ ニ エ ン ス メ ソ ッ ド
drools.halt() の呼び出しはルール実行をすぐに中断します。現在のセッションが
fireUntilHalt() と連携していた時点に制御を戻すために必要です。
insert(Object o)、update(Object o)、retract(Object o) メソッドは drools でも呼び
出されますが、頻繁に使用されるためオブジェクト参照なしで呼び出すことができます。
drools.getWorkingMem ory() は WorkingMem ory オブジェクトを返します。
drools.setFocus( String s) は指定のアジェンダグループにフォーカスを設定します。
ルールの RHS から呼び出された drools.getRule().getNam e() はルールの名前を返します。
drools.getT uple() は現在実行中のルールと合致する T uple を返
し、drools.getActivation() は該当するアクティベーションを行います (これらの呼び出しはロ
ギングやデバッグ目的に便利です)。
バグを報告する
16.40. kcontext 変 数 を 使 用 し た コ ン ビ ニ エ ン ス メ ソ ッ ド
kcontext.getKnowledgeRuntim e().halt() の呼び出しはルールの実行を即座に終了します。
getAgenda() アクセサーは、セッションの Agenda への参照を返し、順番に様々なルールグループ
(アクティベーショングループ、アジェンダグループ、ルールフローグループ) へアクセスできるよう
にします。一般的な例はアジェンダグループの一部をアクティブ化することで、これは長めの呼び出
150
第16章 要素と変数
しで可能になります。
// give focus to the agenda group CleanUp
kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "CleanUp"
).setFocus();
(drools.setFocus( "CleanUp" ) を使用しても同じことが行えます)
クエリを実行するには getQueryResults(String query) を呼び出し、そこで結果を処理するこ
とができます。
イベント管理を処理するメソッドは、ワーキングメモリーやアジェンダに対してイベントリスナーの
追加や削除を可能にします。
getKnowledgeBase() メソッドは KnowledgeBase オブジェクト、システム内の全ナレッジの
バックボーン、現在のセッションの開始元を返します。
setGlobal(...)、getGlobal(...)、getGlobals() で global を管理できます。
getEnvironm ent() メソッドはランタイムの Environm ent を返します。
バグを報告する
16.41. modify ス テ ー ト メ ン ト
表 16.6 modify ステートメント
名前
説明
modify
これにより、fact を更
新する際に構造化した
アプローチを行うこと
ができます。更新オペ
レーションと多くの
セッター呼び出しを組
み合わせてオブジェク
トのフィールドを変更
します。
構文
modify ( <factexpression> )
{<expression> [
,<expression>
]*
}
括弧内の <factexpression> は、ファク
トのオブジェクト参照
を生成する必要があり
ます。ブロック内の表
現リストには、通常の
オブジェクト参照 (自動
的にコンパイラーによ
り先頭に追加) なしに記
述されるように指定の
オブジェクトに対する
セッター呼び出しを含
めなければなりませ
ん。
例
rule "modify
stilton"
when
$stilton :
Cheese(type ==
"stilton")
then
modify(
$stilton ){
setPrice( 20 ),
setAge(
"overripe" )
}
end
バグを報告する
16.42. ク エ リ ー の 例
151
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
注記
結果を返すには、ksession.getQueryResults("nam e") を使用します。"name" にはクエ
リーの名前が入ります。これは、クエリー結果のリストを返すため、クエリーに該当したオブジェ
クトを取得できます。
年齢 30 を超える人に関するクエリー
query "people over the age of 30"
person : Person( age > 30 )
end
年齢が x を超え、 y に住んでいる人に関するクエリー
query "people over the age of x" (int x, String y)
person : Person( age > x, location == y )
end
バグを報告する
16.43. QueryResults の 例
標準の 'for' loop を使用して QueryResults を反復します。各要素は QueryResultsRow で、tuple の各列
にアクセスする際に使用できます。これらの列は、バインドされた宣言名またはインデックスの位置によ
りアクセスできます。
QueryResults results = ksession.getQueryResults( "people over the age of 30" );
System.out.println( "we have " + results.size() + " people over the age of 30" );
System.out.println( "These people are are over 30:" );
for ( QueryResultsRow row : results ) {
Person person = ( Person ) row.get( "person" );
System.out.println( person.getName() + "\n" );
}
バグを報告する
16.44. 他 の ク エ リ を 呼 び 出 す ク エ リ
クエリは他のクエリを呼び出すことができます。オプションのクエリ引数と組み合わせて、抽出クエリス
タイルの後ろ向き連鎖を提供します。また、位置と名前付きを混ぜることも可能ですが、位置が先に来る
必要があります (セミコロンで区切る)。リテラル表現はクエリ引数として渡すことが可能ですが、表現と
変数を混合することはできません。
152
第16章 要素と変数
注記
このプロセスで '?' 記号を使用すると、クエリのみがプルされ、結果が返されると基盤のデータが
変更してもこれ以上結果を受け取ることはありません。
バグを報告する
16.45. 他 の ク エ リ を 呼 び 出 す ク エ リ 例
別のクエリを呼び出すクエリ
declare Location
thing : String
location : String
end
query isContainedIn( String x, String y )
Location(x, y;)
or
( Location(z, y;) and ?isContainedIn(x, z;) )
end
ライブクエリを使用してクエリの結果から変更を徐々に反応的に受け取る例
query isContainedIn( String x, String y )
Location(x, y;)
or
( Location(z, y;) and isContainedIn(x, z;) )
end
rule look when
Person( $l : likes )
isContainedIn( $l, 'office'; )
then
insertLogical( $l 'is in the office' );
end
バグを報告する
16.46. 派 生 ク エ リ の ユ ニ フ ィ ケ ー シ ョ ン
JBoss Rules は、派生クエリのユニフィケーションに対応しています。これは引数はオプションであると
いう意味です。静的なフィールド org.drools.runtime.rule.Variable.v. を使用して引数を指定せずに Java か
らクエリを呼び出すことができます (別の変数インスタンスではなく、'v' を使用する必要があります)。こ
れらは 'out' 引数と呼ばれます。
153
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
注記
クエリ自体は、コンパイル時には引数が in または out のいずれであるかを宣言しません。これ
は、使うたびにランタイム時にだけ定義することができます。
バグを報告する
154
第17章 ドメイン固有言語 (D SL)
第 17章 ドメイン固有言語 (DSL)
17.1. ド メ イ ン 固 有 言 語
ドメイン固有言語 (または DSL) は、問題ドメイン専用のルール言語を作成する手段です。DSL 定義の
セットには、DSL 「センテンス」から DRL コンストラクトへの変換が含まれており、基礎となるすべて
のルール言語とエンジン機能の使用を可能にします。ルールを DSL ルール (DSLR) ファイルで記述可能
で、それが DRL ファイルに変換されます。
DSL and DSLR ファイルはプレーンテキストファイルで、これらのファイルの作成や変更にはどんなテキ
ストエディターでもご利用いただけます。また、DSL の機能が完全に提供されないかもしれませんが、
IDE や Web ベースの BRMS で使用できる DSL と DSLR エディターもあります。
バグを報告する
17.2. DSL の 使 用
DSL は、ドメインオブジェクトやルールエンジンのネイティブ言語やメソッドのモデリングによる技術的
な複雑性からルール作成 (およびルール作成者) を切り離す層として機能します。DSL は実装詳細を見せ
ず、ルールロジックの真意にフォーカスします。DSL のセンテンスは、条件要素やルールで繰り返し使用
される結果アクションの「テンプレート」としての役割も果たすことができます (バリエーションも少し
あり)。このようなバリエーションに対応する手段として提供されるパラメーターを使用して、これらの反
復フレーズにマッピングされるように DSL センテンスを定義することができます。
バグを報告する
17.3. DSL の 例
表 17.1 DSL の例
例
説明
[when]Something is
{colour}=Something(colour=="{colour}"
)
[when] は、式のスコープを示します (ルールの
LHS または RHS に有効であるかどうかなど)。
括弧内のキーワードの後にくる部分は、ルールで
使用する式です。
等号 = の右部分で、式がルール言語にマッピング
されています。この文字列の形式はそのマッピン
グ先にによって異なります (RHS または LHS)。
LHS の場合は、通常の LHS 構文に基づいた用語で
なければならず、RHS の場合は、Java ステート
メントの場合があります。
バグを報告する
17.4. DSL パ ー サ ー の 仕 組 み
DSL パーサーが DSL で記述されたルールファイルの行と DSL 定義の式を照合するときは、必ず文字列操
作の 3 つの手順が実行されます。
DSL は、式に括弧で囲まれた変数名が含まれる場所に表示される文字列の値を抽出します。
155
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
このようなキャプチャーで取得した値は、その名前がマッピングの右辺部 (RHS) に出てくる箇所で常
に補間されます。
補間された文字列は、DSL ルールファイルの行の式全体と照合して合致したものを置き換えます。
注記
例えば、前にくる文字を任意とする'?' を使用することができます。これを使用するリユは、DSL
の自然言語の句にあるバリエーションに対応するためです。しかし、これらの式が正規表現のパ
ターンだとすると、Java のパターン構文のワイルドカード文字はすべて、バックスラッシュ ('\')
が前にきた場合エスケープされなければなりません。
バグを報告する
17.5. DSL コ ン パ イ ラ ー
DSL コンパイラーは DSL ルールファイルを行ごとに変換します。変換する必要がない場合は、キャプ
チャーが文字テキスト (単語または単一文字) で囲まれてることを確認してください。結果、パーサーが行
う照合オペレーションは、行の中からサブストリングを抽出します。以下の例は、引用句が特有な文字と
して使用されています (キャプチャーを囲む文字は補間の際には含まれず内容だけが含まれます)。
バグを報告する
17.6. DSL 構 文 の 例
156
第17章 ドメイン固有言語 (D SL)
表 17.2 DSL 構文の例
名前
説明
引用符
ルールエディターにより入力さ
れる可能性のあるテキストデー
タに対して引用符を使用しま
す。テキストが正しく照合され
るように取得された値を単語で
囲むこともできます。
括弧
正しい構文でマッピングする例
DSL マッピングでは、括弧 "{"
と "}" 変数の定義または参照を囲
むためだけに使用する必要があ
ります。括弧で囲むとキャプ
チャーとなります。表現または
右辺部で置き換えたテキストが
リテラルで処理される必要があ
る場合、これらを、表現または
右辺部の置換テキスト内でリテ
ラルに使用する場合は、バック
スラッシュ ("\") を前に付けてエ
スケープする必要があります。
例
[when]something is
"{color}"=Something(col
or=="{color}")
[when]another {state}
thing=OtherThing(state==
"{state}"
[then]do something= if
(foo) \{ doSomething();
\}
なし
# This is a comment to
be ignored.
[when]There is a person
with name of
"{name}"=Person(name=="
{name}")
[when]Person is at
least {age} years old
and lives in
"{location}"=
Person(age >=
{age},
location=="{location}")
[then]Log
"{message}"=System.out.
println("{message}");
[when]And = and
DSL 展開例
なし
157
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
DSL 展開例
なし
There is a person with
name of "Kitty"
==>
Person(name="Kitty")
Person is at least 42
years old and lives in
"Atlanta"
==> Person(age >=
42, location="Atlanta")
Log "boo"
==>
System.out.println("boo
");
There is a person with
name of "Bob" and
Person is at least 30
years old and lives in
"Utah"
==>
Person(name="Bob") and
Person(age >= 30,
location="Utah")
注記
DSL ルール行からプレーンテキストをキャプチャーし、式で文字列リテラルとして使用する場合
は、マッピングの右辺部で引用符を提供する必要があります。
バグを報告する
17.7. DSL 表 現 の 連 鎖
DSL 表現は、一度に使用できるように一つに連鎖させることができます。終了箇所と開始箇所、パラメー
ターを表すテキストの終了箇所を明確にする必要があります (パラメーター値として行末まですべてのテ
キストが取得されてしまう危険性があります)。DSL 定義ファイルの順番に従い、DSL 表現が次々に試行
されます。合致があると、残りの DSL 表現も検証されます。
バグを報告する
17.8. フ ァ ク ト へ の 制 約 の 追 加
158
第17章 ドメイン固有言語 (D SL)
表 17.3 ファクトへの制約の追加
名前
説明
LHS 条件の表現
DSL の機能は、単純な規定によ
り制約をパターンに追加するこ
とができます。DSL 表現がハイ
フン ("-") で開始されている 場
合、フィールド制約と考えられ
るため、その前にくる最後のパ
ターンの行に追加されます。
例
Cheese(age < 5, price
== 20, type=="stilton",
country=="ch")
この例では、クラス Cheese に
は type、price、age、country の
フィールドがあります。通常の
DRL で LHS の条件を表現するこ
とができるものもあります。
DSL の定義
"-"
この例にある DSL 定義は、3 つ
の DSL 句となり、これらの
フィールドに関する制約の組み
合わせを作成する際に使用する
ことができます。
パーサーは、"-" で始まる行を取
得し、先行のパターンに制約と
して追加します (必要に応じてコ
ンマを挿入します)。
[when]There is a Cheese
with=Cheese()
[when]- age is less
than {age}=age<{age}
[when]- type is
'{type}'=type=='{type}'
[when]- country equal
to
'{country}'=country=='{
country}'
There is a Cheese with
- age is less
than 42
- type is
'stilton'
Cheese(age<42,
type=='stilton')
DSL 句の定義
フィールド制約を処理する様々
な演算子や一般的な表現に対し
て DSL 句を定義すると、DSL の
エントリ数を減らします。
[when][]is less than or
equal to=<=
[when][]is less than=<
[when][]is greater than
or equal to=>=
[when][]is greater
than=>
[when][]is equal to===
[when][]equals===
[when][]There is a
Cheese with=Cheese()
[when][]- {field:\w*} {operator}
{value:\d*}={field} {operator}
{value}
DSL 定義ルール
なし
159
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
DSL 定義ルール
なし
There is a Cheese with
- age is less than
42
- rating is greater
than 50
- type equals
'stilton'
この特定の場合では、"is less
than" の句は < で置き換えら
れ、その行は最終の DSL エント
リと合致します。これによりハ
イフンは削除されますが、最終
結果は先行のパターンに制約と
して追加されます。すべての行
を処理した後の結果 DRL テキス
トは以下のようになります。
Cheese(age<42, rating >
50, type=='stilton')
注記
個別の DSL 式が同じ行を順番に照合する場合は、DSL のエントリの順序が重要です。
バグを報告する
17.9. DSL 開 発 の ヒ ン ト
お使いのアプリケーションが必要とするルールの表現サンプルを記述して、開発しながらテストも行
います。
DRL と DSLR のルールは、データモデルにしたがってエンティティを参照します。このデータモデル
は、ルール内で定義される推測プロセスにより変化するアプリケーションデータを表現します。
データモデルの方が多くがファクトの場合、ルールの記述はより簡単です。
変数部分をパラメーターとしてマークします。こうすることで、便利な DSL エントリに関する信頼で
きる糸口が提供されます。
特定の条件要素やアクションを大なり記号 (">") を行頭につけ DRL 形式で残すことで、この初期設計
段階で条件やアクション関連の実装決定を延期することができます。
新しいルールは、既存の DSL 定義を再利用したり、パラメータを既存の条件または結果エントリに追
加したりすることにより記述できます。
DSL エントリの数は少なくして抑えてください。パラメーターを使用すると、類似のルールパターン
または制約に対して、同じ DSL センテンスを適用できます。
バグを報告する
17.10. DSL お よ び DSLR 参 照
DSL ファイルは行指向形式のテキストファイルです。このエントリは、DRL 構文にしたがい、DSLR ファ
160
第17章 ドメイン固有言語 (D SL)
イルをファイルに変換するために使用されます。
"#" または "//" (前にスペースの有無に拘らず) で始まる行は、コメントとして扱われます。"#/" で始ま
るコメント行は、デバッグオプションを要求する単語がないかスキャンされます。以下を参照してく
ださい。
開始括弧 ("[") で始まる行は、DSL エントリ定義の最初の行とみなされます。
他の任意の行は先行する DSL エントリ定義に追加され、行の最後はスペースで置換されます。
バグを報告する
17.11. DSL エ ン ト リ の 構 成
DSL エントリは、以下の 4 つの部分から構成されます。
スコープの定義。括弧 ("[" および "]") で囲まれた "when" または"condition"、"then" または
"consequence"、"*"、"keyword" の 1 つで記述されています。これは、DSL エントリがルールの条件
や結果 (あるいは条件と結果両方) に対して有効であるかを指定します。"keyword" のスコープは、エ
ントリがグローバルかどうか (DSLR ファイル内のどこでも認識されるか) を指定します。
型の定義。Java クラス名として記述し括弧で括ります。この部分は、次の部分が開始括弧で始まらな
い限りオプションです。括弧内が空白のペアは無効です。
正規表現 (Java) で構成され、任意の数の組み込み変数定義を持ち等号 ("=") で終わる DSL 式。変数定
義は波括弧 ("{" と "}") で囲まれ、変数名と 2 つのオプションの添付 (コロン (":") で区切られます) か
ら構成されます。添付が 1 つの場合は、一致するテキストの正規表現が変数に割り当てられます。添
付が 2 つの場合は、最初の添付が GUI エディターのヒントとなり、2 つ目の添付が正規表現になりま
す。
表現内で文字をリテラルで使用する必要がある場合、正規表現で "magic" 状態文字はすべて、その文
字の前にバックスラッシュ ("\") を付けてエスケープする必要があることに注意してください。
行の区切り等号後の部分は、正規表現に一致する DSLR テキストの置換テキストです。これには変数
参照 (波括弧で囲まれた変数名) を含めることができます。オプションで、変数名の後に感嘆符 ("!") と
変換機能を指定できます。以下を参照してください。
置き換え文字列でリテラルに括弧 ("{" および "}") を使用する必要がある場合は、これらの括弧の前に
バックスラッシュ ("\") を挿入してエスケープする必要があります。
バグを報告する
17.12. DSL 拡 張 の デ バ ッ グ オ プ シ ョ ン
161
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 17.4 DSL 拡張のデバッグオプション
単語
説明
結果
結果となる DRL テキストを行番号とともに出力し
ます。
steps
条件および結果行の各拡張ステップを出力しま
す。
keyword
スコープ "keyword" を持つすべての DSL エントリ
の内部表現をダンプします。
when
スコープ "when" または "*" を持つすべての DSL
エントリの内部表現をダンプします。
then
スコープ "when" または "*" を持つすべての DSL
エントリの内部表現をダンプします。
usage
すべての DSL エントリの使用統計を表示します。
バグを報告する
17.13. DSL 定 義 の 例
以下は、DSL 定義の例です。
# Comment: DSL examples
#/ debug: display result and usage
# keyword definition: replaces "regula" by "rule"
[keyword][]regula=rule
# conditional element: "T" or "t", "a" or "an", convert matched word
[when][][Tt]here is an? {entity:\w+}=
${entity!lc}: {entity!ucfirst} ()
# consequence statement: convert matched word, literal braces
[then][]update {entity:\w+}=modify( ${entity!lc} )\{ \}
バグを報告する
17.14. DSLR フ ァ イ ル の 変 換
DSLR ファイルの変換は以下のように行われます。
1. テキストがメモリに読み込まれます。
2. 各 keyword エントリがテキスト全体に適用されます。キーワード定義からの正規表現を変更するに
は、ホワイトスペースのシーケンスを任意の数のホワイトスペースに一致するパターンで置き換
え、変数定義を定義またはデフォルトの (".*?) で提供された正規表現からのキャプチャーで置き換
えます。次に、変更された正規表現に一致する文字列がDSLR テキストにないか徹底的に検索され
ます。さらに、変数キャプチャーに対応する一致文字列のサブ文字列が抽出され、対応する置換テ
キストの変数参照が置換され、このテキストによって DSLR テキストの一致文字列が置換されま
す。
3. 以下で説明されているように、"when" と "then" 間、および "then" と "end" 間の DSLR テキスト
のセクションは、一律した方法で行ごとに特定され処理されます。
行に対して、行のセクションに関係する各 DSL エントリが、DSL ファイルに現れる順序で取得され
162
第17章 ドメイン固有言語 (D SL)
ます。この正規表現部分は変更されます。ホワイトスペースは任意の数のホワイトスペースと合致
するパターンで置換されます。正規表現の変数定義は、この正規表現のキャプチャーにより置換さ
れます (デフォルト値は ".*?")。結果となる正規表現が行のすべてまたは部分に一致する場合、一致
箇所が適切に変更された置換テキストで置換されます。
置換テキストの変更は、正規表現キャプチャに対応するテキストで変数参照を置換することによっ
て行われます。このテキストは、変数参照で提供される文字列変換機能に従って変更できます。詳
細については以下を参照してください。
同じエントリで定義されない変数を指定する変数参照が存在する場合は、エキスパンダーがその名
前の変数にバインドされた値を置換します (これが現在のルールの先行する行のいずれかで定義さ
れた場合)。
4. 条件の DSLR 行がハイフンで始まる場合、展開された結果は最後の行に挿入されます。これには
(型名の後に括弧のペアがくる) パターンの条件要素を含める必要があります。このペアが空白の場
合、展開された行 (有効な制約を含む) が単に挿入されます。それ以外の場合は、コンマ (",") が前
に挿入されます。
結果の DSLR 行がハイフンで始まる場合、展開された結果が最後の行に挿入されます。これには、
"modify" ステートメントが含まれ、括弧のペア ("{" と "}") で終わります。このペアが空白の場合
は、展開された行 (有効なメソッドコールを含む) が単に挿入されます。それ以外の場合は、コンマ
(",") が前に挿入されます。
注記
現時点では、ハイフンで始まる行を使用して、他の条件要素形式に ("accumulate" など) にテキス
トを挿入することはできません。または、最初の挿入に対してのみ可能です ("eval" など)。
バグを報告する
17.15. 文 字 列 変 換 関 数
表 17.5 文字列変換関数
名前
説明
uc
すべての文字を大文字に変換します。
lc
すべての文字を小文字に変換します。
ucfirst
最初の文字を大文字、他のすべての文字を小文字
に変換します。
num
文字列からすべての数字と "-" を抽出します。元
の文字列の下二桁の前に "." または "," がある場
合、小数点が該当の位置に挿入されます。
a?b/c
文字列を文字列 a と比較し、同じである場合
は、b と置換し、同じでない場合は、c と置換しま
す。ただし、c は別の triplet a、b、c である場合
があるため、構造全体が実際には変換テーブルに
なります。
バグを報告する
17.16. 文 字 列 DSL 変 換 関 数
163
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 17.6 文字列 DSL 変換関数
名前
説明
.dsl
DSL 定義を含むファイルには、
通常拡張子 .dsl が与えられま
す。これは Knowledge Builder
に ResourceT ype.DSL で渡さ
れます。DSL 定義を使用する
ファイルに対して、拡張子
.dslr を使用する必要がありま
す。Knowledge Builder では
ResourceT ype.DSLR が期待
されます。ただし、IDE は、
ルールファイルを適切に認識
し、使用するためにファイルの
拡張子に依存します。
DSL の指定
DSL は、DSL を使用するルール
ファイルよりも前に Knowledge
Builder に渡す必要があります。
DSLR ファイルを解析および展
開する場合、DSL 設定が読み込
まれ、パーサーに提供されま
す。パーサーは DSL 式を「認
識」し、ネイティブのルール言
語式に変換します。
バグを報告する
164
例
# definitions for
conditions
[when][]There is an?
{entity}=${entity!lc}:
{entity!ucfirst}()
[when][]- with an?
{attr} greater than
{amount}={attr} <=
{amount!num}
[when][]- with a {what}
{attr}={attr}
{what!positive?
>0/negative?%lt;0/zero?
==0/ERROR}
KnowledgeBuilder
kBuilder = new
KnowledgeBuilder();
Resource dsl =
ResourceFactory.newClas
sPathResource( dslPath,
getClass() );
kBuilder.add( dsl,
ResourceType.DSL );
Resource dslr =
ResourceFactory.newClas
sPathResource( dslrPath,
getClass() );
kBuilder.add( dslr,
ResourceType.DSLR );
第18章 XML
第 18章 XML
18.1. XML 形 式
警告
XML ルール言語は、Drools 5.x で導入された機能に対応するため更新されていませんが、この機能
は廃止される可能性があります。
オプションとして、JBoss Rules は、DRL の代わりに "ネイティブ" ルール言語をサポートします。これ
により、ユーザーはルールを XML データとして取得および管理できます。非 XML DRL の形式のように、
XML 形式はできるだけ早く内部の "AST " 表現に解析されます (SAX パーサーの使用)。外部の変換ステッ
プは必要ありません。
バグを報告する
18.2. XML ル ー ル の 例
以下は、XML でルールはどのように記述されるかを示しています。
165
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
<?xml version="1.0" encoding="UTF-8"?><package name="com.sample"
xmlns="http://drools.org/drools-5.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://drools.org/drools-5.0 drools-5.0.xsd"><import
name="java.util.HashMap" /><import name="org.drools.*" /><global identifier="x"
type="com.sample.X" /><global identifier="yada" type="com.sample.Yada" /><function
return-type="void" name="myFunc"><parameter identifier="foo" type="Bar"
/><parameter identifier="bada" type="Bing" /><body>
System.out.println("hello world");
</body></function><rule name="simple_rule"><rule-attribute name="salience"
value="10" /><rule-attribute name="no-loop" value="true" /><rule-attribute
name="agenda-group" value="agenda-group" /><rule-attribute name="activation-group"
value="activation-group" /><lhs><pattern identifier="foo2" object-type="Bar" ><orconstraint-connective><and-constraint-connective><field-constraint fieldname="a"><or-restriction-connective><and-restriction-connective><literalrestriction evaluator=">" value="60" /><literal-restriction evaluator="<"
value="70" /></and-restriction-connective><and-restriction-connective><literalrestriction evaluator="<" value="50" /><literal-restriction evaluator=">"
value="55" /></and-restriction-connective></or-restriction-connective></fieldconstraint><field-constraint field-name="a3"><literal-restriction evaluator="=="
value="black" /></field-constraint></and-constraint-connective><and-constraintconnective><field-constraint field-name="a"><literal-restriction evaluator="=="
value="40" /></field-constraint><field-constraint field-name="a3"><literalrestriction evaluator="==" value="pink" /></field-constraint></and-constraintconnective><and-constraint-connective><field-constraint field-name="a"><literalrestriction evaluator="==" value="12"/></field-constraint><field-constraint fieldname="a3"><or-restriction-connective><literal-restriction evaluator="=="
value="yellow"/><literal-restriction evaluator="==" value="blue" /></orrestriction-connective></field-constraint></and-constraint-connective></orconstraint-connective></pattern><not><pattern object-type="Person"><fieldconstraint field-name="likes"><variable-restriction evaluator="=="
identifier="type"/></field-constraint></pattern><exists><pattern objecttype="Person"><field-constraint field-name="likes"><variable-restriction
evaluator="==" identifier="type"/></field-constraint></pattern></exists></not><orconditional-element><pattern identifier="foo3" object-type="Bar" ><fieldconstraint field-name="a"><or-restriction-connective><literal-restriction
evaluator="==" value="3" /><literal-restriction evaluator="==" value="4" /></orrestriction-connective></field-constraint><field-constraint fieldname="a3"><literal-restriction evaluator="==" value="hello" /></fieldconstraint><field-constraint field-name="a4"><literal-restriction evaluator="=="
value="null" /></field-constraint></pattern><pattern identifier="foo4" objecttype="Bar" ><field-binding field-name="a" identifier="a4" /><field-constraint
field-name="a"><literal-restriction evaluator="!=" value="4" /><literalrestriction evaluator="!=" value="5" /></field-constraint></pattern></orconditional-element><pattern identifier="foo5" object-type="Bar" ><fieldconstraint field-name="b"><or-restriction-connective><return-value-restriction
evaluator="==" >a4 + 1</return-value-restriction><variable-restriction
evaluator=">" identifier="a4" /><qualified-identifier-restriction evaluator="==">
org.drools.Bar.BAR_ENUM_VALUE
</qualified-identifier-restriction></or-restrictionconnective></field-constraint></pattern><pattern identifier="foo6" objecttype="Bar" ><field-binding field-name="a" identifier="a4" /><field-constraint
field-name="b"><literal-restriction evaluator="==" value="6" /></fieldconstraint></pattern></lhs><rhs>
if ( a == b ) {
assert( foo3 );
} else {
retract( foo4 );
}
System.out.println( a4 );
166
第18章 XML
</rhs></rule></package>
167
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
168
第18章 XML
バグを報告する
18.3. XML 要 素
表 18.1 XML 要素
名前
説明
global
ルールで参照できる Global オブジェクトを定義し
ます。
function
関数をルールで使用できるようにするための関数
宣言が含まれます。戻り型、一意の名前、パラ
メーターをコードスニペットのボディに指定する
必要があります。
import
ルールで使用する型をインポートします。
バグを報告する
18.4. ル ー ル 要 素 の 詳 細
このルールの例には LHS および RHS (条件と結果) のセクションがあります。RHS はルールがアクティブ
化される際に実行されるセマンティックコードのブロックです。LHS は、条件要素、制約、制限のネスト
化された要素が含まれるため、RHS よりも若干複雑です。
169
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
<rule name="simple_rule"><rule-attribute name="salience" value="10" /><ruleattribute name="no-loop" value="true" /><rule-attribute name="agenda-group"
value="agenda-group" /><rule-attribute name="activation-group" value="activationgroup" /><lhs><pattern identifier="cheese" objecttype="Cheese"><from><accumulate><pattern object-type="Person"></pattern><init>
int total = 0;
</init><action>
total += $cheese.getPrice();
</action><result>
new Integer( total ) );
</result></accumulate></from></pattern><pattern identifier="max"
object-type="Number"><from><accumulate><pattern identifier="cheese" objecttype="Cheese"></pattern><external-function evaluator="max"
expression="$price"/></accumulate></from></pattern></lhs><rhs>
list1.add( $cheese );
</rhs></rule>
バグを報告する
18.5. XML ル ー ル の 要 素
170
第18章 XML
表 18.2 XML ルールの要素
要素
説明
パターン
型 (クラス) を指定し、おそらくそのクラスのイン
スタンスに変数をバインドできるようになりま
す。必要がある制約と制限がパターンオブジェク
トの下にネストされます。Predicate および
Return Value 制約を使用すると、Java 表現を組み
込むことができます。
条件要素 (not、exists、and、or)
DRL のように動作します。以下にネストされた要
素と "and" 要素は論理的に "and" によって結合さ
れます。"or" (さらにネストできます) と同様に、
"Exists" と "Not" はパターンと連携してパターン
の制約を満たすファクトが存在するかしないかを
チェックします。
Eval
ブール値 (単なる断片なのでセミコロンで終了しな
いでください) と評価される限り、有効な Java
コードのスニペットを実行できます。これには、
関数の呼び出しを含めることができます。ルール
エンジンが毎回評価する必要があるため、Eval は
列よりも非効率です。ただし、これは列制約で何
をする必要があるか表現できる場合は "catch all"
機能です。
バグを報告する
18.6. XML と DRL 間 の 自 動 変 換
JBoss Rules には形式間を変換するいくつかのユーティリティクラスが含まれます。これは、ソース形式
からのルールを AST に解析し、適切なターゲット形式に「ダンプ」することで動作します。これによ
り、たとえば、ルールを DRL で記述して XML にエクスポートすることができます。
バグを報告する
18.7. XML と DRL 間 の 自 動 変 換 用 の ク ラ ス
XML と DRL ファイル感で変換を行う際に使用するクラスを以下に示しています。これらの組み合わせを
使用することで、形式間の変換が可能になります (変換がまたに戻すことも可能)。
DrlDumper - DRL のエクスポート
DrlParser - DRL の読み込み
XmlPackageReader - XML の読み込み
注記
DSL は (DSL を使用する DRL から) 保護されませんが、変換は可能です。
バグを報告する
171
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 19章 Java ルールエンジンアプリケーションプログラミング
インターフェース
19.1. JSR94
JSR94 は、JBoss Rules で使用されている API です。単一の API から複数のルールエンジンに対応する
ことができます。JSR94 は、ルール言語自体の処理は行いません。
JSR94 規格は、ルールエンジンの機能に関する「最小限の共通点」を表します。つまり、標準の Knowledge API よりも JSR94 には機能が少なくなっています。JSR94 を使用すると、JBoss Rules の機
能をすべて使用することができません。global を使用して、JSR94 と連携するプロパティマップで
DRL、DSL、XML に対応する必要があります。これにより、移植性のない機能を導入します。
注記
JSR94 にはルール言語がないため、ルールエンジンを切り替える際の複雑性は少ししか解決でき
ないに拘らず、利点はほとんどありません。Red Hat は、Knowledge (JBoss Rules および jBPM)
API 以外でプログラミングを行うように推奨しています。
バグを報告する
19.2. Javax.rules イ ン タ ー フ ェ ー ス
Handle
Handle は、StatefulRuleSession に追加された WorkingMem ory からオブジェクトから取得し
なおすために使用されます。Handle で WorkingMem ory から Object を変更または削除すること
ができます。オブジェクトを変更するには、 StatefulRuleSession から updateObject() を呼
び出します。オブジェクトを削除するには、Handle で rem oveObject() をパラメーターとして呼
び出します。Java Rule Engine API の実装の内部では、カプセル化された Knowledge (Drools および
jBPM) の m odifyObject() および retractObject() メソッドを呼び出します。
ObjectFilter
このインターフェースは RuleSession のオブジェクトをフィルタリングするために使用します。
RuleExecutionSetMetadata
RuleExecutionSetMetadata は RuleExecutionSet の名前、説明、URI を格納するために使用します。
RuleRuntim e
RuleRuntime は RuleSession へのキーで、RuleRuntime は RuleServiceProvider から取得します。
RuleRuntime を取得する場合、RuleSession を開くために createRuleSession() を呼び出します。
RuleRuntime で RuleAdministrator で登録したすべての RuleExecutionSets の URI 一覧を取得できま
す。RuleSession をルールエンジンに対して開くためには、文字列としての URI が必要です。ルール
エンジンは、RuleSession 内の RuleExecutionSet ルールを使用します。
Map は、Global に使用します。Global は (Drools 2.x では) 以前 ApplicationData と呼ばれていまし
た。キーは Global の識別子である必要があり、値は Global として使用するオブジェクトである必要
があります。
RuleSession
RuleSession は、ルールエンジンへ問い合わせする場合に使用するオブジェクトです。
RuleRuntime から RuleSession を取得する場合、StatefulRuleSession か StatelessRuleSession のい
172
第19章 Java ルールエンジンアプリケーションプログラミングインターフェース
ずれかです。
すべてのリソースが解放されるように、release()-メソッドを呼び出します。
StatefulRuleSession
1 回以上ルールエンジンを実行する必要がある場合、StatefulRuleSession を実行します。オブジェク
トのアサート、ルールの実行などができます。
Rule Session にアサートするすべてのオブジェクトに関する Handle を取得します。ワーキングメモ
リのオブジェクトを削除または変更する際に必要になりますので、なくさないようにしてください。
実装内で使用される Drools のワーキングメモリには直接問い合わせできません。これには
RuleSession を使用します。
StatelessRuleSession
StatelessRuleSession は、ルールエンジンへのコンタクト 1 つのみとなります。ルールエンジンへオ
ブジェクトの一覧を渡して、ルールエンジンはオブジェクトすべてをアサートし直後に実行を開始し
ます。結果はオブジェクトの一覧となります。結果一覧の内容はルールにより左右されmさう。ルー
ルがワーキングメモリーからのオブジェクトを変更または削除しない場合、再度追加したオブジェク
トをすべて取得するはずです。
取得前にオブジェクトの結果一覧をフィルタリングする ObjectFilter を使用することができます。
バグを報告する
19.3. Javax.rules ク ラ ス
RuleServiceProvider
RuleServiceProvider により、新しいルールセッションを開くために必要な RuleAdministrator や
RuleRuntime へアクセスできるようにします。RuleServiceProvider を取得するには、
RuleServiceProviderManager.getRuleServiceProvider() を呼び出します。
J2EE 環境では、RuleServiceProvider を JNDI にバインドして、ルックアップを作成してアプリケー
ションすべてに設置することができます。
RuleServiceProviderManager
RuleServiceProvider は頻繁に DriverManager と比較して JDBC で使用します。これは、データベー
スのドライバーを設定するように機能します。
バグを報告する
19.4. Javax.rules の 例 外
ConfigurationException
この例外は、ユーザー設定にエラーがあった場合に送出されます。
InvalidHandleException
この例外は、クライアントが無効な Handle をルールエンジンに渡した場合に送出されます。
InvalidRuleSessionException
InvalidRuleSessionException はメソッドが RuleSession で呼び出され、RuleSession の内部のステー
タスが無効の場合に送出されるはずです。これは、StatefulRuleSession が直列化され外部リソースに
アクセスできなうなってしまった場合に発生する場合があります。この例外は、RuleSession は無効
のステータスであるとのシグナルを送信する際にも使用されます (release メソッドが呼び出された後
に使用しようとし場合など)。 (JCP API ドキュメンテーションより抜粋)
RuleException
javax.rules パッケージの例外クラスすべてに対するベースクラス
173
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
RuleExecutionException
Drools 3 JSR 94 実装ではこの例外は送出されません。
RuleExecutionSetNotFoundException
この例外は、クライアントが RuleExecutionSet を RuleRuntime から依頼して、URI または
RuleExecutionSet が見つからなかった場合に送出されます (JCP API ドキュメンテーションから抜
粋)。
RuleSessionCreateException
この例外は、クライアントが RuleRuntime から RuleSession を依頼して、RuleSession を返すことが
できないといったエラーが発生した場合に送出されます (JCP API ドキュメンテーションから抜粋)。
RuleSessionT ypeUnsupportedException
この例外は、クライアントが RuleSession を依頼してベンダーが指定の型の対応していないか、
RuleExecutionSet 自体が依頼したモードに対応していない場合に送出されます (JCP API ドキュメン
テーションから抜粋)。
バグを報告する
19.5. ル ー ル サ ー ビ ス プ ロ バ イ ダ ー の 使 用
手順 19.1 タスク
1. 以下のコードを使用して JBoss Rules ルールサービスプロバイダーを読み込みます。
Class ruleServiceProviderClass =
Class.forNam e("org.drools.jsr94 .rules.RuleServiceProviderIm pl");
2. 以下のコードを使用して登録します。
RuleServiceProviderManager.registerRuleServiceProvider(
"http://jboss.com /products/rules", ruleServiceProviderClass);
3. 以下のコードを使用して RuleServiceProvider への呼び出しを行います。
RuleServiceProviderManager.getRuleServiceProvider("http://jboss.com /pro
ducts/rules");
4. ルールサービスを停止するには、このコードで登録を解除します。
RuleServiceProviderManager.deregisterRuleServiceProvider(
"http://jboss.com /products/rules");
バグを報告する
19.6. Javax.rules.admin イ ン タ ー フ ェ ー ス
LocalRuleExecutionSetProvider
Rule
RuleAdm inistrator
RuleExecutionSet
RuleExecutionSetProvider
バグを報告する
19.7. Javax.rules.admin の 例 外
174
第19章 Java ルールエンジンアプリケーションプログラミングインターフェース
RuleAdm inistrationException
javax.rules.admin パッケージの administration RuleException クラスすべてに対するベースクラス
(JCP API ドキュメンテーションから抜粋)
RuleExecutionSetCreateException
ルール実行セットを作成する際にエラーが発生すると、この例外が起こります。
RuleExecutionSetDeregistrationException
URI からルール実行セットの登録解除を試行するときにエラーが発生すると、この例外が起こりま
す。
RuleExecutionSetRegisterException
URI からルール実行セットに登録を試行するときにエラーが発生すると、この例外が起こります。
バグを報告する
19.8. RuleServiceProvider
RuleServiceProvider により、RuleRuntime や RuleAdministrator API にアクセスできるようになります。
RuleAdministrator は、RuleExecutionSet オブジェクトの管理に管理 API を提供することで、
RuleExecutionSet の登録が可能でき、RuleRuntime 経由で取得することができるようになります。
バグを報告する
19.9. RuleServiceProviderManager
RuleServiceProviderManager は、RuleServiceProviders の登録や取得を管理します。JBossRules
RuleServiceProvider 実装は、クラスが Class.forName を使用して読み込まれる際に、JDBC ドライバー
とよく似た方法で、自動的に静的ブロックで登録されます。
バグを報告する
19.10. RuleServiceProvider 自 動 登 録 の 例
以下は、自動 RuleServiceProvider の登録例です。
// RuleServiceProviderImpl is registered to "http://drools.org/"
// via a static initialization block
Class.forName("org.drools.jsr94.rules.RuleServiceProviderImpl");
// Get the rule service provider from the provider manager.
RuleServiceProvider ruleServiceProvider =
RuleServiceProviderManager.getRuleServiceProvider("http://drools.org/");
バグを報告する
19.11. LocalRuleExecutionSet を RuleAdministrator API で 登 録
手順 19.2 タスク
1. RuleExecutionSet を作成します。空の LocalRuleExecutionSetProvider または
RuleExecutionSetProvider を返すファクトリメソッドを提供する RuleAdministrator を使用するこ
とで、この作成が可能です。
2. RuleExecutionSet の名前を指定します。
175
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
3. 以下のように RuleExecutionSet を登録します。
// Register the RuleExecutionSet with the RuleAdministrator
String uri = ruleExecutionSet.getName();
ruleAdministrator.registerRuleExecutionSet(uri, ruleExecutionSet, null);
4. LocalRuleExecutionSetProvider を使用して、ストリームなどのような、直列化できないローカル
ソースから RuleExecutionSets を読み込みます。
5. RuleExecutionSetProvider を使用して、DOM 要素やパッケージなどのような、直列化できるソー
スから RuleExecutionSets を読み込みます。"ruleAdministrator.getLocalRuleExecutionSetProvider(
null );" と the "ruleAdministrator.getRuleExecutionSetProvider( null );" (null をパラメーターとして
使用)
6. 以下の例は、LocalRuleExecutionSet の登録の方法の例を示しています。
// Get the RuleAdministration
RuleAdministrator ruleAdministrator =
ruleServiceProvider.getRuleAdministrator();
LocalRuleExecutionSetProvider ruleExecutionSetProvider =
ruleAdministrator.getLocalRuleExecutionSetProvider( null );
// Create a Reader for the drl
URL drlUrl = new URL("http://mydomain.org/sources/myrules.drl");
Reader drlReader = new InputStreamReader( drlUrl.openStream() );
// Create the RuleExecutionSet for the drl
RuleExecutionSet ruleExecutionSet =
ruleExecutionSetProvider.createRuleExecutionSet( drlReader, null );
7. "ruleExecutionSetProvider.createRuleExecutionSet( reader, null )" プロパティを使用して、受信
ソースの設定を提供します。null が指定されると、デフォルトを使用して drl として入力を読み込み
ます。マップで利用可能なキーは "source" と "dsl" です。"source" キーは、値として "drl" か
"xml" を取ります。
8. "source" を "drl" に設定して DRL を読み込み、"xml" を設定して XML ソースを読み込みます。
"xml" は "dsl" key/value 設定を無視します。"dsl" キーは、Reader または String (dsl のコンテン
ツ) を値として取ることができます。以下の dsl の例を参照してください。
// Get the RuleAdministration
RuleAdministration ruleAdministrator =
ruleServiceProvider.getRuleAdministrator();
LocalRuleExecutionSetProvider ruleExecutionSetProvider =
ruleAdministrator.getLocalRuleExecutionSetProvider( null );
// Create a Reader for the drl
URL drlUrl = new URL("http://mydomain.org/sources/myrules.drl");
Reader drlReader = new InputStreamReader( drlUrl.openStream() );
// Create a Reader for the dsl and a put in the properties map
URL dslUrl = new URL("http://mydomain.org/sources/myrules.dsl");
Reader dslReader = new InputStreamReader( dslUrl.openStream() );
Map properties = new HashMap();
properties.put( "source", "drl" );
properties.put( "dsl", dslReader );
// Create the RuleExecutionSet for the drl and dsl
RuleExecutionSet ruleExecutionSet =
ruleExecutionSetProvider.createRuleExecutionSet( reader, properties );
176
第19章 Java ルールエンジンアプリケーションプログラミングインターフェース
バグを報告する
19.12. ス テ ー ト フ ル お よ び ス テ ー ト レ ス RuleSessions
手順 19.3 タスク
1. 以下のように RuleServiceProvider へアクセスしてランタイムを取得します。
RuleRuntime ruleRuntime = ruleServiceProvider.getRuleRuntime();
2. ルールセッションを作成するには、RuleRuntime パブリック定数 2 つの内 1 つを使用します。パブ
リック定数は、"RuleRuntime.ST AT EFUL_SESSION_T YPE" と
"RuleRuntime.ST AT ELESS_SESSION_T YPE" で RuleSession をインスタンス化する
RuleExecutionSet に URI を追加します。
3. オプションで、Global を指定するプロパティにアクセスします。
4. createRuleSession(...) メソッドは、RuleSession インスタンスを返します。StatefulRuleSession
または StatelessRuleSession にキャストする必要があります。
(StatefulRuleSession) session =
ruleRuntime.createRuleSession( uri,
null,
RuleRuntime.STATEFUL_SESSION_TYPE );
session.addObject( new PurchaseOrder( "cheese" ) );
session.executeRules();
5. StatelessRuleSession を使用すると、オプションのフィルター、オブジェクト一覧を渡す
executeRules(List list) を呼び出し、結果のオブジェクトが返されます。
(StatelessRuleSession) session =
ruleRuntime.createRuleSession( uri,
null,
RuleRuntime.STATELESS_SESSION_TYPE );
List list = new ArrayList();
list.add( new PurchaseOrder( "even more cheese" ) );
List results = new ArrayList();
results = session.executeRules( list );
バグを報告する
19.13. JSR94 で の Global の 使 用
JSR94 は、RuleSession ファクトリメソッドに渡されるプロパティマップを使用することで global に対
応しています (移植性がない形で)。Global は DRL または XML ファイルで先に定義する必要があります。
そうでないと、例外が送出されます。キーは、DRL または XML で宣言された識別子を表現し、値は実行
時に使用するインスタンスとなります。
バグを報告する
19.14. JSR94 で Global を 使 用 し た 例
以下は、JSR94 での global の実装例です。
177
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
java.util.List globalList = new java.util.ArrayList( );
java.util.Map map = new java.util.HashMap( );
map.put( "list", globalList );
//Open a stateless Session
StatelessRuleSession srs =
(StatelessRuleSession) runtime.createRuleSession( "SistersRules",
map,
RuleRuntime.STATELESS_SESSION_TYPE );
...
// Persons added to List
// call executeRules( ) giving a List of Objects as parameter
// There are rules which will put Objects in the List
// fetch the list from the map
List list = (java.util.List) map.get("list");
DRL で global "一覧"を宣言するのを忘れないでください。
package SistersRules;
import org.drools.jsr94.rules.Person;
global java.util.List list
rule FindSisters
when
$person1 : Person ( $name1:name )
$person2 : Person ( $name2:name )
eval( $person1.hasSister($person2) )
then
list.add($person1.getName() + " and " + $person2.getName() +" are sisters");
assert( $person1.getName() + " and " + $person2.getName() +" are sisters");
end
バグを報告する
19.15. JSR94 に 関 す る 参 考 資 料
JSR94 に関する詳細情報は、以下のリンクを参照してください。
1. Java Rule Engine API (JSR 94) の公式な JCP 仕様
http://www.jcp.org/en/jsr/detail?id=94
2. Java Rule Engine API ドキュメンテーション
http://www.javarules.org/api_doc/api/index.html
3. T he Logic From T he Bottom Line: An Introduction to T he Drools Project. N. Alex Rupp 著 (2004 年
に T heServiceSide.com で公開)
http://www.theserverside.com/articles/article.tss?l=Drools
4. Getting Started With the Java Rule Engine API (JSR 94): T oward Rule-Based Applications. Dr.
Qusay H. Mahmoud 著 (2005 年 Sun Developer Network で公開)
http://java.sun.com/developer/technicalArticles/J2SE/JavaRule.html
5. Jess and the javax.rules API. Ernest Friedman-Hill 著 (2003 年に T heServerSide.com で公開)
http://www.theserverside.com/articles/article.tss?l=Jess
バグを報告する
178
第20章 JBoss D eveloper Studio
第 20章 JBoss Developer Studio
20.1. ル ー ル の 統 合 開 発 環 境 (IDE)
統合開発環境 (IDE) は、様々な形式でルールを編集、テストする環境を提供してアプリケーションと統合
します。
JBoss Rules IDE は、Eclpse プラグインとして提供され、Eclipse 内からルールを作成、管理して、お使
いのアプリケーションとルールを統合することができます。これはオプションのツールです。JBoss
Rules IDE は Red Hat Developer Studio (以前の JBoss IDE) の一部でもあります。
バグを報告する
20.2. Rules IDE 機 能
Rules IDE には以下の機能が含まれています。
1. テキスト/グラフィカルルールエディター
a. DRL 構文を認識して、コンテンツアシストを提供するエディター (アウトラインビューを含
む)
b. DSL (ドメイン固有言語) の拡張を認識して、コンテンツアシストを提供するエディター
2. RuleFlow グラフィカルエディター
プロセス (ルールフロー) を表す画像グラフを編集できます。その後、RuleFlow がお使いのルール
パッケージに適用され命令形制御を行います。
3. 以下を素早く作成するウィザード
a. "rules" プロジェクト
b. ルールのリソース (DRL ファイル)
c. ドメイン固有言語
d. 決定表
e. ruleflow
4. ドメイン固有言語エディター
a. ユーザーの言語からルール言語へのマッピングを作成して管理します。
5. ルールのバリデーション
a. ルールが入力されると、ルールは背景に構築され可能な場合は問題ビューでエラーが報告さ
れます。
バグを報告する
20.3. JBoss Rules ラ ン タ イ ム
JBoss Rules ランタイムは、JBoss Rules プロジェクト jars の固有リリース 1 つを表現する jar ファイル
の集まりです。ランタイムを作成するには、希望のリリースに IDE をポイントする必要があります。ま
た、プラグイン自体に含まれる最新の JBoss Rules プロジェクト jar に基づき新しいランタイムを作成す
ることもできます。Eclipse ワークスペースに対してデフォルトの JBoss Rules ランタイムを指定する必
要がありますが、個々のプロジェクトはデフォルトを上書きし、そのプロジェクトに対してのみ適切なラ
ンタイムを選択できます。
バグを報告する
179
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
20.4. JBoss Rules ラ ン タ イ ム の 定 義
手順 20.1 タスク
1. JBoss Rules で新しいセッションを作成します。
2. WindowPreferences を選択します。"Preferences" ダイアログが表示されます。
3. このダイアログの左側の JBoss Rules カテゴリーで、"Installed JBoss Rules runtimes" を選択しま
す。右側のパネルに、現在定義されている JBoss Rules ランタイムが表示されるはずです。
4. add ボタンをクリックします。ダイアログが表示され、ランタイムの名前とランタイムがあるファ
イルシステムの場所を入力するように求められます。
5. JBoss Rules Eclipse プラグインからデフォルトの jar ファイルを使用するには、Create a new
Drools 5 runtime ... ボタンをクリックすると新しい JBoss Rules ランタイムが自動的に作成され
ます。ファイルブラウザーが表示され、このランタイムを作成するファイルシステムの場所の入力
が求められます。その後、プラグインが自動的に必要とされる依存関係を指定のフォルダーにコ
ピーします。
6. JBoss Rules プロジェクトの固有のリリースを 1 つ使用するには、必要とされる JBoss Rules ライ
ブラリと依存パッケージが含まれているファイルシステム上にフォルダーを作成します。ランタイ
ムに名前を指定して、必要な jar がすべて含まれているこのフォルダーの場所を選択します。OK を
クリックします。
7. ランタイムは、インストールした JBoss Rules ランタイムのテーブルに表示されます。新しく作成
されたランタイムのチェックボックスをクリックして、デフォルトの JBoss Rules ランタイムに設
定します。デフォルトの JBoss Rules ランタイムは、プロジェクト固有のランタイムが選択されて
いない JBoss Rules プロジェクトすべてのランタイムとして使用されます。
8. デフォルトのランタイムを変更し、デフォルトのランタイムを使用しているすべてのプロジェクト
がクラスパスを適切に更新するには、Eclipse を再起動します。
バグを報告する
20.5. JBoss Rules プ ロ ジ ェ ク ト に 対 す る ラ ン タ イ ム の 選 択
手順 20.2 タスク
1. New JBoss Rules Project ウィザードを使用して、新しい JBoss Rules プロジェクトを作成
します。
2. または、Java オブジェクトを右クリックして Convert to JBoss Rules Project ダイアログ
をクリックすることで、アクションを使用して既存の Java プロジェクトを JBoss Rules プロジェ
クトに変換します。プラグインは、必要な jar すべてをプロジェクトのクラスパスに自動的に追加
します。
3. オプションで、New JBoss Rules Project ウィザードの最後のページで、プロジェクト固有の
ランタイムを選択することができます。Use default JBoss Rules runtim e チェックボック
スのチェックを外して、ドロップダウンボックスで適切なランタイムを選択します。
4. preferences にアクセスして、ランタイムを追加するには、workspace preferences へ移動し
て、Configure workspace settings ... をクリックします。
5. プロジェクトプロパティを開いて JBoss Rules カテゴリを選択することで、いつでも JBoss Rules
プロジェクトのランタイムを変更することができます。Enable project specific
settings チェックボックスにチェックをつけて、ドロップダウンボックスから適切なランタイム
を選択します。
6. Configure workspace settings ... リンクをクリックします。すると、現在インストール
されているランタイムが表示されている workspace preferences が表示されます。メニューを使用
してこのスペースで新しいランタイムを追加します。Enable project specific settings
チェックボックスの選択を解除すると、global preferences で定義されているデフォルトのランタ
180
第20章 JBoss D eveloper Studio
イムを使用します。
バグを報告する
20.6. Rule フ ァ イ ル の 例
新しく作成されたプロジェクトには、src/rules ディレクトリの中にあるサンプルのルールファイル
(Sample.drl)、JBoss Rules エンジンでルールを実行するために使用できるサンプルの Java ファイル
(DroolsT est.java) が含まれています。これは、com.sample パッケージの src/java フォルダーに入ってい
ます。実行時に必要なその他の jar は、JBoss Rules Library と呼ばれる、カスタムのクラスパスコンテ
ナーのクラスパスに追加されます。
バグを報告する
20.7. JBoss Rules Builder
JBoss Rules プラグインは JBoss Rules Builder 機能を Eclipse インスタンスに追加します。つまり、リ
ソースが変更されるとルールを構築してバリデーションを行うプロジェクトでビルダーを有効にすること
ができます。これは、Rule Project ウィザードで自動的に有効になりますが、プロジェクト上で手動で有
効にすることも可能です。ルールを完全にバリデーションするには、当然ながら単体テストでルールを実
行する必要があります。
注記
ファイルに 500 以上のルールが含まれるルールファイルの場合、パフォーマンスが低下する可能
性があります。対処するには、ビルダーをオフにするか、ルールエディターをまだ使用できる .rule
ファイルに大きいルールを設定してください。ただし、バックグラウンドでルールの構築は行われ
ません。
バグを報告する
20.8. 新 規 ル ー ル の 作 成
手順 20.3 タスク
1. 空の .drl テキストファイルを作成します。
2. このファイルにルールをコピーして貼り付けます。
3. 保存して終了します。
4. または、Rules ウィザードを使用してルールを作成します。この際、Ctrl+N を渡すか、ツール
バーから選択します。
5. このウィザードは、ルールリソースを生成するための基本オプションに関する入力を求めます。
ルールファイルを保存するには、ディレクトリ src/rules を通常作成して、適切な名前のサブディレ
クトリを作成します。パッケージ名は必須で、Java のパッケージ名とよく似ています (つまり、関
連のルールをグループ化するための名前空間を設定します)。
6. 適切なオプションを選択して、Finish をクリックします。
結果
展開可能なルールスケルトンが完成しました。
バグを報告する
181
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
20.9. ル ー ル エ デ ィ タ ー
ルールエディターは、ルールマネージャーおよび開発者が変更を加えるところです。ルールエディター
は、Eclipse の通常のテキストエディターのパターンに従います。このルールエディターは、ポップアッ
プコンテンツアシストがあり、Ctrl+Space を押すとポップアップコンテンツアシストが起動します。
ルールエディターは、.drl (または .rule) の拡張子を持つファイル上で動作します。通常、これらには関連
のルールが含まれていますが、同じパッケージの名前空間に入れることでグループ化されている個別ファ
イルにルールを入れることも可能です。これらの DRL ファイルはプレーンテキストファイルです。
バグを報告する
20.10. JBoss ル ー ル ビ ュ ー
ルールの変更時は、以下のビューを切り替えることができます。
ワーキングメモリのビュー
JBoss Rules ワーキングメモリの全要素を表示します。
アジェンダのビュー
アジェンダにあるすべての要素を表示します。アジェンダにあるルールごとに、ルール名および
バインド変数が表示されます。
グローバルデータのビュー
JBoss Rules ワーキングメモリで現在定義されているすべてのグローバルデータを表示します。
監査ビュー
ルールエンジンの実行時にロギングされたイベントを含む監査ログをツリー形式で表示する際に
利用できます。
Rete ビュー
DRL ファイルの現在の Rete Network を表示します。DRL エディターウィンドウの下にある
"Rete T ree" タブをクリックすると表示されます。Rete Network が表示されると、個別のノード
でドラッグアンドドロップを使用して、最適なネットワーク全体図をアレンジすることができま
す。また、長方形をドラッグして複数のノードを選択することもでき、全グループを移動するこ
とが可能です。
注記
Rete ビューは、JBoss Rules Builder がプロジェクトのプロパティに設定されているプロ
ジェクトでのみ機能します。他のプロジェクトは、回避策をお使いください。現在のプロ
ジェクトの横に JBoss Rules プロジェクトを設定し、Rete ビューで確認するライブラリ
と DRL を変換します。DRL エディターの右下のタブをクリックしてから、"Generate
Rete View" をクリックします。
バグを報告する
182
第20章 JBoss D eveloper Studio
20.11. JBoss Rules ビ ュ ー の 使 用
手順 20.4 タスク
1. JBoss Rules ビューを使用するには、ワーキングメモリを呼び出してコードのブレークポイントを
作成します。例えば、workingMem ory.fireAllRules() を呼び出す行は、ブレークを設定す
るには理想的な場所です。
2. デバッガーがジョイント部分で停止した場合、デバッグ変数のビューでワーキングメモリの変数を
選択します。次に、利用可能なビューを使用して、選択したワーキングメモリの詳細を表示しま
す。
バグを報告する
20.12. Show Logical Structure
Show Logical Structure は、JBoss Rules ビューで使用します。ワーキングメモリやアジェンダアイテム
にある要素の論理構造の表示を切り替えることができます。例えば、論理構造により、要素のセットがよ
り明確にわかるように表示できます。
バグを報告する
20.13. 監 査 ロ グ の 作 成
手順 20.5 タスク
1. 監査ログを作成するには、ルールエンジンを実行します。新しい監査ログを作成するかの選択を求
められます。
2. 以下のコードを入力します。
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
// Create a new Knowledge Runtime Logger, that logs to file.
// An event.log file is created in the subdirectory log dir (which must
exist) of the working directory
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(
ksession, "log/event");
ksession.insert(...);
ksession.fireAllRules();
// stop logging
logger.close();
3. 監査ビューの最初のアイコン Open Log アクションをクリックしてログを開き、ファイルを選択し
ます。監査ビューには、ルール実行時にロギングされたイベントすべてが表示されます。
バグを報告する
20.14. 監 査 ビ ュ ー の イ ベ ン ト ア イ コ ン
183
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
表 20.1 監査ビューのイベントアイコン
アイコン
説明
緑色の四角
オブジェクトが挿入されました。
黄色の四角
オブジェクトが更新されました。
赤色の四角
オブジェクトが削除されました。
右向きの矢印
アクティベーションが作成されました。
左向きの矢印
アクティベーションがキャンセルされました。
青色の菱形
アクティベーションが実行されました。
プロセスのアイコン
ルールフローが開始または終了しました。
アクティビティアイコン
Ruleflow-group のアクティベーションおよびアク
ティベーション解除
JBoss Rules アイコン
ルールまたはルールパッケージが追加または削除
されました。
バグを報告する
20.15. 原 因 取 得 の メ ソ ッ ド
アクティベーションの実行時にイベントが発生した場合、そのアクティベーションの実行イベントの子と
して表示されます。以下のイベントが発生すると、原因を取得することができます。
1. イベントを変更または削除するオブジェクトの原因がそのオブジェクトの最後のオブジェクトイベ
ントの場合。オブジェクトがアサートしたイベントまたはそのオブジェクトで最後に変更されたオ
ブジェクトのイベントのいずれかです。
2. アクティベーションがキャンセルまたは実行されたイベントの原因が該当のアクティベーションの
作成イベントの場合。
注記
イベントを選択する場合、原因が監査ビューに緑色で表示されます。アクションを右クリックし
て、"Show Cause" のメニューアイテムを選択します。すると、選択したイベントの原因までスク
ロールされます。
バグを報告する
20.16. DSL エ デ ィ タ ー
DSL エディターは、Language (言語) の Rule Expression (ルール表現) へのマッピングをテーブル形式で
確認できます。Language Expression (言語表現) は、DSL 設定からの Language Expression を提案でき
るように、ルールエディターのコンテンツアシストをフィードします (ルールリソースを編集するために
読み込むと、ルールエディターは DSL 設定を読み込みます)。
バグを報告する
20.17. ル ー ル 言 語 マ ッ ピ ン グ
ルール言語のマッピングは、言語表現がルールエンジンコンパイラーによってどのようにコンパイルされ
るかを定義します。このルールの言語表現の形式は、ルールの条件部分またはアクション部分になるかに
184
第20章 JBoss D eveloper Studio
より左右されます (例えば、RHS では Java のスニペットの可能性があります)。scope アイテムは、表
現が所属するところを指定して、when アイテムは LHS その後に RHS を指定します。さらに * アイテム
はどこでも対応できます。また、キーワードのエイリアスを作成することも可能です。
バグを報告する
20.18. ル ー ル 言 語 マ ッ ピ ン グ で の 作 業
手順 20.6 タスク
1. DSL エディターを開きマッピングタブを選択します。
2. マッピングアイテム (表の中の 1 行) を選択して、表の下のテキストフィールドの表現とマッピング
を確認します。
3. 編集ボタンをクリックまたは押して編集ダイアログを開きます。
4. その他のボタンでマッピングの削除や追加が可能です。使用中にマッピングを削除しないようにし
てください。
バグを報告する
20.19. DSL 変 換 コ ン ポ ー ネ ン ト
表 20.2 DSL 変換コンポーネント
名前
説明
パーサー
パーサーは、DSL のルールテキストを行毎に読み
込み、言語表現の一部と照合します。照合の後、
波括弧 (例: {age}) に囲まれるプレースホルダーに
該当する値がルールソースから抽出されます。
プレースホルダー
該当のルール表現のプレースホルダーは、該当す
る値で置き換えられます。例えば、自然言語表現
は、フィールド age および location を元に型
person のファクトに対して 2 つの制約をマッピン
グします。そして、{age} と {location} の値は、元
のルールテキストから抽出されます。
注記
drl で特定のルールで言語マッピングを使用しない場合、表現の前に > を付けると、コンパイラー
は言語定義にしたがった変換は実施しません。また、ドメイン固有言語はオプションである点にも
注意してください。ルールがコンパイルされると、.dsl ファイルも使用できるようにする必要があ
ります。
バグを報告する
20.20. 大 き な DRL フ ァ イ ル で 作 業 す る 際 の ヒ ン ト
1. 使用する JDK により、Permanent Generation (Perm Gen) の最大サイズを増やすことができます。
この方法は、-XX:MaxPerm Size=###m で Eclipse を起動します。
2. 4000 以上のルールセットは、Permanent Generation を 128Mb 以上に設定する必要があります。
185
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
3. .rule 拡張子を持つファイルにルールを設定します。バックグラウンドのビルダーは、IDE がより
早く実行できるように変更が加えられても毎回コンパイルを試行するわけではありません。
バグを報告する
20.21. ブ レ ー ク ポ イ ン ト の 作 成
手順 20.7 タスク
1. ブレークポイントを作成してルールのデバッグをより簡単に行うには、DRL エディターを開き、使
用する DRL ファイルを読み込みます。
2. ブレークポイントを追加する行で DRL エディターのルーラーをダブルクリックします。ルールのブ
レークポイントは、ルールの結果でのみ作成される点に注目してください。ブレークポイントが作
成できない行でダブルクリックしても何もおこりません。ブレークポイントは、ルーラーをもう一
度ダブルクリックして削除することができます。
3. ルーラーを右クリックします。T oggle breakpoint アクションを含むポップアップメニューが
表示されます。ルールのブレークポイントは、ルールの結果でのみ作成することができる点に注意
してください。ルールのブレークポイントがその行で作成できない場合は、このアクションは自動
的に無効になります。
4. アクションをクリックして、選択した行にブレークポイントを追加します (ブレークポイントがす
でにある場合は削除されます)。
注記
Debug Perspective にはブレークポイントのビューが含まれており、定義されたすべてのブ
レークポイントの参照、そのプロパティの取得、ブレークポイントの有効化/無効化または
削除などを行うために、このビューを使用します。
バグを報告する
20.22. JBoss Rules ア プ リ ケ ー シ ョ ン と し て の デ バ ッ グ
手順 20.8 タスク
1. DRL エディターを開きます。
2. アプリケーションの主要クラスを選択します。
3. 主要クラスの右クリックして、Debug As > サブメニューを選択後、JBoss Rules
Application を選びます。
または、Debug ... メニューアイテムを選択して、デバッグ設定の作成、管理、実行を行う新し
いダイアログを開きます。
4. 左側のツリーの Drools Application アイテムを選択して、New launch configuration
ボタン (ツリーの上にあるツールバーの一番左端のアイコン) をクリックします。これにより新しい
設定が作成されますが、最初に選択した主要クラスをもとにすでに入力されているプロパティもあ
ります。
5. デバッグ設定の名前を意味があるものに変更します。他のプロパティについてはすべてデフォルト
で確定します。
6. 下側の Debug ボタンをクリックしてアプリケーションのデバッグを開始します。デバッグ設定の
定義は一度だけで結構です。JBoss Rules アプリケーションを次に実行する際は、JBoss Rules ツ
リーノードのサブ要素としてツリーの内にある以前に定義された設定を選択して JBoss Rules ボタ
ンをクリックします。Eclipse ツールバーにはショートカットボタンが含まれており、以前の設定の
186
第20章 JBoss D eveloper Studio
1 つをすばやく再実行できるようになっています。
結果
Debug ボタンをクリックすると、アプリケーションは実行を開始して、ブレークポイントに到達すると停
止します。JBoss Rules のブレークポイントに到達すると、毎回該当の DRL ファイルが開きアクティブ
な行がハイライトされます。また、Variables ビューには、全ルールのパラメーターとその値が含まれて
います。デフォルトの Java デバッグアクションを使用して、次に何をするか (再開、終了、中断など) 決
定することができます。デバッグビューを使用して、その時点のワーキングメモリやアジェンダのコンテ
ンツも確認することができます。現在実行中のワーキングメモリが表示されるため、ワーキングメモリを
選択する必要はありません。
バグを報告する
20.23. Rules IDE の 設 定
Rules IDE には、カスタマイズ可能な設定が含まれており、以下のオプションを設定することができま
す。
Java リソースが変更されると、すべてのルールが再度、自動的に解析される
Java クラスが変更されると、すべてのルールが再度構築されるようにトリガーされます。
DRL ファイルの相互参照を可能にする
DRL ファイルのリソースが別のファイルで定義した別のリソースを参照できるようにします。例
えば、別のファイルで宣言した型を使用して、ファイルにルールを設定することができます。こ
のオプションを有効にすると、2 つの違った DRL ファイルで同じリソース (同じパッケージ内で
同じ名前を持つ 2 つのルール) を宣言することができなくなります。
内部の Drools クラスの使用
パブリック API に公開されていない JBoss Rules クラスの使用を許可、却下、警告 (警告の生成)
します。
バグを報告する
187
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 21章 Hello World の例
21.1. HelloWorld の 例 : KnowledgeBase と セ ッ シ ョ ン の 作 成
final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
// this will parse and compile in one step
kbuilder.add(ResourceFactory.newClassPathResource("HelloWorld.drl",
HelloWorldExample.class), ResourceType.DRL);
// Check the builder for errors
if (kbuilder.hasErrors()) {
System.out.println(kbuilder.getErrors().toString());
throw new RuntimeException("Unable to compile \"HelloWorld.drl\".");
}
// get the compiled packages (which are serializable)
final Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();
// add the packages to a KnowledgeBase (deploy the knowledge packages).
final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(pkgs);
final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeBuilder は DRL ソースファイルを、ナレッジベースが消費可能な Package オブジェク
トに変換するために使用します。
add メソッドは Resource インターフェースとリソース型をパラメーターとして取得しま
す。Resource は、様々な場所から DRL ソースファイルを取得するために使用できます。この場
合、ResourceFactory を使用してクラスパスから DRL ファイルを取得しましたが、ディスクファ
イルや URL から取得数rことも可能です。
様々な名前空間の複数パッケージは、同じナレッジベースに追加することができます。
ナレッジベースはパッケージのバリデーションを行いますが、エラー情報へのアクセスは文字列とし
てでしか行えません。そのため、エラー情報のデバッグをするには、KnowledgeBuilder インスタ
ンスで実行する必要があります。
ビルダーにエラーがなくなると、Package コレクションを取得して、KnowledgeBaseFactory か
らの KnowledgeBase をインスタンス化してパッケージコレクションに追加します。
バグを報告する
21.2. HelloWorld の 例 : イ ベ ン ト の ロ ギ ン グ と 監 査
// setup the debug listeners
ksession.addEventListener( new DebugAgendaEventListener() );
ksession.addEventListener( new DebugWorkingMemoryEventListener() );
// setup the audit logging
KnowledgeRuntimeLogger logger =
KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "log/helloworld");
デフォルトのデバッグリスナーは、DebugAgendaEventListener と
DebugWorkingMem oryEventListener の 2 つが提供されています。これらのリスナーは、コン
188
第21章 Hello World の例
ソールウィンドウに表示される System .err ストリームにデバッグイベント情報を出力します。
KnowledgeRuntim eLogger は、グラフィカルビューワーで表示可能な実行監査を提供します。こ
のロガーは、アジェンダとワーキングメモリのリスナー上に構築された特別な実装です。
エンジンの実行が完了すると logger.close() を呼び出す必要があります。
バグを報告する
21.3. HelloWorld の 例 : Message ク ラ ス
public static class Message {
public static final int HELLO
= 0;
public static final int GOODBYE = 1;
private String
private int
...
message;
status;
}
この例で使用されている単一のクラスには、メッセージ (文字列) とステータス (HELLO または
GOODBYE の integer の 1 つ) のフィールド 2 つがあります。
バグを報告する
21.4. HelloWorld の 例 : 実 行
final Message message = new Message();
message.setMessage("Hello World");
message.setStatus(Message.HELLO);
ksession.insert(message);
ksession.fireAllRules();
logger.close();
ksession.dispose();
単一の Message オブジェクトは、メッセージテキスト "Hello World" とステータス HELLO で作成さ
れ、エンジンに挿入されます。この時点で fireAllRules() が実行されます。
ネットワークの評価は、挿入時に行われます。プログラム実行が fireAllRules() メソッド呼び出
しに到達するまでには、エンジンはどのルールが完全に一致して発火可能かすでに把握しています。
注記
Java アプリケーションとしてこの例を実行する方法:
1. Eclipse IDE で org.drools.exam ples.helloworld.HelloWorldExam ple クラスを
開きます。
2. クラスを右クリックして Run as... を選び Java application を選択します。
バグを報告する
189
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
21.5. HelloWorld の 例 : コ ン ソ ー ル ウ ィ ン ド ウ で の System.out
Hello
Goodbye
==>[ActivationCreated(0): rule=Hello World;
tuple=[fid:1:1:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
[ObjectInserted:
handle=[fid:1:1:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]
;
object=org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]
[BeforeActivationFired: rule=Hello World;
tuple=[fid:1:1:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
==>[ActivationCreated(4): rule=Good Bye;
tuple=[fid:1:2:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
[ObjectUpdated:
handle=[fid:1:2:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]
;
old_object=org.drools.examples.helloworld.HelloWorldExample$Message@17cec96;
new_object=org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]
[AfterActivationFired(0): rule=Hello World]
[BeforeActivationFired: rule=Good Bye;
tuple=[fid:1:2:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
[AfterActivationFired(4): rule=Good Bye]
fireAllRules() メソッドでブレークポイントを設置して ksession 変数を選択することで、
"Hello World" ルールははすでにアクティブ化され、アジェンダでパターンに一致する作業は挿入時に
実行されることが分かります。
アプリケーションは、System .out へ移動するよう出力し、デバッグリスナーは System .err へ移
動するよう出力します。
バグを報告する
21.6. HelloWorld の 例 : ル ー ル "Hello World"
rule "Hello World"
dialect "mvel"
when
m : Message( status == Message.HELLO, message : message )
then
System.out.println( message );
modify ( m ) { message = "Goodbye cruel world",
status = Message.GOODBYE };
end
ルールの LHS (when の後ろ) 部では、ステータスが Message.HELLO のワーキングメモリに挿入され
190
第21章 Hello World の例
た Message オブジェクトごとにルールがアクティベートされると記述されています。
また、変数バインドが 2 つ作成されています。m essage 変数は m essage 属性に、m 変数は合致した
Message オブジェクト自体にバインドされています。
ルールの RHS (then の後ろ) または結果部では、ルールの属性 dialect が宣言しているように、
MVEL 式言語を使用して記述されています。
System .out に m essage バインド変数の内容を出力した後、ルールは m essage の値と m にバイン
ドされている Message オブジェクトの status 属性を変更します。
MVEL の m odify ステートメントは、ブロックの最後で自動的に変更を通知するエンジンを使用し
て、1 つのステートメントに代入ブロックを適用することができます。
バグを報告する
21.7. HelloWorld の 例 : "Debug as..." オ プ シ ョ ン の 使 用
手順 21.1 タスク
1. このデバッグオプションを使用するにはお使いの Eclipse IDE の
org.drools.exam ples.HelloWorld クラスを開きます。
2. このクラスを右クリックして「Debug as...」を選択し、「Drools application」を選びます。その
ルールとルールの場所の情報が表示されます。
バグを報告する
21.8. HelloWorld の 例 : ル ー ル "Good Bye"
rule "Good Bye"
dialect "java"
when
Message( status == Message.GOODBYE, message : message )
then
System.out.println( message );
end
"java" 方言を指定する "Good Bye" ルールは、ステータスが Message.GOODBYE の Message オブ
ジェクトと照合すること以外は、"Hello World" ルールとよく似ています。
バグを報告する
191
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 22章 Salience ステータスの例
22.1. Salience ス テ ー タ ス の 例 : State ク ラ ス の 例
public class State {
public static final int NOTRUN
= 0;
public static final int FINISHED = 1;
private final PropertyChangeSupport changes =
new PropertyChangeSupport( this );
private String name;
private int
state;
... setters and getters go here...
}
各 State クラスには、名前と現在のステータスのフィールドがあります
(org.drools.exam ples.state.State クラス参照)。各オブジェクトで考えられる 2 つのステー
タスは NOT RUN と FINISHED です。
バグを報告する
22.2. Salience ス テ ー タ ス の 例 : 実 行
State
State
State
final
a = new
b = new
c = new
State d
State( "A" );
State( "B" );
State( "C" );
= new State( "D" );
// By setting dynamic to TRUE, Drools will use JavaBean
// PropertyChangeListeners so you don't have to call modify or update().
boolean dynamic = true;
session.insert(
session.insert(
session.insert(
session.insert(
a,
b,
c,
d,
dynamic
dynamic
dynamic
dynamic
);
);
);
);
session.fireAllRules();
session.dispose(); // Stateful rule session must always be disposed when finished
各インスタンスは順番にセッションにアサートされ、その後に fireAllRules() が呼び出されま
す。
バグを報告する
22.3. Salience ス テ ー タ ス の 例 : ア プ リ ケ ー シ ョ ン の 実 行
手順 22.1 タスク
1. Eclipse IDE の org.drools.exam ples.state.StateExam pleUsingSalience クラスを開
きます。
192
第22章 Salience ステータスの例
2. このクラスの上で右クリックして Run as... を選び Java application を選択します。以下の
出力が表示されます。
A
B
C
D
finished
finished
finished
finished
バグを報告する
22.4. Salience ス テ ー タ ス の 例 : オ ペ レ ー シ ョ ン の あ る 監 査 ロ ギ ン
グを使用
手順 22.2 タスク
1. オペレーションが生成した監査ログを表示するには、IDE を開き Window をクリックしてから
Show View を選び、その後、Other...、Drools、Audit View の順に選択します。
2. "Audit View" で Open Log ボタンをクリックして <drools-exam ples-dir>/log/state.log
ファイルを選択します。
バグを報告する
22.5. Salience ス テ ー タ ス の 例 : ル ー ル "Bootstrap"
rule Bootstrap
when
a : State(name == "A", state == State.NOTRUN )
then
System.out.println(a.getName() + " finished" );
a.setState( State.FINISHED );
end
結果
rule "A to B"
when
State(name == "A", state == State.FINISHED )
b : State(name == "B", state == State.NOTRUN )
then
System.out.println(b.getName() + " finished" );
b.setState( State.FINISHED );
end
全アクションと該当の変更がワーキングメモリに表示されます。
ステータス NOT RUN のステータスオブジェクト A のアサーションにより、 Bootstrap ルールがアク
ティベートされますが、その他の State オブジェクトのアサーションからの影響はすぐにはありませ
ん。
ルール Bootstrap を実行すると、ステータスが A から FINISHED に変更され、ルール "A to B" をア
クティベートします。
バグを報告する
193
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
22.6. Salience ス テ ー タ ス の 例 : ル ー ル "B to C"
rule "B to C"
salience 10
when
State(name == "B", state == State.FINISHED )
c : State(name == "C", state == State.NOTRUN )
then
System.out.println(c.getName() + " finished" );
c.setState( State.FINISHED );
end
競合解決戦略は、エンジンのアジェンダがどのルールを発火するか決定できるようにします。
ルール "B to C" の salience 値が高いため (10 とデフォルトの salience 値 0)、先に発火されオブジェ
クト C をステータス FINISHED に変更します。
アジェンダビューは、ルール内にデバッグポイントを設置しアジェンダビューを開いた状態で、ジェ
ンダーのステータスを調査するために使用することもできます。
バグを報告する
22.7. Salience ス テ ー タ ス の 例 : ル ー ル "B to D"
rule "B to D"
when
State(name == "B", state == State.FINISHED )
d : State(name == "D", state == State.NOTRUN )
then
System.out.println(d.getName() + " finished" );
d.setState( State.FINISHED );
end
ルール "B to D" は最後に発火され、オブジェクト D をステータス FINISHED に変更します。
実行するルールがないためエンジンが停止します。
バグを報告する
22.8. Salience ス テ ー タ ス の 例 : 動 的 フ ァ ク ト の 挿 入
// By setting dynamic to TRUE, JBoss Rules will use JavaBean
// PropertyChangeListeners so you don't have to call modify or update().
final boolean dynamic = true;
session.insert( fact, dynamic );
エンジンがファクトのプロパティを参照して反応するには、アプリケーションがエンジンに対して変
更があったことを通知する必要があります。これは、m odify ステートメントを使用してルールで明
示するか、エンジンにファクトが JavaBeans specification で定義されているように
PropertyChangeSupport を実装していると暗黙的に通知することで実行できます。
上記の例では、ルールに m odify ステートメントを明示しないでもいいよう
に、PropertyChangeSupport の使用方法を紹介しています。
org.drools.exam ple.State クラスと同じように、ファクトが PropertyChangeSupport を
194
第22章 Salience ステータスの例
実装するようにします。
バグを報告する
22.9. Salience ス テ ー タ ス の 例 : PropertyChangeSupport を 持 つ
セッター
public void setState(final int newState) {
int oldState = this.state;
this.state = newState;
this.changes.firePropertyChange( "state",
oldState,
newState );
}
org.drools.exam ples クラス内の state のセッター
PropertyChangeListener オブジェクトを使用する場合、各セッターは通知用に追加でコードを
実装する必要があります。
バグを報告する
22.10. Salience ス テ ー タ ス の 例 : グ ル ー プ ル ー ル "B to C"
rule "B to C"
agenda-group "B to C"
auto-focus true
when
State(name == "B", state == State.FINISHED )
c : State(name == "C", state == State.NOTRUN )
then
System.out.println(c.getName() + " finished" );
c.setState( State.FINISHED );
kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "B to D"
).setFocus();
end
結果
rule "B to D"
agenda-group "B to D"
when
State(name == "B", state == State.FINISHED )
d : State(name == "D", state == State.NOTRUN )
then
System.out.println(d.getName() + " finished" );
d.setState( State.FINISHED );
end
デフォルトでは、アジェンダグループ "MAIN" にすべてのルールが入っています。
"agenda-group" 属性により、ルールに対して別のアジェンダグループを指定することができます。最
初は、ワーキングメモリのフォーカスは "MAIN" に置かれています。
グループのルールは、グループにフォーカスが当たっているときのみ発火されます。setFocus() メ
ソッドか、ルール属性 auto-focus を使用することで可能になります。
195
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
auto-focus は、ルールが合致してアクティベートされた場合に、ルールが自動的にアジェンダグ
ループにフォーカスを設定するという意味です。"B to D" の前に "B to C" を発火できるようにするの
は、この "auto-focus" なのです。
ルール "B to C" がアジェンダグループ "B to D" で setFocus() を呼び出して、アクティブなルール
を発火するため、ルール "B to D" を発火させることができます。
バグを報告する
22.11. Salience ス テ ー タ ス の 例 : グ ル ー プ ル ー ル "B to D"
rule "B to D"
agenda-group "B to D"
when
State(name == "B", state == State.FINISHED )
d : State(name == "D", state == State.NOTRUN )
then
System.out.println(d.getName() + " finished" );
d.setState( State.FINISHED );
end
バグを報告する
22.12. Salience ス テ ー タ ス の 例 : グ ル ー プ ル ー ル "D to E"
rule "D to E"
when
State(name == "D", state == State.FINISHED )
e : State(name == "E", state == State.NOTRUN )
then
System.out.println(e.getName() + " finished" );
e.setState( State.FINISHED );
end
この例では、以下のような出力が表示されるはずです。
A
B
C
D
E
finished
finished
finished
finished
finished
StateExam pleWithDynam icRules は、別のルールをルールベース (fireAllRules() の後ろ)
に追加します。
バグを報告する
196
第23章 フィボナッチの例
第 23章 フィボナッチの例
23.1. フ ィ ボ ナ ッ チ の 例 : ク ラ ス
public static class Fibonacci {
private int sequence;
private long value;
public Fibonacci( final int sequence ) {
this.sequence = sequence;
this.value = -1;
}
... setters and getters go here...
}
Sequence フィールドは、フィボナッチ数の順番におけるオブジェクトの位置を指定するために使用し
ます。
Value フィールドは、その順位のフィボナッチオブジェクトの値を表示します。算出の必要な値を指定
するために -1 を使用しています。
バグを報告する
23.2. フ ィ ボ ナ ッ チ の 例 : 実 行
手順 23.1 タスク
1. Eclipse IED を起動します。
2. org.drools.exam ples.fibonacci.FibonacciExam ple クラスを開きます。
3. クラスを右クリックして Run as... を選び Java application を選択します。
結果
Eclipse は、コンソールウィンドウに以下の出力を表示します ("...snip..." はスペースを節約するために省
略された行のことです)。
197
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
recurse for 50
recurse for 49
recurse for 48
recurse for 47
...snip...
recurse for 5
recurse for 4
recurse for 3
recurse for 2
1 == 1
2 == 1
3 == 2
4 == 3
5 == 5
6 == 8
...snip...
47 == 2971215073
48 == 4807526976
49 == 7778742049
50 == 12586269025
バグを報告する
23.3. フ ィ ボ ナ ッ チ の 例 : 実 行 の 詳 細
ksession.insert( new Fibonacci( 50 ) );
ksession.fireAllRules();
Java でこれを使用するには、Sequnce フィールドが 50 個ある Fibonacci オブジェクトを 1 つ挿入し
ます。
再帰的なルールは、他の 49 Fibonacci オブジェクトを挿入するために使用します。
上記の例は、MVEL 方言を使用しています。つまり、m odify キーワードを使用でき、エンジンに変
更を通知するブロックセッターのアクションが可能となります。
バグを報告する
23.4. Fibonacci の 例 : Recurse ル ー ル
rule Recurse
salience 10
when
f : Fibonacci ( value == -1 )
not ( Fibonacci ( sequence == 1 ) )
then
insert( new Fibonacci( f.sequence - 1 ) );
System.out.println( "recurse for " + f.sequence );
end
Recurse ルールは、アサーションされた Fibonacci オブジェクトで -1 の値を持つものを照合して
いき、現在合致しているオブジェクトより 1 つ少ない順番の Fibonacci オブジェクトを新たに作成
してアサーションします。
Fibonacci オブジェクトが追加され、Sequence フィールドが 1 のものが存在しない場合、ルールの照
合と発火が再度行われます。
198
第23章 フィボナッチの例
not の条件要素は、Fibonacci オブジェクト 50 個すべてがメモリに入った時点でルールの照合を停止
するために使用します。
Recurse ルールには salience 値があるため、Fibonacci オブジェクト 50 個すべてが Bootstrap
ルールが実行される前にアサートされます。
監査ビューに切り替えて、Sequence フィールド 50 個持つ Fibonacci オブジェクトの元のアサー
ションを表示します。そこから、監査ビューはルールの反復が継続的に行われ、アサーションされた
各 Fibonacci オブジェクトは Recurse オブジェクトをアクティベートして再度発火させます。
バグを報告する
23.5. Fibonacci の 例 : Bootstrap ル ー ル
rule Bootstrap
when
f : Fibonacci( sequence == 1 || == 2, value == -1 ) // multi-restriction
then
modify ( f ){ value = 1 };
System.out.println( f.sequence + " == " + f.value );
end
Sequence フィールドが 2 の Fibonacci オブジェクトがアサートされると、Bootstrap ルールが
マッチし、Recurse ルールと一緒にアクティベートされます。
1 または 2 と等価かどうかをテストする sequence フィールドのマルチ制約に注目してください。
Sequence が 1 の Fibonacci オブジェクトがアサートされると、Bootstrap ルールが再度照合さ
れ、2 つのルールのアクティベーションが行われます。Fibonacci オブジェクトで sequence が 1
のものが存在すれば、not 条件要素がルールの照合を即座に停止するため、Recurse ルールの照合や
アクティベーションはされません。
バグを報告する
23.6. Fibonacci の 例 : Calculate ル ー ル
rule Calculate
when
// Bind f1 and s1
f1 : Fibonacci( s1 : sequence, value != -1 )
// Bind f2 and v2; refer to bound variable s1
f2 : Fibonacci( sequence == (s1 + 1), v2 : value != -1 )
// Bind f3 and s3; alternative reference of f2.sequence
f3 : Fibonacci( s3 : sequence == (f2.sequence + 1 ), value == -1 )
then
// Note the various referencing techniques.
modify ( f3 ) { value = f1.value + v2 };
System.out.println( s3 + " == " + f3.value );
end
-1 以外の値を持つ Fibonacci オブジェクトが 2 つある場合、Calculate ルールはこれらのオブジェ
クトと照合ができます。
ワーキングメモリに 50 の Fibonacci オブジェクトがあり、適切なオブジェクト 3 つが選択され、順番
に値を算出していきます。
フィールド制約なしにルールで Fibonacci パターンを使用してクロス積候補を絞り込むと、誤ってルー
199
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
ルを発火させることになります。Calculate ルールは、フィールド制約を使用して、正しく Fibonacci
パターンを正しい順番で制約していきます。この手法は、クロス積のマッチング (cross product
matching) と呼ばれています。
最初のパターンは、値が != -1 の Fibonacci を検索して、パターンとフィールドをバインドします。2
つ目の Fibonacci も同じことを行いますが、フィールド制約が追加され f1 にバインドされた
Fibonacci よりも順番が 1 つ大きくなるようにします。このルールが初めて発火されると、2 つの制約
により f1 は順番 1 を、f2 は順番 2 を参照するようにします。最後のパターンは、値が -1 で、順番
が f2 よりも大きい Fibonacci を検索します。
使用可能なクロス積から正しく選択された Fibonacci オブジェクトが 3 つあります。f3 にバイン
ドされた 3 番目の Fibonacci オブジェクトの値を算出することができます。
m odify ステートメントは、f3 にバインドされた Fibonacci オブジェクトの値を更新します。つ
まり、-1 以外の値を持つ別の Fibonacci オブジェクトが新たに存在するということで、Calculate ルー
ルにより、再度合致があるか検索して次の Fibonacci 番号を算出することができます。
監査ビューに切り替えると、最後の Bootstrap を発火することで Fibonacci オブジェクトが変更さ
れ、"Calculate" ルールが照合を開始できることが分かります。これにより、別の Fibonacci オブジェ
クトが変更され、Calculate ルールはオブジェクトの照合を再度行います。すべての Fibonacci オブ
ジェクトに値が設定されるまで、これが繰り返されます。
バグを報告する
200
第24章 バンキングの例
第 24章 バンキングの例
24.1. バ ン キ ン グ の 例 : RuleRunner
public class RuleRunner {
public RuleRunner() {
}
public void runRules(String[] rules,
Object[] facts) throws Exception {
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
for ( int i = 0; i < rules.length; i++ ) {
String ruleFile = rules[i];
System.out.println( "Loading file: " + ruleFile );
kbuilder.add( ResourceFactory.newClassPathResource( ruleFile,
RuleRunner.class
),
ResourceType.DRL );
}
Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();
kbase.addKnowledgePackages( pkgs );
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
for ( int i = 0; i < facts.length; i++ ) {
Object fact = facts[i];
System.out.println( "Inserting fact: " + fact );
ksession.insert( fact );
}
ksession.fireAllRules();
}
RuleRunner クラスは、データセットに対して 1 つまたは複数の DRL ファイルを実行する際に使用
します。このクラスはパッケージをコンパイルして、実行毎にナレッジベースを作成して、簡単に各
シナリオを実行し出力を確認できるようにします。
バグを報告する
24.2. バ ン キ ン グ の 例 : Example1.drl の ル ー ル
rule "Rule 01"
when
eval( 1==1 )
then
System.out.println( "Rule 01 Works" );
end
出力:
201
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
Loading file: Example1.drl
Rule 01 Works
このルールには、eval 条件が 1 つあり、常に true となっているため、このルールは開始後に照合が
行われ発火されます。
上記の出力から、ルールが 1 つの出力ステートメントに合致して実行されたことが分かります。
バグを報告する
24.3. バ ン キ ン グ の 例 : Java の 例 2
public class Example2 {
public static void main(String[] args) throws Exception {
Number[] numbers = new Number[] {wrap(3), wrap(1), wrap(4), wrap(1),
wrap(5)};
new RuleRunner().runRules( new String[] { "Example2.drl" },
numbers );
}
private static Integer wrap( int i ) {
return new Integer(i);
}
}
上記の例は、基本的なファクトをアサートして出力しています。
バグを報告する
24.4. バ ン キ ン グ の 例 : Example2.drl の ル ー ル
rule "Rule 02"
when
Number( $intValue : intValue )
then
System.out.println( "Number found with value: " + $intValue );
end
出力:
Loading file: Example2.drl
Inserting fact: 3
Inserting fact: 1
Inserting fact: 4
Inserting fact: 1
Inserting fact: 5
Number found with value: 5
Number found with value: 1
Number found with value: 4
Number found with value: 1
Number found with value: 3
これは、指定の数字を出力するという基本ルールです。Num ber オブジェクトで値を出力するファク
トを識別します。抽象クラス Num ber の使用に注目してください。
202
第24章 バンキングの例
パターンマッチングエンジンは、アサートしたオブジェクトのインターフェースとスーパークラスを
マッチすることができます。
上記の出力は、DRL の読み込み、ファクトの挿入が終わってから、ルールの合致と発火が行われたこ
とを表示しています。挿入した番号はそれぞれ、合致、発火後に出力されていることが分かります。
バグを報告する
24.5. バ ン キ ン グ の 例 : Example3.java
public class Example3 {
public static void main(String[] args) throws Exception {
Number[] numbers = new Number[] {wrap(3), wrap(1), wrap(4), wrap(1),
wrap(5)};
new RuleRunner().runRules( new String[] { "Example3.drl" },
numbers );
}
private static Integer wrap(int i) {
return new Integer(i);
}
}
上記は、ルールをベースにした基本的な分類手法です。
バグを報告する
24.6. バ ン キ ン グ の 例 : Example3.drl の ル ー ル
rule "Rule 03"
when
$number : Number( )
not Number( intValue < $number.intValue )
then
System.out.println("Number found with value: " + $number.intValue() );
retract( $number );
end
出力:
Loading file: Example3.drl
Inserting fact: 3
Inserting fact: 1
Inserting fact: 4
Inserting fact: 1
Inserting fact: 5
Number found with value: 1
Number found with value: 1
Number found with value: 3
Number found with value: 4
Number found with value: 5
ルールの最初の行は、Num ber を識別して値を抽出します。
2 行目で、最初のパターンで検出されたものよりも低い数値が存在しないようにします。出力後に数字
を消去するというのは、最小値が削除され次に小さい数値が公開されることを指します。
203
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
バグを報告する
24.7. バ ン キ ン グ の 例 : Cashflow ク ラ ス
public class Cashflow {
private Date
date;
private double amount;
public Cashflow() {
}
public Cashflow(Date date, double amount) {
this.date = date;
this.amount = amount;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String toString() {
return "Cashflow[date=" + date + ",amount=" + amount + "]";
}
}
クラス Cashflow には、単純な属性が 2 つ (日付と数量) あります (浮動小数点は多くの番号を正しく
表すことができないため、金額の単位に型 double を使用するのは一般的には良い慣習とは言えませ
ん。
値を設定するオーバーロードのコンストラクターと、キャッシュフローを出力するメソッド
toString があります。
バグを報告する
24.8. バ ン キ ン グ の 例 : Example4.java
204
第24章 バンキングの例
public class Example4 {
public static void main(String[] args) throws Exception {
Object[] cashflows = {
new Cashflow(new SimpleDate("01/01/2007"), 300.00),
new Cashflow(new SimpleDate("05/01/2007"), 100.00),
new Cashflow(new SimpleDate("11/01/2007"), 500.00),
new Cashflow(new SimpleDate("07/01/2007"), 800.00),
new Cashflow(new SimpleDate("02/01/2007"), 400.00),
};
new RuleRunner().runRules( new String[] { "Example4.drl" },
cashflows );
}
}
上記の例の Java コードは、日付と数量が異なる Cashflow オブジェクトを 5 つ挿入しています。
バグを報告する
24.9. バ ン キ ン グ の 例 : SimpleDate ク ラ ス
public class SimpleDate extends Date {
private static final SimpleDateFormat format = new
SimpleDateFormat("dd/MM/yyyy");
public SimpleDate(String datestr) throws Exception {
setTime(format.parse(datestr).getTime());
}
}
便利な Sim pleDate クラスは java.util.Date を継承して、コンストラクターが文字列を入力と
して受付日付形式を定義することができるようにします。
バグを報告する
24.10. バ ン キ ン グ の 例 : Example4.drl の ル ー ル
rule "Rule 04"
when
$cashflow : Cashflow( $date : date, $amount : amount )
not Cashflow( date < $date)
then
System.out.println("Cashflow: "+$date+" :: "+$amount);
retract($cashflow);
end
出力:
205
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
Loading file: Example4.drl
Inserting fact: Cashflow[date=Mon Jan 01 00:00:00
Inserting fact: Cashflow[date=Fri Jan 05 00:00:00
Inserting fact: Cashflow[date=Thu Jan 11 00:00:00
Inserting fact: Cashflow[date=Sun Jan 07 00:00:00
Inserting fact: Cashflow[date=Tue Jan 02 00:00:00
Cashflow: Mon Jan 01 00:00:00 GMT 2007 :: 300.0
Cashflow: Tue Jan 02 00:00:00 GMT 2007 :: 400.0
Cashflow: Fri Jan 05 00:00:00 GMT 2007 :: 100.0
Cashflow: Sun Jan 07 00:00:00 GMT 2007 :: 800.0
Cashflow: Thu Jan 11 00:00:00 GMT 2007 :: 500.0
GMT
GMT
GMT
GMT
GMT
2007,amount=300.0]
2007,amount=100.0]
2007,amount=500.0]
2007,amount=800.0]
2007,amount=400.0]
Cashflow が特定され、日付と数量が抽出されます。
ルールの 2 行目で、検出された日付よりも前の日付を持つ Cashflow がないことが決定します。
結果では Cashflow が出力されます。これによりルールに該当することになり削除され、次に古い
Cashflow に移ります。
バグを報告する
24.11. バ ン キ ン グ の 例 : TypedCashflow ク ラ ス
public class TypedCashflow extends Cashflow {
public static final int CREDIT = 0;
public static final int DEBIT = 1;
private int
type;
public TypedCashflow() {
}
public TypedCashflow(Date date, int type, double amount) {
super( date, amount );
this.type = type;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String toString() {
return "TypedCashflow[date=" + getDate() +
",type=" + (type == CREDIT ? "Credit" : "Debit") +
",amount=" + getAmount() + "]";
}
}
Cashflow が継承されると T ypedCashflow が返され、入金または出金オペレーションのいずれか
となります。
バグを報告する
206
第24章 バンキングの例
24.12. バ ン キ ン グ の 例 : Example5.java
クラス:
public class Example5 {
public static void main(String[] args) throws Exception {
Object[] cashflows = {
new TypedCashflow(new SimpleDate("01/01/2007"),
TypedCashflow.CREDIT, 300.00),
new TypedCashflow(new SimpleDate("05/01/2007"),
TypedCashflow.CREDIT, 100.00),
new TypedCashflow(new SimpleDate("11/01/2007"),
TypedCashflow.CREDIT, 500.00),
new TypedCashflow(new SimpleDate("07/01/2007"),
TypedCashflow.DEBIT, 800.00),
new TypedCashflow(new SimpleDate("02/01/2007"),
TypedCashflow.DEBIT, 400.00),
};
new RuleRunner().runRules( new String[] { "Example5.drl" },
cashflows );
}
}
ルール:
rule "Rule 05"
when
$cashflow : TypedCashflow( $date : date,
$amount : amount,
type == TypedCashflow.CREDIT )
not TypedCashflow( date < $date,
type == TypedCashflow.CREDIT )
then
System.out.println("Credit: "+$date+" :: "+$amount);
retract($cashflow);
end
出力:
Loading file: Example5.drl
Inserting fact: TypedCashflow[date=Mon Jan 01 00:00:00
2007,type=Credit,amount=300.0]
Inserting fact: TypedCashflow[date=Fri Jan 05 00:00:00
2007,type=Credit,amount=100.0]
Inserting fact: TypedCashflow[date=Thu Jan 11 00:00:00
2007,type=Credit,amount=500.0]
Inserting fact: TypedCashflow[date=Sun Jan 07 00:00:00
2007,type=Debit,amount=800.0]
Inserting fact: TypedCashflow[date=Tue Jan 02 00:00:00
2007,type=Debit,amount=400.0]
Credit: Mon Jan 01 00:00:00 GMT 2007 :: 300.0
Credit: Fri Jan 05 00:00:00 GMT 2007 :: 100.0
Credit: Thu Jan 11 00:00:00 GMT 2007 :: 500.0
GMT
GMT
GMT
GMT
GMT
クラスも .drl もルールエンジンに渡されます。
クラスでは、入金または出勤のオペレーションのいずれかである Cashflow オブジェクトセットが作
成されます。
207
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
成されます。
Cashflow ファクトは CREDIT 型で特定され、日付と数量が抽出されます。ルールの 2 行目では、検
出された日付より前で同じ型を持つ Cashflow がないことを確認します。結果では、パターンと合致
する cashflow を出力してから削除し、次に古い cashflow 型に進みます。
バグを報告する
24.13. バ ン キ ン グ の 例 : Account ク ラ ス
public class Account {
private long
accountNo;
private double balance = 0;
public Account() {
}
public Account(long accountNo) {
this.accountNo = accountNo;
}
public long getAccountNo() {
return accountNo;
}
public void setAccountNo(long accountNo) {
this.accountNo = accountNo;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String toString() {
return "Account[" + "accountNo=" + accountNo + ",balance=" + balance + "]";
}
}
ルールエンジンに渡す前に、2 種の Account オブジェクトが作成され、Cashflows オブジェクトに
挿入されます。
バグを報告する
24.14. バ ン キ ン グ の 例 : AllocatedCashflow ク ラ ス
208
第24章 バンキングの例
public class AllocatedCashflow extends TypedCashflow {
private Account account;
public AllocatedCashflow() {
}
public AllocatedCashflow(Account account, Date date, int type, double amount) {
super( date, type, amount );
this.account = account;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String toString() {
return "AllocatedCashflow[" +
"account=" + account +
",date=" + getDate() +
",type=" + (getType() == CREDIT ? "Credit" : "Debit") +
",amount=" + getAmount() + "]";
}
}
T ypedCashflow を継承すると Account を含む AllocatedCashflow となります。
バグを報告する
24.15. バ ン キ ン グ の 例 : Example5.java の 継 承
209
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
public class Example6 {
public static void main(String[] args) throws Exception {
Account acc1 = new Account(1);
Account acc2 = new Account(2);
Object[] cashflows = {
new AllocatedCashflow(acc1,new SimpleDate("01/01/2007"),
TypedCashflow.CREDIT, 300.00),
new AllocatedCashflow(acc1,new SimpleDate("05/02/2007"),
TypedCashflow.CREDIT, 100.00),
new AllocatedCashflow(acc2,new SimpleDate("11/03/2007"),
TypedCashflow.CREDIT, 500.00),
new AllocatedCashflow(acc1,new SimpleDate("07/02/2007"),
TypedCashflow.DEBIT, 800.00),
new AllocatedCashflow(acc2,new SimpleDate("02/03/2007"),
TypedCashflow.DEBIT, 400.00),
new AllocatedCashflow(acc1,new SimpleDate("01/04/2007"),
TypedCashflow.CREDIT, 200.00),
new AllocatedCashflow(acc1,new SimpleDate("05/04/2007"),
TypedCashflow.CREDIT, 300.00),
new AllocatedCashflow(acc2,new SimpleDate("11/05/2007"),
TypedCashflow.CREDIT, 700.00),
new AllocatedCashflow(acc1,new SimpleDate("07/05/2007"),
TypedCashflow.DEBIT, 900.00),
new AllocatedCashflow(acc2,new SimpleDate("02/05/2007"),
TypedCashflow.DEBIT, 100.00)
};
new RuleRunner().runRules( new String[] { "Example6.drl" },
cashflows );
}
}
上記の Java コードは、2 つの Account オブジェクトを作成して、コンストラクターの呼び出しの各
キャッシュフローにこのオブジェクトの 1 つを渡します。
バグを報告する
24.16. バ ン キ ン グ の 例 : Example6.drl の ル ー ル
210
第24章 バンキングの例
rule "Rule 06 - Credit"
when
$cashflow : AllocatedCashflow( $account : account,
$date : date,
$amount : amount,
type == TypedCashflow.CREDIT )
not AllocatedCashflow( account == $account, date < $date)
then
System.out.println("Credit: " + $date + " :: " + $amount);
$account.setBalance($account.getBalance()+$amount);
System.out.println("Account: " + $account.getAccountNo() +
" - new balance: " + $account.getBalance());
retract($cashflow);
end
rule "Rule 06 - Debit"
when
$cashflow : AllocatedCashflow( $account : account,
$date : date,
$amount : amount,
type == TypedCashflow.DEBIT )
not AllocatedCashflow( account == $account, date < $date)
then
System.out.println("Debit: " + $date + " :: " + $amount);
$account.setBalance($account.getBalance() - $amount);
System.out.println("Account: " + $account.getAccountNo() +
" - new balance: " + $account.getBalance());
retract($cashflow);
end
出力:
211
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
Loading file: Example6.drl
Inserting fact: AllocatedCashflow[account=Account[accountNo=1,balance=0.0],date=Mon
Jan 01 00:00:00 GMT 2007,type=Credit,amount=300.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=1,balance=0.0],date=Mon
Feb 05 00:00:00 GMT 2007,type=Credit,amount=100.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=2,balance=0.0],date=Sun
Mar 11 00:00:00 GMT 2007,type=Credit,amount=500.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=1,balance=0.0],date=Wed
Feb 07 00:00:00 GMT 2007,type=Debit,amount=800.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=2,balance=0.0],date=Fri
Mar 02 00:00:00 GMT 2007,type=Debit,amount=400.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=1,balance=0.0],date=Sun
Apr 01 00:00:00 BST 2007,type=Credit,amount=200.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=1,balance=0.0],date=Thu
Apr 05 00:00:00 BST 2007,type=Credit,amount=300.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=2,balance=0.0],date=Fri
May 11 00:00:00 BST 2007,type=Credit,amount=700.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=1,balance=0.0],date=Mon
May 07 00:00:00 BST 2007,type=Debit,amount=900.0]
Inserting fact: AllocatedCashflow[account=Account[accountNo=2,balance=0.0],date=Wed
May 02 00:00:00 BST 2007,type=Debit,amount=100.0]
Debit: Fri Mar 02 00:00:00 GMT 2007 :: 400.0
Account: 2 - new balance: -400.0
Credit: Sun Mar 11 00:00:00 GMT 2007 :: 500.0
Account: 2 - new balance: 100.0
Debit: Wed May 02 00:00:00 BST 2007 :: 100.0
Account: 2 - new balance: 0.0
Credit: Fri May 11 00:00:00 BST 2007 :: 700.0
Account: 2 - new balance: 700.0
Credit: Mon Jan 01 00:00:00 GMT 2007 :: 300.0
Account: 1 - new balance: 300.0
Credit: Mon Feb 05 00:00:00 GMT 2007 :: 100.0
Account: 1 - new balance: 400.0
Debit: Wed Feb 07 00:00:00 GMT 2007 :: 800.0
Account: 1 - new balance: -400.0
Credit: Sun Apr 01 00:00:00 BST 2007 :: 200.0
Account: 1 - new balance: -200.0
Credit: Thu Apr 05 00:00:00 BST 2007 :: 300.0
Account: 1 - new balance: 100.0
Debit: Mon May 07 00:00:00 BST 2007 :: 900.0
Account: 1 - new balance: -800.0
上記の例は、日付順の cashflow が適用、算出され、残額が出力されています。
入金と出金に対して別のルールが存在しますが、以前の cashflow を確認する際の型が指定されていま
せん。これは、すべての cashflow が cashflow の型に拘らず、日付順に適用されるようにするためで
す。
このような条件で、アカウントが特定され、結果 cashflow の額が更新されます。
バグを報告する
212
第25章 価格設定ルールの例
第 25章 価格設定ルールの例
25.1. 価 格 設 定 ル ー ル の 例 : 価 格 設 定 ル ー ル の 実 行 例
手順 25.1 タスク
1. コンソールを開きます。
2. PricingRuleDT Exam ple.java ファイルを開き、Java アプリケーションとして実行します。
コンソールウィンドウに以下の出力を表示されます。
Cheapest possible
BASE PRICE IS: 120
DISCOUNT IS: 20
3. 以下のコードを使用して、この例を実行します。
DecisionTableConfiguration dtableconfiguration =
KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtableconfiguration.setInputType( DecisionTableInputType.XLS );
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
Resource xlsRes = ResourceFactory.newClassPathResource(
"ExamplePolicyPricing.xls",
getClass()
);
kbuilder.add( xlsRes,
ResourceType.DTABLE,
dtableconfiguration );
DecisionT ableConfiguration オブジェクトの型は、 DecisionT ableInputT ype.XLS
に設定されています。
この例では Driver と Policy の 2 つのファクト型が使用されています。いずれも、デフォルト
値が使用されています。Driver は 30 歳、以前に請求なし、現在のリスクプロファイル LOW と
なっています。適用される Policy は COMPREHENSIVE で、まだ承認されていません。
バグを報告する
25.2. 価 格 設 定 ル ー ル の 例 : 決 定 テ ー ブ ル の 設 定
213
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
図 25.1 決定テーブルの設定
RuleSet はパッケージ名を宣言します。その他グローバル変数には Variables、インポートクラス
には Im ports など、オプションのアイテムとしてここに設定できます。今回の場合は、ルールの名
前空間がファクトクラスと同じであるため、省略可能です。
RuleT able 宣言 (Pricing bracket) の後の名前は生成されたルールすべての接頭辞として使用されま
す。
"CONDIT ION or ACT ION" は列の目的を指します。つまり、条件の一部か、生成されるルールの結果
のどちらであるかを指します。
ドライバーのデータは、3 つのセルに分かれており、そのセルの下のテンプレートの表現が適用されま
す。ドライバーの年齢の範囲 (コンマ区切りの値で $1 と $2 を使
用)、locationRiskProfile、priorClaim s がそれぞれの列で確認できます。
ポリシーベースの価格とメッセージログを Action 列に設定することができます。
バグを報告する
25.3. 価 格 設 定 ル ー ル の 例 : 基 本 価 格 の 算 出 例
214
第25章 価格設定ルールの例
図 25.2 基本価格の算出例
一番左の列のコメントで、広義のカテゴリーが示されます。
ドライバーの詳細は、事故歴がなく 30 歳であるため、行番号 18 と合致します。つまり、基本料金が
120 となります。
バグを報告する
25.4. 価 格 設 定 ル ー ル の 例 : 割 引 の 算 出 例
図 25.3 割引の算出例
215
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
Age 範囲、以前の請求、保険タイプから割引が出されます。
ドライバーは 30 歳で以前に請求がなく、COMPREHENSIVE 保険に申し込んでいます。つまり、20%
の割引が適用されます。これは、同じワークシートの別の表であるため、異なるテンプレートが適用
されます。
通常のルールエンジンの仕組みがすべて適用されるため、ルールの評価は指定の順番でなくても構い
ません。
バグを報告する
216
第26章 ペットショップの例
第 26章 ペットショップの例
26.1. ペ ッ ト シ ョ ッ プ の 例
ペットショップの例の Java コードはすべて PetStore.java ファイルの中に含まれています。これは
(Swing イベントを処理する複数のクラスに加え) 以下の主要なクラスを定義しています。
Petstore には m ain() メソッドが含まれています。
PetStoreUI は Swing ベースの GUI を作成、表示します。これには複数の小さいクラスが含まれて
おり、主にマウスボタンのクリックなど様々ん GUI イベントに対応します。
T ableModel には表データが含まれており、Swing クラス AbstractT ableModel を継承する
JavaBean です。
CheckoutCallback は GUI とルール間で対話できるようにします。
Ordershow は顧客が購入を希望するアイテムです。
Purchase には、顧客が購入する商品と商品の詳細が保存されています。
Product は、販売可能な製品と価格の詳細を含む JavaBean です。
バグを報告する
26.2. ペ ッ ト シ ョ ッ プ の 例 : PetStore.main で の PetStore RuleBase
作成
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClassPathResource( "PetStore.drl",
PetStore.class ),
ResourceType.DRL );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
// Create the stock.
Vector<Product> stock =
stock.add( new Product(
stock.add( new Product(
stock.add( new Product(
new Vector<Product>();
"Gold Fish", 5 ) );
"Fish Tank", 25 ) );
"Fish Food", 2 ) );
// A callback is responsible for populating the
// Working Memory and for firing all rules.
PetStoreUI ui = new PetStoreUI( stock,
new CheckoutCallback( kbase ) );
ui.createAndShowGUI();
上記のコードは、クラスパスの DRL ファイルからルールを読み取ります。この読み取りは、コンスト
ラクターを使用して、PetStoreUI オブジェクトが作成される最後の 2 行で行われます。商品が集め
られた Vector object stock を承認します。
CheckoutCallback クラスには読み込まれた Rule Base が含まれています。
バグを報告する
217
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
26.3. ペ ッ ト シ ョ ッ プ の 例 : CheckoutCallBack.checkout() か ら の
ルールの発火
public String checkout(JFrame frame, List<Product> items) {
Order order = new Order();
// Iterate through list and add to cart
for ( Product p: items ) {
order.addItem( new Purchase( order, p ) );
}
// Add the JFrame to the ApplicationData to allow for user interaction
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ksession.setGlobal( "frame", frame );
ksession.setGlobal( "textArea", this.output );
ksession.insert( new Product( "Gold Fish", 5 ) );
ksession.insert( new Product( "Fish Tank", 25 ) );
ksession.insert( new Product( "Fish Food", 2 ) );
ksession.insert( new Product( "Fish Food Sample", 0 ) );
ksession.insert( order );
ksession.fireAllRules();
// Return the state of the cart
return order.toString();
}
ルールを発火する Java コードは、CheckoutCallBack.checkout() メソッド内にあります。これ
は、ユーザーがチェックアウトボタンを押すと (最終的に) トリガーされます。
2 つのアイテムがこのメソッドに渡されます。1 つは GUI の一番下にある出力テキストフレームの周
りにある JFram e Swing コンポーネントへのハンドルです。2 つ目は注文アイテムの一覧です。これ
は GUI の右上にある "T able" 部分からの情報を格納する T ableModel からの情報です。
for ループは GUI からの注文アイテム一覧を Order JavaBean (PetStore.java ファイルにも含ま
れている) に変換します。
この例のすべてのステータスは、Swing コンポーネントに保存されています。これらのルールは実質
的にステートレスとなっています。
"Checkout" ボタンを押すたびに、このコードは Swing T ableModel の内容をセッションのワーキン
グメモリにコピーします。
ワーキングメモリに対する呼び出しは 9 個です。1 つは、ナレッジベースからステートフルナレッジ
セッションとして新しいワーキングメモリを作成します。次の 2 つは、ルールでグローバル変数とし
て保持されるオブジェクトを 2 つ渡します。Swing テキスト部分と Swing フレームは、メッセージの
記述に使用されます。
他の挿入は商品に関する情報をワーキングメモリと注文一覧に保存します。最後の呼び出しは標準の
fireAllRules() となっています。
バグを報告する
26.4. ペ ッ ト シ ョ ッ プ の 例 : PetStore.drl か ら の パ ッ ケ ー ジ 、 イ ン
ポート、グローバル、方言
218
第26章 ペットショップの例
package org.drools.examples
import
import
import
import
import
import
org.drools.WorkingMemory
org.drools.examples.petstore.PetStoreExample.Order
org.drools.examples.petstore.PetStoreExample.Purchase
org.drools.examples.petstore.PetStoreExample.Product
java.util.ArrayList
javax.swing.JOptionPane;
import javax.swing.JFrame
global JFrame frame
global javax.swing.JTextArea textArea
PetStore.drl ファイルの最初の部分には、様々な Java クラスをルールで使用できるようにする標
準のパッケージ、import ステートメントが含まれています。
2 つの globals fram e と textArea は、setGlobal() メソッドを呼び出す Java コードにより以前
に渡された Swing コンポーネント JFram e と JT extArea に対する参照を保持しています。これらの
グローバル変数は、セッションが生存している間、それらの値を保持します。
バグを報告する
26.5. ペ ッ ト シ ョ ッ プ の 例 : PetStore.drl か ら の 抽 出 さ れ た Java 関
数
219
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
function void doCheckout(JFrame frame, WorkingMemory workingMemory) {
Object[] options = {"Yes",
"No"};
int n = JOptionPane.showOptionDialog(frame,
"Would you like to checkout?",
"",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (n == 0) {
workingMemory.setFocus( "checkout" );
}
}
function boolean requireTank(JFrame frame, WorkingMemory workingMemory, Order
order, Product fishTank, int total) {
Object[] options = {"Yes",
"No"};
int n = JOptionPane.showOptionDialog(frame,
"Would you like to buy a tank for your " + total + " fish?",
"Purchase Suggestion",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
System.out.print( "SUGGESTION: Would you like to buy a tank for your "
+ total + " fish? - " );
if (n == 0) {
Purchase purchase = new Purchase( order, fishTank );
workingMemory.insert( purchase );
order.addItem( purchase );
System.out.println( "Yes" );
} else {
System.out.println( "No" );
}
return true;
}
ルールファイルにこれらの関数を設定することで、ペットショップの例がさらにコンパクトになりま
す。
同じルールパッケージ内のファイルで、または標準の Java クラスでの静的メソッドとして関数を設定
して、im port function m y.package.Foo.hello を使用してインポートします。
doCheckout() は、チェックアウトをするかどうかの確認ダイアログを表示します。チェックアウト
する場合は、フォーカスが checkOut agenda-group にセットされ、そのグループのルールが発火で
きるようになります。
requireT ank() は、水槽を購入するかどうかを確認するダイアログを表示します。購入する場合、
新しい水槽 Product がワーキングメモリの注文リストに追加されます。
バグを報告する
220
第26章 ペットショップの例
26.6. ペ ッ ト シ ョ ッ プ の 例 : PetStore.drl か ら ワ ー キ ン グ メ モ リ へ
のアイテム追加
// Insert each item in the shopping cart into the Working Memory
rule "Explode Cart"
agenda-group "init"
auto-focus true
salience 10
dialect "java"
when
$order : Order( grossTotal == -1 )
$item : Purchase() from $order.items
then
insert( $item );
kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "show items"
).setFocus();
kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "evaluate"
).setFocus();
end
auto-focus 属性が true を設定されているため、最初に抽出されたものが最初に発火されます。
このルールは、grossT otal が算出されていないオーダーすべてに対して照合が行われます。この順
番で各購入アイテムに対してもループが行われます。ルール名、Salience (ルールの発火順の提
示)、java に設定された方言など、"Explode Cart" ルールの一部はすでに説明されています。
agenda-groupinit はアジェンダグループの名前を定義します。この場合、グループにはルールが
1 つしかありません。しかし、Java コードもルール結果もこのグループにフォーカスされていないた
め、発火されるかどうかは、次の属性で分かります。
auto-focustrue は、fireAllRules() が Java コードから呼び出されるとこのルール (このルー
ルは本アジェンダグループで唯一のルール) が発火可能となるようにします。
kcontext....setFocus() はフォーカスを show item s と evaluate アジェンダーに順番に移し
ていき、これらのルールが発火できるようにします。実際、この順でアイテムすべてをループしてメ
モリに挿入して、他のルールも挿入が終わってから発火されます。
バグを報告する
26.7. ペ ッ ト シ ョ ッ プ の 例 : PetStore.drl か ら GUI の ア イ テ ム を 表
示
rule "Show Items"
agenda-group "show items"
dialect "mvel"
when
$order : Order( )
$p : Purchase( order == $order )
then
textArea.append( $p.product + "\n");
end
show item s アジェンダグループには、"Show Items" と呼ばれるルール 1 つのみが存在します (違い
に注意)。現在ワーキングメモリにある注文の購入ごとに、GUI の下部分にあるテキストエリアに詳細
がログされます。これに使用される textArea 変数はグローバル変数になっています。
221
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
evaluate アジェンダグループは、Explode Cart ルールからフォーカスを取得します。
バグを報告する
26.8. ペ ッ ト シ ョ ッ プ の 例 : PetStore.drl か ら の ア ジ ェ ン ダ グ ル ー
プの評価
// Free Fish Food sample when we buy a Gold Fish if we haven't already bought
// Fish Food and don't already have a Fish Food Sample
rule "Free Fish Food Sample"
agenda-group "evaluate"
dialect "mvel"
when
$order : Order()
not ( $p : Product( name == "Fish Food") && Purchase( product == $p ) )
not ( $p : Product( name == "Fish Food Sample") && Purchase( product == $p ) )
exists ( $p : Product( name == "Gold Fish") && Purchase( product == $p ) )
$fishFoodSample : Product( name == "Fish Food Sample" );
then
System.out.println( "Adding free Fish Food Sample to cart" );
purchase = new Purchase($order, $fishFoodSample);
insert( purchase );
$order.addItem( purchase );
end
// Suggest a tank if we have bought more than 5 gold fish and don't already have
one
rule "Suggest Tank"
agenda-group "evaluate"
dialect "java"
when
$order : Order()
not ( $p : Product( name == "Fish Tank") && Purchase( product == $p ) )
ArrayList( $total : size > 5 ) from collect( Purchase( product.name == "Gold
Fish" ) )
$fishTank : Product( name == "Fish Tank" )
then
requireTank(frame, drools.getWorkingMemory(), $order, $fishTank, $total);
end
"Free Fish Food Sam ple" ルールは、以下の状況でのみ発火されます。
店舗には魚の餌がまだ ない。かつ
店舗には魚の餌のサンプルがまだ ない。かつ
店舗には金魚の注文が 入っている
"Suggest T ank" ルールは、以下の状況でのみ発火されます。
店舗に水槽の注文がまだ入っていない。かつ
店舗への注文に金魚関連の商品が 5 点以上 入っている
ルールが発火されると、requireT ank() 関数が発火され、ユーザーにダイアログが表示され、確定
されるとタンクが注文およびワーキングメモリに追加されるようになっています。
requireTank() 関数が呼び出されると、関数に Swing GUI へのハンドルが設定されるように、ルールは
グローバルの frame 変数に渡されます。
222
第26章 ペットショップの例
ルールが発火されると、新しい商品 (魚の餌のサンプル) を作成して、ワーキングメモリの注文にその
商品が追加されます。
バグを報告する
26.9. ペ ッ ト シ ョ ッ プ の 例 : PetStore.drl か ら チ ェ ッ ク ア ウ ト を 抽
出
rule "do checkout"
dialect "java"
when
then
doCheckout(frame, drools.getWorkingMemory());
end
"do checkout" ルールには、アジェンダグループが設定されておらず auto-focus 属性もありませ
ん。そのため、デフォルト (MAIN) のアジェンダグループの一部とされます。明示的にフォーカスが来
るように設定されているアジェンダグループのルールすべてのループが行われている間、このグルー
プはデフォルトでフォーカスが当てられています。
このルールには LHS がないため、RHS は常に doCheckout() 関数を呼び出します。
doCheckout() 関数を呼び出すと、ルールは、関数に Swing GUI へのハンドルを設定できるよう
に、グローバルの fram e 変数を渡します。
doCheckout() 関数は、ユーザーに確認ダイアログを表示します。確定されると、関数はフォーカス
を checkout アジェンダグループに移して、次のルールを多数発火できるようにします。
バグを報告する
26.10. ペ ッ ト シ ョ ッ プ の 例 : PetStore.drl か ら チ ェ ッ ク ア ウ ト ル ー
ル
223
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
rule "Gross Total"
agenda-group "checkout"
dialect "mvel"
when
$order : Order( grossTotal == -1)
Number( total : doubleValue )
from accumulate( Purchase( $price : product.price ), sum( $price ) )
then
modify( $order ) { grossTotal = total };
textArea.append( "\ngross total=" + total + "\n" );
end
rule "Apply 5% Discount"
agenda-group "checkout"
dialect "mvel"
when
$order : Order( grossTotal >= 10 &&< 20 )
then
$order.discountedTotal = $order.grossTotal * 0.95;
textArea.append( "discountedTotal total=" + $order.discountedTotal + "\n" );
end
rule "Apply 10% Discount"
agenda-group "checkout"
dialect "mvel"
when
$order : Order( grossTotal >= 20 )
then
$order.discountedTotal = $order.grossTotal * 0.90;
textArea.append( "discountedTotal total=" + $order.discountedTotal + "\n" );
end
checkout アジェンダグループには、3 つのルールがあります。
Gross T otal は、商品の価格を累積して合計を出し、ワーキングメモリーに保存して textArea グ
ローバル変数を使用して Swing JT extArea 経由で表示します。
総計が 10 から 20 の場合、Apply 5% Discount により割引合計が算出され、ワーキングメモリー
に追加されてからテキスト領域に表示されます。
総計が 20 未満の場合、Apply 10% Discount により割引合計が算出され、ワーキングメモリーに
追加されてからテキスト領域に表示されます。
バグを報告する
26.11. ペ ッ ト シ ョ ッ プ の 例 : PetStore.java の 実 行
PetStore.java を使用するには、以下の条件を満たす必要があります。
1. m ain() メソッドがルールベースの実行と読み込みを終えているが、ルールが発火されていないこ
と。今のところ、実行されたルールに関連する唯一のコードがこれです。
2. 新しい PetStoreUI オブジェクトが作成され、後で使用できるようにルールベースにハンドルを
渡すこと。
3. Swing コンポーネントがデプロイされ、コンソールがユーザー入力を待機すること。
PetStore.java ファイルには、m ain() メソッドが含まれているため、コマンドラインまたは IDE
で標準の Java アプリケーションとして実行できます。クラスパスが正しく設定されていることを前提
224
第26章 ペットショップの例
としています。
最初に表示される画面は、ペットショップのデモです。ここには販売商品の一覧、選択された商品 (空
の一覧)、Checkout と Reset ボタン、空のシステムメッセージ領域が含まれています。
「Checkout」ボタンを押すとビジネスルールが発火されます。
1. CheckOutCallBack.checkout() メソッドが「Checkout」ボタンが押されるのを待機している
Swing クラスにより呼びだされます。これにより、T ableModel オブジェクトからデータが挿入
され、セッションのワーキングメモリーに挿入されます。その後、ルールを発火します。
2. 最初に発火するルールは、auto-focus が true に設定されているルールです。カート内の商品す
べてに対してループして、商品がすべてワーキングメモリに保存されているようにしてから、Show
Item s と Evaluation のアジェンダグループが発火できるようにします。これらのグループの
ルールは、カートの中身をテキスト領域に追加して (ウィンドウの一番下)、ユーザーに魚の餌を無
料で提供するか決定し、水槽を購入するかどうかの確認をします。
バグを報告する
26.12. ペ ッ ト シ ョ ッ プ の 例 : チ ェ ッ ク ア ウ ト ル ー ル の 実 行
1. Do Checkout ルールは、デフォルトの (MAIN) アジェンダグループに含まれています。常に
doCheckout() 関数を呼び出して 'Would you like to Checkout?' のダイアログボックスを表示しま
す。
2. doCheckout() 関数はフォーカスを checkout アジェンダグループに設定して、そのグループに
あるルールが発火できる状態にします。
3. checkout アジェンダグループのルールは、カートの中身を表示して適切な割引を適用します。
4. Swing then waits for user input は、別の商品をチェックアウトするか (再度ルールを発火させる)、
GUI を終了します。
バグを報告する
225
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 27章 数独の例
27.1. 数 独 の 例 : 例 の 読 み 込 み
手順 27.1 タスク
1. IDE で sudoku.drl を開きます。
2. java org.drools.exam ples.DroolsExam plesApp を実行して SudokuExam ple をクリッ
クします。ウィンドウには、空のグリッドが含まれていますが、このプログラムには読み込みや解
決が可能なグリッドが複数、内部に格納されています。
3. File → Samples → Simple をクリックして例の 1 つを読み込みます。グリッドが読み込まれるま
で、ボタンはすべて無効となっています。Sim ple の例を読み込むと、パズルの最初の状態に従い
グリッドが埋められます。
4. Solve ボタンをクリックすると、JBoss Rules エンジンが残りの値を埋めていきます。このボタン
は再度無効になります。
5. または、Step ボタンをクリックすると、ルールセットで検索された次の数字を確認できます。コ
ンソールウィンドウで、以下の例のように解読可能な形式で、このステップの解決に実行される
ルールに関する詳細情報が表示されます。
single 8 at [0,1]
column elimination due to [1,2]: remove 9 from [4,2]
hidden single 9 at [1,2]
row elimination due to [2,8]: remove 7 from [2,4]
remove 6 from [3,8] due to naked pair at [3,2] and [3,7]
hidden pair in row at [4,6] and [4,4]
6. Dum p ボタンをクリックするとグリッドの状態が表示されます。このセルは解決済みの値か残りの
候補値を表示します。以下の例をご覧ください。
Col: 0
Col: 1
Col: 2
Col: 3
Col: 7
Col: 8
Row 0:
2 4 7 9
2 456
4567 9
3 67 9 --- 8 --4 67
Row 1: 12
7 9 --- 8 --- 1
67 9
3 67 9
3 67 9 --- 5 --Row 2: 1 4 7 9 1 456
--- 3 ---- 2 --4 67 9 1 4 67
Row 3: 1234
12345
1 45
5 78
45 7
--- 9 --Row 4: --- 6 --- --- 7 --5
5 8
--- 1 --- --- 3 --Row 5: --- 8 --- 12 45
1 45
9
567
4567
2 4 67
Row 6: 1 3
7
1 3 6
--- 2 ---- 4 --3 567 9 1
678
Row 7: --- 5 --- 1 34 6
1 4 678
1 3 678
--- 2 --- 1
678
Row 8:
34
--- 9 --4 6 8
3 56 8
3 56
6 8
Col: 4
23 56
9
--- 5 ---
23
9
--- 4 ---
6
56 89
12
5
8
--- 4 --12
5
3
6 8
--- 7 ---
27.2. 数 独 の 例 : 壊 れ た 内 容 の デ バ ッ グ 例
Col: 6
--- 1 --23
5 78
--- 6 --2
5
8
--- 3 ---
3 56 8
バグを報告する
226
Col: 5
5
8
2
67
1
5678
-
5 78
--- 9 --2
5 7
3 56 8
--- 9 ---
34 6 8
--- 1 ---
23456 8
-
第27章 数独の例
手順 27.2 タスク
1. IDEで sudoku.drl を開きます。
2. File → Samples → !DELIBERAT LEY BROKEN! をくりっくします。JBoss Rules エンジンは、
グリッドを確認して以下の出力を生成します。
cell [0,8]: 5 has a duplicate
cell [0,0]: 5 has a duplicate
cell [6,0]: 8 has a duplicate
cell [4,0]: 8 has a duplicate
Validation complete.
in
in
in
in
row
row
col
col
0
0
0
0
3. Solve ボタンをクリックして、この無効なグリッドに回答ルールを適用します。これらのルールは
問題解決にセルの値を使用します。このような状況を検出するルールはし知恵のセルの解決値など
Setting ファクトを挿入します。このファクトは、グループ内の全セルから不正な値を削除します。
バグを報告する
27.3. 数 独 の 例 : Java ソ ー ス お よ び ル ー ル
Java ソースコードは、/src/m ain/java/org/drools/exam ples/sudoku ディレクトリにあ
り、ルールを定義する 2 つの DRL ファイルは
/src/m ain/rules/org/drools/exam ples/sudoku ディレクトリにあります。
org.drools.exam ples.sudoku.swing パッケージには、数独パズルのフレームワークを実装す
るクラスセットが含まれています。このパッケージには、JBoss Rules ライブラリとの依存関係はあ
りません。
SudokuGridModel は、9x9 グリッドの Cell オブジェクトとして数独パズルを格納するために実装
可能なインターフェースを定義しています。
SudokuGridView は Swing コンポーネントで SudokuGridModel 実装の視覚化が可能です。
SudokuGridEvent と SudokuGridListener は、モデルとビューの間のステータスの変化をやり
取りするために使用します。セルの値が解決または変更されると、イベントが発火されます。
SudokuGridSam ples は、デモ用に一部入力されている数独パズルを複数提供します。
org.drools.exam ples.sudoku.rules パッケージには、DRL ファイルのコンパイル用のメソッ
ドとユーティリティクラスが含まれています。
org.drools.exam ples.sudoku パッケージには、初級の Cell オブジェクトと様々な累積を実装
するクラスが含まれています。これには、CellFile サブタイプ CellRow、 CellCol、CellSqr
が含まれています (これらは CellGroup サブタイプとなっています)。
バグを報告する
27.4. 数 独 の 例 : Cell オ ブ ジ ェ ク ト
Cell と CellGroup は SetOfNine のサブクラスで、Set<Integer> 型の free プロパティを提
供します。Cell は、個別の候補セットを表します。CellGroup は、セルの全候補セットの統合また
は、割り当ての必要のある数値セットです。
特定の状況を検出して、セルへの値の割り当て、候補セットからの値の削除などを許可するルールを
記述します。例えば、Cell オブジェクトは 81 の Cell と 27 の CellGroup オブジェクトを持つリ
ストを作成することができます。また、Cell プロパティである cellRow、cellCol、cellSqr と
the CellGroup プロパティの cells からのリンクを組み合わせることも可能です。
227
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
バグを報告する
27.5. 数 独 の 例 : ク ラ ス と オ ブ ジ ェ ク ト
Setting クラスに所属するオブジェクトは、値の割り当てに伴うオペレーションをトリガーするため
に使用します。Setting ファクトは、プロセスの変更を検出するすべてのルールに使用します。これ
は、中間のステータスに整合性がとれない場合などに反応しないようにするためです。
Stepping クラスのオブジェクトは、優先順位が低いルールに使用して、"step" が予期なく中断され
た場合に緊急停止を行います。これは、プログラムでパズルを解決できないということです。
org.drools.exam ples.sudoku.SudokuExam ple クラスは、上記のコンポーネントを組み合わ
せる Java アプリケーションを実装します。
バグを報告する
27.6. 数 独 の 例 : Validate.drl
Sudoku Validator Rules (validate.drl) は、セルグループで重複している番号を検出します。アジェンダ
グループで組み合わせて、パズルの読み込みした後にアクティベートできるようにします。
3 つの duplicate in cell... ルールは非常によく似ています。最初のパターンは、割り当てた値
でセルの場所を検索します。2 番目のパターンは、セルが所属するセルグループ 3 つのいずれかをプ
ルします。最後のパターンは、同じ行、列、四角の中でそれぞれ、最初のセルと同じ値を持つセルを
検索します。
term inate group ルールを最後に発火します。メッセージを出力して halt を呼び出します。
バグを報告する
27.7. 数 独 の 例 : Sudoku.drl
Sudoku.drl にはルール解決のタイプが 3 種類あります。1 つは、グループがセルへの数値の割り当て
を処理して、もう 1 つは実行可能な割り当てを検出して、3 つ目は候補セットからの値を削除しま
す。
set a value、elim inate a value from Cell、retract setting のルールは、Setting
オブジェクトがあるかどうかにより左右されます。
Set a value は、セルへの割り当てやセルの 3 つのグループの "free" セットから値を削除する操作
を処理します。また、ゼロの場合には fireUntilHalt() が呼び出された Java アプリケーションへ
の制御を返すカウンターを 1 つ減らします。
Elim inate a value from Cell は、新しく割り当てられたセルに関する全セルの候補リストを
減らします。
Retract setting は、削除がすべて終わると Setting ファクトのトリガーを削除します。
セルに数字を割り当てることができる状況を割り出すルールは 2 つだけです。single ルールは、数
字が 1 つだけの候補セットを含む Cell の場合に発火します。hidden single ルールは、候補が
あっても、セルが所属するグループの 1 つに含まれるその他すべてのセルにkの候補が含まれていな
い場合に発火されます。これらのルールはいずれも Setting ファクトを作成、挿入します。
ルールの最大のグループからのルールは、様々な解決手法を 1 つまたは 2-3 のグループ単位で実装し
ます。これは、数独パズルが手動で解決された場合に使用されるためです。
naked pair ルールは、グループの 2 つのセルで全く同じ候補セットを 2 つ検出します。これら 2
つの値は、そのグループのその他の全候補セットから削除することができます。
228
第27章 数独の例
hidden pair in ルールでは、ルールはグループの 2 つのセルで 2 つの数字を探します。どの値も
このグループの他のセルには入りません。つまり、他の候補はすべて、隠れたペアを持つ 2 つのセル
から削除します。
ルールのペアは、列と行内の X-wings を処理します。行 (または列) 2 つの値に対して考えられるセ
ルが 2 つしかない場合、これらの候補は同じ行 (または列) に入れられ、この行 (または列) でこの値に
対する他の候補すべてが削除されます。条件 sam e または only は、適切な制約を持つパターンにな
るか、not の接頭辞がつきます。
intersection rem oval... のルールペアは、1 つの四角の中に (1 つの行または列) 使用できる数
字を制限するというルールに基づいています。つまり、この番号は行または列の中の 2-3 セルの 1 つ
に入っていないといけないのです。グループの別のセルすべての中にある候補セットから削除できま
す。このパターンは、発生制限を確立して、同じセルファイルの中かつ、四角の外のセルそれぞれに
対して発火されます。
非常に困難なグリッドを解決するには、ルールセットはより複雑なルールで拡張する必要があります
(最終的には、試行錯誤でしか解決できないパズルもあります)。
バグを報告する
229
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
第 28章 数字当ての例
28.1. 数 字 当 て の 例 : サ ン プ ル の 読 み 込 み
final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClassPathResource( "NumberGuess.drl",
ShoppingExample.class ),
ResourceType.DRL );
kbuilder.add( ResourceFactory.newClassPathResource( "NumberGuess.rf",
ShoppingExample.class ),
ResourceType.DRF );
final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
Num berGuess.drl にある数字当てのサンプルでは、ルールフローの用途、ルール発火の順番を制御
する方法などが説明されています。上記のように読み込まれます。
バグを報告する
28.2. 数 字 当 て の 例 : RuleFlow の 開 始
final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger =
KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "log/numberguess");
ksession.insert( new GameRules( 100, 5 ) );
ksession.insert( new RandomNumber() );
ksession.insert( new Game() );
ksession.startProcess( "Number Guess" );
ksession.fireAllRules();
logger.close();
ksession.dispose();
上記のコードは、パッケージの作成とルールの読み込みの例です (add() メソッドの使用)。
ルールフローを追加する (Num berGuess.rf) 行が 1 つ増えており、同じナレッジベースに別のルー
ルフローを指定するオプションが追加されます。
ナレッジベースが作成されると、ステートフルセッションの取得に使用できます。その後ファクトが
挿入されます。
バグを報告する
28.3. 数 字 当 て の 例 : ク ラ ス と メ ソ ッ ド
230
第28章 数字当ての例
注記
数字当てサンプルのクラスはすべて Num berGuessExam ple.java ファイルに含まれています。
Gam eRules クラスでは、数当ての最大範囲と何度まで推理できるかを決定します。
Random Num ber クラスは、0 から 100 までの数字を自動生成して、ルールで使用できるようにしま
す。getValue() メソッドを使って挿入をすることで行います。
Gam e クラスは、推理した回数をトラッキングします。
startProcess() メソッドを呼び出して、プロセスを開始します。
ルールの実行には fireAllRules() メソッドが呼び出されます。
ワーキングメモリセッションの削除には、dispose() メソッドが呼び出されます。
バグを報告する
28.4. 数 字 当 て の 例 : RuleFlow の 確 認
手順 28.1 タスク
1. Drools IDE で Num berGuess.rf ファイルを開きます。標準的なフローチャートのように機能する
図が表示されます。
2. この図を編集するには、IDE の図の左側にある、使用可能なコンポーネントメニューを使用しま
す。これは パレット と呼ばれます。
3. XML でこの図を保存します (XStream がインストールされている場合は使用することができます)。
4. まだ開いてない場合は、IDE で Properties View が表示されるようにしてください。Window →
Show View → Other をクリックして開き、ここから Properties ビューを選択します。ルール
フローのアイテムを選択する (ルールフローのスペースをクリックする) 前にこれを行うとプロパ
ティが表示されます。これらのプロパティを使用して、プロセスの特定や変更の確認を行うことが
できます。
バグを報告する
28.5. 数 字 当 て の 例 : RuleFlow ノ ー ド
数字当ての RuleFlow には、ノード型が複数あります。
開始ノード (緑の丸の中に白い矢印) と終端ノード (赤い箱) は、ルールフローの最初と最後を表してい
ます。
ルールフローグループのボックス (アイコンなし、黄色) は、ルール (DRL) ファイルで定義されたルー
ルフローグループを指します。例えば、フローがルールフローグループ "too high" に到達すると、属
性が ruleflow-group"T oo High" とマーキングされているルールのみが発火できるようになりま
す。
アクションノード (黄色い歯車の形をしたアイコン) は標準の Java メソッド呼び出しを実行します。
このサンプルにある多くのアクションノードは System .out.println() を呼び出し、プログラムの
進捗をユーザーに表示します。
"Guess Correct?" や "More guesses Join" マークなどの分割ノードと結合ノード (青い楕円、アイコ
ンなし) は、制御フローが分割、結合できる場所に設置されます。
矢印は、様々なノードとノードの間のフローを指します。
バグを報告する
231
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
28.6. 数 当 て の 例 : NumberGuess.drl の 特 定 の ポ イ ン ト で の ル ー ル
の発火
rule "Get user Guess"
ruleflow-group "Guess"
no-loop
when
$r : RandomNumber()
rules : GameRules( allowed : allowedGuesses )
game : Game( guessCount < allowed )
not ( Guess() )
then
System.out.println( "You have " + ( rules.allowedGuesses - game.guessCount
)
+ " out of " + rules.allowedGuesses
+ " guesses left.\nPlease enter your guess from 0 to
"
+ rules.maxRange );
br = new BufferedReader( new InputStreamReader( System.in ) );
i = br.readLine();
modify ( game ) { guessCount = game.guessCount + 1 }
insert( new Guess( i ) );
end
ルールと様々なノードを組み合わせることで、数当てゲームが機能します。例えば、"Guess" ルール
フローグループは、"Get user Guess" ルールしか同じ ruleflow-group"Guess" 属性を持たない
ためこのルールだけを発火させることができます。
ルールの LHS のセクション (when の後の部分) は、Random Num ber オブジェクトがワーキングメモ
リに挿入されるたびにアクティベートされると記述しています。つまり、guessCount が
Gam eRules からの allowedGuesses より多く、正しい数字を推理していない場合です。
RHS のセクション (または結果、then の後ろの部分) はユーザーにメッセージを出力して
System .in からのユーザー入力があるまで待機します。この入力を取得すると (readLine() メ
ソッド呼び出しは Return キーが押されるまでブロック)、推理回数を変更して新たな推理を挿入し、
両方をワーキングメモリで使用できるようにします。
このパッケージでは、方言を MVEL で宣言し、様々な Java クラスがインポートされています。
合計で、このファイルにはルールが 5 つあります。
1. ユーザーに推測させるルール (上記でルールは検証済み)。
2. 一番推理の回数が多いものを記録するルール。
3. 一番推理の回数が少ないものを記録するルール。
4. 推理した数字を検証して間違っている場合はメモリから削除するルール。
5. 最大で推理が試行できる回数をすべて使い果たしたことをユーザーに通知するルール。
バグを報告する
28.7. 数 字 当 て の 例 : RuleFlow の 制 約 の 確 認
手順 28.2 タスク
1. IDE で Properties ビューに移動して "Constraints" プロパティの行をクリックして Constraints
232
第28章 数字当ての例
Editor を開きます。
2. T o node T oo High の横の Edit ボタンをクリックして、様々なオプションが含まれているダイ
アログを開きます。T extual Editor ウィンドウの値は、LHS の標準ルール形式に従い、ワーキ
ングメモリのオブジェクトを参照します。LHS の式が T rue と評価された場合、結果 (RHS) では制
御のフローがこのノードに従います (T o node T oo High)。
バグを報告する
28.8. 数 字 当 て の 例 : コ ン ソ ー ル の 出 力
You have 5 out of 5 guesses left.
Please enter your guess from 0 to
50
Your guess was too high
You have 4 out of 5 guesses left.
Please enter your guess from 0 to
25
Your guess was too low
You have 3 out of 5 guesses left.
Please enter your guess from 0 to
37
Your guess was too low
You have 2 out of 5 guesses left.
Please enter your guess from 0 to
44
Your guess was too low
You have 1 out of 5 guesses left.
Please enter your guess from 0 to
47
Your guess was too low
You have no more guesses
The correct guess was 48
100
100
100
100
100
ファイル Num berGuess.java には m ain() メソッドが含まれているため、コマンドラインまたは
IDE から標準の Java アプリケーションとして実行できます。一般的なゲームであれば、上記のような
対話が行われるでしょう。太字の数字はユーザーが入力したものです。
Num berGuessExam ple.java の m ain() メソッドはルールベースを読み込み、ステートフルセッ
ションを作成して、そのセッションに Gam e、Gam eRules、Random Num ber (正解となる数字) オブ
ジェクトを挿入します。このメソッドは使用するプロセスフローを設定して、すべてのルールを発火
します。RuleFlow に制御が移動します。
RuleFlow ファイル Num berGuess.rf は "Start" ノードから開始します。
Guess ノードで、適切な Rule Flow Group ("Get user Guess") が有効になります。この場合
(Num berGuess.drl ファイル内の) "Guess" ルールがトリガーされます。このルールは、ユーザーに
メッセージを表示して、応答を受け取りワーキングメモリに挿入します。フローは、次の Rule Flow
ノードに移ります。
次のノード "Guess Correct" 制約が現在のセッションをチェックしてどのパスをたどるかを決定しま
す。
ステップ 4 で推理した数字が大きすぎる/小さすぎる場合、フローは、通常の Java コードを使用する
アクションノードがあるパスに進み適切なメッセージを出力して、Rule Flow Group が最大推理回数ま
たは最小推理回数ルールをトリガーします。フローはこれらのノードからステップ 6 に移ります。
ステップ 4 の推理が正しい場合、RuleFlow の終端へのパスを進んでいきます。これの前に、通常の
Java コードを使用するアクションノードが "You guessed correctly" とう文章を出力します。ここで
233
JBoss Enterprise BRMS Platform 5 JBoss Rules 5 リファレンスガイド
は結合ノードがあるため (ルールフローが終了する直前)、no-more-guesses パス (ステップ 7) も
RuleFlow を終了することができます。
結合ノードを経由して RuleFlow に従い制御が "guess incorrect" RuleFlow Group に移動し (ワーキン
グメモリから推理を削除するルールをトリガー)、”More Guesses" の決定ノードに移動します。
"More guesses" の決定ノード (ルールフローの右側) は制約を使用し、ルールがワーキングメモリに
挿入した値を確認し、ユーザーが推理ゲームを継続できるかどうかを決定します。継続できる場合、
ステップ 3 に進みます。できない場合、"you have no more guesses" と表示するルールをトリガーす
る RuleFlow Group を通り、RuleFlow の最後に進みます。
ステップ 3 から 7 までのループは、数字が正しく推理されるか、ユーザーが最大推理回数に到達する
まで、継続されます。
バグを報告する
234
改訂履歴
改訂履歴
改訂 5.0.0-1
Wed Jan 15 2014
Robot CS Builder [FAMILY
Given]
Built from Content Specification: 12778, Revision: 507496
235
Fly UP