2016-11-30 14 views
0

Droolsを使用して常に最終的に(CTLに似た)クエリ操作を定義しようとしています。このツリーは、パスIDで注釈が付けられたノード(Artifacts)で構成されています。ツリー内のすべての分割(複数の子を持つ親)は、新しいパスIDを生成し、ファクトSplitFrom(child, parent)をナレッジベースに挿入することによって表されます。Drools:forallでのサブクエリの使用

基本的には、開始パスIDから、指定されたArtifactオブジェクトがツリーのすべてのパスに存在するかどうかを確認する必要があります。このOへの私の試みは以下の通りである:

query alwaysFinally(String $type, String $productName, long $parentPathId) 
    Artifact(type == $type, productName == $productName, pathId == $parentPathId) 
    or 
    forall(SplitFrom(parent == $parentPathId, $childPathId := child) 
     and 
     ?alwaysFinally($type, $productName, $childPathId;)) 
end 

残念ながら、これは、次のエラーが発生:

java.lang.RuntimeException: Build Errors: 
Error Messages: 
Message [id=1, level=ERROR, path=edu/umn/crisys/sim/agent/cognition/futureworld/rules/process/antecedent/commonAntecedents.drl, line=47, column=0 
    text=[ERR 102] Line 47:6 mismatched input '?' in query] 
Message [id=2, level=ERROR, path=edu/umn/crisys/sim/agent/cognition/futureworld/rules/process/antecedent/commonAntecedents.drl, line=0, column=0 
    text=Parser returned a null Package] 
... 

「私は、いくつかの異なる方法で括弧を挿入してプレイしましたが、私はドンそれが本当の問題だとは思わない。

java.lang.ClassCastException: org.drools.core.rule.QueryElement cannot be cast to org.drools.core.rule.Pattern 

    at org.drools.compiler.rule.builder.ForallBuilder.build(ForallBuilder.java:57) 
    at org.drools.compiler.rule.builder.ForallBuilder.build(ForallBuilder.java:32) 
    at org.drools.compiler.rule.builder.GroupElementBuilder.build(GroupElementBuilder.java:66) 
    at org.drools.compiler.rule.builder.GroupElementBuilder.build(GroupElementBuilder.java:36) 
    at org.drools.compiler.rule.builder.GroupElementBuilder.build(GroupElementBuilder.java:66) 
    at org.drools.compiler.rule.builder.RuleBuilder.build(RuleBuilder.java:97) 
    at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.addRule(KnowledgeBuilderImpl.java:1820) 
    at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.compileRules(KnowledgeBuilderImpl.java:1111) 
    at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.compileAllRules(KnowledgeBuilderImpl.java:989) 
    at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.buildRules(CompositeKnowledgeBuilderImpl.java:260) 
    at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.buildPackages(CompositeKnowledgeBuilderImpl.java:121) 
    at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.build(CompositeKnowledgeBuilderImpl.java:105) 
    at org.drools.compiler.kie.builder.impl.AbstractKieModule.buildKnowledgePackages(AbstractKieModule.java:243) 
    at org.drools.compiler.kie.builder.impl.AbstractKieProject.verify(AbstractKieProject.java:64) 
    at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieProject(KieBuilderImpl.java:230) 
    at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:198) 

私はクエリはPatternオブジェクトではありませんので、アキュムレータはここで働いてますとは思わない:私はandを削除し、コンマまたは改行で置き換えた場合、私は次のエラーを取得します。

誰でもDroolsでこれを表現する方法はありますか?

答えて

0

forallは必要ありません。これは、Droolsがすべてのマッチに対して自動的に行い、マッチングプロセスを続行するものです。 forallは、あなたがここで必要としない普遍的な量指定子です。なぜなら、条件がすべての事実の集合に対して真実である必要はないからです。

query alwaysFinally(String $type, String $productName, long $parentPathId) 
    Artifact(type == $type, productName == $productName, pathId == $parentPathId) 
    or 
    (SplitFrom(parent == $parentPathId, $childPathId := child) 
    and 
    ?alwaysFinally($type, $productName, $childPathId;) 
end 

アーティファクトが複数回発生すると、複数の一致が発生することがあります。

+0

おそらく私は説明が間違っています。私が実行すると、 "or"の後ろの部分があたかもあたかもあたかも指定された親を持つsplitFromの子パスがあり、子パスが常に最終的に成果物を含んでいるかのように動作し、真を返します。言い換えれば、現実的に定量化されているように振舞う。私が望むのはsplitFromsのすべての子であり、指定された親と各子パス(またはそこからのパス)にアーティファクトが含まれている場合はtrueを返します。私は子供のパスIDを収集してからそれらについてフォールリングを行うことを考えましたが、もう一度、その上でクエリを呼び出すことは機能していません。 – desilvai

0

ロジックルールが勝ちました。 「または」ステートメントの後半すぐ

let childPathIds: { SplitFrom(parent == $parentPathId, child := childPathId } 
forall x in childPathIds, P(x) 

(集合表記法を使用して)として表すことができる、我々は二重否定とアイデンティティを維持することができます。これは、私たちを取得します。したがって、それは次のよう

accumulate(SplitFrom(parent == $parentPathId, $childPathId := child); 
         $childPaths: collectSet($childPathId)) 
and 
// Set non-empty 
exists($childPathId: Long() from $childPaths) 
and 
(not(exists($childPathId: Long() from $childPaths 
     and 
     not (?alwaysFinally($type, $productName, $childPathId;)))) 
) 

お知らせ追加の非空のチェックを使用してdoolsで表すことができ

let childPathIds: { SplitFrom(parent == $parentPathId, child := childPathId } 
exists x in childPathIds, not P(x) 

$childPathsが空の場合、3番目の条件はtrueを返すので、これが必要です。

それで、ストーリーの道徳:はい、私たちはサブクエリで全部をキャプチャすることができます。しかし、それを行うにはもっとはっきりとした構文を使わなければなりません。少なくとも、Javaを実装する必要はありません。

関連する問題