読者です 読者をやめる 読者になる 読者になる

Drools でルールの有効期間を指定する - date-effective, date-expires

Drools の DRL ではルール毎の有効期間を以下のルール属性を使って指定できるようになっています。

  • date-effective 開始日時
  • date-expires 終了日時

どちらも日付の指定に文字列が使えますが、デフォルトの日付フォーマットが "dd-MMM-yyyy" となっており、これ以外のフォーマットで日付を指定するとエラーが発生します。

ただし、以下のようにシステムプロパティ drools.dateformat の値を変更する事で任意の日付フォーマットが使えます。

Drools 日付フォーマットの変更例 ("2012-02-02 01:00:00" のような日付を指定できるようにするための設定)
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");

以下の例のようにルールを定義すると 2012-02-02 00:30:00 から 2012-02-03 00:30:00 の期間内に実行した場合にのみこのルールが有効になります。(drools.dateformat を上記のように変更している事が前提)

DRL 例(date-effective と date-expires の使用)
rule "・・・"
    ・・・
    date-effective "2012-02-02 00:30:00"
    date-expires "2012-02-03 00:30:00"
    ・・・
    when
      ・・・
    then
      ・・・

ちなみに、date-effective と date-expires はどちらか片方だけを指定することもできます。

ルールの有効期間を指定したサンプル

以下では date-effective と date-expires を使った簡単なサンプルを Groovy で実装してみました。

サンプルソースは http://github.com/fits/try_samples/tree/master/blog/20120202/

effective_expires_sample.groovy
@Grab("org.drools:drools-core:5.4.0.Beta2")
@Grab("org.drools:drools-compiler:5.4.0.Beta2")
@Grab("com.sun.xml.bind:jaxb-xjc:2.2.5-b09")
import org.drools.KnowledgeBaseFactory
import org.drools.builder.KnowledgeBuilderFactory
import org.drools.builder.ResourceType
import org.drools.io.ResourceFactory

def drl = '''
dialect "mvel"

rule "ルール1"
    no-loop
    salience 20
    date-effective "2012-02-02 00:30:00"
    date-expires "2012-02-03 00:30:00"
    when
        $d : Data(done == false)
    then
        System.out.println("*** ルール1")
        $d.setDone(true)
        update($d)
end

rule "ルール2"
    no-loop
    salience 10
    when
        $d : Data(done == false)
    then
        System.out.println("*** ルール2")
        $d.setDone(true)
        update($d)
end
'''

class Data {
    def done = false
}

def createSession = {drlString ->
    def builder = KnowledgeBuilderFactory.newKnowledgeBuilder()

    builder.add(ResourceFactory.newReaderResource(new StringReader(drlString)), ResourceType.DRL)

    if (builder.hasErrors()) {
        println builder.errors
        throw new RuntimeException("invalid DRL")
    }

    def base = KnowledgeBaseFactory.newKnowledgeBase()
    base.addKnowledgePackages(builder.getKnowledgePackages())

    base.newStatefulKnowledgeSession()
}

//Drools デフォルトの日付フォーマットを変更
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss")

def session = createSession(drl)

session.insert(new Data())

session.fireAllRules()
session.dispose()


このスクリプトを実行した日時が有効期間内 *1 であれば "ルール1" が適用され、期間外であれば "ルール2" が適用される事を確認できます。

実行結果例1(有効期間内に実行した場合)
> groovy effective_expires_sample.groovy
*** ルール1
実行結果例2(有効期間外に実行した場合)
> groovy effective_expires_sample.groovy
*** ルール2

*1:date-effective で指定した日時から date-expires で指定した日時までの期間