Drools 口齿不清复杂的事实

Drools 口齿不清复杂的事实,drools,drools-guvnor,Drools,Drools Guvnor,我一直在研究如何简化我的一些规则,这些规则是用DRL手工编写的,很难维护 通过谷歌搜索,结果是“决策表是最好的搜索方式” 但不幸的是,我们的事实非常复杂,所以目前drools无法处理如此复杂的事实 因此,第一个问题是开发人员通常如何处理drools知识库中非常复杂的事实 例如,我们有如下事实 Person->List<Cars>->List<Insurances>->Each insurance Has List<History> 人员->

我一直在研究如何简化我的一些规则,这些规则是用DRL手工编写的,很难维护

通过谷歌搜索,结果是“决策表是最好的搜索方式”

但不幸的是,我们的事实非常复杂,所以目前drools无法处理如此复杂的事实

因此,第一个问题是开发人员通常如何处理drools知识库中非常复杂的事实

例如,我们有如下事实

Person->List<Cars>->List<Insurances>->Each insurance Has List<History>
人员->列表->列表->每个保险都有列表
现在我必须写一条规则,说这个人的保险索赔历史不好。然后我发现很难将其放入speadsheet,因为手动将此规则写入drl文件更容易


谢谢你的帮助。上述示例的任何帮助都将非常有用。

对于类似这样的复杂规则,我们使用Drools模板。您可以为要填充的字段编写带有参数扩展的规则模板,并且在填充骨架规则的实际值的来源方面具有更大的灵活性

这个功能内置于Drools Guvnor中,但是通过GUI编写复杂的规则模板有些繁琐。我还编写了独立Java来从属性文件中提取的值列表中填充模板drl文件,最近还开发了一个SmartGWT web应用程序,允许用户填充规则值并生成drl

编辑:添加示例程序。DroolTemplateBuilder创建TestType对象的列表,这些对象的字段映射到Test.drl中的模板键。生成的DRL被打印并编译成一个pkg,该pkg被写入一个名为Test.pkg的文件

库:antlr-3.3.jar、antlr-runtime-3.3.jar、drools-compiler-5.2.0.Final.jar、drools-core-5.2.0.Final.jar、drools-templates-5.2.0.Final.jar、ecj-4.2.jar、knowledge-api-5.2.0.Final.jar、mvel2-2.1.0.drools.jar(这些可能都不是必需的)

注意:此示例使用5.2.0库,在较新版本中,某些功能可能有所不同。xml应该清楚地说明如何构造项目

DroolsTemplateBuilder.java:

package some.test.pkg;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;

import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.common.DroolsObjectOutputStream;
import org.drools.definitions.impl.KnowledgePackageImp;
import org.drools.io.ResourceFactory;
import org.drools.template.ObjectDataCompiler;

public class DroolsTemplateBuilder {

    private String filePath;
    private String drl;

    public static void main(String[] args) {
        DroolsTemplateBuilder test = new DroolsTemplateBuilder();
        test.filePath = args[0] + File.separator + "Test.drl";
        test.runTest();
    }

    public void runTest() {
        buildPackage();
        writeRulePackageToFile();
    }

    public void buildPackage() {

        Collection<Object> templateList = new ArrayList<Object>();
        templateList.add(new TestType(1, "John", "Manager"));
        templateList.add(new TestType(2, "Peter", "CEO"));
        templateList.add(new TestType(3, "Kate", "Engineer"));

        try {
            ObjectDataCompiler converter = new ObjectDataCompiler();
            InputStream templateStream = new FileInputStream(filePath);

            String myDrl = inputStreamToString(templateStream, 200);
            // I use this ##### replacement instead of just a newline in the
            // template
            // because of windows/linux issues with newline and carriage return.
            // Drools template
            // builder, at least in 5.2.0, was very picky about the template
            // structure, including
            // where newlines are expected.
            myDrl = myDrl.replaceAll("#####", "\n");

            InputStream tempStream = new ByteArrayInputStream(myDrl.getBytes());

            drl = converter.compile(templateList, tempStream);
            System.out.println(drl);
        } catch (Exception e) {
            System.out.println("Exception: " + e.getMessage());
        }

    }

    public void writeRulePackageToFile() {
        try {
            KnowledgeBuilder kBuilder = KnowledgeBuilderFactory
                    .newKnowledgeBuilder();

            Reader rdr = new StringReader(drl);

            kBuilder.add(ResourceFactory.newReaderResource(rdr),
                    ResourceType.DRL);

            if (kBuilder.hasErrors()) {
                System.out.println("Drools blew up on");
                for (KnowledgeBuilderError err : kBuilder.getErrors()) {
                    System.out.println(err.getMessage());
                }
            } else {
                String outFile = filePath.replaceFirst("\\.drl", ".pkg");
                OutputStream os = new FileOutputStream(outFile);
                ObjectOutputStream oos = new DroolsObjectOutputStream(os);
                KnowledgePackageImp kPackage = (KnowledgePackageImp) kBuilder
                        .getKnowledgePackages().iterator().next();
                oos.writeObject(kPackage);
                oos.close();
            }
        } catch (Exception e) {
            System.out.println("Exception " + e.getMessage());
        }
    }

    public String inputStreamToString(final InputStream is, final int bufferSize) {
        final char[] buffer = new char[bufferSize];
        final StringBuilder out = new StringBuilder();
        try {
            final Reader in = new InputStreamReader(is, "UTF-8");
            try {
                for (;;) {
                    int rsz = in.read(buffer, 0, buffer.length);
                    if (rsz < 0)
                        break;
                    out.append(buffer, 0, rsz);
                }
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println("Something went wrong: " + ex.getMessage());
        }
        return out.toString();
    }

}
template header
id
name
title
#####
package some.test.pkg;

template "sampleTemplate"

rule "id filter_@{row.rowNumber}"
no-loop true
dialect "java"
when
    $t : TestType(id=="@{id}")
then
    System.out.println("Doing something special...");
end

end template

template "anotherSample"

rule "another rule_@{row.rowNumber}"
no-loop true
dialect "java"
when
    $t : TestType((name=="@{name}") || (title=="@{title}"))
then
    System.out.println("Doing something else...");
end

end template
package some.test.pkg;

public class TestType {

    private int id;
    private String name;
    private String title;

    public TestType(int id, String name, String title) {
        this.id = id;
        this.name = name;
        this.title = title;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}
<project name="TemplateTest" basedir="." default="jar">

    <property name="src.dir" value="src" />

    <property name="build.dir" value="build" />
    <property name="drl.dir" value="${basedir}/drl" />
    <property name="classes.dir" value="${build.dir}/classes" />
    <property name="jar.dir" value="${build.dir}/jar" />
    <property name="lib.dir" value="${basedir}/lib" />

    <path id="compile.classpath">
        <fileset dir="${lib.dir}" includes="*.jar" />
    </path>

    <path id="run.classpath">
        <fileset dir="${jar.dir}" includes="*.jar" />
        <fileset dir="${lib.dir}" includes="*.jar" />
    </path>

    <target name="clean">
        <delete dir="${classes.dir}" />
        <delete dir="${jar.dir}" />
    </target>

    <target name="compile" depends="clean">
        <mkdir dir="${classes.dir}" />
        <mkdir dir="${jar.dir}" />
        <javac includeantruntime="false" srcdir="${src.dir}" classpathref="compile.classpath" destdir="${classes.dir}" />
    </target>

    <target name="jar" depends="compile">
        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
        </jar>
    </target>

    <target name="run" depends="jar" description="run">
        <java classpathref="run.classpath" classname="some.test.pkg.DroolsTemplateBuilder" fork="true">
            <arg value="${drl.dir}" />
        </java>
    </target>

</project>
TestType.java:

package some.test.pkg;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;

import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.common.DroolsObjectOutputStream;
import org.drools.definitions.impl.KnowledgePackageImp;
import org.drools.io.ResourceFactory;
import org.drools.template.ObjectDataCompiler;

public class DroolsTemplateBuilder {

    private String filePath;
    private String drl;

    public static void main(String[] args) {
        DroolsTemplateBuilder test = new DroolsTemplateBuilder();
        test.filePath = args[0] + File.separator + "Test.drl";
        test.runTest();
    }

    public void runTest() {
        buildPackage();
        writeRulePackageToFile();
    }

    public void buildPackage() {

        Collection<Object> templateList = new ArrayList<Object>();
        templateList.add(new TestType(1, "John", "Manager"));
        templateList.add(new TestType(2, "Peter", "CEO"));
        templateList.add(new TestType(3, "Kate", "Engineer"));

        try {
            ObjectDataCompiler converter = new ObjectDataCompiler();
            InputStream templateStream = new FileInputStream(filePath);

            String myDrl = inputStreamToString(templateStream, 200);
            // I use this ##### replacement instead of just a newline in the
            // template
            // because of windows/linux issues with newline and carriage return.
            // Drools template
            // builder, at least in 5.2.0, was very picky about the template
            // structure, including
            // where newlines are expected.
            myDrl = myDrl.replaceAll("#####", "\n");

            InputStream tempStream = new ByteArrayInputStream(myDrl.getBytes());

            drl = converter.compile(templateList, tempStream);
            System.out.println(drl);
        } catch (Exception e) {
            System.out.println("Exception: " + e.getMessage());
        }

    }

    public void writeRulePackageToFile() {
        try {
            KnowledgeBuilder kBuilder = KnowledgeBuilderFactory
                    .newKnowledgeBuilder();

            Reader rdr = new StringReader(drl);

            kBuilder.add(ResourceFactory.newReaderResource(rdr),
                    ResourceType.DRL);

            if (kBuilder.hasErrors()) {
                System.out.println("Drools blew up on");
                for (KnowledgeBuilderError err : kBuilder.getErrors()) {
                    System.out.println(err.getMessage());
                }
            } else {
                String outFile = filePath.replaceFirst("\\.drl", ".pkg");
                OutputStream os = new FileOutputStream(outFile);
                ObjectOutputStream oos = new DroolsObjectOutputStream(os);
                KnowledgePackageImp kPackage = (KnowledgePackageImp) kBuilder
                        .getKnowledgePackages().iterator().next();
                oos.writeObject(kPackage);
                oos.close();
            }
        } catch (Exception e) {
            System.out.println("Exception " + e.getMessage());
        }
    }

    public String inputStreamToString(final InputStream is, final int bufferSize) {
        final char[] buffer = new char[bufferSize];
        final StringBuilder out = new StringBuilder();
        try {
            final Reader in = new InputStreamReader(is, "UTF-8");
            try {
                for (;;) {
                    int rsz = in.read(buffer, 0, buffer.length);
                    if (rsz < 0)
                        break;
                    out.append(buffer, 0, rsz);
                }
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println("Something went wrong: " + ex.getMessage());
        }
        return out.toString();
    }

}
template header
id
name
title
#####
package some.test.pkg;

template "sampleTemplate"

rule "id filter_@{row.rowNumber}"
no-loop true
dialect "java"
when
    $t : TestType(id=="@{id}")
then
    System.out.println("Doing something special...");
end

end template

template "anotherSample"

rule "another rule_@{row.rowNumber}"
no-loop true
dialect "java"
when
    $t : TestType((name=="@{name}") || (title=="@{title}"))
then
    System.out.println("Doing something else...");
end

end template
package some.test.pkg;

public class TestType {

    private int id;
    private String name;
    private String title;

    public TestType(int id, String name, String title) {
        this.id = id;
        this.name = name;
        this.title = title;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}
<project name="TemplateTest" basedir="." default="jar">

    <property name="src.dir" value="src" />

    <property name="build.dir" value="build" />
    <property name="drl.dir" value="${basedir}/drl" />
    <property name="classes.dir" value="${build.dir}/classes" />
    <property name="jar.dir" value="${build.dir}/jar" />
    <property name="lib.dir" value="${basedir}/lib" />

    <path id="compile.classpath">
        <fileset dir="${lib.dir}" includes="*.jar" />
    </path>

    <path id="run.classpath">
        <fileset dir="${jar.dir}" includes="*.jar" />
        <fileset dir="${lib.dir}" includes="*.jar" />
    </path>

    <target name="clean">
        <delete dir="${classes.dir}" />
        <delete dir="${jar.dir}" />
    </target>

    <target name="compile" depends="clean">
        <mkdir dir="${classes.dir}" />
        <mkdir dir="${jar.dir}" />
        <javac includeantruntime="false" srcdir="${src.dir}" classpathref="compile.classpath" destdir="${classes.dir}" />
    </target>

    <target name="jar" depends="compile">
        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
        </jar>
    </target>

    <target name="run" depends="jar" description="run">
        <java classpathref="run.classpath" classname="some.test.pkg.DroolsTemplateBuilder" fork="true">
            <arg value="${drl.dir}" />
        </java>
    </target>

</project>
build.xml:

package some.test.pkg;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;

import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.common.DroolsObjectOutputStream;
import org.drools.definitions.impl.KnowledgePackageImp;
import org.drools.io.ResourceFactory;
import org.drools.template.ObjectDataCompiler;

public class DroolsTemplateBuilder {

    private String filePath;
    private String drl;

    public static void main(String[] args) {
        DroolsTemplateBuilder test = new DroolsTemplateBuilder();
        test.filePath = args[0] + File.separator + "Test.drl";
        test.runTest();
    }

    public void runTest() {
        buildPackage();
        writeRulePackageToFile();
    }

    public void buildPackage() {

        Collection<Object> templateList = new ArrayList<Object>();
        templateList.add(new TestType(1, "John", "Manager"));
        templateList.add(new TestType(2, "Peter", "CEO"));
        templateList.add(new TestType(3, "Kate", "Engineer"));

        try {
            ObjectDataCompiler converter = new ObjectDataCompiler();
            InputStream templateStream = new FileInputStream(filePath);

            String myDrl = inputStreamToString(templateStream, 200);
            // I use this ##### replacement instead of just a newline in the
            // template
            // because of windows/linux issues with newline and carriage return.
            // Drools template
            // builder, at least in 5.2.0, was very picky about the template
            // structure, including
            // where newlines are expected.
            myDrl = myDrl.replaceAll("#####", "\n");

            InputStream tempStream = new ByteArrayInputStream(myDrl.getBytes());

            drl = converter.compile(templateList, tempStream);
            System.out.println(drl);
        } catch (Exception e) {
            System.out.println("Exception: " + e.getMessage());
        }

    }

    public void writeRulePackageToFile() {
        try {
            KnowledgeBuilder kBuilder = KnowledgeBuilderFactory
                    .newKnowledgeBuilder();

            Reader rdr = new StringReader(drl);

            kBuilder.add(ResourceFactory.newReaderResource(rdr),
                    ResourceType.DRL);

            if (kBuilder.hasErrors()) {
                System.out.println("Drools blew up on");
                for (KnowledgeBuilderError err : kBuilder.getErrors()) {
                    System.out.println(err.getMessage());
                }
            } else {
                String outFile = filePath.replaceFirst("\\.drl", ".pkg");
                OutputStream os = new FileOutputStream(outFile);
                ObjectOutputStream oos = new DroolsObjectOutputStream(os);
                KnowledgePackageImp kPackage = (KnowledgePackageImp) kBuilder
                        .getKnowledgePackages().iterator().next();
                oos.writeObject(kPackage);
                oos.close();
            }
        } catch (Exception e) {
            System.out.println("Exception " + e.getMessage());
        }
    }

    public String inputStreamToString(final InputStream is, final int bufferSize) {
        final char[] buffer = new char[bufferSize];
        final StringBuilder out = new StringBuilder();
        try {
            final Reader in = new InputStreamReader(is, "UTF-8");
            try {
                for (;;) {
                    int rsz = in.read(buffer, 0, buffer.length);
                    if (rsz < 0)
                        break;
                    out.append(buffer, 0, rsz);
                }
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println("Something went wrong: " + ex.getMessage());
        }
        return out.toString();
    }

}
template header
id
name
title
#####
package some.test.pkg;

template "sampleTemplate"

rule "id filter_@{row.rowNumber}"
no-loop true
dialect "java"
when
    $t : TestType(id=="@{id}")
then
    System.out.println("Doing something special...");
end

end template

template "anotherSample"

rule "another rule_@{row.rowNumber}"
no-loop true
dialect "java"
when
    $t : TestType((name=="@{name}") || (title=="@{title}"))
then
    System.out.println("Doing something else...");
end

end template
package some.test.pkg;

public class TestType {

    private int id;
    private String name;
    private String title;

    public TestType(int id, String name, String title) {
        this.id = id;
        this.name = name;
        this.title = title;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}
<project name="TemplateTest" basedir="." default="jar">

    <property name="src.dir" value="src" />

    <property name="build.dir" value="build" />
    <property name="drl.dir" value="${basedir}/drl" />
    <property name="classes.dir" value="${build.dir}/classes" />
    <property name="jar.dir" value="${build.dir}/jar" />
    <property name="lib.dir" value="${basedir}/lib" />

    <path id="compile.classpath">
        <fileset dir="${lib.dir}" includes="*.jar" />
    </path>

    <path id="run.classpath">
        <fileset dir="${jar.dir}" includes="*.jar" />
        <fileset dir="${lib.dir}" includes="*.jar" />
    </path>

    <target name="clean">
        <delete dir="${classes.dir}" />
        <delete dir="${jar.dir}" />
    </target>

    <target name="compile" depends="clean">
        <mkdir dir="${classes.dir}" />
        <mkdir dir="${jar.dir}" />
        <javac includeantruntime="false" srcdir="${src.dir}" classpathref="compile.classpath" destdir="${classes.dir}" />
    </target>

    <target name="jar" depends="compile">
        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
        </jar>
    </target>

    <target name="run" depends="jar" description="run">
        <java classpathref="run.classpath" classname="some.test.pkg.DroolsTemplateBuilder" fork="true">
            <arg value="${drl.dir}" />
        </java>
    </target>

</project>

我们也使用模板,事实(以及由此产生的规则)非常复杂。模板表中的值用于方法调用规则、设置规则“选项”、计时器值等


当规则参数采用表格格式时,模板会有所帮助。如果需要访问控制,您可能最终需要具有相同逻辑的多个模板,只是不同的值。(在guvnor中,只需复制第一个模板即可轻松完成)。

还有人愿意吗?嗨,我只是想知道有没有办法实现这一点?你有这样的例子吗?请