1. 程式人生 > >Drools學習筆記2—Conditions / LHS 匹配模式&條件元素

Drools學習筆記2—Conditions / LHS 匹配模式&條件元素

  • Rule的LHS由條件元素(Conditional Elements—CE)和匹配模式(Patterns)組成
  • Patterns被用來指示出fact的欄位約束
  • 每個約束必須為true才能讓RHS的actions fire

測試程式碼,測試用獲取KnowledgeBase方法:

  /**
   * 獲取KnowledgeBase
   * @return
   * @throws Exception
   */
  private static KnowledgeBase readKnowledgeBase(String ruleName) throws Exception {
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newClassPathResource(ruleName, RuleTest.class), ResourceType.DRL);
    KnowledgeBuilderErrors errors = kbuilder.getErrors();
    if (errors.size() > 0) {
        for (KnowledgeBuilderError error: errors) {
            System.err.println(error);
        }
        throw new IllegalArgumentException("Could not parse knowledge.");
    }
    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
    return kbase;
}

使用到的fact物件

package com.bean;

import java.util.ArrayList;
import java.util.List;

public class Customer {
  private String name;
  private String Company;
  private Integer age;
  private String gender;
  private String city;
  private List<Account> accounts = new ArrayList<Account>();
  //省略set、get、toString方法  
}
package com.bean;

public class Account {
  private String name;
  private String status;
  private int num;
}

匹配模式(Patterns)

  • 沒有欄位約束的Pattern

    Person()

/**規則檔案.drl**/
package com.sample
 
import  com.bean.Customer;
 
 
 rule "No args"
    when
       Customer()
    then
        System.out.println( "no massage" );
end


/**java測試程式碼,採用Junit測試**/
  /**
   * 沒有欄位約束的Pattern
   * @throws Exception
   */
  @Test
  public void testNoParam() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("NoParam.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    ksession.insert(customer);
    ksession.fireAllRules();
    logger.close();
  }
  • 有文字欄位約束的Pattern

    Person( name == “bob” )

/**規則檔案.drl**/
package com.sample
 
import  com.bean.Customer;
 
 
 rule "Binding Param"
    when
       Customer($name:name=="七夜雪")
    then
        System.out.println( "Binding Param Rule and Customer is " + $name );
end


/**java測試程式碼,採用Junit測試**/
  /**
   * 有文字欄位約束的Pattern
   * @throws Exception
   */
    Customer customer = new Customer();
    customer.setName("七夜雪");
    ksession.insert(customer);
    ksession.fireAllRules();
  • 欄位繫結的Pattern

    Person( $name : name == “bob” )
    變數名稱可以是任何合法的java變數,$是可選的,可由於區分欄位和變數

//drl規則檔案
package com.sample
 
import  com.bean.Customer;
 
 rule "Binding Fact"
    when
       $customer:Customer(name=="七夜雪")
    then
        System.out.println( "Binding Fact Rule :"  + $customer );
end
  /**
   * java測試方法
   * 欄位繫結的Pattern
   * @throws Exception
   */
  @Test
  public void testBindingParam() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("HaveParam.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    customer.setName("七夜雪");
    ksession.insert(customer);
    ksession.fireAllRules();
    logger.close();
  }
  • Fact繫結的Pattern

    $bob : Person( name == “bob” )欄位繫結的Pattern

//drl檔案
package com.sample
 
import  com.bean.Customer;
 
 rule "Binding Fact"
    when
       $customer:Customer(name=="七夜雪")  //繫結變數$customer變數名
then 
  System.out.println( "Binding Fact Rule :" + $customer ); 
end
  /**
   * Fact繫結的Pattern
   * @throws Exception
   */
  @Test
  public void testBindingFact() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("BindingFact.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    customer.setName("七夜雪");
    customer.setCompany("聽雪樓");
    ksession.insert(customer);
    ksession.fireAllRules();
    logger.close();
  }
  • 變數約束的Pattern

    Person( name == $name )

package com.sample
 
import  com.bean.Customer;
import  com.bean.Account;
 
 
 rule "Param Limit"
    when
       Customer($name:name=="七夜雪")
       Account(name==$name)
    then
        System.out.println( "Param Limit Rule"  );
end 
 /**
   * 變數約束的Pattern
   * @throws Exception
   */
  @Test
  public void testParamLimit() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("ParamLimit.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    customer.setName("七夜雪");
    customer.setCompany("聽雪樓");
    Account account = new Account();
    account.setName("七夜雪");
    ksession.insert(customer);
    ksession.insert(account);
    ksession.fireAllRules();
    logger.close();
  }

條件元素(Conditional Elements)

    and

  • 對於頂級(非巢狀)patterns是隱式成立的
  • 可以顯示add
  • 使用關鍵字’and’(不推薦使用 &&)
package com.sample
 
import  com.bean.Customer;
import  com.bean.Account;
 
 
 rule "And"
    when
       Customer(name=="七夜雪" ) and
       Account(name=="七夜雪")
    then
        System.out.println( "And Rule"  );
end
 
 
  rule "Default"
    when
       Customer(name=="七夜雪" ) 
       Account(name=="七夜雪")
    then
        System.out.println( "default  is and"  );
end


 rule "&&"
    when
       Customer(name=="七夜雪" ) &&
       Account(name=="七夜雪")
    then
        System.out.println( "And && Rule"  );
end
  /**
   * 條件元素 and、&&,不寫預設為and
   * @throws Exception
   */
  @Test
  public void testAndRule() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("And.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    customer.setName("七夜雪");
    Account account = new Account();
    account.setName("七夜雪");
    ksession.insert(customer);
    ksession.insert(account);
    ksession.fireAllRules();
    logger.close();
  }

 or

  • 列能被顯式or
  • 使用關鍵字’or’(不推薦使用 ||)
package com.sample
 
import  com.bean.Customer;
import  com.bean.Account;
 
 
 rule "Or"
    when
       Customer(name=="七夜雪" ) or
       Account(name=="七夜雪")
    then
        System.out.println( "And Rule"  );
end
  /**
   * 條件元素 or,不寫預設為and
   * 注:每個條件符合,then的內容都會執行一次
   * @throws Exception
   */
  @Test
  public void testOrRule() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("Or.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    customer.setName("七夜雪");
    Account account = new Account();
    account.setName("七夜雪");
    ksession.insert(customer);
    ksession.insert(account);
    ksession.fireAllRules();
    logger.close();
  }

exists 、Not

package com.sample
 
import  com.bean.Customer;
import  com.bean.Account;
 
 
 rule "Exists"
    when
       exists Customer()  //工作空間存在customer物件
    then
        System.out.println( "Customer Exists"  );
end


 rule "Not"
    when
      not  Account()  //工作空間不存在Account物件
    then
        System.out.println( "Account Not Exists"  );
 end
  /**
   * 條件元素 exist、not,兩個剛好相反
   * 
   * @throws Exception
   */
  @Test
  public void testExistsAndNotRule() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("From.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    Account account = new Account();
    account.setName("七夜雪");
    Account account1 = new Account();
    account.setName("碧落");
    customer.getAccounts().add(account);
    customer.getAccounts().add(account1);
    ksession.insert(customer);
    ksession.fireAllRules();
    logger.close();
  }

  from

package com.sample
 
import  com.bean.Customer;
import  com.bean.Account;
 
 
 rule "from"
    when
       $customer:Customer( )
    //customer中的accounts列表中存在name="碧落"的account物件
       Account(name=="碧落") from $customer.accounts 
    then
        System.out.println( "from element test success"  );
end
  /**
   * 條件元素 from
   * 
   * @throws Exception
   */
  @Test
  public void testFromRule() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("From.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    ksession.insert(customer);
    ksession.fireAllRules();
    logger.close();
  }

collect

package com.sample
 
import  com.bean.Customer;
import  com.bean.Account;
import  java.util.ArrayList;
 
 rule "collect"
    when
       $customer:Customer( )
    //列表中status="Y"的Account物件大於等於4個,
       $accounts:ArrayList(size >= 4) from collect (Account(status == "Y"))
    then
        System.out.println( "collect element test success"  );
end
  /**
   * 條件元素 collect
   * 
   * @throws Exception
   */
  @Test
  public void testCollectRule() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("Collect.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    Account account1 = new Account();
    account1.setStatus("Y");
    Account account2 = new Account();
    account2.setStatus("Y");
    Account account3= new Account();
    account3.setStatus("Y");
    Account account4 = new Account();
    account4.setStatus("Y");
    ksession.insert(customer);
    ksession.insert(account1);
    ksession.insert(account2);
    ksession.insert(account3);
    ksession.insert(account4);
    ksession.fireAllRules();
    logger.close();
  }

Accumulate 聚合函式

package com.sample
 
import  com.bean.Customer;
import  com.bean.Account;
 
 rule "accumulate"
    when
    //工作空間中,account物件的num屬性之和大於400時符合規則
       $total:Number( intValue > 400)
       from accumulate (Account($num:num),sum($num))
    then
        System.out.println( "accumulate element test success"  );
end
  /**
   * 條件元素 Accumulate
   * 聚合函式
   * @throws Exception
   */
  @Test
  public void testAccumulateRule() throws Exception {
    KnowledgeBase kbase = readKnowledgeBase("Accumulate.drl");
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
    Customer customer = new Customer();
    Account account1 = new Account();
    account1.setNum(100);
    Account account2 = new Account();
    account2.setNum(100);
    Account account3= new Account();
    account3.setNum(100);
    Account account4 = new Account();
    account4.setNum(200);
    ksession.insert(customer);
    ksession.insert(account1);
    ksession.insert(account2);
    ksession.insert(account3);
    ksession.insert(account4);
    ksession.fireAllRules();
    logger.close();
  }