从有状态的drools会话中获取事实

时间:2013-11-10 00:29:59

标签: java drools

我正试图从规则中获取新的插入事实:

import com.neu.als.thesis.db.beans.FLTBean
import com.neu.als.thesis.db.beans.StudentBean

rule "Excellent"
    no-loop

    when
        $m: FLTBean ( listeningScore > 85 && listeningScore < 101 )
    then
        StudentBean studentBean = new StudentBean();
        studentBean.setKnowledgeLevel( "Excellent" );
        insert( studentBean );
end

要从有状态会话中获取内容,我应该这样做:

protected Collection<Object> findFacts( final StatefulKnowledgeSession session, final String factClass )
{
    ObjectFilter filter = new ObjectFilter()
    {
        @Override
        public boolean accept( Object object )
        {
            return object.getClass().equals( factClass );
        }
    };
    Collection<Object> results = session.getObjects( filter );
    return results;
}

鉴于我已经将代码设置为读取规则,我所做的下一步是:

protected void processFacts( KnowledgeBase aKnowledgeBase, Object aBean )
{
    StatefulKnowledgeSession ksession = aKnowledgeBase.newStatefulKnowledgeSession();

    ksession.insert( aBean );
    ksession.fireAllRules();

    Collection<Object> result = findFacts( ksession, "StudentBean" );

    ksession.dispose();

    for( Object test : result )
    {
        System.out.println( test == null );
        System.out.println( test );
    }
}

为什么我没有得到对象的任何回复?它不打印任何东西。没有堆栈跟踪,没有错误。我甚至检查它是否为null。但仍然没有回应。我做错了什么?

更新

这是读取.drl文件的方法。

protected KnowledgeBase readKnowledgeBase( String aRuleFileName ) throws Exception
{
     KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
     kbuilder.add( ResourceFactory.newClassPathResource( aRuleFileName, getClass() ), 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;
}

调用processFacts方法的是

public String evaluateConceptKnowledgeLevel( double FLTmark )
{
   String knowledgeLevel = null;

   // test
   InferenceEngine ie = new InferenceEngine();
   KnowledgeBase kbase;
   try
   {
       kbase = ie.readKnowledgeBase( "KnowledgeLevel.drl" );
       FLTBean bean = new FLTBean();
       bean.setListeningScore( FLTmark );

       ie.processFacts( kbase, bean );
   }
   catch( Exception e )
   {
       e.printStackTrace();
   }
   // up to here

   return knowledgeLevel;
}

1 个答案:

答案 0 :(得分:1)

一些选择......

传入简单名称而不是完整的班级名称。

更改

Collection<Object> result = findFacts( ksession, "com.neu.als.thesis.db.beans.StudentBean" );

Collection<Object> result = findFacts( ksession, "StudentBean" );

更改'accept'方法以比较完整的班级名称。

更改

     public boolean accept( Object object ) {
         return object.getClass().getSimpleName().equals( factClass );
     }

     public boolean accept( Object object ) {
         return object.getClass().getName().equals( factClass );
     }

更改find​​Facts方法,将实际的类作为参数并与之比较。

更改

protected Collection<Object> findFacts( 
        final StatefulKnowledgeSession session, 
        final String factClass ) {
    ObjectFilter filter = new ObjectFilter() {
    @Override
        public boolean accept( Object object ) {
            return object.getClass().getSimpleName().equals( factClass );
        }
    };

    Collection<Object> results = session.getObjects( filter );
    return results;
}

protected Collection<Object> findFacts( 
        final StatefulKnowledgeSession session, 
        final Class factClass ) {
    ObjectFilter filter = new ObjectFilter() {
    @Override
        public boolean accept( Object object ) {
            return object.getClass().equals( factClass );
        }
    };

    Collection<Object> results = session.getObjects( filter );
    return results;
}

假设您的事实都是Java类,那么比较该类的第3个选项是更好的选择。如果使用声明的类型,那么简单名称很有用,因为您不太可能引用Drools生成的实际类。

当您测试这些内容时,Drools API还提供了没有参数的session.getObjects()方法。通过调用,您将获得对工作记忆中所有事实的引用,无论它们是什么。在编写过滤器时,使用它来向自己证明预期的事实在工作记忆中,然后添加过滤,这样你就可以根据它们的类和属性选择特定的事实,这不是一个坏主意。