package org.drools.agent; import java.io.File; import java.util.ArrayList; import java.util.List; import org.drools.KnowledgeBase; import org.drools.KnowledgeBaseFactory; import org.drools.Person; import org.drools.io.ResourceFactory; import org.drools.runtime.StatefulKnowledgeSession; public class KnowledgeAgentDSLTest extends BaseKnowledgeAgentTest { public void testDSLAndIncrementalChangeSet() throws Exception { //create a basic dsl file this.fileManager.write("myExpander.dsl", this.createCommonDSL(null)); //create a basic dslr file this.fileManager.write("rules.dslr", this.createCommonDSLRRule("Rule1")); String xml = ""; xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'"; xml += " xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'"; xml += " xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >"; xml += " <add> "; xml += " <resource source='http://localhost:" + this.getPort() + "/rules.dslr' type='DSLR' />"; xml += " <resource source='http://localhost:" + this.getPort() + "/myExpander.dsl' type='DSL' />"; xml += " </add> "; xml += "</change-set>"; File fxml = fileManager.write( "changeset.xml", xml ); List<String> list = new ArrayList<String>(); //Create a new Agent with newInstace=false KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); KnowledgeAgent kagent = this.createKAgent( kbase, false ); //Agent: take care of them! this.applyChangeSet(kagent, ResourceFactory.newUrlResource(fxml.toURI().toURL())); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.setGlobal("list", list); ksession.insert(new Person()); ksession.fireAllRules(); //The rule should be fired assertEquals(1, list.size()); assertTrue(list.contains("Rule1")); list.clear(); //the dsl is now modified. File expander = this.fileManager.write("myExpander.dsl", this.createCommonDSL("name == \"John\"")); //We also need to mark the dslr file as modified, so the rules could //be regenerated this.fileManager.write("rules.dslr", this.createCommonDSLRRule("Rule1")); this.scan(kagent); ksession.insert(new Person()); ksession.fireAllRules(); //The rule was modified then no rule got fired. assertEquals(0, list.size()); Person p = new Person(); p.setName("John"); ksession.insert(p); ksession.fireAllRules(); //The new fact activated and fired the modified rule assertEquals(1, list.size()); assertTrue(list.contains("Rule1")); //let's add a new rule this.fileManager.write("rules.dslr", this.createCommonDSLRRule(new String[]{"Rule1","Rule2"})); this.scan(kagent); list.clear(); ksession.fireAllRules(); //because we already had a John inserted, Rule2 gets fired. assertEquals(1, list.size()); assertTrue(list.contains("Rule2")); //let's remove Rule1 and Rule2 and add a new rule: Rule3 this.fileManager.write("rules.dslr", this.createCommonDSLRRule("Rule3")); this.scan(kagent); //we want to use a new ksession. ksession.dispose(); ksession = kbase.newStatefulKnowledgeSession(); //insert John list.clear(); ksession.setGlobal("list", list); ksession.insert(p); ksession.fireAllRules(); //The only existing rule must be fired assertEquals(1, list.size()); assertTrue(list.contains("Rule3")); //let's delete the dsl file (errors are expected) this.fileManager.deleteFile(expander); this.fileManager.write("rules.dslr", this.createCommonDSLRRule("Rule1")); try { this.scan(kagent); fail( "Knowledge should fail to compile" ); } catch (Exception e) { } ksession.dispose(); kagent.dispose(); } public void testDSLAndNewInstance() throws Exception { //create a basic dsl file this.fileManager.write("myExpander.dsl", this.createCommonDSL(null)); //create a basic dslr file this.fileManager.write("rules.dslr",this.createCommonDSLRRule("Rule1")); String xml = ""; xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'"; xml += " xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'"; xml += " xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >"; xml += " <add> "; xml += " <resource source='http://localhost:" + this.getPort() + "/rules.dslr' type='DSLR' />"; xml += " <resource source='http://localhost:" + this.getPort() + "/myExpander.dsl' type='DSL' />"; xml += " </add> "; xml += "</change-set>"; File fxml = fileManager.write( "changeset.xml", xml ); List<String> list = new ArrayList<String>(); //Create a new Agent with newInstace=true KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); KnowledgeAgent kagent = this.createKAgent(kbase,true); //Agent: take care of them! this.applyChangeSet(kagent,ResourceFactory.newUrlResource(fxml.toURI().toURL())); StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession(); ksession.setGlobal("list", list); ksession.insert(new Person()); ksession.fireAllRules(); //The rule should be fired assertEquals(1, list.size()); assertTrue(list.contains("Rule1")); list.clear(); ksession.dispose(); //Let's modify the dsl file File expander = this.fileManager.write("myExpander.dsl", this.createCommonDSL("name == \"John\"")); //We also need to mark the dslr file as modified, so the rules could //be regenerated this.fileManager.write("rules.dslr", this.createCommonDSLRRule("Rule1")); this.scan(kagent); //get a new ksession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession(); //A Person without name shouldn't fire any rule now (because it was //modified) ksession.setGlobal("list", list); ksession.insert(new Person()); ksession.fireAllRules(); assertEquals(0, list.size()); //A "John" Person should fire the modified rule Person p = new Person(); p.setName("John"); ksession.insert(p); ksession.fireAllRules(); assertEquals(1, list.size()); assertTrue(list.contains("Rule1")); ksession.dispose(); //Let's add a new Rule this.fileManager.write("rules.dslr", this.createCommonDSLRRule(new String[]{"Rule1","Rule2"})); this.scan(kagent); //get a new ksession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession(); //A "John" Person now should fire 2 rules list.clear(); ksession.setGlobal("list", list); ksession.insert(p); ksession.fireAllRules(); assertEquals(2, list.size()); assertTrue(list.contains("Rule1")); assertTrue(list.contains("Rule2")); ksession.dispose(); //Let's remove both rules and add a new one: Rule3 this.fileManager.write("rules.dslr", this.createCommonDSLRRule("Rule3")); this.scan(kagent); //get a new ksession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession(); //A "John" Person now should only Rule3 (the other two rules were removes) list.clear(); ksession.setGlobal("list", list); ksession.insert(p); ksession.fireAllRules(); assertEquals(1, list.size()); assertTrue(list.contains("Rule3")); ksession.dispose(); //let's delete the dsl file (errors are expected) fileManager.deleteFile(expander); this.fileManager.write("rules.dslr", this.createCommonDSLRRule("Rule1")); try { this.scan(kagent); //Compilation errors should occurred fail( "Knowledge should fail to compile" ); } catch (Exception e) { } kagent.dispose(); } }