For complex rules like this, we use Drools patterns. You write a rule template with an extension of parameters to fill in the fields, and you have much more flexibility when the actual values come from filling in the skeleton rule.
This feature is built into Drools Guvnor, but writing complex rule patterns through the GUI is somewhat tedious. I also wrote standalone Java to populate drl file templates from lists of values extracted from property files, and recently developed the SmartGWT web application that allows the user to populate rule values and generate DRLs.
Edit: Add a sample program. DroolsTemplateBuilder creates a list of TestType objects that have fields that map to the template keys in Test.drl. The generated DRL is printed and also compiled into pkg, which is written to the Test.pkg file.
Libraries: 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 (this may not be all necessary).
Note. The libraries used in this example are 5.2.0, and some features may differ in newer versions. build.xml should clearly indicate how to structure your project.
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);
Test.drl:
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
TestType.java:
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; } }
build.xml
<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>