こんにちは。渡邊です。
商用ルールエンジン、Corticonの研究をしています。
“Corticon Foundation User Guide.pdf” を一読しました。
概要についてはCorticon 5.3 : Corticon Foundation User Guide.pdf メモにまとめました。本記事では、Demand-Loading and Lazy-Loadingついて掘り下げます。
Vocabularyの編集者とRulesheetの編集者が異なる場合のシナリオについて考えます。
編集者が異なるという点はさほど重要ではありませんが、その方が本記事で言わんとしていることが理解しやすいのではないかと思います。Vocabulary編集者は語彙を登録し、同時にRulesheet編集者がスコープを定義しているとしましょう。
Rulesheet編集者側の視点で話を進めます。Presentation APIは、VocabularyとRulesheetとで独立しています。といって、IVocabularyTreeModelAPIとIRulesheetTableModelAPIを個別に生成するかというと、その必要はありません。次のように、IRulesheetTableModelAPIからVocabularyのCanonical APIを取得することができます。
IRulesheetTableModelAPI rulesheetAPI = RulesheetTableModelAPIFactory.getInstance(); rulesheetAPI.loadResource(fileName); IVocabularyModelAPI vocabularyAPI = rulesheetAPI.getVocabularyModelAPI();
スコープを追加する場合は、次のように書けます。
IRulesheetTableModelAPI rulesheetAPI = RulesheetTableModelAPIFactory.getInstance(); rulesheetAPI.loadResource(fileName); IEntity newEntity = rulesheetAPI.getVocabularyModelAPI().findEntity(name); rulesheetAPI.addScopeEntity(newEntity);
IRulesheetTableModelAPIにとって主となるRulesheetリソース(拡張子”.ers”)は、1次リソースといいます。一方、Vocabularyリソース(拡張子”.core”)は、2次リソースといいます。それぞれリソースのロードのタイミングが異なります。
1次リソースは、APIのloadResourceメソッド呼出し時にロードされます。2次リソースは、必要になったタイミングで遅延ロードされます。
注意する必要があるのは、いずれのリソースもロードされるのは一度だけロードという点です。その振る舞いを確認するコードを書きました。以下では重要箇所だけ説明します。完全なコードはこちらからダウンロード可能です。
メインロジック
Vocabulary編集者がエンティティ「商品」を登録、および保存した後に、Rulesheet編集者がリソースをロードしました。その時点では、エンティティ「注文」は保存されていないことに注目してください。
public void start(String vocabularyFileName, String rulesheetFileName) { // Vocabulary編集開始 VocabularyEditor vocabularyEditor = new VocabularyEditor(vocabularyFileName); vocabularyEditor.addEntity("商品"); vocabularyEditor.save(); vocabularyEditor.addEntity("注文"); // Rulesheet編集開始 RulesheetEditor rulesheetEditor = new RulesheetEditor(rulesheetFileName); rulesheetEditor.addScopeEntity("商品"); rulesheetEditor.addScopeEntity("注文"); vocabularyEditor.save(); rulesheetEditor.addScopeEntity("注文"); rulesheetEditor.load(rulesheetFileName); rulesheetEditor.addScopeEntity("注文"); rulesheetEditor.save(); // 後処理 vocabularyEditor.dispose(); rulesheetEditor.dispose(); }
Vocabulary編集者
直接生成しているのはIVocabularyTreeModelAPIだけです。
class VocabularyEditor { private IVocabularyTreeModelAPI vocabularyAPI; private Resource resource; public VocabularyEditor(String fileName) { systemout("Vocabulary> 編集を開始(API生成)します。"); vocabularyAPI = VocabularyTreeModelAPIFactory.getInstance(); load(fileName); } public void load(String fileName) { systemout("Vocabulary> リソースをロードします。"); resource = vocabularyAPI.loadResource(fileName); } public void addEntity(String name) { IEntity newEntity1 = vocabularyAPI.addEntity(); vocabularyAPI.setEntityName(newEntity1, name); systemout("Vocabulary> エンティティ'" + name + "'を語彙に追加しました。"); } public void save() { vocabularyAPI.saveResource(resource); systemout("Vocabulary> 保存しました。"); } public void dispose() { vocabularyAPI.dispose(); } }
Rulesheet編集者
直接生成しているのはIRulesheetTableModelAPIだけです。IRulesheetTableModelAPI経由でIVocabularyModelAPIを取得し、登録済みの語彙を取得しています。語彙が見つからない場合は、その旨をコンソール出力しています。
class RulesheetEditor { private IRulesheetTableModelAPI rulesheetAPI; private Resource resource; public RulesheetEditor(String fileName) { systemout("Rulesheet> 編集を開始(API生成)します。"); rulesheetAPI = RulesheetTableModelAPIFactory.getInstance(); load(fileName); } public void load(String fileName) { systemout("Rulesheet> リソースをロードします。"); resource = rulesheetAPI.loadResource(fileName); } public void addScopeEntity(String name) { IVocabularyModelAPI vocabularyAPI = rulesheetAPI.getVocabularyModelAPI(); IEntity newEntity = vocabularyAPI.findEntity(name); if (newEntity != null) { rulesheetAPI.addScopeEntity(newEntity); systemout("Rulesheet> エンティティ'" + name + "'をスコープに追加しました。"); } else { systemout("Rulesheet> エンティティ'" + name + "'は存在しません。スコープに登録できません。"); } } public void save() { rulesheetAPI.saveResource(resource); systemout("Rulesheet> 保存しました。"); } public void dispose() { rulesheetAPI.dispose(); } }
実行結果
Vocabulary編集者がエンティティ「注文」の登録を保存した後においても、IRulesheetTableModelAPIにその状態がロードされません。
01: Vocabulary> 編集を開始(API生成)します。 02: Vocabulary> リソースをロードします。 03: Vocabulary> エンティティ'商品'を語彙に追加しました。 04: Vocabulary> 保存しました。 05: Vocabulary> エンティティ'注文'を語彙に追加しました。 06: Rulesheet> 編集を開始(API生成)します。 07: Rulesheet> リソースをロードします。 08: Rulesheet> エンティティ'商品'をスコープに追加しました。 09: Rulesheet> エンティティ'注文'は存在しません。スコープに登録できません。 10: Vocabulary> 保存しました。 11: Rulesheet> エンティティ'注文'は存在しません。スコープに登録できません。 12: Rulesheet> リソースをロードします。 13: Rulesheet> エンティティ'注文'は存在しません。スコープに登録できません。 14: Rulesheet> 保存しました。
保存されたRulesheetをStudioから開きました。Rulesheet編集者がリソースを再読み込みしましたが、実際は読み込まれておらず、保存前の状態=スコープに「商品」が追加された状態が残っていました。