0

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

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 );
    }
}

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

更新:

这是读取 .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;
}
4

1 回答 1

1

A few options...

Pass in the simple name instead of the full class name.

Change

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

to

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

Change the 'accept' method to compare the full class name.

Change

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

to

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

Change the findFacts method to take the actual class as an argument and compare to that.

Change

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;
}

to

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;
}

Assuming that your facts are all Java classes, then the 3rd option of comparing the class is a better option. If you use declared types, then the simple name is useful, as you are unlikely to have a reference to the actual class that Drools generates.

An additional note for when you're testing these things, the Drools API also provides the session.getObjects() method with no arguments. By calling that you will get a reference to all facts that are in working memory, no matter what they are. When writing filters, it's not a bad idea to use that to prove to yourself that the expected facts are in working memory, and then to add filtering, so that you can pick out specific facts according to their class and their properties.

于 2013-11-10T09:55:41.733 回答