/* * Copyright 2010 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.workbench.models.commons.backend.rule; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.drools.workbench.models.datamodel.imports.Import; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.PackageDataModelOracle; import org.drools.workbench.models.datamodel.rule.ActionCallMethod; import org.drools.workbench.models.datamodel.rule.ActionExecuteWorkItem; import org.drools.workbench.models.datamodel.rule.ActionFieldFunction; import org.drools.workbench.models.datamodel.rule.ActionFieldValue; import org.drools.workbench.models.datamodel.rule.ActionGlobalCollectionAdd; import org.drools.workbench.models.datamodel.rule.ActionInsertFact; import org.drools.workbench.models.datamodel.rule.ActionInsertLogicalFact; import org.drools.workbench.models.datamodel.rule.ActionRetractFact; import org.drools.workbench.models.datamodel.rule.ActionSetField; import org.drools.workbench.models.datamodel.rule.ActionUpdateField; import org.drools.workbench.models.datamodel.rule.ActionWorkItemFieldValue; import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.CompositeFactPattern; import org.drools.workbench.models.datamodel.rule.CompositeFieldConstraint; import org.drools.workbench.models.datamodel.rule.ConnectiveConstraint; import org.drools.workbench.models.datamodel.rule.DSLComplexVariableValue; import org.drools.workbench.models.datamodel.rule.DSLSentence; import org.drools.workbench.models.datamodel.rule.DSLVariableValue; import org.drools.workbench.models.datamodel.rule.ExpressionField; import org.drools.workbench.models.datamodel.rule.ExpressionFormLine; import org.drools.workbench.models.datamodel.rule.ExpressionMethod; import org.drools.workbench.models.datamodel.rule.ExpressionText; import org.drools.workbench.models.datamodel.rule.ExpressionUnboundFact; import org.drools.workbench.models.datamodel.rule.ExpressionVariable; import org.drools.workbench.models.datamodel.rule.FactPattern; import org.drools.workbench.models.datamodel.rule.FieldNatureType; import org.drools.workbench.models.datamodel.rule.FreeFormLine; import org.drools.workbench.models.datamodel.rule.FromAccumulateCompositeFactPattern; import org.drools.workbench.models.datamodel.rule.FromCollectCompositeFactPattern; import org.drools.workbench.models.datamodel.rule.FromCompositeFactPattern; import org.drools.workbench.models.datamodel.rule.FromEntryPointFactPattern; import org.drools.workbench.models.datamodel.rule.IAction; import org.drools.workbench.models.datamodel.rule.IPattern; import org.drools.workbench.models.datamodel.rule.RuleAttribute; import org.drools.workbench.models.datamodel.rule.RuleModel; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraintEBLeftSide; import org.drools.workbench.models.datamodel.workitems.PortableBooleanParameterDefinition; import org.drools.workbench.models.datamodel.workitems.PortableFloatParameterDefinition; import org.drools.workbench.models.datamodel.workitems.PortableIntegerParameterDefinition; import org.drools.workbench.models.datamodel.workitems.PortableStringParameterDefinition; import org.drools.workbench.models.datamodel.workitems.PortableWorkDefinition; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class RuleModelDRLPersistenceTest { private static final Logger logger = LoggerFactory.getLogger(RuleModelDRLPersistenceTest.class); private RuleModelPersistence ruleModelPersistence; @Before public void setUp() throws Exception { ruleModelPersistence = RuleModelDRLPersistenceImpl.getInstance(); } @Test public void testGenerateEmptyDRL() { String expected = "rule \"null\"\n\tdialect \"mvel\"\n\twhen\n\tthen\nend\n"; checkMarshalling(expected, new RuleModel()); } private void checkMarshalling(String expected, RuleModel m) { String drl = ruleModelPersistence.marshal(m); assertNotNull(drl); if (expected != null) { assertEqualsIgnoreWhitespace(expected, drl); } } private void checkMarshallingUsingDsl(String expected, RuleModel m) { String drl = ruleModelPersistence.marshal(m); assertNotNull(drl); if (expected != null) { assertEqualsIgnoreWhitespace(expected, drl); } } @Test public void testFreeForm() { RuleModel m = new RuleModel(); m.name = "with composite"; m.lhs = new IPattern[1]; m.rhs = new IAction[1]; FreeFormLine fl = new FreeFormLine(); fl.setText("Person()"); m.lhs[0] = fl; FreeFormLine fr = new FreeFormLine(); fr.setText("fun()"); m.rhs[0] = fr; String drl = ruleModelPersistence.marshal(m); assertNotNull(drl); assertTrue(drl.indexOf("Person()") > 0); assertTrue(drl.indexOf("fun()") > drl.indexOf("Person()")); } @Test public void testBasics() { String expected = "rule \"my rule\"\n\tno-loop true\n\tdialect \"mvel\"\n\twhen\n\t\tPerson( )\n" + "\t\tAccident( )\n\tthen\n\t\tinsert( new Report() );\nend\n"; RuleModel m = new RuleModel(); m.addLhsItem(new FactPattern("Person")); m.addLhsItem(new FactPattern("Accident")); m.addAttribute(new RuleAttribute("no-loop", "true")); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testInsertLogical() { String expected = "rule \"my rule\"\n\tno-loop true\n\tdialect \"mvel\"\n\twhen\n\t\tPerson( )\n" + "\t\tAccident( )\n\tthen\n\t\tinsertLogical( new Report() );\nend\n"; final RuleModel m = new RuleModel(); m.addLhsItem(new FactPattern("Person")); m.addLhsItem(new FactPattern("Accident")); m.addAttribute(new RuleAttribute("no-loop", "true")); m.addRhsItem(new ActionInsertLogicalFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testAttr() { RuleModel m = new RuleModel(); m.attributes = new RuleAttribute[1]; m.attributes[0] = new RuleAttribute("enabled", "true"); final String drl = ruleModelPersistence.marshal(m); assertTrue(drl.indexOf("enabled true") > 0); } @Test public void testCalendars() { //BZ1059232 - Guided rule editor: calendars attribute is broken when a list of calendars is used RuleModel m = new RuleModel(); m.attributes = new RuleAttribute[1]; m.attributes[0] = new RuleAttribute("calendars", "a, b"); final String drl = ruleModelPersistence.marshal(m); assertTrue(drl.indexOf("calendars \"a\", \"b\"") > 0); } @Test public void testCalendarsWithQuotes() { //BZ1059232 - Guided rule editor: calendars attribute is broken when a list of calendars is used RuleModel m = new RuleModel(); m.attributes = new RuleAttribute[1]; m.attributes[0] = new RuleAttribute("calendars", "\"a\", \"b\""); final String drl = ruleModelPersistence.marshal(m); assertTrue(drl.indexOf("calendars \"a\", \"b\"") > 0); } @Test public void testCalendarsWithQuotesAroundWholeValue() { //BZ1059232 - Guided rule editor: calendars attribute is broken when a list of calendars is used RuleModel m = new RuleModel(); m.attributes = new RuleAttribute[1]; m.attributes[0] = new RuleAttribute("calendars", "\"a, b\""); final String drl = ruleModelPersistence.marshal(m); assertTrue(drl.indexOf("calendars \"a\", \"b\"") > 0); } @Test public void testEnumNoType() { //A legacy "Guvnor" enums (i.e pick-list of underlying field data-type) String expected = "rule \"my rule\"\n\tdialect \"mvel\"\n\twhen\n\t\tCheese( type == \"CheeseType.CHEDDAR\" )\n" + "\tthen\n\t\tinsert( new Report() );\nend\n"; final RuleModel m = new RuleModel(); final FactPattern pat = new FactPattern("Cheese"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("type"); con.setOperator("=="); con.setValue("CheeseType.CHEDDAR"); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_ENUM); pat.addConstraint(con); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testEnumTypeString() { //A legacy "Guvnor" enums (i.e pick-list of underlying field data-type) String expected = "rule \"my rule\"\n\tdialect \"mvel\"\n\twhen\n\t\tCheese( type == \"CHEDDAR\" )\n" + "\tthen\n\t\tinsert( new Report() );\nend\n"; final RuleModel m = new RuleModel(); final FactPattern pat = new FactPattern("Cheese"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("type"); con.setOperator("=="); con.setValue("CHEDDAR"); con.setFieldType(DataType.TYPE_STRING); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_ENUM); pat.addConstraint(con); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testExtends() { String expected = "rule \"my rule\" extends \"secondRule\"\n\tdialect \"mvel\"\n\twhen\n" + "\tthen\n\nend\n"; final RuleModel m = new RuleModel(); m.parentName = "secondRule"; m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testSumAsGivenValue() { // BZ-1013682 String expected = "" + "rule \"my rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " m:Message()\n" + " then\n" + " modify( m ) {\n" + " setText( \"Hello \" + \"world\" )\n" + " }\n" + "end\n"; final RuleModel m = new RuleModel(); FactPattern factPattern = new FactPattern(); factPattern.setFactType("Message"); factPattern.setBoundName("m"); m.lhs = new IPattern[]{factPattern}; ActionUpdateField actionUpdateField = new ActionUpdateField(); actionUpdateField.setVariable("m"); ActionFieldValue actionFieldValue = new ActionFieldValue(); actionFieldValue.setField("text"); actionFieldValue.setType("String"); actionFieldValue.setNature(FieldNatureType.TYPE_FORMULA); actionFieldValue.setValue("\"Hello \" + \"world\""); actionUpdateField.setFieldValues(new ActionFieldValue[]{actionFieldValue}); m.rhs = new IAction[]{actionUpdateField}; m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testNotNull() { String expected = "" + "rule \"my rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " Customer( contact != null , contact.tel1 > 15 )\n" + " then\n" + "end\n"; final RuleModel m = new RuleModel(); FactPattern factPattern = new FactPattern(); factPattern.setFactType("Customer"); m.lhs = new IPattern[]{factPattern}; SingleFieldConstraint constraint1 = new SingleFieldConstraint("Customer", "contact", "Contact", null); constraint1.setOperator("!= null"); factPattern.addConstraint(constraint1); SingleFieldConstraint constraint2 = new SingleFieldConstraint("Customer", "contact", "Contact", null); factPattern.addConstraint(constraint2); SingleFieldConstraint constraint3 = new SingleFieldConstraint("Contact", "tel1", "Integer", constraint2); constraint3.setOperator(">"); constraint3.setValue("15"); factPattern.addConstraint(constraint3); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testCallFunction() throws Exception { String expected = "" + "package org.mortgages;\n" + "import org.mortgages.LoanApplication;\n" + "\n" + "rule \"my rule\"\n" + " dialect \"mvel\"\n" + " when\n" + " a : LoanApplication( )\n" + " then\n" + " keke.clear( );\n" + "end\n"; final RuleModel m = new RuleModel(); m.setPackageName("org.mortgages"); m.getImports().addImport(new Import("org.mortgages.LoanApplication")); m.name = "my rule"; FactPattern factPattern = new FactPattern(); factPattern.setFactType("LoanApplication"); factPattern.setBoundName("a"); m.lhs = new IPattern[]{factPattern}; ActionCallMethod actionCallMethod = new ActionCallMethod(); actionCallMethod.setState(1); actionCallMethod.setMethodName("clear"); actionCallMethod.setVariable("keke"); m.rhs = new IAction[]{actionCallMethod}; checkMarshalling(expected, m); } @Test public void testEnumTypeNumeric() { //A legacy "Guvnor" enums (i.e pick-list of underlying field data-type) String expected = "rule \"my rule\"\n\tdialect \"mvel\"\n\twhen\n\t\tCheese( age == 100 )\n" + "\tthen\n\t\tinsert( new Report() );\nend\n"; final RuleModel m = new RuleModel(); final FactPattern pat = new FactPattern("Cheese"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("age"); con.setOperator("=="); con.setValue("100"); con.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_ENUM); pat.addConstraint(con); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testEnumTypeStringInOperator() { //A legacy "Guvnor" enums (i.e pick-list of underlying field data-type) String expected = "rule \"my rule\"\n" + "\tdialect \"mvel\"\n" + "\twhen\n" + "\t\tCheese( type in ( \"CHEDDAR\", \"STILTON\" ) )\n" + "\tthen\n" + "\t\tinsert( new Report() );\n" + "end\n"; final RuleModel m = new RuleModel(); final FactPattern pat = new FactPattern("Cheese"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("type"); con.setOperator("in"); con.setValue("( \"CHEDDAR\",\"STILTON\" )"); con.setFieldType(DataType.TYPE_STRING); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_ENUM); pat.addConstraint(con); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testEnumTypeBoolean() { //A legacy "Guvnor" enums (i.e pick-list of underlying field data-type) String expected = "rule \"my rule\"\n\tdialect \"mvel\"\n\twhen\n\t\tCheese( smelly == true )\n" + "\tthen\n\t\tinsert( new Report() );\nend\n"; final RuleModel m = new RuleModel(); final FactPattern pat = new FactPattern("Cheese"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("smelly"); con.setOperator("=="); con.setValue("true"); con.setFieldType(DataType.TYPE_BOOLEAN); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_ENUM); pat.addConstraint(con); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testEnumTypeDate() { //A legacy "Guvnor" enums (i.e pick-list of underlying field data-type) String expected = "rule \"my rule\"\n\tdialect \"mvel\"\n\twhen\n\t\tCheese( dateMade == \"31-Jan-2010\" )\n" + "\tthen\n\t\tinsert( new Report() );\nend\n"; final RuleModel m = new RuleModel(); final FactPattern pat = new FactPattern("Cheese"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("dateMade"); con.setOperator("=="); con.setValue("31-Jan-2010"); con.setFieldType(DataType.TYPE_DATE); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_ENUM); pat.addConstraint(con); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testEnumTypeComparable() { //Java 1.5+ "true" enums are of type Comparable String expected = "rule \"my rule\"\n\tdialect \"mvel\"\n\twhen\n\t\tCheese( type == Cheese.CHEDDAR )\n" + "\tthen\n\t\tinsert( new Report() );\nend\n"; final RuleModel m = new RuleModel(); final FactPattern pat = new FactPattern("Cheese"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("type"); con.setOperator("=="); con.setValue("Cheese.CHEDDAR"); con.setFieldType(DataType.TYPE_COMPARABLE); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_ENUM); pat.addConstraint(con); m.addRhsItem(new ActionInsertFact("Report")); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testMoreComplexRendering() { final RuleModel m = getComplexModel(false); String expected = "rule \"Complex Rule\"\n" + "no-loop true\n" + "salience -10\n" + "agenda-group \"aGroup\"\n" + "dialect \"mvel\"\n" + "when\n" + " p1 : Person( f1 : age < 42 )\n" + " not (Cancel( )) \n" + "then\n" + " modify( p1 ) {\n" + " setStatus( \"rejected\" ),\n" + " setName( \"Fred\" )\n" + " }\n" + " retract( p1 );\n" + "end\n"; checkMarshalling(expected, m); } @Test public void testMoreComplexRenderingWithDsl() { final RuleModel m = getComplexModel(true); String expected = "rule \"Complex Rule\"\n" + "no-loop true\n" + "salience -10\n" + "agenda-group \"aGroup\"\n" + "dialect \"mvel\"\n" + "when\n" + " >p1 : Person( f1 : age < 42 )\n" + " >not (Cancel( )) \n" + "then\n" + " >modify( p1 ) {\n" + " >setStatus( \"rejected\" ),\n" + " >setName( \"Fred\" )\n" + " >}\n" + " >retract( p1 );\n" + "Send an email to administrator\n" + "end\n"; checkMarshallingUsingDsl(expected, m); String drl = ruleModelPersistence.marshal(m); assertEqualsIgnoreWhitespace(expected, drl); String dslFile = "[then]Send an email to {administrator}=sendMailTo({administrator});"; RuleModel unmarshalledModel = ruleModelPersistence.unmarshalUsingDSL(drl, null, mock(PackageDataModelOracle.class), dslFile); IAction[] actions = unmarshalledModel.rhs; DSLSentence dslSentence = (DSLSentence) actions[actions.length - 1]; assertEquals("Send an email to {administrator}", dslSentence.getDefinition()); checkMarshallingUsingDsl(expected, unmarshalledModel); } @Test public void testDSLExpansion() { String expected = "rule \"Rule With DSL\"\n" + "\tdialect \"mvel\"\n" + "\twhen\n" + "\t\tThe credit rating is AA\n" + "\tthen\n" + "end\n"; final String dslDefinition = "The credit rating is {rating:ENUM:Applicant.creditRating}"; final DSLSentence dsl = new DSLSentence(); dsl.setDefinition(dslDefinition); //Check values are correctly parsed final List<DSLVariableValue> values = dsl.getValues(); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof DSLComplexVariableValue); assertEquals("rating", values.get(0).getValue()); assertEquals("ENUM:Applicant.creditRating", ((DSLComplexVariableValue) values.get(0)).getId()); //The following line is normally performed by the UI when the user sets values dsl.getValues().get(0).setValue("AA"); //Check interpolation final String expansion = dsl.interpolate(); assertEquals("The credit rating is AA", expansion); assertEquals(dsl.getDefinition(), dslDefinition); final RuleModel m = new RuleModel(); m.name = "Rule With DSL"; m.addLhsItem(dsl); String drl = ruleModelPersistence.marshal(m); assertEqualsIgnoreWhitespace(expected, drl); String dslFile = "[when]" + dslDefinition + "=Credit( rating == {rating} )"; RuleModel unmarshalledModel = ruleModelPersistence.unmarshalUsingDSL(drl, null, null, dslFile); DSLSentence dslSentence = (DSLSentence) unmarshalledModel.lhs[0]; assertEquals(dslDefinition, dslSentence.getDefinition()); assertEquals(1, dslSentence.getValues().size()); assertTrue(dslSentence.getValues().get(0) instanceof DSLComplexVariableValue); DSLComplexVariableValue dslComplexVariableValue = (DSLComplexVariableValue) dslSentence.getValues().get(0); assertEquals("AA", dslComplexVariableValue.getValue()); assertEquals("ENUM:Applicant.creditRating", dslComplexVariableValue.getId()); assertEqualsIgnoreWhitespace(expected, ruleModelPersistence.marshal(unmarshalledModel)); } @Test public void testDSLExpansionContainingRegex() { String expected = "rule \"RegexDslRule\"\n" + "dialect \"mvel\"\n" + "when\n" + "When the ages is less than 57\n" + "then\n" + "end\n"; final String dslDefinition = "When the ages is less than {num:1?[0-9]?[0-9]}"; final DSLSentence dsl = new DSLSentence(); dsl.setDefinition(dslDefinition); //Check values are correctly parsed final List<DSLVariableValue> values = dsl.getValues(); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof DSLComplexVariableValue); assertEquals("num", values.get(0).getValue()); assertEquals("1?[0-9]?[0-9]", ((DSLComplexVariableValue) values.get(0)).getId()); //The following line is normally performed by the UI when the user sets values dsl.getValues().get(0).setValue("57"); //Check interpolation final String expansion = dsl.interpolate(); assertEquals("When the ages is less than 57", expansion); assertEquals(dsl.getDefinition(), dslDefinition); final RuleModel m = new RuleModel(); m.name = "RegexDslRule"; m.addLhsItem(dsl); String drl = ruleModelPersistence.marshal(m); assertEqualsIgnoreWhitespace(expected, drl); String dslFile = "[when]" + dslDefinition + "=applicant:Applicant(age<{num})"; RuleModel model = ruleModelPersistence.unmarshalUsingDSL(drl, null, null, dslFile); DSLSentence dslSentence = (DSLSentence) model.lhs[0]; assertEquals(dslDefinition, dslSentence.getDefinition()); assertEquals(1, dslSentence.getValues().size()); assertTrue(dslSentence.getValues().get(0) instanceof DSLComplexVariableValue); DSLComplexVariableValue dslComplexVariableValue = (DSLComplexVariableValue) dslSentence.getValues().get(0); assertEquals("57", dslComplexVariableValue.getValue()); assertEquals("1?[0-9]?[0-9]", dslComplexVariableValue.getId()); assertEqualsIgnoreWhitespace(drl, ruleModelPersistence.marshal(model)); } @Test public void testDSLExpansionLHS() { final String dslDefinition = "The credit rating is {rating:ENUM:Applicant.creditRating}"; final String drlExpected = "rule \"r1\"\n" + "dialect \"mvel\"\n" + "when\n" + "The credit rating is AA\n" + "then\n" + "end"; final DSLSentence dsl = new DSLSentence(); dsl.setDefinition(dslDefinition); //The following line is normally performed by the UI when the user sets values dsl.getValues().get(0).setValue("AA"); //Append DSL to RuleModel to check marshalling final RuleModel m = new RuleModel(); m.name = "r1"; m.addLhsItem(dsl); final String drlActual = ruleModelPersistence.marshal(m); assertEqualsIgnoreWhitespace(drlExpected, drlActual); } private RuleModel getComplexModel(boolean useDsl) { final RuleModel m = new RuleModel(); m.name = "Complex Rule"; m.addAttribute(new RuleAttribute("no-loop", "true")); m.addAttribute(new RuleAttribute("salience", "-10")); m.addAttribute(new RuleAttribute("agenda-group", "aGroup")); final FactPattern pat = new FactPattern("Person"); pat.setBoundName("p1"); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldBinding("f1"); con.setFieldName("age"); con.setOperator("<"); con.setValue("42"); pat.addConstraint(con); m.addLhsItem(pat); final CompositeFactPattern comp = new CompositeFactPattern("not"); comp.addFactPattern(new FactPattern("Cancel")); m.addLhsItem(comp); final ActionUpdateField upd1 = new ActionUpdateField(); upd1.setVariable("p1"); upd1.addFieldValue(new ActionFieldValue("status", "rejected", DataType.TYPE_STRING)); upd1.addFieldValue(new ActionFieldValue("name", "Fred", DataType.TYPE_STRING)); m.addRhsItem(upd1); final ActionRetractFact ret = new ActionRetractFact("p1"); m.addRhsItem(ret); if (useDsl) { final DSLSentence sen = new DSLSentence(); sen.setDefinition("Send an email to {administrator}"); m.addRhsItem(sen); } return m; } @Test public void testFieldBindingWithNoConstraints() { // to satisfy JBRULES-850 RuleModel m = getModelWithNoConstraints(); String s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); logger.debug(s); assertTrue(s.contains("Person( f1 : age)")); checkMarshalling(s, m); } @Test public void textIsNullOperator() { final RuleModel m = new RuleModel(); m.name = "IsNullOperator"; final FactPattern pat = new FactPattern("Person"); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("age"); con.setOperator("== null"); pat.addConstraint(con); m.addLhsItem(pat); String s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(s.indexOf("Person( age == null )") != -1); checkMarshalling(s, m); } @Test public void textIsNotNullOperator() { final RuleModel m = new RuleModel(); m.name = "IsNotNullOperator"; final FactPattern pat = new FactPattern("Person"); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("age"); con.setOperator("!= null"); pat.addConstraint(con); m.addLhsItem(pat); String s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(s.indexOf("Person( age != null )") != -1); checkMarshalling(s, m); } private RuleModel getModelWithNoConstraints() { final RuleModel m = new RuleModel(); m.name = "Complex Rule"; final FactPattern pat = new FactPattern("Person"); pat.setBoundName("p1"); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldBinding("f1"); con.setFieldName("age"); // con.operator = "<"; // con.value = "42"; pat.addConstraint(con); m.addLhsItem(pat); return m; } @Test public void testOrComposite() throws Exception { RuleModel m = new RuleModel(); m.name = "or"; CompositeFactPattern cp = new CompositeFactPattern( CompositeFactPattern.COMPOSITE_TYPE_OR); FactPattern p1 = new FactPattern("Person"); SingleFieldConstraint sf1 = new SingleFieldConstraint("age"); sf1.setOperator("=="); sf1.setValue("42"); p1.addConstraint(sf1); cp.addFactPattern(p1); FactPattern p2 = new FactPattern("Person"); SingleFieldConstraint sf2 = new SingleFieldConstraint("age"); sf2.setOperator("=="); sf2.setValue("43"); p2.addConstraint(sf2); cp.addFactPattern(p2); m.addLhsItem(cp); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("( Person( age == 42 ) or Person( age == 43 ) )") > 0); checkMarshalling(result, m); } @Test public void testExistsMultiPatterns() throws Exception { RuleModel m = getCompositeFOL(CompositeFactPattern.COMPOSITE_TYPE_EXISTS); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("exists (Person( age == 42 ) and Person( age == 43 ))") > 0); checkMarshalling(result, m); } @Test public void testNotMultiPatterns() throws Exception { RuleModel m = getCompositeFOL(CompositeFactPattern.COMPOSITE_TYPE_NOT); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("not (Person( age == 42 ) and Person( age == 43 ))") > 0); checkMarshalling(result, m); } @Test public void testSingleExists() throws Exception { RuleModel m = new RuleModel(); m.name = "or"; CompositeFactPattern cp = new CompositeFactPattern(CompositeFactPattern.COMPOSITE_TYPE_EXISTS); FactPattern p1 = new FactPattern("Person"); SingleFieldConstraint sf1 = new SingleFieldConstraint("age"); sf1.setOperator("=="); sf1.setValue("42"); p1.addConstraint(sf1); cp.addFactPattern(p1); m.addLhsItem(cp); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); logger.debug(result); assertTrue(result.indexOf("exists (Person( age == 42 )) ") > 0); checkMarshalling(result, m); } private RuleModel getCompositeFOL(String type) { RuleModel m = new RuleModel(); m.name = "or"; CompositeFactPattern cp = new CompositeFactPattern(type); FactPattern p1 = new FactPattern("Person"); SingleFieldConstraint sf1 = new SingleFieldConstraint("age"); sf1.setOperator("=="); sf1.setValue("42"); p1.addConstraint(sf1); cp.addFactPattern(p1); FactPattern p2 = new FactPattern("Person"); SingleFieldConstraint sf2 = new SingleFieldConstraint("age"); sf2.setOperator("=="); sf2.setValue("43"); p2.addConstraint(sf2); cp.addFactPattern(p2); m.addLhsItem(cp); return m; } @Test public void testCompositeConstraints() { RuleModel m = new RuleModel(); m.name = "with composite"; FactPattern p1 = new FactPattern("Person"); p1.setBoundName("p1"); m.addLhsItem(p1); FactPattern p = new FactPattern("Goober"); m.addLhsItem(p); CompositeFieldConstraint comp = new CompositeFieldConstraint(); comp.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_OR); p.addConstraint(comp); final SingleFieldConstraint X = new SingleFieldConstraint(); X.setFieldName("goo"); X.setFieldType(DataType.TYPE_STRING); X.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); X.setValue("foo"); X.setOperator("=="); X.setConnectives(new ConnectiveConstraint[1]); X.getConnectives()[0] = new ConnectiveConstraint(); X.getConnectives()[0].setConstraintValueType(ConnectiveConstraint.TYPE_LITERAL); X.getConnectives()[0].setFieldType(DataType.TYPE_STRING); X.getConnectives()[0].setOperator("|| =="); X.getConnectives()[0].setValue("bar"); comp.addConstraint(X); final SingleFieldConstraint Y = new SingleFieldConstraint(); Y.setFieldName("goo2"); Y.setFieldType(DataType.TYPE_STRING); Y.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); Y.setValue("foo"); Y.setOperator("=="); comp.addConstraint(Y); CompositeFieldConstraint comp2 = new CompositeFieldConstraint(); comp2.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_AND); final SingleFieldConstraint Q1 = new SingleFieldConstraint(); Q1.setFieldType(DataType.TYPE_STRING); Q1.setFieldName("goo"); Q1.setOperator("=="); Q1.setValue("whee"); Q1.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); comp2.addConstraint(Q1); final SingleFieldConstraint Q2 = new SingleFieldConstraint(); Q2.setFieldType(DataType.TYPE_STRING); Q2.setFieldName("gabba"); Q2.setOperator("=="); Q2.setValue("whee"); Q2.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); comp2.addConstraint(Q2); // now nest it comp.addConstraint(comp2); final SingleFieldConstraint Z = new SingleFieldConstraint(); Z.setFieldName("goo3"); Z.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); Z.setFieldType(DataType.TYPE_STRING); Z.setValue("foo"); Z.setOperator("=="); p.addConstraint(Z); ActionInsertFact ass = new ActionInsertFact("Whee"); m.addRhsItem(ass); String actual = RuleModelDRLPersistenceImpl.getInstance().marshal(m); String expected = "rule \"with composite\"\n" + "\tdialect \"mvel\"\n" + "\twhen\n" + "\t\tp1 : Person( )\n" + "\t\tGoober( goo == \"foo\" || == \"bar\" || goo2 == \"foo\" || ( goo == \"whee\" && gabba == \"whee\" ), goo3 == \"foo\" )\n" + "\tthen\n" + "\t\tinsert( new Whee() );\n" + "end\n"; assertEqualsIgnoreWhitespace(expected, actual); checkMarshalling(expected, m); } @Test public void testFieldsDeclaredButNoConstraints() { RuleModel m = new RuleModel(); m.name = "boo"; FactPattern p = new FactPattern("Person"); // this isn't an effective constraint, so it should be ignored. p.addConstraint(new SingleFieldConstraint("field1")); m.addLhsItem(p); String actual = RuleModelDRLPersistenceImpl.getInstance().marshal(m); String expected = "rule \"boo\" \tdialect \"mvel\"\n when Person() then end"; checkMarshalling(expected, m); SingleFieldConstraint con = (SingleFieldConstraint) p.getConstraintList().getConstraint(0); con.setFieldBinding("q"); // now it should appear, as we are binding a var to it expected = "rule \"boo\" dialect \"mvel\" when Person(q : field1) then end"; checkMarshalling(expected, m); } @Test public void testLiteralStrings() { RuleModel m = new RuleModel(); m.name = "test literal strings"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_STRING); con.setFieldName("field1"); con.setOperator("=="); con.setValue("goo"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldName("field2"); con2.setOperator("=="); con2.setValue("variableHere"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_VARIABLE); p.addConstraint(con2); m.addLhsItem(p); String expected = "rule \"test literal strings\"" + "\tdialect \"mvel\"\n when " + " Person(field1 == \"goo\", field2 == variableHere)" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionString1() { RuleModel m = new RuleModel(); m.name = "test expressionsString1"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionText("field1")); con.setOperator("=="); con.setValue("goo"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsString1\"" + "\tdialect \"mvel\"\n when " + " Person( field1 == \"goo\" )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionString2() { RuleModel m = new RuleModel(); m.name = "test expressionsString2"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("field1", "java.lang.String", DataType.TYPE_STRING)); con.setOperator("=="); con.setValue("Cheddar"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); String expected = "rule \"test expressionsString2\"" + "\tdialect \"mvel\"\n when " + " Person( field1 == \"Cheddar\" )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionJavaEnum() { RuleModel m = new RuleModel(); m.name = "test expressionsJavaEnum"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("field1", "CHEESE", DataType.TYPE_COMPARABLE)); con.setOperator("=="); con.setValue("CHEESE.Cheddar"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsJavaEnum\"" + "\tdialect \"mvel\"\n when " + " Person( field1 == CHEESE.Cheddar )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionNumber() { RuleModel m = new RuleModel(); m.name = "test expressionsNumber"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("field1", "java.lang.Integer", DataType.TYPE_NUMERIC_INTEGER)); con.setOperator("=="); con.setValue("55"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsNumber\"" + "\tdialect \"mvel\"\n when " + " Person( field1 == 55 )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionDate() { RuleModel m = new RuleModel(); m.name = "test expressionsDate"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("field1", "java.util.Date", DataType.TYPE_DATE)); con.setOperator("=="); con.setValue("27-Jun-2011"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsDate\"" + "\tdialect \"mvel\"\n when " + " Person( field1 == \"27-Jun-2011\" )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionBoolean() { RuleModel m = new RuleModel(); m.name = "test expressionsBoolean"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("field1", "java.lang.Boolean", DataType.TYPE_BOOLEAN)); con.setOperator("=="); con.setValue("true"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsBoolean\"" + "\tdialect \"mvel\"\n when " + " Person( field1 == true )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionNestedString() { RuleModel m = new RuleModel(); m.name = "test expressionsNestedString"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("favouriteCheese", "Cheese", DataType.TYPE_OBJECT)); con.getExpressionLeftSide().appendPart(new ExpressionField("name", "java.lang.String", DataType.TYPE_STRING)); con.setOperator("=="); con.setValue("Cheedar"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsNestedString\"" + "\tdialect \"mvel\"\n when " + " Person( favouriteCheese.name == \"Cheedar\" )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionNestedNumber() { RuleModel m = new RuleModel(); m.name = "test expressionsNestedNumber"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("favouriteCheese", "Cheese", DataType.TYPE_OBJECT)); con.getExpressionLeftSide().appendPart(new ExpressionField("age", "java.lang.Integer", DataType.TYPE_NUMERIC_INTEGER)); con.setOperator("=="); con.setValue("55"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsNestedNumber\"" + "\tdialect \"mvel\"\n when " + " Person( favouriteCheese.age == 55 )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionNestedDate() { RuleModel m = new RuleModel(); m.name = "test expressionsNestedDate"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("favouriteCheese", "Cheese", DataType.TYPE_OBJECT)); con.getExpressionLeftSide().appendPart(new ExpressionField("dateBrought", "java.util.Date", DataType.TYPE_DATE)); con.setOperator("=="); con.setValue("27-Jun-2011"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsNestedDate\"" + "\tdialect \"mvel\"\n when " + " Person( favouriteCheese.dateBrought == \"27-Jun-2011\" )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionNestedJavaEnum() { RuleModel m = new RuleModel(); m.name = "test expressionsNestedJavaEnum"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("favouriteCheese", "Cheese", DataType.TYPE_OBJECT)); con.getExpressionLeftSide().appendPart(new ExpressionField("genericName", "CHEESE", DataType.TYPE_COMPARABLE)); con.setOperator("=="); con.setValue("CHEESE.Cheddar"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsNestedJavaEnum\"" + "\tdialect \"mvel\"\n when " + " Person( favouriteCheese.genericName == CHEESE.Cheddar )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLHSExpressionNestedBoolean() { RuleModel m = new RuleModel(); m.name = "test expressionsNestedBoolean"; FactPattern p = new FactPattern("Person"); SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); con.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con.getExpressionLeftSide().appendPart(new ExpressionField("favouriteCheese", "Cheese", DataType.TYPE_OBJECT)); con.getExpressionLeftSide().appendPart(new ExpressionField("smelly", "java.lang.Boolean", DataType.TYPE_BOOLEAN)); con.setOperator("=="); con.setValue("true"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"test expressionsNestedBoolean\"" + "\tdialect \"mvel\"\n when " + " Person( favouriteCheese.smelly == true )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLiteralNumerics() { RuleModel m = new RuleModel(); m.name = "test literal numerics"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con.setFieldName("field1"); con.setOperator("=="); con.setValue("44"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldName("field2"); con2.setOperator("=="); con2.setValue("variableHere"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_VARIABLE); p.addConstraint(con2); m.addLhsItem(p); String expected = "rule \"test literal numerics\"" + "\tdialect \"mvel\"\n when " + " Person(field1 == 44, field2 == variableHere)" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLiteralBigDecimalMvel() { RuleModel m = new RuleModel(); m.name = "test literal bigdecimal"; m.addAttribute(new RuleAttribute("dialect", "mvel")); FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_BIGDECIMAL); con.setFieldName("field1"); con.setOperator("=="); con.setValue("44"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionInsertFact ai = new ActionInsertFact("Person"); ai.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_BIGDECIMAL)); m.addRhsItem(ai); String expected = "rule \"test literal bigdecimal\" \n" + "\tdialect \"mvel\"\n when \n" + " Person(field1 == 44B) \n" + " then \n" + "Person fact0 = new Person(); \n" + "fact0.setField1( 55B ); \n" + "insert( fact0 ); \n" + "end"; checkMarshalling(expected, m); } @Test public void testLiteralBigIntegerMvel() { RuleModel m = new RuleModel(); m.name = "test literal biginteger"; m.addAttribute(new RuleAttribute("dialect", "mvel")); FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_BIGINTEGER); con.setFieldName("field1"); con.setOperator("=="); con.setValue("44"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionInsertFact ai = new ActionInsertFact("Person"); ai.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_BIGINTEGER)); m.addRhsItem(ai); String expected = "rule \"test literal biginteger\" \n" + "\tdialect \"mvel\"\n when \n" + " Person(field1 == 44I ) \n" + " then \n" + "Person fact0 = new Person(); \n" + "fact0.setField1( 55I ); \n" + "insert( fact0 ); \n" + "end"; checkMarshalling(expected, m); } @Test public void testLiteralBigDecimalJava() { RuleModel m = new RuleModel(); m.name = "test literal bigdecimal"; m.addAttribute(new RuleAttribute("dialect", "java")); FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_BIGDECIMAL); con.setFieldName("field1"); con.setOperator("=="); con.setValue("44"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionInsertFact ai = new ActionInsertFact("Person"); ai.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_BIGDECIMAL)); m.addRhsItem(ai); String expected = "rule \"test literal bigdecimal\" \n" + "\tdialect \"java\"\n when \n" + " Person(field1 == 44B) \n" + " then \n" + "Person fact0 = new Person(); \n" + "fact0.setField1( new java.math.BigDecimal( \"55\" ) ); \n" + "insert( fact0 ); \n" + "end"; checkMarshalling(expected, m); } @Test public void testLiteralBigIntegerJava() { RuleModel m = new RuleModel(); m.name = "test literal biginteger"; m.addAttribute(new RuleAttribute("dialect", "java")); FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_BIGINTEGER); con.setFieldName("field1"); con.setOperator("=="); con.setValue("44"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionInsertFact ai = new ActionInsertFact("Person"); ai.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_BIGINTEGER)); m.addRhsItem(ai); String expected = "rule \"test literal biginteger\" \n" + "\tdialect \"java\"\n when \n" + " Person(field1 == 44I ) \n" + " then \n" + "Person fact0 = new Person(); \n" + "fact0.setField1( new java.math.BigInteger( \"55\" ) ); \n" + "insert( fact0 ); \n" + "end"; checkMarshalling(expected, m); } @Test public void testLiteralBooleans() { RuleModel m = new RuleModel(); m.name = "test literal booleans"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_BOOLEAN); con.setFieldName("field1"); con.setOperator("=="); con.setValue("true"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldName("field2"); con2.setOperator("=="); con2.setValue("variableHere"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_VARIABLE); p.addConstraint(con2); m.addLhsItem(p); String expected = "rule \"test literal booleans\"" + "\tdialect \"mvel\"\n when " + " Person(field1 == true, field2 == variableHere)" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLiteralDates() { RuleModel m = new RuleModel(); m.name = "test literal dates"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_DATE); con.setFieldName("field1"); con.setOperator("=="); con.setValue("31-Jan-2010"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldName("field2"); con2.setOperator("=="); con2.setValue("variableHere"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_VARIABLE); p.addConstraint(con2); m.addLhsItem(p); String expected = "rule \"test literal dates\"" + "\tdialect \"mvel\"\n when " + " Person(field1 == \"31-Jan-2010\", field2 == variableHere)" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testLiteralNoType() { RuleModel m = new RuleModel(); m.name = "test literal no type"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("field1"); con.setOperator("=="); con.setValue("bananna"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldName("field2"); con2.setOperator("=="); con2.setValue("variableHere"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_VARIABLE); p.addConstraint(con2); m.addLhsItem(p); String expected = "rule \"test literal no type\"" + "\tdialect \"mvel\"\n when " + " Person(field1 == \"bananna\", field2 == variableHere)" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testInOperatorString() { RuleModel m = new RuleModel(); m.name = "in"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_STRING); con.setFieldName("field1"); con.setOperator("in"); con.setValue("value1, value2"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"in\" \n" + "dialect \"mvel\" \n" + "when \n" + " Person(field1 in ( \"value1\", \"value2\" ) ) \n" + " then \n" + "end"; checkMarshalling(expected, m); } @Test public void testInOperatorNumber() { RuleModel m = new RuleModel(); m.name = "in"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con.setFieldName("field1"); con.setOperator("in"); con.setValue("55, 66"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"in\" \n" + "dialect \"mvel\" \n" + "when \n" + " Person(field1 in ( 55, 66 ) ) \n" + " then \n" + "end"; checkMarshalling(expected, m); } @Test public void testNotInOperatorString() { RuleModel m = new RuleModel(); m.name = "not in"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_STRING); con.setFieldName("field1"); con.setOperator("not in"); con.setValue("value1, value2"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"not in\" \n" + "dialect \"mvel\" \n" + "when \n" + " Person(field1 not in ( \"value1\", \"value2\" ) ) \n" + " then \n" + "end"; checkMarshalling(expected, m); } @Test public void testNotInOperatorNumber() { RuleModel m = new RuleModel(); m.name = "not in"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con.setFieldName("field1"); con.setOperator("not in"); con.setValue("55, 66"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"not in\" \n" + "dialect \"mvel\" \n" + "when \n" + " Person(field1 not in ( 55, 66 ) ) \n" + " then \n" + "end"; checkMarshalling(expected, m); } @Test public void testRHSDateInsertAction() { String oldValue = System.getProperty("drools.dateformat"); try { System.setProperty("drools.dateformat", "dd-MMM-yyyy"); RuleModel m = new RuleModel(); m.name = "RHS Date"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_DATE); con.setFieldName("dateOfBirth"); con.setOperator("=="); con.setValue("31-Jan-2000"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionInsertFact ai = new ActionInsertFact("Birthday"); ai.addFieldValue(new ActionFieldValue("dob", "31-Jan-2000", DataType.TYPE_DATE)); m.addRhsItem(ai); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(\"dd-MMM-yyyy\");") != -1); assertTrue(result.indexOf("fact0.setDob( sdf.parse(\"31-Jan-2000\"") != -1); checkMarshalling(null, m); } finally { if (oldValue == null) { System.clearProperty("drools.dateformat"); } else { System.setProperty("drools.dateformat", oldValue); } } } @Test public void testRHSDateModifyAction() { String oldValue = System.getProperty("drools.dateformat"); try { System.setProperty("drools.dateformat", "dd-MMM-yyyy"); RuleModel m = new RuleModel(); m.name = "RHS Date"; FactPattern p = new FactPattern("Person"); p.setBoundName("$p"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_DATE); con.setFieldName("dateOfBirth"); con.setOperator("=="); con.setValue("31-Jan-2000"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionUpdateField am = new ActionUpdateField("$p"); am.addFieldValue(new ActionFieldValue("dob", "31-Jan-2000", DataType.TYPE_DATE)); m.addRhsItem(am); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(\"dd-MMM-yyyy\");") != -1); assertTrue(result.indexOf("setDob( sdf.parse(\"31-Jan-2000\"") != -1); assertTrue(result.indexOf("modify( $p ) {") != -1); checkMarshalling(null, m); } finally { if (oldValue == null) { System.clearProperty("drools.dateformat"); } else { System.setProperty("drools.dateformat", oldValue); } } } @Test public void testRHSDateUpdateAction() { String oldValue = System.getProperty("drools.dateformat"); try { System.setProperty("drools.dateformat", "dd-MMM-yyyy"); RuleModel m = new RuleModel(); m.name = "RHS Date"; FactPattern p = new FactPattern("Person"); p.setBoundName("$p"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_DATE); con.setFieldName("dateOfBirth"); con.setOperator("=="); con.setValue("31-Jan-2000"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionSetField au = new ActionSetField("$p"); au.addFieldValue(new ActionFieldValue("dob", "31-Jan-2000", DataType.TYPE_DATE)); m.addRhsItem(au); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(\"dd-MMM-yyyy\");") != -1); assertTrue(result.indexOf("$p.setDob( sdf.parse(\"31-Jan-2000\"") != -1); assertTrue(result.indexOf("update( $p );") == -1); checkMarshalling(null, m); } finally { if (oldValue == null) { System.clearProperty("drools.dateformat"); } else { System.setProperty("drools.dateformat", oldValue); } } } @Test public void testRHSExecuteWorkItem1() { RuleModel m = new RuleModel(); m.name = "WorkItem"; FactPattern p = new FactPattern("Person"); p.setBoundName("$p"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_STRING); con.setFieldName("name"); con.setOperator("=="); con.setValue("Michael"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionExecuteWorkItem awi = new ActionExecuteWorkItem(); PortableWorkDefinition pwd = new PortableWorkDefinition(); pwd.setName("WorkItem"); awi.setWorkDefinition(pwd); PortableBooleanParameterDefinition p1 = new PortableBooleanParameterDefinition(); p1.setName("BooleanParameter"); p1.setValue(Boolean.TRUE); pwd.addParameter(p1); PortableFloatParameterDefinition p2 = new PortableFloatParameterDefinition(); p2.setName("FloatParameter"); p2.setValue(123.456f); pwd.addParameter(p2); PortableIntegerParameterDefinition p3 = new PortableIntegerParameterDefinition(); p3.setName("IntegerParameter"); p3.setValue(123); pwd.addParameter(p3); PortableStringParameterDefinition p4 = new PortableStringParameterDefinition(); p4.setName("StringParameter"); p4.setValue("hello"); pwd.addParameter(p4); m.addRhsItem(awi); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager();") != -1); assertTrue(result.indexOf("org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem = new org.drools.core.process.instance.impl.WorkItemImpl();") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"BooleanParameter\", Boolean.TRUE );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"FloatParameter\", 123.456f );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"IntegerParameter\", 123 );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"StringParameter\", \"hello\" );") != -1); assertTrue(result.indexOf("wim.internalExecuteWorkItem( wiWorkItem );") != -1); checkMarshalling(null, m); } @Test public void testRHSExecuteWorkItem2() { RuleModel m = new RuleModel(); m.name = "WorkItem"; FactPattern p = new FactPattern("Person"); p.setBoundName("$p"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_STRING); con.setFieldName("name"); con.setOperator("=="); con.setValue("Michael"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con); m.addLhsItem(p); ActionExecuteWorkItem awi = new ActionExecuteWorkItem(); PortableWorkDefinition pwd = new PortableWorkDefinition(); pwd.setName("WorkItem"); awi.setWorkDefinition(pwd); PortableBooleanParameterDefinition p1 = new PortableBooleanParameterDefinition(); p1.setName("BooleanParameter"); p1.setValue(Boolean.TRUE); p1.setBinding(""); pwd.addParameter(p1); PortableFloatParameterDefinition p2 = new PortableFloatParameterDefinition(); p2.setName("FloatParameter"); p2.setValue(123.456f); p2.setBinding(""); pwd.addParameter(p2); PortableIntegerParameterDefinition p3 = new PortableIntegerParameterDefinition(); p3.setName("IntegerParameter"); p3.setValue(123); p3.setBinding(""); pwd.addParameter(p3); PortableStringParameterDefinition p4 = new PortableStringParameterDefinition(); p4.setName("StringParameter"); p4.setValue("hello"); p4.setBinding(""); pwd.addParameter(p4); m.addRhsItem(awi); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager();") != -1); assertTrue(result.indexOf("org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem = new org.drools.core.process.instance.impl.WorkItemImpl();") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"BooleanParameter\", Boolean.TRUE );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"FloatParameter\", 123.456f );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"IntegerParameter\", 123 );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"StringParameter\", \"hello\" );") != -1); assertTrue(result.indexOf("wim.internalExecuteWorkItem( wiWorkItem );") != -1); checkMarshalling(null, m); } @Test //Test that WorkItem Parameters whose values are bound are created and //populated in the RHS if the Pattern is bound to the same variable public void testRHSExecuteWorkItemWithBindings() { RuleModel m = new RuleModel(); m.name = "WorkItem"; FactPattern fp1 = new FactPattern("Person"); fp1.setBoundName("$p"); SingleFieldConstraint con1 = new SingleFieldConstraint(); con1.setFieldType(DataType.TYPE_STRING); con1.setFieldName("name"); con1.setOperator("=="); con1.setValue("Michael"); con1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp1.addConstraint(con1); m.addLhsItem(fp1); FactPattern fp2 = new FactPattern("Boolean"); fp2.setBoundName("$b"); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldType(DataType.TYPE_BOOLEAN); con2.setFieldName("this"); con2.setOperator("=="); con2.setValue("true"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp2.addConstraint(con2); m.addLhsItem(fp2); FactPattern fp3 = new FactPattern("Float"); fp3.setBoundName("$f"); SingleFieldConstraint con3 = new SingleFieldConstraint(); con3.setFieldType(DataType.TYPE_NUMERIC_FLOAT); con3.setFieldName("this"); con3.setOperator("=="); con3.setValue("123.456f"); con3.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp3.addConstraint(con3); m.addLhsItem(fp3); FactPattern fp4 = new FactPattern("Integer"); fp4.setBoundName("$i"); SingleFieldConstraint con4 = new SingleFieldConstraint(); con4.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con4.setFieldName("this"); con4.setOperator("=="); con4.setValue("123"); con4.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp4.addConstraint(con4); m.addLhsItem(fp4); FactPattern fp5 = new FactPattern("String"); fp5.setBoundName("$s"); SingleFieldConstraint con5 = new SingleFieldConstraint(); con5.setFieldType(DataType.TYPE_STRING); con5.setFieldName("this"); con5.setOperator("=="); con5.setValue("hello"); con5.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp5.addConstraint(con5); m.addLhsItem(fp5); ActionExecuteWorkItem awi = new ActionExecuteWorkItem(); PortableWorkDefinition pwd = new PortableWorkDefinition(); pwd.setName("WorkItem"); awi.setWorkDefinition(pwd); PortableBooleanParameterDefinition p1 = new PortableBooleanParameterDefinition(); p1.setName("BooleanParameter"); p1.setBinding("$b"); p1.setValue(Boolean.TRUE); pwd.addParameter(p1); PortableFloatParameterDefinition p2 = new PortableFloatParameterDefinition(); p2.setName("FloatParameter"); p2.setBinding("$f"); p2.setValue(123.456f); pwd.addParameter(p2); PortableIntegerParameterDefinition p3 = new PortableIntegerParameterDefinition(); p3.setName("IntegerParameter"); p3.setBinding("$i"); p3.setValue(123); pwd.addParameter(p3); PortableStringParameterDefinition p4 = new PortableStringParameterDefinition(); p4.setName("StringParameter"); p4.setBinding("$s"); p4.setValue("hello"); pwd.addParameter(p4); m.addRhsItem(awi); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager();") != -1); assertTrue(result.indexOf("org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem = new org.drools.core.process.instance.impl.WorkItemImpl();") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"BooleanParameter\", $b );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"FloatParameter\", $f );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"IntegerParameter\", $i );") != -1); assertTrue(result.indexOf("wiWorkItem.getParameters().put( \"StringParameter\", $s );") != -1); assertTrue(result.indexOf("wim.internalExecuteWorkItem( wiWorkItem );") != -1); checkMarshalling(null, m); } @Test //Test that WorkItem Parameters whose values are bound are *NOT* created or //populated in the RHS if the Pattern is *NOT* bound to the same variable public void testRHSExecuteWorkItemWithMissingBindings1() { RuleModel m = new RuleModel(); m.name = "WorkItem"; FactPattern fp1 = new FactPattern("Person"); fp1.setBoundName("$p"); SingleFieldConstraint con1 = new SingleFieldConstraint(); con1.setFieldType(DataType.TYPE_STRING); con1.setFieldName("name"); con1.setOperator("=="); con1.setValue("Michael"); con1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp1.addConstraint(con1); m.addLhsItem(fp1); FactPattern fp2 = new FactPattern("Boolean"); fp2.setBoundName("$b1"); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldType(DataType.TYPE_BOOLEAN); con2.setFieldName("this"); con2.setOperator("=="); con2.setValue("true"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp2.addConstraint(con2); m.addLhsItem(fp2); FactPattern fp3 = new FactPattern("Float"); fp3.setBoundName("$f1"); SingleFieldConstraint con3 = new SingleFieldConstraint(); con3.setFieldType(DataType.TYPE_NUMERIC_FLOAT); con3.setFieldName("this"); con3.setOperator("=="); con3.setValue("123.456f"); con3.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp3.addConstraint(con3); m.addLhsItem(fp3); FactPattern fp4 = new FactPattern("Integer"); fp4.setBoundName("$i1"); SingleFieldConstraint con4 = new SingleFieldConstraint(); con4.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con4.setFieldName("this"); con4.setOperator("=="); con4.setValue("123"); con4.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp4.addConstraint(con4); m.addLhsItem(fp4); FactPattern fp5 = new FactPattern("String"); fp5.setBoundName("$s1"); SingleFieldConstraint con5 = new SingleFieldConstraint(); con5.setFieldType(DataType.TYPE_STRING); con5.setFieldName("this"); con5.setOperator("=="); con5.setValue("hello"); con5.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp5.addConstraint(con5); m.addLhsItem(fp5); ActionExecuteWorkItem awi = new ActionExecuteWorkItem(); PortableWorkDefinition pwd = new PortableWorkDefinition(); pwd.setName("WorkItem"); awi.setWorkDefinition(pwd); PortableBooleanParameterDefinition p1 = new PortableBooleanParameterDefinition(); p1.setName("BooleanParameter"); p1.setBinding("$b"); p1.setValue(Boolean.TRUE); pwd.addParameter(p1); PortableFloatParameterDefinition p2 = new PortableFloatParameterDefinition(); p2.setName("FloatParameter"); p2.setBinding("$f"); p2.setValue(123.456f); pwd.addParameter(p2); PortableIntegerParameterDefinition p3 = new PortableIntegerParameterDefinition(); p3.setName("IntegerParameter"); p3.setBinding("$i"); p3.setValue(123); pwd.addParameter(p3); PortableStringParameterDefinition p4 = new PortableStringParameterDefinition(); p4.setName("StringParameter"); p4.setBinding("$s"); p4.setValue("hello"); pwd.addParameter(p4); m.addRhsItem(awi); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager();") != -1); assertTrue(result.indexOf("org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem = new org.drools.core.process.instance.impl.WorkItemImpl();") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"BooleanParameter\", $b1 );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"FloatParameter\", $f1 );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"IntegerParameter\", $i1 );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"StringParameter\", $s1 );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"BooleanParameter\", $b2 );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"FloatParameter\", $f2 );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"IntegerParameter\", $i2 );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"StringParameter\", $s2 );") != -1); assertTrue(result.indexOf("wim.internalExecuteWorkItem( wiWorkItem );") != -1); checkMarshalling(null, m); } @Test //Test that WorkItem Parameters whose values are bound are *NOT* created or //populated in the RHS if the Pattern is *NOT* bound to the same variable public void testRHSExecuteWorkItemWithMissingBindings2() { RuleModel m = new RuleModel(); m.name = "WorkItem"; FactPattern fp1 = new FactPattern("Person"); fp1.setBoundName("$p"); SingleFieldConstraint con1 = new SingleFieldConstraint(); con1.setFieldType(DataType.TYPE_STRING); con1.setFieldName("name"); con1.setOperator("=="); con1.setValue("Michael"); con1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); fp1.addConstraint(con1); m.addLhsItem(fp1); ActionExecuteWorkItem awi = new ActionExecuteWorkItem(); PortableWorkDefinition pwd = new PortableWorkDefinition(); pwd.setName("WorkItem"); awi.setWorkDefinition(pwd); PortableBooleanParameterDefinition p1 = new PortableBooleanParameterDefinition(); p1.setName("BooleanParameter"); p1.setBinding("$b2"); p1.setValue(Boolean.TRUE); pwd.addParameter(p1); PortableFloatParameterDefinition p2 = new PortableFloatParameterDefinition(); p2.setName("FloatParameter"); p2.setBinding("$f2"); p2.setValue(123.456f); pwd.addParameter(p2); PortableIntegerParameterDefinition p3 = new PortableIntegerParameterDefinition(); p3.setName("IntegerParameter"); p3.setBinding("$i2"); p3.setValue(123); pwd.addParameter(p3); PortableStringParameterDefinition p4 = new PortableStringParameterDefinition(); p4.setName("StringParameter"); p4.setBinding("$s2"); p4.setValue("hello"); pwd.addParameter(p4); m.addRhsItem(awi); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager();") != -1); assertTrue(result.indexOf("org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem = new org.drools.core.process.instance.impl.WorkItemImpl();") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"BooleanParameter\", $b );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"FloatParameter\", $f );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"IntegerParameter\", $i );") != -1); assertFalse(result.indexOf("wiWorkItem.getParameters().put( \"StringParameter\", $s );") != -1); assertTrue(result.indexOf("wim.internalExecuteWorkItem( wiWorkItem );") != -1); checkMarshalling(null, m); } @Test //Test that WorkItem Parameters can be used to set fields on existing Facts public void testRHSActionWorkItemSetFields() { RuleModel m = new RuleModel(); m.name = "WorkItem"; FactPattern fp1 = new FactPattern("Results"); fp1.setBoundName("$r"); m.addLhsItem(fp1); ActionExecuteWorkItem awi = new ActionExecuteWorkItem(); PortableWorkDefinition pwd = new PortableWorkDefinition(); pwd.setName("WorkItem"); awi.setWorkDefinition(pwd); PortableBooleanParameterDefinition p1 = new PortableBooleanParameterDefinition(); p1.setName("BooleanResult"); pwd.addResult(p1); PortableFloatParameterDefinition p2 = new PortableFloatParameterDefinition(); p2.setName("FloatResult"); pwd.addResult(p2); PortableIntegerParameterDefinition p3 = new PortableIntegerParameterDefinition(); p3.setName("IntegerResult"); pwd.addResult(p3); PortableStringParameterDefinition p4 = new PortableStringParameterDefinition(); p4.setName("StringResult"); pwd.addResult(p4); m.addRhsItem(awi); ActionSetField asf = new ActionSetField(); asf.setVariable("$r"); ActionWorkItemFieldValue fv1 = new ActionWorkItemFieldValue("ResultsBooleanResult", DataType.TYPE_BOOLEAN, "WorkItem", "BooleanResult", Boolean.class.getName()); asf.addFieldValue(fv1); ActionWorkItemFieldValue fv2 = new ActionWorkItemFieldValue("ResultsFloatResult", DataType.TYPE_NUMERIC_FLOAT, "WorkItem", "FloatResult", Float.class.getName()); asf.addFieldValue(fv2); ActionWorkItemFieldValue fv3 = new ActionWorkItemFieldValue("ResultsIntegerResult", DataType.TYPE_NUMERIC_INTEGER, "WorkItem", "IntegerResult", Integer.class.getName()); asf.addFieldValue(fv3); ActionWorkItemFieldValue fv4 = new ActionWorkItemFieldValue("ResultsStringResult", DataType.TYPE_STRING, "WorkItem", "StringResult", String.class.getName()); asf.addFieldValue(fv4); m.addRhsItem(asf); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager();") != -1); assertTrue(result.indexOf("org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem = new org.drools.core.process.instance.impl.WorkItemImpl();") != -1); assertTrue(result.indexOf("$r.setResultsBooleanResult( (java.lang.Boolean) wiWorkItem.getResult( \"BooleanResult\" ) );") != -1); assertTrue(result.indexOf("$r.setResultsFloatResult( (java.lang.Float) wiWorkItem.getResult( \"FloatResult\" ) );") != -1); assertTrue(result.indexOf("$r.setResultsIntegerResult( (java.lang.Integer) wiWorkItem.getResult( \"IntegerResult\" ) );") != -1); assertTrue(result.indexOf("$r.setResultsStringResult( (java.lang.String) wiWorkItem.getResult( \"StringResult\" ) );") != -1); assertTrue(result.indexOf("wim.internalExecuteWorkItem( wiWorkItem );") != -1); checkMarshalling(null, m); } @Test //Test that WorkItem Parameters can be used to set fields on new Fact public void testRHSActionWorkItemInsertFacts() { RuleModel m = new RuleModel(); m.name = "WorkItem"; ActionExecuteWorkItem awi = new ActionExecuteWorkItem(); PortableWorkDefinition pwd = new PortableWorkDefinition(); pwd.setName("WorkItem"); awi.setWorkDefinition(pwd); PortableBooleanParameterDefinition p1 = new PortableBooleanParameterDefinition(); p1.setName("BooleanResult"); pwd.addResult(p1); PortableFloatParameterDefinition p2 = new PortableFloatParameterDefinition(); p2.setName("FloatResult"); pwd.addResult(p2); PortableIntegerParameterDefinition p3 = new PortableIntegerParameterDefinition(); p3.setName("IntegerResult"); pwd.addResult(p3); PortableStringParameterDefinition p4 = new PortableStringParameterDefinition(); p4.setName("StringResult"); pwd.addResult(p4); m.addRhsItem(awi); ActionInsertFact aif = new ActionInsertFact(); aif.setBoundName("$r"); aif.setFactType("Results"); ActionWorkItemFieldValue fv1 = new ActionWorkItemFieldValue("ResultsBooleanResult", DataType.TYPE_BOOLEAN, "WorkItem", "BooleanResult", Boolean.class.getName()); aif.addFieldValue(fv1); ActionWorkItemFieldValue fv2 = new ActionWorkItemFieldValue("ResultsFloatResult", DataType.TYPE_NUMERIC_FLOAT, "WorkItem", "FloatResult", Float.class.getName()); aif.addFieldValue(fv2); ActionWorkItemFieldValue fv3 = new ActionWorkItemFieldValue("ResultsIntegerResult", DataType.TYPE_NUMERIC_INTEGER, "WorkItem", "IntegerResult", Integer.class.getName()); aif.addFieldValue(fv3); ActionWorkItemFieldValue fv4 = new ActionWorkItemFieldValue("ResultsStringResult", DataType.TYPE_STRING, "WorkItem", "StringResult", String.class.getName()); aif.addFieldValue(fv4); m.addRhsItem(aif); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager();") != -1); assertTrue(result.indexOf("org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem = new org.drools.core.process.instance.impl.WorkItemImpl();") != -1); assertTrue(result.indexOf("Results $r = new Results();") != -1); assertTrue(result.indexOf("$r.setResultsBooleanResult( (java.lang.Boolean) wiWorkItem.getResult( \"BooleanResult\" ) );") != -1); assertTrue(result.indexOf("$r.setResultsFloatResult( (java.lang.Float) wiWorkItem.getResult( \"FloatResult\" ) );") != -1); assertTrue(result.indexOf("$r.setResultsIntegerResult( (java.lang.Integer) wiWorkItem.getResult( \"IntegerResult\" ) );") != -1); assertTrue(result.indexOf("$r.setResultsStringResult( (java.lang.String) wiWorkItem.getResult( \"StringResult\" ) );") != -1); assertTrue(result.indexOf("insert( $r );") != -1); checkMarshalling(null, m); } @Test public void testSubConstraints() { RuleModel m = new RuleModel(); m.name = "test sub constraints"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("field1"); p.addConstraint(con); SingleFieldConstraint con2 = new SingleFieldConstraint(); con2.setFieldName("field2"); con2.setOperator("=="); con2.setValue("variableHere"); con2.setConstraintValueType(SingleFieldConstraint.TYPE_VARIABLE); con2.setParent(con); p.addConstraint(con2); m.addLhsItem(p); String expected = "rule \"test sub constraints\"" + "\tdialect \"mvel\"\n when " + " Person(field1.field2 == variableHere)" + " then " + "end"; checkMarshalling(expected, m); } private void assertEqualsIgnoreWhitespace(final String expected, final String actual) { final String cleanExpected = expected.replaceAll("\\s+", ""); final String cleanActual = actual.replaceAll("\\s+", ""); assertEquals(cleanExpected, cleanActual); } @Test public void testReturnValueConstraint() { RuleModel m = new RuleModel(); m.name = "yeah"; FactPattern p = new FactPattern("Goober"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setConstraintValueType(SingleFieldConstraint.TYPE_RET_VALUE); con.setValue("someFunc(x)"); con.setOperator("=="); con.setFieldName("goo"); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"yeah\" " + "\tdialect \"mvel\"\n when " + "Goober( goo == ( someFunc(x) ) )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testPredicateConstraint() { RuleModel m = new RuleModel(); m.name = "yeah"; FactPattern p = new FactPattern("Goober"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setConstraintValueType(SingleFieldConstraint.TYPE_PREDICATE); con.setValue("field soundslike \"poo\""); p.addConstraint(con); m.addLhsItem(p); String expected = "rule \"yeah\" " + "\tdialect \"mvel\"\n when " + "Goober( eval( field soundslike \"poo\" ) )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testConnective() { RuleModel m = new RuleModel(); m.name = "test literal strings"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_STRING); con.setFieldName("field1"); con.setOperator("=="); con.setValue("goo"); con.setConstraintValueType(SingleFieldConstraint.TYPE_VARIABLE); p.addConstraint(con); ConnectiveConstraint connective = new ConnectiveConstraint(); connective.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); connective.setFieldType(DataType.TYPE_STRING); connective.setOperator("|| =="); connective.setValue("blah"); con.setConnectives(new ConnectiveConstraint[1]); con.getConnectives()[0] = connective; m.addLhsItem(p); String expected = "rule \"test literal strings\" " + "\tdialect \"mvel\"\n when " + "Person( field1 == goo || == \"blah\" )" + " then " + "end"; checkMarshalling(expected, m); } @Test public void testInvalidComposite() throws Exception { RuleModel m = new RuleModel(); CompositeFactPattern com = new CompositeFactPattern("not"); m.addLhsItem(com); String s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertNotNull(s); m.addLhsItem(new CompositeFactPattern("or")); m.addLhsItem(new CompositeFactPattern("exists")); s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertNotNull(s); } @Test public void testAssertWithDSL() throws Exception { RuleModel m = new RuleModel(); DSLSentence sen = new DSLSentence(); sen.setDefinition("I CAN HAS DSL"); m.addRhsItem(sen); ActionInsertFact ins = new ActionInsertFact("Shizzle"); ActionFieldValue val = new ActionFieldValue("goo", "42", "Numeric"); ins.setFieldValues(new ActionFieldValue[1]); ins.getFieldValues()[0] = val; m.addRhsItem(ins); ActionInsertLogicalFact insL = new ActionInsertLogicalFact("Shizzle"); ActionFieldValue valL = new ActionFieldValue("goo", "42", "Numeric"); insL.setFieldValues(new ActionFieldValue[1]); insL.getFieldValues()[0] = valL; m.addRhsItem(insL); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf(">insert") > -1); assertTrue(result.indexOf(">insertLogical") > -1); } @Test public void testDefaultMVEL() { RuleModel m = new RuleModel(); String s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(s.indexOf("mvel") > -1); m.addAttribute(new RuleAttribute("dialect", "goober")); s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertFalse(s.indexOf("mvel") > -1); assertTrue(s.indexOf("goober") > -1); } @Test public void testLockOnActive() { RuleModel m = new RuleModel(); m.addAttribute(new RuleAttribute("lock-on-active", "true")); m.addAttribute(new RuleAttribute("auto-focus", "true")); m.addAttribute(new RuleAttribute("duration", "42")); String s = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(s.indexOf("lock-on-active true") > -1); assertTrue(s.indexOf("auto-focus true") > -1); assertTrue(s.indexOf("duration 42") > -1); checkMarshalling(s, m); } @Test public void testAddGlobal() { String expected = "rule \"my rule\"\n\tno-loop true\n\tdialect \"mvel\"\n\twhen\n\t\tPerson( )\n" + "\t\tAccident( )\n\tthen\n\t\tinsert( new Report() );\n\t\tresults.add(f);\nend\n"; final RuleModel m = new RuleModel(); m.addLhsItem(new FactPattern("Person")); m.addLhsItem(new FactPattern("Accident")); m.addAttribute(new RuleAttribute("no-loop", "true")); m.addRhsItem(new ActionInsertFact("Report")); ActionGlobalCollectionAdd add = new ActionGlobalCollectionAdd(); add.setGlobalName("results"); add.setFactName("f"); m.addRhsItem(add); m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testCompositeOrConstraints() { RuleModel m = new RuleModel(); m.name = "or composite"; FactPattern p = new FactPattern("Goober"); m.addLhsItem(p); CompositeFieldConstraint comp = new CompositeFieldConstraint(); comp.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_OR); p.addConstraint(comp); final SingleFieldConstraint sfc1 = new SingleFieldConstraint(); sfc1.setFactType("Goober"); sfc1.setFieldName("gooField"); sfc1.setFieldType(DataType.TYPE_STRING); sfc1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc1.setValue("gooValue"); sfc1.setOperator("=="); comp.addConstraint(sfc1); final SingleFieldConstraint sfc2 = new SingleFieldConstraint(); sfc2.setFactType("Goober"); sfc2.setFieldName("fooField"); sfc2.setFieldType(DataType.TYPE_OBJECT); sfc2.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc2.setOperator("!= null"); comp.addConstraint(sfc2); final SingleFieldConstraint sfc3 = new SingleFieldConstraint(); sfc3.setFactType("Bar"); sfc3.setFieldName("barField"); sfc3.setParent(sfc2); sfc3.setFieldType(DataType.TYPE_STRING); sfc3.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc3.setValue("barValue"); sfc3.setOperator("=="); comp.addConstraint(sfc3); ActionInsertFact ass = new ActionInsertFact("Whee"); m.addRhsItem(ass); String actual = RuleModelDRLPersistenceImpl.getInstance().marshal(m); String expected = "rule \"or composite\"" + "dialect \"mvel\"\n" + "when\n" + "Goober( gooField == \"gooValue\" || fooField != null || fooField.barField == \"barValue\" )\n" + "then\n" + "insert( new Whee() );\n" + "end"; checkMarshalling(expected, m); } @Test public void testCompositeOrConstraintsComplex() { RuleModel m = new RuleModel(); m.name = "or composite complex"; FactPattern p = new FactPattern("Goober"); m.addLhsItem(p); CompositeFieldConstraint comp = new CompositeFieldConstraint(); comp.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_OR); p.addConstraint(comp); final SingleFieldConstraint sfc1 = new SingleFieldConstraint(); sfc1.setFactType("Goober"); sfc1.setFieldName("gooField"); sfc1.setFieldType(DataType.TYPE_STRING); sfc1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc1.setValue("gooValue"); sfc1.setOperator("=="); comp.addConstraint(sfc1); final SingleFieldConstraint sfc2 = new SingleFieldConstraint(); sfc2.setFactType("Goober"); sfc2.setFieldName("fooField"); sfc2.setFieldType(DataType.TYPE_OBJECT); sfc2.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc2.setOperator("!= null"); comp.addConstraint(sfc2); final SingleFieldConstraint sfc3 = new SingleFieldConstraint(); sfc3.setFactType("Bar"); sfc3.setFieldName("barField"); sfc3.setParent(sfc2); sfc3.setFieldType(DataType.TYPE_STRING); sfc3.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc3.setValue("barValue"); sfc3.setOperator("=="); comp.addConstraint(sfc3); final SingleFieldConstraint sfc4 = new SingleFieldConstraint(); sfc4.setFactType("Goober"); sfc4.setFieldName("zooField"); sfc4.setFieldType(DataType.TYPE_STRING); sfc4.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc4.setValue("zooValue"); sfc4.setOperator("=="); p.addConstraint(sfc4); ActionInsertFact ass = new ActionInsertFact("Whee"); m.addRhsItem(ass); String expected = "rule \"or composite complex\"" + "dialect \"mvel\"\n" + "when\n" + "Goober( gooField == \"gooValue\" || fooField != null || fooField.barField == \"barValue\", zooField == \"zooValue\" )\n" + "then\n" + "insert( new Whee() );\n" + "end"; checkMarshalling(expected, m); } @Test public void testCompositeAndConstraints() { RuleModel m = new RuleModel(); m.name = "and composite"; FactPattern p = new FactPattern("Goober"); m.addLhsItem(p); CompositeFieldConstraint comp = new CompositeFieldConstraint(); comp.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_AND); p.addConstraint(comp); final SingleFieldConstraint sfc1 = new SingleFieldConstraint(); sfc1.setFactType("Goober"); sfc1.setFieldName("gooField"); sfc1.setFieldType(DataType.TYPE_STRING); sfc1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc1.setValue("gooValue"); sfc1.setOperator("=="); comp.addConstraint(sfc1); final SingleFieldConstraint sfc2 = new SingleFieldConstraint(); sfc2.setFactType("Goober"); sfc2.setFieldName("fooField"); sfc2.setFieldType(DataType.TYPE_OBJECT); sfc2.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc2.setOperator("!= null"); comp.addConstraint(sfc2); final SingleFieldConstraint sfc3 = new SingleFieldConstraint(); sfc3.setFactType("Bar"); sfc3.setFieldName("barField"); sfc3.setParent(sfc2); sfc3.setFieldType(DataType.TYPE_STRING); sfc3.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc3.setValue("barValue"); sfc3.setOperator("=="); comp.addConstraint(sfc3); ActionInsertFact ass = new ActionInsertFact("Whee"); m.addRhsItem(ass); String expected = "rule \"and composite\"" + "dialect \"mvel\"\n" + "when\n" + "Goober( gooField == \"gooValue\" && fooField != null && fooField.barField == \"barValue\" )\n" + "then\n" + "insert( new Whee() );\n" + "end"; checkMarshalling(expected, m); } @Test public void testCompositeAndConstraintsComplex() { RuleModel m = new RuleModel(); m.name = "and composite complex"; FactPattern p = new FactPattern("Goober"); m.addLhsItem(p); CompositeFieldConstraint comp = new CompositeFieldConstraint(); comp.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_AND); p.addConstraint(comp); final SingleFieldConstraint sfc1 = new SingleFieldConstraint(); sfc1.setFactType("Goober"); sfc1.setFieldName("gooField"); sfc1.setFieldType(DataType.TYPE_STRING); sfc1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc1.setValue("gooValue"); sfc1.setOperator("=="); comp.addConstraint(sfc1); final SingleFieldConstraint sfc2 = new SingleFieldConstraint(); sfc2.setFactType("Goober"); sfc2.setFieldName("fooField"); sfc2.setFieldType(DataType.TYPE_OBJECT); sfc2.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc2.setOperator("!= null"); comp.addConstraint(sfc2); final SingleFieldConstraint sfc3 = new SingleFieldConstraint(); sfc1.setFactType("Bar"); sfc3.setFieldName("barField"); sfc3.setParent(sfc2); sfc3.setFieldType(DataType.TYPE_STRING); sfc3.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc3.setValue("barValue"); sfc3.setOperator("=="); comp.addConstraint(sfc3); final SingleFieldConstraint sfc4 = new SingleFieldConstraint(); sfc4.setFactType("Goober"); sfc4.setFieldName("zooField"); sfc4.setFieldType(DataType.TYPE_STRING); sfc4.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); sfc4.setValue("zooValue"); sfc4.setOperator("=="); p.addConstraint(sfc4); ActionInsertFact ass = new ActionInsertFact("Whee"); m.addRhsItem(ass); String actual = RuleModelDRLPersistenceImpl.getInstance().marshal(m); String expected = "rule \"and composite complex\"" + "dialect \"mvel\"\n" + "when\n" + "Goober( gooField == \"gooValue\" && fooField != null && fooField.barField == \"barValue\", zooField == \"zooValue\" )\n" + "then\n" + "insert( new Whee() );\n" + "end"; checkMarshalling(expected, m); } @Test public void testRHSSetMethodCallsMethodMVEL() { String oldValue = System.getProperty("drools.dateformat"); try { System.setProperty("drools.dateformat", "dd-MMM-yyyy"); RuleModel m = new RuleModel(); m.name = "RHS SetMethodCallsMethod"; m.addAttribute(new RuleAttribute("dialect", "mvel")); FactPattern p = new FactPattern("Person"); p.setBoundName("$p"); m.addLhsItem(p); ActionCallMethod acm = new ActionCallMethod(); acm.setMethodName("method"); acm.setVariable("$p"); acm.addFieldValue(new ActionFieldFunction("f1", "String", DataType.TYPE_STRING)); acm.addFieldValue(new ActionFieldFunction("f2", "true", DataType.TYPE_BOOLEAN)); acm.addFieldValue(new ActionFieldFunction("f3", "31-Jan-2012", DataType.TYPE_DATE)); acm.addFieldValue(new ActionFieldFunction("f4", "100", DataType.TYPE_NUMERIC_INTEGER)); acm.addFieldValue(new ActionFieldFunction("f5", "100", DataType.TYPE_NUMERIC_BIGDECIMAL)); m.addRhsItem(acm); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(\"dd-MMM-yyyy\");") != -1); assertTrue(result.indexOf("$p.method( \"String\", true, sdf.parse(\"31-Jan-2012\"), 100, 100B );") != -1); checkMarshalling(null, m); } finally { if (oldValue == null) { System.clearProperty("drools.dateformat"); } else { System.setProperty("drools.dateformat", oldValue); } } } @Test public void testRHSSetMethodCallsMethodJava() { String oldValue = System.getProperty("drools.dateformat"); try { System.setProperty("drools.dateformat", "dd-MMM-yyyy"); RuleModel m = new RuleModel(); m.name = "RHS SetMethodCallsMethod"; m.addAttribute(new RuleAttribute("dialect", "java")); FactPattern p = new FactPattern("Person"); p.setBoundName("$p"); m.addLhsItem(p); ActionCallMethod acm = new ActionCallMethod(); acm.setMethodName("method"); acm.setVariable("$p"); acm.addFieldValue(new ActionFieldFunction("f1", "String", DataType.TYPE_STRING)); acm.addFieldValue(new ActionFieldFunction("f2", "true", DataType.TYPE_BOOLEAN)); acm.addFieldValue(new ActionFieldFunction("f3", "31-Jan-2012", DataType.TYPE_DATE)); acm.addFieldValue(new ActionFieldFunction("f4", "100", DataType.TYPE_NUMERIC_INTEGER)); acm.addFieldValue(new ActionFieldFunction("f5", "100", DataType.TYPE_NUMERIC_BIGDECIMAL)); m.addRhsItem(acm); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertTrue(result.indexOf("java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(\"dd-MMM-yyyy\");") != -1); assertTrue(result.indexOf("$p.method( \"String\", true, sdf.parse(\"31-Jan-2012\"), 100, new java.math.BigDecimal(\"100\") );") != -1); checkMarshalling(null, m); } finally { if (oldValue == null) { System.clearProperty("drools.dateformat"); } else { System.setProperty("drools.dateformat", oldValue); } } } @Test public void testFromAccumulateWithEmbeddedFromEntryPoint() { RuleModel m = new RuleModel(); m.name = "r1"; SingleFieldConstraint sfc = new SingleFieldConstraint("bar"); sfc.setFactType(DataType.TYPE_NUMERIC_INTEGER); sfc.setFieldBinding("$a"); sfc.setOperator("=="); sfc.setValue("777"); FactPattern fp = new FactPattern("Foo"); fp.addConstraint(sfc); FromEntryPointFactPattern fep = new FromEntryPointFactPattern(); fep.setEntryPointName("ep"); fep.setFactPattern(fp); FromAccumulateCompositeFactPattern fac = new FromAccumulateCompositeFactPattern(); fac.setSourcePattern(fep); fac.setFactPattern(new FactPattern("java.util.List")); fac.setFunction("max($a)"); m.addLhsItem(fac); String expected = "rule \"r1\"\n" + "dialect \"mvel\"\n" + "when\n" + "java.util.List( ) from accumulate ( Foo( $a : bar == 777 ) from entry-point \"ep\", \n" + "max($a))\n" + "then\n" + "end"; checkMarshalling(expected, m); } @Test public void testFromCollectWithEmbeddedFromEntryPoint() { RuleModel m = new RuleModel(); m.name = "r1"; SingleFieldConstraint sfc = new SingleFieldConstraint("bar"); sfc.setFactType(DataType.TYPE_NUMERIC_INTEGER); sfc.setFieldBinding("$a"); sfc.setOperator("=="); sfc.setValue("777"); FactPattern fp = new FactPattern("Foo"); fp.addConstraint(sfc); FromEntryPointFactPattern fep = new FromEntryPointFactPattern(); fep.setEntryPointName("ep"); fep.setFactPattern(fp); FromCollectCompositeFactPattern fac = new FromCollectCompositeFactPattern(); fac.setRightPattern(fep); fac.setFactPattern(new FactPattern("java.util.List")); m.addLhsItem(fac); String expected = "rule \"r1\"\n" + "dialect \"mvel\"\n" + "when\n" + "java.util.List( ) from collect ( Foo( $a : bar == 777 ) from entry-point \"ep\" ) \n" + "then\n" + "end"; checkMarshalling(expected, m); } @Test public void testCompositeFactPatternWithFrom() { final RuleModel m = new RuleModel(); m.name = "model"; final FactPattern fp1 = new FactPattern("Data"); fp1.setBoundName("$d"); m.addLhsItem(fp1); final FactPattern fp2 = new FactPattern("Person"); final FromCompositeFactPattern ffp1 = new FromCompositeFactPattern(); ffp1.setExpression(new ExpressionFormLine(new ExpressionVariable(fp1.getBoundName(), fp1.getFactType()))); ffp1.setFactPattern(fp2); m.addLhsItem(ffp1); final String actual = RuleModelDRLPersistenceImpl.getInstance().marshal(m); final String expected = "rule \"model\"\n" + "dialect \"mvel\"\n" + "when\n" + "$d : Data( )\n" + "(Person( ) from $d)\n" + "\n" + "then\n" + "end\n"; assertEqualsIgnoreWhitespace(expected, actual); } @Test public void testCompositeFactPatternWithFromWithDSL() { final RuleModel m = new RuleModel(); m.name = "model"; final DSLSentence sen = new DSLSentence(); sen.setDefinition("A DSL phrase"); m.addLhsItem(sen); final FactPattern fp1 = new FactPattern("Data"); fp1.setBoundName("$d"); m.addLhsItem(fp1); final CompositeFactPattern cp = new CompositeFactPattern(CompositeFactPattern.COMPOSITE_TYPE_NOT); final FactPattern fp2 = new FactPattern("Person"); final FromCompositeFactPattern ffp1 = new FromCompositeFactPattern(); ffp1.setExpression(new ExpressionFormLine(new ExpressionVariable(fp1.getBoundName(), fp1.getFactType()))); ffp1.setFactPattern(fp2); cp.addFactPattern(ffp1); m.addLhsItem(cp); final String actual = RuleModelDRLPersistenceImpl.getInstance().marshal(m); final String expected = "rule \"model\"\n" + "dialect \"mvel\"\n" + "when\n" + "A DSL phrase\n" + ">$d : Data( )\n" + ">not ( Person( ) from $d\n" + ")\n" + "then\n" + "end\n"; assertEqualsIgnoreWhitespace(expected, actual); } @Test public void testImports() { final String drl = "import java.util.ArrayList;\n" + "rule \"r0\"\n" + "dialect \"mvel\"" + "when\n" + "then\n" + "end\n"; PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertNotNull(m); assertEquals(1, m.getImports().getImports().size()); assertEquals("java.util.ArrayList", m.getImports().getImports().get(0).getType()); } @Test public void testActionSetFieldValue() { final String drl = "rule \"r0\"\n" + "dialect \"mvel\"\n" + "when\n" + "$a : Applicant( )\n" + "then\n" + "$a.setName( \"Michael\" );\n" + "end\n"; PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertNotNull(m); //LHS assertEquals(1, m.lhs.length); assertTrue(m.lhs[0] instanceof FactPattern); final FactPattern p = (FactPattern) m.lhs[0]; assertEquals("$a", p.getBoundName()); assertEquals("Applicant", p.getFactType()); //RHS assertEquals(1, m.rhs.length); assertTrue(m.rhs[0] instanceof ActionSetField); final ActionSetField a = (ActionSetField) m.rhs[0]; assertEquals("$a", a.getVariable()); assertEquals(1, a.getFieldValues().length); final ActionFieldValue fv = a.getFieldValues()[0]; assertEquals("name", fv.getField()); assertEquals("Michael", fv.getValue()); } @Test public void testActionSetFieldValueWithDSL() { String oldValue = System.getProperty("drools.dateformat"); try { System.setProperty("drools.dateformat", "dd-MMM-yyyy"); final String dsl = "There is an Applicant"; final String dslDefinition = "[when]" + dsl + "=$a : Applicant();"; final RuleModel m = new RuleModel(); m.name = "r0"; final DSLSentence sen = new DSLSentence(); sen.setDefinition(dsl); m.addLhsItem(sen); final ActionInsertFact aif = new ActionInsertFact("Applicant"); aif.addFieldValue(new ActionFieldValue("applicationDate", "13-Mar-2017", DataType.TYPE_DATE)); m.addRhsItem(aif); final String expected = "rule \"r0\"\n" + "dialect \"mvel\"\n" + "when\n" + "There is an Applicant\n" + "then\n" + ">java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(\"dd-MMM-yyyy\");\n" + ">Applicant fact0 = new Applicant();\n" + ">fact0.setApplicationDate( sdf.parse(\"13-Mar-2017\") );\n" + ">insert( fact0 );\n" + "end"; final String actual = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertEqualsIgnoreWhitespace(expected, actual); PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); final RuleModel m2 = RuleModelDRLPersistenceImpl.getInstance().unmarshalUsingDSL(actual, Collections.emptyList(), dmo, dslDefinition); assertNotNull(m2); //LHS assertEquals(1, m.lhs.length); DSLSentence dslSentence = (DSLSentence) m.lhs[0]; assertEquals(dsl, dslSentence.getDefinition()); assertEquals(0, dslSentence.getValues().size()); //RHS assertEquals(1, m2.rhs.length); assertTrue(m2.rhs[0] instanceof ActionInsertFact); final ActionInsertFact a = (ActionInsertFact) m2.rhs[0]; assertEquals("Applicant", a.getFactType()); assertEquals(1, a.getFieldValues().length); final ActionFieldValue afv = a.getFieldValues()[0]; assertEquals("applicationDate", afv.getField()); assertEquals("13-Mar-2017", afv.getValue()); } finally { if (oldValue == null) { System.clearProperty("drools.dateformat"); } else { System.setProperty("drools.dateformat", oldValue); } } } @Test public void testActionCallMethod() { final String drl = "rule \"r0\"\n" + "dialect \"mvel\"\n" + "when\n" + "$a : Applicant( )\n" + "then\n" + "$a.addName( \"Michael\" );\n" + "end\n"; PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertNotNull(m); //LHS assertEquals(1, m.lhs.length); assertTrue(m.lhs[0] instanceof FactPattern); final FactPattern p = (FactPattern) m.lhs[0]; assertEquals("$a", p.getBoundName()); assertEquals("Applicant", p.getFactType()); //RHS assertEquals(1, m.rhs.length); assertTrue(m.rhs[0] instanceof ActionCallMethod); final ActionCallMethod a = (ActionCallMethod) m.rhs[0]; assertEquals("$a", a.getVariable()); assertEquals("addName", a.getMethodName()); assertEquals(1, a.getFieldValues().length); final ActionFieldValue fv = a.getFieldValue(0); assertEquals("Michael", fv.getValue()); } @Test public void testAddToGlobalCollection() { String global = "global java.util.ArrayList list"; String drl = "rule \"r0\"\n" + "dialect \"mvel\"\n" + "when\n" + "$a : Applicant( )\n" + "then\n" + "list.add( $a );\n" + "end\n"; final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Arrays.asList(global), mock(PackageDataModelOracle.class)); assertNotNull(m); assertEqualsIgnoreWhitespace(drl, RuleModelDRLPersistenceImpl.getInstance().marshal(m)); //LHS assertEquals(1, m.lhs.length); assertTrue(m.lhs[0] instanceof FactPattern); final FactPattern p = (FactPattern) m.lhs[0]; assertEquals("$a", p.getBoundName()); assertEquals("Applicant", p.getFactType()); //RHS assertEquals(1, m.rhs.length); assertTrue(m.rhs[0] instanceof ActionGlobalCollectionAdd); final ActionGlobalCollectionAdd a = (ActionGlobalCollectionAdd) m.rhs[0]; assertEquals("list", a.getGlobalName()); assertEquals("$a", a.getFactName()); } @Test public void testFreeFormatDRLCondition() { final String drl = "rule \"r0\"\n" + "dialect \"mvel\"\n" + "when\n" + "$a : Applicant( )\n" + "Here's something typed by the user as free-format DRL\n" + "$b : Bananna( )\n" + "then\n" + "end\n"; PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertNotNull(m); //LHS assertEquals(3, m.lhs.length); //Condition line 1 assertTrue(m.lhs[0] instanceof FactPattern); final FactPattern fp1 = (FactPattern) m.lhs[0]; assertEquals("$a", fp1.getBoundName()); assertEquals("Applicant", fp1.getFactType()); //Condition line 2 assertTrue(m.lhs[1] instanceof FreeFormLine); final FreeFormLine ffl = (FreeFormLine) m.lhs[1]; assertEquals("Here's something typed by the user as free-format DRL", ffl.getText()); //Condition line 3 assertTrue(m.lhs[2] instanceof FactPattern); final FactPattern fp2 = (FactPattern) m.lhs[2]; assertEquals("$b", fp2.getBoundName()); assertEquals("Bananna", fp2.getFactType()); } @Test public void testFreeFormatDRLAction() { final String drl = "rule \"r0\"\n" + "dialect \"mvel\"\n" + "when\n" + "$a : Applicant( )\n" + "then\n" + "$a.setName( \"Michael\" );\n" + "Here's something typed by the user as free-format DRL\n" + "$a.setAge( 40 );\n" + "end\n"; PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertNotNull(m); //LHS assertEquals(1, m.lhs.length); assertTrue(m.lhs[0] instanceof FreeFormLine); final FreeFormLine ffl1 = (FreeFormLine) m.lhs[0]; assertEquals("$a : Applicant( )", ffl1.getText()); //RHS assertEquals(1, m.rhs.length); assertTrue(m.rhs[0] instanceof FreeFormLine); final FreeFormLine ffl2 = (FreeFormLine) m.rhs[0]; assertEquals("$a.setName( \"Michael\" );\n" + "Here's something typed by the user as free-format DRL\n" + "$a.setAge( 40 );", ffl2.getText()); } @Test public void testGenerateEmptyXML() { final RuleModelPersistence p = RuleModelDRLPersistenceImpl.getInstance(); final String drl = p.marshal(new RuleModel()); assertNotNull(drl); assertFalse(drl.equals("")); } @Test public void testBasics2() { final RuleModelPersistence p = RuleModelDRLPersistenceImpl.getInstance(); final RuleModel m = new RuleModel(); m.addLhsItem(new FactPattern("Person")); m.addLhsItem(new FactPattern("Accident")); m.addAttribute(new RuleAttribute("no-loop", "true")); m.addRhsItem(new ActionInsertFact("Report")); ActionGlobalCollectionAdd ag = new ActionGlobalCollectionAdd(); ag.setFactName("x"); ag.setGlobalName("g"); m.addRhsItem(ag); m.name = "my rule"; final String drl = p.marshal(m); assertTrue(drl.indexOf("Person( )") > -1); assertTrue(drl.indexOf("Accident( )") > -1); assertTrue(drl.indexOf("no-loop true") > -1); assertTrue(drl.indexOf("org.kie") == -1); assertTrue(drl.indexOf("g.add( x );") > -1); PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); RuleModel rm_ = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertEquals(2, rm_.rhs.length); } @Test public void testMoreComplexRendering2() { final RuleModelPersistence p = RuleModelDRLPersistenceImpl.getInstance(); final RuleModel m = getComplexModel(); final String drl = p.marshal(m); assertTrue(drl.indexOf("org.kie") == -1); } @Test public void testRoundTrip() { final RuleModel m = getComplexModel(); final String drl = RuleModelDRLPersistenceImpl.getInstance().marshal(m); PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); final RuleModel m2 = RuleModelDRLPersistenceImpl.getInstance().unmarshalUsingDSL(drl, Collections.EMPTY_LIST, dmo); assertNotNull(m2); assertEquals(m.name, m2.name); assertEquals(m.lhs.length, m2.lhs.length); assertEquals(m.rhs.length, m2.rhs.length); assertEquals(1, m.attributes.length); final RuleAttribute at = m.attributes[0]; assertEquals("no-loop", at.getAttributeName()); assertEquals("true", at.getValue()); final String drl2 = RuleModelDRLPersistenceImpl.getInstance().marshal(m2); assertEquals(drl, drl2); } @Test public void testCompositeConstraintsRoundTrip() throws Exception { RuleModel m = new RuleModel(); m.name = "with composite"; FactPattern p1 = new FactPattern("Person"); p1.setBoundName("p1"); m.addLhsItem(p1); FactPattern p = new FactPattern("Goober"); m.addLhsItem(p); CompositeFieldConstraint comp = new CompositeFieldConstraint(); comp.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_OR); p.addConstraint(comp); final SingleFieldConstraint X = new SingleFieldConstraint(); X.setFieldName("goo"); X.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); X.setValue("foo"); X.setOperator("=="); X.setConnectives(new ConnectiveConstraint[1]); X.getConnectives()[0] = new ConnectiveConstraint(); X.getConnectives()[0].setConstraintValueType(ConnectiveConstraint.TYPE_LITERAL); X.getConnectives()[0].setOperator("|| =="); X.getConnectives()[0].setValue("bar"); comp.addConstraint(X); final SingleFieldConstraint Y = new SingleFieldConstraint(); Y.setFieldName("goo2"); Y.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); Y.setValue("foo"); Y.setOperator("=="); comp.addConstraint(Y); CompositeFieldConstraint comp2 = new CompositeFieldConstraint(); comp2.setCompositeJunctionType(CompositeFieldConstraint.COMPOSITE_TYPE_AND); final SingleFieldConstraint Q1 = new SingleFieldConstraint(); Q1.setFieldName("goo"); Q1.setOperator("=="); Q1.setValue("whee"); Q1.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); comp2.addConstraint(Q1); final SingleFieldConstraint Q2 = new SingleFieldConstraint(); Q2.setFieldName("gabba"); Q2.setOperator("=="); Q2.setValue("whee"); Q2.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); comp2.addConstraint(Q2); //now nest it comp.addConstraint(comp2); final SingleFieldConstraint Z = new SingleFieldConstraint(); Z.setFieldName("goo3"); Z.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); Z.setValue("foo"); Z.setOperator("=="); p.addConstraint(Z); ActionInsertFact ass = new ActionInsertFact("Whee"); m.addRhsItem(ass); String drl = RuleModelDRLPersistenceImpl.getInstance().marshal(m); PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); RuleModel m2 = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertNotNull(m2); assertEquals("with composite", m2.name); assertEquals(m2.lhs.length, m.lhs.length); assertEquals(m2.rhs.length, m.rhs.length); } @Test public void testFreeFormLine() { RuleModel m = new RuleModel(); m.name = "with composite"; m.lhs = new IPattern[1]; m.rhs = new IAction[1]; FreeFormLine fl = new FreeFormLine(); fl.setText("Person()"); m.lhs[0] = fl; FreeFormLine fr = new FreeFormLine(); fr.setText("fun()"); m.rhs[0] = fr; String drl = RuleModelDRLPersistenceImpl.getInstance().marshal(m); assertNotNull(drl); PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); RuleModel m_ = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl, Collections.EMPTY_LIST, dmo); assertEquals(1, m_.lhs.length); assertEquals(1, m_.rhs.length); assertEquals("Person", ((FactPattern) m_.lhs[0]).getFactType()); assertEquals("fun()", ((FreeFormLine) m_.rhs[0]).getText()); } private RuleModel getComplexModel() { final RuleModel m = new RuleModel(); m.name = "complex"; m.addAttribute(new RuleAttribute("no-loop", "true")); final FactPattern pat = new FactPattern("Person"); pat.setBoundName("p1"); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFactType("Person"); con.setFieldBinding("f1"); con.setFieldName("age"); con.setOperator("<"); con.setValue("42"); pat.addConstraint(con); m.addLhsItem(pat); final CompositeFactPattern comp = new CompositeFactPattern("not"); comp.addFactPattern(new FactPattern("Cancel")); m.addLhsItem(comp); final ActionUpdateField set = new ActionUpdateField(); set.setVariable("p1"); set.addFieldValue(new ActionFieldValue("status", "rejected", DataType.TYPE_STRING)); m.addRhsItem(set); final ActionRetractFact ret = new ActionRetractFact("p1"); m.addRhsItem(ret); final DSLSentence sen = new DSLSentence(); sen.setDefinition("Send an email to {administrator}"); m.addRhsItem(sen); return m; } @Test public void testLoadEmpty() { PackageDataModelOracle dmo = mock(PackageDataModelOracle.class); RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal("", Collections.EMPTY_LIST, dmo); assertNotNull(m); m = RuleModelDRLPersistenceImpl.getInstance().unmarshal("", Collections.EMPTY_LIST, dmo); assertNotNull(m); } @Test public void testIncompleteFieldConstraintStringWithNull() { String expected = "" + "rule \"rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " Message( text == \"\" )\n" + " then\n" + "end\n"; final RuleModel m = new RuleModel(); m.name = "rule"; final FactPattern pat = new FactPattern("Message"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("text"); con.setOperator("=="); con.setValue(null); con.setFieldType(DataType.TYPE_STRING); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); pat.addConstraint(con); checkMarshalling(expected, m); } @Test public void testIncompleteFieldConstraintStringWithNonNull() { String expected = "" + "rule \"rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " Message( text == \"\" )\n" + " then\n" + "end\n"; final RuleModel m = new RuleModel(); m.name = "rule"; final FactPattern pat = new FactPattern("Message"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("text"); con.setOperator("=="); con.setValue(""); con.setFieldType(DataType.TYPE_STRING); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); pat.addConstraint(con); checkMarshalling(expected, m); } @Test public void testIncompleteFieldConstraintNonStringWithNull() { String expected = "" + "rule \"rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " Message()\n" + " then\n" + "end\n"; final RuleModel m = new RuleModel(); m.name = "rule"; final FactPattern pat = new FactPattern("Message"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("number"); con.setOperator("=="); con.setValue(null); con.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); pat.addConstraint(con); checkMarshalling(expected, m); } @Test public void testIncompleteFieldConstraintNonStringWithNonNull() { String expected = "" + "rule \"rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " Message()\n" + " then\n" + "end\n"; final RuleModel m = new RuleModel(); m.name = "rule"; final FactPattern pat = new FactPattern("Message"); m.addLhsItem(pat); final SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldName("number"); con.setOperator("=="); con.setValue(""); con.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); pat.addConstraint(con); checkMarshalling(expected, m); } @Test public void testRHSFactBindingZeroBound() { RuleModel m = new RuleModel(); m.addAttribute(new RuleAttribute("dialect", "mvel")); m.name = "test"; ActionInsertFact ai0 = new ActionInsertFact("Person"); ai0.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_LONG)); ActionInsertFact ai1 = new ActionInsertFact("Person"); ai1.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_LONG)); m.addRhsItem(ai0); m.addRhsItem(ai1); String expected = "rule \"test\" \n" + "dialect \"mvel\"\n" + "when" + "then \n" + "Person fact0 = new Person(); \n" + "fact0.setField1( 55 ); \n" + "insert( fact0 ); \n" + "Person fact1 = new Person(); \n" + "fact1.setField1( 55 ); \n" + "insert( fact1 ); \n" + "end"; checkMarshalling(expected, m); } @Test public void testRHSFactBindingFirstBound() { RuleModel m = new RuleModel(); m.name = "test"; ActionInsertFact ai0 = new ActionInsertFact("Person"); ai0.setBoundName("fact0"); ai0.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_LONG)); ActionInsertFact ai1 = new ActionInsertFact("Person"); ai1.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_LONG)); m.addRhsItem(ai0); m.addRhsItem(ai1); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); String expected = "rule \"test\" \n" + "dialect \"mvel\"\n" + "when" + "then \n" + "Person fact0 = new Person(); \n" + "fact0.setField1( 55 ); \n" + "insert( fact0 ); \n" + "Person fact1 = new Person(); \n" + "fact1.setField1( 55 ); \n" + "insert( fact1 ); \n" + "end"; checkMarshalling(expected, m); } @Test public void testRHSFactBindingLastBound() { RuleModel m = new RuleModel(); m.name = "test"; ActionInsertFact ai0 = new ActionInsertFact("Person"); ai0.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_LONG)); ActionInsertFact ai1 = new ActionInsertFact("Person"); ai1.setBoundName("fact0"); ai1.addFieldValue(new ActionFieldValue("field1", "55", DataType.TYPE_NUMERIC_LONG)); m.addRhsItem(ai0); m.addRhsItem(ai1); String result = RuleModelDRLPersistenceImpl.getInstance().marshal(m); String expected = "rule \"test\" \n" + "dialect \"mvel\"\n" + "when" + "then \n" + "Person fact1 = new Person(); \n" + "fact1.setField1( 55 ); \n" + "insert( fact1 ); \n" + "Person fact0 = new Person(); \n" + "fact0.setField1( 55 ); \n" + "insert( fact0 ); \n" + "end"; checkMarshalling(expected, m); } @Test public void testEmptyFreeForm() { //https://bugzilla.redhat.com/show_bug.cgi?id=1058247 RuleModel m = new RuleModel(); m.name = "Empty FreeFormLine"; m.lhs = new IPattern[1]; m.rhs = new IAction[1]; FreeFormLine fl = new FreeFormLine(); m.lhs[0] = fl; FreeFormLine fr = new FreeFormLine(); m.rhs[0] = fr; String drl = ruleModelPersistence.marshal(m); assertNotNull(drl); } @Test public void testRHSSetFieldWithVariable() { //https://bugzilla.redhat.com/show_bug.cgi?id=1077212 RuleModel m = new RuleModel(); m.name = "variable"; FactPattern p = new FactPattern("Person"); SingleFieldConstraint con = new SingleFieldConstraint(); con.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con.setFieldName("field1"); con.setOperator("=="); con.setValue("44"); con.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); con.setFieldBinding("$f"); p.addConstraint(con); m.addLhsItem(p); ActionInsertFact ai = new ActionInsertFact("Person"); ActionFieldValue acv = new ActionFieldValue("field1", "=$f", DataType.TYPE_OBJECT); acv.setNature(FieldNatureType.TYPE_VARIABLE); ai.addFieldValue(acv); m.addRhsItem(ai); String expected = "rule \"variable\"\n" + "dialect \"mvel\"\n" + "when\n" + "Person( $f : field1 == 44 )\n" + "then\n" + "Person fact0 = new Person();\n" + "fact0.setField1( $f );\n" + "insert( fact0 );\n" + "end"; checkMarshalling(expected, m); } @Test public void testLHSFormula() { //https://bugzilla.redhat.com/show_bug.cgi?id=1087690 RuleModel m = new RuleModel(); m.name = "test"; FactPattern p = new FactPattern("Number"); m.addLhsItem(p); SingleFieldConstraint con1 = new SingleFieldConstraint(); con1.setValue("true"); con1.setConstraintValueType(SingleFieldConstraint.TYPE_PREDICATE); p.addConstraint(con1); SingleFieldConstraintEBLeftSide con2 = new SingleFieldConstraintEBLeftSide(); con2.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con2.getExpressionLeftSide().appendPart(new ExpressionMethod("intValue", "int", DataType.TYPE_NUMERIC_INTEGER)); con2.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); con2.setOperator("=="); con2.setValue("0"); p.addConstraint(con2); String expected = "rule \"test\"\n" + "dialect \"mvel\"\n" + "when\n" + "Number( eval( true ), intValue() == 0 )\n" + "then\n" + "end"; checkMarshalling(expected, m); } @Test public void testLHSReturnType() { //https://bugzilla.redhat.com/show_bug.cgi?id=1087690 RuleModel m = new RuleModel(); m.name = "test"; FactPattern p = new FactPattern("Number"); m.addLhsItem(p); SingleFieldConstraint con1 = new SingleFieldConstraint(); con1.setFieldType(DataType.TYPE_NUMERIC_INTEGER); con1.setFieldName("this"); con1.setOperator("!= null"); con1.setConstraintValueType(SingleFieldConstraint.TYPE_LITERAL); p.addConstraint(con1); SingleFieldConstraintEBLeftSide con2 = new SingleFieldConstraintEBLeftSide(); con2.getExpressionLeftSide().appendPart(new ExpressionUnboundFact(p.getFactType())); con2.getExpressionLeftSide().appendPart(new ExpressionMethod("intValue", "int", DataType.TYPE_NUMERIC_INTEGER)); con2.setConstraintValueType(BaseSingleFieldConstraint.TYPE_LITERAL); con2.setOperator("=="); con2.setValue("0"); p.addConstraint(con2); String expected = "rule \"test\"\n" + "dialect \"mvel\"\n" + "when\n" + "Number( this != null, intValue() == 0 )\n" + "then\n" + "end"; checkMarshalling(expected, m); } @Test public void testRHSChangeMultipleFieldsModifyBoth() { String expected = "" + "rule \"my rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " $p : Person()\n" + " then\n" + " modify( $p ) {\n" + " setName( \"Fred\" ),\n" + " setAge( 55 )\n" + " }\n" + "end\n"; final RuleModel m = new RuleModel(); FactPattern factPattern = new FactPattern(); factPattern.setFactType("Person"); factPattern.setBoundName("$p"); m.lhs = new IPattern[]{factPattern}; ActionUpdateField auf = new ActionUpdateField(); auf.setVariable("$p"); ActionFieldValue afv1 = new ActionFieldValue(); afv1.setField("name"); afv1.setType(DataType.TYPE_STRING); afv1.setNature(FieldNatureType.TYPE_LITERAL); afv1.setValue("Fred"); ActionFieldValue afv2 = new ActionFieldValue(); afv2.setField("age"); afv2.setType(DataType.TYPE_NUMERIC_INTEGER); afv2.setNature(FieldNatureType.TYPE_LITERAL); afv2.setValue("55"); auf.setFieldValues(new ActionFieldValue[]{afv1, afv2}); m.rhs = new IAction[]{auf}; m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testRHSChangeMultipleFieldsModifyOneUpdateOther() { String expected = "" + "rule \"my rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " $p : Person()\n" + " then\n" + " modify( $p ) {\n" + " setName( \"Fred\" )\n" + " }\n" + " $p.setAge( 55 );\n" + "end\n"; final RuleModel m = new RuleModel(); FactPattern factPattern = new FactPattern(); factPattern.setFactType("Person"); factPattern.setBoundName("$p"); m.lhs = new IPattern[]{factPattern}; ActionUpdateField auf = new ActionUpdateField(); auf.setVariable("$p"); ActionFieldValue afv1 = new ActionFieldValue(); afv1.setField("name"); afv1.setType(DataType.TYPE_STRING); afv1.setNature(FieldNatureType.TYPE_LITERAL); afv1.setValue("Fred"); auf.setFieldValues(new ActionFieldValue[]{afv1}); ActionSetField asf = new ActionSetField(); asf.setVariable("$p"); ActionFieldValue afv2 = new ActionFieldValue(); afv2.setField("age"); afv2.setType(DataType.TYPE_NUMERIC_INTEGER); afv2.setNature(FieldNatureType.TYPE_LITERAL); afv2.setValue("55"); asf.setFieldValues(new ActionFieldValue[]{afv2}); m.rhs = new IAction[]{auf, asf}; m.name = "my rule"; checkMarshalling(expected, m); } @Test public void testRHSChangeMultipleFieldsBlockModify() { String expected = "" + "rule \"my rule\" \n" + " dialect \"mvel\"\n" + " when\n" + " $p : Person()\n" + " then\n" + " modify( $p ) {\n" + " setName( \"Fred\" ),\n" + " setAge( 55 )\n" + " }\n" + " $p.setGender( \"X\" );" + "end\n"; final RuleModel m = new RuleModel(); FactPattern factPattern = new FactPattern(); factPattern.setFactType("Person"); factPattern.setBoundName("$p"); m.lhs = new IPattern[]{factPattern}; ActionUpdateField auf1 = new ActionUpdateField(); auf1.setVariable("$p"); ActionFieldValue afv1 = new ActionFieldValue(); afv1.setField("name"); afv1.setType(DataType.TYPE_STRING); afv1.setNature(FieldNatureType.TYPE_LITERAL); afv1.setValue("Fred"); auf1.setFieldValues(new ActionFieldValue[]{afv1}); ActionSetField asf = new ActionSetField(); asf.setVariable("$p"); ActionFieldValue afv2 = new ActionFieldValue(); afv2.setField("gender"); afv2.setType(DataType.TYPE_STRING); afv2.setNature(FieldNatureType.TYPE_LITERAL); afv2.setValue("X"); asf.setFieldValues(new ActionFieldValue[]{afv2}); ActionUpdateField auf2 = new ActionUpdateField(); auf2.setVariable("$p"); ActionFieldValue afv3 = new ActionFieldValue(); afv3.setField("age"); afv3.setType(DataType.TYPE_NUMERIC_INTEGER); afv3.setNature(FieldNatureType.TYPE_LITERAL); afv3.setValue("55"); auf2.setFieldValues(new ActionFieldValue[]{afv3}); m.rhs = new IAction[]{auf1, asf, auf2}; m.name = "my rule"; checkMarshalling(expected, m); } }