From 3a059b98d7248ef111b09619625418241a1d9dfb Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 9 Jun 2014 14:48:22 +0200 Subject: [PATCH 01/76] [BZ-1096128] fix incremental compilation of KieModules having external dependencies (cherry picked from commit 7ac8092562dc3fafd320831f99b753e7bda6986b) --- .../org/kie/scanner/DependencyDescriptor.java | 4 ++ .../kie/scanner/KieRepositoryScannerImpl.java | 46 ++++++++---- .../kie/scanner/KieRepositoryScannerTest.java | 72 ++++++++++++++++++- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/kie-ci/src/main/java/org/kie/scanner/DependencyDescriptor.java b/kie-ci/src/main/java/org/kie/scanner/DependencyDescriptor.java index d57f469a6e3..5eee3c584bc 100644 --- a/kie-ci/src/main/java/org/kie/scanner/DependencyDescriptor.java +++ b/kie-ci/src/main/java/org/kie/scanner/DependencyDescriptor.java @@ -95,6 +95,10 @@ public static boolean isRangedVersion(String version) { version.indexOf('[') >= 0 || version.indexOf(']') >= 0; } + public boolean isSameArtifact(ReleaseId releaseId) { + return groupId.equals(releaseId.getGroupId()) && artifactId.equals(releaseId.getArtifactId()); + } + public boolean isSnapshot() { return isSnapshot(version); } diff --git a/kie-ci/src/main/java/org/kie/scanner/KieRepositoryScannerImpl.java b/kie-ci/src/main/java/org/kie/scanner/KieRepositoryScannerImpl.java index 86b8c5a48aa..2548da405fa 100644 --- a/kie-ci/src/main/java/org/kie/scanner/KieRepositoryScannerImpl.java +++ b/kie-ci/src/main/java/org/kie/scanner/KieRepositoryScannerImpl.java @@ -1,17 +1,18 @@ package org.kie.scanner; import org.drools.compiler.kie.builder.impl.InternalKieContainer; -import org.drools.compiler.kproject.ReleaseIdImpl; -import org.drools.compiler.kproject.models.KieModuleModelImpl; -import org.kie.api.builder.ReleaseId; -import org.kie.api.builder.KieModule; -import org.kie.api.builder.KieScanner; -import org.kie.api.builder.Message; import org.drools.compiler.kie.builder.impl.InternalKieModule; import org.drools.compiler.kie.builder.impl.InternalKieScanner; import org.drools.compiler.kie.builder.impl.MemoryKieModule; import org.drools.compiler.kie.builder.impl.ResultsImpl; import org.drools.compiler.kie.builder.impl.ZipKieModule; +import org.drools.compiler.kproject.ReleaseIdImpl; +import org.drools.compiler.kproject.models.KieModuleModelImpl; +import org.kie.api.KieServices; +import org.kie.api.builder.KieModule; +import org.kie.api.builder.KieScanner; +import org.kie.api.builder.Message; +import org.kie.api.builder.ReleaseId; import org.kie.api.builder.model.KieModuleModel; import org.kie.api.runtime.KieContainer; import org.kie.scanner.management.KieScannerMBean; @@ -33,9 +34,9 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import static org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieModule; import static org.drools.compiler.kie.builder.impl.KieBuilderImpl.setDefaultsforEmptyKieModule; import static org.kie.scanner.ArtifactResolver.getResolverFor; -import static org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieModule; import static org.kie.scanner.DependencyDescriptor.isFixedVersion; public class KieRepositoryScannerImpl implements InternalKieScanner { @@ -148,12 +149,17 @@ private InternalKieModule buildArtifact(Artifact artifact, ArtifactResolver reso private void addDependencies(InternalKieModule kieModule, ArtifactResolver resolver, List dependencies) { for (DependencyDescriptor dep : dependencies) { - Artifact depArtifact = resolver.resolveArtifact(dep.getReleaseId()); - if (depArtifact != null && isKJar(depArtifact.getFile())) { - ReleaseId depReleaseId = new DependencyDescriptor(depArtifact).getReleaseId(); - ZipKieModule zipKieModule = createZipKieModule(depReleaseId, depArtifact.getFile()); - if (zipKieModule != null) { - kieModule.addKieDependency(zipKieModule); + InternalKieModule dependency = (InternalKieModule) KieServices.Factory.get().getRepository().getKieModule(dep.getReleaseId()); + if (dependency != null) { + kieModule.addKieDependency(dependency); + } else { + Artifact depArtifact = resolver.resolveArtifact(dep.getReleaseId()); + if (depArtifact != null && isKJar(depArtifact.getFile())) { + ReleaseId depReleaseId = new DependencyDescriptor(depArtifact).getReleaseId(); + ZipKieModule zipKieModule = createZipKieModule(depReleaseId, depArtifact.getFile()); + if (zipKieModule != null) { + kieModule.addKieDependency(zipKieModule); + } } } } @@ -246,9 +252,20 @@ public synchronized void scanNow() { return; } status = Status.UPDATING; + + // build the dependencies first + Map.Entry containerEntry = null; for (Map.Entry entry : updatedArtifacts.entrySet()) { - updateKieModule(entry.getKey(), entry.getValue()); + if (entry.getKey().isSameArtifact(kieContainer.getContainerReleaseId())) { + containerEntry = entry; + } else { + updateKieModule(entry.getKey(), entry.getValue()); + } } + if (containerEntry != null) { + updateKieModule(containerEntry.getKey(), containerEntry.getValue()); + } + log.info("The following artifacts have been updated: " + updatedArtifacts); // show we catch exceptions here and shutdown the scanner if one happens? @@ -262,6 +279,7 @@ private void updateKieModule(DependencyDescriptor oldDependency, Artifact artifa ReleaseId newReleaseId = new DependencyDescriptor(artifact).getReleaseId(); ZipKieModule kieModule = createZipKieModule(newReleaseId, artifact.getFile()); if (kieModule != null) { + addDependencies(kieModule, artifactResolver, artifactResolver.getArtifactDependecies(newReleaseId.toString())); ResultsImpl messages = build(kieModule); if ( messages.filterMessages(Message.Level.ERROR).isEmpty()) { ((InternalKieContainer)kieContainer).updateDependencyToVersion(oldDependency.getArtifactReleaseId(), diff --git a/kie-ci/src/test/java/org/kie/scanner/KieRepositoryScannerTest.java b/kie-ci/src/test/java/org/kie/scanner/KieRepositoryScannerTest.java index ef26dc3762f..af49d91b17e 100644 --- a/kie-ci/src/test/java/org/kie/scanner/KieRepositoryScannerTest.java +++ b/kie-ci/src/test/java/org/kie/scanner/KieRepositoryScannerTest.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.junit.Assert.*; @@ -196,6 +197,9 @@ public void testScannerOnPomProject() throws Exception { KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, 15); + + ks.getRepository().removeKieModule(releaseId1); + ks.getRepository().removeKieModule(releaseId2); } private File createMasterKPom(String depArtifactId) throws IOException { @@ -232,7 +236,8 @@ private void checkKSession(KieSession ksession, Object... results) { assertEquals(results.length, list.size()); for (Object result : results) { - assertTrue( list.contains( result ) ); + assertTrue( String.format("Expected to contain: %s, got: %s", result, Arrays.toString(list.toArray())), + list.contains( result ) ); } } @@ -313,6 +318,9 @@ public void testScannerOnPomRuleProject() throws Exception { KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, "rule2"); + + ks.getRepository().removeKieModule(releaseId1); + ks.getRepository().removeKieModule(releaseId2); } @Test @@ -331,6 +339,8 @@ public void testMissingDependency() throws Exception { List messages = kieBuilder.buildAll().getResults().getMessages(); assertEquals(1, messages.size()); assertTrue(messages.get(0).toString().contains("missing-dep")); + + ks.getRepository().removeKieModule(releaseId); } @Test @@ -370,5 +380,65 @@ public void testScanIncludedDependency() throws Exception { KieSession ksession2 = kieContainer.newKieSession("KSession2"); checkKSession(ksession2, "rule2"); + + ks.getRepository().removeKieModule(containerReleaseId); + ks.getRepository().removeKieModule(includedReleaseId); + } + + @Test + public void testScanIncludedAndIncludingDependency() throws Exception { + MavenRepository repository = getMavenRepository(); + KieServices ks = KieServices.Factory.get(); + + ReleaseId containerReleaseId = KieServices.Factory.get().newReleaseId( "org.kie", "test-container", "1.0.0-SNAPSHOT" ); + ReleaseId includedReleaseId = KieServices.Factory.get().newReleaseId( "org.kie", "test-project", "1.0.0-SNAPSHOT" ); + + InternalKieModule kJar1 = createKieJar(ks, includedReleaseId, "rule1"); + repository.deployArtifact(includedReleaseId, kJar1, createKPom(fileManager, includedReleaseId)); + + resetFileManager(); + + InternalKieModule containerKJar = createIncludingKJar(containerReleaseId, includedReleaseId, "ruleX"); + repository.deployArtifact(containerReleaseId, containerKJar, createKPom(fileManager, containerReleaseId, includedReleaseId)); + + KieContainer kieContainer = ks.newKieContainer(containerReleaseId); + KieSession ksession = kieContainer.newKieSession("KSession2"); + checkKSession(ksession, "rule1", "ruleX"); + + resetFileManager(); + + KieScanner scanner = ks.newKieScanner(kieContainer); + + InternalKieModule kJar2 = createKieJar(ks, includedReleaseId, "rule2"); + repository.deployArtifact(includedReleaseId, kJar2, createKPom(fileManager, includedReleaseId)); + resetFileManager(); + + InternalKieModule containerKJar2 = createIncludingKJar(containerReleaseId, includedReleaseId, "ruleY"); + repository.deployArtifact(containerReleaseId, containerKJar2, createKPom(fileManager, containerReleaseId, includedReleaseId)); + resetFileManager(); + + scanner.scanNow(); + + KieSession ksession2 = kieContainer.newKieSession("KSession2"); + checkKSession(ksession2, "rule2", "ruleY"); + + ks.getRepository().removeKieModule(containerReleaseId); + ks.getRepository().removeKieModule(includedReleaseId); + } + + private InternalKieModule createIncludingKJar(ReleaseId containerReleaseId, ReleaseId includedReleaseId, String rule) { + KieServices ks = KieServices.Factory.get(); + KieFileSystem kfs = ks.newKieFileSystem(); + String file = "org/test/" + rule + ".drl"; + kfs.write("src/main/resources/KBase2/" + file, createDRL(rule)); + + KieModuleModel kproj = ks.newKieModuleModel(); + kproj.newKieBaseModel("KBase2").addInclude("KBase1").newKieSessionModel("KSession2"); + kfs.writeKModuleXML(kproj.toXML()); + kfs.writePomXML(getPom(containerReleaseId, includedReleaseId)); + + KieBuilder kieBuilder = ks.newKieBuilder(kfs); + assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty()); + return (InternalKieModule) kieBuilder.getKieModule(); } } \ No newline at end of file From f6af4dbc1d27ee1a5cab708d88354279d8401f3e Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 11 Jun 2014 09:47:54 +0200 Subject: [PATCH 02/76] [BZ-1106300] propagate as insert a formerly deleted eval left tuple (cherry picked from commit 320f34fd01dc6763b46922e3fc2a002f16c64274) --- .../compiler/integrationtests/Misc2Test.java | 116 ++++++++++++++++++ .../drools/core/phreak/PhreakEvalNode.java | 8 +- 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index 617403e114d..10f73ce8da1 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -6035,4 +6035,120 @@ public void testAccumulateWithNodeSharing() throws Exception { ksession.fireAllRules(); assertEquals(1, d.getValue()); } + + public static class Reading { + private final String type; + private final int value; + + public Reading(String type, int value) { + this.type = type; + this.value = value; + } + + public String getType() { + return type; + } + + public int getValue() { + return value; + } + } + + public static class Alarm { + private String type; + private String level; + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + } + + @Test + public void testDeletedEvalLeftTuple() throws Exception { + // BZ-1106300 + String drl = + "import " + Reading.class.getCanonicalName() + ";\n" + + "import " + Alarm.class.getCanonicalName() + ";\n" + + "rule Normal when\n" + + " Number( intValue <= 5) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + + " alarm : Alarm ()\n" + + "then\n" + + " System.out.println(kcontext.getRule().getName());" + + " delete( alarm );\n" + + "end\n" + + " \n" + + "rule Abnormal when\n" + + " Number( intValue > 5, intValue <= 10 ) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + + " not Alarm ()\n" + + "then\n" + + " System.out.println(kcontext.getRule().getName());" + + " Alarm alarm = new Alarm();\n" + + " alarm.setType(\"t1\");\n" + + " alarm.setLevel( \"ABNORMAL\" );\n" + + " insert(alarm);\n" + + "end\n" + + "\n" + + "rule Severe when\n" + + " Number( intValue > 10) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + + " not Alarm ()\n" + + "then\n" + + " System.out.println(kcontext.getRule().getName());" + + " Alarm alarm = new Alarm();\n" + + " alarm.setType(\"t1\");\n" + + " alarm.setLevel( \"SEVERE\" );\n" + + " insert(alarm);\n" + + "end\n" + + "\n" + + "rule AbnormalToSevere when\n" + + " Number( intValue > 10) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + + " alarm : Alarm (level == \"ABNORMAL\")\n" + + "then\n" + + " System.out.println(kcontext.getRule().getName());" + + " alarm.setLevel( \"SEVERE\" );\n" + + " update(alarm);\n" + + "end\n" + + "\n" + + "rule SevereToAbnormal when\n" + + " $type : String()\n" + + " accumulate( reading : Reading( type == $type ), $avg : average( reading.getValue() ) )\n" + + " eval( $avg.intValue() > 5 && $avg.intValue() <= 10 )\n" + + " alarm : Alarm (type == $type, level == \"SEVERE\")\n" + + "then\n" + + " System.out.println(kcontext.getRule().getName());" + + " alarm.setLevel( \"ABNORMAL\" );\n" + + " update(alarm);\n" + + "end"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ksession = helper.build().newKieSession(); + + ksession.insert("t1"); + + ksession.insert(new Reading("t1", 12)); + ksession.fireAllRules(); + ksession.insert(new Reading("t1", 0)); + ksession.fireAllRules(); + ksession.insert(new Reading("t1", 0)); + ksession.fireAllRules(); + + ksession.insert(new Reading("t1", 16)); + ksession.fireAllRules(); + ksession.insert(new Reading("t1", 32)); + ksession.fireAllRules(); + ksession.insert(new Reading("t1", -6)); + ksession.fireAllRules(); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java b/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java index 1b8bbc065da..68fccea7939 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java +++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java @@ -16,6 +16,9 @@ * To change this template use File | Settings | File Templates. */ public class PhreakEvalNode { + + private static final String EVAL_LEFT_TUPLE_DELETED = "EVAL_LEFT_TUPLE_DELETED"; + public void doNode(EvalConditionNode evalNode, EvalMemory em, LeftTupleSink sink, @@ -77,12 +80,14 @@ public void doLeftUpdates(EvalConditionNode evalNode, for (LeftTuple leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple != null; ) { LeftTuple next = leftTuple.getStagedNext(); - boolean wasPropagated = leftTuple.getFirstChild() != null; + boolean wasPropagated = leftTuple.getFirstChild() != null && leftTuple.getObject() != EVAL_LEFT_TUPLE_DELETED; boolean allowed = condition.isAllowed(leftTuple, wm, em.context); if (allowed) { + leftTuple.setObject(null); + if (wasPropagated) { // update LeftTuple childLeftTuple = leftTuple.getFirstChild(); @@ -107,6 +112,7 @@ public void doLeftUpdates(EvalConditionNode evalNode, } else { if (wasPropagated) { // retract + leftTuple.setObject(EVAL_LEFT_TUPLE_DELETED); LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple.setPropagationContext( leftTuple.getPropagationContext()); From 1ee15b970f2fc27cb5ccf7cf1c92887b2359bf26 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 11 Jun 2014 12:02:25 +0200 Subject: [PATCH 03/76] [DROOLS-517] enhance DRL->RuleModel unmarshalling to handle modify() {...} block (cherry picked from commit 93a7db35d91795a4d22da01e935aa785d4433655) --- .../org/drools/core/util/StringUtils.java | 4 +- .../rule/RuleModelDRLPersistenceImpl.java | 145 +++++++++++++----- ...eModelDRLPersistenceUnmarshallingTest.java | 25 ++- 3 files changed, 123 insertions(+), 51 deletions(-) diff --git a/drools-core/src/main/java/org/drools/core/util/StringUtils.java b/drools-core/src/main/java/org/drools/core/util/StringUtils.java index c48fc6d85e9..fc1acd8b5e0 100644 --- a/drools-core/src/main/java/org/drools/core/util/StringUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/StringUtils.java @@ -987,12 +987,12 @@ private static List codeAwareSplitOnChar(CharSequence string, char ch) { case '(': case '[': case '{': - nestedParam++; + if (!isQuoted) nestedParam++; break; case ')': case ']': case '}': - nestedParam--; + if (!isQuoted) nestedParam--; break; case '"': case '\'': diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java index 80b5cdd81fd..38bd2a15221 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java @@ -16,16 +16,6 @@ package org.drools.workbench.models.commons.backend.rule; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.drools.compiler.compiler.DrlParser; import org.drools.compiler.compiler.DroolsParserException; import org.drools.compiler.lang.descr.AccumulateDescr; @@ -113,6 +103,17 @@ import org.drools.workbench.models.datamodel.workitems.PortableStringParameterDefinition; import org.drools.workbench.models.datamodel.workitems.PortableWorkDefinition; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.drools.core.util.StringUtils.splitArgumentsList; import static org.drools.workbench.models.commons.backend.rule.RuleModelPersistenceHelper.*; /** @@ -2258,6 +2259,9 @@ private void parseRhs( RuleModel m, Map setStatementsPosition = new HashMap(); Map factsType = new HashMap(); + String modifiedVariable = null; + String modifiers = null; + int lineCounter = -1; String[] lines = rhs.split( "\n" ); for ( String line : lines ) { @@ -2270,7 +2274,32 @@ private void parseRhs( RuleModel m, } } line = line.trim(); - if ( line.startsWith( "insertLogical" ) ) { + if ( modifiedVariable != null ) { + int modifyBlockEnd = line.lastIndexOf('}'); + if (modifiers == null) { + modifiers = modifyBlockEnd > 0 ? + line.substring( line.indexOf( '{' ) + 1, modifyBlockEnd ).trim() : + line.substring( line.indexOf( '{' ) + 1 ).trim(); + } else if (modifyBlockEnd != 0) { + modifiers += modifyBlockEnd > 0 ? + line.substring( 0, modifyBlockEnd ).trim() : + line; + } + if (modifyBlockEnd >= 0) { + ActionUpdateField action = new ActionUpdateField(); + action.setVariable( modifiedVariable ); + m.addRhsItem( action ); + addModifiersToAction( modifiedVariable, + modifiers, + action, + boundParams, + dmo, + m.getImports(), + isJavaDialect ); + modifiedVariable = null; + modifiers = null; + } + } else if ( line.startsWith( "insertLogical" ) ) { String fact = unwrapParenthesis( line ); String type = getStatementType( fact, factsType ); if ( type != null ) { @@ -2287,7 +2316,7 @@ private void parseRhs( RuleModel m, } } } else if ( line.startsWith( "insert" ) ) { - String fact = unwrapParenthesis( line ); + String fact = unwrapParenthesis(line); String type = getStatementType( fact, factsType ); if ( type != null ) { ActionInsertFact action = new ActionInsertFact( type ); @@ -2315,7 +2344,28 @@ private void parseRhs( RuleModel m, dmo, m.getImports(), isJavaDialect ); - } else if ( line.startsWith( "retract" ) ) { + } else if ( line.startsWith( "modify" ) ) { + int modifyBlockEnd = line.lastIndexOf('}'); + if (modifyBlockEnd > 0) { + String variable = line.substring( line.indexOf( '(' ) + 1, line.indexOf( ')' ) ).trim(); + ActionUpdateField action = new ActionUpdateField(); + action.setVariable( variable ); + m.addRhsItem( action ); + addModifiersToAction( variable, + line.substring( line.indexOf( '{' ) + 1, modifyBlockEnd ).trim(), + action, + boundParams, + dmo, + m.getImports(), + isJavaDialect ); + } else { + modifiedVariable = line.substring( line.indexOf( '(' ) + 1, line.indexOf( ')' ) ).trim(); + int modifyBlockStart = line.indexOf('{'); + if (modifyBlockStart > 0) { + modifiers = line.substring(modifyBlockStart+1).trim(); + } + } + } else if ( line.startsWith( "retract" ) || line.startsWith( "delete" ) ) { String variable = unwrapParenthesis( line ); m.addRhsItem( new ActionRetractFact( variable ) ); } else if ( line.startsWith( "org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem" ) ) { @@ -2323,7 +2373,7 @@ private void parseRhs( RuleModel m, pwd = new PortableWorkDefinition(); pwd.setName( "WorkItem" ); awi.setWorkDefinition( pwd ); - m.addRhsItem( awi ); + m.addRhsItem(awi); } else if ( line.startsWith( "wiWorkItem.getParameters().put" ) ) { String statement = line.substring( "wiWorkItem.getParameters().put".length() ); statement = unwrapParenthesis( statement ); @@ -2457,7 +2507,7 @@ private DSLSentence toDSLSentence( List dslPatterns, return dslSentence; } } - dslSentence.setDefinition( dslLine ); + dslSentence.setDefinition(dslLine); return dslSentence; } @@ -2527,26 +2577,51 @@ private void addSettersToAction( List setters, int dotPos = statement.indexOf( '.' ); int argStart = statement.indexOf( '(' ); String methodName = statement.substring( dotPos + 1, argStart ).trim(); - String field = getSettedField( methodName ); - String value = unwrapParenthesis( statement ); - String dataType = inferDataType( action, - field, - boundParams, - dmo, - imports ); - if ( dataType == null ) { - dataType = inferDataType( value, - boundParams, - isJavaDialect ); - } - action.addFieldValue( buildFieldValue( isJavaDialect, - field, - value, - dataType, - boundParams, - dmo ) ); - } - } + addSetterToAction(action, boundParams, dmo, imports, isJavaDialect, statement, methodName); + } + } + } + + private void addModifiersToAction( String variable, + String modifiers, + ActionFieldList action, + Map boundParams, + PackageDataModelOracle dmo, + Imports imports, + boolean isJavaDialect ) { + for (String statement : splitArgumentsList(modifiers)) { + int argStart = statement.indexOf( '(' ); + String methodName = statement.substring( 0, argStart ).trim(); + addSetterToAction(action, boundParams, dmo, imports, isJavaDialect, statement, methodName); + } + } + + + private void addSetterToAction( ActionFieldList action, + Map boundParams, + PackageDataModelOracle dmo, + Imports imports, + boolean isJavaDialect, + String statement, + String methodName ) { + String field = getSettedField( methodName ); + String value = unwrapParenthesis( statement ); + String dataType = inferDataType( action, + field, + boundParams, + dmo, + imports ); + if ( dataType == null ) { + dataType = inferDataType( value, + boundParams, + isJavaDialect ); + } + action.addFieldValue(buildFieldValue(isJavaDialect, + field, + value, + dataType, + boundParams, + dmo)); } private ActionFieldValue buildFieldValue( boolean isJavaDialect, diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java index 1b620a6cd81..efa33a58468 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java @@ -15,13 +15,6 @@ * limitations under the License. */ -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.FieldAccessorsAndMutators; import org.drools.workbench.models.datamodel.oracle.MethodInfo; @@ -66,8 +59,16 @@ import org.junit.Ignore; import org.junit.Test; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class RuleModelDRLPersistenceUnmarshallingTest { @@ -4643,7 +4644,6 @@ public void testLHSInOperatorFieldNameContainingNotInLiteral() { } @Test - @Ignore("https://issues.jboss.org/browse/DROOLS-517") public void testRHSModifyBlockSingleFieldSingleLine() throws Exception { //The value used in the "set" is intentionally yucky to catch extraction of the field's value errors! String drl = "rule \"modify1\"\n" + @@ -4687,7 +4687,6 @@ public void testRHSModifyBlockSingleFieldSingleLine() throws Exception { } @Test - @Ignore("https://issues.jboss.org/browse/DROOLS-517") public void testRHSModifyBlockSingleFieldMultipleLines() throws Exception { //The value used in the "set" is intentionally yucky to catch extraction of the field's value errors! String drl = "rule \"modify1\"\n" + @@ -4733,7 +4732,6 @@ public void testRHSModifyBlockSingleFieldMultipleLines() throws Exception { } @Test - @Ignore("https://issues.jboss.org/browse/DROOLS-517") public void testRHSModifyBlockMultipleFieldsSingleLine() throws Exception { //The value used in the "set" is intentionally yucky to catch extraction of the field's value errors! String drl = "rule \"modify1\"\n" + @@ -4779,7 +4777,7 @@ public void testRHSModifyBlockMultipleFieldsSingleLine() throws Exception { assertEquals( DataType.TYPE_STRING, value1.getType() ); - ActionFieldValue value2 = field.getFieldValues()[ 0 ]; + ActionFieldValue value2 = field.getFieldValues()[ 1 ]; assertEquals( "lastName", value2.getField() ); assertEquals( ",)", @@ -4791,7 +4789,6 @@ public void testRHSModifyBlockMultipleFieldsSingleLine() throws Exception { } @Test - @Ignore("https://issues.jboss.org/browse/DROOLS-517") public void testRHSModifyBlockMultipleFieldsMultipleLines() throws Exception { //The value used in the "set" is intentionally yucky to catch extraction of the field's value errors! String drl = "rule \"modify1\"\n" + @@ -4840,7 +4837,7 @@ public void testRHSModifyBlockMultipleFieldsMultipleLines() throws Exception { assertEquals( DataType.TYPE_STRING, value1.getType() ); - ActionFieldValue value2 = field.getFieldValues()[ 0 ]; + ActionFieldValue value2 = field.getFieldValues()[ 1 ]; assertEquals( "lastName", value2.getField() ); assertEquals( ",)", From 0d1e9cd4cf6cf676d5a10dde11b3e71c3ab5173a Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Tue, 10 Jun 2014 16:49:58 +0100 Subject: [PATCH 04/76] BZ1105043 - Guided rule editor cannot handle 'str' as a substring of fact pattern (cherry picked from commit b1a358c9148fb338e2f3bf0add864a1218e94301) --- ...eModelDRLPersistenceUnmarshallingTest.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java index efa33a58468..aae495c6b32 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java @@ -4848,6 +4848,76 @@ public void testRHSModifyBlockMultipleFieldsMultipleLines() throws Exception { value2.getType() ); } + @Test + @Ignore("https://bugzilla.redhat.com/show_bug.cgi?id=1105043") + public void testLiteralStrFieldNames() throws Exception { + //The issue is fields that contain the "str" operator literal value + String drl = "rule \"rule1\"\n" + + " dialect \"mvel\"\n" + + " when\n" + + " Room( decoration == \"tapestry\" , strangeField == 11 )\n" + + " then\n" + + "end"; + + addModelField( "Room", + "decoration", + "java.lang.String", + DataType.TYPE_STRING ); + addModelField( "Room", + "strangeField", + "java.lang.Integer", + DataType.TYPE_NUMERIC_INTEGER ); + + RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + Collections.EMPTY_LIST, + dmo ); + + assertNotNull( m ); + assertEquals( "rule1", + m.name ); + + assertEquals( 1, + m.lhs.length ); + IPattern p = m.lhs[ 0 ]; + assertTrue( p instanceof FactPattern ); + + FactPattern fp = (FactPattern) p; + assertEquals( "Room", + fp.getFactType() ); + + assertEquals( 2, + fp.getNumberOfConstraints() ); + assertTrue( fp.getConstraint( 0 ) instanceof SingleFieldConstraint ); + + SingleFieldConstraint sfp0 = (SingleFieldConstraint) fp.getConstraint( 0 ); + assertEquals( "Room", + sfp0.getFactType() ); + assertEquals( "decoration", + sfp0.getFieldName() ); + assertEquals( "==", + sfp0.getOperator() ); + assertEquals( "tapestry", + sfp0.getValue() ); + assertEquals( BaseSingleFieldConstraint.TYPE_LITERAL, + sfp0.getConstraintValueType() ); + assertEquals( DataType.TYPE_STRING, + sfp0.getFieldType() ); + + SingleFieldConstraint sfp1 = (SingleFieldConstraint) fp.getConstraint( 1 ); + assertEquals( "Room", + sfp1.getFactType() ); + assertEquals( "strangeField", + sfp1.getFieldName() ); + assertEquals( "==", + sfp1.getOperator() ); + assertEquals( "11", + sfp1.getValue() ); + assertEquals( BaseSingleFieldConstraint.TYPE_LITERAL, + sfp1.getConstraintValueType() ); + assertEquals( DataType.TYPE_NUMERIC_INTEGER, + sfp1.getFieldType() ); + } + private void assertEqualsIgnoreWhitespace( final String expected, final String actual ) { final String cleanExpected = expected.replaceAll( "\\s+", From aae610a61ee4d10df6f3ee381f4b80a90e848024 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 11 Jun 2014 12:57:03 +0200 Subject: [PATCH 05/76] [BZ-1105043] fix operators recognition inside an expression (cherry picked from commit 4073a9603b8f774f1e72cff3fd3c74e161e8e30b) --- .../rule/RuleModelDRLPersistenceImpl.java | 23 +++++++++++++++---- ...eModelDRLPersistenceUnmarshallingTest.java | 2 -- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java index 38bd2a15221..9f7fb309736 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java @@ -2207,13 +2207,18 @@ private void parseConstraint( RuleModel m, private static String findOperator( String expr ) { final Set potentialOperators = new HashSet(); for ( Operator op : Operator.getAllOperators() ) { + String opString = op.getOperatorString(); if ( op.isNegated() ) { - if ( expr.contains( " not " + op.getOperatorString() ) ) { - return "not " + op.getOperatorString(); + if ( expr.contains( " not " + opString ) ) { + return "not " + opString; } } - if ( expr.contains( op.getOperatorString() ) ) { - potentialOperators.add( op.getOperatorString() ); + int opPos = expr.indexOf(opString); + if ( opPos >= 0 && !isInQuote(expr, opPos) && + !(Character.isLetter(opString.charAt(0)) && + (expr.length() == opPos + opString.length() || Character.isLetter(expr.charAt(opPos + opString.length())) || + (opPos > 0 && Character.isLetter(expr.charAt(opPos-1))))) ) { + potentialOperators.add( opString ); } } String operator = ""; @@ -2237,6 +2242,16 @@ private static String findOperator( String expr ) { return null; } + private static boolean isInQuote(String expr, int pos) { + boolean isInQuote = false; + for (int i = pos-1; i >= 0; i--) { + if (expr.charAt(i) == '"') { + isInQuote = !isInQuote; + } + } + return isInQuote; + } + private static final String[] NULL_OPERATORS = new String[]{ "== null", "!= null" }; private static String findNullOrNotNullOperator( String expr ) { diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java index aae495c6b32..f754853e6b9 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java @@ -56,7 +56,6 @@ import org.drools.workbench.models.datamodel.rule.SingleFieldConstraintEBLeftSide; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.util.ArrayList; @@ -4849,7 +4848,6 @@ public void testRHSModifyBlockMultipleFieldsMultipleLines() throws Exception { } @Test - @Ignore("https://bugzilla.redhat.com/show_bug.cgi?id=1105043") public void testLiteralStrFieldNames() throws Exception { //The issue is fields that contain the "str" operator literal value String drl = "rule \"rule1\"\n" + From 734ec1e3caf7ae04ba4ac77526712395977b9c22 Mon Sep 17 00:00:00 2001 From: Craig West Date: Mon, 9 Jun 2014 21:51:33 -0400 Subject: [PATCH 06/76] Fix ClassLoader leak during incremental compilation (cherry picked from commit 76171a64182a6a7ae3d9f81b31720c53d66d8b07) --- .../drools/compiler/rule/builder/dialect/java/JavaDialect.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialect.java b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialect.java index 6e1b1df478b..9ac114c0c25 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialect.java +++ b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialect.java @@ -394,6 +394,7 @@ public EntryPointBuilder getEntryPointBuilder() { */ public void compileAll() { if ( this.generatedClassList.isEmpty() ) { + this.errorHandlers.clear(); return; } final String[] classes = new String[this.generatedClassList.size()]; @@ -429,6 +430,7 @@ public void compileAll() { // We've compiled everthing, so clear it for the next set of additions this.generatedClassList.clear(); + this.errorHandlers.clear(); } /** From d1f267f5e6f18290184d5bb43e102ca602ce7a5e Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 12 Jun 2014 15:08:16 +0200 Subject: [PATCH 07/76] [BZ-1108070] fix compilation of a kjar in the kie-maven-plugin when it includes a kiebase from a different kjar (cherry picked from commit 7320e0cfd24c541668f57b67ba19ce078ca8f851) --- .../java/org/kie/maven/plugin/BuildMojo.java | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java index d12841c0925..5ccd0c69a5e 100644 --- a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java +++ b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java @@ -12,23 +12,33 @@ import org.drools.compiler.compiler.PMMLCompilerFactory; import org.drools.compiler.compiler.ProcessBuilderFactory; import org.drools.compiler.kie.builder.impl.InternalKieModule; +import org.drools.compiler.kie.builder.impl.KieContainerImpl; import org.drools.compiler.kie.builder.impl.KieMetaInfoBuilder; +import org.drools.compiler.kie.builder.impl.KieProject; +import org.drools.compiler.kie.builder.impl.ResultsImpl; +import org.drools.compiler.kie.builder.impl.ZipKieModule; +import org.drools.compiler.kproject.ReleaseIdImpl; +import org.drools.compiler.kproject.models.KieModuleModelImpl; import org.kie.api.KieServices; -import org.kie.api.builder.KieModule; import org.kie.api.builder.KieRepository; import org.kie.api.builder.Message; -import org.drools.compiler.kie.builder.impl.KieContainerImpl; -import org.drools.compiler.kie.builder.impl.KieProject; -import org.drools.compiler.kie.builder.impl.ResultsImpl; +import org.kie.api.builder.ReleaseId; +import org.kie.api.builder.model.KieModuleModel; import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import static org.drools.compiler.kie.builder.impl.KieBuilderImpl.setDefaultsforEmptyKieModule; /** * This goal builds the drools file belonging to the kproject. @@ -63,6 +73,8 @@ public class BuildMojo extends AbstractMojo { public void execute() throws MojoExecutionException, MojoFailureException { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + List kmoduleDeps = new ArrayList(); + try { Set urls = new HashSet(); for (String element : project.getCompileClasspathElements()) { @@ -74,6 +86,11 @@ public void execute() throws MojoExecutionException, MojoFailureException { File file = artifact.getFile(); if (file != null) { urls.add(file.toURI().toURL()); + KieModuleModel depModel = getDependencyKieModel(file); + if (depModel != null) { + ReleaseId releaseId = new ReleaseIdImpl(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()); + kmoduleDeps.add(new ZipKieModule(releaseId, depModel, file)); + } } } urls.add(outputDirectory.toURI().toURL()); @@ -98,7 +115,11 @@ public void execute() throws MojoExecutionException, MojoFailureException { try { KieRepository kr = ks.getRepository(); - KieModule kModule = kr.addKieModule(ks.getResources().newFileSystemResource(sourceFolder)); + InternalKieModule kModule = (InternalKieModule)kr.addKieModule(ks.getResources().newFileSystemResource(sourceFolder)); + for (InternalKieModule kmoduleDep : kmoduleDeps) { + kModule.addKieDependency(kmoduleDep); + } + KieContainerImpl kContainer = (KieContainerImpl) ks.newKieContainer(kModule.getReleaseId()); KieProject kieProject = kContainer.getKieProject(); @@ -118,4 +139,26 @@ public void execute() throws MojoExecutionException, MojoFailureException { } getLog().info("KieModule successfully built!"); } + + private KieModuleModel getDependencyKieModel(File jar) { + ZipFile zipFile = null; + try { + zipFile = new ZipFile( jar ); + ZipEntry zipEntry = zipFile.getEntry( KieModuleModelImpl.KMODULE_JAR_PATH ); + if (zipEntry != null) { + KieModuleModel kieModuleModel = KieModuleModelImpl.fromXML(zipFile.getInputStream(zipEntry)); + setDefaultsforEmptyKieModule(kieModuleModel); + return kieModuleModel; + } + } catch ( Exception e ) { + } finally { + if (zipFile != null) { + try { + zipFile.close(); + } catch (IOException e) { + } + } + } + return null; + } } From 848ae804bb7265c2dd7169880e051993af039e9d Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 12 Jun 2014 15:33:16 +0200 Subject: [PATCH 08/76] [BZ-1107982] log errors when trying to resolve maven artifacts (cherry picked from commit 1be49863ce93c9c54c692a57ec17eaa019e7f60d) --- kie-ci/src/main/java/org/kie/scanner/MavenRepository.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java b/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java index 1aa886bbc2b..a3a820a5502 100644 --- a/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java +++ b/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java @@ -7,9 +7,11 @@ import org.apache.maven.settings.RepositoryPolicy; import org.apache.maven.settings.Server; import org.apache.maven.settings.Settings; -import org.kie.api.builder.ReleaseId; import org.drools.compiler.kie.builder.impl.InternalKieModule; +import org.kie.api.builder.ReleaseId; import org.kie.scanner.embedder.MavenSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonatype.aether.artifact.Artifact; import org.sonatype.aether.collection.CollectRequest; import org.sonatype.aether.collection.CollectResult; @@ -43,6 +45,8 @@ public class MavenRepository { + private static final Logger log = LoggerFactory.getLogger(MavenRepository.class); + private static MavenRepository defaultMavenRepository; private final Aether aether; @@ -191,6 +195,7 @@ public Artifact resolveArtifact(String artifactName) { ArtifactResult artifactResult = aether.getSystem().resolveArtifact(aether.getSession(), artifactRequest); return artifactResult.getArtifact(); } catch (ArtifactResolutionException e) { + log.warn("Unable to resolve artifact: " + artifactName, e); return null; } } @@ -206,6 +211,7 @@ public Version resolveVersion(String artifactName) { VersionRangeResult versionRangeResult = aether.getSystem().resolveVersionRange(aether.getSession(), versionRequest); return versionRangeResult.getHighestVersion(); } catch (VersionRangeResolutionException e) { + log.warn("Unable to resolve version range for artifact: " + artifactName, e); return null; } } From c239fa3c05288d9965c6ef953c506e46685055c4 Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Thu, 12 Jun 2014 16:00:35 +0100 Subject: [PATCH 09/76] GUVNOR-2104: Change Guided Rule, Template and Decision Table Editors to generate modify() {...} block (cherry picked from commit bc6203ba67ceb67f5d6f1b39a2d9fe32f0ea6f70) --- .../rule/RuleModelDRLPersistenceImpl.java | 325 +++++++++--- .../GeneratorContextRuleModelVisitor.java | 76 +-- .../LHSGeneratorContext.java} | 25 +- .../context/LHSGeneratorContextFactory.java | 46 ++ .../rule/context/RHSGeneratorContext.java | 52 ++ .../RHSGeneratorContextFactory.java} | 19 +- .../rule/RuleModelDRLPersistenceTest.java | 231 +++++++-- .../backend/GuidedDTDRLPersistence.java | 35 +- .../util/GuidedDTBRDRLPersistence.java | 45 +- .../dtable/backend/BRLRuleModelTest.java | 420 +++++++++++++++- .../backend/GuidedDTDRLPersistenceTest.java | 244 ++++++++- .../RuleTemplateModelDRLPersistenceImpl.java | 108 +++- .../RuleTemplateModelDRLPersistenceTest.java | 465 ++++++++++++++++++ 13 files changed, 1845 insertions(+), 246 deletions(-) rename drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/{ => context}/GeneratorContextRuleModelVisitor.java (80%) rename drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/{GeneratorContext.java => context/LHSGeneratorContext.java} (75%) create mode 100644 drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/LHSGeneratorContextFactory.java create mode 100644 drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/RHSGeneratorContext.java rename drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/{GeneratorContextFactory.java => context/RHSGeneratorContextFactory.java} (55%) diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java index 9f7fb309736..fdaca19222e 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java @@ -16,6 +16,17 @@ package org.drools.workbench.models.commons.backend.rule; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.drools.compiler.compiler.DrlParser; import org.drools.compiler.compiler.DroolsParserException; import org.drools.compiler.lang.descr.AccumulateDescr; @@ -44,6 +55,10 @@ import org.drools.workbench.models.commons.backend.imports.ImportsWriter; import org.drools.workbench.models.commons.backend.packages.PackageNameParser; import org.drools.workbench.models.commons.backend.packages.PackageNameWriter; +import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContext; +import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContextFactory; +import org.drools.workbench.models.commons.backend.rule.context.RHSGeneratorContext; +import org.drools.workbench.models.commons.backend.rule.context.RHSGeneratorContextFactory; import org.drools.workbench.models.datamodel.imports.Import; import org.drools.workbench.models.datamodel.imports.Imports; import org.drools.workbench.models.datamodel.oracle.DataType; @@ -103,17 +118,7 @@ import org.drools.workbench.models.datamodel.workitems.PortableStringParameterDefinition; import org.drools.workbench.models.datamodel.workitems.PortableWorkDefinition; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.drools.core.util.StringUtils.splitArgumentsList; +import static org.drools.core.util.StringUtils.*; import static org.drools.workbench.models.commons.backend.rule.RuleModelPersistenceHelper.*; /** @@ -179,11 +184,12 @@ protected String marshalRule( final RuleModel model ) { this.marshalLHS( buf, model, isDSLEnhanced, - new GeneratorContextFactory() ); + new LHSGeneratorContextFactory() ); buf.append( "\tthen\n" ); this.marshalRHS( buf, model, - isDSLEnhanced ); + isDSLEnhanced, + new RHSGeneratorContextFactory() ); this.marshalFooter( buf ); return buf.toString(); } @@ -300,7 +306,7 @@ protected void marshalMetadata( final StringBuilder buf, protected void marshalLHS( final StringBuilder buf, final RuleModel model, final boolean isDSLEnhanced, - final GeneratorContextFactory generatorContextFactory ) { + final LHSGeneratorContextFactory generatorContextFactory ) { String indentation = "\t\t"; String nestedIndentation = indentation; boolean isNegated = model.isNegated(); @@ -334,7 +340,7 @@ protected LHSPatternVisitor getLHSPatternVisitor( final boolean isDSLEnhanced, final StringBuilder buf, final String nestedIndentation, final boolean isNegated, - final GeneratorContextFactory generatorContextFactory ) { + final LHSGeneratorContextFactory generatorContextFactory ) { return new LHSPatternVisitor( isDSLEnhanced, bindingsPatterns, bindingsFields, @@ -347,7 +353,8 @@ protected LHSPatternVisitor getLHSPatternVisitor( final boolean isDSLEnhanced, protected void marshalRHS( final StringBuilder buf, final RuleModel model, - final boolean isDSLEnhanced ) { + final boolean isDSLEnhanced, + final RHSGeneratorContextFactory generatorContextFactory ) { String indentation = "\t\t"; if ( model.rhs != null ) { @@ -367,20 +374,117 @@ protected void marshalRHS( final StringBuilder buf, //Marshall the model itself RHSActionVisitor actionVisitor = getRHSActionVisitor( isDSLEnhanced, buf, - indentation ); + indentation, + generatorContextFactory ); + + //Reconcile ActionSetField and ActionUpdateField calls + final List actions = new ArrayList(); + for ( IAction action : model.rhs ) { + if ( action instanceof ActionSetField ) { + final ActionSetField asf = (ActionSetField) action; + final ActionSetFieldWrapper afw = findExistingAction( asf, + actions ); + if ( afw == null ) { + actions.add( new ActionSetFieldWrapper( asf, + ( asf instanceof ActionUpdateField ) ) ); + } else { + final List existingActionFieldValue = new ArrayList( Arrays.asList( afw.getAction().getFieldValues() ) ); + for ( ActionFieldValue afv : asf.getFieldValues() ) { + existingActionFieldValue.add( afv ); + } + final ActionFieldValue[] temp = new ActionFieldValue[ existingActionFieldValue.size() ]; + afw.getAction().setFieldValues( existingActionFieldValue.toArray( temp ) ); + } + + } else { + actions.add( action ); + } + } + model.rhs = new IAction[ actions.size() ]; + for ( int i = 0; i < actions.size(); i++ ) { + final IAction action = actions.get( i ); + if ( action instanceof ActionSetFieldWrapper ) { + model.rhs[ i ] = ( (ActionSetFieldWrapper) action ).getAction(); + } else { + model.rhs[ i ] = action; + } + } + + //Now generate DRL for ( IAction action : model.rhs ) { actionVisitor.visit( action ); } } } + private ActionSetFieldWrapper findExistingAction( final ActionSetField asf, + final List actions ) { + for ( IAction action : actions ) { + if ( action instanceof ActionSetFieldWrapper ) { + final ActionSetFieldWrapper afw = (ActionSetFieldWrapper) action; + if ( asf.getVariable().equals( afw.getAction().getVariable() ) && ( asf instanceof ActionUpdateField ) == afw.isUpdate() ) { + return afw; + } + } + } + return null; + } + + private static class ActionSetFieldWrapper implements IAction { + + private final ActionSetField action; + private final boolean isUpdate; + + private ActionSetFieldWrapper( final ActionSetField action, + final boolean isUpdate ) { + this.action = clone( action ); + this.isUpdate = isUpdate; + } + + private ActionSetField getAction() { + return action; + } + + private boolean isUpdate() { + return isUpdate; + } + + private ActionSetField clone( final ActionSetField action ) { + if ( action instanceof ActionUpdateField ) { + final ActionUpdateField auf = (ActionUpdateField) action; + final ActionUpdateField clone = new ActionUpdateField( auf.getVariable() ); + clone.setFieldValues( auf.getFieldValues() ); + return clone; + + } else if ( action instanceof ActionCallMethod ) { + final ActionCallMethod acm = (ActionCallMethod) action; + final ActionCallMethod clone = new ActionCallMethod( acm.getVariable() ); + clone.setState( acm.getState() ); + clone.setMethodName( acm.getMethodName() ); + clone.setFieldValues( acm.getFieldValues() ); + return clone; + + } else if ( action instanceof ActionSetField ) { + final ActionSetField clone = new ActionSetField( action.getVariable() ); + clone.setFieldValues( action.getFieldValues() ); + return clone; + + } else { + return action; + } + } + + } + protected RHSActionVisitor getRHSActionVisitor( final boolean isDSLEnhanced, final StringBuilder buf, - final String indentation ) { + final String indentation, + final RHSGeneratorContextFactory generatorContextFactory ) { return new RHSActionVisitor( isDSLEnhanced, bindingsPatterns, bindingsFields, constraintValueBuilder, + generatorContextFactory, buf, indentation ); } @@ -422,13 +526,13 @@ public static class LHSPatternVisitor extends ReflectiveVisitor { private Map bindingsPatterns; private Map bindingsFields; protected DRLConstraintValueBuilder constraintValueBuilder; - protected GeneratorContextFactory generatorContextFactory; + protected LHSGeneratorContextFactory generatorContextFactory; public LHSPatternVisitor( final boolean isDSLEnhanced, final Map bindingsPatterns, final Map bindingsFields, final DRLConstraintValueBuilder constraintValueBuilder, - final GeneratorContextFactory generatorContextFactory, + final LHSGeneratorContextFactory generatorContextFactory, final StringBuilder b, final String indentation, final boolean isPatternNegated ) { @@ -439,7 +543,7 @@ public LHSPatternVisitor( final boolean isDSLEnhanced, this.generatorContextFactory = generatorContextFactory; this.indentation = indentation; this.isPatternNegated = isPatternNegated; - buf = b; + this.buf = b; } public void visitFactPattern( final FactPattern pattern ) { @@ -711,7 +815,7 @@ private void generateFactPattern( final FactPattern pattern ) { } private void generateConstraints( final FactPattern pattern ) { - GeneratorContext gctx = generatorContextFactory.newGeneratorContext(); + LHSGeneratorContext gctx = generatorContextFactory.newGeneratorContext(); preGenerateConstraints( gctx ); for ( int constraintIndex = 0; constraintIndex < pattern.getFieldConstraints().length; constraintIndex++ ) { FieldConstraint constr = pattern.getConstraintList().getConstraints()[ constraintIndex ]; @@ -721,28 +825,28 @@ private void generateConstraints( final FactPattern pattern ) { } } - public void preGenerateConstraints( GeneratorContext gctx ) { + public void preGenerateConstraints( LHSGeneratorContext gctx ) { // empty, overridden by rule templates } - public void preGenerateNestedConnector( GeneratorContext gctx ) { + public void preGenerateNestedConnector( LHSGeneratorContext gctx ) { // empty, overridden by rule templates } - public void postGenerateNestedConnector( GeneratorContext gctx ) { + public void postGenerateNestedConnector( LHSGeneratorContext gctx ) { // empty, overridden by rule templates } - public void preGenerateNestedConstraint( GeneratorContext gctx ) { + public void preGenerateNestedConstraint( LHSGeneratorContext gctx ) { // empty, overridden by rule templates } - public void postGenerateNestedConstraint( GeneratorContext gctx ) { + public void postGenerateNestedConstraint( LHSGeneratorContext gctx ) { // empty, overridden by rule templates } public void generateSeparator( FieldConstraint constr, - GeneratorContext gctx ) { + LHSGeneratorContext gctx ) { if ( !gctx.isHasOutput() ) { return; } @@ -762,14 +866,14 @@ public void generateSeparator( FieldConstraint constr, * readable DRL in the most common cases. */ protected void generateConstraint( final FieldConstraint con, - final GeneratorContext gctx ) { + final LHSGeneratorContext gctx ) { generateSeparator( con, gctx ); if ( con instanceof CompositeFieldConstraint ) { CompositeFieldConstraint cfc = (CompositeFieldConstraint) con; FieldConstraint[] nestedConstraints = cfc.getConstraints(); if ( nestedConstraints != null ) { - GeneratorContext nestedGctx = generatorContextFactory.newChildGeneratorContext( gctx ); + LHSGeneratorContext nestedGctx = generatorContextFactory.newChildGeneratorContext( gctx ); preGenerateConstraints( nestedGctx ); preGenerateNestedConstraint( gctx ); if ( gctx.getDepth() > 0 ) { @@ -794,7 +898,7 @@ protected void generateConstraint( final FieldConstraint con, } private void generateSingleFieldConstraint( final SingleFieldConstraint constr, - final GeneratorContext gctx ) { + final LHSGeneratorContext gctx ) { if ( constr.getConstraintValueType() == BaseSingleFieldConstraint.TYPE_PREDICATE ) { buf.append( "eval( " ); buf.append( constr.getValue() ); @@ -868,8 +972,8 @@ private void generateNormalFieldRestriction( SingleFieldConstraint constr, private void generateConnectiveFieldRestriction( final SingleFieldConstraint constr, final Map parameters, - final GeneratorContext gctx ) { - GeneratorContext cctx = generatorContextFactory.newChildGeneratorContext( gctx ); + final LHSGeneratorContext gctx ) { + LHSGeneratorContext cctx = generatorContextFactory.newChildGeneratorContext( gctx ); preGenerateConstraints( cctx ); cctx.setFieldConstraint( constr ); if ( constr instanceof SingleFieldConstraintEBLeftSide ) { @@ -950,7 +1054,7 @@ protected void addConnectiveFieldRestriction( final StringBuilder buf, final Map parameters, final String value, final ExpressionFormLine expression, - GeneratorContext gctx, + LHSGeneratorContext gctx, final boolean spaceBeforeOperator ) { addFieldRestriction( buf, type, fieldType, operator, parameters, value, expression, spaceBeforeOperator ); } @@ -1160,10 +1264,10 @@ public static class RHSActionVisitor extends ReflectiveVisitor { protected StringBuilder buf; private boolean isDSLEnhanced; private String indentation; - // private int idx = 0; private Map bindingsPatterns; private Map bindingsFields; protected DRLConstraintValueBuilder constraintValueBuilder; + protected RHSGeneratorContextFactory generatorContextFactory; //Keep a record of Work Items that are instantiated for Actions that depend on them private Set instantiatedWorkItems; @@ -1172,15 +1276,17 @@ public RHSActionVisitor( final boolean isDSLEnhanced, final Map bindingsPatterns, final Map bindingsFields, final DRLConstraintValueBuilder constraintValueBuilder, + final RHSGeneratorContextFactory generatorContextFactory, final StringBuilder b, final String indentation ) { this.isDSLEnhanced = isDSLEnhanced; this.bindingsPatterns = bindingsPatterns; this.bindingsFields = bindingsFields; this.constraintValueBuilder = constraintValueBuilder; + this.generatorContextFactory = generatorContextFactory; this.indentation = indentation; this.instantiatedWorkItems = new HashSet(); - buf = b; + this.buf = b; } public void visitActionInsertFact( final ActionInsertFact action ) { @@ -1246,14 +1352,17 @@ private void generateInsertCall( final ActionInsertFact action, } public void visitActionUpdateField( final ActionUpdateField action ) { - this.visitActionSetField( action ); buf.append( indentation ); if ( isDSLEnhanced ) { buf.append( ">" ); } - buf.append( "update( " ); - buf.append( action.getVariable() ); - buf.append( " );\n" ); + buf.append( "modify( " ).append( action.getVariable() ).append( " ) {\n" ); + this.generateModifyMethodCalls( action.getFieldValues() ); + buf.append( "\n" ).append( indentation ); + if ( isDSLEnhanced ) { + buf.append( ">" ); + } + buf.append( "}\n" ); } public void visitActionGlobalCollectionAdd( final ActionGlobalCollectionAdd add ) { @@ -1398,6 +1507,66 @@ private void generateSetMethodCallParameterValue( final StringBuilder buf, } } + private void generateModifyMethodCalls( final ActionFieldValue[] fieldValues ) { + RHSGeneratorContext gctx = generatorContextFactory.newGeneratorContext(); + for ( int index = 0; index < fieldValues.length; index++ ) { + final ActionFieldValue fieldValue = fieldValues[ index ]; + preGenerateSetMethodCallParameterValue( fieldValue, + gctx ); + generateModifyMethodSeparator( gctx, + fieldValue ); + generateModifyMethodCall( gctx, + fieldValue ); + gctx = generatorContextFactory.newChildGeneratorContext( gctx ); + } + } + + protected void preGenerateSetMethodCallParameterValue( final ActionFieldValue fieldValue, + final RHSGeneratorContext gctx ) { + gctx.setHasOutput( true ); + } + + protected void generateModifyMethodCall( final RHSGeneratorContext gctx, + final ActionFieldValue fieldValue ) { + buf.append( indentation ).append( indentation ); + if ( isDSLEnhanced ) { + buf.append( ">" ); + } + + if ( fieldValue instanceof ActionFieldFunction ) { + buf.append( fieldValue.getField() ); + } else { + buf.append( "set" ); + buf.append( Character.toUpperCase( fieldValue.getField().charAt( 0 ) ) ); + buf.append( fieldValue.getField().substring( 1 ) ); + } + buf.append( "( " ); + generateSetMethodCallParameterValue( buf, + fieldValue ); + buf.append( " )" ); + } + + protected void generateModifyMethodSeparator( final RHSGeneratorContext gctx, + final ActionFieldValue fieldValue ) { + if ( gctx.getParent() == null ) { + return; + } + if ( doesParentHaveOutput( gctx ) && gctx.isHasOutput() ) { + buf.append( ", \n" ); + } + } + + private boolean doesParentHaveOutput( final RHSGeneratorContext gctx ) { + RHSGeneratorContext parent = gctx.getParent(); + while ( parent != null ) { + if ( parent.isHasOutput() ) { + return true; + } + parent = parent.getParent(); + } + return false; + } + protected void buildFormulaFieldValue( final ActionFieldValue fieldValue, final StringBuilder buf ) { buf.append( fieldValue.getValue() ); @@ -2213,11 +2382,11 @@ private static String findOperator( String expr ) { return "not " + opString; } } - int opPos = expr.indexOf(opString); - if ( opPos >= 0 && !isInQuote(expr, opPos) && - !(Character.isLetter(opString.charAt(0)) && - (expr.length() == opPos + opString.length() || Character.isLetter(expr.charAt(opPos + opString.length())) || - (opPos > 0 && Character.isLetter(expr.charAt(opPos-1))))) ) { + int opPos = expr.indexOf( opString ); + if ( opPos >= 0 && !isInQuote( expr, opPos ) && + !( Character.isLetter( opString.charAt( 0 ) ) && + ( expr.length() == opPos + opString.length() || Character.isLetter( expr.charAt( opPos + opString.length() ) ) || + ( opPos > 0 && Character.isLetter( expr.charAt( opPos - 1 ) ) ) ) ) ) { potentialOperators.add( opString ); } } @@ -2242,10 +2411,11 @@ private static String findOperator( String expr ) { return null; } - private static boolean isInQuote(String expr, int pos) { + private static boolean isInQuote( String expr, + int pos ) { boolean isInQuote = false; - for (int i = pos-1; i >= 0; i--) { - if (expr.charAt(i) == '"') { + for ( int i = pos - 1; i >= 0; i-- ) { + if ( expr.charAt( i ) == '"' ) { isInQuote = !isInQuote; } } @@ -2290,17 +2460,17 @@ private void parseRhs( RuleModel m, } line = line.trim(); if ( modifiedVariable != null ) { - int modifyBlockEnd = line.lastIndexOf('}'); - if (modifiers == null) { + int modifyBlockEnd = line.lastIndexOf( '}' ); + if ( modifiers == null ) { modifiers = modifyBlockEnd > 0 ? - line.substring( line.indexOf( '{' ) + 1, modifyBlockEnd ).trim() : - line.substring( line.indexOf( '{' ) + 1 ).trim(); - } else if (modifyBlockEnd != 0) { + line.substring( line.indexOf( '{' ) + 1, modifyBlockEnd ).trim() : + line.substring( line.indexOf( '{' ) + 1 ).trim(); + } else if ( modifyBlockEnd != 0 ) { modifiers += modifyBlockEnd > 0 ? - line.substring( 0, modifyBlockEnd ).trim() : - line; + line.substring( 0, modifyBlockEnd ).trim() : + line; } - if (modifyBlockEnd >= 0) { + if ( modifyBlockEnd >= 0 ) { ActionUpdateField action = new ActionUpdateField(); action.setVariable( modifiedVariable ); m.addRhsItem( action ); @@ -2331,7 +2501,7 @@ private void parseRhs( RuleModel m, } } } else if ( line.startsWith( "insert" ) ) { - String fact = unwrapParenthesis(line); + String fact = unwrapParenthesis( line ); String type = getStatementType( fact, factsType ); if ( type != null ) { ActionInsertFact action = new ActionInsertFact( type ); @@ -2360,8 +2530,8 @@ private void parseRhs( RuleModel m, m.getImports(), isJavaDialect ); } else if ( line.startsWith( "modify" ) ) { - int modifyBlockEnd = line.lastIndexOf('}'); - if (modifyBlockEnd > 0) { + int modifyBlockEnd = line.lastIndexOf( '}' ); + if ( modifyBlockEnd > 0 ) { String variable = line.substring( line.indexOf( '(' ) + 1, line.indexOf( ')' ) ).trim(); ActionUpdateField action = new ActionUpdateField(); action.setVariable( variable ); @@ -2375,12 +2545,12 @@ private void parseRhs( RuleModel m, isJavaDialect ); } else { modifiedVariable = line.substring( line.indexOf( '(' ) + 1, line.indexOf( ')' ) ).trim(); - int modifyBlockStart = line.indexOf('{'); - if (modifyBlockStart > 0) { - modifiers = line.substring(modifyBlockStart+1).trim(); + int modifyBlockStart = line.indexOf( '{' ); + if ( modifyBlockStart > 0 ) { + modifiers = line.substring( modifyBlockStart + 1 ).trim(); } } - } else if ( line.startsWith( "retract" ) || line.startsWith( "delete" ) ) { + } else if ( line.startsWith( "retract" ) || line.startsWith( "delete" ) ) { String variable = unwrapParenthesis( line ); m.addRhsItem( new ActionRetractFact( variable ) ); } else if ( line.startsWith( "org.drools.core.process.instance.impl.WorkItemImpl wiWorkItem" ) ) { @@ -2388,7 +2558,7 @@ private void parseRhs( RuleModel m, pwd = new PortableWorkDefinition(); pwd.setName( "WorkItem" ); awi.setWorkDefinition( pwd ); - m.addRhsItem(awi); + m.addRhsItem( awi ); } else if ( line.startsWith( "wiWorkItem.getParameters().put" ) ) { String statement = line.substring( "wiWorkItem.getParameters().put".length() ); statement = unwrapParenthesis( statement ); @@ -2522,7 +2692,7 @@ private DSLSentence toDSLSentence( List dslPatterns, return dslSentence; } } - dslSentence.setDefinition(dslLine); + dslSentence.setDefinition( dslLine ); return dslSentence; } @@ -2592,7 +2762,7 @@ private void addSettersToAction( List setters, int dotPos = statement.indexOf( '.' ); int argStart = statement.indexOf( '(' ); String methodName = statement.substring( dotPos + 1, argStart ).trim(); - addSetterToAction(action, boundParams, dmo, imports, isJavaDialect, statement, methodName); + addSetterToAction( action, boundParams, dmo, imports, isJavaDialect, statement, methodName ); } } } @@ -2604,14 +2774,13 @@ private void addModifiersToAction( String variable, PackageDataModelOracle dmo, Imports imports, boolean isJavaDialect ) { - for (String statement : splitArgumentsList(modifiers)) { - int argStart = statement.indexOf( '(' ); - String methodName = statement.substring( 0, argStart ).trim(); - addSetterToAction(action, boundParams, dmo, imports, isJavaDialect, statement, methodName); - } + for ( String statement : splitArgumentsList( modifiers ) ) { + int argStart = statement.indexOf( '(' ); + String methodName = statement.substring( 0, argStart ).trim(); + addSetterToAction( action, boundParams, dmo, imports, isJavaDialect, statement, methodName ); + } } - private void addSetterToAction( ActionFieldList action, Map boundParams, PackageDataModelOracle dmo, @@ -2631,12 +2800,12 @@ private void addSetterToAction( ActionFieldList action, boundParams, isJavaDialect ); } - action.addFieldValue(buildFieldValue(isJavaDialect, - field, - value, - dataType, - boundParams, - dmo)); + action.addFieldValue( buildFieldValue( isJavaDialect, + field, + value, + dataType, + boundParams, + dmo ) ); } private ActionFieldValue buildFieldValue( boolean isJavaDialect, diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContextRuleModelVisitor.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/GeneratorContextRuleModelVisitor.java similarity index 80% rename from drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContextRuleModelVisitor.java rename to drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/GeneratorContextRuleModelVisitor.java index 06959c3588b..e29da57bc8a 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContextRuleModelVisitor.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/GeneratorContextRuleModelVisitor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.drools.workbench.models.commons.backend.rule; +package org.drools.workbench.models.commons.backend.rule.context; import java.util.Set; @@ -53,27 +53,23 @@ public class GeneratorContextRuleModelVisitor { private Set vars; private boolean hasNonTemplateOutput; - public GeneratorContextRuleModelVisitor() { - //Empty constructor for Errai marshalling - } - - public GeneratorContextRuleModelVisitor( Set vars ) { + public GeneratorContextRuleModelVisitor( final Set vars ) { this.vars = vars; } - public GeneratorContextRuleModelVisitor( IPattern pattern, - Set vars ) { + public GeneratorContextRuleModelVisitor( final IPattern pattern, + final Set vars ) { this.vars = vars; this.model.addLhsItem( pattern ); } - public GeneratorContextRuleModelVisitor( IAction action, - Set vars ) { + public GeneratorContextRuleModelVisitor( final IAction action, + final Set vars ) { this.vars = vars; this.model.addRhsItem( action ); } - private void parseStringPattern( String text ) { + private void parseStringPattern( final String text ) { if ( text == null || text.length() == 0 ) { return; } @@ -83,8 +79,8 @@ private void parseStringPattern( String text ) { int end = text.indexOf( '}', pos + 2 ); if ( end != -1 ) { - String varName = text.substring( pos + 2, - end ); + final String varName = text.substring( pos + 2, + end ); pos = end + 1; InterpolationVariable var = new InterpolationVariable( varName, DataType.TYPE_OBJECT ); @@ -95,7 +91,7 @@ private void parseStringPattern( String text ) { } } - public void visit( Object o ) { + public void visit( final Object o ) { if ( o == null ) { return; } @@ -127,11 +123,13 @@ public void visit( Object o ) { visitActionFieldList( (ActionUpdateField) o ); } else if ( o instanceof ActionSetField ) { visitActionFieldList( (ActionSetField) o ); + } else if ( o instanceof ActionFieldValue ) { + visitActionFieldValue( (ActionFieldValue) o ); } } //ActionInsertFact, ActionSetField, ActionpdateField - private void visitActionFieldList( ActionInsertFact afl ) { + private void visitActionFieldList( final ActionInsertFact afl ) { String factType = afl.getFactType(); for ( ActionFieldValue afv : afl.getFieldValues() ) { InterpolationVariable var = new InterpolationVariable( afv.getValue(), @@ -146,7 +144,7 @@ private void visitActionFieldList( ActionInsertFact afl ) { } } - private void visitActionFieldList( ActionSetField afl ) { + private void visitActionFieldList( final ActionSetField afl ) { String factType = model.getLHSBindingType( afl.getVariable() ); for ( ActionFieldValue afv : afl.getFieldValues() ) { InterpolationVariable var = new InterpolationVariable( afv.getValue(), @@ -161,7 +159,7 @@ private void visitActionFieldList( ActionSetField afl ) { } } - private void visitActionFieldList( ActionUpdateField afl ) { + private void visitActionFieldList( final ActionUpdateField afl ) { String factType = model.getLHSBindingType( afl.getVariable() ); for ( ActionFieldValue afv : afl.getFieldValues() ) { InterpolationVariable var = new InterpolationVariable( afv.getValue(), @@ -176,7 +174,13 @@ private void visitActionFieldList( ActionUpdateField afl ) { } } - private void visitCompositeFactPattern( CompositeFactPattern pattern ) { + private void visitActionFieldValue( final ActionFieldValue afv ) { + if ( afv.getNature() != FieldNatureType.TYPE_TEMPLATE ) { + hasNonTemplateOutput = true; + } + } + + private void visitCompositeFactPattern( final CompositeFactPattern pattern ) { if ( pattern.getPatterns() != null ) { for ( IFactPattern fp : pattern.getPatterns() ) { visit( fp ); @@ -184,7 +188,7 @@ private void visitCompositeFactPattern( CompositeFactPattern pattern ) { } } - private void visitCompositeFieldConstraint( CompositeFieldConstraint cfc ) { + private void visitCompositeFieldConstraint( final CompositeFieldConstraint cfc ) { if ( cfc.getConstraints() != null ) { for ( FieldConstraint fc : cfc.getConstraints() ) { visit( fc ); @@ -198,18 +202,18 @@ private void visitDSLSentence( final DSLSentence sentence ) { parseStringPattern( text ); } - private void visitFactPattern( FactPattern pattern ) { + private void visitFactPattern( final FactPattern pattern ) { this.factPattern = pattern; for ( FieldConstraint fc : pattern.getFieldConstraints() ) { visit( fc ); } } - private void visitFreeFormLine( FreeFormLine ffl ) { + private void visitFreeFormLine( final FreeFormLine ffl ) { parseStringPattern( ffl.getText() ); } - private void visitFromAccumulateCompositeFactPattern( FromAccumulateCompositeFactPattern pattern ) { + private void visitFromAccumulateCompositeFactPattern( final FromAccumulateCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); visit( pattern.getSourcePattern() ); @@ -218,17 +222,17 @@ private void visitFromAccumulateCompositeFactPattern( FromAccumulateCompositeFac parseStringPattern( pattern.getReverseCode() ); } - private void visitFromCollectCompositeFactPattern( FromCollectCompositeFactPattern pattern ) { + private void visitFromCollectCompositeFactPattern( final FromCollectCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); visit( pattern.getRightPattern() ); } - private void visitFromCompositeFactPattern( FromCompositeFactPattern pattern ) { + private void visitFromCompositeFactPattern( final FromCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); parseStringPattern( pattern.getExpression().getText() ); } - private void visitRuleModel( RuleModel model ) { + private void visitRuleModel( final RuleModel model ) { this.model = model; if ( model.lhs != null ) { for ( IPattern pat : model.lhs ) { @@ -242,11 +246,11 @@ private void visitRuleModel( RuleModel model ) { } } - private void visitSingleFieldConstraint( SingleFieldConstraint sfc ) { - InterpolationVariable var = new InterpolationVariable( sfc.getValue(), - sfc.getFieldType(), - ( factPattern == null ? "" : factPattern.getFactType() ), - sfc.getFieldName() ); + private void visitSingleFieldConstraint( final SingleFieldConstraint sfc ) { + final InterpolationVariable var = new InterpolationVariable( sfc.getValue(), + sfc.getFieldType(), + ( factPattern == null ? "" : factPattern.getFactType() ), + sfc.getFieldName() ); if ( BaseSingleFieldConstraint.TYPE_TEMPLATE == sfc.getConstraintValueType() && !vars.contains( var ) ) { vars.add( var ); } else { @@ -271,16 +275,16 @@ private void visitSingleFieldConstraint( SingleFieldConstraint sfc ) { } } - private void visitSingleFieldConstraint( SingleFieldConstraintEBLeftSide sfexp ) { - String genericType = sfexp.getExpressionLeftSide().getGenericType(); + private void visitSingleFieldConstraint( final SingleFieldConstraintEBLeftSide sfexp ) { + final String genericType = sfexp.getExpressionLeftSide().getGenericType(); String factType = sfexp.getExpressionLeftSide().getPreviousClassType(); if ( factType == null ) { factType = sfexp.getExpressionLeftSide().getClassType(); } - InterpolationVariable var = new InterpolationVariable( sfexp.getValue(), - genericType, - factType, - sfexp.getFieldName() ); + final InterpolationVariable var = new InterpolationVariable( sfexp.getValue(), + genericType, + factType, + sfexp.getFieldName() ); if ( BaseSingleFieldConstraint.TYPE_TEMPLATE == sfexp.getConstraintValueType() && !vars.contains( var ) ) { vars.add( var ); } else { diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContext.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/LHSGeneratorContext.java similarity index 75% rename from drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContext.java rename to drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/LHSGeneratorContext.java index 9b5429cd39d..a3c29dee64e 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContext.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/LHSGeneratorContext.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.drools.workbench.models.commons.backend.rule; +package org.drools.workbench.models.commons.backend.rule.context; import java.util.HashSet; import java.util.Set; @@ -22,25 +22,24 @@ import org.drools.workbench.models.datamodel.rule.InterpolationVariable; /** - * DRL generation context object + * LHS DRL generation context object */ -public class GeneratorContext { +public class LHSGeneratorContext { private Set varsInScope = new HashSet(); private FieldConstraint fieldConstraint; - private GeneratorContext parent; + private LHSGeneratorContext parent; private int depth; private int offset; private boolean hasOutput; private boolean hasNonTemplateOutput; - private int childCount; - GeneratorContext() { + LHSGeneratorContext() { } - GeneratorContext( GeneratorContext parent, - int depth, - int offset ) { + LHSGeneratorContext( final LHSGeneratorContext parent, + final int depth, + final int offset ) { this.parent = parent; this.depth = depth; this.offset = offset; @@ -50,11 +49,11 @@ public FieldConstraint getFieldConstraint() { return fieldConstraint; } - public void setFieldConstraint( FieldConstraint fieldConstraint ) { + public void setFieldConstraint( final FieldConstraint fieldConstraint ) { this.fieldConstraint = fieldConstraint; this.varsInScope.clear(); - Set vars = new HashSet(); - GeneratorContextRuleModelVisitor visitor = new GeneratorContextRuleModelVisitor( vars ); + final Set vars = new HashSet(); + final GeneratorContextRuleModelVisitor visitor = new GeneratorContextRuleModelVisitor( vars ); visitor.visit( fieldConstraint ); for ( InterpolationVariable var : vars ) { varsInScope.add( var.getVarName() ); @@ -62,7 +61,7 @@ public void setFieldConstraint( FieldConstraint fieldConstraint ) { hasNonTemplateOutput = visitor.hasNonTemplateOutput(); } - public GeneratorContext getParent() { + public LHSGeneratorContext getParent() { return parent; } diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/LHSGeneratorContextFactory.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/LHSGeneratorContextFactory.java new file mode 100644 index 00000000000..d961e932ccb --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/LHSGeneratorContextFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 JBoss Inc + * + * 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.context; + +import java.util.ArrayList; +import java.util.List; + +/** + * Factory for Generator Contexts + */ +public class LHSGeneratorContextFactory { + + private List contexts = new ArrayList(); + + public LHSGeneratorContext newGeneratorContext() { + final LHSGeneratorContext gc = new LHSGeneratorContext(); + contexts.add( gc ); + return gc; + } + + public LHSGeneratorContext newChildGeneratorContext( final LHSGeneratorContext parent ) { + final LHSGeneratorContext gc = new LHSGeneratorContext( parent, + parent.getDepth() + 1, + parent.getOffset() + 1 ); + contexts.add( gc ); + return gc; + } + + public List getGeneratorContexts() { + return contexts; + } + +} diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/RHSGeneratorContext.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/RHSGeneratorContext.java new file mode 100644 index 00000000000..7614d1e7012 --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/RHSGeneratorContext.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 JBoss Inc + * + * 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.context; + +/** + * RHS DRL generation context object + */ +public class RHSGeneratorContext { + + private RHSGeneratorContext parent; + private int offset; + private boolean hasOutput; + + RHSGeneratorContext() { + } + + RHSGeneratorContext( final RHSGeneratorContext parent, + final int offset ) { + this.parent = parent; + this.offset = offset; + } + + public RHSGeneratorContext getParent() { + return parent; + } + + public boolean isHasOutput() { + return hasOutput; + } + + public void setHasOutput( boolean hasOutput ) { + this.hasOutput = hasOutput; + } + + public int getOffset() { + return offset; + } + +} diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContextFactory.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/RHSGeneratorContextFactory.java similarity index 55% rename from drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContextFactory.java rename to drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/RHSGeneratorContextFactory.java index 364251d91c7..4bd43be2546 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/GeneratorContextFactory.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/RHSGeneratorContextFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.drools.workbench.models.commons.backend.rule; +package org.drools.workbench.models.commons.backend.rule.context; import java.util.ArrayList; import java.util.List; @@ -21,25 +21,24 @@ /** * Factory for Generator Contexts */ -public class GeneratorContextFactory { +public class RHSGeneratorContextFactory { - private List contexts = new ArrayList(); + private List contexts = new ArrayList(); - public GeneratorContext newGeneratorContext() { - final GeneratorContext gc = new GeneratorContext(); + public RHSGeneratorContext newGeneratorContext() { + final RHSGeneratorContext gc = new RHSGeneratorContext(); contexts.add( gc ); return gc; } - public GeneratorContext newChildGeneratorContext( GeneratorContext parent ) { - final GeneratorContext gc = new GeneratorContext( parent, - parent.getDepth() + 1, - parent.getOffset() + 1 ); + public RHSGeneratorContext newChildGeneratorContext( final RHSGeneratorContext parent ) { + final RHSGeneratorContext gc = new RHSGeneratorContext( parent, + parent.getOffset() + 1 ); contexts.add( gc ); return gc; } - public List getGeneratorContexts() { + public List getGeneratorContexts() { return contexts; } diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java index ecb7291f121..7158f86a99f 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java @@ -328,8 +328,9 @@ public void testSumAsGivenValue() { " when\n" + " m:Message()\n" + " then\n" + - " m.setText( \"Hello \" + \"world\" );\n" + - " update(m);\n" + + " modify( m ) {\n" + + " setText( \"Hello \" + \"world\" )\n" + + " }\n" + "end\n"; final RuleModel m = new RuleModel(); @@ -581,39 +582,59 @@ public void testEnumTypeComparable() { @Test public void testMoreComplexRendering() { final RuleModel m = getComplexModel( false ); - String expected = "rule \"Complex Rule\"\n" + "\tno-loop true\n" - + "\tsalience -10\n" + "\tagenda-group \"aGroup\"\n" - + "\tdialect \"mvel\"\n" + "\twhen\n" - + "\t\tp1 : Person( f1 : age < 42 )\n" - + "\t\tnot (Cancel( )) \n" + "\tthen\n" - + "\t\tp1.setStatus( \"rejected\" );\n" - + "\t\tupdate( p1 );\n" + "\t\tretract( p1 );\n" - + "end\n"; + 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"; - checkMarshallUnmarshall( expected, m ); + checkMarshallUnmarshall( expected, + m ); } @Test public void testMoreComplexRenderingWithDsl() { final RuleModel m = getComplexModel( true ); - String expected = "rule \"Complex Rule\"\n" + "\tno-loop true\n" - + "\tsalience -10\n" + "\tagenda-group \"aGroup\"\n" - + "\tdialect \"mvel\"\n" + "\twhen\n" - + "\t\t>p1 : Person( f1 : age < 42 )\n" - + "\t\t>not (Cancel( )) \n" + "\tthen\n" - + "\t\t>p1.setStatus( \"rejected\" );\n" - + "\t\t>update( p1 );\n" + "\t\t>retract( p1 );\n" - + "\t\tSend an email to administrator\n" + "end\n"; + 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"; checkMarshallUnmarshallUsingDsl( expected, m ); String drl = ruleModelPersistence.marshal( m ); - assertEqualsIgnoreWhitespace( expected, drl ); + assertEqualsIgnoreWhitespace( expected, + drl ); String dslFile = "[then]Send an email to {administrator}=sendMailTo({administrator});"; - RuleModel unmarshalledModel = ruleModelPersistence.unmarshalUsingDSL( drl, null, dmo, dslFile ); + RuleModel unmarshalledModel = ruleModelPersistence.unmarshalUsingDSL( drl, + null, + dmo, + dslFile ); IAction[] actions = unmarshalledModel.rhs; DSLSentence dslSentence = (DSLSentence) actions[ actions.length - 1 ]; @@ -804,12 +825,15 @@ private RuleModel getComplexModel( boolean useDsl ) { 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 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 ); @@ -2074,8 +2098,8 @@ public void testRHSDateModifyAction() { 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 ); + assertTrue( result.indexOf( "setDob( sdf.parse(\"31-Jan-2000\"" ) != -1 ); + assertTrue( result.indexOf( "modify( $p ) {" ) != -1 ); checkMarshallUnmarshall( null, m ); @@ -4432,4 +4456,153 @@ public void testLHSReturnType() { 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"; + + checkMarshallUnmarshall( 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"; + + checkMarshallUnmarshall( 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"; + + checkMarshallUnmarshall( expected, + m ); + } + } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java index 5ca08385ee0..15366d4bd21 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java @@ -215,7 +215,6 @@ void doActions( List allColumns, } else if ( c instanceof ActionRetractFactCol52 ) { doAction( actions, - (ActionRetractFactCol52) c, cell ); } else if ( c instanceof ActionWorkItemCol52 ) { @@ -305,18 +304,13 @@ private boolean hasVariables( BRLActionColumn column ) { private void addAction( IAction action, List actions ) { String binding = null; - LabelledAction a = null; if ( action instanceof ActionInsertFact ) { final ActionInsertFact af = (ActionInsertFact) action; binding = af.getBoundName(); - a = findByLabelledAction( actions, - binding ); } else if ( action instanceof ActionSetField ) { final ActionSetField af = (ActionSetField) action; binding = af.getVariable(); - a = findByLabelledAction( actions, - binding ); } //Binding is used to group related field setters together. It is essential for @@ -328,13 +322,10 @@ private void addAction( IAction action, binding = action.toString(); } - if ( a == null ) { - a = new LabelledAction(); - a.boundName = binding; - a.action = action; - actions.add( a ); - } - + final LabelledAction a = new LabelledAction(); + a.boundName = binding; + a.action = action; + actions.add( a ); } private void doAction( List actions, @@ -429,10 +420,12 @@ private void doAction( List actions, ActionSetFieldCol52 sf, String cell ) { LabelledAction a = findByLabelledAction( actions, - sf.getBoundName() ); + sf.getBoundName(), + sf.isUpdate() ); if ( a == null ) { a = new LabelledAction(); a.boundName = sf.getBoundName(); + a.isUpdate = sf.isUpdate(); if ( !sf.isUpdate() ) { a.action = new ActionSetField( sf.getBoundName() ); } else { @@ -454,7 +447,6 @@ private void doAction( List actions, } private void doAction( List actions, - ActionRetractFactCol52 rf, String cell ) { LabelledAction a = new LabelledAction(); a.action = new ActionRetractFact( cell ); @@ -479,10 +471,20 @@ private void doAction( List actions, //ActionSetField and ActionUpdateField need to be grouped in this manner. private LabelledAction findByLabelledAction( List actions, String boundName ) { + return findByLabelledAction( actions, + boundName, + false ); + } + + //Labelled Actions are used to group actions on the same bound Fact. Only + //ActionSetField and ActionUpdateField need to be grouped in this manner. + private LabelledAction findByLabelledAction( List actions, + String boundName, + boolean isUpdate ) { for ( LabelledAction labelledAction : actions ) { IAction action = labelledAction.action; if ( action instanceof ActionFieldList ) { - if ( labelledAction.boundName.equals( boundName ) ) { + if ( labelledAction.boundName.equals( boundName ) && labelledAction.isUpdate == isUpdate ) { return labelledAction; } } @@ -821,6 +823,7 @@ boolean validCell( String c ) { private class LabelledAction { String boundName; + boolean isUpdate; IAction action; } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java index 1a75aaaa4ef..596e038f6ae 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java @@ -21,9 +21,11 @@ import org.drools.core.util.StringUtils; import org.drools.workbench.models.commons.backend.rule.DRLConstraintValueBuilder; -import org.drools.workbench.models.commons.backend.rule.GeneratorContext; -import org.drools.workbench.models.commons.backend.rule.GeneratorContextFactory; import org.drools.workbench.models.commons.backend.rule.RuleModelDRLPersistenceImpl; +import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContext; +import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContextFactory; +import org.drools.workbench.models.commons.backend.rule.context.RHSGeneratorContext; +import org.drools.workbench.models.commons.backend.rule.context.RHSGeneratorContextFactory; import org.drools.workbench.models.datamodel.rule.ActionFieldValue; import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.ExpressionFormLine; @@ -56,7 +58,7 @@ protected LHSPatternVisitor getLHSPatternVisitor( final boolean isDSLEnhanced, final StringBuilder buf, final String nestedIndentation, final boolean isNegated, - final GeneratorContextFactory generatorContextFactory ) { + final LHSGeneratorContextFactory generatorContextFactory ) { return new LHSPatternVisitor( isDSLEnhanced, rowDataProvider, bindingsPatterns, @@ -71,12 +73,14 @@ protected LHSPatternVisitor getLHSPatternVisitor( final boolean isDSLEnhanced, @Override protected RHSActionVisitor getRHSActionVisitor( final boolean isDSLEnhanced, final StringBuilder buf, - final String indentation ) { + final String indentation, + final RHSGeneratorContextFactory generatorContextFactory ) { return new RHSActionVisitor( isDSLEnhanced, rowDataProvider, bindingsPatterns, bindingsFields, constraintValueBuilder, + generatorContextFactory, buf, indentation ); } @@ -91,7 +95,7 @@ public LHSPatternVisitor( final boolean isDSLEnhanced, final Map bindingsPatterns, final Map bindingsFields, final DRLConstraintValueBuilder constraintValueBuilder, - final GeneratorContextFactory generatorContextFactory, + final LHSGeneratorContextFactory generatorContextFactory, final StringBuilder b, final String indentation, final boolean isPatternNegated ) { @@ -115,7 +119,7 @@ protected boolean isValidFieldConstraint( final FieldConstraint constr ) { @Override protected void generateConstraint( final FieldConstraint constr, - GeneratorContext gctx ) { + LHSGeneratorContext gctx ) { if ( isValidFieldConstraint( constr ) ) { super.generateConstraint( constr, gctx ); @@ -129,7 +133,7 @@ protected void addConnectiveFieldRestriction( final StringBuilder buf, final Map parameters, final String value, final ExpressionFormLine expression, - GeneratorContext gctx, + LHSGeneratorContext gctx, final boolean spaceBeforeOperator ) { boolean generateTemplateCheck = type == BaseSingleFieldConstraint.TYPE_TEMPLATE; if ( generateTemplateCheck && !gctx.isHasOutput() && operator.startsWith( "||" ) || operator.startsWith( "&&" ) ) { @@ -210,12 +214,14 @@ public RHSActionVisitor( final boolean isDSLEnhanced, final Map bindingsPatterns, final Map bindingsFields, final DRLConstraintValueBuilder constraintValueBuilder, + final RHSGeneratorContextFactory generatorContextFactory, final StringBuilder b, final String indentation ) { super( isDSLEnhanced, bindingsPatterns, bindingsFields, constraintValueBuilder, + generatorContextFactory, b, indentation ); this.rowDataProvider = rowDataProvider; @@ -236,6 +242,7 @@ protected boolean isValidFieldConstraint( final ActionFieldValue fieldValue ) { return true; } + @Override protected void generateSetMethodCall( final String variableName, final ActionFieldValue fieldValue ) { if ( isValidFieldConstraint( fieldValue ) ) { @@ -243,6 +250,30 @@ protected void generateSetMethodCall( final String variableName, } } + @Override + protected void preGenerateSetMethodCallParameterValue( final ActionFieldValue fieldValue, + final RHSGeneratorContext gctx ) { + gctx.setHasOutput( isValidFieldConstraint( fieldValue ) ); + } + + @Override + protected void generateModifyMethodCall( final RHSGeneratorContext gctx, + final ActionFieldValue fieldValue ) { + if ( isValidFieldConstraint( fieldValue ) ) { + super.generateModifyMethodCall( gctx, + fieldValue ); + } + } + + @Override + protected void generateModifyMethodSeparator( final RHSGeneratorContext gctx, + final ActionFieldValue fieldValue ) { + if ( isValidFieldConstraint( fieldValue ) ) { + super.generateModifyMethodSeparator( gctx, + fieldValue ); + } + } + @Override public void visitFreeFormLine( final FreeFormLine ffl ) { diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/BRLRuleModelTest.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/BRLRuleModelTest.java index adaf2554ed5..fd642ed952f 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/BRLRuleModelTest.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/BRLRuleModelTest.java @@ -16,24 +16,26 @@ package org.drools.workbench.models.guided.dtable.backend; import org.drools.workbench.models.datamodel.oracle.DataType; -import org.drools.workbench.models.guided.dtable.shared.model.adaptors.ActionInsertFactCol52ActionInsertFactAdaptor; +import org.drools.workbench.models.datamodel.rule.ActionFieldValue; +import org.drools.workbench.models.datamodel.rule.ActionInsertFact; +import org.drools.workbench.models.datamodel.rule.ActionUpdateField; +import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; +import org.drools.workbench.models.datamodel.rule.FactPattern; +import org.drools.workbench.models.datamodel.rule.FieldConstraint; +import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; +import org.drools.workbench.models.guided.dtable.backend.util.DataUtilities; import org.drools.workbench.models.guided.dtable.shared.model.ActionInsertFactCol52; import org.drools.workbench.models.guided.dtable.shared.model.BRLActionColumn; +import org.drools.workbench.models.guided.dtable.shared.model.BRLActionVariableColumn; import org.drools.workbench.models.guided.dtable.shared.model.BRLConditionColumn; -import org.drools.workbench.models.guided.dtable.shared.model.ConditionCol52; -import org.drools.workbench.models.guided.dtable.shared.model.adaptors.ActionInsertFactCol52ActionInsertLogicalFactAdaptor; -import org.drools.workbench.models.guided.dtable.shared.model.adaptors.Pattern52FactPatternAdaptor; import org.drools.workbench.models.guided.dtable.shared.model.BRLRuleModel; +import org.drools.workbench.models.guided.dtable.shared.model.ConditionCol52; import org.drools.workbench.models.guided.dtable.shared.model.GuidedDecisionTable52; import org.drools.workbench.models.guided.dtable.shared.model.Pattern52; +import org.drools.workbench.models.guided.dtable.shared.model.adaptors.ActionInsertFactCol52ActionInsertFactAdaptor; +import org.drools.workbench.models.guided.dtable.shared.model.adaptors.ActionInsertFactCol52ActionInsertLogicalFactAdaptor; +import org.drools.workbench.models.guided.dtable.shared.model.adaptors.Pattern52FactPatternAdaptor; import org.junit.Test; -import org.drools.workbench.models.datamodel.oracle.DataType; -import org.drools.workbench.models.datamodel.rule.ActionFieldValue; -import org.drools.workbench.models.datamodel.rule.ActionInsertFact; -import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; -import org.drools.workbench.models.datamodel.rule.FactPattern; -import org.drools.workbench.models.datamodel.rule.FieldConstraint; -import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; import static org.junit.Assert.*; @@ -293,7 +295,7 @@ public void testDecisionTableColumnsWithRHS() { ActionInsertFact r1 = model.getRHSBoundFact( "$ins" ); assertNotNull( r1 ); - assertTrue( r1 instanceof ActionInsertFactCol52ActionInsertFactAdaptor); + assertTrue( r1 instanceof ActionInsertFactCol52ActionInsertFactAdaptor ); ActionInsertFactCol52ActionInsertFactAdaptor raif1 = (ActionInsertFactCol52ActionInsertFactAdaptor) r1; assertEquals( "Person", raif1.getFactType() ); @@ -388,7 +390,7 @@ public void testDecisionTableColumnsWithRHSBoundFacts() { ActionInsertFact r2 = model.getRHSBoundFact( "$ins2" ); assertNotNull( r2 ); - assertTrue( r2 instanceof ActionInsertFactCol52ActionInsertLogicalFactAdaptor); + assertTrue( r2 instanceof ActionInsertFactCol52ActionInsertLogicalFactAdaptor ); ActionInsertFactCol52ActionInsertLogicalFactAdaptor raif2 = (ActionInsertFactCol52ActionInsertLogicalFactAdaptor) r2; assertEquals( "Person2", raif2.getFactType() ); @@ -676,4 +678,396 @@ public void testRuleModelRHSBoundFacts_NoDuplicates() { raif2.getFieldValues()[ 0 ].getNature() ); } + @Test + public void testUpdateModifyMultipleFields() { + GuidedDecisionTable52 dt = new GuidedDecisionTable52(); + + Pattern52 p1 = new Pattern52(); + p1.setBoundName( "x" ); + p1.setFactType( "Context" ); + + ConditionCol52 c = new ConditionCol52(); + c.setConstraintValueType( BaseSingleFieldConstraint.TYPE_LITERAL ); + p1.getChildColumns().add( c ); + dt.getConditions().add( p1 ); + + BRLActionColumn brlAction1 = new BRLActionColumn(); + ActionUpdateField auf1 = new ActionUpdateField( "x" ); + auf1.addFieldValue( new ActionFieldValue( "age", + "$age", + DataType.TYPE_NUMERIC_INTEGER ) ); + auf1.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf1 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$age", + DataType.TYPE_NUMERIC_INTEGER, + "Context", + "age" ) ); + dt.getActionCols().add( brlAction1 ); + + BRLActionColumn brlAction2 = new BRLActionColumn(); + ActionUpdateField auf2 = new ActionUpdateField( "x" ); + auf2.addFieldValue( new ActionFieldValue( "name", + "$name", + DataType.TYPE_STRING ) ); + auf2.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction2.getDefinition().add( auf2 ); + brlAction2.getChildColumns().add( new BRLActionVariableColumn( "$name", + DataType.TYPE_STRING, + "Context", + "name" ) ); + dt.getActionCols().add( brlAction2 ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "55", "Fred" } + } ) ); + String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected1 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setAge( 55 ), \n" + + " setName( \"Fred\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected1, + drl ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "", "Fred" } + } ) ); + drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected2 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setName( \"Fred\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected2, + drl ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "55", "" } + } ) ); + drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected3 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setAge( 55 ) \n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected3, + drl ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped1() { + GuidedDecisionTable52 dt = new GuidedDecisionTable52(); + + Pattern52 p1 = new Pattern52(); + p1.setBoundName( "x" ); + p1.setFactType( "Context" ); + + ConditionCol52 c = new ConditionCol52(); + c.setConstraintValueType( BaseSingleFieldConstraint.TYPE_LITERAL ); + p1.getChildColumns().add( c ); + dt.getConditions().add( p1 ); + + BRLActionColumn brlAction1 = new BRLActionColumn(); + ActionUpdateField auf1 = new ActionUpdateField( "x" ); + auf1.addFieldValue( new ActionFieldValue( "f1", + "$f1", + DataType.TYPE_STRING ) ); + auf1.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf1 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f1", + DataType.TYPE_STRING, + "Context", + "f1" ) ); + ActionUpdateField auf2 = new ActionUpdateField( "x" ); + auf2.addFieldValue( new ActionFieldValue( "f2", + "$f2", + DataType.TYPE_STRING ) ); + auf2.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf2 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f2", + DataType.TYPE_STRING, + "Context", + "f2" ) ); + + ActionUpdateField auf3 = new ActionUpdateField( "x" ); + auf3.addFieldValue( new ActionFieldValue( "f3", + "$f3", + DataType.TYPE_STRING ) ); + auf3.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf3 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f3", + DataType.TYPE_STRING, + "Context", + "f3" ) ); + + dt.getActionCols().add( brlAction1 ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "v1", "v2", "v3" } + } ) ); + String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setF1( \"v1\" ), \n" + + " setF2( \"v2\" ),\n" + + " setF3( \"v3\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected, + drl ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped2() { + GuidedDecisionTable52 dt = new GuidedDecisionTable52(); + + Pattern52 p1 = new Pattern52(); + p1.setBoundName( "x" ); + p1.setFactType( "Context" ); + + ConditionCol52 c = new ConditionCol52(); + c.setConstraintValueType( BaseSingleFieldConstraint.TYPE_LITERAL ); + p1.getChildColumns().add( c ); + dt.getConditions().add( p1 ); + + BRLActionColumn brlAction1 = new BRLActionColumn(); + ActionUpdateField auf1 = new ActionUpdateField( "x" ); + auf1.addFieldValue( new ActionFieldValue( "f1", + "$f1", + DataType.TYPE_STRING ) ); + auf1.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf1 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f1", + DataType.TYPE_STRING, + "Context", + "f1" ) ); + ActionUpdateField auf2 = new ActionUpdateField( "x" ); + auf2.addFieldValue( new ActionFieldValue( "f2", + "$f2", + DataType.TYPE_STRING ) ); + auf2.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf2 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f2", + DataType.TYPE_STRING, + "Context", + "f2" ) ); + + ActionUpdateField auf3 = new ActionUpdateField( "x" ); + auf3.addFieldValue( new ActionFieldValue( "f3", + "$f3", + DataType.TYPE_STRING ) ); + auf3.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf3 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f3", + DataType.TYPE_STRING, + "Context", + "f3" ) ); + + dt.getActionCols().add( brlAction1 ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", null, "v2", "v3" } + } ) ); + String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setF2( \"v2\" ),\n" + + " setF3( \"v3\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected, + drl ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped3() { + GuidedDecisionTable52 dt = new GuidedDecisionTable52(); + + Pattern52 p1 = new Pattern52(); + p1.setBoundName( "x" ); + p1.setFactType( "Context" ); + + ConditionCol52 c = new ConditionCol52(); + c.setConstraintValueType( BaseSingleFieldConstraint.TYPE_LITERAL ); + p1.getChildColumns().add( c ); + dt.getConditions().add( p1 ); + + BRLActionColumn brlAction1 = new BRLActionColumn(); + ActionUpdateField auf1 = new ActionUpdateField( "x" ); + auf1.addFieldValue( new ActionFieldValue( "f1", + "$f1", + DataType.TYPE_STRING ) ); + auf1.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf1 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f1", + DataType.TYPE_STRING, + "Context", + "f1" ) ); + ActionUpdateField auf2 = new ActionUpdateField( "x" ); + auf2.addFieldValue( new ActionFieldValue( "f2", + "$f2", + DataType.TYPE_STRING ) ); + auf2.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf2 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f2", + DataType.TYPE_STRING, + "Context", + "f2" ) ); + + ActionUpdateField auf3 = new ActionUpdateField( "x" ); + auf3.addFieldValue( new ActionFieldValue( "f3", + "$f3", + DataType.TYPE_STRING ) ); + auf3.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf3 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f3", + DataType.TYPE_STRING, + "Context", + "f3" ) ); + + dt.getActionCols().add( brlAction1 ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", null, null, "v3" } + } ) ); + String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setF3( \"v3\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected, + drl ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped4() { + GuidedDecisionTable52 dt = new GuidedDecisionTable52(); + + Pattern52 p1 = new Pattern52(); + p1.setBoundName( "x" ); + p1.setFactType( "Context" ); + + ConditionCol52 c = new ConditionCol52(); + c.setConstraintValueType( BaseSingleFieldConstraint.TYPE_LITERAL ); + p1.getChildColumns().add( c ); + dt.getConditions().add( p1 ); + + BRLActionColumn brlAction1 = new BRLActionColumn(); + ActionUpdateField auf1 = new ActionUpdateField( "x" ); + auf1.addFieldValue( new ActionFieldValue( "f1", + "$f1", + DataType.TYPE_STRING ) ); + auf1.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf1 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f1", + DataType.TYPE_STRING, + "Context", + "f1" ) ); + ActionUpdateField auf2 = new ActionUpdateField( "x" ); + auf2.addFieldValue( new ActionFieldValue( "f2", + "$f2", + DataType.TYPE_STRING ) ); + auf2.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf2 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f2", + DataType.TYPE_STRING, + "Context", + "f2" ) ); + + ActionUpdateField auf3 = new ActionUpdateField( "x" ); + auf3.addFieldValue( new ActionFieldValue( "f3", + "$f3", + DataType.TYPE_STRING ) ); + auf3.getFieldValues()[ 0 ].setNature( BaseSingleFieldConstraint.TYPE_TEMPLATE ); + + brlAction1.getDefinition().add( auf3 ); + brlAction1.getChildColumns().add( new BRLActionVariableColumn( "$f3", + DataType.TYPE_STRING, + "Context", + "f3" ) ); + + dt.getActionCols().add( brlAction1 ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "v1", null, "v3" } + } ) ); + String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setF1( \"v1\" ),\n" + + " setF3( \"v3\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected, + drl ); + } + + private void assertEqualsIgnoreWhitespace( final String expected, + final String actual ) { + final String cleanExpected = expected.replaceAll( "\\s+", + "" ); + final String cleanActual = actual.replaceAll( "\\s+", + "" ); + + assertEquals( cleanExpected, + cleanActual ); + } + } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistenceTest.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistenceTest.java index 305f6e2c69e..e3368e54f09 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistenceTest.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistenceTest.java @@ -1436,7 +1436,7 @@ public void testNoOperator() { @Test public void testRHS() { GuidedDTDRLPersistence p = new GuidedDTDRLPersistence(); - String[] row = new String[]{ "1", "desc", "a", "a condition", "actionsetfield1", "actionsetfield2", "retract", "actioninsertfact1", "actioninsertfact2" }; + String[] row = new String[]{ "1", "desc", "a", "a condition", "actionsetfield1", "actionupdatefield2", "retract", "actioninsertfact1", "actioninsertfact2" }; List allColumns = new ArrayList(); allColumns.add( new RowNumberCol52() ); @@ -1492,14 +1492,14 @@ public void testRHS() { rowDataProvider, rowData, rm ); - assertEquals( 3, + assertEquals( 4, rm.rhs.length ); // examine the set field action that is produced ActionSetField a1 = (ActionSetField) rm.rhs[ 0 ]; assertEquals( "a", a1.getVariable() ); - assertEquals( 2, + assertEquals( 1, a1.getFieldValues().length ); assertEquals( "field1", @@ -1509,43 +1509,49 @@ public void testRHS() { assertEquals( DataType.TYPE_STRING, a1.getFieldValues()[ 0 ].getType() ); + ActionSetField a2 = (ActionSetField) rm.rhs[ 1 ]; + assertEquals( "a", + a2.getVariable() ); + assertEquals( 1, + a2.getFieldValues().length ); + assertEquals( "field2", - a1.getFieldValues()[ 1 ].getField() ); - assertEquals( "actionsetfield2", - a1.getFieldValues()[ 1 ].getValue() ); + a2.getFieldValues()[ 0 ].getField() ); + assertEquals( "actionupdatefield2", + a2.getFieldValues()[ 0 ].getValue() ); assertEquals( DataType.TYPE_NUMERIC_INTEGER, - a1.getFieldValues()[ 1 ].getType() ); + a2.getFieldValues()[ 0 ].getType() ); // examine the retract - ActionRetractFact a2 = (ActionRetractFact) rm.rhs[ 1 ]; + ActionRetractFact a3 = (ActionRetractFact) rm.rhs[ 2 ]; assertEquals( "retract", - a2.getVariableName() ); + a3.getVariableName() ); // examine the insert - ActionInsertFact a3 = (ActionInsertFact) rm.rhs[ 2 ]; + ActionInsertFact a4 = (ActionInsertFact) rm.rhs[ 3 ]; assertEquals( "Cheese", - a3.getFactType() ); + a4.getFactType() ); assertEquals( 2, - a3.getFieldValues().length ); + a4.getFieldValues().length ); assertEquals( "price", - a3.getFieldValues()[ 0 ].getField() ); + a4.getFieldValues()[ 0 ].getField() ); assertEquals( "actioninsertfact1", - a3.getFieldValues()[ 0 ].getValue() ); + a4.getFieldValues()[ 0 ].getValue() ); assertEquals( DataType.TYPE_NUMERIC_INTEGER, - a3.getFieldValues()[ 0 ].getType() ); + a4.getFieldValues()[ 0 ].getType() ); assertEquals( "type", - a3.getFieldValues()[ 1 ].getField() ); + a4.getFieldValues()[ 1 ].getField() ); assertEquals( "actioninsertfact2", - a3.getFieldValues()[ 1 ].getValue() ); + a4.getFieldValues()[ 1 ].getValue() ); assertEquals( DataType.TYPE_NUMERIC_INTEGER, - a3.getFieldValues()[ 1 ].getType() ); + a4.getFieldValues()[ 1 ].getType() ); } @Test - public void testUpdateModify() { + public void testUpdateModifySingleField() { GuidedDecisionTable52 dt = new GuidedDecisionTable52(); Pattern52 p1 = new Pattern52(); @@ -1573,7 +1579,8 @@ public void testUpdateModify() { String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); assertTrue( drl.indexOf( "Context( )" ) > -1 ); - assertTrue( drl.indexOf( "x.setAge" ) > drl.indexOf( "Context( )" ) ); + assertTrue( drl.indexOf( "modify( x ) {" ) > drl.indexOf( "Context( )" ) ); + assertTrue( drl.indexOf( "setAge(" ) > drl.indexOf( "modify( x ) {" ) ); dt.setData( DataUtilities.makeDataLists( new String[][]{ new String[]{ "1", "desc", "", "old" } @@ -1582,8 +1589,192 @@ public void testUpdateModify() { assertEquals( -1, drl.indexOf( "Context( )" ) ); - assertTrue( drl.indexOf( "update( x );" ) > -1 ); + assertTrue( drl.indexOf( "modify( x ) {" ) > -1 ); + assertTrue( drl.indexOf( "setAge(" ) > drl.indexOf( "modify( x ) {" ) ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "", "" } + } ) ); + drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + assertEquals( -1, + drl.indexOf( "Context( )" ) ); + + assertEquals( -1, + drl.indexOf( "modify( x ) {" ) ); + assertEquals( -1, + drl.indexOf( "setAge(" ) ); + } + + @Test + public void testUpdateModifyMultipleFields() { + GuidedDecisionTable52 dt = new GuidedDecisionTable52(); + + Pattern52 p1 = new Pattern52(); + p1.setBoundName( "x" ); + p1.setFactType( "Context" ); + + ConditionCol52 c = new ConditionCol52(); + c.setConstraintValueType( BaseSingleFieldConstraint.TYPE_LITERAL ); + p1.getChildColumns().add( c ); + dt.getConditions().add( p1 ); + + ActionSetFieldCol52 asf1 = new ActionSetFieldCol52(); + asf1.setBoundName( "x" ); + asf1.setFactField( "age" ); + asf1.setType( DataType.TYPE_NUMERIC_INTEGER ); + asf1.setUpdate( true ); + + dt.getActionCols().add( asf1 ); + + ActionSetFieldCol52 asf2 = new ActionSetFieldCol52(); + asf2.setBoundName( "x" ); + asf2.setFactField( "name" ); + asf2.setType( DataType.TYPE_STRING ); + asf2.setUpdate( true ); + + dt.getActionCols().add( asf2 ); + + String[][] data = new String[][]{ + new String[]{ "1", "desc", "x", "55", "Fred" } + }; + dt.setData( DataUtilities.makeDataLists( data ) ); + + String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected1 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setAge( 55 ), \n" + + " setName( \"Fred\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected1, + drl ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "", "Fred" } + } ) ); + drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected2 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setName( \"Fred\" )\n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected2, + drl ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "55", "" } + } ) ); + drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected3 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setAge( 55 ) \n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected3, + drl ); + } + + @Test + public void testUpdateModifyMultipleFieldsUpdateOneModifyTheOther() { + GuidedDecisionTable52 dt = new GuidedDecisionTable52(); + + Pattern52 p1 = new Pattern52(); + p1.setBoundName( "x" ); + p1.setFactType( "Context" ); + + ConditionCol52 c = new ConditionCol52(); + c.setConstraintValueType( BaseSingleFieldConstraint.TYPE_LITERAL ); + p1.getChildColumns().add( c ); + dt.getConditions().add( p1 ); + + ActionSetFieldCol52 asf1 = new ActionSetFieldCol52(); + asf1.setBoundName( "x" ); + asf1.setFactField( "age" ); + asf1.setType( DataType.TYPE_NUMERIC_INTEGER ); + asf1.setUpdate( true ); + + dt.getActionCols().add( asf1 ); + + ActionSetFieldCol52 asf2 = new ActionSetFieldCol52(); + asf2.setBoundName( "x" ); + asf2.setFactField( "name" ); + asf2.setType( DataType.TYPE_STRING ); + asf2.setUpdate( false ); + + dt.getActionCols().add( asf2 ); + + String[][] data = new String[][]{ + new String[]{ "1", "desc", "x", "55", "Fred" } + }; + dt.setData( DataUtilities.makeDataLists( data ) ); + + String drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected1 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setAge( 55 ) \n" + + "}\n" + + "x.setName( \"Fred\" );\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected1, + drl ); + + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "", "Fred" } + } ) ); + drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected2 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + "x.setName( \"Fred\" );\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected2, + drl ); + dt.setData( DataUtilities.makeDataLists( new String[][]{ + new String[]{ "1", "desc", "x", "55", "" } + } ) ); + drl = GuidedDTDRLPersistence.getInstance().marshal( dt ); + final String expected3 = "//from row number: 1\n" + + "//desc\n" + + "rule \"Row 1 null\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " x : Context( )\n" + + "then\n" + + " modify( x ) {\n" + + " setAge( 55 ) \n" + + "}\n" + + "end\n"; + assertEqualsIgnoreWhitespace( expected3, + drl ); } @Test @@ -4401,4 +4592,15 @@ public void testPackageNameAndImports() throws Exception { assertTrue( drl.indexOf( "import java.lang.String;" ) > 0 ); } + private void assertEqualsIgnoreWhitespace( final String expected, + final String actual ) { + final String cleanExpected = expected.replaceAll( "\\s+", + "" ); + final String cleanActual = actual.replaceAll( "\\s+", + "" ); + + assertEquals( cleanExpected, + cleanActual ); + } + } diff --git a/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java b/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java index 34dc1528527..02a863e51e4 100644 --- a/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java +++ b/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java @@ -28,10 +28,12 @@ import org.drools.template.DataProviderCompiler; import org.drools.template.objects.ArrayDataProvider; import org.drools.workbench.models.commons.backend.rule.DRLConstraintValueBuilder; -import org.drools.workbench.models.commons.backend.rule.GeneratorContext; -import org.drools.workbench.models.commons.backend.rule.GeneratorContextFactory; import org.drools.workbench.models.commons.backend.rule.RuleModelDRLPersistenceImpl; import org.drools.workbench.models.commons.backend.rule.RuleModelPersistence; +import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContext; +import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContextFactory; +import org.drools.workbench.models.commons.backend.rule.context.RHSGeneratorContext; +import org.drools.workbench.models.commons.backend.rule.context.RHSGeneratorContextFactory; import org.drools.workbench.models.datamodel.rule.ActionFieldValue; import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.CompositeFieldConstraint; @@ -73,7 +75,7 @@ protected LHSPatternVisitor getLHSPatternVisitor( final boolean isDSLEnhanced, final StringBuilder buf, final String nestedIndentation, final boolean isNegated, - final GeneratorContextFactory generatorContextFactory ) { + final LHSGeneratorContextFactory generatorContextFactory ) { return new LHSPatternVisitor( isDSLEnhanced, bindingsPatterns, bindingsFields, @@ -87,11 +89,13 @@ protected LHSPatternVisitor getLHSPatternVisitor( final boolean isDSLEnhanced, @Override protected RHSActionVisitor getRHSActionVisitor( final boolean isDSLEnhanced, final StringBuilder buf, - final String indentation ) { + final String indentation, + final RHSGeneratorContextFactory generatorContextFactory ) { return new RHSActionVisitor( isDSLEnhanced, bindingsPatterns, bindingsFields, constraintValueBuilder, + generatorContextFactory, buf, indentation ); } @@ -102,7 +106,7 @@ public LHSPatternVisitor( final boolean isDSLEnhanced, final Map bindingsPatterns, final Map bindingsFields, final DRLConstraintValueBuilder constraintValueBuilder, - final GeneratorContextFactory generatorContextFactory, + final LHSGeneratorContextFactory generatorContextFactory, final StringBuilder b, final String indentation, final boolean isPatternNegated ) { @@ -117,12 +121,12 @@ public LHSPatternVisitor( final boolean isDSLEnhanced, } @Override - public void preGenerateConstraints( GeneratorContext gctx ) { + public void preGenerateConstraints( LHSGeneratorContext gctx ) { buf.append( "@code{hasOutput" + gctx.getDepth() + "_" + gctx.getOffset() + " = false}" ); } @Override - public void preGenerateNestedConnector( GeneratorContext gctx ) { + public void preGenerateNestedConnector( LHSGeneratorContext gctx ) { if ( gctx.getVarsInScope().size() > 0 ) { buf.append( "@if{(" ); for ( String var : gctx.getVarsInScope() ) { @@ -130,7 +134,7 @@ public void preGenerateNestedConnector( GeneratorContext gctx ) { } buf.delete( buf.length() - 4, buf.length() ); - GeneratorContext parentContext = gctx.getParent(); + LHSGeneratorContext parentContext = gctx.getParent(); if ( parentContext != null ) { Set parentVarsInScope = new HashSet( parentContext.getVarsInScope() ); parentVarsInScope.removeAll( gctx.getVarsInScope() ); @@ -144,7 +148,7 @@ public void preGenerateNestedConnector( GeneratorContext gctx ) { } buf.append( ") || hasNonTemplateOutput" ).append( gctx.getDepth() + "_" + gctx.getOffset() ).append( "}" ); } else { - GeneratorContext parentContext = gctx.getParent(); + LHSGeneratorContext parentContext = gctx.getParent(); if ( parentContext != null ) { Set parentVarsInScope = new HashSet( parentContext.getVarsInScope() ); parentVarsInScope.removeAll( gctx.getVarsInScope() ); @@ -161,11 +165,11 @@ public void preGenerateNestedConnector( GeneratorContext gctx ) { } @Override - public void postGenerateNestedConnector( GeneratorContext gctx ) { + public void postGenerateNestedConnector( LHSGeneratorContext gctx ) { if ( gctx.getVarsInScope().size() > 0 ) { buf.append( "@end{}" ); } else { - GeneratorContext parentContext = gctx.getParent(); + LHSGeneratorContext parentContext = gctx.getParent(); if ( parentContext != null ) { Set parentVarsInScope = new HashSet( parentContext.getVarsInScope() ); parentVarsInScope.removeAll( gctx.getVarsInScope() ); @@ -177,7 +181,7 @@ public void postGenerateNestedConnector( GeneratorContext gctx ) { } @Override - public void preGenerateNestedConstraint( GeneratorContext gctx ) { + public void preGenerateNestedConstraint( LHSGeneratorContext gctx ) { if ( gctx.getVarsInScope().size() > 0 ) { buf.append( "@if{!(" ); for ( String var : gctx.getVarsInScope() ) { @@ -189,7 +193,7 @@ public void preGenerateNestedConstraint( GeneratorContext gctx ) { } @Override - public void postGenerateNestedConstraint( GeneratorContext gctx ) { + public void postGenerateNestedConstraint( LHSGeneratorContext gctx ) { if ( gctx.getVarsInScope().size() > 0 ) { buf.append( "@end{}" ); } @@ -197,7 +201,7 @@ public void postGenerateNestedConstraint( GeneratorContext gctx ) { @Override protected void generateConstraint( final FieldConstraint constr, - GeneratorContext gctx ) { + LHSGeneratorContext gctx ) { boolean generateTemplateCheck = isTemplateKey( constr ); if ( generateTemplateCheck ) { @@ -230,7 +234,7 @@ private boolean isTemplateKey( FieldConstraint nestedConstr ) { } public void generateSeparator( FieldConstraint constr, - GeneratorContext gctx ) { + LHSGeneratorContext gctx ) { if ( !gctx.isHasOutput() ) { return; } @@ -253,6 +257,7 @@ public void generateSeparator( FieldConstraint constr, } } + @Override protected void addConnectiveFieldRestriction( final StringBuilder buf, final int type, final String fieldType, @@ -260,7 +265,7 @@ protected void addConnectiveFieldRestriction( final StringBuilder buf, final Map parameters, final String value, final ExpressionFormLine expression, - GeneratorContext gctx, + final LHSGeneratorContext gctx, boolean spaceBeforeOperator ) { boolean generateTemplateCheck = type == BaseSingleFieldConstraint.TYPE_TEMPLATE; if ( generateTemplateCheck ) { @@ -311,6 +316,7 @@ public void visitFreeFormLine( final FreeFormLine ffl ) { } } + @Override public void visitFromCollectCompositeFactPattern( final FromCollectCompositeFactPattern pattern, final boolean isSubPattern ) { @@ -359,19 +365,21 @@ public RHSActionVisitor( final boolean isDSLEnhanced, final Map bindingsPatterns, final Map bindingsFields, final DRLConstraintValueBuilder constraintValueBuilder, + final RHSGeneratorContextFactory generatorContextFactory, final StringBuilder b, final String indentation ) { super( isDSLEnhanced, bindingsPatterns, bindingsFields, constraintValueBuilder, + generatorContextFactory, b, indentation ); } - protected void generateSetMethodCall( String variableName, - ActionFieldValue fieldValue ) { - + @Override + protected void generateSetMethodCall( final String variableName, + final ActionFieldValue fieldValue ) { if ( fieldValue.getNature() == FieldNatureType.TYPE_TEMPLATE ) { buf.append( "@if{" + fieldValue.getValue() + " != empty}" ); super.generateSetMethodCall( variableName, @@ -384,6 +392,54 @@ protected void generateSetMethodCall( String variableName, } } + @Override + protected void preGenerateSetMethodCallParameterValue( final ActionFieldValue fieldValue, + final RHSGeneratorContext gctx ) { + if ( fieldValue.getNature() == FieldNatureType.TYPE_TEMPLATE ) { + buf.append( "@if{" + fieldValue.getValue() + " != empty}" ); + buf.append( "@code{hasOutput" + gctx.getOffset() + " = true}" ); + super.preGenerateSetMethodCallParameterValue( fieldValue, + gctx ); + buf.append( "@end{}" ); + } else { + buf.append( "@code{hasOutput" + gctx.getOffset() + " = true}" ); + super.preGenerateSetMethodCallParameterValue( fieldValue, + gctx ); + } + } + + @Override + protected void generateModifyMethodCall( final RHSGeneratorContext gctx, + final ActionFieldValue fieldValue ) { + if ( fieldValue.getNature() == FieldNatureType.TYPE_TEMPLATE ) { + buf.append( "@if{" + fieldValue.getValue() + " != empty}" ); + super.generateModifyMethodCall( gctx, + fieldValue ); + buf.append( "@end{}" ); + + } else { + super.generateModifyMethodCall( gctx, + fieldValue ); + } + } + + @Override + protected void generateModifyMethodSeparator( final RHSGeneratorContext gctx, + final ActionFieldValue fieldValue ) { + if ( gctx.getParent() == null ) { + return; + } + buf.append( "@if{hasOutput" + gctx.getOffset() + " && (" ); + RHSGeneratorContext parent = gctx.getParent(); + while ( parent != null ) { + buf.append( "hasOutput" + parent.getOffset() + ( parent.getParent() != null ? " || " : "" ) ); + parent = parent.getParent(); + } + buf.append( ")}" ); + buf.append( ", \n" ); + buf.append( "@end{}" ); + } + @Override public void visitFreeFormLine( FreeFormLine ffl ) { if ( ffl.getText() == null ) { @@ -434,6 +490,7 @@ public String marshal( final RuleModel model ) { return generatedDrl; } + @Override protected String marshalRule( final RuleModel model ) { boolean isDSLEnhanced = model.hasDSLSentences(); bindingsPatterns = new HashMap(); @@ -443,7 +500,8 @@ protected String marshalRule( final RuleModel model ) { StringBuilder buf = new StringBuilder(); StringBuilder header = new StringBuilder(); - GeneratorContextFactory generatorContextFactory = new GeneratorContextFactory(); + LHSGeneratorContextFactory lhsGeneratorContextFactory = new LHSGeneratorContextFactory(); + RHSGeneratorContextFactory rhsGeneratorContextFactory = new RHSGeneratorContextFactory(); //Build rule this.marshalRuleHeader( model, @@ -458,16 +516,20 @@ protected String marshalRule( final RuleModel model ) { super.marshalLHS( buf, model, isDSLEnhanced, - generatorContextFactory ); + lhsGeneratorContextFactory ); buf.append( "\tthen\n" ); super.marshalRHS( buf, model, - isDSLEnhanced ); + isDSLEnhanced, + rhsGeneratorContextFactory ); this.marshalFooter( buf ); - for ( GeneratorContext gc : generatorContextFactory.getGeneratorContexts() ) { + for ( LHSGeneratorContext gc : lhsGeneratorContextFactory.getGeneratorContexts() ) { header.append( "@code{hasNonTemplateOutput" + gc.getDepth() + "_" + gc.getOffset() + " = " + gc.hasNonTemplateOutput() + "}" ); } + for ( RHSGeneratorContext gc : rhsGeneratorContextFactory.getGeneratorContexts() ) { + header.append( "@code{hasOutput" + gc.getOffset() + " = false}" ); + } return header.append( buf ).toString(); } diff --git a/drools-workbench-models/drools-workbench-models-guided-template/src/test/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceTest.java b/drools-workbench-models/drools-workbench-models-guided-template/src/test/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceTest.java index 5760fb3db95..d30d275fd4e 100644 --- a/drools-workbench-models/drools-workbench-models-guided-template/src/test/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceTest.java +++ b/drools-workbench-models/drools-workbench-models-guided-template/src/test/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceTest.java @@ -21,6 +21,7 @@ import org.drools.workbench.models.datamodel.rule.ActionFieldValue; import org.drools.workbench.models.datamodel.rule.ActionInsertFact; import org.drools.workbench.models.datamodel.rule.ActionSetField; +import org.drools.workbench.models.datamodel.rule.ActionUpdateField; import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.CompositeFactPattern; import org.drools.workbench.models.datamodel.rule.CompositeFieldConstraint; @@ -3313,6 +3314,470 @@ public void testEmptyFreeForm() { m ); } + @Test + public void testActionModifyTwoFieldsFirstTemplateSecondTemplate1() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField1(\"foo\"),\n" + + " setField2(\"bar\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ "foo", "bar" } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testActionModifyTwoFieldsFirstTemplateSecondTemplate2() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField1(\"foo\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ "foo", null } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testActionModifyTwoFieldsFirstTemplateSecondTemplate3() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField2(\"bar\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ null, "bar" } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testActionModifyTwoFieldsFirstTemplateSecondLiteral1() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_LITERAL ); + afv1.setField( "field2" ); + afv1.setValue( "bar" ); + auf1.addFieldValue( afv1 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField1(\"foo\"),\n" + + " setField2(\"bar\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ "foo" } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testActionModifyTwoFieldsFirstTemplateSecondLiteral2() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_LITERAL ); + afv1.setField( "field2" ); + afv1.setValue( "bar" ); + auf1.addFieldValue( afv1 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField2(\"bar\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ null } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testActionModifyTwoFieldsFirstLiteralSecondTemplate1() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_LITERAL ); + afv0.setField( "field1" ); + afv0.setValue( "foo" ); + auf1.addFieldValue( afv0 ); + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField1(\"foo\"),\n" + + " setField2(\"bar\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ "bar" } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testActionModifyTwoFieldsFirstLiteralSecondTemplate2() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_LITERAL ); + afv0.setField( "field1" ); + afv0.setValue( "foo" ); + auf1.addFieldValue( afv0 ); + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField1(\"foo\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ null } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped1() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + ActionFieldValue afv2 = new ActionFieldValue(); + afv2.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv2.setField( "field3" ); + afv2.setValue( "$f3" ); + auf1.addFieldValue( afv2 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField1(\"v1\"),\n" + + " setField2(\"v2\"),\n" + + " setField3(\"v3\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ "v1", "v2", "v3" } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped2() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + ActionFieldValue afv2 = new ActionFieldValue(); + afv2.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv2.setField( "field3" ); + afv2.setValue( "$f3" ); + auf1.addFieldValue( afv2 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField2(\"v2\"),\n" + + " setField3(\"v3\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ null, "v2", "v3" } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped3() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + ActionFieldValue afv2 = new ActionFieldValue(); + afv2.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv2.setField( "field3" ); + afv2.setValue( "$f3" ); + auf1.addFieldValue( afv2 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField3(\"v3\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ null, null, "v3" } ); + + checkMarshall( expected, + m ); + } + + @Test + public void testUpdateModifyMultipleFieldsWithMultipleSkipped4() { + TemplateModel m = new TemplateModel(); + m.name = "r1"; + + FactPattern fp = new FactPattern( "Person" ); + fp.setBoundName( "$p" ); + m.addLhsItem( fp ); + + ActionUpdateField auf1 = new ActionUpdateField( "$p" ); + ActionFieldValue afv0 = new ActionFieldValue(); + afv0.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv0.setField( "field1" ); + afv0.setValue( "$f1" ); + auf1.addFieldValue( afv0 ); + + ActionFieldValue afv1 = new ActionFieldValue(); + afv1.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv1.setField( "field2" ); + afv1.setValue( "$f2" ); + auf1.addFieldValue( afv1 ); + + ActionFieldValue afv2 = new ActionFieldValue(); + afv2.setNature( FieldNatureType.TYPE_TEMPLATE ); + afv2.setField( "field3" ); + afv2.setValue( "$f3" ); + auf1.addFieldValue( afv2 ); + + m.addRhsItem( auf1 ); + + String expected = "rule \"r1_0\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $p : Person()\n" + + "then\n" + + " modify( $p ) {\n" + + " setField1(\"v1\"),\n" + + " setField3(\"v3\")\n" + + " }\n" + + "end"; + + m.addRow( new String[]{ "v1", null, "v3" } ); + + checkMarshall( expected, + m ); + } + private void assertEqualsIgnoreWhitespace( final String expected, final String actual ) { final String cleanExpected = expected.replaceAll( "\\s+", From 3c503f1e079b1fbddc39267561e6200878860444 Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Fri, 13 Jun 2014 09:12:35 +0100 Subject: [PATCH 10/76] Remove hard-coded version number (build section not needed at all for tests) (cherry picked from commit 0d53587386d19cee8857da18362e0f000358ffdd) --- .../models/guided/scorecard/backend/base/Helper.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drools-workbench-models/drools-workbench-models-guided-scorecard/src/test/java/org/drools/workbench/models/guided/scorecard/backend/base/Helper.java b/drools-workbench-models/drools-workbench-models-guided-scorecard/src/test/java/org/drools/workbench/models/guided/scorecard/backend/base/Helper.java index 80408d8faf2..eff6e20dd6a 100644 --- a/drools-workbench-models/drools-workbench-models-guided-scorecard/src/test/java/org/drools/workbench/models/guided/scorecard/backend/base/Helper.java +++ b/drools-workbench-models/drools-workbench-models-guided-scorecard/src/test/java/org/drools/workbench/models/guided/scorecard/backend/base/Helper.java @@ -35,16 +35,6 @@ public static String getPom() { " 1.0\n" + " kjar\n" + " p0\n" + - " \n" + - " \n" + - " \n" + - " org.kie\n" + - " kie-maven-plugin\n" + - " 6.1.0-SNAPSHOT\n" + - " true\n" + - " \n" + - " \n" + - " \n" + ""; } From 191efc8fdd92c3be5fbc5956b0924c120953715a Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 16 Jun 2014 11:07:28 +0200 Subject: [PATCH 11/76] [BZ-1084362] handle external:* notation in maven settings (cherry picked from commit ad5d455b1465880665e212e4f19d60ab60b13ee1) --- .../java/org/kie/scanner/MavenRepository.java | 22 ++++-- .../org/kie/scanner/MavenRepositoryTest.java | 52 ++++++++++++++ .../org/kie/scanner/settings_with_mirror.xml | 67 +++++++++++++++++++ 3 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 kie-ci/src/test/java/org/kie/scanner/MavenRepositoryTest.java create mode 100644 kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml diff --git a/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java b/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java index a3a820a5502..5fa54e48ffe 100644 --- a/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java +++ b/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java @@ -53,13 +53,21 @@ public class MavenRepository { private final Collection extraRepositories; private final Collection remoteRepositoriesForRequest; - private MavenRepository(Aether aether) { + protected MavenRepository(Aether aether) { this.aether = aether; - Settings settings = MavenSettings.getSettings(); + Settings settings = getSettings(); extraRepositories = initExtraRepositories(settings); remoteRepositoriesForRequest = initRemoteRepositoriesForRequest(settings); } + protected Settings getSettings() { + return MavenSettings.getSettings(); + } + + Collection getRemoteRepositoriesForRequest() { + return remoteRepositoriesForRequest; + } + public static synchronized MavenRepository getMavenRepository() { if (defaultMavenRepository == null) { Aether defaultAether = Aether.getAether(); @@ -96,7 +104,7 @@ private Collection initRemoteRepositoriesForRequest(Settings s private RemoteRepository resolveMirroredRepo(Settings settings, RemoteRepository repo) { for (Mirror mirror : settings.getMirrors()) { - if (isMirror(repo.getId(), mirror.getMirrorOf())) { + if (isMirror(repo, mirror.getMirrorOf())) { return setRemoteRepositoryAuthentication(settings, new RemoteRepository(mirror.getId(), mirror.getLayout(), mirror.getUrl()), mirror.getId()); @@ -105,10 +113,12 @@ private RemoteRepository resolveMirroredRepo(Settings settings, RemoteRepository return repo; } - private boolean isMirror(String repoId, String mirrorOf) { + private boolean isMirror(RemoteRepository repo, String mirrorOf) { return mirrorOf.equals("*") || - ( mirrorOf.startsWith("*") && !mirrorOf.contains("!" + repoId) ) || - ( !mirrorOf.startsWith("*") && mirrorOf.contains(repoId) ); + ( mirrorOf.equals("external:*") && !repo.getUrl().startsWith("file:") ) || + ( mirrorOf.startsWith("external:*") && !repo.getUrl().startsWith("file:") && !mirrorOf.contains("!" + repo.getId()) ) || + ( mirrorOf.startsWith("*") && !mirrorOf.contains("!" + repo.getId()) ) || + ( !mirrorOf.startsWith("*") && !mirrorOf.startsWith("external:*") && mirrorOf.contains(repo.getId()) ); } private boolean isProfileActive(Settings settings, Profile profile) { diff --git a/kie-ci/src/test/java/org/kie/scanner/MavenRepositoryTest.java b/kie-ci/src/test/java/org/kie/scanner/MavenRepositoryTest.java new file mode 100644 index 00000000000..e748570ba99 --- /dev/null +++ b/kie-ci/src/test/java/org/kie/scanner/MavenRepositoryTest.java @@ -0,0 +1,52 @@ +package org.kie.scanner; + +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.building.DefaultSettingsBuilderFactory; +import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; +import org.apache.maven.settings.building.SettingsBuilder; +import org.apache.maven.settings.building.SettingsBuildingException; +import org.junit.Test; +import org.sonatype.aether.repository.RemoteRepository; + +import java.io.File; +import java.util.Collection; + +import static org.junit.Assert.*; + +public class MavenRepositoryTest { + + @Test + public void testMirrors() { + MavenRepository repo = new MavenRepositoryMock(Aether.getAether()); + Collection remoteRepos = repo.getRemoteRepositoriesForRequest(); + assertEquals(3, remoteRepos.size()); + for (RemoteRepository remoteRepo : remoteRepos) { + assertTrue(remoteRepo.getId().equals("local") || + remoteRepo.getId().equals("qa") || + remoteRepo.getId().equals("foo")); + } + } + + public static class MavenRepositoryMock extends MavenRepository { + protected MavenRepositoryMock(Aether aether) { + super(aether); + } + + @Override + protected Settings getSettings() { + String path = getClass().getResource(".").toString().substring("file:".length()); + File testSettingsFile = new File(path + "settings_with_mirror.xml"); + assertTrue(testSettingsFile.exists()); + + SettingsBuilder settingsBuilder = new DefaultSettingsBuilderFactory().newInstance(); + DefaultSettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); + request.setUserSettingsFile( testSettingsFile ); + + try { + return settingsBuilder.build( request ).getEffectiveSettings(); + } catch ( SettingsBuildingException e ) { + throw new RuntimeException(e); + } + } + } +} diff --git a/kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml b/kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml new file mode 100644 index 00000000000..6960ca6bd25 --- /dev/null +++ b/kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml @@ -0,0 +1,67 @@ + + /home/mwinkler/QA/jenkins/WORKSPACE/business-central-maven-repo + + + + kie-wb-m2-repo + testadmin + admin1234; + + httpclient + + + true + + + + + + foo + testadmin + admin1234; + + httpclient + + + true + + + + + + + + + qa + external:*,!foo + http://nexuszzz.qa.jboss.com:8081/nexus/content/groups/public-all + + + + + + kie-wb-m2-profile + + true + + + + kie-wb-m2-repo + KIE-WB M2 Repo + http://localhost:8080/business-central/maven2 + + always + + + + foo + foo Repo + http://www.foo.org + + always + + + + + + From 68e4aeb560d8d57718e47a8bcae9a45118e981db Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 16 Jun 2014 15:04:20 +0200 Subject: [PATCH 12/76] [DROOLS-526] flush stream queue before eagerly evaluating a rule (cherry picked from commit 83f80c83f70c1d246e203cc26ef8d4d1e5b5b843) --- .../compiler/integrationtests/CepEspTest.java | 58 +++++++++++++++++++ .../org/drools/core/common/DefaultAgenda.java | 31 +++++----- .../org/drools/core/phreak/RuleExecutor.java | 8 ++- 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java index 90757aef18b..c2d5147a37c 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java @@ -80,6 +80,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import static org.hamcrest.CoreMatchers.is; import static org.mockito.Matchers.any; @@ -4982,5 +4983,62 @@ public void testTemporalOperatorWithConstantAndJoin() throws Exception { assertEquals(1, list.size()); } + @Test + public void testDynamicSalienceInStreamMode() throws Exception { + // DROOLS-526 + String drl = + "import java.util.concurrent.atomic.AtomicInteger;\n" + + "\n" + + "global AtomicInteger salience1\n" + + "global AtomicInteger salience2\n" + + "global java.util.List list\n" + + "\n" + + "declare Integer\n" + + " @role(event)\n" + + "end\n" + + "\n" + + "rule R1\n" + + "salience salience1.get()\n" + + "when\n" + + " $i : Integer()\n" + + "then\n" + + " retract($i);\n" + + " salience1.decrementAndGet();\n" + + " list.add(1);\n" + + "end \n" + + "\n" + + "rule R2\n" + + "salience salience2.get()\n" + + "when\n" + + " $i : Integer()\n" + + "then\n" + + " retract($i);\n" + + " salience2.decrementAndGet();\n" + + " list.add(2);\n" + + "end"; + + KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); + kbuilder.add( ResourceFactory.newByteArrayResource( drl.getBytes() ), ResourceType.DRL); + if ( kbuilder.hasErrors() ) { + fail( kbuilder.getErrors().toString() ); + } + + KieBaseConfiguration baseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); + baseConfig.setOption( EventProcessingOption.STREAM ); + KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( baseConfig ); + kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); + KieSession ksession = kbase.newKieSession(); + List list = new ArrayList(); + ksession.setGlobal("list", list); + ksession.setGlobal("salience1", new AtomicInteger(9)); + ksession.setGlobal("salience2", new AtomicInteger(10)); + + for (int i = 0; i < 10; i++) { + ksession.insert(i); + ksession.fireAllRules(); + } + + assertEquals(list, Arrays.asList(2, 1, 2, 1, 2, 1, 2, 1, 2, 1)); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java index 391175b1184..c2a54c94ddb 100644 --- a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java +++ b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java @@ -16,18 +16,6 @@ package org.drools.core.common; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; - import org.drools.core.RuleBaseConfiguration; import org.drools.core.WorkingMemory; import org.drools.core.impl.InternalKnowledgeBase; @@ -43,10 +31,10 @@ import org.drools.core.rule.Declaration; import org.drools.core.rule.EntryPointId; import org.drools.core.spi.Activation; -import org.drools.core.spi.InternalActivationGroup; import org.drools.core.spi.AgendaGroup; import org.drools.core.spi.ConsequenceException; import org.drools.core.spi.ConsequenceExceptionHandler; +import org.drools.core.spi.InternalActivationGroup; import org.drools.core.spi.KnowledgeHelper; import org.drools.core.spi.PropagationContext; import org.drools.core.spi.RuleFlowGroup; @@ -60,6 +48,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Rule-firing Agenda. * @@ -949,8 +949,9 @@ public int fireNextItem(final AgendaFilter filter, public void evaluateEagerList() { synchronized (eager) { while ( !eager.isEmpty() ) { - RuleAgendaItem item = eager.removeFirst(); - item.getRuleExecutor().evaluateNetwork(this.workingMemory); + RuleExecutor ruleExecutor = eager.removeFirst().getRuleExecutor(); + ruleExecutor.flushTupleQueue(); + ruleExecutor.evaluateNetwork(this.workingMemory); } } } diff --git a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java index 93daf97a625..3fd19460cef 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java +++ b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java @@ -1,7 +1,5 @@ package org.drools.core.phreak; -import java.util.Comparator; - import org.drools.core.base.SalienceInteger; import org.drools.core.common.AgendaItem; import org.drools.core.common.EventSupport; @@ -26,6 +24,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Comparator; + public class RuleExecutor { protected static transient Logger log = LoggerFactory.getLogger(RuleExecutor.class); @@ -200,6 +200,10 @@ public synchronized void reEvaluateNetwork(InternalWorkingMemory wm, LinkedList< } } + public void flushTupleQueue( ) { + flushTupleQueue( pmem.getTupleQueue() ); + } + public static void flushTupleQueue( TupleEntryQueue tupleQueue ) { if ( tupleQueue != null ) { while ( ! tupleQueue.isEmpty() ) { From f48c54676203e5a4f1c084a8f7e25463fea0d0fb Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Tue, 17 Jun 2014 12:41:56 +0100 Subject: [PATCH 13/76] DROOLS-527: IncrementalBuild Results are incorrect when DRL is completely invalid (cherry picked from commit 31dae21119f3412f581cf957f302ebaf065fcf33) --- .../IncrementalCompilationTest.java | 158 ++++++++++++------ 1 file changed, 111 insertions(+), 47 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java index 221978d24b0..8e9857ea563 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java @@ -1,11 +1,20 @@ package org.drools.compiler.integrationtests; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.drools.compiler.CommonTestMethodBase; import org.drools.compiler.Message; import org.drools.compiler.kie.builder.impl.KieContainerImpl; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.impl.KnowledgeBaseImpl; import org.drools.core.reteoo.RuleTerminalNode; +import org.junit.Ignore; import org.junit.Test; import org.kie.api.KieServices; import org.kie.api.builder.KieBuilder; @@ -23,15 +32,7 @@ import org.kie.internal.builder.IncrementalResults; import org.kie.internal.builder.InternalKieBuilder; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static java.util.Arrays.asList; +import static java.util.Arrays.*; public class IncrementalCompilationTest extends CommonTestMethodBase { @@ -102,7 +103,7 @@ private void createAndDeployAndTest( KieContainer kc, int i = 0; for ( String ruleName : ruleNames ) { - assertEquals( ruleName, i++, ((RuleImpl) rules.get( ruleName )).getLoadOrder() ); + assertEquals( ruleName, i++, ( (RuleImpl) rules.get( ruleName ) ).getLoadOrder() ); } } @@ -589,25 +590,25 @@ public void testRuleRemoval() throws Exception { assertEquals( 3, kpkg.getRules().size() ); Map rules = rulestoMap( kpkg.getRules() ); - assertNotNull(((org.drools.core.definitions.rule.impl.RuleImpl) rules.get("R1"))); - assertNotNull(((org.drools.core.definitions.rule.impl.RuleImpl) rules.get("R2"))); - assertNotNull(((org.drools.core.definitions.rule.impl.RuleImpl) rules.get("R3"))); - - RuleTerminalNode rtn1_1 = (RuleTerminalNode) ((KnowledgeBaseImpl)kc.getKieBase()).getReteooBuilder().getTerminalNodes( "R1" )[0]; - RuleTerminalNode rtn2_1 = (RuleTerminalNode) ((KnowledgeBaseImpl)kc.getKieBase()).getReteooBuilder().getTerminalNodes( "R2" )[0]; - RuleTerminalNode rtn3_1 = (RuleTerminalNode) ((KnowledgeBaseImpl)kc.getKieBase()).getReteooBuilder().getTerminalNodes( "R3" )[0]; - + assertNotNull( ( (org.drools.core.definitions.rule.impl.RuleImpl) rules.get( "R1" ) ) ); + assertNotNull( ( (org.drools.core.definitions.rule.impl.RuleImpl) rules.get( "R2" ) ) ); + assertNotNull( ( (org.drools.core.definitions.rule.impl.RuleImpl) rules.get( "R3" ) ) ); + + RuleTerminalNode rtn1_1 = (RuleTerminalNode) ( (KnowledgeBaseImpl) kc.getKieBase() ).getReteooBuilder().getTerminalNodes( "R1" )[ 0 ]; + RuleTerminalNode rtn2_1 = (RuleTerminalNode) ( (KnowledgeBaseImpl) kc.getKieBase() ).getReteooBuilder().getTerminalNodes( "R2" )[ 0 ]; + RuleTerminalNode rtn3_1 = (RuleTerminalNode) ( (KnowledgeBaseImpl) kc.getKieBase() ).getReteooBuilder().getTerminalNodes( "R3" )[ 0 ]; + // Create a new jar for version 1.1.0 ReleaseId releaseId2 = ks.newReleaseId( "org.kie", "test-upgrade", "1.1.0" ); km = createAndDeployJar( ks, releaseId2, drl1 + drl3 ); // try to update the container to version 1.1.0 - kc.updateToVersion(releaseId2); + kc.updateToVersion( releaseId2 ); + + KnowledgeBaseImpl rb_2 = ( (KnowledgeBaseImpl) kc.getKieBase() ); - KnowledgeBaseImpl rb_2 = ((KnowledgeBaseImpl) kc.getKieBase()); - - RuleTerminalNode rtn1_2 = (RuleTerminalNode) rb_2.getReteooBuilder().getTerminalNodes( "R1" )[0]; - RuleTerminalNode rtn3_2 = (RuleTerminalNode) rb_2.getReteooBuilder().getTerminalNodes( "R3" )[0]; + RuleTerminalNode rtn1_2 = (RuleTerminalNode) rb_2.getReteooBuilder().getTerminalNodes( "R1" )[ 0 ]; + RuleTerminalNode rtn3_2 = (RuleTerminalNode) rb_2.getReteooBuilder().getTerminalNodes( "R3" )[ 0 ]; assertNull( rb_2.getReteooBuilder().getTerminalNodes( "R2" ) ); assertSame( rtn3_1, rtn3_2 ); @@ -1001,35 +1002,35 @@ public void testIncrementalCompilationWithIncludes() throws Exception { // DROOLS-462 String drl1 = "global java.util.List list\n" + - "rule R1 when\n" + - " $s : String() " + - "then\n" + - " list.add( \"a\" + $s );" + - "end\n"; + "rule R1 when\n" + + " $s : String() " + + "then\n" + + " list.add( \"a\" + $s );" + + "end\n"; String drl2 = "global java.util.List list\n" + - "rule R1 when\n" + - " $s : String() " + - "then\n" + - " list.add( \"b\" + $s );" + - "end\n"; + "rule R1 when\n" + + " $s : String() " + + "then\n" + + " list.add( \"b\" + $s );" + + "end\n"; ReleaseId releaseId = KieServices.Factory.get().newReleaseId( "org.test", "test", "1.0.0-SNAPSHOT" ); KieServices ks = KieServices.Factory.get(); KieModuleModel kproj = ks.newKieModuleModel(); - KieBaseModel kieBaseModel1 = kproj.newKieBaseModel("KBase1") - .addPackage("org.pkg1"); - kieBaseModel1.newKieSessionModel("KSession1"); - KieBaseModel kieBaseModel2 = kproj.newKieBaseModel("KBase2") - .addPackage("org.pkg2") - .addInclude("KBase1"); - kieBaseModel2.newKieSessionModel("KSession2"); + KieBaseModel kieBaseModel1 = kproj.newKieBaseModel( "KBase1" ) + .addPackage( "org.pkg1" ); + kieBaseModel1.newKieSessionModel( "KSession1" ); + KieBaseModel kieBaseModel2 = kproj.newKieBaseModel( "KBase2" ) + .addPackage( "org.pkg2" ) + .addInclude( "KBase1" ); + kieBaseModel2.newKieSessionModel( "KSession2" ); KieFileSystem kfs = ks.newKieFileSystem() - .generateAndWritePomXML(releaseId) - .write("src/main/resources/KBase1/org/pkg1/r1.drl", drl1) - .writeKModuleXML(kproj.toXML()); + .generateAndWritePomXML( releaseId ) + .write( "src/main/resources/KBase1/org/pkg1/r1.drl", drl1 ) + .writeKModuleXML( kproj.toXML() ); KieBuilder kieBuilder = ks.newKieBuilder( kfs ); @@ -1039,18 +1040,18 @@ public void testIncrementalCompilationWithIncludes() throws Exception { KieContainer kc = ks.newKieContainer( releaseId ); - KieSession ksession = kc.newKieSession("KSession2"); + KieSession ksession = kc.newKieSession( "KSession2" ); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.insert( "Foo" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); - assertEquals("aFoo", list.get(0)); + assertEquals( "aFoo", list.get( 0 ) ); list.clear(); - kfs.delete("src/main/resources/KBase1/org/pkg1/r1.drl"); - kfs.write("src/main/resources/KBase1/org/pkg1/r2.drl", drl2); + kfs.delete( "src/main/resources/KBase1/org/pkg1/r1.drl" ); + kfs.write( "src/main/resources/KBase1/org/pkg1/r2.drl", drl2 ); IncrementalResults results = ( (InternalKieBuilder) kieBuilder ).incrementalBuild(); assertEquals( 0, results.getAddedMessages().size() ); @@ -1066,4 +1067,67 @@ public void testIncrementalCompilationWithIncludes() throws Exception { assertEquals( 2, list.size() ); assertTrue( list.containsAll( asList( "bBar", "bFoo" ) ) ); } + + @Test + @Ignore("https://issues.jboss.org/browse/DROOLS-527") + public void testIncrementalCompilationWithInvalidDRL() throws Exception { + String drl1 = "Smurf"; + + String drl2_1 = "package org.drools.compiler\n" + + "rule R2\n" + + "when\n" + + " $m : Mesage()\n" + + "then\n" + + "end\n"; + + String drl2_2 = "package org.drools.compiler\n" + + "rule R2\n" + + "when\n" + + " $m : Message()\n" + + "then\n" + + "end\n"; + + KieServices ks = KieServices.Factory.get(); + KieFileSystem kfs = ks.newKieFileSystem(); + + //First file contains errors + kfs.write( "src/main/resources/r1.drl", + drl1 ); + + KieBuilder kieBuilder = ks.newKieBuilder( kfs ).buildAll(); + Results results1 = kieBuilder.getResults(); + assertEquals( 2, + results1.getMessages().size() ); + + //Second file also contains errors.. expect some added messages + kfs.write( "src/main/resources/r2.drl", + drl2_1 ); + IncrementalResults results2 = ( (InternalKieBuilder) kieBuilder ).createFileSet( "src/main/resources/r2.drl" ).build(); + + assertEquals( 1, + results2.getAddedMessages().size() ); + assertEquals( 0, + results2.getRemovedMessages().size() ); + + //Correct second file... expect original errors relating to the file to be removed + kfs.write( "src/main/resources/r2.drl", + drl2_2 ); + IncrementalResults results3 = ( (InternalKieBuilder) kieBuilder ).createFileSet( "src/main/resources/r2.drl" ).build(); + + assertEquals( 0, + results3.getAddedMessages().size() ); + assertEquals( 1, + results3.getRemovedMessages().size() ); + + //Remove first file... expect related errors to be removed + kfs.delete( "src/main/resources/r1.drl" ); + IncrementalResults results4 = ( (InternalKieBuilder) kieBuilder ).createFileSet( "src/main/resources/r1.drl" ).build(); + + assertEquals( 0, + results4.getAddedMessages().size() ); + assertEquals( 1, + results4.getRemovedMessages().size() ); + + } + } From 6cee06cc4b535373d6849094e80d1f0a13a0581c Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Tue, 17 Jun 2014 17:34:35 +0100 Subject: [PATCH 14/76] BZ996944 - GDT Audit log: missing information in column update logs (cherry picked from commit e9456736958287320df28e0a1bafb4b0b5adb14a) --- .../shared/model/BaseColumnFieldDiffImpl.java | 83 ++++++++++++++----- .../dtable/shared/model/DTColumnConfig52.java | 65 +++++++++++---- 2 files changed, 111 insertions(+), 37 deletions(-) diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BaseColumnFieldDiffImpl.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BaseColumnFieldDiffImpl.java index 05227e5a8ae..32743ce9ca1 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BaseColumnFieldDiffImpl.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BaseColumnFieldDiffImpl.java @@ -19,17 +19,20 @@ import java.util.Map; public class BaseColumnFieldDiffImpl implements BaseColumnFieldDiff { + private String fieldName; private Object oldValue; private Object newValue; /** * Default no-arg constructor for errai marshalling. - * */ + */ public BaseColumnFieldDiffImpl() { } - public BaseColumnFieldDiffImpl(String fieldName, Object oldValue, Object newValue) { + public BaseColumnFieldDiffImpl( String fieldName, + Object oldValue, + Object newValue ) { this.fieldName = fieldName; this.oldValue = oldValue; this.newValue = newValue; @@ -39,7 +42,7 @@ public String getFieldName() { return fieldName; } - public void setFieldName(String fieldName) { + public void setFieldName( String fieldName ) { this.fieldName = fieldName; } @@ -47,7 +50,7 @@ public Object getOldValue() { return oldValue; } - public void setOldValue(Object oldValue) { + public void setOldValue( Object oldValue ) { this.oldValue = oldValue; } @@ -55,25 +58,35 @@ public Object getValue() { return newValue; } - public void setValue(Object newValue) { + public void setValue( Object newValue ) { this.newValue = newValue; } - public static boolean hasChanged(String fieldName, List source) { - if (fieldName == null) return false; - if (source != null && !source.isEmpty()) { - for (BaseColumnFieldDiff diffCol : source) { - if (fieldName.equals(diffCol.getFieldName())) return true; + public static boolean hasChanged( String fieldName, + List source ) { + if ( fieldName == null ) { + return false; + } + if ( source != null && !source.isEmpty() ) { + for ( BaseColumnFieldDiff diffCol : source ) { + if ( fieldName.equals( diffCol.getFieldName() ) ) { + return true; + } } } return false; } - public static BaseColumnFieldDiff getDiff(String fieldName, List source) { - if (fieldName == null) return null; - if (source != null && !source.isEmpty()) { - for (BaseColumnFieldDiff diffCol : source) { - if (fieldName.equals(diffCol.getFieldName())) return diffCol; + public static BaseColumnFieldDiff getDiff( String fieldName, + List source ) { + if ( fieldName == null ) { + return null; + } + if ( source != null && !source.isEmpty() ) { + for ( BaseColumnFieldDiff diffCol : source ) { + if ( fieldName.equals( diffCol.getFieldName() ) ) { + return diffCol; + } } } return null; @@ -81,12 +94,10 @@ public static BaseColumnFieldDiff getDiff(String fieldName, List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } List result = new ArrayList(); DTColumnConfig52 other = (DTColumnConfig52) otherColumn; // Field: hide column. if ( this.isHideColumn() != other.isHideColumn() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_HIDE_COLUMN, this.isHideColumn(), other.isHideColumn())); + result.add( new BaseColumnFieldDiffImpl( FIELD_HIDE_COLUMN, + this.isHideColumn(), + other.isHideColumn() ) ); } // Field: default value. - // NOTE: Compare using getDefaultValueAsString because then if data types differs it will appear as changed field. - // And data type can be changed due to legacy implementations (see ConditionPopup#makeDefaultValueWidget) - if ( !isEqualOrNull( this.getDefaultValueAsString(), - other.getDefaultValueAsString() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_DEFAULT_VALUE, this.getDefaultValueAsString(), other.getDefaultValueAsString())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getDefaultValue(), + other.getDefaultValue() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_DEFAULT_VALUE, + extractDefaultValue( this.getDefaultValue() ), + extractDefaultValue( other.getDefaultValue() ) ) ); } // Field: width. if ( this.getWidth() != other.getWidth() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_WIDTH, this.getWidth(), other.getWidth())); + result.add( new BaseColumnFieldDiffImpl( FIELD_WIDTH, + this.getWidth(), + other.getWidth() ) ); } // Field: header. if ( !isEqualOrNull( this.getHeader(), - other.getHeader() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_HEADER, this.getHeader(), other.getHeader())); + other.getHeader() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_HEADER, + this.getHeader(), + other.getHeader() ) ); } return result; } + private Object extractDefaultValue( final DTCellValue52 dcv ) { + switch ( dcv.getDataType() ) { + case BOOLEAN: + return dcv.getBooleanValue(); + case DATE: + return dcv.getDateValue(); + case NUMERIC: + case NUMERIC_BIGDECIMAL: + case NUMERIC_BIGINTEGER: + case NUMERIC_BYTE: + case NUMERIC_DOUBLE: + case NUMERIC_FLOAT: + case NUMERIC_INTEGER: + case NUMERIC_LONG: + case NUMERIC_SHORT: + return dcv.getNumericValue(); + default: + return dcv.getStringValue(); + } + } + // Check whether two Objects are equal or both null - public static boolean isEqualOrNull( Object s1, - Object s2 ) { - return BaseColumnFieldDiffImpl.isEqualOrNull(s1, s2); + public static boolean isEqualOrNull( final Object s1, + final Object s2 ) { + return BaseColumnFieldDiffImpl.isEqualOrNull( s1, s2 ); } public void setHideColumn( boolean hideColumn ) { From 80987402538e0ee21962b58b890d0b6fa8f48acb Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 18 Jun 2014 15:53:04 +0200 Subject: [PATCH 15/76] [DROOLS-527] attempt drl compilation even if parsing fail in order to give a complete error reporting (cherry picked from commit 789b4e2ca849166bbc1a9ae5e1dd6d089297d806) --- .../builder/impl/KnowledgeBuilderImpl.java | 5 +-- .../builder/impl/KnowledgeBuilderTest.java | 2 +- .../IncrementalCompilationTest.java | 36 ++++++++----------- .../IncrementalCompilationTest.java | 15 ++++---- 4 files changed, 24 insertions(+), 34 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java index 62f01f5d370..1175287274f 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java @@ -837,10 +837,7 @@ public void addPackage(final PackageDescr packageDescr) { void compileAllRules(PackageDescr packageDescr, PackageRegistry pkgRegistry) { pkgRegistry.setDialect(getPackageDialect(packageDescr)); - // only try to compile if there are no parse errors - if (!hasErrors()) { - compileRules(packageDescr, pkgRegistry); - } + compileRules(packageDescr, pkgRegistry); compileAll(); try { diff --git a/drools-compiler/src/test/java/org/drools/compiler/builder/impl/KnowledgeBuilderTest.java b/drools-compiler/src/test/java/org/drools/compiler/builder/impl/KnowledgeBuilderTest.java index 95ff7a4b0ea..075dd384892 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/builder/impl/KnowledgeBuilderTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/builder/impl/KnowledgeBuilderTest.java @@ -895,7 +895,7 @@ public void testDuplicateRuleNames() throws Exception { builder.addPackage( packageDescr ); - assertLength( 1, + assertLength( 2, builder.getErrors().getErrors() ); final ParserError err = (ParserError) builder.getErrors().getErrors()[0]; assertEquals( 42, diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java index 8e9857ea563..6d4f77761ed 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java @@ -1,20 +1,11 @@ package org.drools.compiler.integrationtests; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.drools.compiler.CommonTestMethodBase; import org.drools.compiler.Message; import org.drools.compiler.kie.builder.impl.KieContainerImpl; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.impl.KnowledgeBaseImpl; import org.drools.core.reteoo.RuleTerminalNode; -import org.junit.Ignore; import org.junit.Test; import org.kie.api.KieServices; import org.kie.api.builder.KieBuilder; @@ -32,7 +23,15 @@ import org.kie.internal.builder.IncrementalResults; import org.kie.internal.builder.InternalKieBuilder; -import static java.util.Arrays.*; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Arrays.asList; public class IncrementalCompilationTest extends CommonTestMethodBase { @@ -484,7 +483,7 @@ public void testIncrementalCompilationWithDuplicatedRuleInSameDRL() throws Excep .write( "src/main/resources/r1.drl", drl1 ); KieBuilder kieBuilder = ks.newKieBuilder( kfs ).buildAll(); - assertEquals( 1, kieBuilder.getResults().getMessages( org.kie.api.builder.Message.Level.ERROR ).size() ); + assertEquals( 2, kieBuilder.getResults().getMessages( org.kie.api.builder.Message.Level.ERROR ).size() ); } @Test @@ -1069,7 +1068,6 @@ public void testIncrementalCompilationWithIncludes() throws Exception { } @Test - @Ignore("https://issues.jboss.org/browse/DROOLS-527") public void testIncrementalCompilationWithInvalidDRL() throws Exception { String drl1 = "Smurf"; @@ -1091,8 +1089,7 @@ public void testIncrementalCompilationWithInvalidDRL() throws Exception { KieFileSystem kfs = ks.newKieFileSystem(); //First file contains errors - kfs.write( "src/main/resources/r1.drl", - drl1 ); + kfs.write( "src/main/resources/r1.drl", drl1 ); KieBuilder kieBuilder = ks.newKieBuilder( kfs ).buildAll(); Results results1 = kieBuilder.getResults(); @@ -1100,8 +1097,7 @@ public void testIncrementalCompilationWithInvalidDRL() throws Exception { results1.getMessages().size() ); //Second file also contains errors.. expect some added messages - kfs.write( "src/main/resources/r2.drl", - drl2_1 ); + kfs.write( "src/main/resources/r2.drl", drl2_1 ); IncrementalResults results2 = ( (InternalKieBuilder) kieBuilder ).createFileSet( "src/main/resources/r2.drl" ).build(); assertEquals( 1, @@ -1110,8 +1106,7 @@ public void testIncrementalCompilationWithInvalidDRL() throws Exception { results2.getRemovedMessages().size() ); //Correct second file... expect original errors relating to the file to be removed - kfs.write( "src/main/resources/r2.drl", - drl2_2 ); + kfs.write( "src/main/resources/r2.drl", drl2_2 ); IncrementalResults results3 = ( (InternalKieBuilder) kieBuilder ).createFileSet( "src/main/resources/r2.drl" ).build(); assertEquals( 0, @@ -1125,9 +1120,8 @@ public void testIncrementalCompilationWithInvalidDRL() throws Exception { assertEquals( 0, results4.getAddedMessages().size() ); - assertEquals( 1, + assertEquals( 2, results4.getRemovedMessages().size() ); } - -} +} \ No newline at end of file diff --git a/drools-decisiontables/src/test/java/org/drools/decisiontable/integrationtests/IncrementalCompilationTest.java b/drools-decisiontables/src/test/java/org/drools/decisiontable/integrationtests/IncrementalCompilationTest.java index 3a481fce97f..62bc8e95132 100644 --- a/drools-decisiontables/src/test/java/org/drools/decisiontable/integrationtests/IncrementalCompilationTest.java +++ b/drools-decisiontables/src/test/java/org/drools/decisiontable/integrationtests/IncrementalCompilationTest.java @@ -1,16 +1,15 @@ package org.drools.decisiontable.integrationtests; -import java.io.InputStream; - -import org.junit.Ignore; import org.junit.Test; import org.kie.api.KieServices; -import org.kie.internal.builder.IncrementalResults; -import org.kie.internal.builder.InternalKieBuilder; import org.kie.api.builder.KieBuilder; import org.kie.api.builder.KieFileSystem; +import org.kie.internal.builder.IncrementalResults; +import org.kie.internal.builder.InternalKieBuilder; + +import java.io.InputStream; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; public class IncrementalCompilationTest { @@ -37,7 +36,7 @@ public void testDuplicateXLSResources() throws Exception { KieServices.Factory.get().getResources().newInputStreamResource( in2 ) ); //Check errors on a full build - assertEquals( 1, ks.newKieBuilder( kfs ).buildAll().getResults().getMessages().size() ); + assertEquals( 2, ks.newKieBuilder( kfs ).buildAll().getResults().getMessages().size() ); } finally { if ( in1 != null ) { @@ -82,7 +81,7 @@ public void testIncrementalCompilationDuplicateXLSResources() throws Exception { assertEquals( 0, addResults.getRemovedMessages().size() ); //Check errors on a full build - assertEquals( 1, ks.newKieBuilder( kfs ).buildAll().getResults().getMessages().size() ); + assertEquals( 2, ks.newKieBuilder( kfs ).buildAll().getResults().getMessages().size() ); } finally { if ( in1 != null ) { From b1e718a2baed5f5ecb3a01ca6a997ac1d2fe3ba2 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 12 Jun 2014 11:11:34 +0200 Subject: [PATCH 16/76] [DROOLS-516] implement stream queue garbage collector (cherry picked from commit 9d12847c9a79e3ce642f248d0f7cbf2035649666) --- .../compiler/integrationtests/CepEspTest.java | 239 +++++++++++++++++- .../org/drools/core/common/DefaultAgenda.java | 77 +++++- .../drools/core/common/GarbageCollector.java | 14 + .../drools/core/common/InternalAgenda.java | 4 +- .../core/common/StreamTupleEntryQueue.java | 47 ++++ .../impl/StatefulKnowledgeSessionImpl.java | 4 +- .../org/drools/core/phreak/AddRemoveRule.java | 2 +- .../drools/core/phreak/PhreakQueryNode.java | 4 +- .../drools/core/phreak/RuleAgendaItem.java | 20 ++ .../org/drools/core/phreak/RuleExecutor.java | 167 +++++++----- .../drools/core/phreak/SegmentUtilities.java | 20 +- .../java/org/drools/core/reteoo/BetaNode.java | 50 ++-- .../core/reteoo/LeftInputAdapterNode.java | 39 ++- .../java/org/drools/core/reteoo/NotNode.java | 6 +- .../org/drools/core/reteoo/PathMemory.java | 39 +-- .../org/drools/core/reteoo/RiaPathMemory.java | 4 +- .../org/drools/core/reteoo/SegmentMemory.java | 16 +- .../org/drools/reteoo/common/ReteAgenda.java | 26 +- 18 files changed, 602 insertions(+), 176 deletions(-) create mode 100644 drools-core/src/main/java/org/drools/core/common/GarbageCollector.java create mode 100644 drools-core/src/main/java/org/drools/core/common/StreamTupleEntryQueue.java diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java index c2d5147a37c..b15a851f898 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java @@ -12,12 +12,18 @@ import org.drools.core.audit.WorkingMemoryFileLogger; import org.drools.core.base.ClassObjectType; import org.drools.core.base.evaluators.TimeIntervalParser; +import org.drools.core.common.DefaultAgenda; import org.drools.core.common.EventFactHandle; import org.drools.core.common.InternalFactHandle; +import org.drools.core.common.InternalWorkingMemory; +import org.drools.core.common.RightTupleSets; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.impl.KnowledgeBaseImpl; import org.drools.core.impl.StatefulKnowledgeSessionImpl; +import org.drools.core.reteoo.BetaMemory; +import org.drools.core.reteoo.JoinNode; import org.drools.core.reteoo.ObjectTypeNode; +import org.drools.core.reteoo.Rete; import org.drools.core.rule.EntryPointId; import org.drools.core.rule.TypeDeclaration; import org.drools.core.spi.ObjectType; @@ -4994,27 +5000,27 @@ public void testDynamicSalienceInStreamMode() throws Exception { "global java.util.List list\n" + "\n" + "declare Integer\n" + - " @role(event)\n" + + " @role(event)\n" + "end\n" + "\n" + "rule R1\n" + "salience salience1.get()\n" + "when\n" + - " $i : Integer()\n" + + " $i : Integer()\n" + "then\n" + - " retract($i);\n" + - " salience1.decrementAndGet();\n" + - " list.add(1);\n" + - "end \n" + + " retract($i);\n" + + " salience1.decrementAndGet();\n" + + " list.add(1);\n" + + "end \n" + "\n" + "rule R2\n" + "salience salience2.get()\n" + "when\n" + - " $i : Integer()\n" + + " $i : Integer()\n" + "then\n" + - " retract($i);\n" + - " salience2.decrementAndGet();\n" + - " list.add(2);\n" + + " retract($i);\n" + + " salience2.decrementAndGet();\n" + + " list.add(2);\n" + "end"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); @@ -5041,4 +5047,217 @@ public void testDynamicSalienceInStreamMode() throws Exception { assertEquals(list, Arrays.asList(2, 1, 2, 1, 2, 1, 2, 1, 2, 1)); } + + @Test + public void testRightTupleLeak() throws Exception { + // DROOLS-516 + String drl = + "declare Integer @role(event) end\n" + + "declare Long @role(event) end\n" + + "\n" + + "rule R1 when\n" + + " $long : Long()\n" + + " Integer( this > $long )\n" + + "then\n" + + "end\n" + + "\n" + + "rule R2 when\n" + + " $i : Integer()\n" + + "then\n" + + " retract( $i );\n" + + "end"; + + KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); + kbuilder.add(ResourceFactory.newByteArrayResource(drl.getBytes()), ResourceType.DRL); + if ( kbuilder.hasErrors() ) { + fail( kbuilder.getErrors().toString() ); + } + + KieBaseConfiguration baseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); + baseConfig.setOption( EventProcessingOption.STREAM ); + KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( baseConfig ); + kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); + + KieSession ksession = kbase.newKieSession(); + + for (int i = 0; i < 10; i++) { + ksession.insert(new Integer(i)); + ksession.fireAllRules(); + } + + // force gc + ((DefaultAgenda)ksession.getAgenda()).getGarbageCollector().forceGcUnlinkedRules(); + + Rete rete = ((KnowledgeBaseImpl)kbase).getRete(); + JoinNode joinNode = null; + for (ObjectTypeNode otn : rete.getObjectTypeNodes()) { + if ( Integer.class == otn.getObjectType().getValueType().getClassType() ) { + joinNode = (JoinNode)otn.getSinkPropagator().getSinks()[0]; + break; + } + } + + assertNotNull(joinNode); + InternalWorkingMemory wm = (InternalWorkingMemory)ksession; + BetaMemory memory = (BetaMemory)wm.getNodeMemory(joinNode); + assertEquals(0, memory.getSegmentMemory().getStreamQueue().size()); + + RightTupleSets stagedRightTuples = memory.getStagedRightTuples(); + assertEquals(0, stagedRightTuples.deleteSize()); + assertEquals(0, stagedRightTuples.insertSize()); + } + + @Test + public void testRightTupleLeak2() throws Exception { + // DROOLS-516 + String drl = + "declare Integer @role(event) end\n" + + "declare Long @role(event) end\n" + + "global java.util.List list\n" + + "\n" + + "rule R1 when\n" + + " $long : Long()\n" + + " $i : Integer( this > $long )\n" + + "then\n" + + " list.add($i);\n" + + "end\n" + + "\n" + + "rule R2 when\n" + + " $i : Integer( this > 3 )\n" + + "then\n" + + " retract( $i );\n" + + "end"; + + KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); + kbuilder.add(ResourceFactory.newByteArrayResource(drl.getBytes()), ResourceType.DRL); + if ( kbuilder.hasErrors() ) { + fail( kbuilder.getErrors().toString() ); + } + + KieBaseConfiguration baseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); + baseConfig.setOption( EventProcessingOption.STREAM ); + KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( baseConfig ); + kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); + + KieSession ksession = kbase.newKieSession(); + + List list = new ArrayList(); + ksession.setGlobal("list", list); + + for (int i = 0; i < 10; i++) { + ksession.insert(new Integer(i)); + ksession.fireAllRules(); + } + + // force gc + ((DefaultAgenda)ksession.getAgenda()).getGarbageCollector().forceGcUnlinkedRules(); + + Rete rete = ((KnowledgeBaseImpl)kbase).getRete(); + JoinNode joinNode = null; + for (ObjectTypeNode otn : rete.getObjectTypeNodes()) { + if ( Integer.class == otn.getObjectType().getValueType().getClassType() ) { + joinNode = (JoinNode)otn.getSinkPropagator().getSinks()[0]; + break; + } + } + + assertNotNull(joinNode); + InternalWorkingMemory wm = (InternalWorkingMemory)ksession; + BetaMemory memory = (BetaMemory)wm.getNodeMemory(joinNode); + assertEquals(0, memory.getSegmentMemory().getStreamQueue().size()); + + RightTupleSets stagedRightTuples = memory.getStagedRightTuples(); + assertEquals(0, stagedRightTuples.deleteSize()); + assertEquals(4, stagedRightTuples.insertSize()); + + ksession.insert(new Long(0)); + ksession.fireAllRules(); + + assertEquals(3, list.size()); + assertTrue(list.containsAll(Arrays.asList(1, 2, 3))); + } + + @Test + public void testRightTupleLeak3() throws Exception { + // DROOLS-516 + String drl = + "declare Integer @role(event) end\n" + + "declare Long @role(event) end\n" + + "global java.util.List list\n" + + "\n" + + "rule R1 when\n" + + " $long : Long()\n" + + " $i : Integer( this > $long )\n" + + " String()\n" + + "then\n" + + " list.add($i);\n" + + "end\n" + + "rule R2 when\n" + + " $long : Long()\n" + + " $i : Integer( this > $long )\n" + + " eval( $i % 2 == 0 )\n" + + "then\n" + + " retract($i);\n" + + "end"; + + KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); + kbuilder.add(ResourceFactory.newByteArrayResource(drl.getBytes()), ResourceType.DRL); + if ( kbuilder.hasErrors() ) { + fail( kbuilder.getErrors().toString() ); + } + + KieBaseConfiguration baseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); + baseConfig.setOption( EventProcessingOption.STREAM ); + KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( baseConfig ); + kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); + + KieSession ksession = kbase.newKieSession(); + + List list = new ArrayList(); + ksession.setGlobal("list", list); + + FactHandle sFH = ksession.insert(""); + ksession.insert(new Long(0)); + ksession.fireAllRules(); + + for (int i = 0; i < 10; i++) { + ksession.insert(new Integer(i)); + if (i == 6) { + ksession.delete(sFH); + } + } + ksession.fireAllRules(); + + // force gc + ((DefaultAgenda)ksession.getAgenda()).getGarbageCollector().forceGcUnlinkedRules(); + + Rete rete = ((KnowledgeBaseImpl)kbase).getRete(); + JoinNode joinNode = null; + for (ObjectTypeNode otn : rete.getObjectTypeNodes()) { + if ( Integer.class == otn.getObjectType().getValueType().getClassType() ) { + joinNode = (JoinNode)otn.getSinkPropagator().getSinks()[0]; + break; + } + } + + assertNotNull(joinNode); + InternalWorkingMemory wm = (InternalWorkingMemory)ksession; + BetaMemory memory = (BetaMemory)wm.getNodeMemory(joinNode); + assertEquals(0, memory.getSegmentMemory().getStreamQueue().size()); + + RightTupleSets stagedRightTuples = memory.getStagedRightTuples(); + assertEquals(4, stagedRightTuples.deleteSize()); + assertEquals(0, stagedRightTuples.insertSize()); + + ksession.insert(""); + ksession.fireAllRules(); + + assertEquals(0, stagedRightTuples.deleteSize()); + assertEquals(0, stagedRightTuples.insertSize()); + + System.out.println(list); + + assertEquals(5, list.size()); + assertTrue(list.containsAll(Arrays.asList(1, 3, 5, 7, 9))); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java index c2a54c94ddb..1def269b8c7 100644 --- a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java +++ b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java @@ -41,6 +41,7 @@ import org.drools.core.util.ClassUtils; import org.drools.core.util.StringUtils; import org.drools.core.util.index.LeftTupleList; +import org.kie.api.conf.EventProcessingOption; import org.kie.api.event.rule.MatchCancelledCause; import org.kie.api.runtime.process.ProcessInstance; import org.kie.api.runtime.rule.AgendaFilter; @@ -54,10 +55,13 @@ import java.io.ObjectOutput; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; + import java.util.concurrent.atomic.AtomicBoolean; /** @@ -90,7 +94,7 @@ public class DefaultAgenda private Map agendaGroups; - private Map activationGroups; + private Map activationGroups; private LinkedList focusStack; @@ -98,7 +102,7 @@ public class DefaultAgenda private InternalAgendaGroup main; - private LinkedList eager; + private final LinkedList eager = new LinkedList(); private AgendaGroupFactory agendaGroupFactory; @@ -109,16 +113,20 @@ public class DefaultAgenda private org.kie.api.runtime.rule.ConsequenceExceptionHandler consequenceExceptionHandler; protected AtomicBoolean halt = new AtomicBoolean( true ); - protected volatile boolean fireUntilHalt = false; + protected volatile boolean fireUntilHalt = false; protected int activationCounter; private boolean declarativeAgenda; + private boolean streamMode; + private ObjectTypeConf activationObjectTypeConf; private ActivationsFilter activationsFilter; + private GarbageCollector garbageCollector; + // ------------------------------------------------------------ // Constructors // ------------------------------------------------------------ @@ -149,7 +157,6 @@ public DefaultAgenda(InternalKnowledgeBase kBase, this.focusStack.add( this.main ); } - eager = new LinkedList(); Object object = ClassUtils.instantiateObject( kBase.getConfiguration().getConsequenceExceptionHandler(), kBase.getConfiguration().getClassLoader() ); @@ -160,6 +167,10 @@ public DefaultAgenda(InternalKnowledgeBase kBase, } this.declarativeAgenda = kBase.getConfiguration().isDeclarativeAgenda(); + this.streamMode = kBase.getConfiguration().getEventProcessingMode() == EventProcessingOption.STREAM; + if (this.streamMode) { + this.garbageCollector = new DefaultGarbageCollector(); + } } public void readExternal(ObjectInput in) throws IOException, @@ -174,6 +185,7 @@ public void readExternal(ObjectInput in) throws IOException, knowledgeHelper = (KnowledgeHelper) in.readObject(); legacyConsequenceExceptionHandler = (ConsequenceExceptionHandler) in.readObject(); declarativeAgenda = in.readBoolean(); + streamMode = in.readBoolean(); } public void writeExternal(ObjectOutput out) throws IOException { @@ -186,7 +198,8 @@ public void writeExternal(ObjectOutput out) throws IOException { out.writeObject( agendaGroupFactory ); out.writeObject( knowledgeHelper ); out.writeObject( legacyConsequenceExceptionHandler ); - out.writeBoolean( declarativeAgenda ); + out.writeBoolean(declarativeAgenda); + out.writeBoolean( streamMode ); } public RuleAgendaItem createRuleAgendaItem(final int salience, @@ -672,7 +685,7 @@ public void activateRuleFlowGroup(final InternalRuleFlowGroup group, long proces } public void deactivateRuleFlowGroup(final String name) { - deactivateRuleFlowGroup((InternalRuleFlowGroup ) getRuleFlowGroup(name)); + deactivateRuleFlowGroup((InternalRuleFlowGroup) getRuleFlowGroup(name)); } public void deactivateRuleFlowGroup(final InternalRuleFlowGroup group) { @@ -767,7 +780,7 @@ public void clear() { // reset all activation groups. for ( InternalActivationGroup group : this.activationGroups.values() ) { - group.setTriggeredForRecency( this.workingMemory.getFactHandleFactory().getRecency() ); + group.setTriggeredForRecency(this.workingMemory.getFactHandleFactory().getRecency()); group.reset(); } @@ -925,6 +938,10 @@ public int fireNextItem(final AgendaFilter filter, } if (item != null) { + if (streamMode) { + garbageCollector.remove(item); + } + localFireCount = item.getRuleExecutor().evaluateNetworkAndFire(this.workingMemory, filter, fireCount, fireLimit); if ( localFireCount == 0 ) { @@ -950,7 +967,7 @@ public void evaluateEagerList() { synchronized (eager) { while ( !eager.isEmpty() ) { RuleExecutor ruleExecutor = eager.removeFirst().getRuleExecutor(); - ruleExecutor.flushTupleQueue(); + ruleExecutor.flushTupleQueue(ruleExecutor.getPathMemory().getStreamQueue()); ruleExecutor.evaluateNetwork(this.workingMemory); } } @@ -1171,6 +1188,10 @@ public void fireUntilHalt(final AgendaFilter agendaFilter) { } } } + } else { + if (streamMode) { + garbageCollector.gcUnlinkedRules(); + } } } if ( log.isTraceEnabled() ) { @@ -1203,6 +1224,9 @@ public int fireAllRules(AgendaFilter agendaFilter, this.halt.set(true); } } + if (streamMode) { + garbageCollector.gcUnlinkedRules(); + } return fireCount; } @@ -1237,4 +1261,41 @@ public ActivationsFilter getActivationsFilter() { public KnowledgeHelper getKnowledgeHelper() { return knowledgeHelper; } + + public GarbageCollector getGarbageCollector() { + return garbageCollector; + } + + public static class DefaultGarbageCollector implements GarbageCollector { + private static final int GC_THRESHOLD = 1000; + private Set unlinked = new HashSet(); + + private volatile int deleteCounter = 0; + + public synchronized void increaseDeleteCounter() { + deleteCounter++; + } + + public synchronized void gcUnlinkedRules() { + if (deleteCounter > GC_THRESHOLD) { + forceGcUnlinkedRules(); + } + } + + public synchronized void forceGcUnlinkedRules() { + for (RuleAgendaItem item : unlinked) { + item.getRuleExecutor().gcStreamQueue(); + } + unlinked.clear(); + deleteCounter = 0; + } + + public synchronized void remove(RuleAgendaItem item) { + unlinked.remove(item); + } + + public synchronized void add(RuleAgendaItem item) { + unlinked.add(item); + } + } } diff --git a/drools-core/src/main/java/org/drools/core/common/GarbageCollector.java b/drools-core/src/main/java/org/drools/core/common/GarbageCollector.java new file mode 100644 index 00000000000..0344e059c4a --- /dev/null +++ b/drools-core/src/main/java/org/drools/core/common/GarbageCollector.java @@ -0,0 +1,14 @@ +package org.drools.core.common; + +import org.drools.core.phreak.RuleAgendaItem; + +public interface GarbageCollector { + + void increaseDeleteCounter(); + + void gcUnlinkedRules(); + void forceGcUnlinkedRules(); + + void remove(RuleAgendaItem item); + void add(RuleAgendaItem item); +} diff --git a/drools-core/src/main/java/org/drools/core/common/InternalAgenda.java b/drools-core/src/main/java/org/drools/core/common/InternalAgenda.java index da6b9386420..50e33e85cf1 100644 --- a/drools-core/src/main/java/org/drools/core/common/InternalAgenda.java +++ b/drools-core/src/main/java/org/drools/core/common/InternalAgenda.java @@ -325,5 +325,7 @@ RuleAgendaItem createRuleAgendaItem(final int salience, boolean createPostponedActivation(LeftTuple postponedTuple, PropagationContext propagationContext, InternalWorkingMemory workingMemory, TerminalNode terminalNode); - public boolean isRuleActiveInRuleFlowGroup(String ruleflowGroupName, String ruleName, long processInstanceId); + boolean isRuleActiveInRuleFlowGroup(String ruleflowGroupName, String ruleName, long processInstanceId); + + GarbageCollector getGarbageCollector(); } diff --git a/drools-core/src/main/java/org/drools/core/common/StreamTupleEntryQueue.java b/drools-core/src/main/java/org/drools/core/common/StreamTupleEntryQueue.java new file mode 100644 index 00000000000..4439b36e1b1 --- /dev/null +++ b/drools-core/src/main/java/org/drools/core/common/StreamTupleEntryQueue.java @@ -0,0 +1,47 @@ +package org.drools.core.common; + +import org.drools.core.phreak.TupleEntry; + +import java.util.concurrent.atomic.AtomicInteger; + +public class StreamTupleEntryQueue { + private final TupleEntryQueue queue = new TupleEntryQueueImpl(); + + private final AtomicInteger insertCounter = new AtomicInteger(0); + private final AtomicInteger updateCounter = new AtomicInteger(0); + private final AtomicInteger deleteCounter = new AtomicInteger(0); + + public TupleEntry peek() { + return queue.peek(); + } + + public boolean addInsert(TupleEntry entry) { + queue.add(entry); + return insertCounter.getAndIncrement() == 0; + } + + public boolean addUpdate(TupleEntry entry) { + queue.add(entry); + return updateCounter.getAndIncrement() == 0; + } + + public boolean addDelete(TupleEntry entry) { + queue.add(entry); + return deleteCounter.getAndIncrement() == 0; + } + + public int size() { + return queue.size(); + } + + public boolean isEmpty() { + return queue.isEmpty(); + } + + public synchronized TupleEntryQueue takeAllForFlushing() { + insertCounter.set(0); + updateCounter.set(0); + deleteCounter.set(0); + return queue.takeAll(); + } +} \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java b/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java index 8633e043426..acc88b20a51 100644 --- a/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java +++ b/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java @@ -840,8 +840,8 @@ protected BaseNode[] evalQuery(String queryName, DroolsQuery queryObject, Intern LeftInputAdapterNode.doInsertObject( handle, pCtx, lian, this, lmem, false, queryObject.isOpen() ); RuleBaseConfiguration conf = this.kBase.getConfiguration(); - if( conf.isPhreakEnabled() && lmem.getSegmentMemory().getTupleQueue() != null ) { - RuleExecutor.flushTupleQueue(lmem.getSegmentMemory().getTupleQueue()); + if ( conf.isPhreakEnabled() ) { + RuleExecutor.flushTupleQueue(lmem.getSegmentMemory().getStreamQueue()); } List pmems = lmem.getSegmentMemory().getPathMemories(); diff --git a/drools-core/src/main/java/org/drools/core/phreak/AddRemoveRule.java b/drools-core/src/main/java/org/drools/core/phreak/AddRemoveRule.java index e92a80c271d..885d4cf6ceb 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/AddRemoveRule.java +++ b/drools-core/src/main/java/org/drools/core/phreak/AddRemoveRule.java @@ -894,7 +894,7 @@ public static LeftTupleSource getNetworkSplitPoint(TerminalNode tn) { public static SegmentMemory splitSegment(SegmentMemory sm1, LeftTupleSource splitNode) { // create new segment, starting after split - SegmentMemory sm2 = new SegmentMemory(splitNode.getSinkPropagator().getFirstLeftTupleSink(), sm1.getTupleQueue() ); // we know there is only one sink + SegmentMemory sm2 = new SegmentMemory(splitNode.getSinkPropagator().getFirstLeftTupleSink(), sm1.getStreamQueue() ); // we know there is only one sink if ( sm1.getFirst() != null ) { for ( SegmentMemory sm = sm1.getFirst(); sm != null;) { diff --git a/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java b/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java index c2eea90d9b6..0a7d86aa64c 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java +++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java @@ -184,9 +184,7 @@ public void doLeftDeletes(QueryElementNodeMemory qmem, } public void flushTupleQuery( LiaNodeMemory lm, InternalWorkingMemory wm ) { - if ( lm.getSegmentMemory().getTupleQueue() != null ) { - RuleExecutor.flushTupleQueue( lm.getSegmentMemory().getTupleQueue() ); - } + RuleExecutor.flushTupleQueue( lm.getSegmentMemory().getStreamQueue() ); } } diff --git a/drools-core/src/main/java/org/drools/core/phreak/RuleAgendaItem.java b/drools-core/src/main/java/org/drools/core/phreak/RuleAgendaItem.java index bd218e80203..581cde7042c 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/RuleAgendaItem.java +++ b/drools-core/src/main/java/org/drools/core/phreak/RuleAgendaItem.java @@ -74,4 +74,24 @@ public void nullPrevNext() { previous = null; next = null; } + + @Override + public boolean equals(final Object object) { + if (object == this) { + return true; + } + + return object instanceof RuleAgendaItem && getRule().equals(((RuleAgendaItem) object).getRule()); + } + + /** + * Return the hashCode of the + * TupleKey as the hashCode of the AgendaItem + * + * @return + */ + @Override + public int hashCode() { + return getRule().hashCode(); + } } diff --git a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java index 3fd19460cef..3c3b0f5e899 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java +++ b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java @@ -6,11 +6,13 @@ import org.drools.core.common.InternalAgenda; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.LeftTupleSets; +import org.drools.core.common.StreamTupleEntryQueue; import org.drools.core.common.TupleEntryQueue; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.reteoo.BetaMemory; import org.drools.core.reteoo.LeftTuple; import org.drools.core.reteoo.PathMemory; +import org.drools.core.reteoo.RightTuple; import org.drools.core.reteoo.RuleTerminalNode; import org.drools.core.reteoo.RuleTerminalNodeLeftTuple; import org.drools.core.reteoo.SegmentMemory; @@ -25,6 +27,10 @@ import org.slf4j.LoggerFactory; import java.util.Comparator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; public class RuleExecutor { @@ -50,6 +56,23 @@ public RuleExecutor(final PathMemory pmem, } } + public synchronized void gcStreamQueue() { + List nonNormalizedDeletes = flushStreamQueue(); + for (TupleEntry tupleEntry : nonNormalizedDeletes) { + if (tupleEntry.getLeftTuple() != null) { + LeftTuple leftTuple = tupleEntry.getLeftTuple(); + if (leftTuple.getMemory() != null) { + leftTuple.getMemory().remove(leftTuple); + } + } else { + RightTuple rightTuple = tupleEntry.getRightTuple(); + if (rightTuple.getMemory() != null) { + rightTuple.getMemory().remove(rightTuple); + } + } + } + } + public synchronized void evaluateNetwork(InternalWorkingMemory wm) { NETWORK_EVALUATOR.evaluateNetwork(pmem, null, this, wm); setDirty(false); @@ -185,9 +208,9 @@ public void removeRuleAgendaItemWhenEmpty(InternalWorkingMemory wm) { } public synchronized void reEvaluateNetwork(InternalWorkingMemory wm, LinkedList outerStack, boolean fireUntilHalt) { - if (isDirty() || (pmem.getTupleQueue() != null && !pmem.getTupleQueue().isEmpty())) { + if (isDirty() || (pmem.getStreamQueue() != null && !pmem.getStreamQueue().isEmpty())) { setDirty(false); - TupleEntryQueue queue = pmem.getTupleQueue() != null ? pmem.getTupleQueue().takeAll() : null; + TupleEntryQueue queue = pmem.getStreamQueue() != null ? pmem.getStreamQueue().takeAllForFlushing() : null; if ( queue == null || queue.isEmpty() ) { NETWORK_EVALUATOR.evaluateNetwork(pmem, outerStack, this, wm); @@ -200,80 +223,94 @@ public synchronized void reEvaluateNetwork(InternalWorkingMemory wm, LinkedList< } } - public void flushTupleQueue( ) { - flushTupleQueue( pmem.getTupleQueue() ); - } + private static void removeQueuedTupleEntry( TupleEntryQueue tupleQueue ) { + TupleEntry tupleEntry = tupleQueue.remove(); + PropagationContext originalPctx = tupleEntry.getPropagationContext(); - public static void flushTupleQueue( TupleEntryQueue tupleQueue ) { - if ( tupleQueue != null ) { - while ( ! tupleQueue.isEmpty() ) { - removeQueuedTupleEntry( tupleQueue ); + while (true) { + processStreamTupleEntry(tupleQueue, tupleEntry); + if (tupleQueue.isEmpty()) { + return; } + tupleEntry = tupleQueue.peek(); + PropagationContext pctx = tupleEntry.getPropagationContext(); + + // repeat if either the pctx number is the same, or the event time is the same or before + if (pctx.getPropagationNumber() != originalPctx.getPropagationNumber()) { + break; + } + tupleEntry = tupleQueue.remove(); } } - public static void removeQueuedTupleEntry( TupleEntryQueue tupleQueue ) { - TupleEntry tupleEntry = tupleQueue.remove(); - PropagationContext originalPctx = tupleEntry.getPropagationContext(); - - boolean repeat = true; - while (repeat) { - if (log.isTraceEnabled()) { - log.trace("Stream removed entry {} {} size {}", System.identityHashCode(tupleQueue), tupleEntry, tupleQueue.size()); + private List flushStreamQueue() { + TupleEntryQueue tupleQueue = pmem.getStreamQueue().takeAllForFlushing(); + if (tupleQueue == null || tupleQueue.isEmpty()) { + return Collections.emptyList(); + } + List nonNormalizedDeletes = new ArrayList(); + while (!tupleQueue.isEmpty()) { + TupleEntry tupleEntry = tupleQueue.remove(); + if ( processStreamTupleEntry( tupleQueue, tupleEntry ) ) { + nonNormalizedDeletes.add(tupleEntry); } - if (tupleEntry.getLeftTuple() != null) { - SegmentMemory sm = tupleEntry.getNodeMemory().getSegmentMemory(); - LeftTupleSets tuples = sm.getStagedLeftTuples(); - tupleEntry.getLeftTuple().setPropagationContext(tupleEntry.getPropagationContext()); - switch (tupleEntry.getPropagationType()) { - case PropagationContext.INSERTION: - case PropagationContext.RULE_ADDITION: - tuples.addInsert(tupleEntry.getLeftTuple()); - break; - case PropagationContext.MODIFICATION: - tuples.addUpdate(tupleEntry.getLeftTuple()); - break; - case PropagationContext.DELETION: - case PropagationContext.EXPIRATION: - case PropagationContext.RULE_REMOVAL: - tuples.addDelete(tupleEntry.getLeftTuple()); - break; - } - } else { - BetaMemory bm = (BetaMemory) tupleEntry.getNodeMemory(); - tupleEntry.getRightTuple().setPropagationContext(tupleEntry.getPropagationContext()); - switch (tupleEntry.getPropagationType()) { - case PropagationContext.INSERTION: - case PropagationContext.RULE_ADDITION: - bm.getStagedRightTuples().addInsert(tupleEntry.getRightTuple()); - break; - case PropagationContext.MODIFICATION: - bm.getStagedRightTuples().addUpdate(tupleEntry.getRightTuple()); - break; - case PropagationContext.DELETION: - case PropagationContext.EXPIRATION: - case PropagationContext.RULE_REMOVAL: - bm.getStagedRightTuples().addDelete(tupleEntry.getRightTuple()); - break; - } + } + return nonNormalizedDeletes; + } + + public static void flushTupleQueue( StreamTupleEntryQueue streamQueue ) { + if ( streamQueue != null ) { + TupleEntryQueue tupleQueue = streamQueue.takeAllForFlushing(); + while (!tupleQueue.isEmpty()) { + processStreamTupleEntry( tupleQueue, tupleQueue.remove() ); } - if (!tupleQueue.isEmpty()) { - tupleEntry = tupleQueue.peek(); - PropagationContext pctx = tupleEntry.getPropagationContext(); + } + } - // repeat if either the pctx number is the same, or the event time is the same or before - if (pctx.getPropagationNumber() == originalPctx.getPropagationNumber()) { - repeat = true; - } else { - repeat = false; - } - } else { - repeat = false; + private static boolean processStreamTupleEntry(TupleEntryQueue tupleQueue, TupleEntry tupleEntry) { + boolean isNonNormalizedDelete = false; + if (log.isTraceEnabled()) { + log.trace("Stream removed entry {} {} size {}", System.identityHashCode(tupleQueue), tupleEntry, tupleQueue.size()); + } + if (tupleEntry.getLeftTuple() != null) { + SegmentMemory sm = tupleEntry.getNodeMemory().getSegmentMemory(); + LeftTupleSets tuples = sm.getStagedLeftTuples(); + tupleEntry.getLeftTuple().setPropagationContext(tupleEntry.getPropagationContext()); + switch (tupleEntry.getPropagationType()) { + case PropagationContext.INSERTION: + case PropagationContext.RULE_ADDITION: + tuples.addInsert(tupleEntry.getLeftTuple()); + break; + case PropagationContext.MODIFICATION: + tuples.addUpdate(tupleEntry.getLeftTuple()); + break; + case PropagationContext.DELETION: + case PropagationContext.EXPIRATION: + case PropagationContext.RULE_REMOVAL: + isNonNormalizedDelete = tupleEntry.getLeftTuple().getStagedType() == LeftTuple.NONE; + tuples.addDelete(tupleEntry.getLeftTuple()); + break; } - if (repeat) { - tupleEntry = tupleQueue.remove(); + } else { + BetaMemory bm = (BetaMemory) tupleEntry.getNodeMemory(); + tupleEntry.getRightTuple().setPropagationContext(tupleEntry.getPropagationContext()); + switch (tupleEntry.getPropagationType()) { + case PropagationContext.INSERTION: + case PropagationContext.RULE_ADDITION: + bm.getStagedRightTuples().addInsert(tupleEntry.getRightTuple()); + break; + case PropagationContext.MODIFICATION: + bm.getStagedRightTuples().addUpdate(tupleEntry.getRightTuple()); + break; + case PropagationContext.DELETION: + case PropagationContext.EXPIRATION: + case PropagationContext.RULE_REMOVAL: + isNonNormalizedDelete = tupleEntry.getRightTuple().getStagedType() == LeftTuple.NONE; + bm.getStagedRightTuples().addDelete(tupleEntry.getRightTuple()); + break; } } + return isNonNormalizedDelete; } public RuleAgendaItem getRuleAgendaItem() { diff --git a/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java b/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java index 6ff05709f05..d999c62a20f 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java +++ b/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java @@ -4,7 +4,7 @@ import org.drools.core.common.Memory; import org.drools.core.common.MemoryFactory; import org.drools.core.common.NetworkNode; -import org.drools.core.common.TupleEntryQueue; +import org.drools.core.common.StreamTupleEntryQueue; import org.drools.core.common.SynchronizedLeftTupleSets; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.impl.KnowledgeBaseImpl; @@ -99,11 +99,11 @@ public static synchronized SegmentMemory createSegmentMemory(LeftTupleSource tu while (true) { nodeTypesInSegment = updateNodeTypesMask(tupleSource, nodeTypesInSegment); - if ( tupleSource.isStreamMode() && smem.getTupleQueue() == null ) { + if ( tupleSource.isStreamMode() && smem.getStreamQueue() == null ) { // need to make sure there is one Queue, for the rule, when a stream mode node is found. - TupleEntryQueue queue = initAndGetTupleQueue(tupleSource, wm); - smem.setTupleQueue( queue ); + StreamTupleEntryQueue queue = initAndGetTupleQueue(tupleSource, wm); + smem.setStreamQueue( queue ); } if (NodeTypeEnums.isBetaNode(tupleSource)) { allLinkedTestMask = processBetaNode(tupleSource, wm, smem, nodePosMask, allLinkedTestMask, updateNodeBit); @@ -435,7 +435,7 @@ private static int updateRiaAndTerminalMemory( LeftTupleSource lt, PathMemory pmem = (PathMemory) wm.getNodeMemory((MemoryFactory) sink); smem.getPathMemories().add(pmem); pmem.getSegmentMemories()[smem.getPos()] = smem; - smem.setTupleQueue( pmem.getTupleQueue() ); + smem.setStreamQueue( pmem.getStreamQueue() ); if (smem.isSegmentLinked()) { // not's can cause segments to be linked, and the rules need to be notified for evaluation smem.notifyRuleLinkSegment(wm); @@ -464,7 +464,7 @@ private static void checkEagerSegmentCreation(LeftTupleSource lt, InternalWorkin } } - public static TupleEntryQueue initAndGetTupleQueue(NetworkNode node, InternalWorkingMemory wm) { + public static StreamTupleEntryQueue initAndGetTupleQueue(NetworkNode node, InternalWorkingMemory wm) { // get's or initializes the queue, if it does not exist. It recurse to the outer most PathMemory // and then trickle the Queue back up to the inner PathMememories LeftTupleSink sink = null; @@ -478,13 +478,13 @@ public static TupleEntryQueue initAndGetTupleQueue(NetworkNode node, InternalWor sink = (LeftTupleSink)node; } - TupleEntryQueue queue = null; + StreamTupleEntryQueue queue = null; if (NodeTypeEnums.RightInputAdaterNode == sink.getType()) { RightInputAdapterNode rian = (RightInputAdapterNode) sink; RiaNodeMemory riaMem = (RiaNodeMemory) wm.getNodeMemory((MemoryFactory)sink); RiaPathMemory pmem = riaMem.getRiaPathMemory(); - queue = pmem.getTupleQueue(); + queue = pmem.getStreamQueue(); if ( queue == null ) { ObjectSink[] nodes = rian.getSinkPropagator().getSinks(); // iterate the first child sink, we only need the first, as all reach the same outer rtn @@ -492,10 +492,10 @@ public static TupleEntryQueue initAndGetTupleQueue(NetworkNode node, InternalWor } } else if (NodeTypeEnums.isTerminalNode(sink)) { PathMemory pmem = (PathMemory) wm.getNodeMemory((MemoryFactory) sink); - queue = pmem.getTupleQueue(); + queue = pmem.getStreamQueue(); if ( queue == null ) { pmem.initQueue(); - queue = pmem.getTupleQueue(); + queue = pmem.getStreamQueue(); } } return queue; diff --git a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java index 027f272e3b6..802ce047b6b 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java @@ -21,6 +21,8 @@ import org.drools.core.common.BetaConstraints; import org.drools.core.common.DoubleBetaConstraints; import org.drools.core.common.DoubleNonIndexSkipBetaConstraints; +import org.drools.core.common.GarbageCollector; +import org.drools.core.common.InternalAgenda; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.Memory; @@ -127,11 +129,7 @@ public BetaNode() { setLeftTupleSource(leftInput); this.rightInput = rightInput; - if (NodeTypeEnums.RightInputAdaterNode == rightInput.getType()) { - rightInputIsRiaNode = true; - } else { - rightInputIsRiaNode = false; - } + rightInputIsRiaNode = NodeTypeEnums.RightInputAdaterNode == rightInput.getType(); setConstraints(constraints); @@ -230,11 +228,7 @@ public void readExternal(ObjectInput in) throws IOException, rightListenedProperties = (List) in.readObject(); setUnificationJoin(); super.readExternal( in ); - if ( NodeTypeEnums.RightInputAdaterNode == rightInput.getType() ) { - rightInputIsRiaNode = true; - } else { - rightInputIsRiaNode = false; - } + rightInputIsRiaNode = NodeTypeEnums.RightInputAdaterNode == rightInput.getType(); } public void writeExternal(ObjectOutput out) throws IOException { @@ -254,8 +248,8 @@ public void writeExternal(ObjectOutput out) throws IOException { out.writeLong( rightDeclaredMask ); out.writeLong( rightInferredMask ); out.writeLong( rightNegativeMask ); - out.writeObject( leftListenedProperties ); - out.writeObject( rightListenedProperties ); + out.writeObject(leftListenedProperties); + out.writeObject(rightListenedProperties); super.writeExternal( out ); } @@ -291,9 +285,9 @@ public void assertObject( final InternalFactHandle factHandle, boolean stagedInsertWasEmpty = false; if ( streamMode ) { int propagationType = pctx.getType() == PropagationContext.MODIFICATION ? PropagationContext.INSERTION : pctx.getType(); - stagedInsertWasEmpty = memory.getSegmentMemory().getTupleQueue().add(new RightTupleEntry(rightTuple, pctx, memory, propagationType)); + stagedInsertWasEmpty = memory.getSegmentMemory().getStreamQueue().addInsert(new RightTupleEntry(rightTuple, pctx, memory, propagationType)); if ( log.isTraceEnabled() ) { - log.trace( "JoinNode insert queue={} size={} pctx={} lt={}", System.identityHashCode( memory.getSegmentMemory().getTupleQueue() ), memory.getSegmentMemory().getTupleQueue().size(), PhreakPropagationContext.intEnumToString(pctx), rightTuple ); + log.trace( "JoinNode insert queue={} size={} pctx={} lt={}", System.identityHashCode( memory.getSegmentMemory().getStreamQueue() ), memory.getSegmentMemory().getStreamQueue().size(), PhreakPropagationContext.intEnumToString(pctx), rightTuple ); } } else { stagedInsertWasEmpty = memory.getStagedRightTuples().addInsert(rightTuple); @@ -320,7 +314,7 @@ public void modifyObject(InternalFactHandle factHandle, ModifyPreviousTuples mod // if the peek is for a different OTN we assume that it is after the current one and then this is an assert while ( rightTuple != null && - (( BetaNode ) rightTuple.getRightTupleSink()).getRightInputOtnId().before( getRightInputOtnId() ) ) { + rightTuple.getRightTupleSink().getRightInputOtnId().before(getRightInputOtnId()) ) { modifyPreviousTuples.removeRightTuple(); // we skipped this node, due to alpha hashing, so retract now @@ -330,7 +324,7 @@ public void modifyObject(InternalFactHandle factHandle, ModifyPreviousTuples mod rightTuple = modifyPreviousTuples.peekRightTuple(); } - if ( rightTuple != null && (( BetaNode ) rightTuple.getRightTupleSink()).getRightInputOtnId().equals(getRightInputOtnId()) ) { + if ( rightTuple != null && rightTuple.getRightTupleSink().getRightInputOtnId().equals(getRightInputOtnId()) ) { modifyPreviousTuples.removeRightTuple(); rightTuple.reAdd(); if ( intersect( context.getModificationMask(), getRightInferredMask() ) ) { @@ -358,19 +352,30 @@ public void doDeleteRightTuple(final RightTuple rightTuple, boolean stagedDeleteWasEmpty = false; if ( isStreamMode() ) { - stagedDeleteWasEmpty = memory.getSegmentMemory().getTupleQueue().isEmpty(); PropagationContext pctx = rightTuple.getPropagationContext(); int propagationType = pctx.getType() == PropagationContext.MODIFICATION ? PropagationContext.DELETION : pctx.getType(); - memory.getSegmentMemory().getTupleQueue().add(new RightTupleEntry(rightTuple, pctx, memory, propagationType)); + stagedDeleteWasEmpty = memory.getSegmentMemory().getStreamQueue().addDelete(new RightTupleEntry(rightTuple, pctx, memory, propagationType)); if ( log.isTraceEnabled() ) { - log.trace( "{} delete queue={} size={} pctx={} lt={}", getClass().getSimpleName(), System.identityHashCode( memory.getSegmentMemory().getTupleQueue() ), memory.getSegmentMemory().getTupleQueue().size(), PhreakPropagationContext.intEnumToString(rightTuple.getPropagationContext()), rightTuple ); + log.trace( "{} delete queue={} size={} pctx={} lt={}", getClass().getSimpleName(), System.identityHashCode( memory.getSegmentMemory().getStreamQueue() ), memory.getSegmentMemory().getStreamQueue().size(), PhreakPropagationContext.intEnumToString(rightTuple.getPropagationContext()), rightTuple ); + } + + if (stagedDeleteWasEmpty && !memory.getSegmentMemory().isSegmentLinked()) { + GarbageCollector garbageCollector = ((InternalAgenda)wm.getAgenda()).getGarbageCollector(); + synchronized (garbageCollector) { + for (PathMemory pmem : memory.getSegmentMemory().getPathMemories()) { + if (pmem.getNodeType() == NodeTypeEnums.RuleTerminalNode) { + garbageCollector.add(pmem.getOrCreateRuleAgendaItem(wm)); + } + } + garbageCollector.increaseDeleteCounter(); + } } } else { - stagedDeleteWasEmpty = stagedRightTuples.addDelete( rightTuple ); + stagedDeleteWasEmpty = stagedRightTuples.addDelete(rightTuple); } if ( memory.getAndDecCounter() == 1 ) { - memory.unlinkNode( wm ); + memory.unlinkNode(wm); } else if ( stagedDeleteWasEmpty ) { // nothing staged before, notify rule, so it can evaluate network memory.setNodeDirty( wm ); @@ -385,9 +390,8 @@ public void doUpdateRightTuple(final RightTuple rightTuple, boolean stagedUpdateWasEmpty = false; if ( streamMode ) { - stagedUpdateWasEmpty = memory.getSegmentMemory().getTupleQueue().isEmpty(); PropagationContext pctx = rightTuple.getPropagationContext(); - memory.getSegmentMemory().getTupleQueue().add(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); + stagedUpdateWasEmpty = memory.getSegmentMemory().getStreamQueue().addUpdate(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); } else { stagedUpdateWasEmpty = stagedRightTuples.addUpdate( rightTuple ); } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java index f50d892a21a..d0179eb8597 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java @@ -16,17 +16,6 @@ package org.drools.core.reteoo; -import static org.drools.core.reteoo.PropertySpecificUtil.calculatePositiveMask; -import static org.drools.core.reteoo.PropertySpecificUtil.getSettableProperties; -import static org.drools.core.reteoo.PropertySpecificUtil.isPropertyReactive; -import static org.drools.core.util.BitMaskUtil.intersect; - -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.Deque; -import java.util.Map; - import org.drools.core.RuleBaseConfiguration; import org.drools.core.base.ClassObjectType; import org.drools.core.common.BaseNode; @@ -55,6 +44,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Deque; +import java.util.Map; + +import static org.drools.core.reteoo.PropertySpecificUtil.*; +import static org.drools.core.util.BitMaskUtil.intersect; + /** * All asserting Facts must propagated into the right ObjectSink side of a BetaNode, if this is the first Pattern * then there are no BetaNodes to propagate to. LeftInputAdapter is used to adapt an ObjectSink propagation into a @@ -264,13 +262,12 @@ private static void doInsertSegmentMemory(PropagationContext pctx, InternalWorki boolean stagedInsertWasEmpty = false; // mask check is necessary if insert is a result of a modify - if ( liaNode.isStreamMode() && sm.getTupleQueue() != null ) { - stagedInsertWasEmpty = sm.getTupleQueue().isEmpty(); + if ( liaNode.isStreamMode() && sm.getStreamQueue() != null ) { int propagationType = pctx.getType() == PropagationContext.MODIFICATION ? PropagationContext.INSERTION : pctx.getType(); - sm.getTupleQueue().add(new LeftTupleEntry(leftTuple, pctx, sm.getNodeMemories().getFirst(), propagationType)); + stagedInsertWasEmpty = sm.getStreamQueue().addInsert(new LeftTupleEntry(leftTuple, pctx, sm.getNodeMemories().getFirst(), propagationType)); if ( log.isTraceEnabled() ) { - log.trace( "LeftInputAdapterNode insert size={} queue={} pctx={} lt={}", System.identityHashCode( sm.getTupleQueue() ), sm.getTupleQueue().size(), PhreakPropagationContext.intEnumToString(pctx), leftTuple); + log.trace( "LeftInputAdapterNode insert size={} queue={} pctx={} lt={}", System.identityHashCode( sm.getStreamQueue() ), sm.getStreamQueue().size(), PhreakPropagationContext.intEnumToString(pctx), leftTuple); } } else { stagedInsertWasEmpty = sm.getStagedLeftTuples().addInsert( leftTuple ); @@ -328,12 +325,11 @@ private static void doDeleteSegmentMemory(LeftTuple leftTuple, PropagationContex leftTuple.setPropagationContext( pctx ); boolean stagedDeleteWasEmpty = false; - if ( ((BaseNode)sm.getRootNode()).isStreamMode() && sm.getTupleQueue() != null ) { - stagedDeleteWasEmpty = sm.getTupleQueue().isEmpty(); + if ( ((BaseNode)sm.getRootNode()).isStreamMode() && sm.getStreamQueue() != null ) { int propagationType = pctx.getType() == PropagationContext.MODIFICATION ? PropagationContext.DELETION : pctx.getType(); - sm.getTupleQueue().add(new LeftTupleEntry(leftTuple, pctx, sm.getNodeMemories().getFirst(), propagationType)); + stagedDeleteWasEmpty = sm.getStreamQueue().addDelete(new LeftTupleEntry(leftTuple, pctx, sm.getNodeMemories().getFirst(), propagationType)); if ( log.isTraceEnabled() ) { - log.trace( "LeftInputAdapterNode delete size={} queue={} pctx={} lt={}", System.identityHashCode( sm.getTupleQueue() ), sm.getTupleQueue().size(), PhreakPropagationContext.intEnumToString(pctx), leftTuple ); + log.trace( "LeftInputAdapterNode delete size={} queue={} pctx={} lt={}", System.identityHashCode( sm.getStreamQueue() ), sm.getStreamQueue().size(), PhreakPropagationContext.intEnumToString(pctx), leftTuple ); } } else { stagedDeleteWasEmpty = leftTuples.addDelete(leftTuple); @@ -388,9 +384,8 @@ private static void doUpdateSegmentMemory(LeftTuple leftTuple, PropagationContex // if LeftTuple is already staged, leave it there leftTuple.setPropagationContext( pctx ); boolean stagedUpdateWasEmpty = false; - if ( ((BaseNode)sm.getRootNode()).isStreamMode() && sm.getTupleQueue() != null ) { - stagedUpdateWasEmpty = sm.getTupleQueue().isEmpty(); - sm.getTupleQueue().add(new LeftTupleEntry(leftTuple, pctx, sm.getNodeMemories().getFirst(), pctx.getType())); + if ( ((BaseNode)sm.getRootNode()).isStreamMode() && sm.getStreamQueue() != null ) { + stagedUpdateWasEmpty = sm.getStreamQueue().addUpdate(new LeftTupleEntry(leftTuple, pctx, sm.getNodeMemories().getFirst(), pctx.getType())); } else { stagedUpdateWasEmpty = leftTuples.addUpdate(leftTuple); } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java b/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java index 92a0f5b72eb..300aa4d2c6d 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java @@ -151,8 +151,7 @@ public void assertObject( final InternalFactHandle factHandle, // This is because we need the first RightTuple to link with it's blocked boolean stagedInsertWasEmpty = false; if ( streamMode ) { - stagedInsertWasEmpty = memory.getSegmentMemory().getTupleQueue().isEmpty(); - memory.getSegmentMemory().getTupleQueue().add(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); + stagedInsertWasEmpty = memory.getSegmentMemory().getStreamQueue().addInsert(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); //log.trace( "NotNode insert queue={} size={} lt={}", System.identityHashCode( memory.getSegmentMemory().getTupleQueue() ), memory.getSegmentMemory().getTupleQueue().size(), rightTuple ); } else { stagedInsertWasEmpty = memory.getStagedRightTuples().addInsert( rightTuple ); @@ -184,8 +183,7 @@ public void doDeleteRightTuple(final RightTuple rightTuple, boolean stagedDeleteWasEmpty = false; if ( streamMode ) { PropagationContext pctx = rightTuple.getPropagationContext(); - stagedDeleteWasEmpty = memory.getSegmentMemory().getTupleQueue().isEmpty(); - memory.getSegmentMemory().getTupleQueue().add(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); + stagedDeleteWasEmpty = memory.getSegmentMemory().getStreamQueue().addDelete(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); //log.trace( "NotNode delete queue={} size={} lt={}", System.identityHashCode( memory.getSegmentMemory().getTupleQueue() ), memory.getSegmentMemory().getTupleQueue().size(), rightTuple ); } else { stagedDeleteWasEmpty = stagedRightTuples.addDelete( rightTuple ); diff --git a/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java index a6a11399ce0..30df768ccc8 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java @@ -7,8 +7,7 @@ import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.Memory; import org.drools.core.common.NetworkNode; -import org.drools.core.common.TupleEntryQueue; -import org.drools.core.common.TupleEntryQueueImpl; +import org.drools.core.common.StreamTupleEntryQueue; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.phreak.RuleAgendaItem; import org.drools.core.util.AbstractBaseLinkedListNode; @@ -26,7 +25,7 @@ public class PathMemory extends AbstractBaseLinkedListNode private volatile RuleAgendaItem agendaItem; private SegmentMemory[] segmentMemories; private SegmentMemory segmentMemory; - protected TupleEntryQueue queue; + protected StreamTupleEntryQueue queue; public PathMemory(NetworkNode networkNode) { this.networkNode = networkNode; @@ -34,10 +33,10 @@ public PathMemory(NetworkNode networkNode) { } public void initQueue() { - this.queue = new TupleEntryQueueImpl(); + this.queue = new StreamTupleEntryQueue(); } - public TupleEntryQueue getTupleQueue() { + public StreamTupleEntryQueue getStreamQueue() { return queue; } @@ -89,32 +88,40 @@ public void linkSegment(long mask, } } - public synchronized void doLinkRule(InternalWorkingMemory wm) { + public boolean hasAgendaItem() { + return agendaItem != null; + } + + public synchronized RuleAgendaItem getOrCreateRuleAgendaItem(InternalWorkingMemory wm) { + ensureAgendaItemCreated(wm); + return agendaItem; + } + + private TerminalNode ensureAgendaItemCreated(InternalWorkingMemory wm) { TerminalNode rtn = (TerminalNode) getNetworkNode(); - if (log.isTraceEnabled()) { - log.trace(" LinkRule name={}", rtn.getRule().getName()); - } if (agendaItem == null) { int salience = ( rtn.getRule().getSalience() instanceof MVELSalienceExpression) ? 0 : rtn.getRule().getSalience().getValue(null, rtn.getRule(), wm); agendaItem = ((InternalAgenda) wm.getAgenda()).createRuleAgendaItem(salience, this, rtn); } + return rtn; + } + + public synchronized void doLinkRule(InternalWorkingMemory wm) { + TerminalNode rtn = ensureAgendaItemCreated(wm); + if (log.isTraceEnabled()) { + log.trace(" LinkRule name={}", rtn.getRule().getName()); + } queueRuleAgendaItem(wm); } public synchronized void doUnlinkRule(InternalWorkingMemory wm) { - TerminalNode rtn = (TerminalNode) getNetworkNode(); + TerminalNode rtn = ensureAgendaItemCreated(wm); if (log.isTraceEnabled()) { log.trace(" UnlinkRule name={}", rtn.getRule().getName()); } - if (agendaItem == null) { - int salience = ( rtn.getRule().getSalience() instanceof MVELSalienceExpression) - ? 0 - : rtn.getRule().getSalience().getValue(null, rtn.getRule(), wm); - agendaItem = ((InternalAgenda) wm.getAgenda()).createRuleAgendaItem(salience, this, rtn); - } queueRuleAgendaItem(wm); } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/RiaPathMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/RiaPathMemory.java index e72347e1db3..a27945b5bb3 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/RiaPathMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/RiaPathMemory.java @@ -1,7 +1,7 @@ package org.drools.core.reteoo; import org.drools.core.common.InternalWorkingMemory; -import org.drools.core.common.TupleEntryQueue; +import org.drools.core.common.StreamTupleEntryQueue; import java.util.ArrayList; import java.util.List; @@ -21,7 +21,7 @@ public void initQueue() { throw new UnsupportedOperationException("Queues can only be created onthe outer Rule PathMemory"); } - public void setTupleQueue(TupleEntryQueue queue) { + public void setStreamQueue(StreamTupleEntryQueue queue) { this.queue = queue; } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java index 862badc7750..ef44d8b5036 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java @@ -6,7 +6,7 @@ import org.drools.core.common.Memory; import org.drools.core.common.MemoryFactory; import org.drools.core.common.NetworkNode; -import org.drools.core.common.TupleEntryQueue; +import org.drools.core.common.StreamTupleEntryQueue; import org.drools.core.common.SynchronizedLeftTupleSets; import org.drools.core.phreak.SegmentUtilities; import org.drools.core.reteoo.QueryElementNode.QueryElementNodeMemory; @@ -40,13 +40,13 @@ public class SegmentMemory extends LinkedList private boolean active; private SegmentMemory previous; private SegmentMemory next; - private TupleEntryQueue queue; + private StreamTupleEntryQueue queue; public SegmentMemory(NetworkNode rootNode) { this(rootNode, null); } - public SegmentMemory(NetworkNode rootNode, TupleEntryQueue queue) { + public SegmentMemory(NetworkNode rootNode, StreamTupleEntryQueue queue) { this.rootNode = rootNode; this.linkedNodeMask = new AtomicBitwiseLong(); this.dirtyNodeMask = new AtomicBitwiseLong(); @@ -56,11 +56,11 @@ public SegmentMemory(NetworkNode rootNode, TupleEntryQueue queue) { this.queue = queue; } - public TupleEntryQueue getTupleQueue() { + public StreamTupleEntryQueue getStreamQueue() { return queue; } - public void setTupleQueue(TupleEntryQueue queue) { + public void setStreamQueue(StreamTupleEntryQueue queue) { this.queue = queue; } @@ -367,10 +367,10 @@ public SegmentMemory newSegmentMemory(InternalWorkingMemory wm) { } } - if ( hasQueue && smem.getTupleQueue() == null ) { + if ( hasQueue && smem.getStreamQueue() == null ) { // need to make sure there is one Queue, for the rule, when a stream mode node is found. - TupleEntryQueue queue = SegmentUtilities.initAndGetTupleQueue(smem.getTipNode(), wm); - smem.setTupleQueue( queue ); + StreamTupleEntryQueue queue = SegmentUtilities.initAndGetTupleQueue(smem.getTipNode(), wm); + smem.setStreamQueue( queue ); } if (hasSyncStagedLeftTuple) { diff --git a/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java b/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java index f9c7b3813d9..1872077f2ba 100644 --- a/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java +++ b/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java @@ -26,6 +26,7 @@ import org.drools.core.common.AgendaItem; import org.drools.core.common.EventFactHandle; import org.drools.core.common.EventSupport; +import org.drools.core.common.GarbageCollector; import org.drools.core.common.InternalAgenda; import org.drools.core.common.InternalAgendaGroup; import org.drools.core.common.InternalFactHandle; @@ -308,7 +309,7 @@ public void addEagerRuleAgendaItem(RuleAgendaItem item) { if ( log.isTraceEnabled() ) { log.trace("Added {} to eager evaluation list.", item.getRule().getName() ); } - eager.add( item ); + eager.add(item); } @Override @@ -1485,4 +1486,27 @@ public void setActivationsFilter(ActivationsFilter filter) { public ActivationsFilter getActivationsFilter() { return this.activationsFilter; } + + public GarbageCollector getGarbageCollector() { + return DUMMY_GARBAGE_COLLECTOR; + } + + private static final GarbageCollector DUMMY_GARBAGE_COLLECTOR = new DummyGarbageCollector(); + + public static class DummyGarbageCollector implements GarbageCollector { + @Override + public void increaseDeleteCounter() { } + + @Override + public void gcUnlinkedRules() { } + + @Override + public void forceGcUnlinkedRules() { } + + @Override + public void remove(RuleAgendaItem item) { } + + @Override + public void add(RuleAgendaItem item) { } + } } From c34417f3498f2f37141d924da90bcef8586f19af Mon Sep 17 00:00:00 2001 From: Edson Tirelli Date: Wed, 18 Jun 2014 19:09:42 -0400 Subject: [PATCH 17/76] DROOLS-530: fixing jar file creation on MemoryFileSystem (cherry picked from commit acff8a982ca853f76d46547f0c7803eb9c7de0c1) --- .../compiler/compiler/io/memory/MemoryFileSystem.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/compiler/io/memory/MemoryFileSystem.java b/drools-compiler/src/main/java/org/drools/compiler/compiler/io/memory/MemoryFileSystem.java index a5cc1b9dc54..dfb25d8862f 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/compiler/io/memory/MemoryFileSystem.java +++ b/drools-compiler/src/main/java/org/drools/compiler/compiler/io/memory/MemoryFileSystem.java @@ -426,14 +426,16 @@ public void writeAsFs(Folder f, private void writeJarEntries(Folder f, ZipOutputStream out) throws IOException { for ( Resource rs : f.getMembers() ) { + String rname = rs.getPath().toPortableString(); if ( rs instanceof Folder ) { - ZipEntry entry = new ZipEntry( rs.getPath().toPortableString() ); + rname = rname.endsWith("/") ? rname : rname + "/"; // a folder name must end with / according to ZIP spec + ZipEntry entry = new ZipEntry( rname ); out.putNextEntry( entry ); writeJarEntries( (Folder) rs, out ); } else { - ZipEntry entry = new ZipEntry( rs.getPath().toPortableString() ); + ZipEntry entry = new ZipEntry( rname ); out.putNextEntry( entry ); byte[] contents = getFileContents( (MemoryFile) rs ); From 8993a0ebac4c2dd2b2a48c187aaa3a5eebdab6c9 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 19 Jun 2014 10:52:02 +0200 Subject: [PATCH 18/76] [BZ-1084362] handle external:* notation in maven settings (cherry picked from commit 898bcc3e9426f68948f9815d7ee0735b6315477a) --- kie-ci/src/main/java/org/kie/scanner/MavenRepository.java | 4 ++-- .../test/resources/org/kie/scanner/settings_with_mirror.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java b/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java index 5fa54e48ffe..19a95bc235a 100644 --- a/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java +++ b/kie-ci/src/main/java/org/kie/scanner/MavenRepository.java @@ -116,9 +116,9 @@ private RemoteRepository resolveMirroredRepo(Settings settings, RemoteRepository private boolean isMirror(RemoteRepository repo, String mirrorOf) { return mirrorOf.equals("*") || ( mirrorOf.equals("external:*") && !repo.getUrl().startsWith("file:") ) || - ( mirrorOf.startsWith("external:*") && !repo.getUrl().startsWith("file:") && !mirrorOf.contains("!" + repo.getId()) ) || + ( mirrorOf.contains("external:*") && !repo.getUrl().startsWith("file:") && !mirrorOf.contains("!" + repo.getId()) ) || ( mirrorOf.startsWith("*") && !mirrorOf.contains("!" + repo.getId()) ) || - ( !mirrorOf.startsWith("*") && !mirrorOf.startsWith("external:*") && mirrorOf.contains(repo.getId()) ); + ( !mirrorOf.startsWith("*") && !mirrorOf.contains("external:*") && mirrorOf.contains(repo.getId()) ); } private boolean isProfileActive(Settings settings, Profile profile) { diff --git a/kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml b/kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml index 6960ca6bd25..09528563463 100644 --- a/kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml +++ b/kie-ci/src/test/resources/org/kie/scanner/settings_with_mirror.xml @@ -33,7 +33,7 @@ qa - external:*,!foo + !foo,external:* http://nexuszzz.qa.jboss.com:8081/nexus/content/groups/public-all From 030bcacd426a58b46d5f2d1b9277abc7c015e222 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Fri, 20 Jun 2014 09:03:18 +0200 Subject: [PATCH 19/76] [DROOLS-532] Avoid using compilation cache between incompatible drools versions (cherry picked from commit f0763abf6851b1aabc3985d71544ded69dbc0c4f) --- .../kie/builder/impl/AbstractKieModule.java | 10 +++ .../builder/impl/KieModuleCacheHelper.java | 20 +++--- drools-core/pom.xml | 10 +++ .../drools.versions.properties | 1 + .../java/org/drools/core/util/Drools.java | 70 +++++++++++++++++++ 5 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 drools-core/src/main/filtered-resources/drools.versions.properties create mode 100644 drools-core/src/main/java/org/drools/core/util/Drools.java diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/AbstractKieModule.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/AbstractKieModule.java index 065bd555bb6..de2d7d294d3 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/AbstractKieModule.java +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/AbstractKieModule.java @@ -14,6 +14,7 @@ import org.drools.core.builder.conf.impl.ResourceConfigurationImpl; import org.drools.core.rule.KieModuleMetaInfo; import org.drools.core.rule.TypeMetaInfo; +import org.drools.core.util.Drools; import org.drools.core.util.StringUtils; import org.kie.api.builder.Message; import org.kie.api.builder.ReleaseId; @@ -305,6 +306,15 @@ protected CompilationCache getCompilationCache(String kbaseName) { ExtensionRegistry registry = KieModuleCacheHelper.buildRegistry(); try { Header _header = KieModuleCacheHelper.readFromStreamWithHeaderPreloaded(new ByteArrayInputStream(fileContents), registry); + + if (!Drools.isCompatible(_header.getVersion().getVersionMajor(), + _header.getVersion().getVersionMinor(), + _header.getVersion().getVersionRevision())) { + // if cache has been built with an incompatible version avoid to use it + log.warn("Compilation cache has been built with an incompatible version, so don't use it"); + return null; + } + KModuleCache _cache = KModuleCache.parseFrom(_header.getPayload()); cache = new CompilationCache(); diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieModuleCacheHelper.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieModuleCacheHelper.java index 8df5a14d8e2..47af6bc5548 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieModuleCacheHelper.java +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieModuleCacheHelper.java @@ -16,6 +16,13 @@ package org.drools.compiler.kie.builder.impl; +import com.google.protobuf.ByteString; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.Message; +import org.drools.compiler.kie.builder.impl.KieModuleCache.Header; +import org.drools.core.util.Drools; +import org.drools.core.util.KeyStoreHelper; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -25,13 +32,6 @@ import java.security.NoSuchAlgorithmException; import java.security.SignatureException; -import org.drools.compiler.kie.builder.impl.KieModuleCache.Header; -import org.drools.core.util.KeyStoreHelper; - -import com.google.protobuf.ByteString; -import com.google.protobuf.ExtensionRegistry; -import com.google.protobuf.Message; - public class KieModuleCacheHelper { public static void writeToStreamWithHeader( OutputStream stream, @@ -39,9 +39,9 @@ public static void writeToStreamWithHeader( OutputStream stream, KieModuleCache.Header.Builder _header = KieModuleCache.Header.newBuilder(); // need to automate this version numbering somehow _header.setVersion( KieModuleCache.Version.newBuilder() - .setVersionMajor( 6 ) - .setVersionMinor( 0 ) - .setVersionRevision( 0 ) + .setVersionMajor( Drools.getMajorVersion() ) + .setVersionMinor( Drools.getMinorVersion() ) + .setVersionRevision( Drools.getRevisionVersion() ) .build() ); byte[] buff = payload.toByteArray(); diff --git a/drools-core/pom.xml b/drools-core/pom.xml index ffdf4d3847d..3715de840a2 100644 --- a/drools-core/pom.xml +++ b/drools-core/pom.xml @@ -166,6 +166,16 @@ + + + src/main/resources + + + true + src/main/filtered-resources + + + org.apache.felix diff --git a/drools-core/src/main/filtered-resources/drools.versions.properties b/drools-core/src/main/filtered-resources/drools.versions.properties new file mode 100644 index 00000000000..d01d77ba5a4 --- /dev/null +++ b/drools-core/src/main/filtered-resources/drools.versions.properties @@ -0,0 +1 @@ +drools.version=${project.version} \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/util/Drools.java b/drools-core/src/main/java/org/drools/core/util/Drools.java new file mode 100644 index 00000000000..6b239f3026b --- /dev/null +++ b/drools-core/src/main/java/org/drools/core/util/Drools.java @@ -0,0 +1,70 @@ +package org.drools.core.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class Drools { + + private static String droolsFullVersion; + + private static int droolsMajorVersion; + private static int droolsMinorVersion; + private static int droolsRevisionVersion; + + static { + droolsFullVersion = Drools.class.getPackage().getImplementationVersion(); + if (droolsFullVersion == null) { + InputStream is = null; + try { + is = Drools.class.getClassLoader().getResourceAsStream("drools.versions.properties"); + Properties properties = new Properties(); + properties.load(is); + droolsFullVersion = properties.get("drools.version").toString(); + is.close(); + } catch ( IOException e ) { + throw new RuntimeException(e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + + String[] versionSplit = droolsFullVersion.split("\\."); + droolsMajorVersion = Integer.parseInt(versionSplit[0]); + droolsMinorVersion = Integer.parseInt(versionSplit[1]); + int pos = versionSplit[2].indexOf('-'); + droolsRevisionVersion = pos >= 0 ? + Integer.parseInt(versionSplit[2].substring(0, pos)) : + Integer.parseInt(versionSplit[2]); + } + + public static String getFullVersion() { + return droolsFullVersion; + } + + public static int getMajorVersion() { + return droolsMajorVersion; + } + + public static int getMinorVersion() { + return droolsMinorVersion; + } + + public static int getRevisionVersion() { + return droolsRevisionVersion; + } + + public static boolean isCompatible(int major, int minor, int revision) { + if (major != droolsMajorVersion) { + return false; + } + // 6.0.x and 6.1+.x aren't compatible + return minor == 0 ? droolsMinorVersion == 0 : droolsMinorVersion > 0; + } +} From e9a095b8fd929373d3d336cb9052f43ac99130c6 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Fri, 20 Jun 2014 10:09:06 +0200 Subject: [PATCH 20/76] [DROOLS-531] allow to create a valid KieClasspathContainer even from a non-maven project (cherry picked from commit 1fb4c12d133e576dd9669406ac5c238fcb3cf8a0) --- .../compiler/kie/builder/impl/ClasspathKieProject.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java index 581cde0de4d..9c4d2c9f73d 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java @@ -164,8 +164,13 @@ private static InternalKieModule fetchKModule(URL url, String fixedURL) { setDefaultsforEmptyKieModule(kieProject); String pomProperties = getPomProperties( fixedURL ); - - ReleaseId releaseId = ReleaseIdImpl.fromPropertiesString(pomProperties); + if (pomProperties == null) { + log.warn("Cannot find maven pom properties for this project. Using the container's default ReleaseId"); + } + + ReleaseId releaseId = pomProperties != null ? + ReleaseIdImpl.fromPropertiesString(pomProperties) : + KieServices.Factory.get().getRepository().getDefaultReleaseId(); String rootPath = fixedURL; if ( rootPath.lastIndexOf( ':' ) > 0 ) { From 96ef4d66ccdf8b160680accc61c8c2170cbb257b Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Thu, 19 Jun 2014 21:49:31 +0100 Subject: [PATCH 21/76] BZ996944 - GDT Audit log: missing information in column update logs (cherry picked from commit e1ae903922fdea13be8da7c2038cadc45086382d) --- .../auditlog/ActionWorkItemColumnDetails.java | 53 ++++++++ ...ActionWorkItemInsertFactColumnDetails.java | 57 ++++++++ .../ActionWorkItemSetFieldColumnDetails.java | 57 ++++++++ .../auditlog/InsertColumnAuditLogEntry.java | 10 ++ .../auditlog/UpdateColumnAuditLogEntry.java | 9 +- .../shared/model/ActionInsertFactCol52.java | 43 +++--- .../model/ActionInsertFactFieldsPattern.java | 20 +-- .../shared/model/ActionSetFieldCol52.java | 40 +++--- .../shared/model/ActionWorkItemCol52.java | 125 ++++++++++++++++-- .../model/ActionWorkItemInsertFactCol52.java | 12 +- .../model/ActionWorkItemSetFieldCol52.java | 22 +-- .../dtable/shared/model/AttributeCol52.java | 38 +++--- .../dtable/shared/model/BRLActionColumn.java | 20 ++- .../shared/model/BRLActionVariableColumn.java | 32 +++-- .../shared/model/BRLConditionColumn.java | 20 ++- .../model/BRLConditionVariableColumn.java | 20 ++- .../dtable/shared/model/ConditionCol52.java | 46 ++++--- .../dtable/shared/model/DTCellValue52.java | 13 -- .../dtable/shared/model/DTColumnConfig52.java | 10 +- .../dtable/shared/model/DiffColumn.java | 7 +- .../LimitedEntryActionInsertFactCol52.java | 21 ++- .../LimitedEntryActionRetractFactCol52.java | 21 ++- .../LimitedEntryActionSetFieldCol52.java | 21 ++- .../model/LimitedEntryConditionCol52.java | 21 ++- .../dtable/shared/model/MetadataCol52.java | 26 ++-- .../guided/dtable/shared/model/Pattern52.java | 76 ++++++----- .../src/main/resources/ErraiApp.properties | 21 +-- 27 files changed, 604 insertions(+), 257 deletions(-) create mode 100644 drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemColumnDetails.java create mode 100644 drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemInsertFactColumnDetails.java create mode 100644 drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemSetFieldColumnDetails.java diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemColumnDetails.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemColumnDetails.java new file mode 100644 index 00000000000..87fa615f1de --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemColumnDetails.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012 JBoss Inc + * + * 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.guided.dtable.shared.auditlog; + +import java.util.HashMap; +import java.util.Map; + +import org.drools.workbench.models.datamodel.workitems.PortableParameterDefinition; +import org.drools.workbench.models.guided.dtable.shared.model.ActionWorkItemCol52; + +/** + * Details of an ActionWorkItem column, for when a Work Item is executed + */ +public class ActionWorkItemColumnDetails extends ColumnDetails { + + private String name; + private Map parameters; + + public ActionWorkItemColumnDetails() { + } + + public ActionWorkItemColumnDetails( final ActionWorkItemCol52 column ) { + super( column ); + this.name = column.getWorkItemDefinition().getName(); + this.parameters = new HashMap(); + for ( String parameterName : column.getWorkItemDefinition().getParameterNames() ) { + this.parameters.put( parameterName, + column.getWorkItemDefinition().getParameter( parameterName ) ); + } + } + + public String getName() { + return name; + } + + public Map getParameters() { + return parameters; + } + +} diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemInsertFactColumnDetails.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemInsertFactColumnDetails.java new file mode 100644 index 00000000000..1205d9cd227 --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemInsertFactColumnDetails.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012 JBoss Inc + * + * 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.guided.dtable.shared.auditlog; + +import org.drools.workbench.models.guided.dtable.shared.model.ActionWorkItemInsertFactCol52; + +/** + * Details of an ActionWorkItemInsertFact column + */ +public class ActionWorkItemInsertFactColumnDetails extends ColumnDetails { + + private String factType; + private String factField; + private String workItemName; + private String workItemResultParameterName; + + public ActionWorkItemInsertFactColumnDetails() { + } + + public ActionWorkItemInsertFactColumnDetails( final ActionWorkItemInsertFactCol52 column ) { + super( column ); + this.factType = column.getFactType(); + this.factField = column.getFactField(); + this.workItemName = column.getWorkItemName(); + this.workItemResultParameterName = column.getWorkItemResultParameterName(); + } + + public String getFactType() { + return factType; + } + + public String getFactField() { + return factField; + } + + public String getWorkItemName() { + return workItemName; + } + + public String getWorkItemResultParameterName() { + return workItemResultParameterName; + } + +} diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemSetFieldColumnDetails.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemSetFieldColumnDetails.java new file mode 100644 index 00000000000..41d737c6001 --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/ActionWorkItemSetFieldColumnDetails.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012 JBoss Inc + * + * 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.guided.dtable.shared.auditlog; + +import org.drools.workbench.models.guided.dtable.shared.model.ActionWorkItemSetFieldCol52; + +/** + * Details of an ActionWorkItemSetField column + */ +public class ActionWorkItemSetFieldColumnDetails extends ColumnDetails { + + private String boundName; + private String factField; + private String workItemName; + private String workItemResultParameterName; + + public ActionWorkItemSetFieldColumnDetails() { + } + + public ActionWorkItemSetFieldColumnDetails( final ActionWorkItemSetFieldCol52 column ) { + super( column ); + this.boundName = column.getBoundName(); + this.factField = column.getFactField(); + this.workItemName = column.getWorkItemName(); + this.workItemResultParameterName = column.getWorkItemResultParameterName(); + } + + public String getBoundName() { + return boundName; + } + + public String getFactField() { + return factField; + } + + public String getWorkItemName() { + return workItemName; + } + + public String getWorkItemResultParameterName() { + return workItemResultParameterName; + } + +} diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/InsertColumnAuditLogEntry.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/InsertColumnAuditLogEntry.java index 769c459a3f3..0ca94fcabfa 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/InsertColumnAuditLogEntry.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/InsertColumnAuditLogEntry.java @@ -18,6 +18,9 @@ import org.drools.workbench.models.datamodel.auditlog.AuditLogEntry; import org.drools.workbench.models.guided.dtable.shared.model.ActionInsertFactCol52; import org.drools.workbench.models.guided.dtable.shared.model.ActionSetFieldCol52; +import org.drools.workbench.models.guided.dtable.shared.model.ActionWorkItemCol52; +import org.drools.workbench.models.guided.dtable.shared.model.ActionWorkItemInsertFactCol52; +import org.drools.workbench.models.guided.dtable.shared.model.ActionWorkItemSetFieldCol52; import org.drools.workbench.models.guided.dtable.shared.model.AttributeCol52; import org.drools.workbench.models.guided.dtable.shared.model.BRLActionColumn; import org.drools.workbench.models.guided.dtable.shared.model.BRLConditionColumn; @@ -53,6 +56,7 @@ public InsertColumnAuditLogEntry( final String userName, } protected ColumnDetails getDetails( final BaseColumn column ) { + //Order of columns is important to account for sub-types and super-types if ( column instanceof MetadataCol52 ) { return new MetadataColumnDetails( (MetadataCol52) column ); } else if ( column instanceof AttributeCol52 ) { @@ -65,14 +69,20 @@ protected ColumnDetails getDetails( final BaseColumn column ) { return new LimitedEntryConditionColumnDetails( (LimitedEntryConditionCol52) column ); } else if ( column instanceof BRLActionColumn ) { return new ColumnDetails( column ); + } else if ( column instanceof ActionWorkItemInsertFactCol52 ) { + return new ActionWorkItemInsertFactColumnDetails( (ActionWorkItemInsertFactCol52) column ); } else if ( column instanceof ActionInsertFactCol52 ) { return new ActionInsertFactColumnDetails( (ActionInsertFactCol52) column ); } else if ( column instanceof LimitedEntryActionInsertFactCol52 ) { return new LimitedEntryActionInsertFactColumnDetails( (LimitedEntryActionInsertFactCol52) column ); + } else if ( column instanceof ActionWorkItemSetFieldCol52 ) { + return new ActionWorkItemSetFieldColumnDetails( (ActionWorkItemSetFieldCol52) column ); } else if ( column instanceof ActionSetFieldCol52 ) { return new ActionSetFieldColumnDetails( (ActionSetFieldCol52) column ); } else if ( column instanceof LimitedEntryActionSetFieldCol52 ) { return new LimitedEntryActionSetFieldColumnDetails( (LimitedEntryActionSetFieldCol52) column ); + } else if ( column instanceof ActionWorkItemCol52 ) { + return new ActionWorkItemColumnDetails( (ActionWorkItemCol52) column ); } else { return new ColumnDetails( column ); } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/UpdateColumnAuditLogEntry.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/UpdateColumnAuditLogEntry.java index 6c9ee146618..fc3ae1e37dc 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/UpdateColumnAuditLogEntry.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/UpdateColumnAuditLogEntry.java @@ -15,11 +15,10 @@ */ package org.drools.workbench.models.guided.dtable.shared.auditlog; +import java.util.List; + import org.drools.workbench.models.guided.dtable.shared.model.BaseColumn; import org.drools.workbench.models.guided.dtable.shared.model.BaseColumnFieldDiff; -import org.drools.workbench.models.guided.dtable.shared.model.DiffColumn; - -import java.util.List; /** * An Audit Event when a column is updated @@ -53,9 +52,9 @@ public UpdateColumnAuditLogEntry( final String userName, public UpdateColumnAuditLogEntry( final String userName, final BaseColumn originalColumn, final BaseColumn newColumn, - final List diffs) { + final List diffs ) { super( userName, - newColumn ); + newColumn ); this.originalDetails = getDetails( originalColumn ); this.diffs = diffs; } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactCol52.java index e4e526df593..c4105ee14e0 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactCol52.java @@ -31,7 +31,6 @@ public class ActionInsertFactCol52 extends ActionCol52 { public static final String FIELD_VALUE_LIST = "valueList"; public static final String FIELD_IS_INSERT_LOGICAL = "isInsertLogical"; - /** * The fact type (class) that is to be created. eg Driver, Purchase, Cheese. */ @@ -66,46 +65,60 @@ public class ActionInsertFactCol52 extends ActionCol52 { private boolean isInsertLogical = false; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); ActionInsertFactCol52 other = (ActionInsertFactCol52) otherColumn; // Field: fact type. if ( !isEqualOrNull( this.getFactType(), - other.getFactType() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_TYPE, this.getFactType(), other.getFactType())); + other.getFactType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_TYPE, + this.getFactType(), + other.getFactType() ) ); } // Field: bundle name. if ( !isEqualOrNull( this.getBoundName(), - other.getBoundName() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_BOUND_NAME, this.getBoundName(), other.getBoundName())); + other.getBoundName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_BOUND_NAME, + this.getBoundName(), + other.getBoundName() ) ); } // Field: fact field. if ( !isEqualOrNull( this.getFactField(), - other.getFactField() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_FIELD, this.getFactField(), other.getFactField())); + other.getFactField() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_FIELD, + this.getFactField(), + other.getFactField() ) ); } // Field: type. if ( !isEqualOrNull( this.getType(), - other.getType() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_TYPE, this.getType(), other.getType())); + other.getType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_TYPE, + this.getType(), + other.getType() ) ); } // Field: value list. if ( !isEqualOrNull( this.getValueList(), - other.getValueList() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VALUE_LIST, this.getValueList(), other.getValueList())); + other.getValueList() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VALUE_LIST, + this.getValueList(), + other.getValueList() ) ); } // Field: isInsertLogical. if ( this.isInsertLogical() != other.isInsertLogical() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_IS_INSERT_LOGICAL, this.isInsertLogical(), other.isInsertLogical())); + result.add( new BaseColumnFieldDiffImpl( FIELD_IS_INSERT_LOGICAL, + this.isInsertLogical(), + other.isInsertLogical() ) ); } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactFieldsPattern.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactFieldsPattern.java index caac2216dfe..f79e2c954c6 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactFieldsPattern.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactFieldsPattern.java @@ -32,15 +32,19 @@ public class ActionInsertFactFieldsPattern extends Pattern52 { public static final String FIELD_IS_INSERTED_LOGICALLY = "isInsertedLogically"; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); ActionInsertFactFieldsPattern other = (ActionInsertFactFieldsPattern) otherColumn; // Field: isInsertedLogically. if ( this.isInsertedLogically() != other.isInsertedLogically() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_IS_INSERTED_LOGICALLY, this.isInsertedLogically(), other.isInsertedLogically())); + result.add( new BaseColumnFieldDiffImpl( FIELD_IS_INSERTED_LOGICALLY, + this.isInsertedLogically(), + other.isInsertedLogically() ) ); } return result; @@ -57,13 +61,13 @@ public void setInsertedLogically( boolean isInsertedLogically ) { @Override public ActionInsertFactFieldsPattern clonePattern() { ActionInsertFactFieldsPattern cloned = (ActionInsertFactFieldsPattern) super.clonePattern(); - cloned.setInsertedLogically(isInsertedLogically); + cloned.setInsertedLogically( isInsertedLogically ); return cloned; } @Override - public void update(Pattern52 other) { - super.update(other); - setInsertedLogically(((ActionInsertFactFieldsPattern)other).isInsertedLogically); + public void update( Pattern52 other ) { + super.update( other ); + setInsertedLogically( ( (ActionInsertFactFieldsPattern) other ).isInsertedLogically ); } } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionSetFieldCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionSetFieldCol52.java index 611b6218be3..10361a62264 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionSetFieldCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionSetFieldCol52.java @@ -63,47 +63,57 @@ public class ActionSetFieldCol52 extends ActionCol52 { */ private boolean update = false; - @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); ActionSetFieldCol52 other = (ActionSetFieldCol52) otherColumn; // Field: bound name.. if ( !isEqualOrNull( this.getBoundName(), - other.getBoundName() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_BOUND_NAME, this.getBoundName(), other.getBoundName())); + other.getBoundName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_BOUND_NAME, + this.getBoundName(), + other.getBoundName() ) ); } // Field: factField.. if ( !isEqualOrNull( this.getFactField(), - other.getFactField() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_FIELD, this.getFactField(), other.getFactField())); + other.getFactField() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_FIELD, + this.getFactField(), + other.getFactField() ) ); } // Field: type.. if ( !isEqualOrNull( this.getType(), - other.getType() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_TYPE, this.getType(), other.getType())); + other.getType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_TYPE, + this.getType(), + other.getType() ) ); } // Field: valueList.. if ( !isEqualOrNull( this.getValueList(), - other.getValueList() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VALUE_LIST, this.getValueList(), other.getValueList())); + other.getValueList() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VALUE_LIST, + this.getValueList(), + other.getValueList() ) ); } // Field: update.. - if ( this.isUpdate() != other.isUpdate()) { - result.add(new BaseColumnFieldDiffImpl(FIELD_UPDATE, this.isUpdate(), other.isUpdate())); + if ( this.isUpdate() != other.isUpdate() ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_UPDATE, + this.isUpdate(), + other.isUpdate() ) ); } return result; } - public void setValueList( String valueList ) { this.valueList = valueList; } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemCol52.java index 280c3fea301..dc4fb704c93 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemCol52.java @@ -15,10 +15,13 @@ */ package org.drools.workbench.models.guided.dtable.shared.model; -import org.drools.workbench.models.datamodel.workitems.PortableWorkDefinition; - +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import org.drools.workbench.models.datamodel.workitems.PortableParameterDefinition; +import org.drools.workbench.models.datamodel.workitems.PortableWorkDefinition; + /** * A column representing the execution of a Work Item. */ @@ -31,19 +34,121 @@ public class ActionWorkItemCol52 extends ActionCol52 { /** * Available fields for this type of column. */ - public static final String FIELD_WORKITEM_DEFINITION = "workItemDefinition"; + public static final String FIELD_WORKITEM_DEFINITION_NAME = "workItemDefinitionName"; + + public static final String FIELD_WORKITEM_DEFINITION_DISPLAY_NAME = "workItemDefinitionDisplayName"; + + public static final String FIELD_WORKITEM_DEFINITION_PARAMETER_NAME = "workItemDefinitionParameterName"; + + public static final String FIELD_WORKITEM_DEFINITION_PARAMETER_VALUE = "workItemDefinitionParameterValue"; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); ActionWorkItemCol52 other = (ActionWorkItemCol52) otherColumn; - // Field: default value. - if ( !isEqualOrNull( this.getWorkItemDefinition(), - other.getWorkItemDefinition() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_WORKITEM_DEFINITION, this.getWorkItemDefinition(), other.getWorkItemDefinition())); + // Field: Work Item definition. + final PortableWorkDefinition thisDefinition = this.getWorkItemDefinition(); + final PortableWorkDefinition otherDefinition = other.getWorkItemDefinition(); + + //Determine diffs between "this" WorkItemDefinition and the "other" WorkItemDefinition + //If both are null there are no changes; if however one is null and the other is not + //then the WorkItemDefinition has effectively been added or deleted. Otherwise look + //for differences between the two WorkItemDefinitions + if ( thisDefinition == null && otherDefinition == null ) { + return result; + + } else if ( thisDefinition != null && otherDefinition == null ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_NAME, + thisDefinition.getName(), + null ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_DISPLAY_NAME, + thisDefinition.getDisplayName(), + null ) ); + for ( PortableParameterDefinition parameter : thisDefinition.getParameters() ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_NAME, + parameter.getName(), + null ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_VALUE, + parameter.asString(), + null ) ); + } + + } else if ( thisDefinition == null && otherDefinition != null ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_NAME, + null, + otherDefinition.getName() ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_DISPLAY_NAME, + null, + otherDefinition.getDisplayName() ) ); + for ( PortableParameterDefinition parameter : otherDefinition.getParameters() ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_NAME, + null, + parameter.getName() ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_VALUE, + null, + parameter.asString() ) ); + } + + } else { + if ( !thisDefinition.getName().equals( otherDefinition.getName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_NAME, + thisDefinition.getName(), + otherDefinition.getName() ) ); + } + if ( !thisDefinition.getDisplayName().equals( otherDefinition.getDisplayName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_DISPLAY_NAME, + thisDefinition.getDisplayName(), + otherDefinition.getDisplayName() ) ); + } + final List thisDefinitionParameterNames = Arrays.asList( thisDefinition.getParameterNames() ); + final List otherDefinitionParameterNames = Arrays.asList( otherDefinition.getParameterNames() ); + + //Some Parameters have been deleted + final List parameterNamesDeleted = new ArrayList( thisDefinitionParameterNames ); + parameterNamesDeleted.removeAll( otherDefinitionParameterNames ); + for ( String parameterName : parameterNamesDeleted ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_NAME, + thisDefinition.getParameter( parameterName ).getName(), + null ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_VALUE, + thisDefinition.getParameter( parameterName ).asString(), + null ) ); + } + + //Some Parameters have been added + final List parameterNamesAdded = new ArrayList( otherDefinitionParameterNames ); + parameterNamesAdded.removeAll( thisDefinitionParameterNames ); + for ( String parameterName : parameterNamesAdded ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_NAME, + null, + otherDefinition.getParameter( parameterName ).getName() ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_VALUE, + null, + otherDefinition.getParameter( parameterName ).asString() ) ); + } + + //Some Parameters have been updated + final List parameterNamesUpdated = new ArrayList( thisDefinitionParameterNames ); + parameterNamesUpdated.retainAll( otherDefinitionParameterNames ); + for ( String parameterName : parameterNamesUpdated ) { + if ( !isEqualOrNull( thisDefinition.getParameter( parameterName ).getName(), + otherDefinition.getParameter( parameterName ).getName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_NAME, + thisDefinition.getParameter( parameterName ).getName(), + otherDefinition.getParameter( parameterName ).getName() ) ); + } + if ( !isEqualOrNull( thisDefinition.getParameter( parameterName ).asString(), + otherDefinition.getParameter( parameterName ).asString() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORKITEM_DEFINITION_PARAMETER_VALUE, + thisDefinition.getParameter( parameterName ).asString(), + otherDefinition.getParameter( parameterName ).asString() ) ); + } + } } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemInsertFactCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemInsertFactCol52.java index 17069b1f362..0f092f77eb7 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemInsertFactCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemInsertFactCol52.java @@ -52,19 +52,25 @@ public List diff( BaseColumn otherColumn ) { // Field: workItemName. if ( !isEqualOrNull( this.getWorkItemName(), other.getWorkItemName() ) ) { - result.add( new BaseColumnFieldDiffImpl( FIELD_WORK_ITEM_NAME, this.getWorkItemName(), other.getWorkItemName() ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORK_ITEM_NAME, + this.getWorkItemName(), + other.getWorkItemName() ) ); } // Field: workItemResultParameterName. if ( !isEqualOrNull( this.getWorkItemResultParameterName(), other.getWorkItemResultParameterName() ) ) { - result.add( new BaseColumnFieldDiffImpl( FIELD_WORK_ITEM_RESULT_PARAM_NAME, this.getWorkItemResultParameterName(), other.getWorkItemResultParameterName() ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_WORK_ITEM_RESULT_PARAM_NAME, + this.getWorkItemResultParameterName(), + other.getWorkItemResultParameterName() ) ); } // Field: parameterClassName. if ( !isEqualOrNull( this.getParameterClassName(), other.getParameterClassName() ) ) { - result.add( new BaseColumnFieldDiffImpl( FIELD_PARAMETER_CLASSNAME, this.getParameterClassName(), other.getParameterClassName() ) ); + result.add( new BaseColumnFieldDiffImpl( FIELD_PARAMETER_CLASSNAME, + this.getParameterClassName(), + other.getParameterClassName() ) ); } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemSetFieldCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemSetFieldCol52.java index 2ea9ca54aad..a312dae637e 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemSetFieldCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemSetFieldCol52.java @@ -40,36 +40,36 @@ public class ActionWorkItemSetFieldCol52 extends ActionSetFieldCol52 { private String parameterClassName; - @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); ActionWorkItemSetFieldCol52 other = (ActionWorkItemSetFieldCol52) otherColumn; // Field: workItemName. if ( !isEqualOrNull( this.getWorkItemName(), - other.getWorkItemName() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_WORK_ITEM_NAME, this.getWorkItemName(), other.getWorkItemName())); + other.getWorkItemName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORK_ITEM_NAME, this.getWorkItemName(), other.getWorkItemName() ) ); } // Field: workItemResultParameterName. if ( !isEqualOrNull( this.getWorkItemResultParameterName(), - other.getWorkItemResultParameterName() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_WORK_ITEM_RESULT_PARAM_NAME, this.getWorkItemResultParameterName(), other.getWorkItemResultParameterName())); + other.getWorkItemResultParameterName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WORK_ITEM_RESULT_PARAM_NAME, this.getWorkItemResultParameterName(), other.getWorkItemResultParameterName() ) ); } // Field: parameterClassName. if ( !isEqualOrNull( this.getParameterClassName(), - other.getParameterClassName() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_PARAMETER_CLASSNAME, this.getParameterClassName(), other.getParameterClassName())); + other.getParameterClassName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_PARAMETER_CLASSNAME, this.getParameterClassName(), other.getParameterClassName() ) ); } return result; } - public String getWorkItemName() { return workItemName; } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/AttributeCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/AttributeCol52.java index f75bd934fde..252e74c610e 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/AttributeCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/AttributeCol52.java @@ -41,27 +41,34 @@ public class AttributeCol52 extends DTColumnConfig52 { public static final String FIELD_USE_ROW_NUMBER = "useRowNumber"; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); AttributeCol52 other = (AttributeCol52) otherColumn; - // Field: attribute. if ( !isEqualOrNull( this.getAttribute(), - other.getAttribute() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_ATTRIBUTE, this.getAttribute(), other.getAttribute())); + other.getAttribute() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_ATTRIBUTE, + this.getAttribute(), + other.getAttribute() ) ); } // Field: reverseOrder. if ( this.isReverseOrder() != other.isReverseOrder() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_REVERSE_ORDER, this.isReverseOrder(), other.isReverseOrder())); + result.add( new BaseColumnFieldDiffImpl( FIELD_REVERSE_ORDER, + this.isReverseOrder(), + other.isReverseOrder() ) ); } // Field: useRowNumber. if ( this.isUseRowNumber() != other.isUseRowNumber() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_USE_ROW_NUMBER, this.isUseRowNumber(), other.isUseRowNumber())); + result.add( new BaseColumnFieldDiffImpl( FIELD_USE_ROW_NUMBER, + this.isUseRowNumber(), + other.isUseRowNumber() ) ); } return result; @@ -69,18 +76,17 @@ public List diff(BaseColumn otherColumn) { /** * Clones this metadata column instance. - * * @return The cloned instance. */ public AttributeCol52 cloneColumn() { AttributeCol52 cloned = new AttributeCol52(); - cloned.setAttribute(getAttribute()); - cloned.setReverseOrder(isReverseOrder()); - cloned.setUseRowNumber(isUseRowNumber()); - cloned.setWidth(getWidth()); - cloned.setHideColumn(isHideColumn()); - cloned.setHeader(getHeader()); - cloned.setDefaultValue(getDefaultValue() != null ? getDefaultValue().cloneDefaultValueCell() : null ); + cloned.setAttribute( getAttribute() ); + cloned.setReverseOrder( isReverseOrder() ); + cloned.setUseRowNumber( isUseRowNumber() ); + cloned.setWidth( getWidth() ); + cloned.setHideColumn( isHideColumn() ); + cloned.setHeader( getHeader() ); + cloned.setDefaultValue( getDefaultValue() != null ? getDefaultValue().cloneDefaultValueCell() : null ); return cloned; } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionColumn.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionColumn.java index b695d930170..a514eddf536 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionColumn.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionColumn.java @@ -41,22 +41,28 @@ public class BRLActionColumn extends ActionCol52 public static final String FIELD_CHILD_COLUMNS = "childColumns"; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); BRLActionColumn other = (BRLActionColumn) otherColumn; // Field: definition. if ( !isEqualOrNull( this.getDefinition(), - other.getDefinition() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_DEFINITION, this.getDefinition(), other.getDefinition())); + other.getDefinition() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_DEFINITION, + this.getDefinition(), + other.getDefinition() ) ); } // Field: childColumns. if ( !isEqualOrNull( this.getChildColumns(), - other.getChildColumns() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_CHILD_COLUMNS, this.getChildColumns(), other.getChildColumns())); + other.getChildColumns() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_CHILD_COLUMNS, + this.getChildColumns(), + other.getChildColumns() ) ); } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionVariableColumn.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionVariableColumn.java index c20342874e1..a79affa65a2 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionVariableColumn.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionVariableColumn.java @@ -62,34 +62,44 @@ public BRLActionVariableColumn( String varName, } @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); BRLActionVariableColumn other = (BRLActionVariableColumn) otherColumn; // Field: varName. if ( !isEqualOrNull( this.getVarName(), - other.getVarName() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VAR_NAME, this.getVarName(), other.getVarName())); + other.getVarName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VAR_NAME, + this.getVarName(), + other.getVarName() ) ); } // Field: fieldType. if ( !isEqualOrNull( this.getFieldType(), - other.getFieldType() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FIELD_TYPE, this.getFieldType(), other.getFieldType())); + other.getFieldType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FIELD_TYPE, + this.getFieldType(), + other.getFieldType() ) ); } // Field: factType. if ( !isEqualOrNull( this.getFactType(), - other.getFactType() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_TYPE, this.getFactType(), other.getFactType())); + other.getFactType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_TYPE, + this.getFactType(), + other.getFactType() ) ); } // Field: factField. if ( !isEqualOrNull( this.getFactField(), - other.getFactField() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_FIELD, this.getFactField(), other.getFactField())); + other.getFactField() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_FIELD, + this.getFactField(), + other.getFactField() ) ); } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionColumn.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionColumn.java index e3caa29221f..be8ce9514e0 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionColumn.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionColumn.java @@ -41,22 +41,28 @@ public class BRLConditionColumn extends ConditionCol52 public static final String FIELD_CHILD_COLUMNS = "childColumns"; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); BRLConditionColumn other = (BRLConditionColumn) otherColumn; // Field: definition. if ( !isEqualOrNull( this.getDefinition(), - other.getDefinition() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_DEFINITION, this.getDefinition(), other.getDefinition())); + other.getDefinition() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_DEFINITION, + this.getDefinition(), + other.getDefinition() ) ); } // Field: childColumns. if ( !isEqualOrNull( this.getChildColumns(), - other.getChildColumns() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_CHILD_COLUMNS, this.getChildColumns(), other.getChildColumns())); + other.getChildColumns() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_CHILD_COLUMNS, + this.getChildColumns(), + other.getChildColumns() ) ); } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionVariableColumn.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionVariableColumn.java index 7178162e522..def5028af7d 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionVariableColumn.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionVariableColumn.java @@ -56,22 +56,28 @@ public BRLConditionVariableColumn( String varName, } @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); BRLConditionVariableColumn other = (BRLConditionVariableColumn) otherColumn; // Field: varName. if ( !isEqualOrNull( this.getVarName(), - other.getVarName() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VAR_NAME, this.getVarName(), other.getVarName())); + other.getVarName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VAR_NAME, + this.getVarName(), + other.getVarName() ) ); } // Field: factType. if ( !isEqualOrNull( this.getFactType(), - other.getFactType() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_TYPE, this.getFactType(), other.getFactType())); + other.getFactType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_TYPE, + this.getFactType(), + other.getFactType() ) ); } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ConditionCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ConditionCol52.java index 84eb77f0d35..ba95e1b2492 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ConditionCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ConditionCol52.java @@ -73,48 +73,62 @@ public class ConditionCol52 extends DTColumnConfig52 public static final String FIELD_BINDING = "binding"; - public static final String FIELD_CONSTRAINT_VALUE_TYPE= "constraintValueType"; + public static final String FIELD_CONSTRAINT_VALUE_TYPE = "constraintValueType"; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); ConditionCol52 other = (ConditionCol52) otherColumn; // Field: factField. if ( !isEqualOrNull( this.getFactField(), - other.getFactField() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_FIELD, this.getFactField(), other.getFactField())); + other.getFactField() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_FIELD, + this.getFactField(), + other.getFactField() ) ); } // Field: fieldType. if ( !isEqualOrNull( this.getFieldType(), - other.getFieldType() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FIELD_TYPE, this.getFieldType(), other.getFieldType())); + other.getFieldType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FIELD_TYPE, + this.getFieldType(), + other.getFieldType() ) ); } // Field: operator. if ( !isEqualOrNull( this.getOperator(), - other.getOperator() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_OPERATOR, this.getOperator(), other.getOperator())); + other.getOperator() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_OPERATOR, + this.getOperator(), + other.getOperator() ) ); } // Field: valueList. if ( !isEqualOrNull( this.getValueList(), - other.getValueList() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VALUE_LIST, this.getValueList(), other.getValueList())); + other.getValueList() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VALUE_LIST, + this.getValueList(), + other.getValueList() ) ); } // Field: binding. if ( !isEqualOrNull( this.getBinding(), - other.getBinding() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_BINDING, this.getBinding(), other.getBinding())); + other.getBinding() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_BINDING, + this.getBinding(), + other.getBinding() ) ); } - // Field: binding. + // Field: constraint type. if ( this.getConstraintValueType() != other.getConstraintValueType() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_CONSTRAINT_VALUE_TYPE, this.getConstraintValueType(), other.getConstraintValueType())); + result.add( new BaseColumnFieldDiffImpl( FIELD_CONSTRAINT_VALUE_TYPE, + this.getConstraintValueType(), + other.getConstraintValueType() ) ); } return result; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTCellValue52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTCellValue52.java index d7b50634e9b..b5681b1d823 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTCellValue52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTCellValue52.java @@ -19,7 +19,6 @@ import java.math.BigInteger; import java.util.Date; -import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.DataType.DataTypes; @@ -443,18 +442,6 @@ public boolean equals( Object obj ) { return true; } - /** - * BZ-996944: To display the changed value into audit logging. - * @return The value as a String. - */ - public String getValueAsString() { - if (valueBoolean != null) return valueBoolean.toString(); - if (valueDate != null) return valueDate.toString(); - if (valueNumeric != null) return valueNumeric.toString(); - if (valueString != null) return valueString; - return ""; - } - /** * Clones this default value instance. * @return The cloned instance. diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTColumnConfig52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTColumnConfig52.java index a1259760d19..08a285e3d28 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTColumnConfig52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTColumnConfig52.java @@ -54,14 +54,6 @@ public DTCellValue52 getDefaultValue() { return typedDefaultValue; } - public String getDefaultValueAsString() { - String result = ""; - if ( typedDefaultValue != null ) { - result = typedDefaultValue.getValueAsString(); - } - return result; - } - public int getWidth() { return width; } @@ -116,7 +108,7 @@ public List diff( BaseColumn otherColumn ) { return result; } - private Object extractDefaultValue( final DTCellValue52 dcv ) { + protected Object extractDefaultValue( final DTCellValue52 dcv ) { switch ( dcv.getDataType() ) { case BOOLEAN: return dcv.getBooleanValue(); diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DiffColumn.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DiffColumn.java index a550cf03bc4..8ed2ed87844 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DiffColumn.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DiffColumn.java @@ -19,19 +19,16 @@ /** * A column than can perform diff with another column. - * * E.g.: Useful when querying the differences in a user edited column for update column event. - * - * BZ-996944: The idea is to show the changed fileds and its values in audit log events. + * BZ-996944: The idea is to show the changed fields and its values in audit log events. */ public interface DiffColumn { /** * Analyze differences between two columns of same type. - * * @param otherColumn The column to compare with this one. * @return A list of fields and its values that have changed. */ - List diff(BaseColumn otherColumn); + List diff( BaseColumn otherColumn ); } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionInsertFactCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionInsertFactCol52.java index c944c194351..d2ab8540492 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionInsertFactCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionInsertFactCol52.java @@ -34,16 +34,20 @@ public class LimitedEntryActionInsertFactCol52 extends ActionInsertFactCol52 private DTCellValue52 value; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); LimitedEntryActionInsertFactCol52 other = (LimitedEntryActionInsertFactCol52) otherColumn; // Field: default value. - if ( !isEqualOrNull( this.getValue(), - other.getValue() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VALUE, this.getValueAsString(), other.getValueAsString())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getValue(), + other.getValue() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VALUE, + extractDefaultValue( this.getValue() ), + extractDefaultValue( other.getValue() ) ) ); } return result; @@ -57,9 +61,4 @@ public void setValue( DTCellValue52 value ) { this.value = value; } - public String getValueAsString() { - if (value != null) return value.getValueAsString(); - return ""; - } - } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionRetractFactCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionRetractFactCol52.java index 93ab4d7ddbd..d33bbcdc395 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionRetractFactCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionRetractFactCol52.java @@ -36,16 +36,20 @@ public class LimitedEntryActionRetractFactCol52 extends ActionRetractFactCol52 private DTCellValue52 value; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); LimitedEntryActionRetractFactCol52 other = (LimitedEntryActionRetractFactCol52) otherColumn; // Field: default value. - if ( !isEqualOrNull( this.getValue(), - other.getValue() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VALUE, this.getValueAsString(), other.getValueAsString())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getValue(), + other.getValue() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VALUE, + extractDefaultValue( this.getValue() ), + extractDefaultValue( other.getValue() ) ) ); } return result; @@ -59,9 +63,4 @@ public void setValue( DTCellValue52 value ) { this.value = value; } - public String getValueAsString() { - if (value != null) return value.getValueAsString(); - return ""; - } - } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionSetFieldCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionSetFieldCol52.java index dd0dd86c50f..5569186fdd6 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionSetFieldCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionSetFieldCol52.java @@ -34,16 +34,20 @@ public class LimitedEntryActionSetFieldCol52 extends ActionSetFieldCol52 private DTCellValue52 value; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); LimitedEntryActionSetFieldCol52 other = (LimitedEntryActionSetFieldCol52) otherColumn; // Field: default value. - if ( !isEqualOrNull( this.getValue(), - other.getValue() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VALUE, this.getValueAsString(), other.getValueAsString())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getValue(), + other.getValue() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VALUE, + extractDefaultValue( this.getValue() ), + extractDefaultValue( other.getValue() ) ) ); } return result; @@ -57,9 +61,4 @@ public void setValue( DTCellValue52 value ) { this.value = value; } - public String getValueAsString() { - if (value != null) return value.getValueAsString(); - return ""; - } - } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryConditionCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryConditionCol52.java index 4aeb0880a69..458cc5e1c45 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryConditionCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryConditionCol52.java @@ -35,16 +35,20 @@ public class LimitedEntryConditionCol52 extends ConditionCol52 public static final String FIELD_VALUE = "value"; @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); LimitedEntryConditionCol52 other = (LimitedEntryConditionCol52) otherColumn; // Field: default value. - if ( !isEqualOrNull( this.getValue(), - other.getValue() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_VALUE, this.getValueAsString(), other.getValueAsString())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getValue(), + other.getValue() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_VALUE, + extractDefaultValue( this.getValue() ), + extractDefaultValue( other.getValue() ) ) ); } return result; @@ -58,9 +62,4 @@ public void setValue( DTCellValue52 value ) { this.value = value; } - public String getValueAsString() { - if (value != null) return value.getValueAsString(); - return ""; - } - } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/MetadataCol52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/MetadataCol52.java index fcbe64a26bb..9f63d51e824 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/MetadataCol52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/MetadataCol52.java @@ -15,7 +15,6 @@ */ package org.drools.workbench.models.guided.dtable.shared.model; -import java.util.ArrayList; import java.util.List; /** @@ -39,16 +38,20 @@ public void setMetadata( String metadata ) { } @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } - List result = super.diff(otherColumn); + List result = super.diff( otherColumn ); MetadataCol52 other = (MetadataCol52) otherColumn; // Field: metadata. if ( !isEqualOrNull( this.getMetadata(), - other.getMetadata() ) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_METADATA, this.getMetadata(), other.getMetadata())); + other.getMetadata() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_METADATA, + this.getMetadata(), + other.getMetadata() ) ); } return result; @@ -56,16 +59,15 @@ public List diff(BaseColumn otherColumn) { /** * Clones this metadata column instance. - * * @return The cloned instance. */ public MetadataCol52 cloneColumn() { MetadataCol52 cloned = new MetadataCol52(); - cloned.setMetadata(getMetadata()); - cloned.setWidth(getWidth()); - cloned.setHideColumn(isHideColumn()); - cloned.setHeader(getHeader()); - cloned.setDefaultValue(getDefaultValue() != null ? getDefaultValue().cloneDefaultValueCell() : null ); + cloned.setMetadata( getMetadata() ); + cloned.setWidth( getWidth() ); + cloned.setHideColumn( isHideColumn() ); + cloned.setHeader( getHeader() ); + cloned.setDefaultValue( getDefaultValue() != null ? getDefaultValue().cloneDefaultValueCell() : null ); return cloned; } diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/Pattern52.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/Pattern52.java index 6d5b0f65c3d..f26b7a8c5cf 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/Pattern52.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/Pattern52.java @@ -26,7 +26,8 @@ */ public class Pattern52 implements CompositeColumn, - HasCEPWindow, DiffColumn { + HasCEPWindow, + DiffColumn { // The type of the fact - class - eg Driver, Purchase, Cheese etc. private String factType; @@ -60,47 +61,56 @@ public class Pattern52 public static final String FIELD_ENTRY_POINT_NAME = "entryPointName"; - public Pattern52() { this.conditions = new ArrayList(); } @Override - public List diff(BaseColumn otherColumn) { - if (otherColumn == null) return null; + public List diff( BaseColumn otherColumn ) { + if ( otherColumn == null ) { + return null; + } List result = new ArrayList(); Pattern52 other = (Pattern52) otherColumn; - - // Field: factType. - if ( !BaseColumnFieldDiffImpl.isEqualOrNull(this.getFactType(), - other.getFactType()) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_FACT_TYPE, this.getFactType(), other.getFactType())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getFactType(), + other.getFactType() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_FACT_TYPE, + this.getFactType(), + other.getFactType() ) ); } // Field: boundName. - if ( !BaseColumnFieldDiffImpl.isEqualOrNull(this.getBoundName(), - other.getBoundName()) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_BOUND_NAME, this.getBoundName(), other.getBoundName())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getBoundName(), + other.getBoundName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_BOUND_NAME, + this.getBoundName(), + other.getBoundName() ) ); } // Field: isNegated. if ( this.isNegated() != other.isNegated() ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_IS_NEGATED, this.isNegated(), other.isNegated())); + result.add( new BaseColumnFieldDiffImpl( FIELD_IS_NEGATED, + this.isNegated(), + other.isNegated() ) ); } // Field: window. - if ( !BaseColumnFieldDiffImpl.isEqualOrNull(this.getWindow(), - other.getWindow()) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_WINDOW, this.getWindow(), other.getWindow())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getWindow(), + other.getWindow() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_WINDOW, + this.getWindow(), + other.getWindow() ) ); } // Field: entryPointName. - if ( !BaseColumnFieldDiffImpl.isEqualOrNull(this.getEntryPointName(), - other.getEntryPointName()) ) { - result.add(new BaseColumnFieldDiffImpl(FIELD_ENTRY_POINT_NAME, this.getEntryPointName(), other.getEntryPointName())); + if ( !BaseColumnFieldDiffImpl.isEqualOrNull( this.getEntryPointName(), + other.getEntryPointName() ) ) { + result.add( new BaseColumnFieldDiffImpl( FIELD_ENTRY_POINT_NAME, + this.getEntryPointName(), + other.getEntryPointName() ) ); } return result; @@ -108,32 +118,30 @@ public List diff(BaseColumn otherColumn) { /** * Clones this pattern instance. - * * @return The cloned instance. */ public Pattern52 clonePattern() { Pattern52 cloned = new Pattern52(); - cloned.setBoundName(getBoundName()); - cloned.setChildColumns(new ArrayList(getChildColumns())); - cloned.setEntryPointName(getEntryPointName()); - cloned.setFactType(getFactType()); - cloned.setNegated(isNegated()); - cloned.setWindow(getWindow()); + cloned.setBoundName( getBoundName() ); + cloned.setChildColumns( new ArrayList( getChildColumns() ) ); + cloned.setEntryPointName( getEntryPointName() ); + cloned.setFactType( getFactType() ); + cloned.setNegated( isNegated() ); + cloned.setWindow( getWindow() ); return cloned; } /** * Update this pattern instance properties with the given ones from other pattern instance. - * * @param other The pattern to obtain the properties to set. */ - public void update(Pattern52 other) { - setBoundName(other.getBoundName()); - setChildColumns(other.getChildColumns()); - setEntryPointName(other.getEntryPointName()); - setFactType(other.getFactType()); - setNegated(other.isNegated()); - setWindow(other.getWindow()); + public void update( Pattern52 other ) { + setBoundName( other.getBoundName() ); + setChildColumns( other.getChildColumns() ); + setEntryPointName( other.getEntryPointName() ); + setFactType( other.getFactType() ); + setNegated( other.isNegated() ); + setWindow( other.getWindow() ); } public String getFactType() { diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/resources/ErraiApp.properties b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/resources/ErraiApp.properties index d8d0c84736c..7fea5eae593 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/resources/ErraiApp.properties +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/resources/ErraiApp.properties @@ -63,22 +63,25 @@ errai.marshalling.serializableTypes=org.drools.workbench.models.guided.dtable.sh org.drools.workbench.models.guided.dtable.shared.model.RowNumberCol52 \ org.drools.workbench.models.guided.dtable.shared.model.ActionSetFieldCol52 \ org.drools.workbench.models.guided.dtable.shared.model.ActionWorkItemInsertFactCol52 \ + org.drools.workbench.models.guided.dtable.shared.auditlog.ActionInsertFactColumnDetails \ org.drools.workbench.models.guided.dtable.shared.auditlog.ActionSetFieldColumnDetails \ - org.drools.workbench.models.guided.dtable.shared.auditlog.UpdateColumnAuditLogEntry \ + org.drools.workbench.models.guided.dtable.shared.auditlog.ActionWorkItemColumnDetails \ + org.drools.workbench.models.guided.dtable.shared.auditlog.ActionWorkItemInsertFactColumnDetails \ + org.drools.workbench.models.guided.dtable.shared.auditlog.ActionWorkItemSetFieldColumnDetails \ + org.drools.workbench.models.guided.dtable.shared.auditlog.AttributeColumnDetails \ + org.drools.workbench.models.guided.dtable.shared.auditlog.ColumnDetails \ org.drools.workbench.models.guided.dtable.shared.auditlog.ConditionColumnDetails \ - org.drools.workbench.models.guided.dtable.shared.auditlog.InsertColumnAuditLogEntry \ - org.drools.workbench.models.guided.dtable.shared.auditlog.InsertRowAuditLogEntry \ - org.drools.workbench.models.guided.dtable.shared.auditlog.ActionInsertFactColumnDetails \ + org.drools.workbench.models.guided.dtable.shared.auditlog.DecisionTableAuditEvents \ + org.drools.workbench.models.guided.dtable.shared.auditlog.DecisionTableAuditLogFilter \ org.drools.workbench.models.guided.dtable.shared.auditlog.DeleteColumnAuditLogEntry \ - org.drools.workbench.models.guided.dtable.shared.auditlog.ColumnDetails \ org.drools.workbench.models.guided.dtable.shared.auditlog.DeleteRowAuditLogEntry \ - org.drools.workbench.models.guided.dtable.shared.auditlog.AttributeColumnDetails \ + org.drools.workbench.models.guided.dtable.shared.auditlog.InsertColumnAuditLogEntry \ + org.drools.workbench.models.guided.dtable.shared.auditlog.InsertRowAuditLogEntry \ org.drools.workbench.models.guided.dtable.shared.auditlog.LimitedEntryActionInsertFactColumnDetails \ - org.drools.workbench.models.guided.dtable.shared.auditlog.DecisionTableAuditEvents \ - org.drools.workbench.models.guided.dtable.shared.auditlog.LimitedEntryConditionColumnDetails \ org.drools.workbench.models.guided.dtable.shared.auditlog.LimitedEntryActionSetFieldColumnDetails \ - org.drools.workbench.models.guided.dtable.shared.auditlog.DecisionTableAuditLogFilter \ + org.drools.workbench.models.guided.dtable.shared.auditlog.LimitedEntryConditionColumnDetails \ org.drools.workbench.models.guided.dtable.shared.auditlog.MetadataColumnDetails \ + org.drools.workbench.models.guided.dtable.shared.auditlog.UpdateColumnAuditLogEntry \ org.drools.workbench.models.guided.dtable.shared.conversion.ConversionAsset \ org.drools.workbench.models.guided.dtable.shared.conversion.ConversionMessage \ org.drools.workbench.models.guided.dtable.shared.conversion.ConversionMessageType \ From c82ee78218704a5ccac07450b6c577fdbd151c74 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Fri, 20 Jun 2014 16:32:49 +0200 Subject: [PATCH 22/76] [DROOLS-529] fix synchronization of phreak segments creation (cherry picked from commit f74eb7a980cbb9d3a41f531eaf509a2b498a015e) --- .../impl/StatefulKnowledgeSessionImpl.java | 6 +- .../drools/core/phreak/SegmentUtilities.java | 241 +++++++++--------- .../java/org/drools/core/reteoo/BetaNode.java | 9 +- .../org/drools/core/reteoo/PathMemory.java | 15 +- .../org/drools/core/reteoo/SegmentMemory.java | 22 +- 5 files changed, 153 insertions(+), 140 deletions(-) diff --git a/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java b/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java index acc88b20a51..08c51163c82 100644 --- a/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java +++ b/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java @@ -1242,10 +1242,8 @@ public void fireUntilHalt(final AgendaFilter agendaFilter) { if ( this.firing.compareAndSet( false, true ) ) { try { - synchronized ( this ) { - executeQueuedActions(); - this.agenda.fireUntilHalt( agendaFilter ); - } + executeQueuedActions(); + this.agenda.fireUntilHalt( agendaFilter ); } finally { this.firing.set( false ); } diff --git a/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java b/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java index d999c62a20f..e4d1b0a3482 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java +++ b/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java @@ -68,130 +68,132 @@ public class SegmentUtilities { * * @param wm */ - public static synchronized SegmentMemory createSegmentMemory(LeftTupleSource tupleSource, - final InternalWorkingMemory wm) { - SegmentMemory smem = wm.getNodeMemory((MemoryFactory) tupleSource).getSegmentMemory(); - if ( smem != null ) { - return smem; // this can happen when multiple threads are trying to initialize the segment - } + public static SegmentMemory createSegmentMemory(LeftTupleSource tupleSource, + final InternalWorkingMemory wm) { + synchronized (wm) { + SegmentMemory smem = wm.getNodeMemory((MemoryFactory) tupleSource).getSegmentMemory(); + if ( smem != null ) { + return smem; // this can happen when multiple threads are trying to initialize the segment + } - // find segment root - while (tupleSource.getType() != NodeTypeEnums.LeftInputAdapterNode && - SegmentUtilities.parentInSameSegment(tupleSource, null)) { - tupleSource = tupleSource.getLeftTupleSource(); - } + // find segment root + while (tupleSource.getType() != NodeTypeEnums.LeftInputAdapterNode && + SegmentUtilities.parentInSameSegment(tupleSource, null)) { + tupleSource = tupleSource.getLeftTupleSource(); + } - LeftTupleSource segmentRoot = tupleSource; - int nodeTypesInSegment = 0; + LeftTupleSource segmentRoot = tupleSource; + int nodeTypesInSegment = 0; - smem = restoreSegmentFromPrototype(wm, segmentRoot, nodeTypesInSegment); - if ( smem != null ) { - return smem; - } + smem = restoreSegmentFromPrototype(wm, segmentRoot, nodeTypesInSegment); + if ( smem != null ) { + return smem; + } - smem = new SegmentMemory(segmentRoot); + smem = new SegmentMemory(segmentRoot); - // Iterate all nodes on the same segment, assigning their position as a bit mask value - // allLinkedTestMask is the resulting mask used to test if all nodes are linked in - long nodePosMask = 1; - long allLinkedTestMask = 0; - boolean updateNodeBit = true; // nodes after a branch CE can notify, but they cannot impact linking + // Iterate all nodes on the same segment, assigning their position as a bit mask value + // allLinkedTestMask is the resulting mask used to test if all nodes are linked in + long nodePosMask = 1; + long allLinkedTestMask = 0; + boolean updateNodeBit = true; // nodes after a branch CE can notify, but they cannot impact linking - while (true) { - nodeTypesInSegment = updateNodeTypesMask(tupleSource, nodeTypesInSegment); - if ( tupleSource.isStreamMode() && smem.getStreamQueue() == null ) { - // need to make sure there is one Queue, for the rule, when a stream mode node is found. + while (true) { + nodeTypesInSegment = updateNodeTypesMask(tupleSource, nodeTypesInSegment); + if ( tupleSource.isStreamMode() && smem.getStreamQueue() == null ) { + // need to make sure there is one Queue, for the rule, when a stream mode node is found. - StreamTupleEntryQueue queue = initAndGetTupleQueue(tupleSource, wm); - smem.setStreamQueue( queue ); - } - if (NodeTypeEnums.isBetaNode(tupleSource)) { - allLinkedTestMask = processBetaNode(tupleSource, wm, smem, nodePosMask, allLinkedTestMask, updateNodeBit); - } else { - switch (tupleSource.getType()) { - case NodeTypeEnums.LeftInputAdapterNode: - allLinkedTestMask = processLiaNode((LeftInputAdapterNode) tupleSource, wm, smem, nodePosMask, allLinkedTestMask); - break; - case NodeTypeEnums.EvalConditionNode: - processEvalNode((EvalConditionNode) tupleSource, wm, smem); - break; - case NodeTypeEnums.ConditionalBranchNode: - updateNodeBit = processBranchNode((ConditionalBranchNode) tupleSource, wm, smem); - break; - case NodeTypeEnums.FromNode: - processFromNode((FromNode) tupleSource, wm, smem); - break; - case NodeTypeEnums.TimerConditionNode: - processTimerNode((TimerNode) tupleSource, wm, smem, nodePosMask); - break; - case NodeTypeEnums.QueryElementNode: - updateNodeBit = processQueryNode((QueryElementNode) tupleSource, wm, segmentRoot, smem, nodePosMask); - break; + StreamTupleEntryQueue queue = initAndGetTupleQueue(tupleSource, wm); + smem.setStreamQueue( queue ); } - } - nodePosMask = nodePosMask << 1; - - if (tupleSource.getSinkPropagator().size() == 1) { - LeftTupleSinkNode sink = (LeftTupleSinkNode) tupleSource.getSinkPropagator().getFirstLeftTupleSink(); - if (NodeTypeEnums.isLeftTupleSource(sink)) { - tupleSource = (LeftTupleSource) sink; + if (NodeTypeEnums.isBetaNode(tupleSource)) { + allLinkedTestMask = processBetaNode(tupleSource, wm, smem, nodePosMask, allLinkedTestMask, updateNodeBit); } else { - // rtn or rian - // While not technically in a segment, we want to be able to iterate easily from the last node memory to the ria/rtn memory - // we don't use createNodeMemory, as these may already have been created by, but not added, by the method updateRiaAndTerminalMemory - Memory memory = wm.getNodeMemory((MemoryFactory) sink); - if (sink.getType() == NodeTypeEnums.RightInputAdaterNode) { - PathMemory riaPmem = ((RiaNodeMemory)memory).getRiaPathMemory(); - smem.getNodeMemories().add( riaPmem ); - - RightInputAdapterNode rian = ( RightInputAdapterNode ) sink; - ObjectSink[] nodes = rian.getSinkPropagator().getSinks(); - for ( ObjectSink node : nodes ) { - if ( NodeTypeEnums.isLeftTupleSource(node) ) { - SegmentMemory parentSmem = createSegmentMemory( (LeftTupleSource) node, wm ); + switch (tupleSource.getType()) { + case NodeTypeEnums.LeftInputAdapterNode: + allLinkedTestMask = processLiaNode((LeftInputAdapterNode) tupleSource, wm, smem, nodePosMask, allLinkedTestMask); + break; + case NodeTypeEnums.EvalConditionNode: + processEvalNode((EvalConditionNode) tupleSource, wm, smem); + break; + case NodeTypeEnums.ConditionalBranchNode: + updateNodeBit = processBranchNode((ConditionalBranchNode) tupleSource, wm, smem); + break; + case NodeTypeEnums.FromNode: + processFromNode((FromNode) tupleSource, wm, smem); + break; + case NodeTypeEnums.TimerConditionNode: + processTimerNode((TimerNode) tupleSource, wm, smem, nodePosMask); + break; + case NodeTypeEnums.QueryElementNode: + updateNodeBit = processQueryNode((QueryElementNode) tupleSource, wm, segmentRoot, smem, nodePosMask); + break; + } + } + nodePosMask = nodePosMask << 1; + + if (tupleSource.getSinkPropagator().size() == 1) { + LeftTupleSinkNode sink = (LeftTupleSinkNode) tupleSource.getSinkPropagator().getFirstLeftTupleSink(); + if (NodeTypeEnums.isLeftTupleSource(sink)) { + tupleSource = (LeftTupleSource) sink; + } else { + // rtn or rian + // While not technically in a segment, we want to be able to iterate easily from the last node memory to the ria/rtn memory + // we don't use createNodeMemory, as these may already have been created by, but not added, by the method updateRiaAndTerminalMemory + Memory memory = wm.getNodeMemory((MemoryFactory) sink); + if (sink.getType() == NodeTypeEnums.RightInputAdaterNode) { + PathMemory riaPmem = ((RiaNodeMemory)memory).getRiaPathMemory(); + smem.getNodeMemories().add( riaPmem ); + + RightInputAdapterNode rian = ( RightInputAdapterNode ) sink; + ObjectSink[] nodes = rian.getSinkPropagator().getSinks(); + for ( ObjectSink node : nodes ) { + if ( NodeTypeEnums.isLeftTupleSource(node) ) { + SegmentMemory parentSmem = createSegmentMemory( (LeftTupleSource) node, wm ); + } } + } else if (NodeTypeEnums.isTerminalNode(sink)) { + smem.getNodeMemories().add((PathMemory)memory); } - } else if (NodeTypeEnums.isTerminalNode(sink)) { - smem.getNodeMemories().add((PathMemory)memory); + memory.setSegmentMemory(smem); + smem.setTipNode(sink); + break; } - memory.setSegmentMemory(smem); - smem.setTipNode(sink); + } else { + // not in same segment + smem.setTipNode(tupleSource); break; } - } else { - // not in same segment - smem.setTipNode(tupleSource); - break; } - } - smem.setAllLinkedMaskTest(allLinkedTestMask); - - // iterate to find root and determine the SegmentNodes position in the RuleSegment - LeftTupleSource pathRoot = segmentRoot; - int ruleSegmentPosMask = 1; - int counter = 0; - while (pathRoot.getType() != NodeTypeEnums.LeftInputAdapterNode) { - if (!SegmentUtilities.parentInSameSegment(pathRoot, null)) { - // for each new found segment, increase the mask bit position - ruleSegmentPosMask = ruleSegmentPosMask << 1; - counter++; + smem.setAllLinkedMaskTest(allLinkedTestMask); + + // iterate to find root and determine the SegmentNodes position in the RuleSegment + LeftTupleSource pathRoot = segmentRoot; + int ruleSegmentPosMask = 1; + int counter = 0; + while (pathRoot.getType() != NodeTypeEnums.LeftInputAdapterNode) { + if (!SegmentUtilities.parentInSameSegment(pathRoot, null)) { + // for each new found segment, increase the mask bit position + ruleSegmentPosMask = ruleSegmentPosMask << 1; + counter++; + } + pathRoot = pathRoot.getLeftTupleSource(); } - pathRoot = pathRoot.getLeftTupleSource(); - } - smem.setSegmentPosMaskBit(ruleSegmentPosMask); - smem.setPos(counter); + smem.setSegmentPosMaskBit(ruleSegmentPosMask); + smem.setPos(counter); - if (smem.getRootNode().getType() != NodeTypeEnums.LeftInputAdapterNode && - ((LeftTupleSource)smem.getRootNode()).getLeftTupleSource().getType() == NodeTypeEnums.LeftInputAdapterNode ) { - // If LiaNode is in it's own segment, then the segment first after that must use SynchronizedLeftTupleSets - smem.setStagedTuples( new SynchronizedLeftTupleSets() ); - } + if (smem.getRootNode().getType() != NodeTypeEnums.LeftInputAdapterNode && + ((LeftTupleSource)smem.getRootNode()).getLeftTupleSource().getType() == NodeTypeEnums.LeftInputAdapterNode ) { + // If LiaNode is in it's own segment, then the segment first after that must use SynchronizedLeftTupleSets + smem.setStagedTuples( new SynchronizedLeftTupleSets() ); + } - nodeTypesInSegment = updateRiaAndTerminalMemory(tupleSource, tupleSource, smem, wm, false, nodeTypesInSegment); + nodeTypesInSegment = updateRiaAndTerminalMemory(tupleSource, tupleSource, smem, wm, false, nodeTypesInSegment); - ((KnowledgeBaseImpl)wm.getKnowledgeBase()).registerSegmentPrototype(segmentRoot, smem); + ((KnowledgeBaseImpl)wm.getKnowledgeBase()).registerSegmentPrototype(segmentRoot, smem); - return smem; + return smem; + } } private static SegmentMemory restoreSegmentFromPrototype(InternalWorkingMemory wm, LeftTupleSource segmentRoot, int nodeTypesInSegment) { @@ -312,17 +314,19 @@ private static long processBetaNode(LeftTupleSource tupleSource, InternalWorking return allLinkedTestMask; } - public static synchronized void createChildSegments(final InternalWorkingMemory wm, - SegmentMemory smem, - LeftTupleSinkPropagator sinkProp) { - if ( !smem.isEmpty() ) { - return; // this can happen when multiple threads are trying to initialize the segment - } - for (LeftTupleSinkNode sink = (LeftTupleSinkNode) sinkProp.getFirstLeftTupleSink(); sink != null; sink = sink.getNextLeftTupleSinkNode()) { - Memory memory = wm.getNodeMemory((MemoryFactory) sink); + public static void createChildSegments(final InternalWorkingMemory wm, + SegmentMemory smem, + LeftTupleSinkPropagator sinkProp) { + synchronized (smem) { + if ( !smem.isEmpty() ) { + return; // this can happen when multiple threads are trying to initialize the segment + } + for (LeftTupleSinkNode sink = (LeftTupleSinkNode) sinkProp.getFirstLeftTupleSink(); sink != null; sink = sink.getNextLeftTupleSinkNode()) { + Memory memory = wm.getNodeMemory((MemoryFactory) sink); - SegmentMemory childSmem = createChildSegment(wm, sink, memory); - smem.add(childSmem); + SegmentMemory childSmem = createChildSegment(wm, sink, memory); + smem.add(childSmem); + } } } @@ -513,15 +517,12 @@ public static boolean parentInSameSegment(LeftTupleSource lt, RuleImpl removingR // looks like a split, but one of the branches may be removed. LeftTupleSink first = parentLt.getSinkPropagator().getFirstLeftTupleSink(); - LeftTupleSink last = parentLt.getSinkPropagator().getLastLeftTupleSink(); - if (first.getAssociations().size() == 1 && first.getAssociations().containsKey(removingRule)) { return true; - } else if (last.getAssociations().size() == 1 && last.getAssociations().containsKey(removingRule)) { - return true; - } else { - return false; } + + LeftTupleSink last = parentLt.getSinkPropagator().getLastLeftTupleSink(); + return last.getAssociations().size() == 1 && last.getAssociations().containsKey(removingRule); } else { return size == 1; } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java index 802ce047b6b..b293b3146e8 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java @@ -69,7 +69,8 @@ public abstract class BetaNode extends LeftTupleSource RightTupleSink, MemoryFactory { - protected static transient Logger log = LoggerFactory.getLogger(BetaNode.class); + protected static final Logger log = LoggerFactory.getLogger(BetaNode.class); + protected static final boolean isLogTraceEnabled = log.isTraceEnabled(); protected ObjectSource rightInput; @@ -286,13 +287,13 @@ public void assertObject( final InternalFactHandle factHandle, if ( streamMode ) { int propagationType = pctx.getType() == PropagationContext.MODIFICATION ? PropagationContext.INSERTION : pctx.getType(); stagedInsertWasEmpty = memory.getSegmentMemory().getStreamQueue().addInsert(new RightTupleEntry(rightTuple, pctx, memory, propagationType)); - if ( log.isTraceEnabled() ) { + if ( isLogTraceEnabled ) { log.trace( "JoinNode insert queue={} size={} pctx={} lt={}", System.identityHashCode( memory.getSegmentMemory().getStreamQueue() ), memory.getSegmentMemory().getStreamQueue().size(), PhreakPropagationContext.intEnumToString(pctx), rightTuple ); } } else { stagedInsertWasEmpty = memory.getStagedRightTuples().addInsert(rightTuple); } - if ( log.isTraceEnabled() ) { + if ( isLogTraceEnabled ) { log.trace("BetaNode insert={} stagedInsertWasEmpty={}", memory.getStagedRightTuples().insertSize(), stagedInsertWasEmpty ); } if ( memory.getAndIncCounter() == 0 ) { @@ -355,7 +356,7 @@ public void doDeleteRightTuple(final RightTuple rightTuple, PropagationContext pctx = rightTuple.getPropagationContext(); int propagationType = pctx.getType() == PropagationContext.MODIFICATION ? PropagationContext.DELETION : pctx.getType(); stagedDeleteWasEmpty = memory.getSegmentMemory().getStreamQueue().addDelete(new RightTupleEntry(rightTuple, pctx, memory, propagationType)); - if ( log.isTraceEnabled() ) { + if ( isLogTraceEnabled ) { log.trace( "{} delete queue={} size={} pctx={} lt={}", getClass().getSimpleName(), System.identityHashCode( memory.getSegmentMemory().getStreamQueue() ), memory.getSegmentMemory().getStreamQueue().size(), PhreakPropagationContext.intEnumToString(rightTuple.getPropagationContext()), rightTuple ); } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java index 30df768ccc8..0c88677e669 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java @@ -18,7 +18,10 @@ public class PathMemory extends AbstractBaseLinkedListNode implements Memory { - protected static transient Logger log = LoggerFactory.getLogger(PathMemory.class); + + protected static final Logger log = LoggerFactory.getLogger(PathMemory.class); + protected static final boolean isLogTraceEnabled = log.isTraceEnabled(); + private AtomicBitwiseLong linkedSegmentMask; private long allLinkedMaskTest; private NetworkNode networkNode; @@ -75,7 +78,7 @@ public void linkNodeWithoutRuleNotify(long mask) { public void linkSegment(long mask, InternalWorkingMemory wm) { linkedSegmentMask.getAndBitwiseOr( mask ); - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { if (NodeTypeEnums.isTerminalNode(getNetworkNode())) { TerminalNode rtn = (TerminalNode) getNetworkNode(); log.trace(" LinkSegment smask={} rmask={} name={}", mask, linkedSegmentMask, rtn.getRule().getName()); @@ -110,7 +113,7 @@ private TerminalNode ensureAgendaItemCreated(InternalWorkingMemory wm) { public synchronized void doLinkRule(InternalWorkingMemory wm) { TerminalNode rtn = ensureAgendaItemCreated(wm); - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { log.trace(" LinkRule name={}", rtn.getRule().getName()); } @@ -119,7 +122,7 @@ public synchronized void doLinkRule(InternalWorkingMemory wm) { public synchronized void doUnlinkRule(InternalWorkingMemory wm) { TerminalNode rtn = ensureAgendaItemCreated(wm); - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { log.trace(" UnlinkRule name={}", rtn.getRule().getName()); } @@ -138,7 +141,7 @@ public void queueRuleAgendaItem(InternalWorkingMemory wm) { } if (!agendaItem.isQueued() && !agendaItem.isBlocked()) { - if ( log.isTraceEnabled() ) { + if ( isLogTraceEnabled ) { log.trace("Queue RuleAgendaItem {}", agendaItem); } InternalAgendaGroup ag = agendaItem.getAgendaGroup(); @@ -156,7 +159,7 @@ public void unlinkedSegment(long mask, InternalWorkingMemory wm) { boolean linkedRule = isRuleLinked(); linkedSegmentMask.getAndBitwiseXor( mask ); - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { log.trace(" UnlinkSegment smask={} rmask={} name={}", mask, linkedSegmentMask, this); } if (linkedRule && !isRuleLinked()) { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java index ef44d8b5036..0b6bc049f1d 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java @@ -26,7 +26,9 @@ public class SegmentMemory extends LinkedList implements LinkedListNode { - protected static transient Logger log = LoggerFactory.getLogger(SegmentMemory.class); + protected static final Logger log = LoggerFactory.getLogger(SegmentMemory.class); + protected static final boolean isLogTraceEnabled = log.isTraceEnabled(); + private NetworkNode rootNode; private NetworkNode tipNode; private LinkedList nodeMemories; @@ -137,7 +139,7 @@ public void linkNode(long mask, InternalWorkingMemory wm) { linkedNodeMask.getAndBitwiseOr( mask ); //dirtyNodeMask = dirtyNodeMask | mask; - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { log.trace("LinkNode notify=true nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames()); } @@ -147,7 +149,7 @@ public void linkNode(long mask, public void linkNodeWithoutRuleNotify(long mask) { linkedNodeMask.getAndBitwiseOr( mask ); //dirtyNodeMask = dirtyNodeMask | mask; - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { log.trace("LinkNode notify=false nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames()); } @@ -188,7 +190,7 @@ public void unlinkNode(long mask, //dirtyNodeMask = dirtyNodeMask | mask; - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { log.trace("UnlinkNode notify=true nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames()); } @@ -212,7 +214,7 @@ public void unlinkNode(long mask, public void unlinkNodeWithoutRuleNotify(long mask) { linkedNodeMask.getAndBitwiseXor( mask ); //dirtyNodeMask = dirtyNodeMask | mask; - if (log.isTraceEnabled()) { + if (isLogTraceEnabled) { log.trace("UnlinkNode notify=false nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames()); } } @@ -334,6 +336,7 @@ public static class Prototype { private List memories = new ArrayList(); private boolean hasQueue; private boolean hasSyncStagedLeftTuple; + private List nodesInSegment; private Prototype(SegmentMemory smem) { this.rootNode = smem.rootNode; @@ -357,7 +360,7 @@ public SegmentMemory newSegmentMemory(InternalWorkingMemory wm) { smem.segmentPosMaskBit = segmentPosMaskBit; smem.pos = pos; int i = 0; - for (NetworkNode node : smem.getNodesInSegment()) { + for (NetworkNode node : getNodesInSegment(smem)) { Memory mem = wm.getNodeMemory((MemoryFactory) node); mem.setSegmentMemory(smem); smem.getNodeMemories().add(mem); @@ -378,6 +381,13 @@ public SegmentMemory newSegmentMemory(InternalWorkingMemory wm) { } return smem; } + + private List getNodesInSegment(SegmentMemory smem) { + if (nodesInSegment == null) { + nodesInSegment = smem.getNodesInSegment(); + } + return nodesInSegment; + } } public abstract static class MemoryPrototype { From fc815435314ef45ba1449f15c15d3242c34623c2 Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Mon, 23 Jun 2014 15:07:56 +0100 Subject: [PATCH 23/76] BZ1112278 - Rule re-opens with one of the field type changed from String to Integer in BRMS 6.0.1 (cherry picked from commit 73c1ee5f3339c4acf4e270b67963085c9357813a) --- .../backend/rule/ActionCallMethodBuilder.java | 12 ++- ...eModelDRLPersistenceUnmarshallingTest.java | 82 +++++++++++++++++-- 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/ActionCallMethodBuilder.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/ActionCallMethodBuilder.java index 122fb901299..bec44089c5c 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/ActionCallMethodBuilder.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/ActionCallMethodBuilder.java @@ -21,6 +21,7 @@ public class ActionCallMethodBuilder { private String methodName; private String variable; private String[] parameters; + private int index; public ActionCallMethodBuilder( RuleModel model, PackageDataModelOracle dmo, @@ -35,7 +36,6 @@ public ActionCallMethodBuilder( RuleModel model, public ActionCallMethod get( String variable, String methodName, String[] parameters ) { - this.variable = variable; this.methodName = methodName; this.parameters = parameters; @@ -43,7 +43,7 @@ public ActionCallMethod get( String variable, ActionCallMethod actionCallMethod = new ActionCallMethod(); actionCallMethod.setMethodName( methodName ); actionCallMethod.setVariable( variable ); - actionCallMethod.setState( 1 ); + actionCallMethod.setState( ActionCallMethod.TYPE_DEFINED ); for ( ActionFieldFunction parameter : getActionFieldFunctions() ) { actionCallMethod.addFieldValue( parameter ); @@ -56,7 +56,7 @@ private List getActionFieldFunctions() { List actionFieldFunctions = new ArrayList(); - int index = 0; + this.index = 0; for ( String param : parameters ) { param = param.trim(); if ( param.length() == 0 ) { @@ -64,8 +64,7 @@ private List getActionFieldFunctions() { } actionFieldFunctions.add( getActionFieldFunction( param, - getDataType( param, - index ) ) ); + getDataType( param ) ) ); } return actionFieldFunctions; } @@ -98,8 +97,7 @@ private ActionFieldFunction getActionFieldFunction( String param, return actionFiled; } - private String getDataType( String param, - int index ) { + private String getDataType( String param ) { String dataType; MethodInfo methodInfo = getMethodInfo(); diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java index f754853e6b9..1bbdce1bc31 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java @@ -15,6 +15,13 @@ * limitations under the License. */ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.FieldAccessorsAndMutators; import org.drools.workbench.models.datamodel.oracle.MethodInfo; @@ -58,16 +65,8 @@ import org.junit.Before; import org.junit.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; public class RuleModelDRLPersistenceUnmarshallingTest { @@ -4916,6 +4915,71 @@ public void testLiteralStrFieldNames() throws Exception { sfp1.getFieldType() ); } + @Test + public void testMethodCallWithTwoParametersIntegerAndString() throws Exception { + String drl = "package org.mortgages;\n" + + "rule \"test\"\n" + + " dialect \"mvel\"\n" + + " when\n" + + " $t : TestClass()\n" + + " then\n" + + " $t.testFunction( 123, \"hello\" );\n" + + "end"; + + final HashMap> map = new HashMap>(); + final ArrayList methodInfos = new ArrayList(); + final ArrayList params = new ArrayList(); + params.add( "Integer" ); + params.add( "String" ); + methodInfos.add( new MethodInfo( "testFunction", + params, + "java.lang.Void", + null, + "TestClass" ) ); + map.put( "TestClass", + methodInfos ); + + when( dmo.getProjectMethodInformation() ).thenReturn( map ); + + final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + new ArrayList(), + dmo ); + + assertNotNull( m ); + + assertEquals( 1, + m.lhs.length ); + + assertEquals( 1, + m.rhs.length ); + + ActionCallMethod actionCallMethod = (ActionCallMethod) m.rhs[ 0 ]; + assertEquals( "testFunction", + actionCallMethod.getMethodName() ); + assertEquals( "$t", + actionCallMethod.getVariable() ); + assertEquals( 2, + actionCallMethod.getFieldValues().length ); + + assertEquals( "testFunction", + actionCallMethod.getFieldValue( 0 ).getField() ); + assertEquals( "123", + actionCallMethod.getFieldValue( 0 ).getValue() ); + assertEquals( FieldNatureType.TYPE_LITERAL, + actionCallMethod.getFieldValue( 0 ).getNature() ); + assertEquals( "Integer", + actionCallMethod.getFieldValue( 0 ).getType() ); + + assertEquals( "testFunction", + actionCallMethod.getFieldValue( 1 ).getField() ); + assertEquals( "hello", + actionCallMethod.getFieldValue( 1 ).getValue() ); + assertEquals( FieldNatureType.TYPE_LITERAL, + actionCallMethod.getFieldValue( 1 ).getNature() ); + assertEquals( "String", + actionCallMethod.getFieldValue( 1 ).getType() ); + } + private void assertEqualsIgnoreWhitespace( final String expected, final String actual ) { final String cleanExpected = expected.replaceAll( "\\s+", From c85b684440501e5ab7377cade97af729a713116d Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Wed, 25 Jun 2014 15:37:29 +0100 Subject: [PATCH 24/76] BZ975922 - GRE constraint operator list box problems when re-opening file (cherry picked from commit b6fcb0ba231e39b85e71c61ed5521fc67a2f98e8) --- .../rule/RuleModelDRLPersistenceImpl.java | 872 +++++++++++------- .../rule/RuleModelPersistenceHelper.java | 65 +- .../rule/RuleModelDRLPersistenceTest.java | 32 +- ...eModelDRLPersistenceUnmarshallingTest.java | 216 ++++- 4 files changed, 802 insertions(+), 383 deletions(-) diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java index fdaca19222e..c6b56e247ca 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java @@ -1730,8 +1730,8 @@ public RuleModel unmarshalUsingDSL( final String str, dmo ); } - private ExpandedDRLInfo parseDSLs( ExpandedDRLInfo expandedDRLInfo, - String[] dsls ) { + private ExpandedDRLInfo parseDSLs( final ExpandedDRLInfo expandedDRLInfo, + final String[] dsls ) { for ( String dsl : dsls ) { for ( String line : dsl.split( "\n" ) ) { String dslPattern = line.trim(); @@ -1751,7 +1751,7 @@ private ExpandedDRLInfo parseDSLs( ExpandedDRLInfo expandedDRLInfo, return expandedDRLInfo; } - private String removeDslTopics( String line ) { + private String removeDslTopics( final String line ) { int lastClosedSquare = -1; boolean lookForOpen = true; for ( int i = 0; i < line.length(); i++ ) { @@ -1772,12 +1772,13 @@ private String removeDslTopics( String line ) { return line.substring( lastClosedSquare + 1 ); } - private String extractDslPattern( String line ) { - return line.substring( 0, line.indexOf( '=' ) ).trim(); + private String extractDslPattern( final String line ) { + return line.substring( 0, + line.indexOf( '=' ) ).trim(); } - private RuleModel getRuleModel( ExpandedDRLInfo expandedDRLInfo, - PackageDataModelOracle dmo ) { + private RuleModel getRuleModel( final ExpandedDRLInfo expandedDRLInfo, + final PackageDataModelOracle dmo ) { //De-serialize model RuleDescr ruleDescr = parseDrl( expandedDRLInfo ); RuleModel model = new RuleModel(); @@ -1787,7 +1788,8 @@ private RuleModel getRuleModel( ExpandedDRLInfo expandedDRLInfo, Map annotations = ruleDescr.getAnnotations(); if ( annotations != null ) { for ( AnnotationDescr annotation : annotations.values() ) { - model.addMetadata( new RuleMetadata( annotation.getName(), annotation.getValuesAsString() ) ); + model.addMetadata( new RuleMetadata( annotation.getName(), + annotation.getValuesAsString() ) ); } } @@ -1803,7 +1805,10 @@ private RuleModel getRuleModel( ExpandedDRLInfo expandedDRLInfo, boolean isJavaDialect = parseAttributes( model, ruleDescr.getAttributes() ); - Map boundParams = parseLhs( model, ruleDescr.getLhs(), expandedDRLInfo, dmo ); + Map boundParams = parseLhs( model, + ruleDescr.getLhs(), + expandedDRLInfo, + dmo ); parseRhs( model, expandedDRLInfo.consequence != null ? expandedDRLInfo.consequence : (String) ruleDescr.getConsequence(), isJavaDialect, @@ -1813,8 +1818,8 @@ private RuleModel getRuleModel( ExpandedDRLInfo expandedDRLInfo, return model; } - private ExpandedDRLInfo preprocessDRL( String str, - boolean hasDsl ) { + private ExpandedDRLInfo preprocessDRL( final String str, + final boolean hasDsl ) { StringBuilder drl = new StringBuilder(); String thenLine = null; List lhsStatements = new ArrayList(); @@ -1869,11 +1874,11 @@ private int parenthesisBalance( String str ) { return balance; } - private ExpandedDRLInfo createExpandedDRLInfo( boolean hasDsl, - StringBuilder drl, - String thenLine, - List lhsStatements, - List rhsStatements ) { + private ExpandedDRLInfo createExpandedDRLInfo( final boolean hasDsl, + final StringBuilder drl, + final String thenLine, + final List lhsStatements, + final List rhsStatements ) { if ( !hasDsl ) { return processFreeFormStatement( drl, thenLine, @@ -1906,13 +1911,15 @@ private ExpandedDRLInfo createExpandedDRLInfo( boolean hasDsl, lineCounter++; String trimmed = statement.trim(); if ( trimmed.endsWith( "end" ) ) { - trimmed = trimmed.substring( 0, trimmed.length() - 3 ).trim(); + trimmed = trimmed.substring( 0, + trimmed.length() - 3 ).trim(); } if ( trimmed.length() > 0 ) { if ( hasDsl && trimmed.startsWith( ">" ) ) { drl.append( trimmed.substring( 1 ) ).append( "\n" ); } else { - expandedDRLInfo.dslStatementsInRhs.put( lineCounter, trimmed ); + expandedDRLInfo.dslStatementsInRhs.put( lineCounter, + trimmed ); } } } @@ -1922,10 +1929,10 @@ private ExpandedDRLInfo createExpandedDRLInfo( boolean hasDsl, return expandedDRLInfo; } - private ExpandedDRLInfo processFreeFormStatement( StringBuilder drl, - String thenLine, - List lhsStatements, - List rhsStatements ) { + private ExpandedDRLInfo processFreeFormStatement( final StringBuilder drl, + final String thenLine, + final List lhsStatements, + final List rhsStatements ) { ExpandedDRLInfo expandedDRLInfo = new ExpandedDRLInfo( false ); int lineCounter = -1; @@ -1959,7 +1966,7 @@ private ExpandedDRLInfo processFreeFormStatement( StringBuilder drl, return expandedDRLInfo; } - private boolean isValidLHSStatement( String lhs ) { + private boolean isValidLHSStatement( final String lhs ) { // TODO: How to identify a non valid (free form) lhs statement? return ( lhs.indexOf( '(' ) >= 0 || lhs.indexOf( ':' ) >= 0 ) && lhs.indexOf( "//" ) == -1; } @@ -1982,7 +1989,7 @@ private static class ExpandedDRLInfo { private Set globals = new HashSet(); - private ExpandedDRLInfo( boolean hasDsl ) { + private ExpandedDRLInfo( final boolean hasDsl ) { this.hasDsl = hasDsl; dslStatementsInLhs = new HashMap(); dslStatementsInRhs = new HashMap(); @@ -1991,12 +1998,12 @@ private ExpandedDRLInfo( boolean hasDsl ) { rhsDslPatterns = new ArrayList(); } - public boolean hasGlobal( String name ) { + public boolean hasGlobal( final String name ) { return globals.contains( name ); } - public ExpandedDRLInfo registerGlobals( PackageDataModelOracle dmo, - List globalStatements ) { + public ExpandedDRLInfo registerGlobals( final PackageDataModelOracle dmo, + final List globalStatements ) { if ( globalStatements != null ) { for ( String globalStatement : globalStatements ) { String identifier = getIdentifier( globalStatement ); @@ -2023,12 +2030,13 @@ private String getIdentifier( String globalStatement ) { } String identifier = globalStatement.substring( lastSpace + 1 ); if ( identifier.endsWith( ";" ) ) { - identifier = identifier.substring( 0, identifier.length() - 1 ); + identifier = identifier.substring( 0, + identifier.length() - 1 ); } return identifier; } - public ExpandedDRLInfo registerGlobalDescrs( List globalDescrs ) { + public ExpandedDRLInfo registerGlobalDescrs( final List globalDescrs ) { if ( globalDescrs != null ) { for ( GlobalDescr globalDescr : globalDescrs ) { globals.add( globalDescr.getIdentifier() ); @@ -2038,7 +2046,7 @@ public ExpandedDRLInfo registerGlobalDescrs( List globalDescrs ) { } } - private RuleDescr parseDrl( ExpandedDRLInfo expandedDRLInfo ) { + private RuleDescr parseDrl( final ExpandedDRLInfo expandedDRLInfo ) { DrlParser drlParser = new DrlParser(); PackageDescr packageDescr; try { @@ -2050,13 +2058,14 @@ private RuleDescr parseDrl( ExpandedDRLInfo expandedDRLInfo ) { return packageDescr.getRules().get( 0 ); } - private boolean parseAttributes( RuleModel m, - Map attributes ) { + private boolean parseAttributes( final RuleModel m, + final Map attributes ) { boolean isJavaDialect = false; for ( Map.Entry entry : attributes.entrySet() ) { String name = entry.getKey(); String value = normalizeAttributeValue( entry.getValue().getValue().trim() ); - RuleAttribute ruleAttribute = new RuleAttribute( name, value ); + RuleAttribute ruleAttribute = new RuleAttribute( name, + value ); m.addAttribute( ruleAttribute ); isJavaDialect |= name.equals( "dialect" ) && value.equals( "java" ); } @@ -2086,47 +2095,59 @@ private String stripQuotes( String value ) { return value; } - private Map parseLhs( RuleModel m, - AndDescr lhs, - ExpandedDRLInfo expandedDRLInfo, - PackageDataModelOracle dmo ) { + private Map parseLhs( final RuleModel m, + final AndDescr lhs, + final ExpandedDRLInfo expandedDRLInfo, + final PackageDataModelOracle dmo ) { Map boundParams = new HashMap(); int lineCounter = -1; for ( BaseDescr descr : lhs.getDescrs() ) { - lineCounter = parseNonDrlInLhs( m, expandedDRLInfo, lineCounter ); - IPattern pattern = parseBaseDescr( m, descr, boundParams, dmo ); + lineCounter = parseNonDrlInLhs( m, + expandedDRLInfo, + lineCounter ); + IPattern pattern = parseBaseDescr( m, + descr, + boundParams, + dmo ); if ( pattern != null ) { m.addLhsItem( pattern ); } } - parseNonDrlInLhs( m, expandedDRLInfo, lineCounter ); + parseNonDrlInLhs( m, + expandedDRLInfo, + lineCounter ); return boundParams; } - private int parseNonDrlInLhs( RuleModel m, - ExpandedDRLInfo expandedDRLInfo, + private int parseNonDrlInLhs( final RuleModel m, + final ExpandedDRLInfo expandedDRLInfo, int lineCounter ) { lineCounter++; - lineCounter = parseDslInLhs( m, expandedDRLInfo, lineCounter ); - lineCounter = parseFreeForm( m, expandedDRLInfo, lineCounter ); + lineCounter = parseDslInLhs( m, + expandedDRLInfo, + lineCounter ); + lineCounter = parseFreeForm( m, + expandedDRLInfo, + lineCounter ); return lineCounter; } - private int parseDslInLhs( RuleModel m, - ExpandedDRLInfo expandedDRLInfo, + private int parseDslInLhs( final RuleModel m, + final ExpandedDRLInfo expandedDRLInfo, int lineCounter ) { if ( expandedDRLInfo.hasDsl ) { String dslLine = expandedDRLInfo.dslStatementsInLhs.get( lineCounter ); while ( dslLine != null ) { - m.addLhsItem( toDSLSentence( expandedDRLInfo.lhsDslPatterns, dslLine ) ); + m.addLhsItem( toDSLSentence( expandedDRLInfo.lhsDslPatterns, + dslLine ) ); dslLine = expandedDRLInfo.dslStatementsInLhs.get( ++lineCounter ); } } return lineCounter; } - private int parseFreeForm( RuleModel m, - ExpandedDRLInfo expandedDRLInfo, + private int parseFreeForm( final RuleModel m, + final ExpandedDRLInfo expandedDRLInfo, int lineCounter ) { String freeForm = expandedDRLInfo.freeFormStatementsInLhs.get( lineCounter ); while ( freeForm != null ) { @@ -2138,39 +2159,55 @@ private int parseFreeForm( RuleModel m, return lineCounter; } - private IPattern parseBaseDescr( RuleModel m, - BaseDescr descr, - Map boundParams, - PackageDataModelOracle dmo ) { + private IPattern parseBaseDescr( final RuleModel m, + final BaseDescr descr, + final Map boundParams, + final PackageDataModelOracle dmo ) { if ( descr instanceof PatternDescr ) { - return parsePatternDescr( m, (PatternDescr) descr, boundParams, dmo ); + return parsePatternDescr( m, + (PatternDescr) descr, + boundParams, + dmo ); } else if ( descr instanceof AndDescr ) { AndDescr andDescr = (AndDescr) descr; - return parseBaseDescr( m, andDescr.getDescrs().get( 0 ), boundParams, dmo ); + return parseBaseDescr( m, + andDescr.getDescrs().get( 0 ), + boundParams, + dmo ); } else if ( descr instanceof EvalDescr ) { FreeFormLine freeFormLine = new FreeFormLine(); freeFormLine.setText( "eval( " + ( (EvalDescr) descr ).getContent() + " )" ); return freeFormLine; } else if ( descr instanceof ConditionalElementDescr ) { - return parseExistentialElementDescr( m, (ConditionalElementDescr) descr, boundParams, dmo ); + return parseExistentialElementDescr( m, + (ConditionalElementDescr) descr, + boundParams, + dmo ); } return null; } - private IFactPattern parsePatternDescr( RuleModel m, - PatternDescr pattern, - Map boundParams, - PackageDataModelOracle dmo ) { + private IFactPattern parsePatternDescr( final RuleModel m, + final PatternDescr pattern, + final Map boundParams, + final PackageDataModelOracle dmo ) { if ( pattern.getSource() != null ) { - return parsePatternSource( m, pattern, pattern.getSource(), boundParams, dmo ); - } - return getFactPattern( m, pattern, boundParams, dmo ); - } - - private FactPattern getFactPattern( RuleModel m, - PatternDescr pattern, - Map boundParams, - PackageDataModelOracle dmo ) { + return parsePatternSource( m, + pattern, + pattern.getSource(), + boundParams, + dmo ); + } + return getFactPattern( m, + pattern, + boundParams, + dmo ); + } + + private FactPattern getFactPattern( final RuleModel m, + final PatternDescr pattern, + final Map boundParams, + final PackageDataModelOracle dmo ) { String type = pattern.getObjectType(); FactPattern factPattern = new FactPattern( getSimpleFactType( type, dmo ) ); @@ -2206,15 +2243,18 @@ private FactPattern getFactPattern( RuleModel m, return factPattern; } - private IFactPattern parsePatternSource( RuleModel m, - PatternDescr pattern, - PatternSourceDescr patternSource, - Map boundParams, - PackageDataModelOracle dmo ) { + private IFactPattern parsePatternSource( final RuleModel m, + final PatternDescr pattern, + final PatternSourceDescr patternSource, + final Map boundParams, + final PackageDataModelOracle dmo ) { if ( patternSource instanceof AccumulateDescr ) { AccumulateDescr accumulate = (AccumulateDescr) patternSource; FromAccumulateCompositeFactPattern fac = new FromAccumulateCompositeFactPattern(); - fac.setSourcePattern( parseBaseDescr( m, accumulate.getInput(), boundParams, dmo ) ); + fac.setSourcePattern( parseBaseDescr( m, + accumulate.getInput(), + boundParams, + dmo ) ); FactPattern factPattern = new FactPattern( pattern.getObjectType() ); factPattern.setBoundName( pattern.getIdentifier() ); @@ -2286,8 +2326,12 @@ private IFactPattern parsePatternSource( RuleModel m, String sourcePart = splitSource[ i ]; if ( i == 0 ) { String type = boundParams.get( sourcePart ); - expression.appendPart( new ExpressionVariable( sourcePart, type, DataType.TYPE_NUMERIC ) ); - fields = findFields( dmo, m, type ); + expression.appendPart( new ExpressionVariable( sourcePart, + type, + DataType.TYPE_NUMERIC ) ); + fields = findFields( m, + dmo, + type ); } else { ModelField modelField = null; for ( ModelField field : fields ) { @@ -2319,8 +2363,8 @@ private IFactPattern parsePatternSource( RuleModel m, expression.appendPart( new ExpressionField( sourcePart, modelField.getClassName(), modelField.getType() ) ); - fields = findFields( dmo, - m, + fields = findFields( m, + dmo, modelField.getClassName() ); } } @@ -2331,49 +2375,63 @@ private IFactPattern parsePatternSource( RuleModel m, throw new RuntimeException( "Unknown pattern source " + patternSource ); } - private CompositeFactPattern parseExistentialElementDescr( RuleModel m, - ConditionalElementDescr conditionalDescr, - Map boundParams, - PackageDataModelOracle dmo ) { + private CompositeFactPattern parseExistentialElementDescr( final RuleModel m, + final ConditionalElementDescr conditionalDescr, + final Map boundParams, + final PackageDataModelOracle dmo ) { CompositeFactPattern comp = conditionalDescr instanceof NotDescr ? new CompositeFactPattern( CompositeFactPattern.COMPOSITE_TYPE_NOT ) : conditionalDescr instanceof OrDescr ? new CompositeFactPattern( CompositeFactPattern.COMPOSITE_TYPE_OR ) : new CompositeFactPattern( CompositeFactPattern.COMPOSITE_TYPE_EXISTS ); - addPatternToComposite( m, conditionalDescr, comp, boundParams, dmo ); + addPatternToComposite( m, + conditionalDescr, + comp, + boundParams, + dmo ); IFactPattern[] patterns = comp.getPatterns(); return patterns != null && patterns.length > 0 ? comp : null; } - private void addPatternToComposite( RuleModel m, - ConditionalElementDescr conditionalDescr, - CompositeFactPattern comp, - Map boundParams, - PackageDataModelOracle dmo ) { + private void addPatternToComposite( final RuleModel m, + final ConditionalElementDescr conditionalDescr, + final CompositeFactPattern comp, + final Map boundParams, + final PackageDataModelOracle dmo ) { for ( Object descr : conditionalDescr.getDescrs() ) { if ( descr instanceof PatternDescr ) { - comp.addFactPattern( parsePatternDescr( m, (PatternDescr) descr, boundParams, dmo ) ); + comp.addFactPattern( parsePatternDescr( m, + (PatternDescr) descr, + boundParams, + dmo ) ); } else if ( descr instanceof ConditionalElementDescr ) { - addPatternToComposite( m, (ConditionalElementDescr) descr, comp, boundParams, dmo ); + addPatternToComposite( m, + (ConditionalElementDescr) descr, + comp, + boundParams, + dmo ); } } } - private void parseConstraint( RuleModel m, - FactPattern factPattern, - ConditionalElementDescr constraint, - Map boundParams, - PackageDataModelOracle dmo ) { + private void parseConstraint( final RuleModel m, + final FactPattern factPattern, + final ConditionalElementDescr constraint, + final Map boundParams, + final PackageDataModelOracle dmo ) { for ( BaseDescr descr : constraint.getDescrs() ) { if ( descr instanceof ExprConstraintDescr ) { ExprConstraintDescr exprConstraint = (ExprConstraintDescr) descr; - Expr expr = parseExpr( exprConstraint.getExpression(), boundParams, dmo ); - factPattern.addConstraint( expr.asFieldConstraint( m, factPattern ) ); + Expr expr = parseExpr( exprConstraint.getExpression(), + boundParams, + dmo ); + factPattern.addConstraint( expr.asFieldConstraint( m, + factPattern ) ); } } } - private static String findOperator( String expr ) { + private static String findOperator( final String expr ) { final Set potentialOperators = new HashSet(); for ( Operator op : Operator.getAllOperators() ) { String opString = op.getOperatorString(); @@ -2411,8 +2469,8 @@ private static String findOperator( String expr ) { return null; } - private static boolean isInQuote( String expr, - int pos ) { + private static boolean isInQuote( final String expr, + final int pos ) { boolean isInQuote = false; for ( int i = pos - 1; i >= 0; i-- ) { if ( expr.charAt( i ) == '"' ) { @@ -2424,7 +2482,7 @@ private static boolean isInQuote( String expr, private static final String[] NULL_OPERATORS = new String[]{ "== null", "!= null" }; - private static String findNullOrNotNullOperator( String expr ) { + private static String findNullOrNotNullOperator( final String expr ) { for ( String op : NULL_OPERATORS ) { if ( expr.contains( op ) ) { return op; @@ -2433,12 +2491,12 @@ private static String findNullOrNotNullOperator( String expr ) { return null; } - private void parseRhs( RuleModel m, - String rhs, - boolean isJavaDialect, - Map boundParams, - ExpandedDRLInfo expandedDRLInfo, - PackageDataModelOracle dmo ) { + private void parseRhs( final RuleModel m, + final String rhs, + final boolean isJavaDialect, + final Map boundParams, + final ExpandedDRLInfo expandedDRLInfo, + final PackageDataModelOracle dmo ) { PortableWorkDefinition pwd = null; Map> setStatements = new HashMap>(); Map setStatementsPosition = new HashMap(); @@ -2454,7 +2512,8 @@ private void parseRhs( RuleModel m, if ( expandedDRLInfo.hasDsl ) { String dslLine = expandedDRLInfo.dslStatementsInRhs.get( lineCounter ); while ( dslLine != null ) { - m.addRhsItem( toDSLSentence( expandedDRLInfo.rhsDslPatterns, dslLine ) ); + m.addRhsItem( toDSLSentence( expandedDRLInfo.rhsDslPatterns, + dslLine ) ); dslLine = expandedDRLInfo.dslStatementsInRhs.get( ++lineCounter ); } } @@ -2463,19 +2522,20 @@ private void parseRhs( RuleModel m, int modifyBlockEnd = line.lastIndexOf( '}' ); if ( modifiers == null ) { modifiers = modifyBlockEnd > 0 ? - line.substring( line.indexOf( '{' ) + 1, modifyBlockEnd ).trim() : + line.substring( line.indexOf( '{' ) + 1, + modifyBlockEnd ).trim() : line.substring( line.indexOf( '{' ) + 1 ).trim(); } else if ( modifyBlockEnd != 0 ) { modifiers += modifyBlockEnd > 0 ? - line.substring( 0, modifyBlockEnd ).trim() : + line.substring( 0, + modifyBlockEnd ).trim() : line; } if ( modifyBlockEnd >= 0 ) { ActionUpdateField action = new ActionUpdateField(); action.setVariable( modifiedVariable ); m.addRhsItem( action ); - addModifiersToAction( modifiedVariable, - modifiers, + addModifiersToAction( modifiers, action, boundParams, dmo, @@ -2486,7 +2546,8 @@ private void parseRhs( RuleModel m, } } else if ( line.startsWith( "insertLogical" ) ) { String fact = unwrapParenthesis( line ); - String type = getStatementType( fact, factsType ); + String type = getStatementType( fact, + factsType ); if ( type != null ) { ActionInsertLogicalFact action = new ActionInsertLogicalFact( type ); m.addRhsItem( action ); @@ -2502,7 +2563,8 @@ private void parseRhs( RuleModel m, } } else if ( line.startsWith( "insert" ) ) { String fact = unwrapParenthesis( line ); - String type = getStatementType( fact, factsType ); + String type = getStatementType( fact, + factsType ); if ( type != null ) { ActionInsertFact action = new ActionInsertFact( type ); m.addRhsItem( action ); @@ -2532,19 +2594,21 @@ private void parseRhs( RuleModel m, } else if ( line.startsWith( "modify" ) ) { int modifyBlockEnd = line.lastIndexOf( '}' ); if ( modifyBlockEnd > 0 ) { - String variable = line.substring( line.indexOf( '(' ) + 1, line.indexOf( ')' ) ).trim(); + String variable = line.substring( line.indexOf( '(' ) + 1, + line.indexOf( ')' ) ).trim(); ActionUpdateField action = new ActionUpdateField(); action.setVariable( variable ); m.addRhsItem( action ); - addModifiersToAction( variable, - line.substring( line.indexOf( '{' ) + 1, modifyBlockEnd ).trim(), + addModifiersToAction( line.substring( line.indexOf( '{' ) + 1, + modifyBlockEnd ).trim(), action, boundParams, dmo, m.getImports(), isJavaDialect ); } else { - modifiedVariable = line.substring( line.indexOf( '(' ) + 1, line.indexOf( ')' ) ).trim(); + modifiedVariable = line.substring( line.indexOf( '(' ) + 1, + line.indexOf( ')' ) ).trim(); int modifyBlockStart = line.indexOf( '{' ); if ( modifyBlockStart > 0 ) { modifiers = line.substring( modifyBlockStart + 1 ).trim(); @@ -2563,35 +2627,49 @@ private void parseRhs( RuleModel m, String statement = line.substring( "wiWorkItem.getParameters().put".length() ); statement = unwrapParenthesis( statement ); int commaPos = statement.indexOf( ',' ); - String name = statement.substring( 0, commaPos ).trim(); + String name = statement.substring( 0, + commaPos ).trim(); String value = statement.substring( commaPos + 1 ).trim(); - pwd.addParameter( buildPortableParameterDefinition( name, value, boundParams ) ); + pwd.addParameter( buildPortableParameterDefinition( name, + value, + boundParams ) ); } else if ( line.startsWith( "wim.internalExecuteWorkItem" ) || line.startsWith( "wiWorkItem.setName" ) ) { // ignore } else { int dotPos = line.indexOf( '.' ); int argStart = line.indexOf( '(' ); if ( dotPos > 0 && argStart > dotPos ) { - String variable = line.substring( 0, dotPos ).trim(); + String variable = line.substring( 0, + dotPos ).trim(); if ( isJavaIdentifier( variable ) ) { - String methodName = line.substring( dotPos + 1, argStart ).trim(); + String methodName = line.substring( dotPos + 1, + argStart ).trim(); if ( isJavaIdentifier( methodName ) ) { if ( getSettedField( methodName ) != null ) { List setters = setStatements.get( variable ); if ( setters == null ) { setters = new ArrayList(); - setStatements.put( variable, setters ); + setStatements.put( variable, + setters ); } - setStatementsPosition.put( variable, lineCounter ); + setStatementsPosition.put( variable, + lineCounter ); setters.add( line ); } else if ( methodName.equals( "add" ) && expandedDRLInfo.hasGlobal( variable ) ) { - String factName = line.substring( argStart + 1, line.lastIndexOf( ')' ) ).trim(); + String factName = line.substring( argStart + 1, + line.lastIndexOf( ')' ) ).trim(); ActionGlobalCollectionAdd actionGlobalCollectionAdd = new ActionGlobalCollectionAdd(); actionGlobalCollectionAdd.setGlobalName( variable ); actionGlobalCollectionAdd.setFactName( factName ); m.addRhsItem( actionGlobalCollectionAdd ); } else { - m.addRhsItem( getActionCallMethod( m, isJavaDialect, boundParams, dmo, line, variable, methodName ) ); + m.addRhsItem( getActionCallMethod( m, + isJavaDialect, + boundParams, + dmo, + line, + variable, + methodName ) ); } continue; } @@ -2601,14 +2679,18 @@ private void parseRhs( RuleModel m, int eqPos = line.indexOf( '=' ); boolean addFreeFormLine = line.trim().length() > 0; if ( eqPos > 0 ) { - String field = line.substring( 0, eqPos ).trim(); + String field = line.substring( 0, + eqPos ).trim(); if ( "java.text.SimpleDateFormat sdf".equals( field ) || "org.drools.core.process.instance.WorkItemManager wim".equals( field ) ) { addFreeFormLine = false; } String[] split = field.split( " " ); if ( split.length == 2 ) { - factsType.put( split[ 1 ], split[ 0 ] ); - addFreeFormLine &= !isInsertedFact( lines, lineCounter, split[ 1 ] ); + factsType.put( split[ 1 ], + split[ 0 ] ); + addFreeFormLine &= !isInsertedFact( lines, + lineCounter, + split[ 1 ] ); } } if ( addFreeFormLine ) { @@ -2627,42 +2709,39 @@ private void parseRhs( RuleModel m, dmo, m.getImports(), isJavaDialect ); - m.addRhsItem( action, setStatementsPosition.get( entry.getKey() ) ); + m.addRhsItem( action, + setStatementsPosition.get( entry.getKey() ) ); } if ( expandedDRLInfo.hasDsl ) { String dslLine = expandedDRLInfo.dslStatementsInRhs.get( ++lineCounter ); while ( dslLine != null ) { - m.addRhsItem( toDSLSentence( expandedDRLInfo.rhsDslPatterns, dslLine ) ); + m.addRhsItem( toDSLSentence( expandedDRLInfo.rhsDslPatterns, + dslLine ) ); dslLine = expandedDRLInfo.dslStatementsInRhs.get( ++lineCounter ); } } } - private ActionCallMethod getActionCallMethod( - RuleModel model, - boolean isJavaDialect, - Map boundParams, - PackageDataModelOracle dmo, - String line, - String variable, - String methodName ) { + private ActionCallMethod getActionCallMethod( final RuleModel model, + final boolean isJavaDialect, + final Map boundParams, + final PackageDataModelOracle dmo, + final String line, + final String variable, + final String methodName ) { - return new ActionCallMethodBuilder( - model, - dmo, - isJavaDialect, - boundParams - ).get( - variable, - methodName, - unwrapParenthesis( line ).split( "," ) - ); + return new ActionCallMethodBuilder( model, + dmo, + isJavaDialect, + boundParams ).get( variable, + methodName, + unwrapParenthesis( line ).split( "," ) ); } - private boolean isInsertedFact( String[] lines, - int lineCounter, - String fact ) { + private boolean isInsertedFact( final String[] lines, + final int lineCounter, + final String fact ) { for ( int i = lineCounter; i < lines.length; i++ ) { String line = lines[ i ].trim(); if ( line.startsWith( "insert" ) ) { @@ -2674,17 +2753,20 @@ private boolean isInsertedFact( String[] lines, return false; } - private DSLSentence toDSLSentence( List dslPatterns, - String dslLine ) { + private DSLSentence toDSLSentence( final List dslPatterns, + final String dslLine ) { DSLSentence dslSentence = new DSLSentence(); for ( String dslPattern : dslPatterns ) { // Dollar breaks the matcher, need to escape them. - dslPattern = dslPattern.replace( "$", "\\$" ); + dslPattern = dslPattern.replace( "$", + "\\$" ); //A DSL Pattern can contain Regex itself, for example "When the ages is less than {num:1?[0-9]?[0-9]}" - String regex = dslPattern.replaceAll( "\\{.*?\\}", "(.*)" ); + String regex = dslPattern.replaceAll( "\\{.*?\\}", + "(.*)" ); Matcher matcher = Pattern.compile( regex ).matcher( dslLine ); if ( matcher.matches() ) { - dslPattern = dslPattern.replace( "\\$", "$" ); + dslPattern = dslPattern.replace( "\\$", + "$" ); dslSentence.setDefinition( dslPattern ); for ( int i = 0; i < matcher.groupCount(); i++ ) { dslSentence.getValues().get( i ).setValue( matcher.group( i + 1 ) ); @@ -2696,9 +2778,9 @@ private DSLSentence toDSLSentence( List dslPatterns, return dslSentence; } - private PortableParameterDefinition buildPortableParameterDefinition( String name, - String value, - Map boundParams ) { + private PortableParameterDefinition buildPortableParameterDefinition( final String name, + final String value, + final Map boundParams ) { PortableParameterDefinition paramDef; String type = boundParams.get( value ); if ( type != null ) { @@ -2720,7 +2802,8 @@ private PortableParameterDefinition buildPortableParameterDefinition( String nam ( (PortableBooleanParameterDefinition) paramDef ).setValue( b ); } else if ( value.startsWith( "\"" ) ) { paramDef = new PortableStringParameterDefinition(); - ( (PortableStringParameterDefinition) paramDef ).setValue( value.substring( 1, value.length() - 1 ) ); + ( (PortableStringParameterDefinition) paramDef ).setValue( value.substring( 1, + value.length() - 1 ) ); } else if ( Character.isDigit( value.charAt( 0 ) ) ) { if ( value.endsWith( "f" ) ) { paramDef = new PortableFloatParameterDefinition(); @@ -2732,17 +2815,18 @@ private PortableParameterDefinition buildPortableParameterDefinition( String nam } else { throw new RuntimeException( "Unknown parameter " + value ); } - paramDef.setName( name.substring( 1, name.length() - 1 ) ); + paramDef.setName( name.substring( 1, + name.length() - 1 ) ); return paramDef; } - private void addSettersToAction( Map> setStatements, - String variable, - ActionFieldList action, - Map boundParams, - PackageDataModelOracle dmo, - Imports imports, - boolean isJavaDialect ) { + private void addSettersToAction( final Map> setStatements, + final String variable, + final ActionFieldList action, + final Map boundParams, + final PackageDataModelOracle dmo, + final Imports imports, + final boolean isJavaDialect ) { addSettersToAction( setStatements.remove( variable ), action, boundParams, @@ -2751,43 +2835,56 @@ private void addSettersToAction( Map> setStatements, isJavaDialect ); } - private void addSettersToAction( List setters, - ActionFieldList action, - Map boundParams, - PackageDataModelOracle dmo, - Imports imports, - boolean isJavaDialect ) { + private void addSettersToAction( final List setters, + final ActionFieldList action, + final Map boundParams, + final PackageDataModelOracle dmo, + final Imports imports, + final boolean isJavaDialect ) { if ( setters != null ) { for ( String statement : setters ) { int dotPos = statement.indexOf( '.' ); int argStart = statement.indexOf( '(' ); - String methodName = statement.substring( dotPos + 1, argStart ).trim(); - addSetterToAction( action, boundParams, dmo, imports, isJavaDialect, statement, methodName ); + String methodName = statement.substring( dotPos + 1, + argStart ).trim(); + addSetterToAction( action, + boundParams, + dmo, + imports, + isJavaDialect, + statement, + methodName ); } } } - private void addModifiersToAction( String variable, - String modifiers, - ActionFieldList action, - Map boundParams, - PackageDataModelOracle dmo, - Imports imports, - boolean isJavaDialect ) { + private void addModifiersToAction( final String modifiers, + final ActionFieldList action, + final Map boundParams, + final PackageDataModelOracle dmo, + final Imports imports, + final boolean isJavaDialect ) { for ( String statement : splitArgumentsList( modifiers ) ) { int argStart = statement.indexOf( '(' ); - String methodName = statement.substring( 0, argStart ).trim(); - addSetterToAction( action, boundParams, dmo, imports, isJavaDialect, statement, methodName ); - } - } - - private void addSetterToAction( ActionFieldList action, - Map boundParams, - PackageDataModelOracle dmo, - Imports imports, - boolean isJavaDialect, - String statement, - String methodName ) { + String methodName = statement.substring( 0, + argStart ).trim(); + addSetterToAction( action, + boundParams, + dmo, + imports, + isJavaDialect, + statement, + methodName ); + } + } + + private void addSetterToAction( final ActionFieldList action, + final Map boundParams, + final PackageDataModelOracle dmo, + final Imports imports, + final boolean isJavaDialect, + final String statement, + final String methodName ) { String field = getSettedField( methodName ); String value = unwrapParenthesis( statement ); String dataType = inferDataType( action, @@ -2804,27 +2901,41 @@ private void addSetterToAction( ActionFieldList action, field, value, dataType, - boundParams, - dmo ) ); + boundParams ) ); } - private ActionFieldValue buildFieldValue( boolean isJavaDialect, + private ActionFieldValue buildFieldValue( final boolean isJavaDialect, String field, - String value, - String dataType, - Map boundParams, - PackageDataModelOracle dmo ) { + final String value, + final String dataType, + final Map boundParams ) { if ( value.contains( "wiWorkItem.getResult" ) ) { field = field.substring( 0, 1 ).toUpperCase() + field.substring( 1 ); String wiParam = field.substring( "Results".length() ); if ( wiParam.equals( "BooleanResult" ) ) { - return new ActionWorkItemFieldValue( field, DataType.TYPE_BOOLEAN, "WorkItem", wiParam, Boolean.class.getName() ); + return new ActionWorkItemFieldValue( field, + DataType.TYPE_BOOLEAN, + "WorkItem", + wiParam, + Boolean.class.getName() ); } else if ( wiParam.equals( "StringResult" ) ) { - return new ActionWorkItemFieldValue( field, DataType.TYPE_STRING, "WorkItem", wiParam, String.class.getName() ); + return new ActionWorkItemFieldValue( field, + DataType.TYPE_STRING, + "WorkItem", + wiParam, + String.class.getName() ); } else if ( wiParam.equals( "IntegerResult" ) ) { - return new ActionWorkItemFieldValue( field, DataType.TYPE_NUMERIC_INTEGER, "WorkItem", wiParam, Integer.class.getName() ); + return new ActionWorkItemFieldValue( field, + DataType.TYPE_NUMERIC_INTEGER, + "WorkItem", + wiParam, + Integer.class.getName() ); } else if ( wiParam.equals( "FloatResult" ) ) { - return new ActionWorkItemFieldValue( field, DataType.TYPE_NUMERIC_FLOAT, "WorkItem", wiParam, Float.class.getName() ); + return new ActionWorkItemFieldValue( field, + DataType.TYPE_NUMERIC_FLOAT, + "WorkItem", + wiParam, + Float.class.getName() ); } } ActionFieldValue fieldValue = new ActionFieldValue( field, @@ -2840,7 +2951,7 @@ private ActionFieldValue buildFieldValue( boolean isJavaDialect, return fieldValue; } - private boolean isJavaIdentifier( String name ) { + private boolean isJavaIdentifier( final String name ) { if ( name == null || name.length() == 0 || !Character.isJavaIdentifierStart( name.charAt( 0 ) ) ) { return false; } @@ -2852,11 +2963,12 @@ private boolean isJavaIdentifier( String name ) { return true; } - private String getSettedField( String methodName ) { + private String getSettedField( final String methodName ) { if ( methodName.length() > 3 && methodName.startsWith( "set" ) ) { String field = methodName.substring( 3 ); if ( Character.isUpperCase( field.charAt( 0 ) ) ) { - return field.substring( 0, 1 ).toLowerCase() + field.substring( 1 ); + return field.substring( 0, + 1 ).toLowerCase() + field.substring( 1 ); } else { return field; } @@ -2864,13 +2976,14 @@ private String getSettedField( String methodName ) { return null; } - private String getStatementType( String fact, - Map factsType ) { + private String getStatementType( final String fact, + final Map factsType ) { String type = null; if ( fact.startsWith( "new " ) ) { String inserted = fact.substring( 4 ).trim(); if ( inserted.endsWith( "()" ) ) { - type = inserted.substring( 0, inserted.length() - 2 ).trim(); + type = inserted.substring( 0, + inserted.length() - 2 ).trim(); } } else { type = factsType.get( fact ); @@ -2878,23 +2991,29 @@ private String getStatementType( String fact, return type; } - private Expr parseExpr( String expr, - Map boundParams, - PackageDataModelOracle dmo ) { + private Expr parseExpr( final String expr, + final Map boundParams, + final PackageDataModelOracle dmo ) { List splittedExpr = splitExpression( expr ); if ( splittedExpr.size() == 1 ) { String singleExpr = splittedExpr.get( 0 ); if ( singleExpr.startsWith( "(" ) ) { - return parseExpr( singleExpr.substring( 1 ), boundParams, dmo ); + return parseExpr( singleExpr.substring( 1 ), + boundParams, + dmo ); } else if ( singleExpr.startsWith( "eval" ) ) { return new EvalExpr( unwrapParenthesis( singleExpr ) ); } else { - return new SimpleExpr( singleExpr, boundParams, dmo ); + return new SimpleExpr( singleExpr, + boundParams, + dmo ); } } ComplexExpr complexExpr = new ComplexExpr( splittedExpr.get( 1 ) ); for ( int i = 0; i < splittedExpr.size(); i += 2 ) { - complexExpr.subExprs.add( parseExpr( splittedExpr.get( i ), boundParams, dmo ) ); + complexExpr.subExprs.add( parseExpr( splittedExpr.get( i ), + boundParams, + dmo ) ); } return complexExpr; } @@ -2903,7 +3022,7 @@ private enum SplitterState { START, EXPR, PIPE, OR, AMPERSAND, AND, NESTED } - private List splitExpression( String expr ) { + private List splitExpression( final String expr ) { List splittedExpr = new ArrayList(); int nestingLevel = 0; SplitterState status = SplitterState.START; @@ -3003,8 +3122,8 @@ private List splitExpression( String expr ) { private interface Expr { - FieldConstraint asFieldConstraint( RuleModel m, - FactPattern factPattern ); + FieldConstraint asFieldConstraint( final RuleModel m, + final FactPattern factPattern ); } private static class SimpleExpr implements Expr { @@ -3013,16 +3132,16 @@ private static class SimpleExpr implements Expr { private final Map boundParams; private final PackageDataModelOracle dmo; - private SimpleExpr( String expr, - Map boundParams, - PackageDataModelOracle dmo ) { + private SimpleExpr( final String expr, + final Map boundParams, + final PackageDataModelOracle dmo ) { this.expr = expr; this.boundParams = boundParams; this.dmo = dmo; } - public FieldConstraint asFieldConstraint( RuleModel m, - FactPattern factPattern ) { + public FieldConstraint asFieldConstraint( final RuleModel m, + final FactPattern factPattern ) { String fieldName = expr; String value = null; @@ -3042,17 +3161,18 @@ public FieldConstraint asFieldConstraint( RuleModel m, } } + boolean isExpression = fieldName.contains( "." ) || fieldName.endsWith( "()" ); return createFieldConstraint( m, factPattern, fieldName, value, operator, - fieldName.contains( "." ) ); + isExpression ); } - private SingleFieldConstraint createNullCheckFieldConstraint( RuleModel m, - FactPattern factPattern, - String fieldName ) { + private SingleFieldConstraint createNullCheckFieldConstraint( final RuleModel m, + final FactPattern factPattern, + final String fieldName ) { return createFieldConstraint( m, factPattern, fieldName, @@ -3061,16 +3181,17 @@ private SingleFieldConstraint createNullCheckFieldConstraint( RuleModel m, true ); } - private SingleFieldConstraint createFieldConstraint( RuleModel m, - FactPattern factPattern, - String fieldName, + private SingleFieldConstraint createFieldConstraint( final RuleModel m, + final FactPattern factPattern, + final String fieldName, String value, - String operator, - boolean isExpression ) { + final String operator, + final boolean isExpression ) { String operatorParams = null; if ( value != null && value.startsWith( "[" ) ) { int endSquare = value.indexOf( ']' ); - operatorParams = value.substring( 1, endSquare ).trim(); + operatorParams = value.substring( 1, + endSquare ).trim(); value = value.substring( endSquare + 1 ).trim(); } @@ -3089,11 +3210,13 @@ private SingleFieldConstraint createFieldConstraint( RuleModel m, if ( operatorParams != null ) { int i = 0; for ( String param : operatorParams.split( "," ) ) { - ( (BaseSingleFieldConstraint) fieldConstraint ).setParameter( "" + i++, param.trim() ); + fieldConstraint.setParameter( "" + i++, + param.trim() ); } - ( (BaseSingleFieldConstraint) fieldConstraint ).setParameter( "org.drools.workbench.models.commons.backend.rule.visibleParameterSet", "" + i ); - ( (BaseSingleFieldConstraint) fieldConstraint ).setParameter( "org.drools.workbench.models.commons.backend.rule.operatorParameterGenerator", - "org.drools.workbench.models.commons.backend.rule.CEPOperatorParameterDRLBuilder" ); + fieldConstraint.setParameter( "org.drools.workbench.models.commons.backend.rule.visibleParameterSet", + "" + i ); + fieldConstraint.setParameter( "org.drools.workbench.models.commons.backend.rule.operatorParameterGenerator", + "org.drools.workbench.models.commons.backend.rule.CEPOperatorParameterDRLBuilder" ); } if ( fieldName.equals( "this" ) && ( operator == null || operator.equals( "!= null" ) ) ) { @@ -3101,7 +3224,9 @@ private SingleFieldConstraint createFieldConstraint( RuleModel m, } fieldConstraint.setFactType( factPattern.getFactType() ); - ModelField field = findField( findFields( dmo, m, factPattern.getFactType() ), + ModelField field = findField( findFields( m, + dmo, + factPattern.getFactType() ), fieldConstraint.getFieldName() ); if ( field != null && ( fieldConstraint.getFieldType() == null || fieldConstraint.getFieldType().trim().length() == 0 ) ) { @@ -3110,11 +3235,11 @@ private SingleFieldConstraint createFieldConstraint( RuleModel m, return fieldConstraint; } - private SingleFieldConstraint createExpressionBuilderConstraint( RuleModel m, - FactPattern factPattern, - String fieldName, - String operator, - String value ) { + private SingleFieldConstraint createExpressionBuilderConstraint( final RuleModel m, + final FactPattern factPattern, + final String fieldName, + final String operator, + final String value ) { // TODO: we should find a way to know when the expression uses a getter and in this case create a plain SingleFieldConstraint //int dotPos = fieldName.lastIndexOf('.'); //SingleFieldConstraint con = createSingleFieldConstraint(dotPos > 0 ? fieldName.substring(dotPos+1) : fieldName, operator, value); @@ -3125,6 +3250,28 @@ private SingleFieldConstraint createExpressionBuilderConstraint( RuleModel m, operator, value ); + return con; + } + + private SingleFieldConstraint createSingleFieldConstraint( final RuleModel m, + final FactPattern factPattern, + String fieldName, + final String operator, + final String value ) { + SingleFieldConstraint con = new SingleFieldConstraint(); + fieldName = setFieldBindingOnContraint( factPattern.getFactType(), + fieldName, + m, + con, + boundParams ); + con.setFieldName( fieldName ); + setOperatorAndValueOnConstraint( m, + operator, + value, + factPattern, + con ); + + //Setup parent relationships for SingleFieldConstraints for ( FieldConstraint fieldConstraint : factPattern.getFieldConstraints() ) { if ( fieldConstraint instanceof SingleFieldConstraint ) { SingleFieldConstraint sfc = (SingleFieldConstraint) fieldConstraint; @@ -3138,33 +3285,18 @@ private SingleFieldConstraint createExpressionBuilderConstraint( RuleModel m, } } - if ( con.getParent() == null && !( con instanceof SingleFieldConstraintEBLeftSide ) ) { + if ( con.getParent() == null ) { con.setParent( createParentFor( m, factPattern, fieldName ) ); } return con; } - private SingleFieldConstraint createSingleFieldConstraint( RuleModel m, - FactPattern factPattern, - String fieldName, - String operator, - String value ) { - SingleFieldConstraint con = new SingleFieldConstraint(); - fieldName = setFieldBindingOnContraint( factPattern.getFactType(), - fieldName, - m, con, - boundParams ); - con.setFieldName( fieldName ); - setOperatorAndValueOnConstraint( m, operator, value, factPattern, con ); - return con; - } - - private SingleFieldConstraintEBLeftSide createSingleFieldConstraintEBLeftSide( RuleModel m, - FactPattern factPattern, + private SingleFieldConstraintEBLeftSide createSingleFieldConstraintEBLeftSide( final RuleModel m, + final FactPattern factPattern, String fieldName, - String operator, - String value ) { + final String operator, + final String value ) { SingleFieldConstraintEBLeftSide con = new SingleFieldConstraintEBLeftSide(); fieldName = setFieldBindingOnContraint( factPattern.getFactType(), @@ -3172,10 +3304,14 @@ private SingleFieldConstraintEBLeftSide createSingleFieldConstraintEBLeftSide( R m, con, boundParams ); - String classType = getFQFactType( m, factPattern.getFactType() ); + String classType = getFQFactType( m, + factPattern.getFactType() ); con.getExpressionLeftSide().appendPart( new ExpressionUnboundFact( factPattern ) ); - parseExpression( m, classType, fieldName, con.getExpressionLeftSide() ); + parseExpression( m, + classType, + fieldName, + con.getExpressionLeftSide() ); setOperatorAndValueOnConstraint( m, operator, @@ -3186,10 +3322,10 @@ private SingleFieldConstraintEBLeftSide createSingleFieldConstraintEBLeftSide( R return con; } - private ExpressionFormLine parseExpression( RuleModel m, + private ExpressionFormLine parseExpression( final RuleModel m, String factType, - String fieldName, - ExpressionFormLine expression ) { + final String fieldName, + final ExpressionFormLine expression ) { String[] splits = fieldName.split( "\\." ); boolean isBoundParam = false; @@ -3199,9 +3335,13 @@ private ExpressionFormLine parseExpression( RuleModel m, isBoundParam = true; } - ModelField[] typeFields = findFields( dmo, - m, + //An ExpressionPart can be a Field or a Method + ModelField[] typeFields = findFields( m, + dmo, factType ); + List methodInfos = getMethodInfosForType( m, + dmo, + factType ); //Handle all but last expression part for ( int i = 0; i < splits.length - 1; i++ ) { @@ -3210,6 +3350,7 @@ private ExpressionFormLine parseExpression( RuleModel m, expression.appendPart( new ExpressionField( expressionPart, factType, DataType.TYPE_THIS ) ); + } else if ( isBoundParam ) { ModelField currentFact = findFact( dmo.getProjectModelFields(), factType ); @@ -3217,18 +3358,35 @@ private ExpressionFormLine parseExpression( RuleModel m, currentFact.getClassName(), currentFact.getType() ) ); isBoundParam = false; + } else { + //An ExpressionPart can be a Field or a Method + String currentClassName = null; ModelField currentField = findField( typeFields, expressionPart ); + if ( currentField != null ) { + currentClassName = currentField.getClassName(); + } + MethodInfo currentMethodInfo = findMethodInfo( methodInfos, + expressionPart ); + if ( currentMethodInfo != null ) { + currentClassName = currentMethodInfo.getReturnClassType(); + } - processExpressionPart( factType, + processExpressionPart( m, + factType, currentField, + currentMethodInfo, expression, expressionPart ); - typeFields = findFields( dmo, - m, - currentField.getClassName() ); + //Refresh field and method information based + typeFields = findFields( m, + dmo, + currentClassName ); + methodInfos = getMethodInfosForType( m, + dmo, + currentClassName ); } } @@ -3236,9 +3394,13 @@ private ExpressionFormLine parseExpression( RuleModel m, String expressionPart = normalizeExpressionPart( splits[ splits.length - 1 ] ); ModelField currentField = findField( typeFields, expressionPart ); + MethodInfo currentMethodInfo = findMethodInfo( methodInfos, + expressionPart ); - processExpressionPart( factType, + processExpressionPart( m, + factType, currentField, + currentMethodInfo, expression, expressionPart ); @@ -3248,41 +3410,34 @@ private ExpressionFormLine parseExpression( RuleModel m, private String normalizeExpressionPart( String expressionPart ) { int parenthesisPos = expressionPart.indexOf( '(' ); if ( parenthesisPos > 0 ) { - expressionPart = expressionPart.substring( 0, parenthesisPos ); + expressionPart = expressionPart.substring( 0, + parenthesisPos ); } return expressionPart.trim(); } - private void processExpressionPart( final String factType, + private void processExpressionPart( final RuleModel m, + final String factType, final ModelField currentField, + final MethodInfo currentMethodInfo, final ExpressionFormLine expression, final String expressionPart ) { if ( currentField == null ) { - final String previousClassName = expression.getClassType(); - final List mis = dmo.getProjectMethodInformation().get( previousClassName ); - boolean isMethod = false; - if ( mis != null ) { - for ( MethodInfo mi : mis ) { - if ( mi.getName().equals( expressionPart ) ) { - expression.appendPart( new ExpressionMethod( mi.getName(), - mi.getReturnClassType(), - mi.getGenericType(), - mi.getParametricReturnType() ) ); - isMethod = true; - break; - } - } - } - if ( isMethod == false ) { + boolean isMethod = currentMethodInfo != null; + if ( isMethod ) { + expression.appendPart( new ExpressionMethod( currentMethodInfo.getName(), + currentMethodInfo.getReturnClassType(), + currentMethodInfo.getGenericType(), + currentMethodInfo.getParametricReturnType() ) ); + } else { expression.appendPart( new ExpressionText( expressionPart ) ); } } else if ( "Collection".equals( currentField.getType() ) ) { - expression.appendPart( - new ExpressionCollection( expressionPart, - currentField.getClassName(), - currentField.getType(), - dmo.getProjectFieldParametersType().get( factType + "#" + expressionPart ) ) + expression.appendPart( new ExpressionCollection( expressionPart, + currentField.getClassName(), + currentField.getType(), + dmo.getProjectFieldParametersType().get( factType + "#" + expressionPart ) ) ); } else { expression.appendPart( new ExpressionField( expressionPart, @@ -3292,8 +3447,8 @@ private void processExpressionPart( final String factType, } - private String getFQFactType( RuleModel ruleModel, - String factType ) { + private String getFQFactType( final RuleModel ruleModel, + final String factType ) { Set factTypes = dmo.getProjectModelFields().keySet(); @@ -3316,8 +3471,8 @@ private String getFQFactType( RuleModel ruleModel, return factType; } - private ModelField findFact( Map modelFields, - String factType ) { + private ModelField findFact( final Map modelFields, + final String factType ) { final ModelField[] typeFields = modelFields.get( factType ); if ( typeFields == null ) { return null; @@ -3330,35 +3485,41 @@ private ModelField findFact( Map modelFields, return null; } - private SingleFieldConstraint createParentFor( RuleModel m, - FactPattern factPattern, - String fieldName ) { + private SingleFieldConstraint createParentFor( final RuleModel m, + final FactPattern factPattern, + final String fieldName ) { int dotPos = fieldName.lastIndexOf( '.' ); if ( dotPos > 0 ) { - SingleFieldConstraint constraint = createNullCheckFieldConstraint( m, factPattern, fieldName.substring( 0, dotPos ) ); + SingleFieldConstraint constraint = createNullCheckFieldConstraint( m, + factPattern, + fieldName.substring( 0, + dotPos ) ); factPattern.addConstraint( constraint ); return constraint; } return null; } - private String setFieldBindingOnContraint( - String factType, - String fieldName, - RuleModel model, - SingleFieldConstraint con, - Map boundParams ) { + private String setFieldBindingOnContraint( final String factType, + String fieldName, + final RuleModel model, + final SingleFieldConstraint con, + final Map boundParams ) { int colonPos = fieldName.indexOf( ':' ); if ( colonPos > 0 ) { - String fieldBinding = fieldName.substring( 0, colonPos ).trim(); + String fieldBinding = fieldName.substring( 0, + colonPos ).trim(); con.setFieldBinding( fieldBinding ); fieldName = fieldName.substring( colonPos + 1 ).trim(); - ModelField[] fields = findFields( dmo, model, factType ); + ModelField[] fields = findFields( model, + dmo, + factType ); if ( fields != null ) { for ( ModelField field : fields ) { if ( field.getName().equals( fieldName ) ) { - boundParams.put( fieldBinding, field.getType() ); + boundParams.put( fieldBinding, + field.getType() ); } } } @@ -3367,11 +3528,11 @@ private String setFieldBindingOnContraint( return fieldName; } - private String setOperatorAndValueOnConstraint( RuleModel m, - String operator, - String value, - FactPattern factPattern, - SingleFieldConstraint con ) { + private String setOperatorAndValueOnConstraint( final RuleModel m, + final String operator, + final String value, + final FactPattern factPattern, + final SingleFieldConstraint con ) { con.setOperator( operator ); String type = null; boolean isAnd = false; @@ -3379,7 +3540,11 @@ private String setOperatorAndValueOnConstraint( RuleModel m, if ( value != null ) { isAnd = value.contains( "&&" ); splittedValue = isAnd ? value.split( "\\&\\&" ) : value.split( "\\|\\|" ); - type = setValueOnConstraint( m, operator, factPattern, con, splittedValue[ 0 ].trim() ); + type = setValueOnConstraint( m, + operator, + factPattern, + con, + splittedValue[ 0 ].trim() ); } if ( splittedValue.length > 1 ) { @@ -3391,23 +3556,28 @@ private String setOperatorAndValueOnConstraint( RuleModel m, connectiveConstraints[ i ] = new ConnectiveConstraint(); connectiveConstraints[ i ].setOperator( ( isAnd ? "&& " : "|| " ) + connectiveOperator ); - setValueOnConstraint( m, operator, factPattern, connectiveConstraints[ i ], connectiveValue ); + setValueOnConstraint( m, + operator, + factPattern, + connectiveConstraints[ i ], + connectiveValue ); } con.setConnectives( connectiveConstraints ); } return type; } - private String setValueOnConstraint( RuleModel m, - String operator, - FactPattern factPattern, - BaseSingleFieldConstraint con, + private String setValueOnConstraint( final RuleModel m, + final String operator, + final FactPattern factPattern, + final BaseSingleFieldConstraint con, String value ) { String type = null; if ( value.startsWith( "\"" ) ) { type = DataType.TYPE_STRING; con.setConstraintValueType( SingleFieldConstraint.TYPE_LITERAL ); - con.setValue( value.substring( 1, value.length() - 1 ) ); + con.setValue( value.substring( 1, + value.length() - 1 ) ); } else if ( value.startsWith( "(" ) ) { if ( operator != null && operator.contains( "in" ) ) { value = unwrapParenthesis( value ); @@ -3428,8 +3598,12 @@ private String setValueOnConstraint( RuleModel m, con ) ) { type = DataType.TYPE_COMPARABLE; con.setConstraintValueType( SingleFieldConstraint.TYPE_ENUM ); - } else if ( value.indexOf( '.' ) > 0 && boundParams.containsKey( value.substring( 0, value.indexOf( '.' ) ).trim() ) ) { - con.setExpressionValue( parseExpression( m, null, value, new ExpressionFormLine() ) ); + } else if ( value.indexOf( '.' ) > 0 && boundParams.containsKey( value.substring( 0, + value.indexOf( '.' ) ).trim() ) ) { + con.setExpressionValue( parseExpression( m, + null, + value, + new ExpressionFormLine() ) ); con.setConstraintValueType( BaseSingleFieldConstraint.TYPE_EXPR_BUILDER_VALUE ); value = ""; } else { @@ -3438,10 +3612,12 @@ private String setValueOnConstraint( RuleModel m, } else { if ( value.endsWith( "I" ) ) { type = DataType.TYPE_NUMERIC_BIGINTEGER; - value = value.substring( 0, value.length() - 1 ); + value = value.substring( 0, + value.length() - 1 ); } else if ( value.endsWith( "B" ) ) { type = DataType.TYPE_NUMERIC_BIGDECIMAL; - value = value.substring( 0, value.length() - 1 ); + value = value.substring( 0, + value.length() - 1 ); } else if ( value.endsWith( "f" ) ) { type = DataType.TYPE_NUMERIC_FLOAT; } else if ( value.endsWith( "d" ) ) { @@ -3461,9 +3637,9 @@ private String setValueOnConstraint( RuleModel m, return type; } - private boolean isEnumerationValue( RuleModel ruleModel, - FactPattern factPattern, - BaseSingleFieldConstraint con ) { + private boolean isEnumerationValue( final RuleModel ruleModel, + final FactPattern factPattern, + final BaseSingleFieldConstraint con ) { String factType = null; String fieldName = null; if ( con instanceof SingleFieldConstraintEBLeftSide ) { @@ -3483,7 +3659,8 @@ private boolean isEnumerationValue( RuleModel ruleModel, return false; } - final String fullyQualifiedFactType = getFQFactType( ruleModel, factType ); + final String fullyQualifiedFactType = getFQFactType( ruleModel, + factType ); final String key = fullyQualifiedFactType + "#" + fieldName; final Map projectJavaEnumDefinitions = dmo.getProjectJavaEnumDefinitions(); @@ -3496,16 +3673,17 @@ private static class ComplexExpr implements Expr { private final List subExprs = new ArrayList(); private final String connector; - private ComplexExpr( String connector ) { + private ComplexExpr( final String connector ) { this.connector = connector; } - public FieldConstraint asFieldConstraint( RuleModel m, - FactPattern factPattern ) { + public FieldConstraint asFieldConstraint( final RuleModel m, + final FactPattern factPattern ) { CompositeFieldConstraint comp = new CompositeFieldConstraint(); comp.setCompositeJunctionType( connector.equals( "&&" ) ? CompositeFieldConstraint.COMPOSITE_TYPE_AND : CompositeFieldConstraint.COMPOSITE_TYPE_OR ); for ( Expr expr : subExprs ) { - comp.addConstraint( expr.asFieldConstraint( m, factPattern ) ); + comp.addConstraint( expr.asFieldConstraint( m, + factPattern ) ); } return comp; } @@ -3515,12 +3693,12 @@ private static class EvalExpr implements Expr { private final String expr; - private EvalExpr( String expr ) { + private EvalExpr( final String expr ) { this.expr = expr; } - public FieldConstraint asFieldConstraint( RuleModel m, - FactPattern factPattern ) { + public FieldConstraint asFieldConstraint( final RuleModel m, + final FactPattern factPattern ) { SingleFieldConstraint con = new SingleFieldConstraint(); con.setConstraintValueType( SingleFieldConstraint.TYPE_PREDICATE ); con.setValue( expr ); diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java index 768e3350b2f..53e039cca27 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java @@ -25,14 +25,15 @@ class RuleModelPersistenceHelper { - static String unwrapParenthesis( String s ) { + static String unwrapParenthesis( final String s ) { int start = s.indexOf( '(' ); int end = s.lastIndexOf( ')' ); - return s.substring( start + 1, end ).trim(); + return s.substring( start + 1, + end ).trim(); } - static String getSimpleFactType( String className, - PackageDataModelOracle dmo ) { + static String getSimpleFactType( final String className, + final PackageDataModelOracle dmo ) { for ( String type : dmo.getProjectModelFields().keySet() ) { if ( type.equals( className ) ) { return type.substring( type.lastIndexOf( "." ) + 1 ); @@ -169,10 +170,9 @@ static int inferFieldNature( final String dataType, return nature; } - static ModelField[] findFields( - PackageDataModelOracle dmo, - RuleModel m, - String type ) { + static ModelField[] findFields( final RuleModel m, + final PackageDataModelOracle dmo, + final String type ) { ModelField[] fields = dmo.getProjectModelFields().get( type ); if ( fields != null ) { return fields; @@ -189,9 +189,8 @@ static ModelField[] findFields( return dmo.getProjectModelFields().get( m.getPackageName() + "." + type ); } - static ModelField findField( - ModelField[] typeFields, - String fieldName ) { + static ModelField findField( final ModelField[] typeFields, + final String fieldName ) { if ( typeFields != null && fieldName != null ) { for ( ModelField typeField : typeFields ) { if ( typeField.getName().equals( fieldName ) ) { @@ -202,11 +201,24 @@ static ModelField findField( return null; } - static String inferDataType( ActionFieldList action, - String field, - Map boundParams, - PackageDataModelOracle dmo, - Imports imports ) { + static MethodInfo findMethodInfo( final List methodInfos, + final String fieldName ) { + if ( methodInfos != null && fieldName != null ) { + for ( MethodInfo methodInfo : methodInfos ) { + if ( methodInfo.getName().equals( fieldName ) ) { + return methodInfo; + } + } + } + return null; + + } + + static String inferDataType( final ActionFieldList action, + final String field, + final Map boundParams, + final PackageDataModelOracle dmo, + final Imports imports ) { String factType = null; if ( action instanceof ActionInsertFact ) { factType = ( (ActionInsertFact) action ).getFactType(); @@ -250,9 +262,9 @@ static String inferDataType( ActionFieldList action, return null; } - static String inferDataType( String param, - Map boundParams, - boolean isJavaDialect ) { + static String inferDataType( final String param, + final Map boundParams, + final boolean isJavaDialect ) { if ( param.startsWith( "sdf.parse(\"" ) ) { return DataType.TYPE_DATE; } else if ( param.startsWith( "\"" ) ) { @@ -271,10 +283,10 @@ static String inferDataType( String param, return DataType.TYPE_NUMERIC; } - static String adjustParam( String dataType, - String param, - Map boundParams, - boolean isJavaDialect ) { + static String adjustParam( final String dataType, + final String param, + final Map boundParams, + final boolean isJavaDialect ) { if ( dataType == DataType.TYPE_DATE ) { return param.substring( "sdf.parse(\"".length(), param.length() - 2 ); @@ -302,9 +314,9 @@ static String adjustParam( String dataType, return param; } - static List getMethodInfosForType( RuleModel model, - PackageDataModelOracle dmo, - String variableType ) { + static List getMethodInfosForType( final RuleModel model, + final PackageDataModelOracle dmo, + final String variableType ) { List methods = dmo.getProjectMethodInformation().get( variableType ); if ( methods == null ) { for ( String imp : model.getImports().getImportStrings() ) { @@ -318,4 +330,5 @@ static List getMethodInfosForType( RuleModel model, } return methods; } + } diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java index 7158f86a99f..b109679b122 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java @@ -16,6 +16,7 @@ package org.drools.workbench.models.commons.backend.rule; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -25,6 +26,7 @@ import org.drools.workbench.models.datamodel.imports.Import; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.FieldAccessorsAndMutators; +import org.drools.workbench.models.datamodel.oracle.MethodInfo; import org.drools.workbench.models.datamodel.oracle.ModelField; import org.drools.workbench.models.datamodel.oracle.PackageDataModelOracle; import org.drools.workbench.models.datamodel.rule.ActionCallMethod; @@ -4408,6 +4410,18 @@ public void testLHSFormula() { con2.setValue( "0" ); p.addConstraint( con2 ); + final HashMap> map = new HashMap>(); + final ArrayList methodInfos = new ArrayList(); + methodInfos.add( new MethodInfo( "intValue", + Collections.EMPTY_LIST, + "int", + null, + DataType.TYPE_NUMERIC_INTEGER ) ); + map.put( "Number", + methodInfos ); + + when( dmo.getProjectMethodInformation() ).thenReturn( map ); + String expected = "rule \"test\"\n" + "dialect \"mvel\"\n" + "when\n" @@ -4416,7 +4430,8 @@ public void testLHSFormula() { + "end"; checkMarshallUnmarshall( expected, - m ); + m, + dmo ); } @Test @@ -4445,6 +4460,18 @@ public void testLHSReturnType() { con2.setValue( "0" ); p.addConstraint( con2 ); + final HashMap> map = new HashMap>(); + final ArrayList methodInfos = new ArrayList(); + methodInfos.add( new MethodInfo( "intValue", + Collections.EMPTY_LIST, + "int", + null, + DataType.TYPE_NUMERIC_INTEGER ) ); + map.put( "Number", + methodInfos ); + + when( dmo.getProjectMethodInformation() ).thenReturn( map ); + String expected = "rule \"test\"\n" + "dialect \"mvel\"\n" + "when\n" @@ -4453,7 +4480,8 @@ public void testLHSReturnType() { + "end"; checkMarshallUnmarshall( expected, - m ); + m, + dmo ); } @Test diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java index 1bbdce1bc31..d0bafc94790 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java @@ -1751,8 +1751,8 @@ public void testNestedFieldConstraints() { sfp0.getConstraintValueType() ); assertNull( sfp0.getParent() ); - assertTrue( fp.getConstraint( 1 ) instanceof SingleFieldConstraint ); - SingleFieldConstraint sfp1 = (SingleFieldConstraint) fp.getConstraint( 1 ); + assertTrue( fp.getConstraint( 1 ) instanceof SingleFieldConstraintEBLeftSide ); + SingleFieldConstraintEBLeftSide sfp1 = (SingleFieldConstraintEBLeftSide) fp.getConstraint( 1 ); assertEquals( "ParentType", sfp1.getFactType() ); assertEquals( "parentChildField", @@ -1764,11 +1764,10 @@ public void testNestedFieldConstraints() { assertNull( sfp1.getValue() ); assertEquals( BaseSingleFieldConstraint.TYPE_UNDEFINED, sfp1.getConstraintValueType() ); - assertSame( sfp0, - sfp1.getParent() ); + assertNull( sfp1.getParent() ); - assertTrue( fp.getConstraint( 2 ) instanceof SingleFieldConstraint ); - SingleFieldConstraint sfp2 = (SingleFieldConstraint) fp.getConstraint( 2 ); + assertTrue( fp.getConstraint( 2 ) instanceof SingleFieldConstraintEBLeftSide ); + SingleFieldConstraintEBLeftSide sfp2 = (SingleFieldConstraintEBLeftSide) fp.getConstraint( 2 ); assertEquals( "childField", sfp2.getFieldName() ); assertEquals( "java.lang.String", @@ -1779,8 +1778,7 @@ public void testNestedFieldConstraints() { sfp2.getValue() ); assertEquals( BaseSingleFieldConstraint.TYPE_LITERAL, sfp2.getConstraintValueType() ); - assertSame( sfp1, - sfp2.getParent() ); + assertNull( sfp2.getParent() ); } @Test @@ -4980,6 +4978,208 @@ public void testMethodCallWithTwoParametersIntegerAndString() throws Exception { actionCallMethod.getFieldValue( 1 ).getType() ); } + @Test + public void testLHSNumberExpressionWithoutThisPrefix() throws Exception { + String drl = "package org.mortgages;\n" + + "import java.lang.Number\n" + + "rule \"test\"\n" + + " dialect \"mvel\"\n" + + " when\n" + + " Number( intValue() > 5 )\n" + + " then\n" + + "end"; + + final HashMap> map = new HashMap>(); + final ArrayList methodInfos = new ArrayList(); + methodInfos.add( new MethodInfo( "intValue", + Collections.EMPTY_LIST, + "int", + null, + DataType.TYPE_NUMERIC_INTEGER ) ); + map.put( "java.lang.Number", + methodInfos ); + + when( dmo.getProjectMethodInformation() ).thenReturn( map ); + + final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + new ArrayList(), + dmo ); + + assertNotNull( m ); + + assertEquals( 1, + m.lhs.length ); + + assertTrue( m.lhs[ 0 ] instanceof FactPattern ); + final FactPattern fp = (FactPattern) m.lhs[ 0 ]; + assertEquals( "Number", + fp.getFactType() ); + + assertEquals( 1, + fp.getNumberOfConstraints() ); + assertTrue( fp.getConstraint( 0 ) instanceof SingleFieldConstraintEBLeftSide ); + final SingleFieldConstraintEBLeftSide exp = (SingleFieldConstraintEBLeftSide) fp.getConstraint( 0 ); + assertEquals( "int", + exp.getFieldType() ); + assertEquals( ">", + exp.getOperator() ); + assertEquals( "5", + exp.getValue() ); + + assertEquals( 2, + exp.getExpressionLeftSide().getParts().size() ); + assertTrue( exp.getExpressionLeftSide().getParts().get( 0 ) instanceof ExpressionUnboundFact ); + final ExpressionUnboundFact expPart0 = (ExpressionUnboundFact) exp.getExpressionLeftSide().getParts().get( 0 ); + assertEquals( "Number", + expPart0.getFact().getFactType() ); + + assertTrue( exp.getExpressionLeftSide().getParts().get( 1 ) instanceof ExpressionMethod ); + final ExpressionMethod expPart1 = (ExpressionMethod) exp.getExpressionLeftSide().getParts().get( 1 ); + assertEquals( "intValue", + expPart1.getName() ); + } + + @Test + public void testLHSNumberExpressionWithThisPrefix() throws Exception { + String drl = "package org.mortgages;\n" + + "import java.lang.Number\n" + + "rule \"test\"\n" + + " dialect \"mvel\"\n" + + " when\n" + + " Number( this.intValue() > 5 )\n" + + " then\n" + + "end"; + + final HashMap> map = new HashMap>(); + final ArrayList methodInfos = new ArrayList(); + methodInfos.add( new MethodInfo( "intValue", + Collections.EMPTY_LIST, + "int", + null, + DataType.TYPE_NUMERIC_INTEGER ) ); + map.put( "java.lang.Number", + methodInfos ); + + when( dmo.getProjectMethodInformation() ).thenReturn( map ); + + final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + new ArrayList(), + dmo ); + + assertNotNull( m ); + + assertEquals( 1, + m.lhs.length ); + + assertTrue( m.lhs[ 0 ] instanceof FactPattern ); + final FactPattern fp = (FactPattern) m.lhs[ 0 ]; + assertEquals( "Number", + fp.getFactType() ); + + assertEquals( 1, + fp.getNumberOfConstraints() ); + assertTrue( fp.getConstraint( 0 ) instanceof SingleFieldConstraintEBLeftSide ); + final SingleFieldConstraintEBLeftSide exp = (SingleFieldConstraintEBLeftSide) fp.getConstraint( 0 ); + assertEquals( "int", + exp.getFieldType() ); + assertEquals( ">", + exp.getOperator() ); + assertEquals( "5", + exp.getValue() ); + + assertEquals( 3, + exp.getExpressionLeftSide().getParts().size() ); + assertTrue( exp.getExpressionLeftSide().getParts().get( 0 ) instanceof ExpressionUnboundFact ); + final ExpressionUnboundFact expPart0 = (ExpressionUnboundFact) exp.getExpressionLeftSide().getParts().get( 0 ); + assertEquals( "Number", + expPart0.getFact().getFactType() ); + + assertTrue( exp.getExpressionLeftSide().getParts().get( 1 ) instanceof ExpressionField ); + final ExpressionField expPart1 = (ExpressionField) exp.getExpressionLeftSide().getParts().get( 1 ); + assertEquals( "this", + expPart1.getName() ); + + assertTrue( exp.getExpressionLeftSide().getParts().get( 2 ) instanceof ExpressionMethod ); + final ExpressionMethod expPart2 = (ExpressionMethod) exp.getExpressionLeftSide().getParts().get( 2 ); + assertEquals( "intValue", + expPart2.getName() ); + } + + @Test + public void testLHSNestedMethodCalls() throws Exception { + String drl = "package org.mortgages;\n" + + "rule \"test\"\n" + + " dialect \"mvel\"\n" + + " when\n" + + " Parent( methodToGetChild1().methodToGetChild2().field1 > 5 )\n" + + " then\n" + + "end"; + + addMethodInformation( "Parent", + "methodToGetChild1", + Collections.EMPTY_LIST, + "Child1", + null, + "Child1" ); + addMethodInformation( "Child1", + "methodToGetChild2", + Collections.EMPTY_LIST, + "Child2", + null, + "Child2" ); + addModelField( "Child2", + "field1", + "int", + DataType.TYPE_NUMERIC_INTEGER ); + + final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + new ArrayList(), + dmo ); + + assertNotNull( m ); + + assertEquals( 1, + m.lhs.length ); + + assertTrue( m.lhs[ 0 ] instanceof FactPattern ); + final FactPattern fp = (FactPattern) m.lhs[ 0 ]; + assertEquals( "Parent", + fp.getFactType() ); + + assertEquals( 1, + fp.getNumberOfConstraints() ); + assertTrue( fp.getConstraint( 0 ) instanceof SingleFieldConstraintEBLeftSide ); + final SingleFieldConstraintEBLeftSide exp = (SingleFieldConstraintEBLeftSide) fp.getConstraint( 0 ); + assertEquals( "int", + exp.getFieldType() ); + assertEquals( ">", + exp.getOperator() ); + assertEquals( "5", + exp.getValue() ); + + assertEquals( 4, + exp.getExpressionLeftSide().getParts().size() ); + assertTrue( exp.getExpressionLeftSide().getParts().get( 0 ) instanceof ExpressionUnboundFact ); + final ExpressionUnboundFact expPart0 = (ExpressionUnboundFact) exp.getExpressionLeftSide().getParts().get( 0 ); + assertEquals( "Parent", + expPart0.getFact().getFactType() ); + + assertTrue( exp.getExpressionLeftSide().getParts().get( 1 ) instanceof ExpressionMethod ); + final ExpressionMethod expPart1 = (ExpressionMethod) exp.getExpressionLeftSide().getParts().get( 1 ); + assertEquals( "methodToGetChild1", + expPart1.getName() ); + + assertTrue( exp.getExpressionLeftSide().getParts().get( 2 ) instanceof ExpressionMethod ); + final ExpressionMethod expPart2 = (ExpressionMethod) exp.getExpressionLeftSide().getParts().get( 2 ); + assertEquals( "methodToGetChild2", + expPart2.getName() ); + + assertTrue( exp.getExpressionLeftSide().getParts().get( 3 ) instanceof ExpressionField ); + final ExpressionField expPart3 = (ExpressionField) exp.getExpressionLeftSide().getParts().get( 3 ); + assertEquals( "field1", + expPart3.getName() ); + } + private void assertEqualsIgnoreWhitespace( final String expected, final String actual ) { final String cleanExpected = expected.replaceAll( "\\s+", From c7c2946dd5e500f4784f5a91f900525d3e7f9e63 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Fri, 27 Jun 2014 14:06:25 +0200 Subject: [PATCH 25/76] [DROOLS-523] make incremental compilation to also update globals (cherry picked from commit 184765346e998430064a4935fbb358930946d82c) --- .../builder/impl/KnowledgeBuilderImpl.java | 3 ++ .../IncrementalCompilationTest.java | 49 +++++++++++++++++++ .../core/impl/InternalKnowledgeBase.java | 8 +-- .../drools/core/impl/KnowledgeBaseImpl.java | 12 +++-- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java index 1175287274f..c9ff8045ea2 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java @@ -1474,6 +1474,9 @@ private void processGlobals(PackageRegistry pkgRegistry, PackageDescr packageDes clazz); this.globals.put(identifier, clazz); + if (kBase != null) { + kBase.addGlobal(identifier, clazz); + } } catch (final ClassNotFoundException e) { addBuilderResult(new GlobalError(global, e.getMessage())); e.printStackTrace(); diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java index 6d4f77761ed..bfaccd4dfe4 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java @@ -1124,4 +1124,53 @@ public void testIncrementalCompilationWithInvalidDRL() throws Exception { results4.getRemovedMessages().size() ); } + + @Test + public void testKJarUpgradeSameSessionAddingGlobal() throws Exception { + // DROOLS-523 + String drl1 = "package org.drools.compiler\n" + + "global java.lang.String foo\n" + + "rule R1 when\n" + + " $m : Message()\n" + + "then\n" + + "end\n"; + + String drl2_1 = "package org.drools.compiler\n" + + "rule R2_1 when\n" + + " $m : Message( message == \"Hi Universe\" )\n" + + "then\n" + + "end\n"; + + String drl2_2 = "package org.drools.compiler\n" + + "global java.lang.String foo\n" + + "rule R2_2 when\n" + + " $m : Message( message == foo )\n" + + "then\n" + + "end\n"; + + KieServices ks = KieServices.Factory.get(); + + // Create an in-memory jar for version 1.0.0 + ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-upgrade", "1.0.0" ); + KieModule km = createAndDeployJar( ks, releaseId1, drl1, drl2_1 ); + + // Create a session and fire rules + KieContainer kc = ks.newKieContainer( km.getReleaseId() ); + KieSession ksession = kc.newKieSession(); + ksession.insert( new Message( "Hello World" ) ); + assertEquals( 1, ksession.fireAllRules() ); + + // Create a new jar for version 1.1.0 + ReleaseId releaseId2 = ks.newReleaseId( "org.kie", "test-upgrade", "1.1.0" ); + km = createAndDeployJar( ks, releaseId2, drl1, drl2_2 ); + + // try to update the container to version 1.1.0 + kc.updateToVersion( releaseId2 ); + + ksession.setGlobal("foo", "Hello World"); + + // continue working with the session + ksession.insert( new Message( "Hello World" ) ); + assertEquals( 2, ksession.fireAllRules() ); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java b/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java index 450bf79c73b..c3b5762c956 100644 --- a/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java +++ b/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java @@ -1,6 +1,5 @@ package org.drools.core.impl; -import org.kie.api.runtime.rule.FactHandle; import org.drools.core.RuleBaseConfiguration; import org.drools.core.base.ClassFieldAccessorCache; import org.drools.core.common.InternalWorkingMemory; @@ -12,12 +11,13 @@ import org.drools.core.reteoo.LeftTupleSource; import org.drools.core.reteoo.Rete; import org.drools.core.reteoo.ReteooBuilder; -import org.drools.core.rule.*; +import org.drools.core.rule.InvalidPatternException; +import org.drools.core.rule.TypeDeclaration; import org.drools.core.spi.FactHandleFactory; import org.drools.core.spi.PropagationContext; import org.drools.core.util.TripleStore; -import org.kie.api.KieBase; import org.kie.api.io.Resource; +import org.kie.api.runtime.rule.FactHandle; import org.kie.internal.KnowledgeBase; import java.io.IOException; @@ -97,6 +97,8 @@ void retractObject(FactHandle handle, void addRule( InternalKnowledgePackage pkg, RuleImpl rule ) throws InvalidPatternException; void removeRule( InternalKnowledgePackage pkg, RuleImpl rule ) throws InvalidPatternException; + void addGlobal(String identifier, Class clazz); + void removeObjectsGeneratedFromResource(Resource resource); TypeDeclaration getTypeDeclaration( Class clazz ); diff --git a/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java b/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java index e22c7d4aed5..adcac218f20 100644 --- a/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java +++ b/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java @@ -579,8 +579,8 @@ private Map buildGlobalMapForSerialization() { private void populateGlobalsMap(Map globs) throws ClassNotFoundException { this.globals = new HashMap>(); for (Map.Entry entry : globs.entrySet()) { - this.globals.put(entry.getKey(), - this.rootClassLoader.loadClass(entry.getValue())); + addGlobal(entry.getKey(), + this.rootClassLoader.loadClass(entry.getValue())); } } @@ -1047,8 +1047,8 @@ private void mergePackage( InternalKnowledgePackage pkg, pkg.addGlobal( identifier, this.rootClassLoader.loadClass( type ) ); // this isn't a package merge, it's adding to the rulebase, but I've put it here for convienience - this.globals.put( identifier, - this.rootClassLoader.loadClass( type ) ); + addGlobal(identifier, + this.rootClassLoader.loadClass(type)); } } } @@ -1109,6 +1109,10 @@ private void mergePackage( InternalKnowledgePackage pkg, } } + public void addGlobal(String identifier, Class clazz) { + this.globals.put( identifier, clazz ); + } + protected void setupRete() { this.rete = new Rete( this ); this.reteooBuilder = new ReteooBuilder( this ); From fe0b49742bd628ccadeed284dc68f0bfba10871e Mon Sep 17 00:00:00 2001 From: mariofusco Date: Sat, 28 Jun 2014 19:08:19 +0200 Subject: [PATCH 26/76] [DROOLS-518] fix left tuple delete in from node (cherry picked from commit f0d845429ca1fd4ff4f7393437f38af60d7c46cd) --- .../compiler/integrationtests/Misc2Test.java | 49 ++++++++++++++ .../drools/core/phreak/PhreakFromNode.java | 67 +++++++------------ 2 files changed, 72 insertions(+), 44 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index 10f73ce8da1..f73ada53434 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -6151,4 +6151,53 @@ public void testDeletedEvalLeftTuple() throws Exception { ksession.insert(new Reading("t1", -6)); ksession.fireAllRules(); } + + public static class C1 { + private int counter = 0; + private final List c2s = Arrays.asList(new C2(), new C2()); + + public List getC2s() { return c2s; } + + public int getSize() { return getC2s().size(); } + + public int getCounter() { return counter; } + public void setCounter(int counter) { this.counter = counter; } + } + + public static class C2 { + private final List c3s = Arrays.asList(new C3(1), new C3(2)); + public List getC3s() { return c3s; } + } + + public static class C3 { + public final int value; + public C3(int value) { this.value = value; } + public int getValue() { return value; } + } + + @Test + public void testDeleteFromLeftTuple() throws Exception { + // DROOLS-518 + String drl = + "import " + C1.class.getCanonicalName() + ";\n" + + "import " + C2.class.getCanonicalName() + ";\n" + + "import " + C3.class.getCanonicalName() + ";\n" + + "rule R when\n" + + " $c1 : C1 ( $c2s : c2s, $c2 : c2s.get(counter), counter < size )\n" + + " C2 ( $c3s : c3s, this == $c2 ) from $c2s\n" + + " accumulate( C3 ( $value : value ) from $c3s;\n" + + " $sum : sum($value)\n" + + " )\n" + + "then\n" + + " $c1.setCounter($c1.getCounter() + 1);\n" + + " update( $c1 );\n" + + "end"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ksession = helper.build().newKieSession(); + + ksession.insert(new C1()); + ksession.fireAllRules(); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java b/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java index e78a18a5199..b2a9eceb158 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java +++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java @@ -21,6 +21,8 @@ import java.util.LinkedHashMap; import java.util.Map; +import static org.drools.core.phreak.PhreakJoinNode.updateChildLeftTuple; + /** * Created with IntelliJ IDEA. * User: mdproctor @@ -199,25 +201,7 @@ public void doLeftUpdates(FromNode fromNode, for (RightTuple rightTuple : previousMatches.values()) { for (RightTuple current = rightTuple; current != null; current = (RightTuple) rightIt.next(current)) { - LeftTuple childLeftTuple = current.getFirstChild(); - if (childLeftTuple != null) { - // childLeftTuple is null, if the constraints in the 'from' pattern fail - childLeftTuple.unlinkFromLeftParent(); - childLeftTuple.unlinkFromRightParent(); - - switch (childLeftTuple.getStagedType()) { - // handle clash with already staged entries - case LeftTuple.INSERT: - stagedLeftTuples.removeInsert(childLeftTuple); - break; - case LeftTuple.UPDATE: - stagedLeftTuples.removeUpdate(childLeftTuple); - break; - } - - childLeftTuple.setPropagationContext(propagationContext); - trgLeftTuples.addDelete(childLeftTuple); - } + deleteChildLeftTuple(propagationContext, trgLeftTuples, stagedLeftTuples, current.getFirstChild()); } } @@ -320,35 +304,30 @@ protected void checkConstraintsAndPropagate(final LeftTupleSink sink, trgLeftTuples.addInsert(childLeftTuple); } else { LeftTuple childLeftTuple = rightTuple.firstChild; - - switch (childLeftTuple.getStagedType()) { - // handle clash with already staged entries - case LeftTuple.INSERT: - stagedLeftTuples.removeInsert(childLeftTuple); - break; - case LeftTuple.UPDATE: - stagedLeftTuples.removeUpdate(childLeftTuple); - break; - } - childLeftTuple.setPropagationContext(propagationContext); - trgLeftTuples.addUpdate(childLeftTuple); + updateChildLeftTuple(childLeftTuple, stagedLeftTuples, trgLeftTuples); } } else { - LeftTuple childLeftTuple = rightTuple.firstChild; - if (childLeftTuple != null) { - switch (childLeftTuple.getStagedType()) { - // handle clash with already staged entries - case LeftTuple.INSERT: - stagedLeftTuples.removeInsert(childLeftTuple); - break; - case LeftTuple.UPDATE: - stagedLeftTuples.removeUpdate(childLeftTuple); - break; - } - childLeftTuple.setPropagationContext(propagationContext); - trgLeftTuples.addDelete(childLeftTuple); + deleteChildLeftTuple(propagationContext, trgLeftTuples, stagedLeftTuples, rightTuple.firstChild); + } + } + + private void deleteChildLeftTuple(PropagationContext propagationContext, LeftTupleSets trgLeftTuples, LeftTupleSets stagedLeftTuples, LeftTuple childLeftTuple) { + if (childLeftTuple != null) { + childLeftTuple.unlinkFromLeftParent(); + childLeftTuple.unlinkFromRightParent(); + + switch (childLeftTuple.getStagedType()) { + // handle clash with already staged entries + case LeftTuple.INSERT: + stagedLeftTuples.removeInsert(childLeftTuple); + break; + case LeftTuple.UPDATE: + stagedLeftTuples.removeUpdate(childLeftTuple); + break; } + childLeftTuple.setPropagationContext(propagationContext); + trgLeftTuples.addDelete(childLeftTuple); } } } From 9a8dd98f3391bce7169f42fcb97daf236a8458aa Mon Sep 17 00:00:00 2001 From: mariofusco Date: Tue, 1 Jul 2014 16:50:50 +0200 Subject: [PATCH 27/76] [DROOLS-509] fix method resolution during constraints jitting (cherry picked from commit aad2dab7c88877d11ec700a371906f8dc1282169) --- .../factmodel/traits/LegacyTraitTest.java | 101 +++++++++++++----- .../compiler/integrationtests/Misc2Test.java | 42 ++++++++ .../rule/constraint/ConditionAnalyzer.java | 47 +++++--- 3 files changed, 150 insertions(+), 40 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java index 2d735ab747f..9ed3ddf75be 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java @@ -1,8 +1,8 @@ + + package org.drools.compiler.factmodel.traits; -import org.drools.core.factmodel.traits.Trait; import org.drools.core.factmodel.traits.TraitFactory; -import org.drools.core.factmodel.traits.Traitable; import org.drools.core.factmodel.traits.VirtualPropertyMode; import org.junit.Test; import org.kie.api.io.ResourceType; @@ -32,13 +32,6 @@ private StatefulKnowledgeSession getSessionFromString( String drl ) { return session; } - public static interface Pers { - public String getName(); - } - - public static interface Patient extends Pers { - } - // Getters and setters are both needed. They should refer to an attribute with the same name public static class PatientImpl implements Patient { private String name; @@ -51,19 +44,30 @@ public void setName(String name) { } + public static interface Pers { + public String getName(); + } + + public static interface Patient extends Pers { + } + public static interface Procedure { public Patient getSubject(); public void setSubject(Patient p); } - @Traitable() - // Getters and setters are both needed. They should refer to an attribute with the same name + public static interface ExtendedProcedure extends Procedure { + public Pers getPers(); + public void setPers(Pers pers); + } + public class ProcedureImpl implements Procedure { public ProcedureImpl() { } private Patient subject; + @Override public Patient getSubject() { return this.subject; @@ -73,54 +77,97 @@ public void setSubject(Patient patient) { } } - // @Trait not necessary, since will need "declare trait" in DRL anyway. - // To be a full trait, the interface should also extend Thing. - public interface Surgery extends Procedure { + public class ExtendedProcedureImpl extends ProcedureImpl implements ExtendedProcedure { + + public ExtendedProcedureImpl() { + } + + private Pers pers; + @Override + public Pers getPers() { + return this.pers; + } + public void setPers(Pers pers) { + this.pers = pers; + } } + @Test public void traitWithPojoInterface() { String source = "package org.drools.compiler.test;" + "import org.drools.compiler.factmodel.traits.LegacyTraitTest.Procedure; " + "import org.drools.compiler.factmodel.traits.LegacyTraitTest; " + - "import org.drools.compiler.factmodel.traits.LegacyTraitTest.ProcedureImpl; " + - "import org.drools.compiler.factmodel.traits.LegacyTraitTest.Surgery; " + + "import org.drools.compiler.factmodel.traits.LegacyTraitTest.ExtendedProcedureImpl; " + + "import org.drools.compiler.factmodel.traits.LegacyTraitTest.ExtendedProcedure; " + // enhanced so that declaration is not needed // "declare ProcedureImpl end " + + "declare trait ExtendedProcedure " + + " @role( event )" + + "end " + // Surgery must be declared as trait, since it does not extend Thing - "declare trait Surgery end " + + "declare trait Surgery extends ExtendedProcedure end " + + + "declare ExtendedProcedureImpl " + + " @Traitable " + + "end " + "rule 'Don Procedure' " + "when " + - " $p : Procedure() " + + " $p : ExtendedProcedure() " + "then " + " don( $p, Surgery.class ); " + "end " + - "rule 'Print Provider' " + + "rule 'Test 1' " + "dialect 'mvel' " + "when " + - " $s : Surgery() " + + " $s1 : ExtendedProcedure( $subject : subject ) " + + " $s2 : ExtendedProcedure( subject == $subject ) " + "then " + - " System.out.println( $s.subject.name ); " + + "end " + + + "rule 'Test 2' " + + "dialect 'mvel' " + + "when " + + " $s1 : ExtendedProcedure( $subject : subject.name ) " + + " $s2 : ExtendedProcedure( subject.name == $subject ) " + + "then " + + "end " + + + "rule 'Test 3' " + + "dialect 'mvel' " + + "when " + + " $s1 : ExtendedProcedure( ) " + + "then " + + " update( $s1 ); " + "end " + "\n"; StatefulKnowledgeSession ks = getSessionFromString( source ); TraitFactory.setMode( VirtualPropertyMode.MAP, ks.getKieBase() ); - ProcedureImpl procedure = new ProcedureImpl(); + ExtendedProcedureImpl procedure1 = new ExtendedProcedureImpl(); + ExtendedProcedureImpl procedure2 = new ExtendedProcedureImpl(); - PatientImpl patient = new PatientImpl(); - patient.setName("John"); - procedure.setSubject( patient ); + PatientImpl patient1 = new PatientImpl(); + patient1.setName("John"); + procedure1.setSubject( patient1 ); + procedure1.setPers(new PatientImpl()); - ks.insert( procedure ); + PatientImpl patient2 = new PatientImpl(); + patient2.setName("John"); + procedure2.setSubject( patient2 ); + procedure2.setPers(new PatientImpl()); - ks.fireAllRules(); + ks.insert( procedure1 ); + ks.insert( procedure2 ); + + ks.fireAllRules( 500 ); } } + diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index f73ada53434..86428849561 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -6200,4 +6200,46 @@ public void testDeleteFromLeftTuple() throws Exception { ksession.insert(new C1()); ksession.fireAllRules(); } + + public interface I0 { + String getValue(); + } + + public interface I1 extends I0 { } + + public static class X implements I0 { + @Override + public String getValue() { + return "x"; + } + } + + public static class Y extends X implements I1 { } + + public static class Z implements I1 { + @Override + public String getValue() { + return "x"; + } + } + + @Test + public void testMethodResolution() throws Exception { + // DROOLS-509 + String drl = + "import " + I1.class.getCanonicalName() + ";\n" + + "rule R1 when\n" + + " I1 ( value == \"x\" )\n" + + "then\n" + + "end"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ksession = helper.build().newKieSession(); + + ksession.insert(new Y()); + ksession.fireAllRules(); + ksession.insert(new Z()); + ksession.fireAllRules(); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/rule/constraint/ConditionAnalyzer.java b/drools-core/src/main/java/org/drools/core/rule/constraint/ConditionAnalyzer.java index 960aaead163..3aa425d76f3 100644 --- a/drools-core/src/main/java/org/drools/core/rule/constraint/ConditionAnalyzer.java +++ b/drools-core/src/main/java/org/drools/core/rule/constraint/ConditionAnalyzer.java @@ -897,34 +897,42 @@ public MethodInvocation(Method method) { this(method, null); } - public MethodInvocation(Method method, String conditionClass) { - this.method = getMethodFromSuperclass(method, conditionClass); + public MethodInvocation(Method method, String conditionClassName) { + this.method = getMethodFromSuperclass(method, conditionClassName); } - private Method getMethodFromSuperclass(Method method, String conditionClass) { + private Method getMethodFromSuperclass(Method method, String conditionClassName) { if (method == null || Modifier.isStatic(method.getModifiers())) { return method; } Class declaringClass = method.getDeclaringClass(); + Class conditionClass = conditionClassName != null ? getConditionClass(declaringClass, conditionClassName) : null; + if (conditionClass != null) { + try { + return conditionClass.getMethod(method.getName(), method.getParameterTypes()); + } catch (Exception e) { } + } + + return getMethodForUnknownConditionClass(method, declaringClass); + } + + private Method getMethodForUnknownConditionClass(Method method, Class declaringClass) { Class declaringSuperclass = declaringClass.getSuperclass(); if (declaringSuperclass != null) { try { - return getMethodFromSuperclass(declaringSuperclass.getMethod(method.getName(), method.getParameterTypes()), conditionClass); + return getMethodForUnknownConditionClass(declaringSuperclass.getMethod(method.getName(), method.getParameterTypes()), declaringSuperclass); } catch (Exception e) { } } - Method iMethod = getMethodFromInterface(declaringClass, method, conditionClass); + Method iMethod = getMethodFromInterface(declaringClass, method); return iMethod == null ? method : iMethod; } - private Method getMethodFromInterface(Class clazz, Method method, String conditionClass) { - if (conditionClass == null || !clazz.getName().equals(conditionClass)) { - for (Class interfaze : clazz.getInterfaces()) { - Method iMethod = getMethodFromInterface(interfaze, method, conditionClass); - if (iMethod != null) { - return iMethod; - } + private Method getMethodFromInterface(Class clazz, Method method) { + for (Class interfaze : clazz.getInterfaces()) { + Method iMethod = getMethodFromInterface(interfaze, method); + if (iMethod != null) { + return iMethod; } - return null; } try { return clazz.getMethod(method.getName(), method.getParameterTypes()); @@ -932,6 +940,19 @@ private Method getMethodFromInterface(Class clazz, Method method, String cond return null; } + private Class getConditionClass(Class declaringClass, String conditionClassName) { + if (declaringClass.getName().equals(conditionClassName)) { + return declaringClass; + } + for (Class interfaze : declaringClass.getInterfaces()) { + if (interfaze.getName().equals(conditionClassName)) { + return interfaze; + } + } + Class declaringSuperclass = declaringClass.getSuperclass(); + return declaringSuperclass != null ? getConditionClass(declaringSuperclass, conditionClassName) : null; + } + public Method getMethod() { return method; } From 2052637d2fd627fe0c360e0311616edc280d8f9c Mon Sep 17 00:00:00 2001 From: sotty Date: Sun, 1 Jun 2014 12:49:53 +0100 Subject: [PATCH 28/76] [DROOLS-510] Traiting a non-natively-traitable bean breaks the assertion behavior (cherry picked from commit 17b24a744051392ca1c7ba6792dd76b1c47e4efa) --- .../compiler/factmodel/traits/TraitTest.java | 77 ++++++++++++++++++- .../core/base/DefaultKnowledgeHelper.java | 13 +++- .../drools/core/common/DefaultFactHandle.java | 28 ++++--- .../core/common/DisconnectedFactHandle.java | 15 ++-- .../common/EqualityAssertMapComparator.java | 2 +- .../common/IdentityAssertMapComparator.java | 10 ++- .../core/common/InternalFactHandle.java | 3 + .../core/common/QueryElementFactHandle.java | 5 ++ .../core/factmodel/traits/TraitFactory.java | 12 +++ .../core/factmodel/traits/TraitTypeEnum.java | 1 + 10 files changed, 140 insertions(+), 26 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/TraitTest.java b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/TraitTest.java index 23468e49e62..82f8d17b7db 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/TraitTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/TraitTest.java @@ -16,6 +16,9 @@ package org.drools.compiler.factmodel.traits; +import org.drools.compiler.Option; +import org.drools.core.RuleBaseConfiguration; +import org.drools.core.SessionConfiguration; import org.drools.core.factmodel.traits.VirtualPropertyMode; import org.junit.Assert; import org.drools.compiler.CommonTestMethodBase; @@ -46,6 +49,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.kie.api.KieBaseConfiguration; import org.kie.api.command.Command; import org.kie.api.definition.type.FactType; import org.kie.api.event.rule.AfterMatchFiredEvent; @@ -58,6 +62,7 @@ import org.kie.api.io.Resource; import org.kie.api.io.ResourceType; import org.kie.api.runtime.ClassObjectFilter; +import org.kie.api.runtime.KieSessionConfiguration; import org.kie.api.runtime.rule.FactHandle; import org.kie.api.runtime.rule.QueryResults; import org.kie.api.runtime.rule.QueryResultsRow; @@ -150,7 +155,7 @@ private StatefulKnowledgeSession getSessionFromString( String drl ) { return session; } - private KnowledgeBase getKieBaseFromString( String drl ) { + private KnowledgeBase getKieBaseFromString( String drl, RuleBaseConfiguration... conf ) { KnowledgeBuilder knowledgeBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); knowledgeBuilder.add( ResourceFactory.newByteArrayResource( drl.getBytes() ), ResourceType.DRL ); @@ -158,7 +163,7 @@ private KnowledgeBase getKieBaseFromString( String drl ) { throw new RuntimeException( knowledgeBuilder.getErrors().toString() ); } - KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); + KnowledgeBase kbase = conf.length > 0 ? KnowledgeBaseFactory.newKnowledgeBase( conf[0] ) : KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( knowledgeBuilder.getKnowledgePackages() ); return kbase; @@ -5145,4 +5150,72 @@ public void testHierarchyEncodeOnPackageMerge() { } + + + @Test + public void testDonThenReinsert() throws InterruptedException { + final String s1 = "package test;\n" + + "import org.drools.core.factmodel.traits.*; \n" + + "import org.drools.compiler.factmodel.traits.TraitTest.TBean;\n" + + "global java.util.List list;\n" + + "" + + "declare TBean " + + " @Traitable " + + " @propertyReactive " + + "end " + + "" + + "declare trait Mask " + + " @propertyReactive " + + "end " + + "" + + "rule 'Don ItemStyle' " + + " when\n" + + " $e : TBean( ) " + + " then " + + " System.out.println( 'Don' ); " + + " don( $e, Mask.class );\n" + + "end\n" + + "" + + "rule \"React\" \n" + + " when \n" + + " $m : Mask() \n" + + "then \n" + + " System.out.println( $m ); \n" + + "end\n" + + "" + + "rule Zero when not Object() then System.out.println( 'Clean' ); end "; + + KieBaseConfiguration kbx = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); + + final RuleBaseConfiguration conf = new RuleBaseConfiguration(); + conf.setAssertBehaviour( RuleBaseConfiguration.AssertBehaviour.IDENTITY ); + + final KnowledgeBase kbase = getKieBaseFromString(s1, conf); + + TraitFactory.setMode( mode, kbase ); + ArrayList list = new ArrayList(); + + StatefulKnowledgeSession knowledgeSession = kbase.newStatefulKnowledgeSession(); + knowledgeSession.setGlobal( "list", list ); + TBean e = new TBean( "aaa" ); + + int n = knowledgeSession.fireAllRules(); + assertEquals( 1, n ); + + knowledgeSession.insert( e ); + n = knowledgeSession.fireAllRules(); + assertEquals( 2, n ); + + knowledgeSession.insert( e ); + n = knowledgeSession.fireAllRules(); + assertEquals( 0, n ); + + knowledgeSession.delete( knowledgeSession.getFactHandle( e ) ); + n = knowledgeSession.fireAllRules(); + assertEquals( 1, n ); + + assertEquals( 0, knowledgeSession.getObjects().size() ); + + } + } diff --git a/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java b/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java index 02c44c7e57a..3c609a54b62 100644 --- a/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java +++ b/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java @@ -339,9 +339,14 @@ public FactHandle getFactHandle(Object object) { } handle = getFactHandleFromWM( object ); - + if ( handle == null ) { - throw new RuntimeException( "Update error: handle not found for object: " + object + ". Is it in the working memory?" ); + if ( object instanceof CoreWrapper ) { + handle = getFactHandleFromWM( ((CoreWrapper) object).getCore() ); + } + if ( handle == null ) { + throw new RuntimeException( "Update error: handle not found for object: " + object + ". Is it in the working memory?" ); + } } return handle; } @@ -766,6 +771,10 @@ protected T applyManyTraits( K core, Collection> t protected T applyTrait( K core, Class trait, Object value, boolean logical ) throws LogicalTypeInconsistencyException { + if ( identityMap == null ) { + // traits and proxies can benefit from a cached lookup + identityMap = new IdentityHashMap( ); + } TraitFactory builder = TraitFactory.getTraitBuilderForKnowledgeBase( this.getKnowledgeRuntime().getKieBase() ); TraitableBean inner = makeTraitable( core, builder, logical ); diff --git a/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java b/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java index 8116cbbbad1..58cece7a2e7 100644 --- a/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java +++ b/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java @@ -16,10 +16,9 @@ package org.drools.core.common; +import org.drools.core.factmodel.traits.TraitFactory; import org.kie.api.runtime.rule.FactHandle; -import org.drools.core.factmodel.traits.TraitProxy; import org.drools.core.factmodel.traits.TraitTypeEnum; -import org.drools.core.factmodel.traits.TraitableBean; import org.drools.core.util.AbstractBaseLinkedListNode; import org.drools.core.util.StringUtils; import org.drools.core.reteoo.LeftTuple; @@ -262,9 +261,16 @@ public Object getObject() { public void setObject( final Object object ) { this.object = object; this.objectHashCode = ( object != null ) ? object.hashCode() : 0; - this.identityHashCode = determineIdentityHashCode( object ); if ( isTraitOrTraitable() ) { - this.traitType = determineTraitType(); + TraitTypeEnum newType = determineTraitType(); + if ( ! ( this.traitType == TraitTypeEnum.LEGACY_TRAITABLE && newType != TraitTypeEnum.LEGACY_TRAITABLE ) ) { + this.identityHashCode = determineIdentityHashCode( object ); + } else { + // we are replacing a non-traitable object with its proxy, so we need to preserve the identity hashcode + } + this.traitType = newType; + } else { + this.identityHashCode = determineIdentityHashCode( object ); } } @@ -617,24 +623,22 @@ private void createFromExternalFormat( String externalFormat ) { private TraitTypeEnum determineTraitType() { if ( isTraitOrTraitable() ) { - if ( object instanceof TraitProxy ) { - return TraitTypeEnum.TRAIT; - } else if ( object instanceof TraitableBean ) { - return TraitTypeEnum.TRAITABLE; - } else { - return TraitTypeEnum.LEGACY_TRAITABLE; - } + return TraitFactory.determineTraitType( object ); } else { return TraitTypeEnum.NON_TRAIT; } } public boolean isTraitable() { - return traitType == TraitTypeEnum.TRAITABLE; + return traitType == TraitTypeEnum.TRAITABLE || traitType == TraitTypeEnum.WRAPPED_TRAITABLE; } public boolean isTraiting() { return traitType == TraitTypeEnum.TRAIT.TRAIT; } + public TraitTypeEnum getTraitType() { + return traitType; + } + } diff --git a/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java b/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java index 4cc8e141dac..5ee98789939 100644 --- a/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java +++ b/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java @@ -1,5 +1,6 @@ package org.drools.core.common; +import org.drools.core.factmodel.traits.TraitFactory; import org.drools.core.factmodel.traits.TraitProxy; import org.drools.core.factmodel.traits.TraitTypeEnum; import org.drools.core.factmodel.traits.TraitableBean; @@ -148,7 +149,7 @@ public boolean isTraitOrTraitable() { } public boolean isTraitable() { - return traitType == TraitTypeEnum.TRAITABLE; + return traitType == TraitTypeEnum.TRAITABLE || traitType == TraitTypeEnum.WRAPPED_TRAITABLE; } public boolean isTraiting() { @@ -298,16 +299,14 @@ public void readExternal(ObjectInput in) throws IOException, private TraitTypeEnum determineTraitType() { if ( isTraitOrTraitable() ) { - if ( object instanceof TraitProxy ) { - return TraitTypeEnum.TRAIT; - } else if ( object instanceof TraitableBean ) { - return TraitTypeEnum.TRAITABLE; - } else { - return TraitTypeEnum.LEGACY_TRAITABLE; - } + return TraitFactory.determineTraitType( object ); } else { return TraitTypeEnum.NON_TRAIT; } } + @Override + public TraitTypeEnum getTraitType() { + return traitType; + } } diff --git a/drools-core/src/main/java/org/drools/core/common/EqualityAssertMapComparator.java b/drools-core/src/main/java/org/drools/core/common/EqualityAssertMapComparator.java index 0b568831f27..477b8893f87 100644 --- a/drools-core/src/main/java/org/drools/core/common/EqualityAssertMapComparator.java +++ b/drools-core/src/main/java/org/drools/core/common/EqualityAssertMapComparator.java @@ -64,7 +64,7 @@ public boolean equal(final Object o1, // o1 is an object, so unwrap o2 for comparison final InternalFactHandle handle = ((InternalFactHandle) o2); o2 = handle.getObject(); - return o1 == o2 || o1.equals( o2 ); + return o1 == o2 || o2.equals( o1 ); } public int compare(final Object o1, diff --git a/drools-core/src/main/java/org/drools/core/common/IdentityAssertMapComparator.java b/drools-core/src/main/java/org/drools/core/common/IdentityAssertMapComparator.java index 507e4a6f180..362cca7e27e 100644 --- a/drools-core/src/main/java/org/drools/core/common/IdentityAssertMapComparator.java +++ b/drools-core/src/main/java/org/drools/core/common/IdentityAssertMapComparator.java @@ -21,6 +21,8 @@ import java.io.ObjectInput; import java.io.ObjectOutput; +import org.drools.core.factmodel.traits.CoreWrapper; +import org.drools.core.factmodel.traits.TraitTypeEnum; import org.drools.core.util.AbstractHashTable; import org.drools.core.util.AbstractHashTable.AbstractObjectComparator; @@ -58,7 +60,13 @@ public boolean equal(final Object o1, Object left = o1; final InternalFactHandle handle = ((InternalFactHandle) o2); - return left == handle.getObject(); + if ( left == handle.getObject() ) { + return true; + } else if ( handle.getTraitType() == TraitTypeEnum.WRAPPED_TRAITABLE ) { + return left == ( (CoreWrapper) handle.getObject() ).getCore(); + } else { + return false; + } } public int compare(final Object o1, diff --git a/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java b/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java index cb8bfc6b6c1..209ea55974a 100644 --- a/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java +++ b/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java @@ -16,6 +16,7 @@ package org.drools.core.common; +import org.drools.core.factmodel.traits.TraitTypeEnum; import org.kie.api.runtime.rule.FactHandle; import org.drools.core.reteoo.LeftTuple; import org.drools.core.reteoo.RightTuple; @@ -62,6 +63,8 @@ public interface InternalFactHandle boolean isTraitable(); boolean isTraiting(); + + TraitTypeEnum getTraitType(); RightTuple getFirstRightTuple(); diff --git a/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java b/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java index c71b819b511..41c445c728c 100644 --- a/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java +++ b/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java @@ -16,6 +16,7 @@ package org.drools.core.common; +import org.drools.core.factmodel.traits.TraitTypeEnum; import org.drools.core.reteoo.LeftTuple; import org.drools.core.reteoo.RightTuple; import org.kie.api.runtime.rule.EntryPoint; @@ -111,6 +112,10 @@ public boolean isTraiting() { return false; } + public TraitTypeEnum getTraitType() { + return TraitTypeEnum.NON_TRAIT; + } + public boolean isValid() { return true; } diff --git a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitFactory.java b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitFactory.java index 9d0d7069d9a..5f3f6f58c5e 100644 --- a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitFactory.java +++ b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitFactory.java @@ -97,4 +97,16 @@ public void setRuleBase( InternalKnowledgeBase kBase ) { this.kBase = kBase; } + public static TraitTypeEnum determineTraitType( Object object ) { + if ( object instanceof TraitProxy ) { + return TraitTypeEnum.TRAIT; + } else if ( object instanceof CoreWrapper ) { + return TraitTypeEnum.WRAPPED_TRAITABLE; + } else if ( object instanceof TraitableBean ) { + return TraitTypeEnum.TRAITABLE; + } else { + return TraitTypeEnum.LEGACY_TRAITABLE; + } + } + } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeEnum.java b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeEnum.java index 80bcb128e02..f1846686694 100644 --- a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeEnum.java +++ b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeEnum.java @@ -6,6 +6,7 @@ public enum TraitTypeEnum { TRAIT, // trait proxy TRAITABLE, // native traitable bean LEGACY_TRAITABLE, // legacy class marked as traitable, bean not yet traited (needs wrapping/injection to provide data structures + WRAPPED_TRAITABLE, // legacy class wrapped by a proxy to provide the core data structures. NON_TRAIT // not marked as trait/traitable } From f9ec0a4476d3f1d5797cbd5ce5bb0ecc26d65a69 Mon Sep 17 00:00:00 2001 From: sotty Date: Tue, 1 Jul 2014 13:12:20 -0500 Subject: [PATCH 29/76] [DROOLS-536] KieBuilder does not resolve declarations across packages - KBase Fix (cherry picked from commit 95b5a8b9104ea5ef06dc2f239282f08e1b47e946) --- .../impl/CompositeKnowledgeBuilderImpl.java | 40 ++- .../builder/impl/KnowledgeBuilderImpl.java | 10 +- .../builder/impl/TypeDeclarationBuilder.java | 264 +++++++++++------- .../compiler/lang/descr/TypeFieldDescr.java | 11 + .../compiler/TypeDeclarationTest.java | 75 +++++ .../impl/CommandFactoryServiceImpl.java | 6 +- .../runtime/rule/DeleteObjectCommand.java | 76 +++++ .../drools/core/impl/KnowledgeBaseImpl.java | 121 ++++---- .../org/drools/core/rule/TypeDeclaration.java | 18 +- 9 files changed, 456 insertions(+), 165 deletions(-) create mode 100644 drools-core/src/main/java/org/drools/core/command/runtime/rule/DeleteObjectCommand.java diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java index 5d65c0d96d6..3dfeb66203a 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java @@ -1,13 +1,14 @@ package org.drools.compiler.builder.impl; -import org.drools.compiler.builder.impl.TypeDefinition; import org.drools.compiler.compiler.BPMN2ProcessFactory; import org.drools.compiler.compiler.PackageRegistry; +import org.drools.compiler.lang.descr.AbstractClassTypeDeclarationDescr; import org.drools.compiler.lang.descr.CompositePackageDescr; import org.drools.compiler.lang.descr.ImportDescr; import org.drools.compiler.lang.descr.PackageDescr; import org.drools.compiler.lang.descr.TypeDeclarationDescr; import org.drools.core.builder.conf.impl.JaxbConfigurationImpl; +import org.drools.core.rule.TypeDeclaration; import org.kie.api.io.Resource; import org.kie.api.io.ResourceConfiguration; import org.kie.api.io.ResourceType; @@ -18,6 +19,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -282,24 +284,50 @@ private void buildRules(Collection packages) { } private void buildTypeDeclarations(Collection packages) { + List allDescrs = new ArrayList(); for (CompositePackageDescr packageDescr : packages) { for (TypeDeclarationDescr typeDeclarationDescr : packageDescr.getTypeDeclarations()) { if (isEmpty( typeDeclarationDescr.getNamespace() )) { typeDeclarationDescr.setNamespace( packageDescr.getNamespace() ); // set the default namespace } - kBuilder.getTypeBuilder().registerGeneratedType(typeDeclarationDescr); + kBuilder.getTypeBuilder().registerGeneratedType( typeDeclarationDescr ); + allDescrs.add( typeDeclarationDescr ); } } + Map unprocesseableDescrs = new HashMap(); List unresolvedTypes = new ArrayList(); for (CompositePackageDescr packageDescr : packages) { - buildTypeDeclarations(packageDescr, unresolvedTypes); + buildTypeDeclarations(packageDescr, unresolvedTypes, unprocesseableDescrs); + } + + if ( ! unprocesseableDescrs.isEmpty() ) { + List sortedDescrs = new ArrayList( unprocesseableDescrs.values() ); + for ( AbstractClassTypeDeclarationDescr descr : sortedDescrs ) { + unprocesseableDescrs.remove( descr.getType().getFullName() ); + PackageRegistry pkg = kBuilder.getPackageRegistry().get( descr.getType().getNamespace() ); + kBuilder.getTypeBuilder().processTypeDeclaration( pkg, + descr, + sortedDescrs, + unresolvedTypes, + unprocesseableDescrs ); + } } for (TypeDefinition unresolvedType : unresolvedTypes) { kBuilder.getTypeBuilder().processUnresolvedType(kBuilder.getPackageRegistry(unresolvedType.getNamespace()), unresolvedType); } + // now we need to sort TypeDeclarations based on the mutual, cross-package dependencies. + // This can't be done at the beginning, before the build pass, since the names are not yet fully qualified there. + // TODO there may be more efficient ways to do it (?) + Collection sorted = kBuilder.getTypeBuilder().sortByHierarchy( allDescrs ); + int j = 0; + for ( AbstractClassTypeDeclarationDescr descr : sorted ) { + TypeDeclaration decl = kBuilder.getPackageRegistry( descr.getNamespace() ).getPackage().getTypeDeclaration( descr.getTypeName() ); + decl.setOrder( j++ ); + } + for (CompositePackageDescr packageDescr : packages) { for (ImportDescr importDescr : packageDescr.getImports()) { kBuilder.getPackageRegistry(packageDescr.getNamespace()).addImport( importDescr ); @@ -307,7 +335,7 @@ private void buildTypeDeclarations(Collection packages) { } } - private List buildTypeDeclarations(CompositePackageDescr packageDescr, List unresolvedTypes) { + private List buildTypeDeclarations(CompositePackageDescr packageDescr, List unresolvedTypes, Map unprocessableDescrs) { kBuilder.setAssetFilter(packageDescr.getFilter()); PackageRegistry pkgRegistry = kBuilder.createPackageRegistry(packageDescr); if (pkgRegistry == null) { @@ -315,9 +343,9 @@ private List buildTypeDeclarations(CompositePackageDescr package } kBuilder.processEntryPointDeclarations(pkgRegistry, packageDescr); - List processTypeDeclarations = kBuilder.getTypeBuilder().processTypeDeclarations(pkgRegistry, packageDescr, unresolvedTypes); + List defsWithUnresolvedTypes = kBuilder.getTypeBuilder().processTypeDeclarations(pkgRegistry, packageDescr, unresolvedTypes, unprocessableDescrs); kBuilder.setAssetFilter(null); - return processTypeDeclarations; + return defsWithUnresolvedTypes; } private Collection buildPackageDescr() { diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java index c9ff8045ea2..39a558a3123 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java @@ -30,6 +30,7 @@ import org.drools.compiler.compiler.ResourceTypeDeclarationWarning; import org.drools.compiler.compiler.RuleBuildError; import org.drools.compiler.compiler.ScoreCardFactory; +import org.drools.compiler.compiler.TypeDeclarationError; import org.drools.compiler.compiler.xml.XmlPackageReader; import org.drools.compiler.lang.ExpanderException; import org.drools.compiler.lang.descr.AccumulateImportDescr; @@ -41,6 +42,7 @@ import org.drools.compiler.lang.descr.ImportDescr; import org.drools.compiler.lang.descr.PackageDescr; import org.drools.compiler.lang.descr.RuleDescr; +import org.drools.compiler.lang.descr.TypeDeclarationDescr; import org.drools.compiler.lang.descr.WindowDeclarationDescr; import org.drools.compiler.lang.dsl.DSLMappingFile; import org.drools.compiler.lang.dsl.DSLTokenizedMappingFile; @@ -1433,9 +1435,13 @@ void mergePackage(PackageRegistry pkgRegistry, PackageDescr packageDescr) { processEntryPointDeclarations(pkgRegistry, packageDescr); - typeBuilder.processTypes(pkgRegistry, packageDescr); + Map unprocessableDescrs = new HashMap(); + typeBuilder.processTypes(pkgRegistry, packageDescr, unprocessableDescrs); + for ( TypeDeclarationDescr descr : unprocessableDescrs.values() ) { + this.addBuilderResult( new TypeDeclarationError( descr, "Unable to process type " + descr.getTypeName() ) ); + } - processOtherDeclarations(pkgRegistry, packageDescr); + processOtherDeclarations( pkgRegistry, packageDescr ); } void processOtherDeclarations(PackageRegistry pkgRegistry, PackageDescr packageDescr) { diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java index 2ad014f9c5f..d524f6bdcbb 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java @@ -37,6 +37,7 @@ import org.drools.core.factmodel.traits.TraitFactory; import org.drools.core.factmodel.traits.Traitable; import org.drools.core.factmodel.traits.TraitableBean; +import org.drools.core.rule.Collect; import org.drools.core.rule.JavaDialectRuntimeData; import org.drools.core.rule.MVELDialectRuntimeData; import org.drools.core.rule.TypeDeclaration; @@ -503,7 +504,7 @@ private Class getClassForType(String type) { return cls; } - private void fillFieldTypes(AbstractClassTypeDeclarationDescr typeDescr, + public void fillFieldTypes( AbstractClassTypeDeclarationDescr typeDescr, PackageDescr packageDescr) { for (TypeFieldDescr field : typeDescr.getFields().values()) { @@ -541,12 +542,15 @@ private void fillFieldTypes(AbstractClassTypeDeclarationDescr typeDescr, * from which descriptors are generated (ii) Both (i) and (iii) are applied, * but the declared fields override the inspected ones * + * + * * @param typeDescr * The base class descriptor, to be completed with the inherited * fields descriptors + * @param unprocessableDescrs * @return true if all went well */ - private boolean mergeInheritedFields(TypeDeclarationDescr typeDescr) { + private boolean mergeInheritedFields( TypeDeclarationDescr typeDescr, List unresolvedTypes, Map unprocessableDescrs ) { if (typeDescr.getSuperTypes().isEmpty()) return false; @@ -561,16 +565,20 @@ private boolean mergeInheritedFields(TypeDeclarationDescr typeDescr) { merge = mergeInheritedFields(simpleSuperTypeName, superTypePackageName, fullSuper, - typeDescr) || merge; + typeDescr, + unresolvedTypes, + unprocessableDescrs) || merge; } return merge; } - private boolean mergeInheritedFields(String simpleSuperTypeName, - String superTypePackageName, - String fullSuper, - TypeDeclarationDescr typeDescr) { + private boolean mergeInheritedFields( String simpleSuperTypeName, + String superTypePackageName, + String fullSuper, + TypeDeclarationDescr typeDescr, + List unresolvedTypes, + Map unprocessableDescrs ) { Map fieldMap = new LinkedHashMap(); @@ -581,8 +589,13 @@ private boolean mergeInheritedFields(String simpleSuperTypeName, } else { // If there is no regisrty the type isn't a DRL-declared type, which is forbidden. // Avoid NPE JIRA-3041 when trying to access the registry. Avoid subsequent problems. - kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Cannot extend supertype '" + fullSuper + "' (not a declared type)")); - typeDescr.setType(null, null); + // DROOLS-536 At this point, the declarations might exist, but the package might not have been processed yet + unprocessableDescrs.put( typeDescr.getType().getFullName(), typeDescr ); + return false; + } + + if ( unprocessableDescrs.containsKey( fullSuper ) ) { + unprocessableDescrs.put( typeDescr.getType().getFullName(), typeDescr ); return false; } @@ -595,7 +608,7 @@ private boolean mergeInheritedFields(String simpleSuperTypeName, // look for the supertype declaration in available packages TypeDeclaration superTypeDeclaration = pack.getTypeDeclaration(simpleSuperTypeName); - if (superTypeDeclaration != null) { + if (superTypeDeclaration != null && superTypeDeclaration.getTypeClassDef() != null ) { ClassDefinition classDef = superTypeDeclaration.getTypeClassDef(); // inherit fields for (org.kie.api.definition.type.FactField fld : classDef.getFields()) { @@ -607,9 +620,18 @@ private boolean mergeInheritedFields(String simpleSuperTypeName, // new classes are already distinguished from tagged external classes isSuperClassTagged = !superTypeDeclaration.isNovel(); } else { - isSuperClassDeclared = false; + for ( TypeDefinition def : unresolvedTypes ) { + if ( def.getTypeClassName().equals( fullSuper ) ) { + TypeDeclarationDescr td = (TypeDeclarationDescr) def.typeDescr; + for ( TypeFieldDescr tf : td.getFields().values() ) { + fieldMap.put( tf.getFieldName(), tf.cloneAsInherited() ); + } + isSuperClassDeclared = def.type.isNovel(); + break; + } + isSuperClassDeclared = false; + } } - } else { isSuperClassDeclared = false; } @@ -699,7 +721,10 @@ protected TypeFieldDescr buildInheritedFieldDescrFromDefinition(org.kie.api.defi PatternDescr fldType = new PatternDescr(); TypeFieldDescr inheritedFldDescr = new TypeFieldDescr(); inheritedFldDescr.setFieldName(fld.getName()); - fldType.setObjectType(((FieldDefinition) fld).getFieldAccessor().getExtractToClassName()); + if ( ((FieldDefinition) fld).getFieldAccessor() != null ) { + // target class may have not been resolved yet + fldType.setObjectType(((FieldDefinition) fld).getFieldAccessor().getExtractToClassName()); + } inheritedFldDescr.setPattern(fldType); if (fld.isKey()) { inheritedFldDescr.getAnnotations().put(TypeDeclaration.ATTR_KEY, @@ -726,9 +751,9 @@ protected TypeFieldDescr buildInheritedFieldDescrFromDefinition(org.kie.api.defi return inheritedFldDescr; } - void processTypes(PackageRegistry pkgRegistry, PackageDescr packageDescr) { + void processTypes(PackageRegistry pkgRegistry, PackageDescr packageDescr, Map unprocessableDescrs) { // process types in 2 steps to deal with circular and recursive declarations - processUnresolvedTypes(pkgRegistry, processTypeDeclarations(pkgRegistry, packageDescr, new ArrayList())); + processUnresolvedTypes(pkgRegistry, processTypeDeclarations(pkgRegistry, packageDescr, new ArrayList(), unprocessableDescrs ) ); } void processUnresolvedTypes(PackageRegistry pkgRegistry, List unresolvedTypeDefinitions) { @@ -941,7 +966,7 @@ void removeTypesGeneratedFromResource(Resource resource) { } } - List processTypeDeclarations(PackageRegistry pkgRegistry, PackageDescr packageDescr, List unresolvedTypes) { + List processTypeDeclarations( PackageRegistry pkgRegistry, PackageDescr packageDescr, List unresolvedTypes, Map unprocessableDescrs ) { Map foreignPackages = null; @@ -1075,121 +1100,148 @@ List processTypeDeclarations(PackageRegistry pkgRegistry, Packag continue; } - //descriptor needs fields inherited from superclass - if (typeDescr instanceof TypeDeclarationDescr) { - TypeDeclarationDescr tDescr = (TypeDeclarationDescr) typeDescr; - for (QualifiedName qname : tDescr.getSuperTypes()) { - //descriptor needs fields inherited from superclass - if (mergeInheritedFields(tDescr)) { - //descriptor also needs metadata from superclass - for (AbstractClassTypeDeclarationDescr descr : sortedTypeDescriptors) { - // sortedTypeDescriptors are sorted by inheritance order, so we'll always find the superClass (if any) before the subclass - if (qname.equals(descr.getType())) { - typeDescr.getAnnotations().putAll(descr.getAnnotations()); - break; - } else if (typeDescr.getType().equals(descr.getType())) { - break; - } + processTypeDeclaration( pkgRegistry, typeDescr, sortedTypeDescriptors, unresolvedTypes, unprocessableDescrs ); + } + return unresolvedTypes; + } + public void processTypeDeclaration( PackageRegistry pkgRegistry, + AbstractClassTypeDeclarationDescr typeDescr, + Collection sortedTypeDescriptors, + List unresolvedTypes, + Map unprocessableDescrs ) { + //descriptor needs fields inherited from superclass + if (typeDescr instanceof TypeDeclarationDescr) { + TypeDeclarationDescr tDescr = (TypeDeclarationDescr) typeDescr; + for (QualifiedName qname : tDescr.getSuperTypes()) { + //descriptor needs fields inherited from superclass + if (mergeInheritedFields(tDescr, unresolvedTypes, unprocessableDescrs)) { + //descriptor also needs metadata from superclass + for (AbstractClassTypeDeclarationDescr descr : sortedTypeDescriptors) { + // sortedTypeDescriptors are sorted by inheritance order, so we'll always find the superClass (if any) before the subclass + if (qname.equals(descr.getType())) { + typeDescr.getAnnotations().putAll(descr.getAnnotations()); + break; + } else if (typeDescr.getType().equals(descr.getType())) { + break; } + } } } + } - // Go on with the build - TypeDeclaration type = new TypeDeclaration(typeDescr.getTypeName()); - if (typeDescr.getResource() == null) { - typeDescr.setResource(kbuilder.getCurrentResource()); - } - type.setResource(typeDescr.getResource()); + if ( unprocessableDescrs.containsKey( typeDescr.getType().getFullName() ) ) { + return; + } - TypeDeclaration parent = null; - if (!typeDescr.getSuperTypes().isEmpty()) { - // parent might have inheritable properties - PackageRegistry sup = kbuilder.getPackageRegistry(typeDescr.getSuperTypeNamespace()); - if (sup != null) { - parent = sup.getPackage().getTypeDeclaration(typeDescr.getSuperTypeName()); - if (parent == null) { - kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Declared class " + typeDescr.getTypeName() + " can't extend class " + typeDescr.getSuperTypeName() + ", it should be declared")); - } else { - if (parent.getNature() == TypeDeclaration.Nature.DECLARATION && kbuilder.getKnowledgeBase() != null) { - // trying to find a definition - parent = kbuilder.getKnowledgeBase().getPackagesMap().get(typeDescr.getSuperTypeNamespace()).getTypeDeclaration(typeDescr.getSuperTypeName()); +// for ( QualifiedName qualifiedName : typeDescr.getSuperTypes() ) { +// for ( TypeDefinition def : unresolvedTypes ) { +// if ( def.typeDescr.getType().equals( qualifiedName ) ) { +// unresolvedTypes.add( ) +// } +// } +// } + + // Go on with the build + TypeDeclaration type = new TypeDeclaration(typeDescr.getTypeName()); + if (typeDescr.getResource() == null) { + typeDescr.setResource(kbuilder.getCurrentResource()); + } + type.setResource(typeDescr.getResource()); + + TypeDeclaration parent = null; + if (!typeDescr.getSuperTypes().isEmpty()) { + // parent might have inheritable properties + PackageRegistry sup = kbuilder.getPackageRegistry(typeDescr.getSuperTypeNamespace()); + if (sup != null) { + parent = sup.getPackage().getTypeDeclaration(typeDescr.getSuperTypeName()); + if ( parent == null ) { + for ( TypeDefinition tdef : unresolvedTypes ) { + if ( tdef.getTypeClassName().equals( typeDescr.getSuperTypes().get( 0 ).getFullName() ) ) { + parent = tdef.type; } } } + if (parent == null) { + kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Declared class " + typeDescr.getTypeName() + " can't extend class " + typeDescr.getSuperTypeName() + ", it should be declared")); + } else { + if (parent.getNature() == TypeDeclaration.Nature.DECLARATION && kbuilder.getKnowledgeBase() != null) { + // trying to find a definition + parent = kbuilder.getKnowledgeBase().getPackagesMap().get(typeDescr.getSuperTypeNamespace()).getTypeDeclaration(typeDescr.getSuperTypeName()); + } + } } + } - // is it a regular fact or an event? - AnnotationDescr annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.Role.ID); - String role = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; - if (role != null) { - type.setRole(TypeDeclaration.Role.parseRole(role)); - } else if (parent != null) { - type.setRole(parent.getRole()); - } - - annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.ATTR_TYPESAFE); - String typesafe = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; - if (typesafe != null) { - type.setTypesafe(Boolean.parseBoolean(typesafe)); - } else if (parent != null && isSet(parent.getSetMask(), TypeDeclaration.TYPESAFE_BIT)) { - type.setTypesafe(parent.isTypesafe()); - } + // is it a regular fact or an event? + AnnotationDescr annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.Role.ID); + String role = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; + if (role != null) { + type.setRole(TypeDeclaration.Role.parseRole(role)); + } else if (parent != null) { + type.setRole(parent.getRole()); + } - // is it a pojo or a template? - annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.Format.ID); - String format = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; - if (format != null) { - type.setFormat(TypeDeclaration.Format.parseFormat(format)); - } + annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.ATTR_TYPESAFE); + String typesafe = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; + if (typesafe != null) { + type.setTypesafe(Boolean.parseBoolean(typesafe)); + } else if (parent != null && isSet(parent.getSetMask(), TypeDeclaration.TYPESAFE_BIT)) { + type.setTypesafe(parent.isTypesafe()); + } - // is it a class, a trait or an enum? - annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.Kind.ID); - String kind = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; - if (kind != null) { - type.setKind(TypeDeclaration.Kind.parseKind(kind)); - } - if (typeDescr instanceof EnumDeclarationDescr) { - type.setKind(TypeDeclaration.Kind.ENUM); - } + // is it a pojo or a template? + annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.Format.ID); + String format = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; + if (format != null) { + type.setFormat(TypeDeclaration.Format.parseFormat(format)); + } - annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.ATTR_CLASS); - String className = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; - if (isEmpty(className)) { - className = type.getTypeName(); - } + // is it a class, a trait or an enum? + annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.Kind.ID); + String kind = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; + if (kind != null) { + type.setKind(TypeDeclaration.Kind.parseKind(kind)); + } + if (typeDescr instanceof EnumDeclarationDescr) { + type.setKind(TypeDeclaration.Kind.ENUM); + } - try { + annotationDescr = getSingleAnnotation(typeDescr, TypeDeclaration.ATTR_CLASS); + String className = (annotationDescr != null) ? annotationDescr.getSingleValue() : null; + if (isEmpty(className)) { + className = type.getTypeName(); + } - // the type declaration is generated in any case (to be used by subclasses, if any) - // the actual class will be generated only if needed - if (!kbuilder.hasErrors()) { - generateDeclaredBean(typeDescr, - type, - pkgRegistry, - unresolvedTypes); + try { - Class clazz = pkgRegistry.getTypeResolver().resolveType(typeDescr.getType().getFullName()); - type.setTypeClass(clazz); - } + // the type declaration is generated in any case (to be used by subclasses, if any) + // the actual class will be generated only if needed + if (!kbuilder.hasErrors()) { + generateDeclaredBean(typeDescr, + type, + pkgRegistry, + unresolvedTypes); - } catch (final ClassNotFoundException e) { - kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, - "Class '" + className + - "' not found for type declaration of '" + - type.getTypeName() + "'")); - continue; + Class clazz = pkgRegistry.getTypeResolver().resolveType(typeDescr.getType().getFullName()); + type.setTypeClass(clazz); } - if (!processTypeFields(pkgRegistry, typeDescr, type, true)) { - unresolvedTypes.add(new TypeDefinition(type, typeDescr)); - } + } catch (final ClassNotFoundException e) { + kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, + "Class '" + className + + "' not found for type declaration of '" + + type.getTypeName() + "'")); + return; } - return unresolvedTypes; + if (!processTypeFields(pkgRegistry, typeDescr, type, true)) { + unresolvedTypes.add(new TypeDefinition(type, typeDescr)); + } } + private AnnotationDescr getSingleAnnotation(AbstractClassTypeDeclarationDescr typeDescr, String name) { AnnotationDescr annotationDescr = typeDescr.getAnnotation(name); if (annotationDescr != null && annotationDescr.isDuplicated()) { diff --git a/drools-compiler/src/main/java/org/drools/compiler/lang/descr/TypeFieldDescr.java b/drools-compiler/src/main/java/org/drools/compiler/lang/descr/TypeFieldDescr.java index 1843937a6d2..2470fdc8de7 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/lang/descr/TypeFieldDescr.java +++ b/drools-compiler/src/main/java/org/drools/compiler/lang/descr/TypeFieldDescr.java @@ -132,4 +132,15 @@ public void setInherited(boolean inherited) { this.inherited = inherited; } + public TypeFieldDescr cloneAsInherited() { + TypeFieldDescr clone = new TypeFieldDescr( fieldName, pattern ); + clone.index = this.index; + clone.initExpr = this.initExpr; + clone.inherited = true; + for ( AnnotationDescr ad : this.getAnnotations().values() ) { + clone.addAnnotation( ad ); + } + return clone; + } + } diff --git a/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java b/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java index b2f46f0e77a..9d67e725e5a 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java @@ -10,6 +10,9 @@ import org.kie.api.builder.KieBuilder; import org.kie.api.builder.KieFileSystem; import org.kie.api.builder.Message; +import org.kie.api.builder.model.KieModuleModel; +import org.kie.api.io.KieResources; +import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.rule.FactHandle; import org.kie.internal.KnowledgeBase; import org.kie.internal.KnowledgeBaseFactory; @@ -38,6 +41,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Collection; +import java.util.Collections; public class TypeDeclarationTest { @@ -755,4 +759,75 @@ public void testPreventReflectionAPIsOnJavaClasses() { FactType type = kieBase.getFactType( "org.drools.compiler", "Person" ); } + + @Test + public void testCrossPackageDeclares() { + String pkg1 = + "package org.drools.compiler.test1; " + + "import org.drools.compiler.test2.GrandChild; " + + "import org.drools.compiler.test2.Child; " + + "import org.drools.compiler.test2.BarFuu; " + + + "declare FuBaz foo : String end " + + + "declare Parent " + + " unknown : BarFuu " + + "end " + + + "declare GreatChild extends GrandChild " + + " father : Child " + + "end " + ; + + String pkg2 = + "package org.drools.compiler.test2; " + + "import org.drools.compiler.test1.Parent; " + + "import org.drools.compiler.test1.FuBaz; " + + + "declare BarFuu " + + " baz : FuBaz " + + "end " + + + "declare Child extends Parent " + + "end " + + + "declare GrandChild extends Child " + + " notknown : FuBaz " + + "end " + ; + + KieServices ks = KieServices.Factory.get(); + KieFileSystem kfs = ks.newKieFileSystem(); + + kfs.generateAndWritePomXML( ks.newReleaseId( "test", "foo", "1.0" ) ); + KieModuleModel km = ks.newKieModuleModel(); + km.newKieBaseModel( "rules" ) + .addPackage( "org.drools.compiler.test2" ) + .addPackage( "org.drools.compiler.test1" ); + kfs.writeKModuleXML( km.toXML() ); + + KieResources kr = ks.getResources(); + Resource r1 = kr.newByteArrayResource( pkg1.getBytes() ) + .setResourceType( ResourceType.DRL ) + .setSourcePath( "org/drools/compiler/test1/p1.drl" ); + Resource r2 = kr.newByteArrayResource( pkg2.getBytes() ) + .setResourceType( ResourceType.DRL ) + .setSourcePath( "org/drools/compiler/test2/p2.drl" ); + + kfs.write( r1 ); + kfs.write( r2 ); + + KieBuilder builder = ks.newKieBuilder( kfs ); + builder.buildAll(); + + assertEquals( Collections.emptyList(), builder.getResults().getMessages( Message.Level.ERROR ) ); + + KieContainer kc = ks.newKieContainer(builder.getKieModule().getReleaseId()); + FactType ft = kc.getKieBase( "rules" ).getFactType( "org.drools.compiler.test2", "Child" ); + + assertNotNull( ft ); + assertNotNull( ft.getFactClass() ); + assertEquals( "org.drools.compiler.test1.Parent", ft.getFactClass().getSuperclass().getName() ); + + } } diff --git a/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java b/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java index cd10cea08d8..0ca460bf403 100644 --- a/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java +++ b/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java @@ -103,7 +103,11 @@ public Command newInsert(Object object, String outIdentifier, boolean returnObje public Command newDelete(FactHandle factHandle) { return new DeleteCommand( factHandle ); } - + + public Command newDeleteObject(Object object,String entryPoint) { + return new DeleteObjectCommand( object, entryPoint ); + } + public Setter newSetter(String accessor, String value) { return new SetterImpl(accessor, value); diff --git a/drools-core/src/main/java/org/drools/core/command/runtime/rule/DeleteObjectCommand.java b/drools-core/src/main/java/org/drools/core/command/runtime/rule/DeleteObjectCommand.java new file mode 100644 index 00000000000..5bc02aa3b2a --- /dev/null +++ b/drools-core/src/main/java/org/drools/core/command/runtime/rule/DeleteObjectCommand.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 JBoss Inc + * + * 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.core.command.runtime.rule; + +import org.drools.core.command.impl.GenericCommand; +import org.drools.core.command.impl.KnowledgeCommandContext; +import org.drools.core.util.StringUtils; +import org.drools.core.xml.jaxb.util.JaxbUnknownAdapter; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.EntryPoint; +import org.kie.api.runtime.rule.FactHandle; +import org.kie.internal.command.Context; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +@XmlAccessorType(XmlAccessType.NONE) +public class DeleteObjectCommand + implements GenericCommand { + + @XmlAttribute(name="object") + @XmlJavaTypeAdapter(JaxbUnknownAdapter.class) + private Object object; + + @XmlAttribute(name="entry-point") + private String entryPoint = "DEFAULT"; + + public DeleteObjectCommand() { + } + + public DeleteObjectCommand( Object object, String entryPoint ) { + this.object = object; + if ( ! StringUtils.isEmpty( this.entryPoint ) ) { + this.entryPoint = entryPoint; + } + } + + public Void execute(Context context) { + KieSession ksession = ((KnowledgeCommandContext) context).getKieSession(); + EntryPoint ep = ksession.getEntryPoint( entryPoint ); + if ( ep != null ) { + FactHandle handle = ksession.getEntryPoint( entryPoint ).getFactHandle( object ); + ksession.delete( handle ); + } + return null; + } + + public Object getObject() { + return this.object; + } + + public String getEntryPointId() { + return entryPoint; + } + + public String toString() { + return "session.entryPoints(" + ((this.entryPoint == null ) ? "DEFAULT" : this.entryPoint) + ").delete( " + object + " );"; + } + +} diff --git a/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java b/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java index adcac218f20..e53e0f0b3aa 100644 --- a/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java +++ b/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java @@ -564,8 +564,8 @@ public void writeExternal(final ObjectOutput out) throws IOException { private Map buildGlobalMapForSerialization() { Map gl = new HashMap(); for (Map.Entry> entry : this.globals.entrySet()) { - gl.put(entry.getKey(), - entry.getValue().getName()); + gl.put( entry.getKey(), + entry.getValue().getName() ); } return gl; } @@ -754,60 +754,46 @@ public void addPackages( final Collection newPkgs ) { } - + List allTypeDeclarations = new ArrayList(); // Add all Type Declarations, this has to be done first incase packages cross reference each other during build process. for ( InternalKnowledgePackage newPkg : clonedPkgs ) { // we have to do this before the merging, as it does some classloader resolving - String lastType = null; - try { - // Add the type declarations to the RuleBase - if ( newPkg.getTypeDeclarations() != null ) { - JavaDialectRuntimeData runtime = ((JavaDialectRuntimeData) newPkg.getDialectRuntimeRegistry().getDialectData( "java" )); - - // add type declarations - for ( TypeDeclaration newDecl : newPkg.getTypeDeclarations().values() ) { - lastType = newDecl.getTypeClassName(); - - - TypeDeclaration typeDeclaration = this.classTypeDeclaration.get( newDecl.getTypeClassName() ); - if ( typeDeclaration == null ) { - String className = newDecl.getTypeClassName(); - - byte [] def = runtime.getClassDefinition(convertClassToResourcePath(className)); - Class definedKlass = registerAndLoadTypeDefinition( className, def ); - - if ( definedKlass == null && typeDeclaration.isNovel() ) { - throw new RuntimeException( "Registering null bytes for class " + className ); - } - - if (newDecl.getTypeClassDef() == null) { - newDecl.setTypeClassDef( new ClassDefinition() ); - } - newDecl.getTypeClassDef().setDefinedClass( definedKlass ); - newDecl.setTypeClass( definedKlass ); - - this.classTypeDeclaration.put( className, newDecl ); - typeDeclaration = newDecl; - } else { - Class definedKlass = typeDeclaration.getTypeClass(); + if ( newPkg.getTypeDeclarations() != null ) { + for ( TypeDeclaration newDecl : newPkg.getTypeDeclarations().values() ) { + allTypeDeclarations.add( newDecl ); + } + } + } + Collections.sort( allTypeDeclarations ); - newDecl.getTypeClassDef().setDefinedClass( definedKlass ); - newDecl.setTypeClass( definedKlass ); + String lastType = null; + try { + // add type declarations according to the global order + for ( TypeDeclaration newDecl : allTypeDeclarations ) { + lastType = newDecl.getTypeClassName(); + InternalKnowledgePackage newPkg = null; + for ( InternalKnowledgePackage kpkg : clonedPkgs ) { + if ( kpkg.getTypeDeclarations().containsKey( newDecl.getTypeName() ) ) { + newPkg = kpkg; + break; + } + } + processTypeDeclaration( newDecl, newPkg ); + } - mergeTypeDeclarations( typeDeclaration, - newDecl ); - } + } catch (ClassNotFoundException e) { + throw new RuntimeException( "unable to resolve Type Declaration class '" + lastType + "'", e ); + } - // update existing OTNs - updateDependentTypes( newPkg, - typeDeclaration ); - } + for ( InternalKnowledgePackage newPkg : clonedPkgs ) { + // Add functions + try { + JavaDialectRuntimeData runtime = ((JavaDialectRuntimeData) newPkg.getDialectRuntimeRegistry().getDialectData( "java" )); - for ( Function function : newPkg.getFunctions().values() ) { - String functionClassName = function.getClassName(); - byte [] def = runtime.getStore().get(convertClassToResourcePath(functionClassName)); - registerAndLoadTypeDefinition( functionClassName, def ); - } + for ( Function function : newPkg.getFunctions().values() ) { + String functionClassName = function.getClassName(); + byte [] def = runtime.getStore().get(convertClassToResourcePath(functionClassName)); + registerAndLoadTypeDefinition( functionClassName, def ); } } catch (ClassNotFoundException e) { throw new RuntimeException( "unable to resolve Type Declaration class '" + lastType + "'", e ); @@ -871,6 +857,43 @@ public void addPackages( final Collection newPkgs ) { } } + protected void processTypeDeclaration( TypeDeclaration newDecl, InternalKnowledgePackage newPkg ) throws ClassNotFoundException { + JavaDialectRuntimeData runtime = ((JavaDialectRuntimeData) newPkg.getDialectRuntimeRegistry().getDialectData( "java" )); + + TypeDeclaration typeDeclaration = this.classTypeDeclaration.get( newDecl.getTypeClassName() ); + if ( typeDeclaration == null ) { + String className = newDecl.getTypeClassName(); + + byte [] def = runtime.getClassDefinition(convertClassToResourcePath(className)); + Class definedKlass = registerAndLoadTypeDefinition( className, def ); + + if ( definedKlass == null && typeDeclaration.isNovel() ) { + throw new RuntimeException( "Registering null bytes for class " + className ); + } + + if (newDecl.getTypeClassDef() == null) { + newDecl.setTypeClassDef( new ClassDefinition() ); + } + newDecl.getTypeClassDef().setDefinedClass( definedKlass ); + newDecl.setTypeClass( definedKlass ); + + this.classTypeDeclaration.put( className, newDecl ); + typeDeclaration = newDecl; + } else { + Class definedKlass = typeDeclaration.getTypeClass(); + + newDecl.getTypeClassDef().setDefinedClass( definedKlass ); + newDecl.setTypeClass( definedKlass ); + + mergeTypeDeclarations( typeDeclaration, + newDecl ); + } + + // update existing OTNs + updateDependentTypes( newPkg, + typeDeclaration ); + } + public Class registerAndLoadTypeDefinition( String className, byte[] def ) throws ClassNotFoundException { try { return this.rootClassLoader.loadClass( className ); diff --git a/drools-core/src/main/java/org/drools/core/rule/TypeDeclaration.java b/drools-core/src/main/java/org/drools/core/rule/TypeDeclaration.java index 3d7a87804ed..a284b31158d 100644 --- a/drools-core/src/main/java/org/drools/core/rule/TypeDeclaration.java +++ b/drools-core/src/main/java/org/drools/core/rule/TypeDeclaration.java @@ -43,7 +43,8 @@ public class TypeDeclaration implements KnowledgeDefinition, - Externalizable { + Externalizable, + Comparable { public static final int ROLE_BIT = 1; public static final int TYPESAFE_BIT = 2; @@ -164,6 +165,7 @@ public static Nature parseNature(String nature) { private transient ObjectType objectType; private long expirationOffset = -1; + private int order; private List redeclarations; public TypeDeclaration() { @@ -598,4 +600,18 @@ public String getFullName() { public String getId() { return getTypeName(); } + + public int getOrder() { + return order; + } + + public void setOrder( int order ) { + this.order = order; + } + + @Override + public int compareTo( TypeDeclaration o ) { + return this.order - o.order; + } + } From 5334f9207b2d86b880b220603ffb842770afc91f Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 3 Jul 2014 15:49:55 +0200 Subject: [PATCH 30/76] [DROOLS-532] fix automatic version recognition when running drools inside eclipse (cherry picked from commit 5d5bddf64291f4a1b4370189d9a0b734af7bfb1c) --- drools-core/pom.xml | 33 +++++++++++++++++++ .../java/org/drools/core/util/Drools.java | 24 +++++++++----- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/drools-core/pom.xml b/drools-core/pom.xml index 3715de840a2..47b6880a5db 100644 --- a/drools-core/pom.xml +++ b/drools-core/pom.xml @@ -214,6 +214,39 @@ src/main/findbugs/findbugs-exclude.xml + + + maven-eclipse-plugin + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + <project>/.externalToolBuilders/mvn-resources.launch + + + + + + .externalToolBuilders/mvn-resources.launch + + + + + + + + + + + +]]> + + + + + diff --git a/drools-core/src/main/java/org/drools/core/util/Drools.java b/drools-core/src/main/java/org/drools/core/util/Drools.java index 6b239f3026b..0027ab2173c 100644 --- a/drools-core/src/main/java/org/drools/core/util/Drools.java +++ b/drools-core/src/main/java/org/drools/core/util/Drools.java @@ -3,14 +3,18 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Drools { - private static String droolsFullVersion; + private static Pattern VERSION_PAT = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)([\\.-](.*))?"); + private static String droolsFullVersion; private static int droolsMajorVersion; private static int droolsMinorVersion; private static int droolsRevisionVersion; + private static String droolsRevisionClassifier; static { droolsFullVersion = Drools.class.getPackage().getImplementationVersion(); @@ -35,13 +39,13 @@ public class Drools { } } - String[] versionSplit = droolsFullVersion.split("\\."); - droolsMajorVersion = Integer.parseInt(versionSplit[0]); - droolsMinorVersion = Integer.parseInt(versionSplit[1]); - int pos = versionSplit[2].indexOf('-'); - droolsRevisionVersion = pos >= 0 ? - Integer.parseInt(versionSplit[2].substring(0, pos)) : - Integer.parseInt(versionSplit[2]); + Matcher m = VERSION_PAT.matcher(droolsFullVersion); + if( m.matches() ) { + droolsMajorVersion = Integer.parseInt(m.group(1)); + droolsMinorVersion = Integer.parseInt(m.group(2)); + droolsRevisionVersion = Integer.parseInt(m.group(3)); + droolsRevisionClassifier = m.group(5); + } } public static String getFullVersion() { @@ -60,6 +64,10 @@ public static int getRevisionVersion() { return droolsRevisionVersion; } + public static String getRevisionClassifier() { + return droolsRevisionClassifier; + } + public static boolean isCompatible(int major, int minor, int revision) { if (major != droolsMajorVersion) { return false; From 193a27691d98c0677332c6ab3afcc0e88b396cfb Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 30 Jun 2014 20:17:34 +0200 Subject: [PATCH 31/76] [DROOLS-541] implement session cache (cherry picked from commit 87607768d6b0c1e82925e2a3d07d1b9f5e32ef44) --- .../SegmentMemoryPrototypeTest.java | 24 ++++- .../drools/core/RuleBaseConfiguration.java | 42 ++++++--- .../org/drools/core/SessionConfiguration.java | 42 +++++++-- .../drools/core/base/MapGlobalResolver.java | 9 +- .../common/AbstractFactHandleFactory.java | 11 ++- .../core/common/ConcurrentNodeMemories.java | 26 ++++++ .../org/drools/core/common/DefaultAgenda.java | 21 ++++- .../java/org/drools/core/common/Memory.java | 7 +- .../org/drools/core/common/NodeMemories.java | 2 + .../common/PhreakWorkingMemoryFactory.java | 4 + .../core/impl/InternalKnowledgeBase.java | 7 ++ .../drools/core/impl/KnowledgeBaseImpl.java | 51 +++++------ .../org/drools/core/impl/SessionsCache.java | 87 +++++++++++++++++++ .../impl/StatefulKnowledgeSessionImpl.java | 48 ++++++++-- .../impl/StatelessKnowledgeSessionImpl.java | 3 +- .../drools/core/phreak/SegmentUtilities.java | 2 +- .../drools/core/reteoo/AccumulateNode.java | 32 ++++--- .../org/drools/core/reteoo/AlphaNode.java | 15 ++-- .../org/drools/core/reteoo/BetaMemory.java | 17 ++-- .../core/reteoo/ConditionalBranchNode.java | 2 + .../drools/core/reteoo/EvalConditionNode.java | 2 + .../java/org/drools/core/reteoo/FromNode.java | 15 +++- .../core/reteoo/LeftInputAdapterNode.java | 4 + .../drools/core/reteoo/LeftTupleMemory.java | 25 +++--- .../drools/core/reteoo/ObjectTypeNode.java | 6 +- .../org/drools/core/reteoo/PathMemory.java | 6 ++ .../core/reteoo/PropagationQueuingNode.java | 7 +- .../drools/core/reteoo/QueryElementNode.java | 4 + .../core/reteoo/RightInputAdapterNode.java | 17 ++-- .../drools/core/reteoo/RightTupleMemory.java | 2 + .../org/drools/core/reteoo/SegmentMemory.java | 9 ++ .../org/drools/core/reteoo/TimerNode.java | 5 ++ .../org/drools/core/reteoo/WindowNode.java | 4 +- .../org/drools/core/spi/GlobalResolver.java | 9 +- .../drools/core/util/AbstractHashTable.java | 20 +++-- .../org/drools/core/util/ObjectHashMap.java | 7 -- .../org/drools/core/util/ObjectHashSet.java | 6 -- .../util/index/LeftTupleIndexHashTable.java | 24 ++--- .../core/util/index/LeftTupleIndexRBTree.java | 6 +- .../util/index/LeftTupleIndexRangeRBTree.java | 6 +- .../util/index/RightTupleIndexHashTable.java | 8 ++ .../util/index/RightTupleIndexRBTree.java | 6 +- .../index/RightTupleIndexRangeRBTree.java | 15 ++-- 43 files changed, 506 insertions(+), 159 deletions(-) create mode 100644 drools-core/src/main/java/org/drools/core/impl/SessionsCache.java diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/SegmentMemoryPrototypeTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/SegmentMemoryPrototypeTest.java index d64fe93cfff..16f9e3895a8 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/SegmentMemoryPrototypeTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/SegmentMemoryPrototypeTest.java @@ -1,7 +1,10 @@ package org.drools.compiler.integrationtests; +import org.drools.compiler.integrationtests.DynamicRulesChangesTest.Fire; +import org.drools.compiler.integrationtests.DynamicRulesChangesTest.Room; +import org.drools.compiler.integrationtests.DynamicRulesChangesTest.Sprinkler; import org.drools.core.impl.InternalKnowledgeBase; -import org.junit.Ignore; +import org.drools.core.impl.StatefulKnowledgeSessionImpl; import org.junit.Test; import org.kie.api.io.ResourceType; import org.kie.api.runtime.KieSession; @@ -16,8 +19,6 @@ import static org.junit.Assert.assertEquals; -import org.drools.compiler.integrationtests.DynamicRulesChangesTest.*; - public class SegmentMemoryPrototypeTest { private static final String DRL = "import " + DynamicRulesChangesTest.class.getCanonicalName() + "\n " + @@ -84,6 +85,23 @@ public void testSegmentMemoryPrototype() throws Exception { checkKieSession(ksession2); } + @Test + public void testSessionCache() throws Exception { + KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); + kbuilder.add( ResourceFactory.newByteArrayResource(DRL.getBytes()), + ResourceType.DRL ); + + InternalKnowledgeBase kbase = (InternalKnowledgeBase) KnowledgeBaseFactory.newKnowledgeBase(); + kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); + + StatefulKnowledgeSessionImpl ksession = (StatefulKnowledgeSessionImpl)kbase.newKieSession(); + checkKieSession(ksession); + + ksession.dispose(); + ksession.reset(); + checkKieSession(ksession); + } + private void checkKieSession(KieSession ksession) { final List events = new ArrayList(); diff --git a/drools-core/src/main/java/org/drools/core/RuleBaseConfiguration.java b/drools-core/src/main/java/org/drools/core/RuleBaseConfiguration.java index 1559cb8f0f2..c3ec4fce577 100755 --- a/drools-core/src/main/java/org/drools/core/RuleBaseConfiguration.java +++ b/drools-core/src/main/java/org/drools/core/RuleBaseConfiguration.java @@ -16,16 +16,6 @@ package org.drools.core; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - import org.drools.core.common.AgendaFactory; import org.drools.core.common.AgendaGroupFactory; import org.drools.core.common.PriorityQueueAgendaGroupFactory; @@ -52,6 +42,7 @@ import org.kie.api.runtime.rule.ConsequenceExceptionHandler; import org.kie.internal.builder.conf.ClassLoaderCacheOption; import org.kie.internal.builder.conf.RuleEngineOption; +import org.kie.internal.builder.conf.SessionCacheOption; import org.kie.internal.conf.AlphaThresholdOption; import org.kie.internal.conf.CompositeKeyDepthOption; import org.kie.internal.conf.ConsequenceExceptionHandlerOption; @@ -69,6 +60,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + /** * RuleBaseConfiguration * @@ -116,6 +117,7 @@ public class RuleBaseConfiguration private static final long serialVersionUID = 510l; public static final boolean DEFAULT_PHREAK = true; + public static final boolean DEFAULT_SESSION_CACHE = true; public static final String DEFAULT_SIGN_ON_SERIALIZATION = "false"; @@ -150,6 +152,8 @@ public class RuleBaseConfiguration private IndexPrecedenceOption indexPrecedenceOption; + private SessionCacheOption sessionCacheOption; + // if "true", rulebase builder will try to split // the rulebase into multiple partitions that can be evaluated // in parallel by using multiple internal threads @@ -206,6 +210,7 @@ public void writeExternal(ObjectOutput out) throws IOException { out.writeBoolean(phreakEnabled); out.writeBoolean(declarativeAgenda); out.writeObject(componentFactory); + out.writeObject(sessionCacheOption); } public void readExternal(ObjectInput in) throws IOException, @@ -237,6 +242,7 @@ public void readExternal(ObjectInput in) throws IOException, phreakEnabled = in.readBoolean(); declarativeAgenda = in.readBoolean(); componentFactory = (KieComponentFactory) in.readObject(); + sessionCacheOption = (SessionCacheOption) in.readObject(); } /** @@ -328,6 +334,8 @@ public void setProperty(String name, setClassLoaderCacheEnabled(StringUtils.isEmpty(value) ? true : Boolean.valueOf(value)); } else if ( name.equals( RuleEngineOption.PROPERTY_NAME ) ) { setPhreakEnabled(StringUtils.isEmpty(value) ? DEFAULT_PHREAK : value.equalsIgnoreCase(RuleEngineOption.PHREAK.toString())); + } else if ( name.equals( SessionCacheOption.PROPERTY_NAME ) ) { + setSessionCacheOption(SessionCacheOption.determineOption(StringUtils.isEmpty(value) ? "none" : value)); } } @@ -474,6 +482,9 @@ private void init(Properties properties) { setPhreakEnabled(Boolean.valueOf(this.chainedProperties.getProperty(RuleEngineOption.PROPERTY_NAME, DEFAULT_PHREAK ? RuleEngineOption.PHREAK.toString() : RuleEngineOption.RETEOO.toString()) .equalsIgnoreCase(RuleEngineOption.PHREAK.toString()))); + + setSessionCacheOption(SessionCacheOption.determineOption(this.chainedProperties.getProperty(SessionCacheOption.PROPERTY_NAME, "none"))); + setDeclarativeAgendaEnabled( Boolean.valueOf( this.chainedProperties.getProperty( DeclarativeAgendaOption.PROPERTY_NAME, "false" ) ) ); @@ -748,6 +759,15 @@ public void setPhreakEnabled(boolean enabled) { this.phreakEnabled = enabled; } + public SessionCacheOption getSessionCacheOption() { + return this.sessionCacheOption; + } + + public void setSessionCacheOption(SessionCacheOption sessionCacheOption) { + checkCanChange(); // throws an exception if a change isn't possible; + this.sessionCacheOption = sessionCacheOption; + } + public boolean isDeclarativeAgenda() { return this.declarativeAgenda; @@ -1254,6 +1274,8 @@ public void setOption(T option) { setClassLoaderCacheEnabled(((ClassLoaderCacheOption) option).isClassLoaderCacheEnabled()); } else if (option instanceof RuleEngineOption) { setPhreakEnabled(((RuleEngineOption) option).isLRUnlinkingEnabled()); + } else if (option instanceof SessionCacheOption) { + setSessionCacheOption((SessionCacheOption) option); } else if (option instanceof DeclarativeAgendaOption) { setDeclarativeAgendaEnabled(((DeclarativeAgendaOption) option).isDeclarativeAgendaEnabled()); } diff --git a/drools-core/src/main/java/org/drools/core/SessionConfiguration.java b/drools-core/src/main/java/org/drools/core/SessionConfiguration.java index ffa6b33f642..eb39be84d24 100644 --- a/drools-core/src/main/java/org/drools/core/SessionConfiguration.java +++ b/drools-core/src/main/java/org/drools/core/SessionConfiguration.java @@ -16,14 +16,6 @@ package org.drools.core; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - import org.drools.core.command.CommandService; import org.drools.core.common.ProjectClassLoader; import org.drools.core.process.instance.WorkItemManagerFactory; @@ -51,6 +43,14 @@ import org.kie.internal.runtime.conf.ForceEagerActivationOption; import org.kie.internal.utils.ChainedProperties; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + /** * SessionConfiguration * @@ -549,4 +549,30 @@ public QueryListenerOption getQueryListenerOption() { return this.queryListener; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SessionConfiguration that = (SessionConfiguration) o; + + if (keepReference != that.keepReference) return false; + if (beliefSystemType != that.beliefSystemType) return false; + if (clockType != that.clockType) return false; + if (timerJobFactoryType != that.timerJobFactoryType) return false; + + return true; + } + + @Override + public int hashCode() { + if (this == defaultInstance) { + return 0; + } + int result = (keepReference ? 1 : 0); + result = 31 * result + clockType.hashCode(); + result = 31 * result + beliefSystemType.hashCode(); + result = 31 * result + timerJobFactoryType.hashCode(); + return result; + } } diff --git a/drools-core/src/main/java/org/drools/core/base/MapGlobalResolver.java b/drools-core/src/main/java/org/drools/core/base/MapGlobalResolver.java index 000459b2f4f..7956d7d714a 100644 --- a/drools-core/src/main/java/org/drools/core/base/MapGlobalResolver.java +++ b/drools-core/src/main/java/org/drools/core/base/MapGlobalResolver.java @@ -16,6 +16,9 @@ package org.drools.core.base; +import org.drools.core.spi.GlobalResolver; +import org.kie.api.runtime.Globals; + import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; @@ -28,9 +31,6 @@ import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; -import org.drools.core.spi.GlobalResolver; -import org.kie.api.runtime.Globals; - public class MapGlobalResolver implements GlobalResolver, Globals, @@ -130,4 +130,7 @@ public String toString() { return "MapGlobalResolver [map=" + map + ", delegate=" + delegate + "]"; } + public void clear() { + map.clear(); + } } diff --git a/drools-core/src/main/java/org/drools/core/common/AbstractFactHandleFactory.java b/drools-core/src/main/java/org/drools/core/common/AbstractFactHandleFactory.java index fbfa2fc3260..3be6d5c8202 100644 --- a/drools-core/src/main/java/org/drools/core/common/AbstractFactHandleFactory.java +++ b/drools-core/src/main/java/org/drools/core/common/AbstractFactHandleFactory.java @@ -16,13 +16,13 @@ package org.drools.core.common; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - import org.drools.core.reteoo.ObjectTypeConf; import org.drools.core.spi.FactHandleFactory; import org.kie.api.runtime.rule.EntryPoint; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + public abstract class AbstractFactHandleFactory implements FactHandleFactory { @@ -118,4 +118,9 @@ public void clear(int id, long counter) { this.id = new AtomicInteger( id ); this.counter = new AtomicLong( counter ); } + + public void reset() { + id.set(0); + counter.set(0); + } } diff --git a/drools-core/src/main/java/org/drools/core/common/ConcurrentNodeMemories.java b/drools-core/src/main/java/org/drools/core/common/ConcurrentNodeMemories.java index 1aadad6e663..14bd9c8d200 100644 --- a/drools-core/src/main/java/org/drools/core/common/ConcurrentNodeMemories.java +++ b/drools-core/src/main/java/org/drools/core/common/ConcurrentNodeMemories.java @@ -17,7 +17,11 @@ package org.drools.core.common; import org.drools.core.impl.InternalKnowledgeBase; +import org.drools.core.reteoo.SegmentMemory; +import org.kie.internal.runtime.StatefulKnowledgeSession; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -47,6 +51,28 @@ public void clear() { this.memories = new AtomicReferenceArray( this.kBase.getNodeCount() ); } + public void resetAllMemories(StatefulKnowledgeSession session) { + InternalKnowledgeBase kBase = (InternalKnowledgeBase)session.getKieBase(); + Set smems = new HashSet(); + + for (int i = 0; i < memories.length(); i++) { + Memory memory = memories.get(i); + if (memory != null) { + if (memory.getSegmentMemory() != null) { + smems.add(memory.getSegmentMemory()); + } + memory.reset(); + } + } + + for (SegmentMemory smem : smems) { + smem.reset(kBase.getSegmentPrototype(smem)); + if ( smem.isSegmentLinked() ) { + smem.notifyRuleLinkSegment((InternalWorkingMemory)session); + } + } + } + /** * The implementation tries to delay locking as much as possible, by running * some potentialy unsafe opperations out of the critical session. In case it diff --git a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java index 1def269b8c7..2e7ce73dcab 100644 --- a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java +++ b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java @@ -763,7 +763,7 @@ public org.drools.core.util.LinkedList getScheduledActivati public void clear() { // reset focus stack this.focusStack.clear(); - this.focusStack.add( getMainAgendaGroup() ); + this.focusStack.add(getMainAgendaGroup()); //reset all agenda groups for ( InternalAgendaGroup group : this.agendaGroups.values() ) { @@ -782,8 +782,27 @@ public void clear() { for ( InternalActivationGroup group : this.activationGroups.values() ) { group.setTriggeredForRecency(this.workingMemory.getFactHandleFactory().getRecency()); group.reset(); + } + } + public void reset() { + // reset focus stack + this.focusStack.clear(); + this.focusStack.add( getMainAgendaGroup() ); + + //reset all agenda groups + for ( InternalAgendaGroup group : this.agendaGroups.values() ) { + group.reset(); + } + + // reset all activation groups. + for ( InternalActivationGroup group : this.activationGroups.values() ) { + group.setTriggeredForRecency(this.workingMemory.getFactHandleFactory().getRecency()); + group.reset(); } + + eager.clear(); + activationCounter = 0; } public void clearAndCancel() { diff --git a/drools-core/src/main/java/org/drools/core/common/Memory.java b/drools-core/src/main/java/org/drools/core/common/Memory.java index 2282af3382d..02d8989e8b1 100644 --- a/drools-core/src/main/java/org/drools/core/common/Memory.java +++ b/drools-core/src/main/java/org/drools/core/common/Memory.java @@ -8,10 +8,11 @@ */ public interface Memory extends LinkedListNode { - public short getNodeType(); + short getNodeType(); - public SegmentMemory getSegmentMemory(); + SegmentMemory getSegmentMemory(); - public void setSegmentMemory(SegmentMemory segmentMemory); + void setSegmentMemory(SegmentMemory segmentMemory); + void reset(); } diff --git a/drools-core/src/main/java/org/drools/core/common/NodeMemories.java b/drools-core/src/main/java/org/drools/core/common/NodeMemories.java index 00aab40cd5e..1f53c494c1f 100644 --- a/drools-core/src/main/java/org/drools/core/common/NodeMemories.java +++ b/drools-core/src/main/java/org/drools/core/common/NodeMemories.java @@ -18,6 +18,7 @@ import org.drools.core.impl.InternalKnowledgeBase; +import org.kie.internal.runtime.StatefulKnowledgeSession; /** * An interface for node memories implementation @@ -50,4 +51,5 @@ public interface NodeMemories { */ int length(); + void resetAllMemories(StatefulKnowledgeSession session); } diff --git a/drools-core/src/main/java/org/drools/core/common/PhreakWorkingMemoryFactory.java b/drools-core/src/main/java/org/drools/core/common/PhreakWorkingMemoryFactory.java index 10557a3cc6d..7548cb97b33 100644 --- a/drools-core/src/main/java/org/drools/core/common/PhreakWorkingMemoryFactory.java +++ b/drools-core/src/main/java/org/drools/core/common/PhreakWorkingMemoryFactory.java @@ -14,6 +14,10 @@ public class PhreakWorkingMemoryFactory implements WorkingMemoryFactory, Serializable { public InternalWorkingMemory createWorkingMemory(int id, InternalKnowledgeBase kBase, SessionConfiguration config, Environment environment) { + InternalWorkingMemory cachedWm = kBase.getCachedSession(config, environment); + if (cachedWm != null) { + return cachedWm; + } return new StatefulKnowledgeSessionImpl(id, kBase, true, config, environment); } diff --git a/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java b/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java index c3b5762c956..17d09b01193 100644 --- a/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java +++ b/drools-core/src/main/java/org/drools/core/impl/InternalKnowledgeBase.java @@ -1,6 +1,7 @@ package org.drools.core.impl; import org.drools.core.RuleBaseConfiguration; +import org.drools.core.SessionConfiguration; import org.drools.core.base.ClassFieldAccessorCache; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.RuleBasePartitionId; @@ -11,12 +12,14 @@ import org.drools.core.reteoo.LeftTupleSource; import org.drools.core.reteoo.Rete; import org.drools.core.reteoo.ReteooBuilder; +import org.drools.core.reteoo.SegmentMemory; import org.drools.core.rule.InvalidPatternException; import org.drools.core.rule.TypeDeclaration; import org.drools.core.spi.FactHandleFactory; import org.drools.core.spi.PropagationContext; import org.drools.core.util.TripleStore; import org.kie.api.io.Resource; +import org.kie.api.runtime.Environment; import org.kie.api.runtime.rule.FactHandle; import org.kie.internal.KnowledgeBase; @@ -76,6 +79,8 @@ void retractObject(FactHandle handle, void disposeStatefulSession(StatefulKnowledgeSessionImpl statefulSession); + StatefulKnowledgeSessionImpl getCachedSession(SessionConfiguration config, Environment environment); + TripleStore getTripleStore(); TraitRegistry getTraitRegistry(); @@ -93,6 +98,8 @@ void retractObject(FactHandle handle, InternalWorkingMemory[] getWorkingMemories(); void invalidateSegmentPrototype(LeftTupleSource tupleSource); + SegmentMemory createSegmentFromPrototype(InternalWorkingMemory wm, LeftTupleSource tupleSource); + SegmentMemory.Prototype getSegmentPrototype(SegmentMemory segment); void addRule( InternalKnowledgePackage pkg, RuleImpl rule ) throws InvalidPatternException; void removeRule( InternalKnowledgePackage pkg, RuleImpl rule ) throws InvalidPatternException; diff --git a/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java b/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java index e53e0f0b3aa..24c7622360c 100644 --- a/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java +++ b/drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java @@ -34,24 +34,6 @@ import org.drools.core.definitions.InternalKnowledgePackage; import org.drools.core.definitions.impl.KnowledgePackageImpl; import org.drools.core.definitions.rule.impl.RuleImpl; -import org.drools.core.event.knowlegebase.impl.AfterFunctionRemovedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterKiePackageAddedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterKiePackageRemovedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterKnowledgeBaseLockedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterKnowledgeBaseUnlockedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterProcessAddedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterProcessRemovedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterRuleAddedEventImpl; -import org.drools.core.event.knowlegebase.impl.AfterRuleRemovedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeFunctionRemovedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeKiePackageAddedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeKiePackageRemovedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeKnowledgeBaseLockedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeKnowledgeBaseUnlockedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeProcessAddedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeProcessRemovedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeRuleAddedEventImpl; -import org.drools.core.event.knowlegebase.impl.BeforeRuleRemovedEventImpl; import org.drools.core.factmodel.ClassDefinition; import org.drools.core.factmodel.traits.TraitRegistry; import org.drools.core.management.DroolsManagementAgent; @@ -80,7 +62,6 @@ import org.kie.api.io.Resource; import org.kie.api.marshalling.Marshaller; import org.kie.api.marshalling.ObjectMarshallingStrategy; -import org.kie.internal.KnowledgeBase; import org.kie.api.definition.KiePackage; import org.kie.internal.definition.KnowledgePackage; import org.kie.api.definition.process.Process; @@ -192,6 +173,8 @@ public class KnowledgeBaseImpl public final Set kieBaseListeners = new HashSet(); + private transient SessionsCache sessionsCache; + public KnowledgeBaseImpl() { } public KnowledgeBaseImpl(final String id, @@ -229,6 +212,13 @@ public KnowledgeBaseImpl(final String id, DroolsManagementAgent.getInstance().registerKnowledgeBase(this); } + if ( this.config.getSessionCacheOption().isEnabled() ) { + if ( this.config.isPhreakEnabled() ) { + sessionsCache = new SessionsCache(this.config.getSessionCacheOption().isAsync()); + } else { + logger.warn("Session cache can be enabled only in PHREAK mode"); + } + } } public int nextWorkingMemoryCounter() { @@ -286,7 +276,7 @@ public Collection getKnowledgePackages() { } public StatefulKnowledgeSession newStatefulKnowledgeSession() { - return newStatefulKnowledgeSession(null, EnvironmentFactory.newEnvironment() ); + return newStatefulKnowledgeSession(null, EnvironmentFactory.newEnvironment()); } public StatefulKnowledgeSession newStatefulKnowledgeSession(KieSessionConfiguration conf, Environment environment) { @@ -621,12 +611,19 @@ public void disposeStatefulSession(StatefulKnowledgeSessionImpl statefulSession) statefulSessionLock.lock(); try { + if (sessionsCache != null) { + sessionsCache.store(statefulSession); + } this.statefulSessions.remove(statefulSession); } finally { statefulSessionLock.unlock(); } } + public StatefulKnowledgeSessionImpl getCachedSession(SessionConfiguration config, Environment environment) { + return sessionsCache != null ? sessionsCache.getCachedSession(config) : null; + } + public FactHandleFactory getFactHandleFactory() { return this.factHandleFactory; } @@ -1210,9 +1207,9 @@ public void assertObject(final FactHandle handle, public void retractObject(final FactHandle handle, final PropagationContext context, final StatefulKnowledgeSessionImpl workingMemory) { - getRete().retractObject( (InternalFactHandle) handle, - context, - workingMemory ); + getRete().retractObject((InternalFactHandle) handle, + context, + workingMemory); } public StatefulKnowledgeSessionImpl newStatefulSession(boolean keepReference) { @@ -1326,7 +1323,7 @@ public void addPackages(InternalKnowledgePackage[] pkgs) { } public void addPackage(final InternalKnowledgePackage newPkg) { - addPackages( Collections.singleton( newPkg ) ); + addPackages( Collections.singleton(newPkg) ); } public void registerSegmentPrototype(LeftTupleSource tupleSource, SegmentMemory smem) { @@ -1343,7 +1340,7 @@ public void invalidateSegmentPrototype(LeftTupleSource tupleSource) { } } - public SegmentMemory getSegmentFromPrototype(InternalWorkingMemory wm, LeftTupleSource tupleSource) { + public SegmentMemory createSegmentFromPrototype(InternalWorkingMemory wm, LeftTupleSource tupleSource) { SegmentMemory.Prototype proto = segmentProtos.get(tupleSource.getId()); if (proto == null) { return null; @@ -1351,6 +1348,10 @@ public SegmentMemory getSegmentFromPrototype(InternalWorkingMemory wm, LeftTuple return proto.newSegmentMemory(wm); } + public SegmentMemory.Prototype getSegmentPrototype(SegmentMemory segment) { + return segmentProtos.get(segment.getRootNode().getId()); + } + private static class TypeDeclarationCandidate { public TypeDeclaration candidate = null; diff --git a/drools-core/src/main/java/org/drools/core/impl/SessionsCache.java b/drools-core/src/main/java/org/drools/core/impl/SessionsCache.java new file mode 100644 index 00000000000..c7567a41966 --- /dev/null +++ b/drools-core/src/main/java/org/drools/core/impl/SessionsCache.java @@ -0,0 +1,87 @@ +package org.drools.core.impl; + +import org.drools.core.SessionConfiguration; +import org.kie.internal.concurrent.ExecutorProviderFactory; + +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Executor; + +public class SessionsCache { + + private final Map> cleanSessions = new ConcurrentHashMap>(); + private final boolean isAsync; + + SessionsCache(boolean isAsync) { + this.isAsync = isAsync; + } + + public void store(StatefulKnowledgeSessionImpl session) { + if (isAsync) { + SessionResetterHolder.SESSION_RESETTER.enqueue(this, session); + } else { + session.reset(); + storeResettedSession(session); + } + } + + private void storeResettedSession(StatefulKnowledgeSessionImpl session) { + Queue cache = cleanSessions.get(session.getSessionConfiguration()); + if (cache == null) { + cache = new ConcurrentLinkedQueue(); + cleanSessions.put(session.getSessionConfiguration(), cache); + } + cache.offer(session); + } + + public StatefulKnowledgeSessionImpl getCachedSession(SessionConfiguration config) { + Queue cache = cleanSessions.get(config); + return cache != null ? cache.poll() : null; + } + + private static class SessionResetterHolder { + private static final SessionResetter SESSION_RESETTER = new SessionResetter(); + } + + private static class SessionResetter { + private final Executor executor = ExecutorProviderFactory.getExecutorProvider().newSingleThreadExecutor(); + + private final BlockingQueue dirtySessions = new ArrayBlockingQueue(20); + + private SessionResetter() { + executor.execute(new Runnable() { + @Override + public void run() { + while (true) { + try { + dirtySessions.take().doReset(); + } catch (InterruptedException e) { } + } + } + }); + } + + private void enqueue(SessionsCache sessionsCache, StatefulKnowledgeSessionImpl session) { + dirtySessions.offer(new SessionSlot(sessionsCache, session)); + } + } + + private static class SessionSlot { + private final SessionsCache sessionsCache; + private final StatefulKnowledgeSessionImpl session; + + private SessionSlot(SessionsCache sessionsCache, StatefulKnowledgeSessionImpl session) { + this.sessionsCache = sessionsCache; + this.session = session; + } + + private void doReset() { + session.reset(); + sessionsCache.storeResettedSession(session); + } + } +} diff --git a/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java b/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java index 08c51163c82..aa43495f84f 100644 --- a/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java +++ b/drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java @@ -33,6 +33,7 @@ import org.drools.core.command.runtime.BatchExecutionCommandImpl; import org.drools.core.common.BaseNode; import org.drools.core.common.ConcurrentNodeMemories; +import org.drools.core.common.DefaultAgenda; import org.drools.core.common.DefaultFactHandle; import org.drools.core.common.EndOperationListener; import org.drools.core.common.EventFactHandle; @@ -436,11 +437,7 @@ public void dispose() { logger.close(); } catch (Exception e) { /* the logger was already closed, swallow */ } } - this.kBase.disposeStatefulSession( this ); - if (this.kBase.getConfiguration().isMBeansEnabled()) { - DroolsManagementAgent.getInstance().unregisterKnowledgeSession(this); - } for (WorkingMemoryEntryPoint ep : this.entryPoints.values()) { ep.dispose(); } @@ -455,7 +452,13 @@ public void dispose() { if (timerService != null) { this.timerService.shutdown(); } + alive = false; + + this.kBase.disposeStatefulSession( this ); + if (this.kBase.getConfiguration().isMBeansEnabled()) { + DroolsManagementAgent.getInstance().unregisterKnowledgeSession(this); + } } public boolean isAlive() { @@ -938,6 +941,12 @@ public void setGlobal(String identifier, value ); } + @Override + public void clear() { + if (globals instanceof GlobalResolver) { + ((GlobalResolver)globals).clear(); + } + } } // ------------------------------------------------------------ @@ -981,7 +990,35 @@ public SessionConfiguration getSessionConfiguration() { } public void reset() { - throw new UnsupportedOperationException( "This should not be called" ); + if (actionQueue != null) { + actionQueue.clear(); + } + + if (nodeMemories != null) { + nodeMemories.resetAllMemories(this); + } + + ((DefaultAgenda)this.agenda).reset(); + + this.globalResolver.clear(); + this.kieBaseEventListeners.clear(); + this.handleFactory.clear( 0, 0 ); + this.propagationIdCounter.set( 0 ); + this.opCounter.set( 0 ); + this.lastIdleTimestamp.set( -1 ); + + initTransient(); + + timerService = TimerServiceFactory.getTimerService(this.config); + ((AcceptsTimerJobFactoryManager) timerService).setTimerJobFactoryManager( config.getTimerJobFactoryManager() ); + + if (this.processRuntime != null) { + this.processRuntime = createProcessRuntime(); + } + + initInitialFact(kBase, null); + + alive = true; } public void reset(int handleId, @@ -2106,5 +2143,4 @@ public ObjectMarshallingStrategyStore getObjectMarshallingStrategyStore() { } return this.marshallingStore; } - } diff --git a/drools-core/src/main/java/org/drools/core/impl/StatelessKnowledgeSessionImpl.java b/drools-core/src/main/java/org/drools/core/impl/StatelessKnowledgeSessionImpl.java index 04458993c2a..29224104c7a 100644 --- a/drools-core/src/main/java/org/drools/core/impl/StatelessKnowledgeSessionImpl.java +++ b/drools-core/src/main/java/org/drools/core/impl/StatelessKnowledgeSessionImpl.java @@ -63,7 +63,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -132,7 +131,7 @@ public StatefulKnowledgeSession newWorkingMemory() { this.kBase.readLock(); try { ksession = (StatefulKnowledgeSession) wmFactory.createWorkingMemory(this.kBase.nextWorkingMemoryCounter(), this.kBase, - (SessionConfiguration) this.conf, this.environment); + (SessionConfiguration) this.conf, this.environment); StatefulKnowledgeSessionImpl ksessionImpl = (StatefulKnowledgeSessionImpl) ksession; diff --git a/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java b/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java index e4d1b0a3482..efeafc78eb5 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java +++ b/drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java @@ -197,7 +197,7 @@ public static SegmentMemory createSegmentMemory(LeftTupleSource tupleSource, } private static SegmentMemory restoreSegmentFromPrototype(InternalWorkingMemory wm, LeftTupleSource segmentRoot, int nodeTypesInSegment) { - SegmentMemory smem = ((KnowledgeBaseImpl)wm.getKnowledgeBase()).getSegmentFromPrototype(wm, segmentRoot); + SegmentMemory smem = wm.getKnowledgeBase().createSegmentFromPrototype(wm, segmentRoot); if ( smem != null ) { // there is a prototype for this segment memory for (NetworkNode node : smem.getNodesInSegment()) { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/AccumulateNode.java b/drools-core/src/main/java/org/drools/core/reteoo/AccumulateNode.java index 650b7566412..bbc807b3aea 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/AccumulateNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/AccumulateNode.java @@ -16,33 +16,32 @@ package org.drools.core.reteoo; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.Serializable; -import java.util.Arrays; -import java.util.Map; - import org.drools.core.RuleBaseConfiguration; import org.drools.core.common.BetaConstraints; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.Memory; import org.drools.core.common.WorkingMemoryAction; -import org.drools.core.marshalling.impl.ProtobufInputMarshaller.TupleKey; -import org.drools.core.marshalling.impl.ProtobufMessages.FactHandle; -import org.drools.core.util.AbstractBaseLinkedListNode; import org.drools.core.marshalling.impl.PersisterHelper; import org.drools.core.marshalling.impl.ProtobufInputMarshaller; +import org.drools.core.marshalling.impl.ProtobufInputMarshaller.TupleKey; import org.drools.core.marshalling.impl.ProtobufMessages; +import org.drools.core.marshalling.impl.ProtobufMessages.FactHandle; import org.drools.core.reteoo.builder.BuildContext; import org.drools.core.rule.Accumulate; import org.drools.core.rule.ContextEntry; +import org.drools.core.spi.Accumulator; import org.drools.core.spi.AlphaNodeFieldConstraint; import org.drools.core.spi.PropagationContext; +import org.drools.core.util.AbstractBaseLinkedListNode; -import static org.drools.core.util.BitMaskUtil.intersect; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Map; /** * AccumulateNode @@ -192,6 +191,7 @@ public Memory createMemory(final RuleBaseConfiguration config, InternalWorkingMe AccumulateMemory memory = new AccumulateMemory(); memory.betaMemory = this.constraints.createBetaMemory( config, NodeTypeEnums.AccumulateNode ); + memory.accumulators = this.accumulate.getAccumulators(); memory.workingMemoryContext = this.accumulate.createWorkingMemoryContext(); memory.resultsContext = this.resultBinder.createContext(); memory.alphaContexts = new ContextEntry[this.resultConstraints.length]; @@ -209,6 +209,7 @@ public static class AccumulateMemory extends AbstractBaseLinkedListNode implements Memory { + private Accumulator[] accumulators; public Object[] workingMemoryContext; public BetaMemory betaMemory; public ContextEntry[] resultsContext; @@ -230,6 +231,13 @@ public void setSegmentMemory(SegmentMemory segmentMemory) { betaMemory.setSegmentMemory(segmentMemory); } + public void reset() { + betaMemory.reset(); + workingMemoryContext = new Object[ this.accumulators.length ]; + for( int i = 0; i < this.accumulators.length; i++ ) { + workingMemoryContext[i] = this.accumulators[i].createWorkingMemoryContext(); + } + } } public static class AccumulateContext diff --git a/drools-core/src/main/java/org/drools/core/reteoo/AlphaNode.java b/drools-core/src/main/java/org/drools/core/reteoo/AlphaNode.java index 2b43f326be0..7ac869277bc 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/AlphaNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/AlphaNode.java @@ -15,12 +15,6 @@ */ package org.drools.core.reteoo; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.List; -import java.util.Map; - import org.drools.core.RuleBaseConfiguration; import org.drools.core.base.evaluators.IsAEvaluatorDefinition; import org.drools.core.common.InternalFactHandle; @@ -38,6 +32,12 @@ import org.kie.api.definition.rule.Rule; import org.kie.api.runtime.rule.Operator; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.List; +import java.util.Map; + import static org.drools.core.util.BitMaskUtil.intersect; /** @@ -271,7 +271,7 @@ public short getNodeType() { } public SegmentMemory getSegmentMemory() { - throw new UnsupportedOperationException(); + return null; } public void setSegmentMemory(SegmentMemory segmentMemory) { @@ -298,6 +298,7 @@ public void nullPrevNext() { throw new UnsupportedOperationException(); } + public void reset() { } } /** diff --git a/drools-core/src/main/java/org/drools/core/reteoo/BetaMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/BetaMemory.java index 4778d50df8a..a1381fa159f 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/BetaMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/BetaMemory.java @@ -20,15 +20,9 @@ import org.drools.core.common.Memory; import org.drools.core.common.RightTupleSets; import org.drools.core.common.SynchronizedRightTupleSets; -import org.drools.core.phreak.TupleEntry; import org.drools.core.rule.ContextEntry; import org.drools.core.util.AbstractBaseLinkedListNode; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Queue; -import java.util.concurrent.atomic.AtomicBoolean; - public class BetaMemory extends AbstractBaseLinkedListNode implements Memory { @@ -145,4 +139,15 @@ public void setNodeDirtyWithoutNotify() { public void setNodeCleanWithoutNotify() { segmentMemory.updateCleanNodeMask( nodePosMaskBit ); } + + public void reset() { + if (leftTupleMemory != null) { + leftTupleMemory.clear(); + } + if (rightTupleMemory != null) { + rightTupleMemory.clear(); + } + stagedRightTuples.resetAll(); + counter = 0; + } } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/ConditionalBranchNode.java b/drools-core/src/main/java/org/drools/core/reteoo/ConditionalBranchNode.java index 820b5910977..9eb22e6e067 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/ConditionalBranchNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/ConditionalBranchNode.java @@ -238,6 +238,8 @@ public void setSegmentMemory(SegmentMemory segmentMemory) { public SegmentMemory getSegmentMemory() { return segmentMemory; } + + public void reset() { } } protected ObjectTypeNode getObjectTypeNode() { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/EvalConditionNode.java b/drools-core/src/main/java/org/drools/core/reteoo/EvalConditionNode.java index 96018bfa149..43ddf87bbc3 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/EvalConditionNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/EvalConditionNode.java @@ -276,6 +276,8 @@ public void setSegmentMemory(SegmentMemory smem) { public SegmentMemory getSegmentMemory() { return this.memory; } + + public void reset() { } } protected ObjectTypeNode getObjectTypeNode() { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/FromNode.java b/drools-core/src/main/java/org/drools/core/reteoo/FromNode.java index b3d277497bf..c4f251fc2f5 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/FromNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/FromNode.java @@ -207,7 +207,7 @@ public Memory createMemory(final RuleBaseConfiguration config, InternalWorkingMe this.betaConstraints.createContext(), NodeTypeEnums.FromNode ); return new FromMemory( beta, - this.dataProvider.createContext(), + this.dataProvider, this.alphaConstraints ); } @@ -274,15 +274,18 @@ public static class FromMemory extends AbstractBaseLinkedListNode Memory { private static final long serialVersionUID = 510l; + private DataProvider dataProvider; + public BetaMemory betaMemory; public Object providerContext; public ContextEntry[] alphaContexts; public FromMemory(BetaMemory betaMemory, - Object providerContext, + DataProvider dataProvider, AlphaNodeFieldConstraint[] constraints) { this.betaMemory = betaMemory; - this.providerContext = providerContext; + this.dataProvider = dataProvider; + this.providerContext = dataProvider.createContext(); this.alphaContexts = new ContextEntry[constraints.length]; for ( int i = 0; i < constraints.length; i++ ) { this.alphaContexts[i] = constraints[i].createContextEntry(); @@ -308,7 +311,11 @@ public BetaMemory getBetaMemory() { public void setBetaMemory(BetaMemory betaMemory) { this.betaMemory = betaMemory; } - + + public void reset() { + this.betaMemory.reset(); + this.providerContext = dataProvider.createContext(); + } } public LeftTuple createLeftTuple(InternalFactHandle factHandle, diff --git a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java index d0179eb8597..d807331c93a 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java @@ -645,6 +645,10 @@ public short getNodeType() { public void setNodeDirty(InternalWorkingMemory wm) { segmentMemory.notifyRuleLinkSegment(wm, nodePosMaskBit); } + + public void reset() { + counter = 0; + } } /** diff --git a/drools-core/src/main/java/org/drools/core/reteoo/LeftTupleMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/LeftTupleMemory.java index 9864fd8981a..6fe1dc75999 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/LeftTupleMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/LeftTupleMemory.java @@ -21,37 +21,38 @@ import org.drools.core.util.Iterator; public interface LeftTupleMemory { - public Iterator iterator(); + Iterator iterator(); - public LeftTuple getFirst(RightTuple rightTuple); + LeftTuple getFirst(RightTuple rightTuple); - public void removeAdd(LeftTuple tuple); + void removeAdd(LeftTuple tuple); - public void add(LeftTuple tuple); + void add(LeftTuple tuple); - public void remove(LeftTuple leftTuple); + void remove(LeftTuple leftTuple); - public boolean contains(LeftTuple leftTuple); + boolean contains(LeftTuple leftTuple); - public boolean isIndexed(); + boolean isIndexed(); - public int size(); + int size(); - public Entry[] toArray(); + Entry[] toArray(); - public FastIterator fastIterator(); + FastIterator fastIterator(); /** * Iterates the entire data structure, regardless of whether TupleMemory is hashed or not. * @return */ - public FastIterator fullFastIterator(); + FastIterator fullFastIterator(); /** * Iterator that resumes from the current RightTuple, regardless of whether the TupleMemory is hashed or not * @param rightTuple * @return */ - public FastIterator fullFastIterator(LeftTuple leftTuple); + FastIterator fullFastIterator(LeftTuple leftTuple); + void clear(); } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/ObjectTypeNode.java b/drools-core/src/main/java/org/drools/core/reteoo/ObjectTypeNode.java index c674863bc2b..c0e5b9331c6 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/ObjectTypeNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/ObjectTypeNode.java @@ -754,7 +754,7 @@ public ObjectHashSet getObjectHashSet() { } public SegmentMemory getSegmentMemory() { - throw new UnsupportedOperationException(); + return null; } public void setSegmentMemory(SegmentMemory segmentMemory) { @@ -781,6 +781,10 @@ public Memory getNext() { throw new UnsupportedOperationException(); } + public void reset() { + memory.clear(); + } + public String toString() { return "ObjectTypeMemory " + otn; } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java index 0c88677e669..698696e3e6f 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java @@ -195,4 +195,10 @@ public String toString() { return "[RuleMem " + getRule().getName() + "]"; } + public void reset() { + if (this.queue != null) { + this.queue = new StreamTupleEntryQueue(); + } + this.linkedSegmentMask.set(0); + } } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/PropagationQueuingNode.java b/drools-core/src/main/java/org/drools/core/reteoo/PropagationQueuingNode.java index bc3b6c96210..41750499bee 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/PropagationQueuingNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/PropagationQueuingNode.java @@ -374,7 +374,7 @@ public Memory getNext() { } public SegmentMemory getSegmentMemory() { - throw new UnsupportedOperationException(); + return null; } public void setSegmentMemory(SegmentMemory segmentMemory) { @@ -384,6 +384,11 @@ public void setSegmentMemory(SegmentMemory segmentMemory) { public void nullPrevNext() { throw new UnsupportedOperationException(); } + + public void reset() { + queue.clear(); + isQueued.set(false); + } } private static abstract class Action diff --git a/drools-core/src/main/java/org/drools/core/reteoo/QueryElementNode.java b/drools-core/src/main/java/org/drools/core/reteoo/QueryElementNode.java index a4d921f2d22..b0fe2d1100c 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/QueryElementNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/QueryElementNode.java @@ -670,6 +670,10 @@ public void setNodeDirtyWithoutNotify() { public void setNodeCleanWithoutNotify() { smem.updateCleanNodeMask( nodePosMaskBit ); } + + public void reset() { + resultLeftTuples.resetAll(); + } } protected ObjectTypeNode getObjectTypeNode() { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/RightInputAdapterNode.java b/drools-core/src/main/java/org/drools/core/reteoo/RightInputAdapterNode.java index 3a8a4cdfb12..6ec8d4b3210 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/RightInputAdapterNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/RightInputAdapterNode.java @@ -16,11 +16,6 @@ package org.drools.core.reteoo; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.List; -import java.util.Map; import org.drools.core.RuleBaseConfiguration; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; @@ -28,13 +23,18 @@ import org.drools.core.common.MemoryFactory; import org.drools.core.common.PropagationContextFactory; import org.drools.core.common.UpdateContext; -import org.drools.core.util.AbstractBaseLinkedListNode; -import org.drools.core.util.ObjectHashMap; import org.drools.core.marshalling.impl.PersisterHelper; import org.drools.core.marshalling.impl.ProtobufInputMarshaller; import org.drools.core.marshalling.impl.ProtobufMessages; import org.drools.core.reteoo.builder.BuildContext; import org.drools.core.spi.PropagationContext; +import org.drools.core.util.AbstractBaseLinkedListNode; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.List; +import java.util.Map; /** * When joining a subnetwork into the main network again, RightInputAdapterNode adapts the @@ -341,6 +341,9 @@ public short getNodeType() { return NodeTypeEnums.RightInputAdaterNode; } + public void reset() { + pathMemory.reset(); + } } public long getLeftInferredMask() { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/RightTupleMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/RightTupleMemory.java index 58913fc6081..c126c1a5dbf 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/RightTupleMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/RightTupleMemory.java @@ -75,4 +75,6 @@ public boolean isComparison() { int size(); IndexType getIndexType(); + + void clear(); } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java b/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java index 0b6bc049f1d..6a1298439f7 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java @@ -326,6 +326,15 @@ public List getNodesInSegment() { return nodes; } + public void reset(Prototype prototype) { + this.dirtyNodeMask.set(0); + this.linkedNodeMask.set( prototype != null ? prototype.linkedNodeMask : 0 ); + if (queue != null) { + queue.takeAllForFlushing(); + } + stagedLeftTuples.resetAll(); + } + public static class Prototype { private NetworkNode rootNode; private NetworkNode tipNode; diff --git a/drools-core/src/main/java/org/drools/core/reteoo/TimerNode.java b/drools-core/src/main/java/org/drools/core/reteoo/TimerNode.java index e3e69ee8ede..a615de0561f 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/TimerNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/TimerNode.java @@ -320,6 +320,11 @@ public void setNodeDirtyWithoutNotify() { public void setNodeCleanWithoutNotify() { memory.updateCleanNodeMask( nodePosMaskBit ); } + + public void reset() { + insertOrUpdateLeftTuples.clear(); + deleteLeftTuples.clear(); + } } @Override diff --git a/drools-core/src/main/java/org/drools/core/reteoo/WindowNode.java b/drools-core/src/main/java/org/drools/core/reteoo/WindowNode.java index 9999e2de55d..2c9e63f296c 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/WindowNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/WindowNode.java @@ -425,7 +425,7 @@ public short getNodeType() { } public SegmentMemory getSegmentMemory() { - throw new UnsupportedOperationException(); + return null; } public void setSegmentMemory(SegmentMemory segmentMemory) { @@ -451,5 +451,7 @@ public void setNext(Memory next) { public void nullPrevNext() { throw new UnsupportedOperationException(); } + + public void reset() { } } } diff --git a/drools-core/src/main/java/org/drools/core/spi/GlobalResolver.java b/drools-core/src/main/java/org/drools/core/spi/GlobalResolver.java index e95ee326c8f..4cbf8308b8f 100644 --- a/drools-core/src/main/java/org/drools/core/spi/GlobalResolver.java +++ b/drools-core/src/main/java/org/drools/core/spi/GlobalResolver.java @@ -16,11 +16,10 @@ package org.drools.core.spi; -import java.io.Externalizable; - public interface GlobalResolver { - public Object resolveGlobal(String identifier); + Object resolveGlobal(String identifier); + + void setGlobal(String identifier, Object value); - public void setGlobal(String identifier, - Object value); + void clear(); } diff --git a/drools-core/src/main/java/org/drools/core/util/AbstractHashTable.java b/drools-core/src/main/java/org/drools/core/util/AbstractHashTable.java index 9e78a4adf67..05859c0c79c 100644 --- a/drools-core/src/main/java/org/drools/core/util/AbstractHashTable.java +++ b/drools-core/src/main/java/org/drools/core/util/AbstractHashTable.java @@ -16,17 +16,17 @@ package org.drools.core.util; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; - -import org.drools.core.util.index.LeftTupleIndexHashTable; import org.drools.core.reteoo.LeftTuple; import org.drools.core.rule.Declaration; import org.drools.core.rule.IndexEvaluator; import org.drools.core.spi.InternalReadAccessor; import org.drools.core.spi.ReadAccessor; +import org.drools.core.util.index.LeftTupleIndexHashTable; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; public abstract class AbstractHashTable implements @@ -779,4 +779,12 @@ public boolean equal(final Object object1, } } + + public void clear() { + this.table = new Entry[Math.min( this.table.length, + 16 )]; + this.threshold = (int) (this.table.length * this.loadFactor); + this.size = 0; + this.iterator = null; + } } diff --git a/drools-core/src/main/java/org/drools/core/util/ObjectHashMap.java b/drools-core/src/main/java/org/drools/core/util/ObjectHashMap.java index 8666c82c465..746121d4e0c 100644 --- a/drools-core/src/main/java/org/drools/core/util/ObjectHashMap.java +++ b/drools-core/src/main/java/org/drools/core/util/ObjectHashMap.java @@ -52,13 +52,6 @@ public Object put(final Object key, true ); } - public void clear() { - this.table = new Entry[Math.min( this.table.length, - 16 )]; - this.threshold = (int) (this.table.length * this.loadFactor); - size = 0; - } - public Object put(final Object key, final Object value, final boolean checkExists) { diff --git a/drools-core/src/main/java/org/drools/core/util/ObjectHashSet.java b/drools-core/src/main/java/org/drools/core/util/ObjectHashSet.java index 8e20a5d11d1..6d726d55088 100644 --- a/drools-core/src/main/java/org/drools/core/util/ObjectHashSet.java +++ b/drools-core/src/main/java/org/drools/core/util/ObjectHashSet.java @@ -54,12 +54,6 @@ public boolean add(final Object value) { true ); } - public void clear() { - this.table = new Entry[Math.min( this.table.length, - 16 )]; - this.threshold = (int) (this.table.length * this.loadFactor); - } - public boolean add(final Object value, final boolean checkExists) { final int hashCode = this.comparator.hashCodeOf( value ); diff --git a/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexHashTable.java b/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexHashTable.java index d6a4d8801e6..4627d2d534b 100644 --- a/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexHashTable.java +++ b/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexHashTable.java @@ -16,18 +16,18 @@ package org.drools.core.util.index; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; - +import org.drools.core.reteoo.LeftTuple; +import org.drools.core.reteoo.LeftTupleMemory; +import org.drools.core.reteoo.RightTuple; import org.drools.core.util.AbstractHashTable; import org.drools.core.util.Entry; import org.drools.core.util.FastIterator; import org.drools.core.util.Iterator; import org.drools.core.util.LinkedList; -import org.drools.core.reteoo.LeftTuple; -import org.drools.core.reteoo.LeftTupleMemory; -import org.drools.core.reteoo.RightTuple; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; public class LeftTupleIndexHashTable extends AbstractHashTable implements @@ -444,9 +444,6 @@ public LeftTupleList get(final RightTuple rightTuple) { /** * We use this method to aviod to table lookups for the same hashcode; which is what we would have to do if we did * a get and then a create if the value is null. - * - * @param value - * @return */ private LeftTupleList getOrCreate(final LeftTuple tuple) { final int hashCode = this.index.hashCodeOf( tuple ); @@ -508,4 +505,11 @@ public String toString() { return builder.toString(); } + public void clear() { + super.clear(); + this.startResult = PRIME; + this.factSize = 0; + this.fullFastIterator = null; + this.tupleValueFullIterator = null; + } } diff --git a/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRBTree.java b/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRBTree.java index a11c15a560e..d0f6948db29 100644 --- a/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRBTree.java +++ b/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRBTree.java @@ -179,5 +179,9 @@ public Entry next(Entry object) { public boolean isFullIterator() { return false; } - } + } + + public void clear() { + tree = new LeftTupleRBTree>(); + } } diff --git a/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRangeRBTree.java b/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRangeRBTree.java index 40c6d0bbaef..e9adc879397 100644 --- a/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRangeRBTree.java +++ b/drools-core/src/main/java/org/drools/core/util/index/LeftTupleIndexRangeRBTree.java @@ -293,5 +293,9 @@ public Entry next(Entry object) { public boolean isFullIterator() { return false; } - } + } + + public void clear() { + tree = new RBTree, RBTree, LeftTupleList>>(); + } } diff --git a/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexHashTable.java b/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexHashTable.java index c1c6d6f5cbd..e2f6ffad702 100644 --- a/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexHashTable.java +++ b/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexHashTable.java @@ -515,4 +515,12 @@ public String toString() { public IndexType getIndexType() { return IndexType.EQUAL; } + + public void clear() { + super.clear(); + this.startResult = PRIME; + this.factSize = 0; + this.fullFastIterator = null; + this.tupleValueFullIterator = null; + } } diff --git a/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRBTree.java b/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRBTree.java index a6938401e04..aaa61ba31a0 100644 --- a/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRBTree.java +++ b/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRBTree.java @@ -185,5 +185,9 @@ public Entry next(Entry object) { public boolean isFullIterator() { return false; } - } + } + + public void clear() { + tree = new RightTupleRBTree>(); + } } diff --git a/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRangeRBTree.java b/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRangeRBTree.java index 57c2d095376..b2da77d3a7d 100644 --- a/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRangeRBTree.java +++ b/drools-core/src/main/java/org/drools/core/util/index/RightTupleIndexRangeRBTree.java @@ -1,16 +1,15 @@ package org.drools.core.util.index; import org.drools.core.common.InternalFactHandle; +import org.drools.core.reteoo.LeftTuple; +import org.drools.core.reteoo.RightTuple; +import org.drools.core.reteoo.RightTupleMemory; +import org.drools.core.util.AbstractHashTable.FieldIndex; import org.drools.core.util.Entry; import org.drools.core.util.FastIterator; import org.drools.core.util.Iterator; import org.drools.core.util.RBTree; -import org.drools.core.reteoo.LeftTuple; -import org.drools.core.reteoo.RightTuple; -import org.drools.core.reteoo.RightTupleMemory; - import org.drools.core.util.index.IndexUtil.ConstraintType; -import org.drools.core.util.AbstractHashTable.FieldIndex; import java.io.Externalizable; import java.io.IOException; @@ -234,5 +233,9 @@ public Entry next(Entry object) { public boolean isFullIterator() { return false; } - } + } + + public void clear() { + tree = new RBTree, RightTupleList>(); + } } From 49a1b948686c6f84e06c3461543d4438df1c16b9 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 7 Jul 2014 11:12:46 +0200 Subject: [PATCH 32/76] [DROOLS-543] try to compile all type declarations even if there was a former compilation problem (cherry picked from commit 0a7991be1b038cd06e0506842e6e66b1a9db807e) --- .../builder/impl/TypeDeclarationBuilder.java | 17 +++++------- .../compiler/integrationtests/Misc2Test.java | 26 +++++++++++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java index d524f6bdcbb..3dcf46a0cbc 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java @@ -37,7 +37,6 @@ import org.drools.core.factmodel.traits.TraitFactory; import org.drools.core.factmodel.traits.Traitable; import org.drools.core.factmodel.traits.TraitableBean; -import org.drools.core.rule.Collect; import org.drools.core.rule.JavaDialectRuntimeData; import org.drools.core.rule.MVELDialectRuntimeData; import org.drools.core.rule.TypeDeclaration; @@ -1215,19 +1214,15 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, } try { - // the type declaration is generated in any case (to be used by subclasses, if any) // the actual class will be generated only if needed - if (!kbuilder.hasErrors()) { - generateDeclaredBean(typeDescr, - type, - pkgRegistry, - unresolvedTypes); - - Class clazz = pkgRegistry.getTypeResolver().resolveType(typeDescr.getType().getFullName()); - type.setTypeClass(clazz); - } + generateDeclaredBean(typeDescr, + type, + pkgRegistry, + unresolvedTypes); + Class clazz = pkgRegistry.getTypeResolver().resolveType(typeDescr.getType().getFullName()); + type.setTypeClass(clazz); } catch (final ClassNotFoundException e) { kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Class '" + className + diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index 86428849561..73dc75130aa 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -6242,4 +6242,30 @@ public void testMethodResolution() throws Exception { ksession.insert(new Z()); ksession.fireAllRules(); } + + @Test + public void testCorrectErrorMessageOnDeclaredTypeCompilation() throws Exception { + // DROOLS-543 + String str = "rule R\n" + + "salience 10\n" + + "when\n" + + " String()\n" + + "then\n" + + "System.out.println(\"Hi\");\n" + + "end\n" + + "declare A\n" + + " a : SomeNonexistenClass @key\n" + + " b : int @key\n" + + "end\n" + + "\n" + + "declare C\n" + + " d : int @key\n" + + " e : int[]\n" + + "end\n"; + + KieServices ks = KieServices.Factory.get(); + KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); + Results results = ks.newKieBuilder( kfs ).buildAll().getResults(); + assertEquals(1, results.getMessages().size()); + } } \ No newline at end of file From cdeba03bf37825877967fe730c2dd77b22ff287a Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 7 Jul 2014 12:53:48 +0200 Subject: [PATCH 33/76] [DROOLS-536] KieBuilder does not resolve declarations across packages (cherry picked from commit 869b669cd32b8eb6c1c5497d3f2eedd8abed2011) --- .../impl/CompositeKnowledgeBuilderImpl.java | 14 ++++----- .../builder/impl/TypeDeclarationBuilder.java | 29 +++++++------------ 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java index 3dfeb66203a..3678c73e822 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java @@ -8,7 +8,6 @@ import org.drools.compiler.lang.descr.PackageDescr; import org.drools.compiler.lang.descr.TypeDeclarationDescr; import org.drools.core.builder.conf.impl.JaxbConfigurationImpl; -import org.drools.core.rule.TypeDeclaration; import org.kie.api.io.Resource; import org.kie.api.io.ResourceConfiguration; import org.kie.api.io.ResourceType; @@ -19,7 +18,6 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -295,14 +293,14 @@ private void buildTypeDeclarations(Collection packages) { } } - Map unprocesseableDescrs = new HashMap(); + Map unprocesseableDescrs = new HashMap(); List unresolvedTypes = new ArrayList(); for (CompositePackageDescr packageDescr : packages) { buildTypeDeclarations(packageDescr, unresolvedTypes, unprocesseableDescrs); } if ( ! unprocesseableDescrs.isEmpty() ) { - List sortedDescrs = new ArrayList( unprocesseableDescrs.values() ); + Collection sortedDescrs = TypeDeclarationBuilder.sortByHierarchy( kBuilder, unprocesseableDescrs.values() ); for ( AbstractClassTypeDeclarationDescr descr : sortedDescrs ) { unprocesseableDescrs.remove( descr.getType().getFullName() ); PackageRegistry pkg = kBuilder.getPackageRegistry().get( descr.getType().getNamespace() ); @@ -321,11 +319,9 @@ private void buildTypeDeclarations(Collection packages) { // now we need to sort TypeDeclarations based on the mutual, cross-package dependencies. // This can't be done at the beginning, before the build pass, since the names are not yet fully qualified there. // TODO there may be more efficient ways to do it (?) - Collection sorted = kBuilder.getTypeBuilder().sortByHierarchy( allDescrs ); int j = 0; - for ( AbstractClassTypeDeclarationDescr descr : sorted ) { - TypeDeclaration decl = kBuilder.getPackageRegistry( descr.getNamespace() ).getPackage().getTypeDeclaration( descr.getTypeName() ); - decl.setOrder( j++ ); + for ( AbstractClassTypeDeclarationDescr descr : TypeDeclarationBuilder.sortByHierarchy( kBuilder, allDescrs ) ) { + kBuilder.getPackageRegistry( descr.getNamespace() ).getPackage().getTypeDeclaration( descr.getTypeName() ).setOrder( j++ ); } for (CompositePackageDescr packageDescr : packages) { @@ -335,7 +331,7 @@ private void buildTypeDeclarations(Collection packages) { } } - private List buildTypeDeclarations(CompositePackageDescr packageDescr, List unresolvedTypes, Map unprocessableDescrs) { + private List buildTypeDeclarations(CompositePackageDescr packageDescr, List unresolvedTypes, Map unprocessableDescrs) { kBuilder.setAssetFilter(packageDescr.getFilter()); PackageRegistry pkgRegistry = kBuilder.createPackageRegistry(packageDescr); if (pkgRegistry == null) { diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java index 3dcf46a0cbc..ff80d3c9480 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java @@ -965,7 +965,7 @@ void removeTypesGeneratedFromResource(Resource resource) { } } - List processTypeDeclarations( PackageRegistry pkgRegistry, PackageDescr packageDescr, List unresolvedTypes, Map unprocessableDescrs ) { + List processTypeDeclarations( PackageRegistry pkgRegistry, PackageDescr packageDescr, List unresolvedTypes, Map unprocessableDescrs ) { Map foreignPackages = null; @@ -1083,7 +1083,7 @@ List processTypeDeclarations( PackageRegistry pkgRegistry, Packa } // sort declarations : superclasses must be generated first - Collection sortedTypeDescriptors = sortByHierarchy(packageDescr.getClassAndEnumDeclarationDescrs()); + Collection sortedTypeDescriptors = sortByHierarchy(kbuilder, packageDescr.getClassAndEnumDeclarationDescrs()); for (AbstractClassTypeDeclarationDescr typeDescr : sortedTypeDescriptors) { registerGeneratedType(typeDescr); @@ -1108,7 +1108,7 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, AbstractClassTypeDeclarationDescr typeDescr, Collection sortedTypeDescriptors, List unresolvedTypes, - Map unprocessableDescrs ) { + Map unprocessableDescrs ) { //descriptor needs fields inherited from superclass if (typeDescr instanceof TypeDeclarationDescr) { TypeDeclarationDescr tDescr = (TypeDeclarationDescr) typeDescr; @@ -1134,14 +1134,6 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, return; } -// for ( QualifiedName qualifiedName : typeDescr.getSuperTypes() ) { -// for ( TypeDefinition def : unresolvedTypes ) { -// if ( def.typeDescr.getType().equals( qualifiedName ) ) { -// unresolvedTypes.add( ) -// } -// } -// } - // Go on with the build TypeDeclaration type = new TypeDeclaration(typeDescr.getTypeName()); if (typeDescr.getResource() == null) { @@ -1256,9 +1248,8 @@ private AnnotationDescr getSingleAnnotation(AbstractClassTypeDeclarationDescr ty * resulting collection. This ensures that superclasses are processed before * their subclasses */ - public Collection sortByHierarchy(List typeDeclarations) { + public static Collection sortByHierarchy(KnowledgeBuilderImpl kbuilder, Collection typeDeclarations) { - HierarchySorter sorter = new HierarchySorter(); Map> taxonomy = new HashMap>(); Map cache = new HashMap(); @@ -1271,7 +1262,7 @@ public Collection sortByHierarchy(List()); } else { kbuilder.addBuilderResult(new TypeDeclarationError(tdescr, - "Found duplicate declaration for type " + tdescr.getType())); + "Found duplicate declaration for type " + tdescr.getType())); } Collection supers = taxonomy.get(name); @@ -1284,7 +1275,7 @@ public Collection sortByHierarchy(List sortByHierarchy(List sorted = sorter.sort(taxonomy); + List sorted = new HierarchySorter().sort(taxonomy); ArrayList list = new ArrayList(sorted.size()); for (QualifiedName name : sorted) { list.add(cache.get(name)); @@ -1311,9 +1302,9 @@ public Collection sortByHierarchy(List> taxonomy) { + private static boolean hasCircularDependency(QualifiedName name, + QualifiedName typeName, + Map> taxonomy) { if (name.equals(typeName)) { return true; } From 7a28117cfd46bba02534f06aeeb2fac43b7e1ae7 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 7 Jul 2014 18:22:27 +0200 Subject: [PATCH 34/76] [DROOLS-546] check for non-existing fields on fact types (cherry picked from commit 315566acb9360eaee2370287f3be8762e61446c6) --- .../compiler/TypeDeclarationTest.java | 46 +++++++++++++------ .../core/factmodel/ClassDefinition.java | 19 ++++---- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java b/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java index 9d67e725e5a..45b213373dd 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java @@ -1,9 +1,9 @@ package org.drools.compiler.compiler; -import org.junit.Assert; import org.drools.core.common.EventFactHandle; import org.drools.core.definitions.impl.KnowledgePackageImpl; import org.drools.core.rule.TypeDeclaration; +import org.junit.Assert; import org.junit.Test; import org.kie.api.KieBase; import org.kie.api.KieServices; @@ -11,7 +11,12 @@ import org.kie.api.builder.KieFileSystem; import org.kie.api.builder.Message; import org.kie.api.builder.model.KieModuleModel; +import org.kie.api.definition.type.Annotation; +import org.kie.api.definition.type.FactField; +import org.kie.api.definition.type.FactType; import org.kie.api.io.KieResources; +import org.kie.api.io.Resource; +import org.kie.api.io.ResourceType; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.rule.FactHandle; import org.kie.internal.KnowledgeBase; @@ -20,22 +25,10 @@ import org.kie.internal.builder.KnowledgeBuilderFactory; import org.kie.internal.builder.KnowledgeBuilderResults; import org.kie.internal.builder.ResultSeverity; -import org.kie.api.definition.type.Annotation; -import org.kie.api.definition.type.FactField; -import org.kie.api.definition.type.FactType; import org.kie.internal.definition.KnowledgePackage; import org.kie.internal.io.ResourceFactory; -import org.kie.api.io.Resource; -import org.kie.api.io.ResourceType; import org.kie.internal.runtime.StatefulKnowledgeSession; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,6 +36,8 @@ import java.util.Collection; import java.util.Collections; +import static org.junit.Assert.*; + public class TypeDeclarationTest { @Test @@ -828,6 +823,31 @@ public void testCrossPackageDeclares() { assertNotNull( ft ); assertNotNull( ft.getFactClass() ); assertEquals( "org.drools.compiler.test1.Parent", ft.getFactClass().getSuperclass().getName() ); + } + + + @Test + public void testUnknownField() throws InstantiationException, IllegalAccessException { + // DROOLS-546 + String drl = "package org.test; " + + "declare Pet" + + " " + + "end \n"; + + KieServices kieServices = KieServices.Factory.get(); + KieFileSystem kfs = kieServices.newKieFileSystem(); + kfs.write( kieServices.getResources().newByteArrayResource( drl.getBytes() ) + .setSourcePath( "test.drl" ) + .setResourceType( ResourceType.DRL ) ); + KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ); + kieBuilder.buildAll(); + + assertFalse( kieBuilder.getResults().hasMessages( Message.Level.ERROR ) ); + KieBase kieBase = kieServices.newKieContainer( kieBuilder.getKieModule().getReleaseId() ).getKieBase(); + FactType factType = kieBase.getFactType("org.test", "Pet"); + Object instance = factType.newInstance(); + factType.get(instance, "unknownField"); + factType.set(instance, "unknownField", "myValue"); } } diff --git a/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java b/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java index ad6b73fcbd9..605343b084c 100755 --- a/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java +++ b/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java @@ -16,11 +16,16 @@ package org.drools.core.factmodel; +import org.kie.api.definition.type.Annotation; +import org.kie.api.definition.type.FactField; +import org.kie.api.definition.type.FactType; + import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -28,11 +33,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Arrays; - -import org.kie.api.definition.type.Annotation; -import org.kie.api.definition.type.FactField; -import org.kie.api.definition.type.FactType; /** * Declares a class to be dynamically created @@ -246,14 +246,17 @@ public List getFields() { public Object get(Object bean, String field) { - return this.getField( field ).getFieldAccessor().getValue( bean ); + FieldDefinition fieldDefinition = getField( field ); + return fieldDefinition != null ? fieldDefinition.getFieldAccessor().getValue( bean ) : null; } public void set(Object bean, String field, Object value) { - this.getField( field ).getFieldAccessor().setValue( bean, - value ); + FieldDefinition fieldDefinition = getField( field ); + if (fieldDefinition != null) { + fieldDefinition.getFieldAccessor().setValue( bean, value ); + } } public Map getAsMap(Object bean) { From 4a1eae33ec27d9dbc711f66ab5f604c6556e72e0 Mon Sep 17 00:00:00 2001 From: sotty Date: Thu, 3 Jul 2014 09:33:21 -0500 Subject: [PATCH 35/76] [DROOLS-542] Expose more commands through the KieCommands interface (cherry picked from commit 0a83a853b0f98340bd018cf223f2490f15ec0e62) --- .../core/command/impl/CommandFactoryServiceImpl.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java b/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java index 0ca460bf403..57bf85f19e8 100644 --- a/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java +++ b/drools-core/src/main/java/org/drools/core/command/impl/CommandFactoryServiceImpl.java @@ -169,10 +169,20 @@ public Command newFireAllRules(int max) { return new FireAllRulesCommand(max); } - public Command newFireAllRules(String outidentifier) { + public Command newFireAllRules(String outidentifier) { return new FireAllRulesCommand(outidentifier); } + @Override + public Command newGetFactHandle( Object object ) { + return new GetFactHandleCommand( object ); + } + + @Override + public Command newGetFactHandleInEntryPoint( Object object, String entryPoint ) { + return new GetFactHandleInEntryPointCommand( object, entryPoint ); + } + public Command newStartProcess(String processId) { StartProcessCommand startProcess = new StartProcessCommand(); startProcess.setProcessId(processId); From 1c4911b7add6ed1e2a9a0e2cb12ddbf45816ab3f Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 10 Jul 2014 18:41:27 +0200 Subject: [PATCH 36/76] [DROOLS-551] avoid to serialize the expiration job of an already retracted event (cherry picked from commit ccd415f20676de7768aad25de97cc167c616116b) --- .../java/org/drools/core/common/DefaultFactHandle.java | 8 ++++---- .../core/marshalling/impl/ProtobufOutputMarshaller.java | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java b/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java index 58cece7a2e7..09446285d89 100644 --- a/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java +++ b/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java @@ -66,6 +66,8 @@ public class DefaultFactHandle extends AbstractBaseLinkedListNode Date: Tue, 15 Jul 2014 17:14:19 +0200 Subject: [PATCH 37/76] [BZ-1119731] return null in legacy api when trying to retrieve the FactHandle for an object not present in the working memory (cherry picked from commit 386dce1443e8404a077e9942f742a2c06cdd87f7) --- .../adapters/KnowledgeRuntimeAdapter.java | 3 ++- .../WorkingMemoryEntryPointAdapter.java | 3 ++- .../org/drools/integrationtests/MiscTest.java | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/KnowledgeRuntimeAdapter.java b/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/KnowledgeRuntimeAdapter.java index a761fe64c94..5716975a082 100644 --- a/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/KnowledgeRuntimeAdapter.java +++ b/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/KnowledgeRuntimeAdapter.java @@ -257,7 +257,8 @@ public void update(FactHandle handle, Object object) { } public FactHandle getFactHandle(Object object) { - return new FactHandleAdapter(delegate.getFactHandle(object)); + org.kie.api.runtime.rule.FactHandle factHandle = delegate.getFactHandle(object); + return factHandle != null ? new FactHandleAdapter(factHandle) : null; } public Object getObject(FactHandle factHandle) { diff --git a/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/WorkingMemoryEntryPointAdapter.java b/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/WorkingMemoryEntryPointAdapter.java index 7837a2427d5..4f162d293d8 100644 --- a/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/WorkingMemoryEntryPointAdapter.java +++ b/knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/WorkingMemoryEntryPointAdapter.java @@ -44,7 +44,8 @@ public void update(FactHandle handle, Object object) { } public FactHandle getFactHandle(Object object) { - return new FactHandleAdapter(delegate.getFactHandle(object)); + org.kie.api.runtime.rule.FactHandle factHandle = delegate.getFactHandle(object); + return factHandle != null ? new FactHandleAdapter(factHandle) : null; } public Object getObject(FactHandle factHandle) { diff --git a/knowledge-api-legacy5-adapter/src/test/java/org/drools/integrationtests/MiscTest.java b/knowledge-api-legacy5-adapter/src/test/java/org/drools/integrationtests/MiscTest.java index 9253ac69313..d7ce42298a5 100644 --- a/knowledge-api-legacy5-adapter/src/test/java/org/drools/integrationtests/MiscTest.java +++ b/knowledge-api-legacy5-adapter/src/test/java/org/drools/integrationtests/MiscTest.java @@ -12,6 +12,7 @@ import org.drools.runtime.KnowledgeSessionConfiguration; import org.drools.runtime.StatefulKnowledgeSession; import org.drools.runtime.conf.ClockTypeOption; +import org.drools.runtime.rule.FactHandle; import org.drools.runtime.rule.QueryResults; import org.drools.runtime.rule.QueryResultsRow; import org.drools.runtime.rule.Variable; @@ -279,4 +280,22 @@ public void testQueriesWithVariableUnification() throws Exception { names.size() ); assertTrue( names.contains( "darth" ) ); } + + @Test + public void testNotExistingFactHandle() { + // BZ-1119731 + String str = + "package foo.bar\n" + + "rule R\n" + + "when\n" + + "then\n" + + "end"; + + KnowledgeBase kbase = loadKnowledgeBaseFromString(str); + StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); + + FactHandle handle = ksession.getFactHandle("fact"); + assertNull(handle); + } + } From f4f539fa3be68c6cf9be8a69cbefe2b6bb3650fb Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 16 Jul 2014 13:10:42 +0200 Subject: [PATCH 38/76] [DROOLS-516] register unlinking caused by a delete in a not node (cherry picked from commit d1814e2a2575cf9e3f8727180306b910b2d0301a) --- .../compiler/integrationtests/CepEspTest.java | 56 +++++++++++++++++++ .../java/org/drools/core/reteoo/BetaNode.java | 26 +++++---- .../java/org/drools/core/reteoo/NotNode.java | 1 + 3 files changed, 72 insertions(+), 11 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java index b15a851f898..d59b1f9257b 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java @@ -16,13 +16,17 @@ import org.drools.core.common.EventFactHandle; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; +import org.drools.core.common.Memory; +import org.drools.core.common.NodeMemories; import org.drools.core.common.RightTupleSets; +import org.drools.core.common.StreamTupleEntryQueue; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.impl.KnowledgeBaseImpl; import org.drools.core.impl.StatefulKnowledgeSessionImpl; import org.drools.core.reteoo.BetaMemory; import org.drools.core.reteoo.JoinNode; import org.drools.core.reteoo.ObjectTypeNode; +import org.drools.core.reteoo.PathMemory; import org.drools.core.reteoo.Rete; import org.drools.core.rule.EntryPointId; import org.drools.core.rule.TypeDeclaration; @@ -67,6 +71,7 @@ import org.kie.internal.definition.KnowledgePackage; import org.kie.internal.io.ResourceFactory; import org.kie.internal.runtime.StatefulKnowledgeSession; +import org.kie.internal.utils.KieHelper; import org.mockito.ArgumentCaptor; import java.io.File; @@ -5260,4 +5265,55 @@ public void testRightTupleLeak3() throws Exception { assertEquals(5, list.size()); assertTrue(list.containsAll(Arrays.asList(1, 3, 5, 7, 9))); } + + @Test + public void testDurationMemoryLeakWithAlwaysLinkedRules() throws Exception { + String drl = + "import org.drools.compiler.StockTick;\n " + + + "declare StockTick\n"+ + " @role( event )\n"+ + " @timestamp( time )\n"+ + "end\n"+ + + "rule Clear \n"+ + "when\n"+ + " $droo : StockTick( company == \"DROO\" )\n"+ + "then\n"+ + " delete($droo);\n"+ + "end\n"+ + + "rule Cancel\n"+ + "when\n"+ + " $oord : StockTick( company != \"DROO\" )\n"+ + " not StockTick( company == \"DROO\" )\n"+ + "then\n"+ + "end"; + + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ksession = helper.build( EventProcessingOption.STREAM ).newKieSession(); + + assertEquals("FactCount should be 0[1]", 0, ksession.getFactCount()); + + for ( int j = 0; j < 100; j++ ) { + ksession.insert(new StockTick(0, "DROO", 1.00)); + } + ksession.fireAllRules(); + assertEquals("FactCount should still be 0[2]", 0, ksession.getFactCount()); + + ((DefaultAgenda)ksession.getAgenda()).getGarbageCollector().forceGcUnlinkedRules(); + + NodeMemories nm = ( (StatefulKnowledgeSessionImpl) ksession ).getNodeMemories(); + for ( int j = 0; j < nm.length(); j++ ) { + Memory mem = nm.peekNodeMemory( j ); + if ( mem != null && mem instanceof PathMemory) { + PathMemory pathMemory = (PathMemory) mem; + StreamTupleEntryQueue kiu = pathMemory.getStreamQueue(); + System.out.println( kiu + " >> " + kiu.size() ); + assertEquals( 0, kiu.size() ); + } + } + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java index b293b3146e8..20c6d746805 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java @@ -360,17 +360,7 @@ public void doDeleteRightTuple(final RightTuple rightTuple, log.trace( "{} delete queue={} size={} pctx={} lt={}", getClass().getSimpleName(), System.identityHashCode( memory.getSegmentMemory().getStreamQueue() ), memory.getSegmentMemory().getStreamQueue().size(), PhreakPropagationContext.intEnumToString(rightTuple.getPropagationContext()), rightTuple ); } - if (stagedDeleteWasEmpty && !memory.getSegmentMemory().isSegmentLinked()) { - GarbageCollector garbageCollector = ((InternalAgenda)wm.getAgenda()).getGarbageCollector(); - synchronized (garbageCollector) { - for (PathMemory pmem : memory.getSegmentMemory().getPathMemories()) { - if (pmem.getNodeType() == NodeTypeEnums.RuleTerminalNode) { - garbageCollector.add(pmem.getOrCreateRuleAgendaItem(wm)); - } - } - garbageCollector.increaseDeleteCounter(); - } - } + registerUnlinkedPaths(wm, memory, stagedDeleteWasEmpty); } else { stagedDeleteWasEmpty = stagedRightTuples.addDelete(rightTuple); } @@ -383,6 +373,20 @@ public void doDeleteRightTuple(final RightTuple rightTuple, }; } + protected void registerUnlinkedPaths(InternalWorkingMemory wm, BetaMemory memory, boolean stagedDeleteWasEmpty) { + if (stagedDeleteWasEmpty && !memory.getSegmentMemory().isSegmentLinked()) { + GarbageCollector garbageCollector = ((InternalAgenda)wm.getAgenda()).getGarbageCollector(); + synchronized (garbageCollector) { + for (PathMemory pmem : memory.getSegmentMemory().getPathMemories()) { + if (pmem.getNodeType() == NodeTypeEnums.RuleTerminalNode) { + garbageCollector.add(pmem.getOrCreateRuleAgendaItem(wm)); + } + } + garbageCollector.increaseDeleteCounter(); + } + } + } + public void doUpdateRightTuple(final RightTuple rightTuple, final InternalWorkingMemory wm, final BetaMemory memory) { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java b/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java index 300aa4d2c6d..a3f80a51bc8 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java @@ -185,6 +185,7 @@ public void doDeleteRightTuple(final RightTuple rightTuple, PropagationContext pctx = rightTuple.getPropagationContext(); stagedDeleteWasEmpty = memory.getSegmentMemory().getStreamQueue().addDelete(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); //log.trace( "NotNode delete queue={} size={} lt={}", System.identityHashCode( memory.getSegmentMemory().getTupleQueue() ), memory.getSegmentMemory().getTupleQueue().size(), rightTuple ); + registerUnlinkedPaths(wm, memory, stagedDeleteWasEmpty); } else { stagedDeleteWasEmpty = stagedRightTuples.addDelete( rightTuple ); } From 5204941f863f1124d068e3cb59d8dcfc867a7f1b Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 20 Mar 2014 15:47:57 +0100 Subject: [PATCH 39/76] upgrade to asm5 (cherry picked from commit 7fe6d7ad068a1ecd17fccdb97b1623060d931070) --- .../EclipseJavaCompilerSettings.java | 2 ++ .../jci/compilers/JavaCompilerSettings.java | 4 +-- .../java/JavaDialectConfiguration.java | 13 +++++++--- .../core/definitions/rule/impl/RuleImpl.java | 3 +-- .../rule/builder/dialect/asm/ClassLevel.java | 3 +++ .../core/util/asm/ClassFieldInspector.java | 9 +++++-- .../core/util/asm/MethodComparator.java | 26 ++++++++++++------- 7 files changed, 42 insertions(+), 18 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/EclipseJavaCompilerSettings.java b/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/EclipseJavaCompilerSettings.java index 81addc57eb8..834c8742481 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/EclipseJavaCompilerSettings.java +++ b/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/EclipseJavaCompilerSettings.java @@ -35,6 +35,7 @@ public final class EclipseJavaCompilerSettings extends JavaCompilerSettings { public static final String CompilerOptions_VERSION_1_5 = "1.5"; //$NON-NLS-1$ public static final String CompilerOptions_VERSION_1_6 = "1.6"; //$NON-NLS-1$ public static final String CompilerOptions_VERSION_1_7 = "1.7"; //$NON-NLS-1$ + public static final String CompilerOptions_VERSION_1_8 = "1.8"; //$NON-NLS-1$ public static final String CompilerOptions_GENERATE = "generate";//$NON-NLS-1$ public static final String CompilerOptions_DO_NOT_GENERATE = "do not generate"; //$NON-NLS-1$ @@ -86,6 +87,7 @@ public EclipseJavaCompilerSettings( final Map pMap ) { put("1.5", CompilerOptions_VERSION_1_5); put("1.6", CompilerOptions_VERSION_1_6); put("1.7", CompilerOptions_VERSION_1_7); + put("1.8", CompilerOptions_VERSION_1_8); }}; private String toNativeVersion( final String pVersion ) { diff --git a/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/JavaCompilerSettings.java b/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/JavaCompilerSettings.java index c2ce2da2e84..48e45baeaf2 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/JavaCompilerSettings.java +++ b/drools-compiler/src/main/java/org/drools/compiler/commons/jci/compilers/JavaCompilerSettings.java @@ -28,8 +28,8 @@ */ public class JavaCompilerSettings { - private String targetVersion = "1.4"; - private String sourceVersion = "1.4"; + private String targetVersion = "1.6"; + private String sourceVersion = "1.6"; private String sourceEncoding = "UTF-8"; private boolean warnings = false; private boolean deprecations = false; diff --git a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialectConfiguration.java b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialectConfiguration.java index adffd2b031c..2016f9ae3d1 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialectConfiguration.java +++ b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialectConfiguration.java @@ -11,7 +11,10 @@ import java.util.Arrays; -import static org.mvel2.asm.Opcodes.*; +import static org.mvel2.asm.Opcodes.V1_5; +import static org.mvel2.asm.Opcodes.V1_6; +import static org.mvel2.asm.Opcodes.V1_7; +import static org.mvel2.asm.Opcodes.V1_8; /** * @@ -46,7 +49,7 @@ public class JavaDialectConfiguration public static final int JANINO = 1; public static final int NATIVE = 2; - public static final String[] LANGUAGE_LEVELS = new String[]{"1.5", "1.6", "1.7"}; + public static final String[] LANGUAGE_LEVELS = new String[]{"1.5", "1.6", "1.7", "1.8"}; private String languageLevel; @@ -161,8 +164,12 @@ private String getDefaultLanguageLevel() { return "1.6"; case V1_7: return "1.7"; + case V1_8: + // ecj still doesn't work with version 1.8 it generates the following error + // "Pb(591) Syntax error, static imports are only available if source level is 1.5 or greater" + return "1.7"; default: - return "1.6"; + return "1.7"; } } } diff --git a/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java b/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java index 1a6687c7500..24001fa5e97 100644 --- a/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java +++ b/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java @@ -814,8 +814,7 @@ public static java.util.List getMethodBytecode(Class cls, String ruleClassName, org.mvel2.asm.ClassReader classReader = new org.mvel2.asm.ClassReader( bos.toByteArray() ); classReader.accept( visit, org.mvel2.asm.ClassReader.SKIP_DEBUG ); - org.mvel2.asm.util.TraceMethodVisitor trace = visit.getTrace(); - return trace.getText(); + return visit.getText(); } public boolean isQuery() { diff --git a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassLevel.java b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassLevel.java index cdaaa51ab37..cc82cdadf4e 100644 --- a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassLevel.java +++ b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassLevel.java @@ -5,6 +5,7 @@ import static org.mvel2.asm.Opcodes.V1_5; import static org.mvel2.asm.Opcodes.V1_6; import static org.mvel2.asm.Opcodes.V1_7; +import static org.mvel2.asm.Opcodes.V1_8; public class ClassLevel { public static final String JAVA_LANG_LEVEL_PROPERTY = "drools.dialect.java.compiler.lnglevel"; @@ -46,6 +47,8 @@ public static int findJavaVersion(ChainedProperties chainedProperties) { return V1_6; } else if ( level.startsWith( "1.7" ) ) { return V1_7; + } else if ( level.startsWith( "1.8" ) ) { + return V1_8; } else { return V1_7; } diff --git a/drools-core/src/main/java/org/drools/core/util/asm/ClassFieldInspector.java b/drools-core/src/main/java/org/drools/core/util/asm/ClassFieldInspector.java index d92b1b3af09..75adeba9990 100644 --- a/drools-core/src/main/java/org/drools/core/util/asm/ClassFieldInspector.java +++ b/drools-core/src/main/java/org/drools/core/util/asm/ClassFieldInspector.java @@ -383,7 +383,7 @@ protected Map> getResults() { * Using the ASM classfield extractor to pluck it out in the order they appear in the class file. */ static class ClassFieldVisitor - implements + extends ClassVisitor { private Class< ? > clazz; @@ -393,6 +393,7 @@ static class ClassFieldVisitor ClassFieldVisitor(final Class< ? > cls, final boolean includeFinalMethods, final ClassFieldInspector inspector) { + super(Opcodes.ASM5); this.clazz = cls; this.includeFinalMethods = includeFinalMethods; this.inspector = inspector; @@ -505,9 +506,13 @@ public FieldVisitor visitField( final int arg0, * It may also come in handy if we want to allow custom annotations for marking field numbers etc. */ static class ClassFieldAnnotationVisitor - implements + extends AnnotationVisitor { + ClassFieldAnnotationVisitor() { + super(Opcodes.ASM5); + } + public void visit( final String arg0, final Object arg1 ) { } diff --git a/drools-core/src/main/java/org/drools/core/util/asm/MethodComparator.java b/drools-core/src/main/java/org/drools/core/util/asm/MethodComparator.java index 98def873f93..5232fe323f8 100644 --- a/drools-core/src/main/java/org/drools/core/util/asm/MethodComparator.java +++ b/drools-core/src/main/java/org/drools/core/util/asm/MethodComparator.java @@ -24,6 +24,9 @@ import org.mvel2.asm.ClassVisitor; import org.mvel2.asm.FieldVisitor; import org.mvel2.asm.MethodVisitor; +import org.mvel2.asm.Opcodes; +import org.mvel2.asm.util.Printer; +import org.mvel2.asm.util.Textifier; import org.mvel2.asm.util.TraceMethodVisitor; /** @@ -62,8 +65,7 @@ public List getMethodBytecode(final String methodName, final Tracer visit = new Tracer( methodName ); classReader.accept( visit, ClassReader.SKIP_DEBUG ); - final TraceMethodVisitor trace = visit.getTrace(); - return trace.getText(); + return visit.getText(); } /** @@ -76,8 +78,7 @@ public static List getMethodBytecode(final String methodName, final ClassReader classReader = new ClassReader( bytes ); classReader.accept( visit, ClassReader.SKIP_DEBUG ); - final TraceMethodVisitor trace = visit.getTrace(); - return trace.getText(); + return visit.getText(); } /** @@ -100,13 +101,15 @@ public static boolean compareBytecode(final List b1, } public static class Tracer - implements + extends ClassVisitor { private TraceMethodVisitor trace; private String methodName; + private Printer printer; public Tracer(final String methodName) { + super(Opcodes.ASM5); this.methodName = methodName; } @@ -150,7 +153,8 @@ public MethodVisitor visitMethod(final int access, final String[] exceptions) { if ( this.methodName.equals( name ) ) { - this.trace = new TraceMethodVisitor(); + this.printer = new Textifier(); + this.trace = new TraceMethodVisitor(printer); return this.trace; } return null; @@ -165,16 +169,20 @@ public void visitSource(final String source, final String debug) { } - public TraceMethodVisitor getTrace() { - return this.trace; + public List getText() { + return this.printer.getText(); } } static class DummyAnnotationVisitor - implements + extends AnnotationVisitor { + public DummyAnnotationVisitor() { + super(Opcodes.ASM5); + } + public void visit(final String name, final Object value) { } From 3442ce5fb57f1eff0f37de4fb88b3ba566233fdf Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Wed, 16 Jul 2014 16:40:33 +0100 Subject: [PATCH 40/76] GUVNOR-2109: DRL->RuleModel marshalling: Method invocations with parameters are not handled correctly --- .../rule/RuleModelDRLPersistenceImpl.java | 126 ++++++++++--- .../rule/RuleModelPersistenceHelper.java | 34 +++- .../GeneratorContextRuleModelVisitor.java | 4 +- ...eModelDRLPersistenceUnmarshallingTest.java | 159 ++++++++++++++++ .../rule/classes/MyListContainerClass.java | 17 ++ .../rule/classes/MyStringContainerClass.java | 15 ++ .../datamodel/rule/CopyExpressionVisitor.java | 112 ------------ .../datamodel/rule/ExpressionFormLine.java | 139 ++------------ .../datamodel/rule/ExpressionMethod.java | 45 +++-- .../rule/ExpressionMethodParameter.java | 54 ++++++ .../models/datamodel/rule/ExpressionText.java | 12 +- .../datamodel/rule/ExpressionVisitor.java | 3 + .../builder}/DRLConstraintValueBuilder.java | 6 +- .../JavaDRLConstraintValueBuilder.java | 2 +- .../MvelDRLConstraintValueBuilder.java | 2 +- .../rule/visitors/CopyExpressionVisitor.java | 151 ++++++++++++++++ .../rule/{ => visitors}/RuleModelVisitor.java | 33 +++- .../visitors/ToStringExpressionVisitor.java | 171 ++++++++++++++++++ .../src/main/resources/ErraiApp.properties | 6 +- .../backend/GuidedDTDRLPersistence.java | 2 +- .../util/GuidedDTBRDRLPersistence.java | 2 +- .../RuleTemplateModelDRLPersistenceImpl.java | 2 +- .../guided/template/shared/TemplateModel.java | 2 +- 23 files changed, 802 insertions(+), 297 deletions(-) create mode 100644 drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyListContainerClass.java create mode 100644 drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyStringContainerClass.java delete mode 100644 drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/CopyExpressionVisitor.java create mode 100644 drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethodParameter.java rename drools-workbench-models/{drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule => drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder}/DRLConstraintValueBuilder.java (93%) rename drools-workbench-models/{drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule => drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder}/JavaDRLConstraintValueBuilder.java (98%) rename drools-workbench-models/{drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule => drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder}/MvelDRLConstraintValueBuilder.java (99%) create mode 100644 drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/CopyExpressionVisitor.java rename drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/{ => visitors}/RuleModelVisitor.java (86%) create mode 100644 drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/ToStringExpressionVisitor.java diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java index c6b56e247ca..dfd5cb4e6e0 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java @@ -88,6 +88,7 @@ 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.ExpressionMethodParameter; import org.drools.workbench.models.datamodel.rule.ExpressionPart; import org.drools.workbench.models.datamodel.rule.ExpressionText; import org.drools.workbench.models.datamodel.rule.ExpressionUnboundFact; @@ -109,6 +110,8 @@ 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.rule.builder.DRLConstraintValueBuilder; +import org.drools.workbench.models.datamodel.rule.visitors.ToStringExpressionVisitor; import org.drools.workbench.models.datamodel.workitems.HasBinding; import org.drools.workbench.models.datamodel.workitems.PortableBooleanParameterDefinition; import org.drools.workbench.models.datamodel.workitems.PortableFloatParameterDefinition; @@ -129,14 +132,11 @@ public class RuleModelDRLPersistenceImpl RuleModelPersistence { private static final String WORKITEM_PREFIX = "wi"; - private static final String DATE_FORMAT = "drools.dateformat"; private static final RuleModelPersistence INSTANCE = new RuleModelDRLPersistenceImpl(); - public static final String DEFAULT_DIALECT = "mvel"; - //This is the default dialect for rules not specifying one explicitly - protected DRLConstraintValueBuilder constraintValueBuilder = DRLConstraintValueBuilder.getBuilder( DEFAULT_DIALECT ); + protected DRLConstraintValueBuilder constraintValueBuilder = DRLConstraintValueBuilder.getBuilder( DRLConstraintValueBuilder.DEFAULT_DIALECT ); //Keep a record of all variable bindings for Actions that depend on them protected Map bindingsPatterns; @@ -277,7 +277,7 @@ protected void marshalAttributes( final StringBuilder buf, // Un comment below for mvel if ( !hasDialect ) { RuleAttribute attr = new RuleAttribute( "dialect", - DEFAULT_DIALECT ); + DRLConstraintValueBuilder.DEFAULT_DIALECT ); buf.append( "\t" ); buf.append( attr ); buf.append( "\n" ); @@ -776,7 +776,9 @@ private void renderSubPattern( final CompositeFactPattern pattern, } private void renderExpression( final ExpressionFormLine expression ) { - buf.append( expression.getText() ); + final ToStringExpressionVisitor visitor = new ToStringExpressionVisitor( expression.getBinding(), + constraintValueBuilder ); + buf.append( expression.getText( visitor ) ); } public void visitDSLSentence( final DSLSentence sentence ) { @@ -917,7 +919,10 @@ private void generateSingleFieldConstraint( final SingleFieldConstraint constr, if ( isConstraintComplete( constr ) ) { if ( constr instanceof SingleFieldConstraintEBLeftSide ) { - buf.append( ( (SingleFieldConstraintEBLeftSide) constr ).getExpressionLeftSide().getText() ); + final SingleFieldConstraintEBLeftSide sfcexp = ( (SingleFieldConstraintEBLeftSide) constr ); + final ToStringExpressionVisitor visitor = new ToStringExpressionVisitor( sfcexp.getExpressionLeftSide().getBinding(), + constraintValueBuilder ); + buf.append( sfcexp.getExpressionLeftSide().getText( visitor ) ); } else { SingleFieldConstraint parent = (SingleFieldConstraint) constr.getParent(); StringBuilder parentBuf = new StringBuilder(); @@ -1207,7 +1212,9 @@ protected void buildExpressionFieldValue( final ExpressionFormLine expression, final StringBuilder buf ) { if ( expression != null ) { buf.append( " " ); - buf.append( expression.getText() ); + final ToStringExpressionVisitor visitor = new ToStringExpressionVisitor( expression.getBinding(), + constraintValueBuilder ); + buf.append( expression.getText( visitor ) ); buf.append( " " ); } } @@ -1807,6 +1814,7 @@ private RuleModel getRuleModel( final ExpandedDRLInfo expandedDRLInfo, ruleDescr.getAttributes() ); Map boundParams = parseLhs( model, ruleDescr.getLhs(), + isJavaDialect, expandedDRLInfo, dmo ); parseRhs( model, @@ -2097,6 +2105,7 @@ private String stripQuotes( String value ) { private Map parseLhs( final RuleModel m, final AndDescr lhs, + final boolean isJavaDialect, final ExpandedDRLInfo expandedDRLInfo, final PackageDataModelOracle dmo ) { Map boundParams = new HashMap(); @@ -2107,6 +2116,7 @@ private Map parseLhs( final RuleModel m, lineCounter ); IPattern pattern = parseBaseDescr( m, descr, + isJavaDialect, boundParams, dmo ); if ( pattern != null ) { @@ -2161,17 +2171,20 @@ private int parseFreeForm( final RuleModel m, private IPattern parseBaseDescr( final RuleModel m, final BaseDescr descr, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { if ( descr instanceof PatternDescr ) { return parsePatternDescr( m, (PatternDescr) descr, + isJavaDialect, boundParams, dmo ); } else if ( descr instanceof AndDescr ) { AndDescr andDescr = (AndDescr) descr; return parseBaseDescr( m, andDescr.getDescrs().get( 0 ), + isJavaDialect, boundParams, dmo ); } else if ( descr instanceof EvalDescr ) { @@ -2181,6 +2194,7 @@ private IPattern parseBaseDescr( final RuleModel m, } else if ( descr instanceof ConditionalElementDescr ) { return parseExistentialElementDescr( m, (ConditionalElementDescr) descr, + isJavaDialect, boundParams, dmo ); } @@ -2189,23 +2203,27 @@ private IPattern parseBaseDescr( final RuleModel m, private IFactPattern parsePatternDescr( final RuleModel m, final PatternDescr pattern, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { if ( pattern.getSource() != null ) { return parsePatternSource( m, pattern, pattern.getSource(), + isJavaDialect, boundParams, dmo ); } return getFactPattern( m, pattern, + isJavaDialect, boundParams, dmo ); } private FactPattern getFactPattern( final RuleModel m, final PatternDescr pattern, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { String type = pattern.getObjectType(); @@ -2221,6 +2239,7 @@ private FactPattern getFactPattern( final RuleModel m, parseConstraint( m, factPattern, pattern.getConstraint(), + isJavaDialect, boundParams, dmo ); @@ -2246,6 +2265,7 @@ private FactPattern getFactPattern( final RuleModel m, private IFactPattern parsePatternSource( final RuleModel m, final PatternDescr pattern, final PatternSourceDescr patternSource, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { if ( patternSource instanceof AccumulateDescr ) { @@ -2253,6 +2273,7 @@ private IFactPattern parsePatternSource( final RuleModel m, FromAccumulateCompositeFactPattern fac = new FromAccumulateCompositeFactPattern(); fac.setSourcePattern( parseBaseDescr( m, accumulate.getInput(), + isJavaDialect, boundParams, dmo ) ); @@ -2263,6 +2284,7 @@ private IFactPattern parsePatternSource( final RuleModel m, parseConstraint( m, factPattern, pattern.getConstraint(), + isJavaDialect, boundParams, dmo ); @@ -2288,10 +2310,12 @@ private IFactPattern parsePatternSource( final RuleModel m, FromCollectCompositeFactPattern fac = new FromCollectCompositeFactPattern(); fac.setRightPattern( parseBaseDescr( m, collect.getInputPattern(), + isJavaDialect, boundParams, dmo ) ); fac.setFactPattern( getFactPattern( m, pattern, + isJavaDialect, boundParams, dmo ) ); return fac; @@ -2301,6 +2325,7 @@ private IFactPattern parsePatternSource( final RuleModel m, fep.setEntryPointName( entryPoint.getText() ); fep.setFactPattern( getFactPattern( m, pattern, + isJavaDialect, boundParams, dmo ) ); return fep; @@ -2312,6 +2337,7 @@ private IFactPattern parsePatternSource( final RuleModel m, parseConstraint( m, factPattern, pattern.getConstraint(), + isJavaDialect, boundParams, dmo ); @@ -2377,6 +2403,7 @@ private IFactPattern parsePatternSource( final RuleModel m, private CompositeFactPattern parseExistentialElementDescr( final RuleModel m, final ConditionalElementDescr conditionalDescr, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { CompositeFactPattern comp = conditionalDescr instanceof NotDescr ? @@ -2387,6 +2414,7 @@ private CompositeFactPattern parseExistentialElementDescr( final RuleModel m, addPatternToComposite( m, conditionalDescr, comp, + isJavaDialect, boundParams, dmo ); IFactPattern[] patterns = comp.getPatterns(); @@ -2396,18 +2424,21 @@ private CompositeFactPattern parseExistentialElementDescr( final RuleModel m, private void addPatternToComposite( final RuleModel m, final ConditionalElementDescr conditionalDescr, final CompositeFactPattern comp, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { for ( Object descr : conditionalDescr.getDescrs() ) { if ( descr instanceof PatternDescr ) { comp.addFactPattern( parsePatternDescr( m, (PatternDescr) descr, + isJavaDialect, boundParams, dmo ) ); } else if ( descr instanceof ConditionalElementDescr ) { addPatternToComposite( m, (ConditionalElementDescr) descr, comp, + isJavaDialect, boundParams, dmo ); } @@ -2417,12 +2448,14 @@ private void addPatternToComposite( final RuleModel m, private void parseConstraint( final RuleModel m, final FactPattern factPattern, final ConditionalElementDescr constraint, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { for ( BaseDescr descr : constraint.getDescrs() ) { if ( descr instanceof ExprConstraintDescr ) { ExprConstraintDescr exprConstraint = (ExprConstraintDescr) descr; Expr expr = parseExpr( exprConstraint.getExpression(), + isJavaDialect, boundParams, dmo ); factPattern.addConstraint( expr.asFieldConstraint( m, @@ -2992,6 +3025,7 @@ private String getStatementType( final String fact, } private Expr parseExpr( final String expr, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { List splittedExpr = splitExpression( expr ); @@ -2999,12 +3033,14 @@ private Expr parseExpr( final String expr, String singleExpr = splittedExpr.get( 0 ); if ( singleExpr.startsWith( "(" ) ) { return parseExpr( singleExpr.substring( 1 ), + isJavaDialect, boundParams, dmo ); } else if ( singleExpr.startsWith( "eval" ) ) { return new EvalExpr( unwrapParenthesis( singleExpr ) ); } else { return new SimpleExpr( singleExpr, + isJavaDialect, boundParams, dmo ); } @@ -3012,6 +3048,7 @@ private Expr parseExpr( final String expr, ComplexExpr complexExpr = new ComplexExpr( splittedExpr.get( 1 ) ); for ( int i = 0; i < splittedExpr.size(); i += 2 ) { complexExpr.subExprs.add( parseExpr( splittedExpr.get( i ), + isJavaDialect, boundParams, dmo ) ); } @@ -3129,13 +3166,16 @@ FieldConstraint asFieldConstraint( final RuleModel m, private static class SimpleExpr implements Expr { private final String expr; + private final boolean isJavaDialect; private final Map boundParams; private final PackageDataModelOracle dmo; private SimpleExpr( final String expr, + final boolean isJavaDialect, final Map boundParams, final PackageDataModelOracle dmo ) { this.expr = expr; + this.isJavaDialect = isJavaDialect; this.boundParams = boundParams; this.dmo = dmo; } @@ -3345,7 +3385,21 @@ private ExpressionFormLine parseExpression( final RuleModel m, //Handle all but last expression part for ( int i = 0; i < splits.length - 1; i++ ) { - String expressionPart = normalizeExpressionPart( splits[ i ] ); + String expressionPart = splits[ i ]; + + //The first part of the expression may be a bound variable + if ( boundParams.containsKey( expressionPart ) ) { + factType = getFQFactType( m, + boundParams.get( expressionPart ) ); + isBoundParam = true; + + typeFields = findFields( m, + dmo, + factType ); + methodInfos = getMethodInfosForType( m, + dmo, + factType ); + } if ( "this".equals( expressionPart ) ) { expression.appendPart( new ExpressionField( expressionPart, factType, @@ -3380,7 +3434,7 @@ private ExpressionFormLine parseExpression( final RuleModel m, expression, expressionPart ); - //Refresh field and method information based + //Refresh field and method information based on current expression part typeFields = findFields( m, dmo, currentClassName ); @@ -3391,7 +3445,7 @@ private ExpressionFormLine parseExpression( final RuleModel m, } //Handle last expression part - String expressionPart = normalizeExpressionPart( splits[ splits.length - 1 ] ); + String expressionPart = splits[ splits.length - 1 ]; ModelField currentField = findField( typeFields, expressionPart ); MethodInfo currentMethodInfo = findMethodInfo( methodInfos, @@ -3407,15 +3461,6 @@ private ExpressionFormLine parseExpression( final RuleModel m, return expression; } - private String normalizeExpressionPart( String expressionPart ) { - int parenthesisPos = expressionPart.indexOf( '(' ); - if ( parenthesisPos > 0 ) { - expressionPart = expressionPart.substring( 0, - parenthesisPos ); - } - return expressionPart.trim(); - } - private void processExpressionPart( final RuleModel m, final String factType, final ModelField currentField, @@ -3425,10 +3470,27 @@ private void processExpressionPart( final RuleModel m, if ( currentField == null ) { boolean isMethod = currentMethodInfo != null; if ( isMethod ) { - expression.appendPart( new ExpressionMethod( currentMethodInfo.getName(), - currentMethodInfo.getReturnClassType(), - currentMethodInfo.getGenericType(), - currentMethodInfo.getParametricReturnType() ) ); + final ExpressionMethod em = new ExpressionMethod( currentMethodInfo.getName(), + currentMethodInfo.getReturnClassType(), + currentMethodInfo.getGenericType(), + currentMethodInfo.getParametricReturnType() ); + //Add applicable parameter values + final List parameters = parseExpressionParameters( expressionPart ); + for ( int index = 0; index < currentMethodInfo.getParams().size(); index++ ) { + final String paramDataType = currentMethodInfo.getParams().get( index ); + final String paramValue = getParameterValue( paramDataType, + parameters, + index ); + if ( paramValue != null ) { + final ExpressionFormLine param = new ExpressionFormLine( index ); + param.appendPart( new ExpressionMethodParameter( paramValue, + paramDataType, + paramDataType ) ); + em.putParam( paramDataType, + param ); + } + } + expression.appendPart( em ); } else { expression.appendPart( new ExpressionText( expressionPart ) ); } @@ -3447,6 +3509,22 @@ private void processExpressionPart( final RuleModel m, } + private String getParameterValue( final String paramDataType, + final List parameters, + final int index ) { + if ( parameters == null || parameters.isEmpty() ) { + return null; + } + if ( index < 0 || index > parameters.size() - 1 ) { + return null; + } + + return RuleModelPersistenceHelper.adjustParam( paramDataType, + parameters.get( index ).trim(), + boundParams, + isJavaDialect ); + } + private String getFQFactType( final RuleModel ruleModel, final String factType ) { diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java index 53e039cca27..349347b7632 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java @@ -4,6 +4,7 @@ import java.math.BigInteger; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -202,10 +203,13 @@ static ModelField findField( final ModelField[] typeFields, } static MethodInfo findMethodInfo( final List methodInfos, - final String fieldName ) { - if ( methodInfos != null && fieldName != null ) { + final String expressionPart ) { + if ( methodInfos != null && expressionPart != null ) { + //Find a MethodInfo that matches name and parameter count + final int expressionParameterCount = parseExpressionParameters( expressionPart ).size(); + final String normalizedExpressionPart = normalizeExpressionPart( expressionPart ); for ( MethodInfo methodInfo : methodInfos ) { - if ( methodInfo.getName().equals( fieldName ) ) { + if ( methodInfo.getName().equals( normalizedExpressionPart ) && methodInfo.getParams().size() == expressionParameterCount ) { return methodInfo; } } @@ -214,6 +218,30 @@ static MethodInfo findMethodInfo( final List methodInfos, } + //TODO This is a naive implementation that won't handle parameter values containing "," + //TODO for example callMyMethod("Anstis, Michael", 41). This would parse as 3 parameters + static List parseExpressionParameters( String expressionPart ) { + int parenthesisOpenPos = expressionPart.indexOf( '(' ); + int parenthesisClosePos = expressionPart.lastIndexOf( ')' ); + if ( parenthesisOpenPos > 0 && parenthesisClosePos > 0 ) { + expressionPart = expressionPart.substring( parenthesisOpenPos + 1, + parenthesisClosePos ); + } + if ( expressionPart.isEmpty() ) { + return Collections.emptyList(); + } + return Arrays.asList( expressionPart.split( "," ) ); + } + + private static String normalizeExpressionPart( String expressionPart ) { + int parenthesisPos = expressionPart.indexOf( '(' ); + if ( parenthesisPos > 0 ) { + expressionPart = expressionPart.substring( 0, + parenthesisPos ); + } + return expressionPart.trim(); + } + static String inferDataType( final ActionFieldList action, final String field, final Map boundParams, diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/GeneratorContextRuleModelVisitor.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/GeneratorContextRuleModelVisitor.java index e29da57bc8a..289c51cf61d 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/GeneratorContextRuleModelVisitor.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/context/GeneratorContextRuleModelVisitor.java @@ -41,6 +41,7 @@ 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.rule.visitors.ToStringExpressionVisitor; /** * A Rule Model Visitor to extract Interpolation Variables (Template Keys). This version @@ -229,7 +230,8 @@ private void visitFromCollectCompositeFactPattern( final FromCollectCompositeFac private void visitFromCompositeFactPattern( final FromCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); - parseStringPattern( pattern.getExpression().getText() ); + ToStringExpressionVisitor visitor = new ToStringExpressionVisitor( pattern.getExpression().getBinding() ); + parseStringPattern( pattern.getExpression().getText( visitor ) ); } private void visitRuleModel( final RuleModel model ) { diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java index d0bafc94790..5bf1f574696 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java @@ -5180,6 +5180,165 @@ public void testLHSNestedMethodCalls() throws Exception { expPart3.getName() ); } + @Test + public void testLHSMissingConstraints() { + String drl = "package org.mortgages;\n" + + "import java.lang.Number;\n" + + "import org.drools.workbench.models.commons.backend.rule.classes.SearchContext;\n" + + "import org.drools.workbench.models.commons.backend.rule.classes.ProducerMasterForRules;\n" + + "import org.drools.workbench.models.commons.backend.rule.classes.RuleFactor;\n" + + + "rule \"SecondaryCuisineRepeatUsage\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $searchContext : SearchContext( lastThreeCuisines != null )\n" + + " ProducerMasterForRules( primaryCuisine != null, primaryCuisine != $searchContext.lastThreeCuisines, secondaryCuisine != null, secondaryCuisine == $searchContext.lastThreeCuisines )\n" + + " $secondaryCuisineRepeatUsageFactor : RuleFactor( )\n" + + "then\n" + + " modify( $secondaryCuisineRepeatUsageFactor ) {\n" + + " setWeightageImpact(-30)\n" + + " }\n" + + "end\n"; + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.SearchContext", + "this", + "org.drools.workbench.models.commons.backend.rule.classes.SearchContext", + DataType.TYPE_THIS ); + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.SearchContext", + "lastThreeCuisines", + "java.lang.String", + DataType.TYPE_STRING ); + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.ProducerMasterForRules", + "primaryCuisine", + "java.lang.String", + DataType.TYPE_STRING ); + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.ProducerMasterForRules", + "secondaryCuisine", + "java.lang.String", + DataType.TYPE_STRING ); + + final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + new ArrayList(), + dmo ); + + assertNotNull( m ); + + assertEqualsIgnoreWhitespace( drl, + RuleModelDRLPersistenceImpl.getInstance().marshal( m ) ); + } + + @Test + public void testLHSNestedMethodOneParameter() { + String drl = "package org.mortgages;\n" + + "import java.lang.Number;\n" + + "import java.util.List;\n" + + "import org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass;\n" + + "import org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass;\n" + + "rule \"r1\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $foo : MyListContainerClass()\n" + + " $bar : MyStringContainerClass( myString == $foo.myList.get(1))\n" + + "then\n" + + "end\n"; + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass", + "this", + "org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass", + DataType.TYPE_THIS ); + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass", + "myList", + "java.util.List", + "java.util.List" ); + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass", + "this", + "org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass", + DataType.TYPE_THIS ); + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass", + "myString", + "java.lang.String", + DataType.TYPE_STRING ); + + addMethodInformation( "java.util.List", + "get", + new ArrayList() {{ + add( "Integer" ); + }}, + "java.lang.Object", + null, + "java.lang.Object" ); + + final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + new ArrayList(), + dmo ); + + assertNotNull( m ); + + assertEqualsIgnoreWhitespace( drl, + RuleModelDRLPersistenceImpl.getInstance().marshal( m ) ); + } + + @Test + public void testLHSNestedMethodTwoParameters() { + String drl = "package org.mortgages;\n" + + "import java.lang.Number;\n" + + "import java.util.List;\n" + + "import org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass;\n" + + "import org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass;\n" + + "rule \"r1\"\n" + + "dialect \"mvel\"\n" + + "when\n" + + " $foo : MyListContainerClass()\n" + + " $bar : MyStringContainerClass( $foo.myList.set(1, \"hello\" ) == true )\n" + + "then\n" + + "end\n"; + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass", + "this", + "org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass", + DataType.TYPE_THIS ); + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyListContainerClass", + "myList", + "java.util.List", + "java.util.List" ); + + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass", + "this", + "org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass", + DataType.TYPE_THIS ); + addModelField( "org.drools.workbench.models.commons.backend.rule.classes.MyStringContainerClass", + "myString", + "java.lang.String", + DataType.TYPE_STRING ); + + addModelField( "java.util.List", + "this", + "java.util.List", + DataType.TYPE_THIS ); + addMethodInformation( "java.util.List", + "set", + new ArrayList() {{ + add( "Integer" ); + add( "String" ); + }}, + DataType.TYPE_BOOLEAN, + null, + DataType.TYPE_BOOLEAN ); + + final RuleModel m = RuleModelDRLPersistenceImpl.getInstance().unmarshal( drl, + new ArrayList(), + dmo ); + + assertNotNull( m ); + + assertEqualsIgnoreWhitespace( drl, + RuleModelDRLPersistenceImpl.getInstance().marshal( m ) ); + } + private void assertEqualsIgnoreWhitespace( final String expected, final String actual ) { final String cleanExpected = expected.replaceAll( "\\s+", diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyListContainerClass.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyListContainerClass.java new file mode 100644 index 00000000000..05c0554094b --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyListContainerClass.java @@ -0,0 +1,17 @@ +package org.drools.workbench.models.commons.backend.rule.classes; + +import java.util.List; + +public class MyListContainerClass { + + private List myList; + + public List getMyList() { + return myList; + } + + public void setMyList( List myList ) { + this.myList = myList; + } + +} diff --git a/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyStringContainerClass.java b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyStringContainerClass.java new file mode 100644 index 00000000000..857055e55d3 --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/classes/MyStringContainerClass.java @@ -0,0 +1,15 @@ +package org.drools.workbench.models.commons.backend.rule.classes; + +public class MyStringContainerClass { + + private String myString; + + public String getMyString() { + return myString; + } + + public void setMyString( String myString ) { + this.myString = myString; + } + +} diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/CopyExpressionVisitor.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/CopyExpressionVisitor.java deleted file mode 100644 index 08c94f2849d..00000000000 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/CopyExpressionVisitor.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012 JBoss Inc - * - * 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.datamodel.rule; - -import java.util.HashMap; -import java.util.Map; - -public class CopyExpressionVisitor implements ExpressionVisitor { - - private ExpressionPart root; - private ExpressionPart curr; - - public CopyExpressionVisitor() { - - } - - public ExpressionPart copy( ExpressionPart part ) { - root = null; - curr = null; - part.accept( this ); - return root; - } - - public void visit( ExpressionPart part ) { - throw new RuntimeException( "can't copy an abstract class: " + ExpressionPart.class.getName() ); - } - - public void visit( ExpressionField part ) { - add( new ExpressionField( part.getName(), part.getClassType(), part.getGenericType(), part.getParametricType() ) ); - moveNext( part ); - } - - public void visit( ExpressionMethod part ) { - ExpressionMethod method = new ExpressionMethod( part.getName(), part.getClassType(), part.getGenericType(), part.getParametricType() ); - copyMethodParams( part, method ); - add( method ); - moveNext( part ); - } - - public void visit( ExpressionVariable part ) { - add( new ExpressionVariable( part.getFact() ) ); - moveNext( part ); - } - - public void visit( ExpressionUnboundFact part ) { - add( new ExpressionUnboundFact( part.getFact() ) ); - moveNext( part ); - } - - public void visit( ExpressionCollection part ) { - add( new ExpressionCollection( part.getName(), part.getClassType(), part.getGenericType(), part.getParametricType() ) ); - moveNext( part ); - } - - public void visit( ExpressionCollectionIndex part ) { - ExpressionCollectionIndex method = new ExpressionCollectionIndex( part.getName(), part.getClassType(), part.getGenericType(), part.getParametricType() ); - copyMethodParams( part, method ); - add( method ); - moveNext( part ); - } - - public void visit( ExpressionText part ) { - add( new ExpressionText( part.getName(), part.getClassType(), part.getGenericType() ) ); - moveNext( part ); - } - - public void visit( ExpressionGlobalVariable part ) { - add( new ExpressionGlobalVariable( part.getName(), part.getClassType(), part.getGenericType(), part.getParametricType() ) ); - moveNext( part ); - - } - - private void copyMethodParams( ExpressionMethod part, - ExpressionMethod method ) { - Map params = new HashMap(); - for ( Map.Entry entry : part.getParams().entrySet() ) { - params.put( entry.getKey(), new ExpressionFormLine( entry.getValue() ) ); - } - method.setParams( params ); - } - - private void moveNext( ExpressionPart ep ) { - if ( ep.getNext() != null ) { - ep.getNext().accept( this ); - } - } - - private void add( ExpressionPart p ) { - if ( root == null ) { - root = p; - curr = p; - } else { - curr.setNext( p ); - curr = p; - } - } - -} diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionFormLine.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionFormLine.java index 13cd76819ce..db90daf312e 100644 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionFormLine.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionFormLine.java @@ -18,7 +18,9 @@ import java.util.LinkedList; import java.util.List; -import java.util.Map; + +import org.drools.workbench.models.datamodel.rule.visitors.CopyExpressionVisitor; +import org.drools.workbench.models.datamodel.rule.visitors.ToStringExpressionVisitor; public class ExpressionFormLine implements @@ -27,15 +29,17 @@ public class ExpressionFormLine private String binding = null; private LinkedList parts = new LinkedList(); + private int index = Integer.MAX_VALUE; public ExpressionFormLine() { } - public ExpressionFormLine( ExpressionPart part ) { - appendPart( part ); + public ExpressionFormLine( final int index ) { + this.index = index; } public ExpressionFormLine( ExpressionFormLine other ) { + this.index = other.getIndex(); CopyExpressionVisitor copier = new CopyExpressionVisitor(); if ( other.getParts().size() == 0 ) { return; @@ -45,13 +49,17 @@ public ExpressionFormLine( ExpressionFormLine other ) { } } - public String getText( boolean renderBindVariable ) { - return new ToStringVisitor().buildString( renderBindVariable ? getBinding() : null, - getRootExpression() ); + public ExpressionFormLine( ExpressionPart part ) { + appendPart( part ); + } + + public String getText( final ToStringExpressionVisitor visitor ) { + visitor.visit( getRootExpression() ); + return visitor.getText(); } - public String getText() { - return getText( false ); + public int getIndex() { + return this.index; } public void appendPart( ExpressionPart part ) { @@ -134,119 +142,4 @@ public List getParts() { return this.parts; } - public static class ToStringVisitor - implements - ExpressionVisitor { - - private StringBuilder str; - private boolean first; - - public ToStringVisitor() { - - } - - public String buildString( String bindVariable, - ExpressionPart exp ) { - if ( exp == null ) { - return ""; - } - str = new StringBuilder(); - first = true; - exp.accept( this ); - return ( bindVariable == null ? "" : bindVariable + ": " ) + str.toString(); - } - - public void visit( ExpressionPart part ) { - throw new IllegalStateException( "can't generate text for: " + part.getClass().getName() ); - } - - public void visit( ExpressionField part ) { - if ( !first ) { - str.append( '.' ); - } - str.append( part.getName() ); - moveNext( part ); - } - - public void visit( ExpressionMethod part ) { - if ( !first ) { - str.append( '.' ); - } - str.append( part.getName() ) - .append( '(' ) - .append( paramsToString( part.getParams() ) ) - .append( ')' ); - moveNext( part ); - } - - public void visit( ExpressionVariable part ) { - if ( !first ) { - str.append( '.' ); - } - str.append( part.getName() ); - moveNext( part ); - } - - public void visit( ExpressionUnboundFact part ) { - moveNext( part, - false ); - } - - public void visit( ExpressionGlobalVariable part ) { - if ( !first ) { - str.append( '.' ); - } - str.append( part.getName() ); - moveNext( part ); - } - - public void visit( ExpressionCollection part ) { - if ( !first ) { - str.append( '.' ); - } - str.append( part.getName() ); - moveNext( part ); - } - - public void visit( ExpressionCollectionIndex part ) { - str.append( '[' ).append( paramsToString( part.getParams() ) ).append( ']' ); - moveNext( part ); - } - - public void visit( ExpressionText part ) { - if ( !first ) { - str.append( '.' ); - } - str.append( part.getName() ); - moveNext( part ); - } - - private String paramsToString( Map params ) { - if ( params.isEmpty() ) { - return ""; - } - ToStringVisitor stringVisitor = new ToStringVisitor(); - StringBuilder strParams = new StringBuilder(); - for ( ExpressionFormLine param : params.values() ) { - strParams.append( ", " ).append( stringVisitor.buildString( param.getBinding(), - param.getRootExpression() ) ); - } - return strParams.substring( 2 ); - } - - private void moveNext( ExpressionPart exp ) { - moveNext( exp, - true ); - } - - private void moveNext( ExpressionPart exp, - boolean resetFirst ) { - if ( exp.getNext() != null ) { - if ( resetFirst ) { - first = false; - } - exp.getNext().accept( this ); - } - } - } } diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethod.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethod.java index a7949010ba9..05c3816c6e0 100644 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethod.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethod.java @@ -16,7 +16,11 @@ package org.drools.workbench.models.datamodel.rule; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class ExpressionMethod extends ExpressionPart { @@ -29,14 +33,19 @@ public ExpressionMethod() { public ExpressionMethod( String methodName, String returnClassType, String returnGenericType ) { - super( methodName, returnClassType, returnGenericType ); + super( methodName, + returnClassType, + returnGenericType ); } public ExpressionMethod( String name, String classType, String genericType, String parametricType ) { - super( name, classType, genericType, parametricType ); + super( name, + classType, + genericType, + parametricType ); } public Map getParams() { @@ -49,19 +58,31 @@ public void setParams( Map params ) { public void putParam( String name, ExpressionFormLine expression ) { - this.params.put( name, expression ); + this.params.put( name, + expression ); } - protected String paramsToString() { - if ( params.isEmpty() ) { - return ""; - } - String sep = ", "; - StringBuilder s = new StringBuilder(); - for ( ExpressionFormLine expr : params.values() ) { - s.append( sep ).append( expr.getText() ); + public List getOrderedParams() { + final List orderedParams = new ArrayList(); + orderedParams.addAll( params.values() ); + Collections.sort( orderedParams, + new Comparator() { + @Override + public int compare( final ExpressionFormLine o1, + final ExpressionFormLine o2 ) { + return o1.getIndex() - o2.getIndex(); + } + } ); + return orderedParams; + } + + public String getParameterDataType( final ExpressionFormLine efl ) { + for ( Map.Entry e : params.entrySet() ) { + if ( e.getValue().equals( efl ) ) { + return e.getKey(); + } } - return s.substring( sep.length() ); + return null; } @Override diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethodParameter.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethodParameter.java new file mode 100644 index 00000000000..70b39d0e9e7 --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionMethodParameter.java @@ -0,0 +1,54 @@ +/* + * Copyright 2014 JBoss Inc + * + * 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.datamodel.rule; + +/** + * ExpressionPart representing a ExpressionMethod parameter + */ +public class ExpressionMethodParameter extends ExpressionPart { + + public ExpressionMethodParameter() { + } + + public ExpressionMethodParameter( String name, + String classType, + String genericType ) { + super( name, + classType, + genericType ); + } + + public ExpressionMethodParameter( String name, + String classType, + String genericType, + String parametricType ) { + super( name, + classType, + genericType, + parametricType ); + } + + public void setText( final String text ) { + this.name = text; + } + + @Override + public void accept( ExpressionVisitor visitor ) { + visitor.visit( this ); + } + +} diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionText.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionText.java index 524e33df905..b0272906aa9 100644 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionText.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionText.java @@ -23,22 +23,22 @@ public class ExpressionText extends ExpressionPart { public ExpressionText() { } - public ExpressionText( final String name, + public ExpressionText( final String text, final String classType, final String genericType ) { - super( name, + super( text, classType, genericType ); } - public ExpressionText( final String name ) { - super( name, + public ExpressionText( final String text ) { + super( text, "java.lang.String", DataType.TYPE_STRING ); } - public void setName( final String name ) { - this.name = name; + public void setText( final String text ) { + this.name = text; } @Override diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionVisitor.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionVisitor.java index 5c69554593e..c3fd132416c 100644 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionVisitor.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/ExpressionVisitor.java @@ -34,5 +34,8 @@ public interface ExpressionVisitor { void visit( ExpressionText part ); + void visit( ExpressionMethodParameter part ); + void visit( ExpressionUnboundFact part ); + } diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/DRLConstraintValueBuilder.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/DRLConstraintValueBuilder.java similarity index 93% rename from drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/DRLConstraintValueBuilder.java rename to drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/DRLConstraintValueBuilder.java index 22e44571305..baea314e68e 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/DRLConstraintValueBuilder.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/DRLConstraintValueBuilder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.drools.workbench.models.commons.backend.rule; +package org.drools.workbench.models.datamodel.rule.builder; /** * A Helper class for building parts of DRL from higher-order representations @@ -22,8 +22,10 @@ */ public abstract class DRLConstraintValueBuilder { + public static final String DEFAULT_DIALECT = "mvel"; + public static DRLConstraintValueBuilder getBuilder( String dialect ) { - if ( RuleModelDRLPersistenceImpl.DEFAULT_DIALECT.equalsIgnoreCase( dialect ) ) { + if ( DEFAULT_DIALECT.equalsIgnoreCase( dialect ) ) { return new MvelDRLConstraintValueBuilder(); } return new JavaDRLConstraintValueBuilder(); diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/JavaDRLConstraintValueBuilder.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/JavaDRLConstraintValueBuilder.java similarity index 98% rename from drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/JavaDRLConstraintValueBuilder.java rename to drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/JavaDRLConstraintValueBuilder.java index 32f2f30899a..4fda9d0b037 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/JavaDRLConstraintValueBuilder.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/JavaDRLConstraintValueBuilder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.drools.workbench.models.commons.backend.rule; +package org.drools.workbench.models.datamodel.rule.builder; import org.drools.workbench.models.datamodel.oracle.DataType; diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/MvelDRLConstraintValueBuilder.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/MvelDRLConstraintValueBuilder.java similarity index 99% rename from drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/MvelDRLConstraintValueBuilder.java rename to drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/MvelDRLConstraintValueBuilder.java index bfb6e0d2cc6..32cc4c2e7d4 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/MvelDRLConstraintValueBuilder.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/builder/MvelDRLConstraintValueBuilder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.drools.workbench.models.commons.backend.rule; +package org.drools.workbench.models.datamodel.rule.builder; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/CopyExpressionVisitor.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/CopyExpressionVisitor.java new file mode 100644 index 00000000000..13985fa4f6e --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/CopyExpressionVisitor.java @@ -0,0 +1,151 @@ +/* + * Copyright 2014 JBoss Inc + * + * 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.datamodel.rule.visitors; + +import java.util.HashMap; +import java.util.Map; + +import org.drools.workbench.models.datamodel.rule.ExpressionCollection; +import org.drools.workbench.models.datamodel.rule.ExpressionCollectionIndex; +import org.drools.workbench.models.datamodel.rule.ExpressionField; +import org.drools.workbench.models.datamodel.rule.ExpressionFormLine; +import org.drools.workbench.models.datamodel.rule.ExpressionGlobalVariable; +import org.drools.workbench.models.datamodel.rule.ExpressionMethod; +import org.drools.workbench.models.datamodel.rule.ExpressionMethodParameter; +import org.drools.workbench.models.datamodel.rule.ExpressionPart; +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.ExpressionVisitor; + +public class CopyExpressionVisitor implements ExpressionVisitor { + + private ExpressionPart root; + private ExpressionPart curr; + + public CopyExpressionVisitor() { + + } + + public ExpressionPart copy( ExpressionPart part ) { + root = null; + curr = null; + part.accept( this ); + return root; + } + + public void visit( ExpressionPart part ) { + throw new RuntimeException( "Can't copy an abstract class: " + ExpressionPart.class.getName() ); + } + + public void visit( ExpressionField part ) { + add( new ExpressionField( part.getName(), + part.getClassType(), + part.getGenericType(), + part.getParametricType() ) ); + moveNext( part ); + } + + public void visit( ExpressionMethod part ) { + ExpressionMethod method = new ExpressionMethod( part.getName(), + part.getClassType(), + part.getGenericType(), + part.getParametricType() ); + copyMethodParams( part, + method ); + add( method ); + moveNext( part ); + } + + public void visit( ExpressionVariable part ) { + add( new ExpressionVariable( part.getFact() ) ); + moveNext( part ); + } + + public void visit( ExpressionUnboundFact part ) { + add( new ExpressionUnboundFact( part.getFact() ) ); + moveNext( part ); + } + + public void visit( ExpressionCollection part ) { + add( new ExpressionCollection( part.getName(), + part.getClassType(), + part.getGenericType(), + part.getParametricType() ) ); + moveNext( part ); + } + + public void visit( ExpressionCollectionIndex part ) { + ExpressionCollectionIndex method = new ExpressionCollectionIndex( part.getName(), + part.getClassType(), + part.getGenericType(), + part.getParametricType() ); + copyMethodParams( part, + method ); + add( method ); + moveNext( part ); + } + + public void visit( ExpressionText part ) { + add( new ExpressionText( part.getName(), + part.getClassType(), + part.getGenericType() ) ); + moveNext( part ); + } + + @Override + public void visit( ExpressionMethodParameter part ) { + add( new ExpressionMethodParameter( part.getName(), + part.getClassType(), + part.getGenericType() ) ); + moveNext( part ); + } + + public void visit( ExpressionGlobalVariable part ) { + add( new ExpressionGlobalVariable( part.getName(), + part.getClassType(), + part.getGenericType(), + part.getParametricType() ) ); + moveNext( part ); + + } + + private void copyMethodParams( ExpressionMethod part, + ExpressionMethod method ) { + Map params = new HashMap(); + for ( Map.Entry entry : part.getParams().entrySet() ) { + params.put( entry.getKey(), new ExpressionFormLine( entry.getValue() ) ); + } + method.setParams( params ); + } + + private void moveNext( ExpressionPart ep ) { + if ( ep.getNext() != null ) { + ep.getNext().accept( this ); + } + } + + private void add( ExpressionPart p ) { + if ( root == null ) { + root = p; + curr = p; + } else { + curr.setNext( p ); + curr = p; + } + } + +} diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/RuleModelVisitor.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/RuleModelVisitor.java similarity index 86% rename from drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/RuleModelVisitor.java rename to drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/RuleModelVisitor.java index 8a73fc62495..11045f3a6ad 100644 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/RuleModelVisitor.java +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/RuleModelVisitor.java @@ -13,13 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.drools.workbench.models.datamodel.rule; - -import org.drools.workbench.models.datamodel.oracle.DataType; -import org.drools.workbench.models.datamodel.oracle.DataType; +package org.drools.workbench.models.datamodel.rule.visitors; import java.util.Map; +import org.drools.workbench.models.datamodel.oracle.DataType; +import org.drools.workbench.models.datamodel.rule.ActionFieldValue; +import org.drools.workbench.models.datamodel.rule.ActionInsertFact; +import org.drools.workbench.models.datamodel.rule.ActionSetField; +import org.drools.workbench.models.datamodel.rule.ActionUpdateField; +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.DSLSentence; +import org.drools.workbench.models.datamodel.rule.FactPattern; +import org.drools.workbench.models.datamodel.rule.FieldConstraint; +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.IAction; +import org.drools.workbench.models.datamodel.rule.IFactPattern; +import org.drools.workbench.models.datamodel.rule.IPattern; +import org.drools.workbench.models.datamodel.rule.InterpolationVariable; +import org.drools.workbench.models.datamodel.rule.RuleModel; +import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; +import org.drools.workbench.models.datamodel.rule.SingleFieldConstraintEBLeftSide; + /** * A Rule Model Visitor to extract Interpolation Variables (Template Keys) */ @@ -200,7 +222,8 @@ private void visitFromCollectCompositeFactPattern( FromCollectCompositeFactPatte private void visitFromCompositeFactPattern( FromCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); - parseStringPattern( pattern.getExpression().getText() ); + ToStringExpressionVisitor visitor = new ToStringExpressionVisitor( pattern.getExpression().getBinding() ); + parseStringPattern( pattern.getExpression().getText( visitor ) ); } private void visitRuleModel( RuleModel model ) { diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/ToStringExpressionVisitor.java b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/ToStringExpressionVisitor.java new file mode 100644 index 00000000000..f719f7e34f5 --- /dev/null +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/java/org/drools/workbench/models/datamodel/rule/visitors/ToStringExpressionVisitor.java @@ -0,0 +1,171 @@ +/* + * Copyright 2014 JBoss Inc + * + * 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.datamodel.rule.visitors; + +import java.util.List; + +import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; +import org.drools.workbench.models.datamodel.rule.ExpressionCollection; +import org.drools.workbench.models.datamodel.rule.ExpressionCollectionIndex; +import org.drools.workbench.models.datamodel.rule.ExpressionField; +import org.drools.workbench.models.datamodel.rule.ExpressionFormLine; +import org.drools.workbench.models.datamodel.rule.ExpressionGlobalVariable; +import org.drools.workbench.models.datamodel.rule.ExpressionMethod; +import org.drools.workbench.models.datamodel.rule.ExpressionMethodParameter; +import org.drools.workbench.models.datamodel.rule.ExpressionPart; +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.ExpressionVisitor; +import org.drools.workbench.models.datamodel.rule.builder.DRLConstraintValueBuilder; + +/** + * A visitor that can emit a String representing the Expression + */ +public class ToStringExpressionVisitor implements + ExpressionVisitor { + + private StringBuilder sb; + private String bindVariable; + private DRLConstraintValueBuilder constraintValueBuilder; + private boolean first; + + public ToStringExpressionVisitor( final String bindVariable ) { + this( bindVariable, + DRLConstraintValueBuilder.getBuilder( DRLConstraintValueBuilder.DEFAULT_DIALECT ) ); + } + + public ToStringExpressionVisitor( final String bindVariable, + final DRLConstraintValueBuilder constraintValueBuilder ) { + this.bindVariable = bindVariable; + this.constraintValueBuilder = constraintValueBuilder; + } + + public void visit( ExpressionPart part ) { + if ( part == null ) { + return; + } + sb = new StringBuilder(); + first = true; + part.accept( this ); + } + + public void visit( ExpressionField part ) { + if ( !first ) { + sb.append( '.' ); + } + sb.append( part.getName() ); + moveNext( part ); + } + + public void visit( ExpressionMethod part ) { + if ( !first ) { + sb.append( '.' ); + } + sb.append( part.getName() ) + .append( '(' ) + .append( paramsToString( part.getOrderedParams() ) ) + .append( ')' ); + moveNext( part ); + } + + public void visit( ExpressionVariable part ) { + if ( !first ) { + sb.append( '.' ); + } + sb.append( part.getName() ); + moveNext( part ); + } + + public void visit( ExpressionUnboundFact part ) { + moveNext( part, + false ); + } + + public void visit( ExpressionGlobalVariable part ) { + if ( !first ) { + sb.append( '.' ); + } + sb.append( part.getName() ); + moveNext( part ); + } + + public void visit( ExpressionCollection part ) { + if ( !first ) { + sb.append( '.' ); + } + sb.append( part.getName() ); + moveNext( part ); + } + + public void visit( ExpressionCollectionIndex part ) { + sb.append( '[' ).append( paramsToString( part.getOrderedParams() ) ).append( ']' ); + moveNext( part ); + } + + public void visit( ExpressionText part ) { + if ( !first ) { + sb.append( '.' ); + } + sb.append( part.getName() ); + moveNext( part ); + } + + public void visit( ExpressionMethodParameter part ) { + if ( !first ) { + sb.append( '.' ); + } + constraintValueBuilder.buildLHSFieldValue( sb, + BaseSingleFieldConstraint.TYPE_LITERAL, + part.getClassType(), + part.getName() ); + moveNext( part ); + } + + public String getText() { + return ( bindVariable == null ? "" : bindVariable + ": " ) + sb.toString(); + } + + private String paramsToString( List params ) { + if ( params.isEmpty() ) { + return ""; + } + StringBuilder strParams = new StringBuilder(); + for ( ExpressionFormLine param : params ) { + ToStringExpressionVisitor visitor = new ToStringExpressionVisitor( param.getBinding(), + constraintValueBuilder ); + visitor.visit( param.getRootExpression() ); + strParams.append( ", " ).append( visitor.getText() ); + } + return strParams.substring( 2 ); + } + + private void moveNext( ExpressionPart exp ) { + moveNext( exp, + true ); + } + + private void moveNext( ExpressionPart exp, + boolean resetFirst ) { + if ( exp.getNext() != null ) { + if ( resetFirst ) { + first = false; + } + exp.getNext().accept( this ); + } + } +} + diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/resources/ErraiApp.properties b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/resources/ErraiApp.properties index 4458c85f291..c404611a808 100644 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/resources/ErraiApp.properties +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/src/main/resources/ErraiApp.properties @@ -61,6 +61,7 @@ errai.marshalling.serializableTypes=org.drools.workbench.models.datamodel.auditl org.drools.workbench.models.datamodel.rule.SingleFieldConstraint \ org.drools.workbench.models.datamodel.rule.ActionFieldValue \ org.drools.workbench.models.datamodel.rule.ExpressionMethod \ + org.drools.workbench.models.datamodel.rule.ExpressionMethodParameter \ org.drools.workbench.models.datamodel.rule.ExpressionVariable \ org.drools.workbench.models.datamodel.rule.FromCollectCompositeFactPattern \ org.drools.workbench.models.datamodel.rule.FromEntryPointFactPattern \ @@ -72,9 +73,7 @@ errai.marshalling.serializableTypes=org.drools.workbench.models.datamodel.auditl org.drools.workbench.models.datamodel.rule.CEPWindow \ org.drools.workbench.models.datamodel.rule.DSLComplexVariableValue \ org.drools.workbench.models.datamodel.rule.ExpressionCollection \ - org.drools.workbench.models.datamodel.rule.RuleModelVisitor \ org.drools.workbench.models.datamodel.rule.ExpressionFormLine \ - org.drools.workbench.models.datamodel.rule.ExpressionFormLine$ToStringVisitor \ org.drools.workbench.models.datamodel.rule.RuleModel \ org.drools.workbench.models.datamodel.rule.ActionGlobalCollectionAdd \ org.drools.workbench.models.datamodel.rule.RuleMetadata \ @@ -84,10 +83,11 @@ errai.marshalling.serializableTypes=org.drools.workbench.models.datamodel.auditl org.drools.workbench.models.datamodel.rule.FreeFormLine \ org.drools.workbench.models.datamodel.rule.InterpolationVariable \ org.drools.workbench.models.datamodel.rule.ExpressionFieldVariable \ - org.drools.workbench.models.datamodel.rule.CopyExpressionVisitor \ org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint \ org.drools.workbench.models.datamodel.rule.ConnectiveConstraint \ org.drools.workbench.models.datamodel.rule.ActionFieldFunction \ + org.drools.workbench.models.datamodel.rule.visitors.RuleModelVisitor \ + org.drools.workbench.models.datamodel.rule.visitors.CopyExpressionVisitor \ org.drools.workbench.models.datamodel.workitems.PortableObjectParameterDefinition \ org.drools.workbench.models.datamodel.workitems.PortableListParameterDefinition \ org.drools.workbench.models.datamodel.workitems.PortableFloatParameterDefinition \ diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java index 15366d4bd21..ab48a1cad91 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/GuidedDTDRLPersistence.java @@ -44,7 +44,7 @@ import org.drools.workbench.models.datamodel.rule.RuleAttribute; import org.drools.workbench.models.datamodel.rule.RuleMetadata; import org.drools.workbench.models.datamodel.rule.RuleModel; -import org.drools.workbench.models.datamodel.rule.RuleModelVisitor; +import org.drools.workbench.models.datamodel.rule.visitors.RuleModelVisitor; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; import org.drools.workbench.models.guided.dtable.backend.util.GuidedDTBRDRLPersistence; import org.drools.workbench.models.guided.dtable.backend.util.GuidedDTDRLOtherwiseHelper; diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java index 596e038f6ae..7e508c87abf 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java @@ -20,7 +20,6 @@ import java.util.regex.Pattern; import org.drools.core.util.StringUtils; -import org.drools.workbench.models.commons.backend.rule.DRLConstraintValueBuilder; import org.drools.workbench.models.commons.backend.rule.RuleModelDRLPersistenceImpl; import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContext; import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContextFactory; @@ -35,6 +34,7 @@ import org.drools.workbench.models.datamodel.rule.FromCollectCompositeFactPattern; import org.drools.workbench.models.datamodel.rule.IFactPattern; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; +import org.drools.workbench.models.datamodel.rule.builder.DRLConstraintValueBuilder; /** * A specialised implementation of BRDELPersistence that can expand Template diff --git a/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java b/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java index 02a863e51e4..a39e67087e3 100644 --- a/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java +++ b/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java @@ -27,7 +27,6 @@ import org.drools.template.DataProvider; import org.drools.template.DataProviderCompiler; import org.drools.template.objects.ArrayDataProvider; -import org.drools.workbench.models.commons.backend.rule.DRLConstraintValueBuilder; import org.drools.workbench.models.commons.backend.rule.RuleModelDRLPersistenceImpl; import org.drools.workbench.models.commons.backend.rule.RuleModelPersistence; import org.drools.workbench.models.commons.backend.rule.context.LHSGeneratorContext; @@ -47,6 +46,7 @@ import org.drools.workbench.models.datamodel.rule.InterpolationVariable; import org.drools.workbench.models.datamodel.rule.RuleModel; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; +import org.drools.workbench.models.datamodel.rule.builder.DRLConstraintValueBuilder; import org.drools.workbench.models.guided.template.shared.TemplateModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/shared/TemplateModel.java b/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/shared/TemplateModel.java index 38bd7eb755f..3913893aecf 100644 --- a/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/shared/TemplateModel.java +++ b/drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/shared/TemplateModel.java @@ -25,7 +25,7 @@ import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.rule.InterpolationVariable; import org.drools.workbench.models.datamodel.rule.RuleModel; -import org.drools.workbench.models.datamodel.rule.RuleModelVisitor; +import org.drools.workbench.models.datamodel.rule.visitors.RuleModelVisitor; public class TemplateModel extends RuleModel { From 9bd2cb41e236c1cc76d64cb128f75246d7e7a6fe Mon Sep 17 00:00:00 2001 From: sotty Date: Sun, 13 Jul 2014 14:58:20 +0100 Subject: [PATCH 41/76] [DROOLS-549] Queries in the default package are built twice (cherry picked from commit ebf7f1dcc85a0a98e41f6bd5ea43cf6e17e80fb7) --- .../drools/compiler/rule/builder/PatternBuilder.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/PatternBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/PatternBuilder.java index 341bf04c05e..ab11e4df573 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/PatternBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/PatternBuilder.java @@ -206,8 +206,9 @@ public RuleConditionElement build( RuleBuildContext context, } if ( rce == null ) { + // look up the query in the current package RuleImpl rule = context.getPkg().getRule( patternDescr.getObjectType() ); - if ( rule instanceof QueryImpl) { + if ( rule instanceof QueryImpl ) { // it's a query so delegate to the QueryElementBuilder QueryElementBuilder qeBuilder = QueryElementBuilder.getInstance(); rce = qeBuilder.build( context, @@ -215,8 +216,10 @@ public RuleConditionElement build( RuleBuildContext context, prefixPattern, (QueryImpl) rule ); } + } - // try package imports + if ( rce == null ) { + // the query may have been imported, so try package imports for ( String importName : context.getDialect().getTypeResolver().getImports() ) { importName = importName.trim(); int pos = importName.indexOf( '*' ); @@ -225,7 +228,7 @@ public RuleConditionElement build( RuleBuildContext context, pos - 1 ); PackageRegistry pkgReg = context.getKnowledgeBuilder().getPackageRegistry( pkgName ); if ( pkgReg != null ) { - rule = pkgReg.getPackage().getRule( patternDescr.getObjectType() ); + RuleImpl rule = pkgReg.getPackage().getRule( patternDescr.getObjectType() ); if ( rule instanceof QueryImpl) { // it's a query so delegate to the QueryElementBuilder QueryElementBuilder qeBuilder = QueryElementBuilder.getInstance(); @@ -238,7 +241,6 @@ public RuleConditionElement build( RuleBuildContext context, } } } - } if ( rce == null ) { From 6d378ebb9aedac27528cac99a425e6e7f7efd306 Mon Sep 17 00:00:00 2001 From: sotty Date: Sun, 13 Jul 2014 14:59:40 +0100 Subject: [PATCH 42/76] [DROOLS-547] Queries should check the type of input arguments (cherry picked from commit 0eb43be028e455ccc175fd739abc554f7c96fa67) --- .../rule/builder/QueryElementBuilder.java | 95 ++++++++++++++++++- .../compiler/integrationtests/QueryTest.java | 68 ++++++++++++- 2 files changed, 161 insertions(+), 2 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java index bc33d00919a..0021a49bf1b 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java @@ -204,6 +204,23 @@ public RuleConditionElement build( RuleBuildContext context, varIndexesArray[i] = varIndexes.get( i ); } + for ( Integer declIndex : declrIndexes ) { + Declaration knownInputArg = (Declaration) arguments.get( declIndex ); + Declaration formalArgument = query.getParameters()[ declIndex ]; + Class actual = knownInputArg.getExtractor().getExtractToClass(); + Class formal = formalArgument.getExtractor().getExtractToClass(); + + // with queries invoking each other, we won't know until runtime whether a declaration is input, output or else + // input argument require a broader type, while output types require a narrower type, so we check for both. + if ( ! isCompatible( actual, formal ) && ! isCompatible( formal, actual ) ) { + context.addError( new DescrBuildError( context.getParentDescr(), + descr, + null, + "Query is being invoked with known argument of type " + actual + + " at position " + declIndex + ", but the expected query argument is of type " + formal ) ); + } + } + return new QueryElement( pattern, query.getName(), arguments.toArray( new Object[arguments.size()] ), @@ -214,6 +231,82 @@ public RuleConditionElement build( RuleBuildContext context, query.isAbductive() ); } + // FIXME : These methods do not belong here, but where? + private boolean isCompatible( Class actual, Class formal ) { + if ( actual.isPrimitive() && formal.isPrimitive() ) { + return isConvertible( actual, formal ); + } else if ( actual.isPrimitive() ) { + return isConvertible( actual, unbox( formal ) ); + } else if ( formal.isPrimitive() ) { + return isConvertible( unbox( actual ), formal ); + } else { + return formal.isAssignableFrom( actual ); + } + } + + private boolean isConvertible( Class srcPrimitive, Class tgtPrimitive ) { + if ( Boolean.TYPE.equals( srcPrimitive ) ) { + return Boolean.TYPE.equals( tgtPrimitive ); + } else if ( Byte.TYPE.equals( tgtPrimitive ) ) { + return Byte.TYPE.equals( tgtPrimitive ) + || Short.TYPE.equals( tgtPrimitive ) + || Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Character.TYPE.equals( srcPrimitive ) ) { + return Character.TYPE.equals( tgtPrimitive ) + || Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Double.TYPE.equals( srcPrimitive ) ) { + return Double.TYPE.equals( tgtPrimitive ); + } else if ( Float.TYPE.equals( srcPrimitive ) ) { + return Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Integer.TYPE.equals( srcPrimitive ) ) { + return Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Long.TYPE.equals( srcPrimitive ) ) { + return Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Short.TYPE.equals( srcPrimitive ) ) { + return Short.TYPE.equals( tgtPrimitive ) + || Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } + return false; + } + + private Class unbox( Class boxed ) { + if ( Boolean.class.equals( boxed ) ) { + return Boolean.TYPE; + } else if ( Byte.class.equals( boxed ) ) { + return Byte.TYPE; + } else if ( Character.class.equals( boxed ) ) { + return Character.TYPE; + } else if ( Double.class.equals( boxed ) ) { + return Double.TYPE; + } else if ( Float.class.equals( boxed ) ) { + return Float.TYPE; + } else if ( Integer.class.equals( boxed ) ) { + return Integer.TYPE; + } else if ( Long.class.equals( boxed ) ) { + return Long.TYPE; + } else if ( Short.class.equals( boxed ) ) { + return Short.TYPE; + } else if ( Number.class.equals( boxed ) ) { + return Double.TYPE; + } + return boxed; + } + @SuppressWarnings("unchecked") private void processBinding( RuleBuildContext context, BaseDescr descr, @@ -336,7 +429,7 @@ private void processPositional( RuleBuildContext context, context.addError( new DescrBuildError( context.getParentDescr(), base, null, - "Unable to parse query '" + query.getName() + "', as postion " + (position-1) + " for expression '" + expression + "' does not exist on query size " + arguments.size()) ); + "Unable to parse query '" + query.getName() + "', as postion " + position + " for expression '" + expression + "' does not exist on query size " + arguments.size()) ); return; } if ( isVariable( expression ) ) { diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java index 59809e3ca64..914e72cdfba 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java @@ -23,7 +23,11 @@ import org.drools.core.util.ObjectHashMap.ObjectEntry; import org.drools.core.util.ObjectHashSet; import org.junit.Test; +import org.kie.api.KieServices; +import org.kie.api.builder.Message; +import org.kie.api.builder.Results; import org.kie.api.definition.rule.Rule; +import org.kie.api.io.ResourceType; import org.kie.api.runtime.conf.QueryListenerOption; import org.kie.api.runtime.rule.FactHandle; import org.kie.api.runtime.rule.LiveQuery; @@ -35,6 +39,7 @@ import org.kie.internal.KnowledgeBase; import org.kie.internal.builder.conf.RuleEngineOption; import org.kie.internal.runtime.StatefulKnowledgeSession; +import org.kie.internal.utils.KieHelper; import java.io.IOException; import java.util.ArrayList; @@ -580,7 +585,7 @@ public void testQueriesWithVariableUnificationOnNestedFields() throws Exception org.kie.api.runtime.rule.QueryResults results = ksession.getQueryResults( "peeps", new Object[]{Variable.v, Variable.v, Variable.v} ); assertEquals( 2, - results.size() ); + results.size() ); List names = new ArrayList(); for ( org.kie.api.runtime.rule.QueryResultsRow row : results ) { names.add( ((Person) row.get( "$p" )).getName() ); @@ -876,4 +881,65 @@ public void testQueryWithEval() throws IOException, ClassNotFoundException { ksession.dispose(); } + @Test + public void testQueryWithIncompatibleArgs() { + String drl = "global java.util.List list; " + + "" + + "query foo( String $s, String $s, String $s ) end " + + "" + + "rule React \n" + + "when\n" + + " $i : Integer() " + + " foo( $i, $x, $i ; ) " + + "then\n" + + "end"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + Results results = helper.verify(); + assertTrue( results.hasMessages( Message.Level.ERROR ) ); + assertEquals( 2, results.getMessages( Message.Level.ERROR ).size() ); + } + + @Test + public void testQueryWithSyntaxError() { + String drl = "global java.util.List list; " + + "" + + "query foo( Integer $i ) end " + + "" + + "rule React \n" + + "when\n" + + " $i : Integer() " + + " foo( $i ) " + // missing ";" should result in 1 compilation error + "then\n" + + "end"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + Results results = helper.verify(); + assertTrue( results.hasMessages( Message.Level.ERROR ) ); + assertEquals( 1, results.getMessages( Message.Level.ERROR ).size() ); + } + + @Test + public void testQueryWithWrongParamNumber() { + String drl = "global java.util.List list; " + + "" + + "query foo( Integer $i ) end " + + "" + + "rule React \n" + + "when\n" + + " $i : Integer() " + + " $j : Integer() " + + " foo( $i, $j ; ) " + + "then\n" + + "end"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + Results results = helper.verify(); + assertTrue( results.hasMessages( Message.Level.ERROR ) ); + assertEquals( 1, results.getMessages( Message.Level.ERROR ).size() ); + } + } From 24f8c5c916ec5f4c221527a2243d5f4606e1d335 Mon Sep 17 00:00:00 2001 From: sotty Date: Tue, 15 Jul 2014 02:48:14 +0100 Subject: [PATCH 43/76] [DROOLS-555] Support both static and dynamic trait interfaces on the same object (cherry picked from commit a475dfd09e05528c6ee9dbf845cce780f268dfc5) --- .../impl/CompositeKnowledgeBuilderImpl.java | 8 +- .../builder/impl/TypeDeclarationBuilder.java | 107 +++++++++++++---- .../factmodel/traits/LegacyTraitTest.java | 111 +++++++++++++++++- .../factmodel/traits/StudentProxy2.java | 3 +- .../core/base/DefaultKnowledgeHelper.java | 29 ++++- .../java/org/drools/core/base/ValueType.java | 3 +- .../core/factmodel/traits/TraitRegistry.java | 84 ++++++++++++- .../core/factmodel/traits/TraitTypeMap.java | 34 ++++++ .../core/reteoo/TraitObjectTypeNode.java | 1 - .../java/org/drools/core/util/ClassUtils.java | 22 ++++ .../core/util/HierarchyEncoderImpl.java | 2 +- 11 files changed, 367 insertions(+), 37 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java index 3678c73e822..089cdeb71ce 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java @@ -319,9 +319,11 @@ private void buildTypeDeclarations(Collection packages) { // now we need to sort TypeDeclarations based on the mutual, cross-package dependencies. // This can't be done at the beginning, before the build pass, since the names are not yet fully qualified there. // TODO there may be more efficient ways to do it (?) - int j = 0; - for ( AbstractClassTypeDeclarationDescr descr : TypeDeclarationBuilder.sortByHierarchy( kBuilder, allDescrs ) ) { - kBuilder.getPackageRegistry( descr.getNamespace() ).getPackage().getTypeDeclaration( descr.getTypeName() ).setOrder( j++ ); + if ( ! kBuilder.hasErrors() ) { + int j = 0; + for ( AbstractClassTypeDeclarationDescr descr : TypeDeclarationBuilder.sortByHierarchy( kBuilder, allDescrs ) ) { + kBuilder.getPackageRegistry( descr.getNamespace() ).getPackage().getTypeDeclaration( descr.getTypeName() ).setOrder( j++ ); + } } for (CompositePackageDescr packageDescr : packages) { diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java index ff80d3c9480..9929f109896 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java @@ -543,13 +543,15 @@ public void fillFieldTypes( AbstractClassTypeDeclarationDescr typeDescr, * * * + * * @param typeDescr * The base class descriptor, to be completed with the inherited * fields descriptors * @param unprocessableDescrs + * @param typeResolver * @return true if all went well */ - private boolean mergeInheritedFields( TypeDeclarationDescr typeDescr, List unresolvedTypes, Map unprocessableDescrs ) { + private boolean mergeInheritedFields( TypeDeclarationDescr typeDescr, List unresolvedTypes, Map unprocessableDescrs, TypeResolver typeResolver ) { if (typeDescr.getSuperTypes().isEmpty()) return false; @@ -561,36 +563,41 @@ private boolean mergeInheritedFields( TypeDeclarationDescr typeDescr, List unresolvedTypes, - Map unprocessableDescrs ) { + private boolean mergeFields( String simpleSuperTypeName, + String superTypePackageName, + String fullSuper, + TypeDeclarationDescr typeDescr, + List unresolvedTypes, + Map unprocessableDescrs, + TypeResolver resolver ) { Map fieldMap = new LinkedHashMap(); + boolean isNovel = isNovelClass( typeDescr ); PackageRegistry registry = kbuilder.getPackageRegistry(superTypePackageName); - InternalKnowledgePackage pack; + InternalKnowledgePackage pack = null; if (registry != null) { pack = registry.getPackage(); } else { // If there is no regisrty the type isn't a DRL-declared type, which is forbidden. // Avoid NPE JIRA-3041 when trying to access the registry. Avoid subsequent problems. // DROOLS-536 At this point, the declarations might exist, but the package might not have been processed yet - unprocessableDescrs.put( typeDescr.getType().getFullName(), typeDescr ); - return false; + if ( isNovel ) { + unprocessableDescrs.put( typeDescr.getType().getFullName(), typeDescr ); + return false; + } } if ( unprocessableDescrs.containsKey( fullSuper ) ) { @@ -636,9 +643,15 @@ private boolean mergeInheritedFields( String simpleSuperTypeName, } // look for the class externally - if (!isSuperClassDeclared || isSuperClassTagged) { + if ( !isSuperClassDeclared || isSuperClassTagged ) { try { - Class superKlass = registry.getTypeResolver().resolveType(fullSuper); + Class superKlass; + if ( registry != null ) { + superKlass = registry.getTypeResolver().resolveType(fullSuper); + } else { + // if the supertype has not been declared, and we have got so far, it means that this class is not novel + superKlass = resolver.resolveType( fullSuper ); + } ClassFieldInspector inspector = new ClassFieldInspector(superKlass); for (String name : inspector.getGetterMethods().keySet()) { // classFieldAccessor requires both getter and setter @@ -1038,6 +1051,10 @@ List processTypeDeclarations( PackageRegistry pkgRegistry, Packa if (typeDescr instanceof TypeDeclarationDescr) { fillSuperType((TypeDeclarationDescr) typeDescr, packageDescr); + AnnotationDescr kind = typeDescr.getAnnotation( TypeDeclaration.Kind.ID ); + if ( typeClass != null && kind != null && kind.hasValue() && TypeDeclaration.Kind.TRAIT == TypeDeclaration.Kind.parseKind( kind.getSingleValue() ) ) { + fillStaticInterfaces( (TypeDeclarationDescr) typeDescr, typeClass ); + } } //identify field types as well @@ -1104,6 +1121,13 @@ List processTypeDeclarations( PackageRegistry pkgRegistry, Packa return unresolvedTypes; } + private void fillStaticInterfaces( TypeDeclarationDescr typeDescr, Class typeClass ) { + for ( Class iKlass : ClassUtils.getAllImplementedInterfaceNames( typeClass ) ) { + typeDescr.addSuperType( iKlass.getName() ); + } + + } + public void processTypeDeclaration( PackageRegistry pkgRegistry, AbstractClassTypeDeclarationDescr typeDescr, Collection sortedTypeDescriptors, @@ -1112,9 +1136,12 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, //descriptor needs fields inherited from superclass if (typeDescr instanceof TypeDeclarationDescr) { TypeDeclarationDescr tDescr = (TypeDeclarationDescr) typeDescr; + boolean isNovel = isNovelClass( typeDescr ); + boolean inferFields = ! isNovel && typeDescr.getFields().isEmpty(); + for (QualifiedName qname : tDescr.getSuperTypes()) { //descriptor needs fields inherited from superclass - if (mergeInheritedFields(tDescr, unresolvedTypes, unprocessableDescrs)) { + if (mergeInheritedFields(tDescr, unresolvedTypes, unprocessableDescrs, pkgRegistry.getTypeResolver())) { //descriptor also needs metadata from superclass for (AbstractClassTypeDeclarationDescr descr : sortedTypeDescriptors) { // sortedTypeDescriptors are sorted by inheritance order, so we'll always find the superClass (if any) before the subclass @@ -1128,6 +1155,33 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, } } } + + if ( inferFields ) { + // not novel, but only an empty declaration was provided. + // after inheriting the fields from supertypes, now we fill in the locally declared fields + try { + Class existingClass = getExistingDeclarationClass( typeDescr ); + ClassFieldInspector inspector = new ClassFieldInspector( existingClass ); + for (String name : inspector.getGetterMethods().keySet()) { + // classFieldAccessor requires both getter and setter + if (inspector.getSetterMethods().containsKey(name)) { + if (!inspector.isNonGetter(name) && !"class".equals(name)) { + TypeFieldDescr inheritedFlDescr = new TypeFieldDescr( + name, + new PatternDescr( + inspector.getFieldTypes().get(name).getName())); + inheritedFlDescr.setInherited(!Modifier.isAbstract(inspector.getGetterMethods().get(name).getModifiers())); + + if (!tDescr.getFields().containsKey(inheritedFlDescr.getFieldName())) + tDescr.getFields().put(inheritedFlDescr.getFieldName(), + inheritedFlDescr); + } + } + } + } catch ( Exception e ) { + // can't happen as we know that the class is not novel - that is, it has been resolved before + } + } } if ( unprocessableDescrs.containsKey( typeDescr.getType().getFullName() ) ) { @@ -1155,7 +1209,8 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, } } if (parent == null) { - kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Declared class " + typeDescr.getTypeName() + " can't extend class " + typeDescr.getSuperTypeName() + ", it should be declared")); + // FIXME Does this behavior still make sense? The need to redeclare an existing (java) class in order to be able to extend it... + // kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Declared class " + typeDescr.getTypeName() + " can't extend class " + typeDescr.getSuperTypeName() + ", it should be declared")); } else { if (parent.getNature() == TypeDeclaration.Nature.DECLARATION && kbuilder.getKnowledgeBase() != null) { // trying to find a definition @@ -1171,6 +1226,7 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, if (role != null) { type.setRole(TypeDeclaration.Role.parseRole(role)); } else if (parent != null) { + // FIXME : Should this be here, since Drools 6 does not namely support annotation inheritance? type.setRole(parent.getRole()); } @@ -1179,6 +1235,7 @@ public void processTypeDeclaration( PackageRegistry pkgRegistry, if (typesafe != null) { type.setTypesafe(Boolean.parseBoolean(typesafe)); } else if (parent != null && isSet(parent.getSetMask(), TypeDeclaration.TYPESAFE_BIT)) { + // FIXME : Should this be here, since Drools 6 does not namely support annotation inheritance? type.setTypesafe(parent.isTypesafe()); } @@ -1578,7 +1635,7 @@ private void generateDeclaredBean(AbstractClassTypeDeclarationDescr typeDescr, try { - if (!type.getTypeClassDef().getFields().isEmpty()) { + if ( type.isNovel() ) { //since the declaration defines one or more fields, it is a DEFINITION type.setNature(TypeDeclaration.Nature.DEFINITION); } else { @@ -1591,8 +1648,10 @@ private void generateDeclaredBean(AbstractClassTypeDeclarationDescr typeDescr, if (previousTypeDeclaration == null) { // new declarations of a POJO can't declare new fields, // except if the POJO was previously generated/compiled and saved into the kjar - if (!kbuilder.getBuilderConfiguration().isPreCompiled() && - !GeneratedFact.class.isAssignableFrom(existingDeclarationClass) && !type.getTypeClassDef().getFields().isEmpty()) { + if ( !kbuilder.getBuilderConfiguration().isPreCompiled() && + !GeneratedFact.class.isAssignableFrom(existingDeclarationClass) && + !type.getTypeClassDef().getFields().isEmpty() + ) { try { Class existingClass = pkgRegistry.getPackage().getTypeResolver().resolveType( typeDescr.getType().getFullName() ); ClassFieldInspector cfi = new ClassFieldInspector( existingClass ); @@ -2052,7 +2111,7 @@ private void updateTraitDefinition(TypeDeclaration type, Set interfaces = new HashSet(); Collections.addAll(interfaces, type.getTypeClassDef().getInterfaces()); - for (Class iKlass : concrete.getInterfaces()) { + for ( Class iKlass : ClassUtils.getAllImplementedInterfaceNames( concrete ) ) { interfaces.add(iKlass.getName()); } type.getTypeClassDef().setInterfaces(interfaces.toArray(new String[interfaces.size()])); diff --git a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java index 9ed3ddf75be..5b6d072d87b 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LegacyTraitTest.java @@ -2,9 +2,14 @@ package org.drools.compiler.factmodel.traits; +import org.drools.core.factmodel.traits.Trait; import org.drools.core.factmodel.traits.TraitFactory; +import org.drools.core.factmodel.traits.Traitable; import org.drools.core.factmodel.traits.VirtualPropertyMode; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.kie.api.definition.type.PropertyReactive; import org.kie.api.io.ResourceType; import org.kie.internal.KnowledgeBase; import org.kie.internal.KnowledgeBaseFactory; @@ -13,9 +18,31 @@ import org.kie.internal.io.ResourceFactory; import org.kie.internal.runtime.StatefulKnowledgeSession; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) public class LegacyTraitTest { + public VirtualPropertyMode mode; + + @Parameterized.Parameters + public static Collection modes() { + return Arrays.asList( new VirtualPropertyMode[][] + { + { VirtualPropertyMode.MAP }, + { VirtualPropertyMode.TRIPLES } + } ); + } + + public LegacyTraitTest( VirtualPropertyMode m ) { + this.mode = m; + } + + private StatefulKnowledgeSession getSessionFromString( String drl ) { KnowledgeBuilder knowledgeBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); @@ -148,7 +175,7 @@ public void traitWithPojoInterface() { "\n"; StatefulKnowledgeSession ks = getSessionFromString( source ); - TraitFactory.setMode( VirtualPropertyMode.MAP, ks.getKieBase() ); + TraitFactory.setMode( mode, ks.getKieBase() ); ExtendedProcedureImpl procedure1 = new ExtendedProcedureImpl(); ExtendedProcedureImpl procedure2 = new ExtendedProcedureImpl(); @@ -169,5 +196,87 @@ public void traitWithPojoInterface() { ks.fireAllRules( 500 ); } + + @Traitable + @PropertyReactive + public static class BarImpl implements Foo { + + } + + + + + public static interface Root { + + } + + public static interface Trunk extends Root { + + } + + @PropertyReactive + @Trait + public static interface Foo extends Trunk { + + } + + @Test + public void traitWithMixedInterfacesExtendingEachOther() { + String source = "package org.drools.compiler.test;" + + "import " + LegacyTraitTest.class.getName() + ".BarImpl; " + + "import " + LegacyTraitTest.class.getName() + ".Foo; " + + "import " + LegacyTraitTest.class.getName() + ".Trunk; " + + "global java.util.List list; " + + + // We need to redeclare the interfaces as traits, the annotation on the original class is not enough here + "declare trait Foo end " + + // notice that the declarations do not include supertypes, and are out of order. The engine will figure out what to do + "declare trait Root end " + + + "declare trait Foo2 extends Foo " + + " @propertyReactive " + + "end " + + + "rule 'Bar Don' " + + "when " + + " $b : BarImpl( this isA Foo.class, this not isA Foo2.class ) " + + "then " + + " list.add( 3 ); " + + " retract( $b ); " + + "end " + + + "rule 'Don Bar' " + + "no-loop " + + "when " + + " $b : Foo( ) " + + "then " + + " list.add( 1 ); " + + " don( $b, Foo2.class ); " + + "end " + + + "rule 'Cant really shed Foo but Foo2' " + + "when " + + " $b : Foo2() " + + "then " + + " list.add( 2 ); " + + " shed( $b, Foo.class ); " + + "end " + + + ""; + + StatefulKnowledgeSession ks = getSessionFromString( source ); + TraitFactory.setMode( mode, ks.getKieBase() ); + ArrayList list = new ArrayList(); + ks.setGlobal( "list", list ); + + ks.insert( new BarImpl() ); + + int n = ks.fireAllRules(); + + System.out.println( list ); + assertEquals( Arrays.asList( 1, 2, 3 ), list ); + assertEquals( 3, n ); + } + } diff --git a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/StudentProxy2.java b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/StudentProxy2.java index 824c9028c5c..6d0a40867f1 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/StudentProxy2.java +++ b/drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/StudentProxy2.java @@ -21,6 +21,7 @@ import org.drools.core.factmodel.traits.TraitableBean; import org.drools.core.spi.InternalReadAccessor; import org.drools.core.spi.WriteAccessor; +import org.drools.core.util.ExternalizableLinkedHashMap; import java.util.HashMap; import java.util.Map; @@ -55,7 +56,7 @@ public StudentProxy2(Imp2 obj, Map m) { } if ( obj._getTraitMap() == null ) { - obj._setTraitMap( new TraitTypeMap( new HashMap() ) ); + obj._setTraitMap( new TraitTypeMap( new ExternalizableLinkedHashMap() ) ); } } diff --git a/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java b/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java index 3c609a54b62..f9a0e47d8d9 100644 --- a/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java +++ b/drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java @@ -16,6 +16,8 @@ package org.drools.core.base; +import org.drools.core.factmodel.traits.TraitRegistry; +import org.drools.core.factmodel.traits.TraitTypeMap; import org.kie.api.runtime.rule.FactHandle; import org.drools.core.WorkingMemory; import org.drools.core.beliefsystem.BeliefSet; @@ -643,7 +645,6 @@ private InternalFactHandle lookupHandleForWrapper( K core ) { /* Trait helper methods */ protected void configureTrait( T thing, Object value ) { - } public T don( Thing core, Class trait, boolean logical ) { @@ -733,6 +734,8 @@ protected T applyManyTraits( K core, Collection> t T firstThing = null; Map things = new HashMap( traits.size() ); + checkStaticTypeCode( inner ); + for ( Class trait : traits ) { boolean needsProxy = trait.isAssignableFrom( inner.getClass() ); boolean hasTrait = inner.hasTrait( trait.getName() ); @@ -769,6 +772,22 @@ protected T applyManyTraits( K core, Collection> t return firstThing; } + private void checkStaticTypeCode( TraitableBean inner ) { + if ( ! inner.hasTraits() ) { + TraitTypeMap ttm = (TraitTypeMap) inner._getTraitMap(); + if ( ttm != null && ttm.getStaticTypeCode() == null ) { + TraitRegistry registry = this.workingMemory.getKnowledgeBase().getConfiguration().getComponentFactory().getTraitRegistry(); + // code that summarizes ALL the static types + BitSet staticCode = registry.getStaticTypeCode( inner.getClass().getName() ); + ttm.setStaticTypeCode( staticCode ); + if ( staticCode != null ) { + for ( String staticTrait : registry.getStaticTypes( inner.getClass().getName() ) ) { + ttm.addStaticTrait( staticTrait, registry.getHierarchy().getCode( staticTrait ) ); + } + } + } + } + } protected T applyTrait( K core, Class trait, Object value, boolean logical ) throws LogicalTypeInconsistencyException { if ( identityMap == null ) { @@ -783,6 +802,8 @@ protected T applyTrait( K core, Class trait, Object value, boolean log boolean hasTrait = inner.hasTrait( trait.getName() ); boolean needsUpdate = needsProxy || core != inner; + checkStaticTypeCode( inner ); + BitSet boundary = inner.getCurrentTypeCode() != null ? (BitSet) inner.getCurrentTypeCode().clone() : null; Collection mostSpecificTraits = getTraitBoundary( inner, needsProxy, hasTrait, trait ); @@ -835,7 +856,11 @@ public Thing shed( TraitableBean core, Cla update( core, Long.MIN_VALUE, core.getClass() ); //updateTraits( core, Long.MIN_VALUE, null, core.getClass(), null, ((TraitableBean) core).getMostSpecificTraits() ); } - return (Thing) core; + if ( core instanceof Thing ) { + return (Thing) core; + } else { + return null; + } } else { Collection> removedTypes; Thing thing = core.getTrait( Thing.class.getName() ); diff --git a/drools-core/src/main/java/org/drools/core/base/ValueType.java b/drools-core/src/main/java/org/drools/core/base/ValueType.java index 9da989ec17a..ad9a0ebb694 100644 --- a/drools-core/src/main/java/org/drools/core/base/ValueType.java +++ b/drools-core/src/main/java/org/drools/core/base/ValueType.java @@ -26,6 +26,7 @@ import org.drools.core.common.EventFactHandle; import org.drools.core.factmodel.traits.Thing; +import org.drools.core.factmodel.traits.Trait; import org.drools.core.facttemplates.FactTemplate; public class ValueType @@ -251,7 +252,7 @@ public static ValueType determineValueType(final Class clazz) { } else if ( clazz == Class.class ) { return ValueType.CLASS_TYPE; } - else if ( Thing.class.isAssignableFrom( clazz )) { + else if ( Thing.class.isAssignableFrom( clazz ) || clazz.isAnnotationPresent( Trait.class ) ) { return ValueType.TRAIT_TYPE; } else { return ValueType.OBJECT_TYPE; diff --git a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitRegistry.java b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitRegistry.java index 31cf6dafc49..ad0ccdd1326 100644 --- a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitRegistry.java +++ b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitRegistry.java @@ -20,6 +20,8 @@ import org.drools.core.factmodel.FieldDefinition; import org.drools.core.factmodel.MapCore; import org.drools.core.rule.TypeDeclaration; +import org.drools.core.util.ClassUtils; +import org.drools.core.util.HierNode; import org.drools.core.util.HierarchyEncoder; import org.drools.core.util.HierarchyEncoderImpl; import org.kie.api.definition.type.FactField; @@ -33,14 +35,17 @@ import java.util.BitSet; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; public class TraitRegistry implements Externalizable { private Map traits; private Map traitables; + private Map> staticTraitTypes; private int codeSize = 0; @@ -50,7 +55,6 @@ public class TraitRegistry implements Externalizable { public TraitRegistry() { - init(); } @@ -86,6 +90,11 @@ private void init() { } public void merge( TraitRegistry other ) { + if ( staticTraitTypes == null && other.staticTraitTypes != null ) { + staticTraitTypes = new HashMap>(); + staticTraitTypes.putAll( other.staticTraitTypes ); + } + if ( traits == null ) { traits = new HashMap(); } @@ -177,10 +186,16 @@ public void addTraitable( ClassDefinition traitable ) { traitables = new HashMap(); } this.traitables.put( traitable.getClassName(), traitable ); + Set staticTraits = detectStaticallyImplementedTraits( traitable ); + if ( ! staticTraits.isEmpty() ) { + if ( staticTraitTypes == null ) { + staticTraitTypes = new HashMap>(); + } + staticTraitTypes.put( traitable.getClassName(), staticTraits ); + } } - public static boolean isSoftField( FieldDefinition field, int index, BitSet mask ) { return ! mask.get( index ); } @@ -254,11 +269,74 @@ public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFo public HierarchyEncoder getHierarchy() { if ( hierarchy == null ) { - hierarchy = new HierarchyEncoderImpl(); + hierarchy = new CachingHierarcyEncoderImpl(); } return hierarchy; } + protected Set detectStaticallyImplementedTraits( ClassDefinition traitable ) { + Set traitInterfaces = new HashSet( 3 ); + for ( Class intf : ClassUtils.getAllImplementedInterfaceNames( traitable.getDefinedClass() ) ) { + if ( Thing.class.isAssignableFrom( intf ) || intf.getAnnotation( Trait.class ) != null ) { + traitInterfaces.add( intf.getName() ); + } + } + return traitInterfaces; + } + + public BitSet getStaticTypeCode( String className ) { + if ( staticTraitTypes != null && staticTraitTypes.containsKey( className ) ) { + CachingHierarcyEncoderImpl cachingHierarcyEncoder = (CachingHierarcyEncoderImpl) hierarchy; + if ( cachingHierarcyEncoder.hasCodeForClass( className ) ) { + return cachingHierarcyEncoder.getCodeForClass( className ); + } else { + return cachingHierarcyEncoder.cacheAndGetCode( className, staticTraitTypes.get( className ) ); + } + } else { + return null; + } + } + + public Set getStaticTypes( String name ) { + return staticTraitTypes.get( name ); + } + + public static class CachingHierarcyEncoderImpl extends HierarchyEncoderImpl { + + private Map cache; + + @Override + protected void encode( HierNode node ) { + super.encode( node ); + invalidateCache(); + } + + private void invalidateCache() { + if ( cache != null ) { + cache.clear(); + } + } + + public boolean hasCodeForClass( String className ) { + return cache != null && cache.containsKey( className ); + } + public BitSet getCodeForClass( String className ) { + return cache.get( className ); + } + public BitSet cacheAndGetCode( String className, Set parents ) { + BitSet bitSet = new BitSet( this.getBottom().length() ); + for ( String parent : parents ) { + bitSet.or( getCode( parent ) ); + } + if ( cache == null ) { + cache = new HashMap(); + } + cache.put( className, bitSet ); + return bitSet; + } + } } + + diff --git a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeMap.java b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeMap.java index 9a52262331e..b1633e42f9b 100644 --- a/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeMap.java +++ b/drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTypeMap.java @@ -16,6 +16,10 @@ public class TraitTypeMap, C> private BitSet currentTypeCode = new BitSet(); private transient Collection mostSpecificTraits = new LinkedList(); + private static final BitSet NO_STATIC = new BitSet(); + private BitSet staticTypeCode; + private Map staticTypes; + public TraitTypeMap() { } @@ -99,6 +103,12 @@ public K remove( Object key ) { public Collection removeCascade( String traitName ) { if ( ! innerMap.containsKey( traitName ) ) { + if ( staticTypes != null ) { + BitSet staticCode = staticTypes.get( traitName ); + if ( staticCode != null ) { + return removeCascade( staticTypes.get( traitName ) ); + } + } return Collections.emptyList(); } K thing = innerMap.get( traitName ); @@ -128,6 +138,9 @@ public Collection removeCascade( BitSet code ) { private void resetCurrentCode() { currentTypeCode = new BitSet( currentTypeCode.length() ); + if ( staticTypeCode != null && staticTypeCode != NO_STATIC ) { + currentTypeCode.or( staticTypeCode ); + } if ( ! this.values().isEmpty() ) { for ( Thing x : this.values() ) { currentTypeCode.or( ((TraitType) x).getTypeCode() ); @@ -178,6 +191,7 @@ public void writeExternal( ObjectOutput objectOutput ) throws IOException { } objectOutput.writeObject( currentTypeCode ); + objectOutput.writeObject( staticTypeCode ); objectOutput.writeObject( mostSpecificTraits ); } @@ -193,6 +207,7 @@ public void readExternal( ObjectInput objectInput ) throws IOException, ClassNot } currentTypeCode = (BitSet) objectInput.readObject(); + staticTypeCode = (BitSet) objectInput.readObject(); mostSpecificTraits = (Collection) objectInput.readObject(); } @@ -225,6 +240,25 @@ public BitSet getCurrentTypeCode() { return currentTypeCode; } + public BitSet getStaticTypeCode() { + return staticTypeCode; + } + + public void setStaticTypeCode( BitSet staticTypeCode ) { + if ( staticTypeCode != null ) { + this.staticTypeCode = staticTypeCode; + currentTypeCode.or( staticTypeCode ); + } else { + this.staticTypeCode = NO_STATIC; + } + } + + public void addStaticTrait( String name, BitSet code ) { + if ( staticTypes == null ) { + staticTypes = new HashMap(); + } + staticTypes.put( name, code ); + } } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/TraitObjectTypeNode.java b/drools-core/src/main/java/org/drools/core/reteoo/TraitObjectTypeNode.java index cfde03d6593..334d5bbd880 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/TraitObjectTypeNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/TraitObjectTypeNode.java @@ -19,7 +19,6 @@ import org.drools.core.base.ClassObjectType; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; -import org.drools.core.factmodel.traits.Key; import org.drools.core.factmodel.traits.Thing; import org.drools.core.factmodel.traits.TraitProxy; import org.drools.core.factmodel.traits.TraitTypeMap; diff --git a/drools-core/src/main/java/org/drools/core/util/ClassUtils.java b/drools-core/src/main/java/org/drools/core/util/ClassUtils.java index 052e7a3bd90..ce41dc4e4ff 100644 --- a/drools-core/src/main/java/org/drools/core/util/ClassUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/ClassUtils.java @@ -18,6 +18,7 @@ import org.drools.core.common.DroolsObjectInputStream; import org.drools.core.common.DroolsObjectOutputStream; +import org.drools.core.factmodel.traits.Thing; import org.kie.api.definition.type.Modifies; import org.kie.internal.utils.ClassLoaderUtil; @@ -43,6 +44,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -520,6 +522,26 @@ public static Class convertPrimitiveNameToType( String typeName ) { return Object.class; } + public static Set> getAllImplementedInterfaceNames( Class klass ) { + Set> interfaces = new HashSet>(); + while( klass != null ) { + Class[] localInterfaces = klass.getInterfaces(); + for ( Class intf : localInterfaces ) { + interfaces.add( intf ); + exploreSuperInterfaces( intf, interfaces ); + } + klass = klass.getSuperclass(); + } + return interfaces; + } + + private static void exploreSuperInterfaces( Class intf, Set> traitInterfaces ) { + for ( Class sup : intf.getInterfaces() ) { + traitInterfaces.add( sup ); + exploreSuperInterfaces( sup, traitInterfaces ); + } + } + public static boolean isWindows() { String os = System.getProperty("os.name"); return os.toUpperCase().contains( "WINDOWS" ); diff --git a/drools-core/src/main/java/org/drools/core/util/HierarchyEncoderImpl.java b/drools-core/src/main/java/org/drools/core/util/HierarchyEncoderImpl.java index 953cae79ae4..0512df0e9ca 100644 --- a/drools-core/src/main/java/org/drools/core/util/HierarchyEncoderImpl.java +++ b/drools-core/src/main/java/org/drools/core/util/HierarchyEncoderImpl.java @@ -31,7 +31,7 @@ /** * Encodes a hierachy using bit masks, according to the algorithm described in * M.F. van Bommel, P. Wang, Encoding Multiple Inheritance Hierarchies for Lattice Operations - * Data & Knowledge Enfineering 50 (2004) 175-194 + * Data & Knowledge Engineering 50 (2004) 175-194 * * @param */ From dfa5d9e5f87dbb7dd18dc5968ecc1814a43b3fad Mon Sep 17 00:00:00 2001 From: sotty Date: Fri, 18 Jul 2014 15:31:20 +0200 Subject: [PATCH 44/76] [DROOLS-549] Move helper methods to ClassUtils (cherry picked from commit dd59435b623cc5dfdbb3ba9b0ff18b187fc3bc79) --- .../rule/builder/QueryElementBuilder.java | 79 +------------------ .../java/org/drools/core/util/ClassUtils.java | 52 ++++++++++++ 2 files changed, 54 insertions(+), 77 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java index 0021a49bf1b..9ab05cb2f18 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java @@ -24,6 +24,7 @@ import org.drools.core.rule.RuleConditionElement; import org.drools.core.spi.InternalReadAccessor; import org.drools.core.spi.ObjectType; +import org.drools.core.util.ClassUtils; import org.drools.core.util.MVELSafeHelper; import org.drools.core.util.StringUtils; import org.kie.api.runtime.rule.Variable; @@ -212,7 +213,7 @@ public RuleConditionElement build( RuleBuildContext context, // with queries invoking each other, we won't know until runtime whether a declaration is input, output or else // input argument require a broader type, while output types require a narrower type, so we check for both. - if ( ! isCompatible( actual, formal ) && ! isCompatible( formal, actual ) ) { + if ( ! ClassUtils.isTypeCompatibleWithArgumentType( actual, formal ) && ! ClassUtils.isTypeCompatibleWithArgumentType( formal, actual ) ) { context.addError( new DescrBuildError( context.getParentDescr(), descr, null, @@ -231,82 +232,6 @@ public RuleConditionElement build( RuleBuildContext context, query.isAbductive() ); } - // FIXME : These methods do not belong here, but where? - private boolean isCompatible( Class actual, Class formal ) { - if ( actual.isPrimitive() && formal.isPrimitive() ) { - return isConvertible( actual, formal ); - } else if ( actual.isPrimitive() ) { - return isConvertible( actual, unbox( formal ) ); - } else if ( formal.isPrimitive() ) { - return isConvertible( unbox( actual ), formal ); - } else { - return formal.isAssignableFrom( actual ); - } - } - - private boolean isConvertible( Class srcPrimitive, Class tgtPrimitive ) { - if ( Boolean.TYPE.equals( srcPrimitive ) ) { - return Boolean.TYPE.equals( tgtPrimitive ); - } else if ( Byte.TYPE.equals( tgtPrimitive ) ) { - return Byte.TYPE.equals( tgtPrimitive ) - || Short.TYPE.equals( tgtPrimitive ) - || Integer.TYPE.equals( tgtPrimitive ) - || Long.TYPE.equals( tgtPrimitive ) - || Float.TYPE.equals( tgtPrimitive ) - || Double.TYPE.equals( tgtPrimitive ); - } else if ( Character.TYPE.equals( srcPrimitive ) ) { - return Character.TYPE.equals( tgtPrimitive ) - || Integer.TYPE.equals( tgtPrimitive ) - || Long.TYPE.equals( tgtPrimitive ) - || Float.TYPE.equals( tgtPrimitive ) - || Double.TYPE.equals( tgtPrimitive ); - } else if ( Double.TYPE.equals( srcPrimitive ) ) { - return Double.TYPE.equals( tgtPrimitive ); - } else if ( Float.TYPE.equals( srcPrimitive ) ) { - return Float.TYPE.equals( tgtPrimitive ) - || Double.TYPE.equals( tgtPrimitive ); - } else if ( Integer.TYPE.equals( srcPrimitive ) ) { - return Integer.TYPE.equals( tgtPrimitive ) - || Long.TYPE.equals( tgtPrimitive ) - || Float.TYPE.equals( tgtPrimitive ) - || Double.TYPE.equals( tgtPrimitive ); - } else if ( Long.TYPE.equals( srcPrimitive ) ) { - return Long.TYPE.equals( tgtPrimitive ) - || Float.TYPE.equals( tgtPrimitive ) - || Double.TYPE.equals( tgtPrimitive ); - } else if ( Short.TYPE.equals( srcPrimitive ) ) { - return Short.TYPE.equals( tgtPrimitive ) - || Integer.TYPE.equals( tgtPrimitive ) - || Long.TYPE.equals( tgtPrimitive ) - || Float.TYPE.equals( tgtPrimitive ) - || Double.TYPE.equals( tgtPrimitive ); - } - return false; - } - - private Class unbox( Class boxed ) { - if ( Boolean.class.equals( boxed ) ) { - return Boolean.TYPE; - } else if ( Byte.class.equals( boxed ) ) { - return Byte.TYPE; - } else if ( Character.class.equals( boxed ) ) { - return Character.TYPE; - } else if ( Double.class.equals( boxed ) ) { - return Double.TYPE; - } else if ( Float.class.equals( boxed ) ) { - return Float.TYPE; - } else if ( Integer.class.equals( boxed ) ) { - return Integer.TYPE; - } else if ( Long.class.equals( boxed ) ) { - return Long.TYPE; - } else if ( Short.class.equals( boxed ) ) { - return Short.TYPE; - } else if ( Number.class.equals( boxed ) ) { - return Double.TYPE; - } - return boxed; - } - @SuppressWarnings("unchecked") private void processBinding( RuleBuildContext context, BaseDescr descr, diff --git a/drools-core/src/main/java/org/drools/core/util/ClassUtils.java b/drools-core/src/main/java/org/drools/core/util/ClassUtils.java index ce41dc4e4ff..ea9da69efbb 100644 --- a/drools-core/src/main/java/org/drools/core/util/ClassUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/ClassUtils.java @@ -396,6 +396,58 @@ private static void processModifiesAnnotation(Class clazz, Set } } + public static boolean isTypeCompatibleWithArgumentType( Class actual, Class formal ) { + if ( actual.isPrimitive() && formal.isPrimitive() ) { + return isConvertible( actual, formal ); + } else if ( actual.isPrimitive() ) { + return isConvertible( actual, convertToPrimitiveType( formal ) ); + } else if ( formal.isPrimitive() ) { + return isConvertible( convertToPrimitiveType( actual ), formal ); + } else { + return formal.isAssignableFrom( actual ); + } + } + + public static boolean isConvertible( Class srcPrimitive, Class tgtPrimitive ) { + if ( Boolean.TYPE.equals( srcPrimitive ) ) { + return Boolean.TYPE.equals( tgtPrimitive ); + } else if ( Byte.TYPE.equals( tgtPrimitive ) ) { + return Byte.TYPE.equals( tgtPrimitive ) + || Short.TYPE.equals( tgtPrimitive ) + || Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Character.TYPE.equals( srcPrimitive ) ) { + return Character.TYPE.equals( tgtPrimitive ) + || Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Double.TYPE.equals( srcPrimitive ) ) { + return Double.TYPE.equals( tgtPrimitive ); + } else if ( Float.TYPE.equals( srcPrimitive ) ) { + return Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Integer.TYPE.equals( srcPrimitive ) ) { + return Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Long.TYPE.equals( srcPrimitive ) ) { + return Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } else if ( Short.TYPE.equals( srcPrimitive ) ) { + return Short.TYPE.equals( tgtPrimitive ) + || Integer.TYPE.equals( tgtPrimitive ) + || Long.TYPE.equals( tgtPrimitive ) + || Float.TYPE.equals( tgtPrimitive ) + || Double.TYPE.equals( tgtPrimitive ); + } + return false; + } + private static class SetterInClass implements Comparable { private final String setter; private final Class clazz; From c6e9c58ce1d6cd0103bc87d05aa364144a03d10f Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 21 Jul 2014 09:45:07 +0200 Subject: [PATCH 45/76] fix wumpus 'climb' command (cherry picked from commit 342fc2b3caaf19a3987ec148269d531c6a6d6bc4) --- drools-examples/src/main/resources/logback.xml | 2 +- .../main/resources/org/drools/games/wumpus/server/score.drl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drools-examples/src/main/resources/logback.xml b/drools-examples/src/main/resources/logback.xml index c950f15bdd5..0df2efd22d4 100644 --- a/drools-examples/src/main/resources/logback.xml +++ b/drools-examples/src/main/resources/logback.xml @@ -9,7 +9,7 @@ - + diff --git a/drools-examples/src/main/resources/org/drools/games/wumpus/server/score.drl b/drools-examples/src/main/resources/org/drools/games/wumpus/server/score.drl index ddc7cfcb3ab..36e6a0c205f 100644 --- a/drools-examples/src/main/resources/org/drools/games/wumpus/server/score.drl +++ b/drools-examples/src/main/resources/org/drools/games/wumpus/server/score.drl @@ -32,7 +32,8 @@ rule "Gold Win +100" salience 100 agenda-group "Score" when $s : Score() then modify( $s ) { value = $s.value + 100 }; -end + setFocus( "EndGame" ); +end rule "Pit Death -1000" salience 100 agenda-group "Score" when PitDeath() From 3e59e1c2f1f0108bbf4c406e042d4ebf5f67fef8 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 21 Jul 2014 19:36:22 +0200 Subject: [PATCH 46/76] [BZ-1120972] avoid trying to parse xsd files when no jaxb configuration is available (cherry picked from commit a1a717c8ca8196523970ad11000402108973888f) --- .../builder/impl/KnowledgeBuilderImpl.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java index 39a558a3123..3b48afb1cc7 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java @@ -703,12 +703,14 @@ PackageDescr pmmlModelToPackageDescr(PMMLCompiler compiler, void addPackageFromXSD(Resource resource, JaxbConfigurationImpl configuration) throws IOException { - String[] classes = DroolsJaxbHelperProviderImpl.addXsdModel(resource, - this, - configuration.getXjcOpts(), - configuration.getSystemId()); - for (String cls : classes) { - configuration.getClasses().add(cls); + if (configuration != null) { + String[] classes = DroolsJaxbHelperProviderImpl.addXsdModel(resource, + this, + configuration.getXjcOpts(), + configuration.getSystemId()); + for (String cls : classes) { + configuration.getClasses().add(cls); + } } } From 76e707e14955fad3eeae76368feb346607420ee0 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Tue, 22 Jul 2014 12:33:40 +0200 Subject: [PATCH 47/76] [DROOLS-559] emit a compilation error when trying to use a non-existing positional argument (cherry picked from commit 4608abf29a9579979f46cc3581b453126ee7e557) --- .../builder/impl/TypeDeclarationBuilder.java | 23 ++- .../compiler/TypeDeclarationError.java | 8 + .../compiler/TypeDeclarationTest.java | 165 ++++++++++++++++-- .../core/factmodel/ClassDefinition.java | 9 +- 4 files changed, 177 insertions(+), 28 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java index 9929f109896..b326f753bf8 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java @@ -213,7 +213,7 @@ private void initTypeDeclaration(Class cls, if (typeDeclaration.isPropertyReactive()) { processModifiedProps(cls, clsDef); } - processFieldsPosition(cls, clsDef); + processFieldsPosition(cls, clsDef, typeDeclaration); // build up a set of all the super classes and interfaces Set tdecls = new LinkedHashSet(); @@ -249,7 +249,8 @@ private void initTypeDeclaration(Class cls, } private void processFieldsPosition(Class cls, - ClassDefinition clsDef) { + ClassDefinition clsDef, + TypeDeclaration typeDeclaration) { // it's a new type declaration, so generate the @Position for it Collection fields = new LinkedList(); Class tempKlass = cls; @@ -258,21 +259,27 @@ private void processFieldsPosition(Class cls, tempKlass = tempKlass.getSuperclass(); } - List orderedFields = new ArrayList(fields.size()); - for (int i = 0; i < fields.size(); i++) { - // as these could be set in any order, initialise first, to allow setting later. - orderedFields.add(null); - } + FieldDefinition[] orderedFields = new FieldDefinition[fields.size()]; for (Field fld : fields) { Position pos = fld.getAnnotation(Position.class); if (pos != null) { + if (pos.value() < 0 || pos.value() >= fields.size()) { + kbuilder.addBuilderResult(new TypeDeclarationError(typeDeclaration, + "Out of range position " + pos.value() + " for field '" + fld.getName() + "' on class " + cls.getName())); + continue; + } + if (orderedFields[pos.value()] != null) { + kbuilder.addBuilderResult(new TypeDeclarationError(typeDeclaration, + "Duplicated position " + pos.value() + " for field '" + fld.getName() + "' on class " + cls.getName())); + continue; + } FieldDefinition fldDef = clsDef.getField(fld.getName()); if (fldDef == null) { fldDef = new FieldDefinition(fld.getName(), fld.getType().getName()); } fldDef.setIndex(pos.value()); - orderedFields.set(pos.value(), fldDef); + orderedFields[pos.value()] = fldDef; } } for (FieldDefinition fld : orderedFields) { diff --git a/drools-compiler/src/main/java/org/drools/compiler/compiler/TypeDeclarationError.java b/drools-compiler/src/main/java/org/drools/compiler/compiler/TypeDeclarationError.java index a26076681db..1bf8b09bbd7 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/compiler/TypeDeclarationError.java +++ b/drools-compiler/src/main/java/org/drools/compiler/compiler/TypeDeclarationError.java @@ -18,6 +18,7 @@ import org.drools.compiler.lang.descr.AbstractClassTypeDeclarationDescr; import org.drools.compiler.lang.descr.TypeFieldDescr; +import org.drools.core.rule.TypeDeclaration; public class TypeDeclarationError extends DroolsError { private String errorMessage; @@ -38,6 +39,13 @@ public TypeDeclarationError(TypeFieldDescr fieldDescr, String errorMessage) { this.namespace = fieldDescr.getNamespace(); } + public TypeDeclarationError(TypeDeclaration typeDeclaration, String errorMessage) { + super(typeDeclaration.getResource()); + this.errorMessage = errorMessage; + this.line = new int[0]; + this.namespace = typeDeclaration.getNamespace(); + } + @Override public String getNamespace() { return namespace; diff --git a/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java b/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java index 45b213373dd..d88252902a4 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java @@ -18,6 +18,7 @@ import org.kie.api.io.Resource; import org.kie.api.io.ResourceType; import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; import org.kie.api.runtime.rule.FactHandle; import org.kie.internal.KnowledgeBase; import org.kie.internal.KnowledgeBaseFactory; @@ -33,8 +34,10 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; import static org.junit.Assert.*; @@ -740,16 +743,11 @@ public void testPreventReflectionAPIsOnJavaClasses() { "end \n" + ""; - KieServices kieServices = KieServices.Factory.get(); - KieFileSystem kfs = kieServices.newKieFileSystem(); - kfs.write( kieServices.getResources().newByteArrayResource( drl.getBytes() ) - .setSourcePath( "test.drl" ) - .setResourceType( ResourceType.DRL ) ); - KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ); - kieBuilder.buildAll(); + + KieBuilder kieBuilder = build(drl); assertFalse( kieBuilder.getResults().hasMessages( Message.Level.ERROR ) ); - KieBase kieBase = kieServices.newKieContainer( kieBuilder.getKieModule().getReleaseId() ).getKieBase(); + KieBase kieBase = KieServices.Factory.get().newKieContainer( kieBuilder.getKieModule().getReleaseId() ).getKieBase(); FactType type = kieBase.getFactType( "org.drools.compiler", "Person" ); @@ -834,20 +832,155 @@ public void testUnknownField() throws InstantiationException, IllegalAccessExcep " " + "end \n"; - KieServices kieServices = KieServices.Factory.get(); - KieFileSystem kfs = kieServices.newKieFileSystem(); - kfs.write( kieServices.getResources().newByteArrayResource( drl.getBytes() ) - .setSourcePath( "test.drl" ) - .setResourceType( ResourceType.DRL ) ); - KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ); - kieBuilder.buildAll(); + KieBuilder kieBuilder = build(drl); assertFalse( kieBuilder.getResults().hasMessages( Message.Level.ERROR ) ); - KieBase kieBase = kieServices.newKieContainer( kieBuilder.getKieModule().getReleaseId() ).getKieBase(); + KieBase kieBase = KieServices.Factory.get().newKieContainer( kieBuilder.getKieModule().getReleaseId() ).getKieBase(); FactType factType = kieBase.getFactType("org.test", "Pet"); Object instance = factType.newInstance(); factType.get(instance, "unknownField"); factType.set(instance, "unknownField", "myValue"); } + + @Test + public void testPositionalArguments() throws InstantiationException, IllegalAccessException { + String drl = "package org.test;\n" + + "global java.util.List names;\n" + + "declare Person\n" + + " name : String\n" + + " age : int\n" + + "end\n" + + "rule R when \n" + + " $p : Person( \"Mark\", 37; )\n" + + "then\n" + + " names.add( $p.getName() );\n" + + "end\n"; + + KieBuilder kieBuilder = build(drl); + + assertFalse(kieBuilder.getResults().hasMessages(Message.Level.ERROR)); + KieBase kieBase = KieServices.Factory.get().newKieContainer( kieBuilder.getKieModule().getReleaseId() ).getKieBase(); + + FactType factType = kieBase.getFactType("org.test", "Person"); + Object instance = factType.newInstance(); + factType.set(instance, "name", "Mark"); + factType.set(instance, "age", 37); + + List names = new ArrayList(); + KieSession ksession = kieBase.newKieSession(); + ksession.setGlobal("names", names); + + ksession.insert(instance); + ksession.fireAllRules(); + + assertEquals(1, names.size()); + assertEquals("Mark", names.get(0)); + } + + @Test + public void testExplictPositionalArguments() throws InstantiationException, IllegalAccessException { + String drl = "package org.test;\n" + + "global java.util.List names;\n" + + "declare Person\n" + + " name : String @position(1)\n" + + " age : int @position(0)\n" + + "end\n" + + "rule R when \n" + + " $p : Person( 37, \"Mark\"; )\n" + + "then\n" + + " names.add( $p.getName() );\n" + + "end\n"; + + KieBuilder kieBuilder = build(drl); + + assertFalse(kieBuilder.getResults().hasMessages(Message.Level.ERROR)); + KieBase kieBase = KieServices.Factory.get().newKieContainer( kieBuilder.getKieModule().getReleaseId() ).getKieBase(); + + FactType factType = kieBase.getFactType("org.test", "Person"); + Object instance = factType.newInstance(); + factType.set(instance, "name", "Mark"); + factType.set(instance, "age", 37); + + List names = new ArrayList(); + KieSession ksession = kieBase.newKieSession(); + ksession.setGlobal("names", names); + + ksession.insert(instance); + ksession.fireAllRules(); + + assertEquals(1, names.size()); + assertEquals("Mark", names.get(0)); + } + + @Test + public void testTooManyPositionalArguments() throws InstantiationException, IllegalAccessException { + // DROOLS-559 + String drl = "package org.test;\n" + + "global java.util.List names;\n" + + "declare Person\n" + + " name : String\n" + + " age : int\n" + + "end\n" + + "rule R when \n" + + " $p : Person( \"Mark\", 37, 42; )\n" + + "then\n" + + " names.add( $p.getName() );\n" + + "end\n"; + + KieBuilder kieBuilder = build(drl); + + assertTrue( kieBuilder.getResults().hasMessages( Message.Level.ERROR ) ); + } + + @Test + public void testOutOfRangePositions() throws InstantiationException, IllegalAccessException { + // DROOLS-559 + String drl = "package org.test;\n" + + "global java.util.List names;\n" + + "declare Person\n" + + " name : String @position(3)\n" + + " age : int @position(1)\n" + + "end\n" + + "rule R when \n" + + " $p : Person( 37, \"Mark\"; )\n" + + "then\n" + + " names.add( $p.getName() );\n" + + "end\n"; + + KieBuilder kieBuilder = build(drl); + + assertTrue( kieBuilder.getResults().hasMessages( Message.Level.ERROR ) ); + } + + @Test + public void testDuplicatedPositions() throws InstantiationException, IllegalAccessException { + // DROOLS-559 + String drl = "package org.test;\n" + + "global java.util.List names;\n" + + "declare Person\n" + + " name : String @position(1)\n" + + " age : int @position(1)\n" + + "end\n" + + "rule R when \n" + + " $p : Person( 37, \"Mark\"; )\n" + + "then\n" + + " names.add( $p.getName() );\n" + + "end\n"; + + KieBuilder kieBuilder = build(drl); + + assertTrue( kieBuilder.getResults().hasMessages( Message.Level.ERROR ) ); + } + + private KieBuilder build(String drl) { + KieServices kieServices = KieServices.Factory.get(); + KieFileSystem kfs = kieServices.newKieFileSystem(); + kfs.write( kieServices.getResources().newByteArrayResource( drl.getBytes() ) + .setSourcePath( "test.drl" ) + .setResourceType( ResourceType.DRL ) ); + KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ); + kieBuilder.buildAll(); + return kieBuilder; + } } diff --git a/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java b/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java index 605343b084c..1617aa74198 100755 --- a/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java +++ b/drools-core/src/main/java/org/drools/core/factmodel/ClassDefinition.java @@ -181,13 +181,14 @@ public FieldDefinition getFieldByAlias( String alias ) { * @return the index-th field */ public FieldDefinition getField(int index) { - if (index >= fields.size() || index < 0) - throw new IndexOutOfBoundsException("Error trying to access field at position " + index); + if (index >= fields.size() || index < 0) { + return null; + } Iterator iter = fields.values().iterator(); - for (int j = 0; j < index ; j++) + for (int j = 0; j < index ; j++) { iter.next(); + } return iter.next(); - } From 40313f788ca87b2adb650db5d481a591f520e5bf Mon Sep 17 00:00:00 2001 From: mariofusco Date: Tue, 22 Jul 2014 20:21:18 +0200 Subject: [PATCH 48/76] [DROOLS-560] fix incremental compilation when both versions of a drl file contain an event type declaration for an existing class (cherry picked from commit 283ba1d94ea752355776f0b0cb490f29a0d081c1) --- .../builder/impl/TypeDeclarationBuilder.java | 172 +++++++++--------- .../IncrementalCompilationTest.java | 64 +++++++ 2 files changed, 149 insertions(+), 87 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java index b326f753bf8..36fc3ab6230 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java +++ b/drools-compiler/src/main/java/org/drools/compiler/builder/impl/TypeDeclarationBuilder.java @@ -990,111 +990,109 @@ List processTypeDeclarations( PackageRegistry pkgRegistry, Packa Map foreignPackages = null; for (AbstractClassTypeDeclarationDescr typeDescr : packageDescr.getClassAndEnumDeclarationDescrs()) { - if (kbuilder.filterAccepts(typeDescr.getNamespace(), typeDescr.getTypeName()) ) { - String qName = typeDescr.getType().getFullName(); - Class typeClass = getClassForType(qName); - if (typeClass == null) { - typeClass = getClassForType(typeDescr.getTypeName()); - } - if (typeClass == null) { - for (ImportDescr id : packageDescr.getImports()) { - String imp = id.getTarget(); - int separator = imp.lastIndexOf('.'); - String tail = imp.substring(separator + 1); - if (tail.equals(typeDescr.getTypeName())) { - typeDescr.setNamespace(imp.substring(0, separator)); - typeClass = getClassForType(typeDescr.getType().getFullName()); - break; - } else if (tail.equals("*")) { - typeClass = getClassForType(imp.substring(0, imp.length() - 1) + typeDescr.getType().getName()); - if (typeClass != null) { - String resolvedNamespace = imp.substring(0, separator); - if ( resolvedNamespace.equals( typeDescr.getNamespace() ) ) { - // the class was found in the declared namespace, so stop here - break; - // here, the class was found in a different namespace. It means that the class was declared - // with no namespace and the initial guess was wrong, or that there is an ambiguity. - // So, we need to check that the resolved class is compatible with the declaration. - } else if ( isCompatible( typeClass, typeDescr ) ) { - typeDescr.setNamespace( resolvedNamespace ); - } else { - typeClass = null; - } + String qName = typeDescr.getType().getFullName(); + Class typeClass = getClassForType(qName); + if (typeClass == null) { + typeClass = getClassForType(typeDescr.getTypeName()); + } + if (typeClass == null) { + for (ImportDescr id : packageDescr.getImports()) { + String imp = id.getTarget(); + int separator = imp.lastIndexOf('.'); + String tail = imp.substring(separator + 1); + if (tail.equals(typeDescr.getTypeName())) { + typeDescr.setNamespace(imp.substring(0, separator)); + typeClass = getClassForType(typeDescr.getType().getFullName()); + break; + } else if (tail.equals("*")) { + typeClass = getClassForType(imp.substring(0, imp.length() - 1) + typeDescr.getType().getName()); + if (typeClass != null) { + String resolvedNamespace = imp.substring(0, separator); + if ( resolvedNamespace.equals( typeDescr.getNamespace() ) ) { + // the class was found in the declared namespace, so stop here + break; + // here, the class was found in a different namespace. It means that the class was declared + // with no namespace and the initial guess was wrong, or that there is an ambiguity. + // So, we need to check that the resolved class is compatible with the declaration. + } else if ( isCompatible( typeClass, typeDescr ) ) { + typeDescr.setNamespace( resolvedNamespace ); + } else { + typeClass = null; } } } } - String className = typeClass != null ? typeClass.getName() : qName; - int dotPos = className.lastIndexOf('.'); - if (dotPos >= 0) { - typeDescr.setNamespace(className.substring(0, dotPos)); - typeDescr.setTypeName(className.substring(dotPos + 1)); - } + } + String className = typeClass != null ? typeClass.getName() : qName; + int dotPos = className.lastIndexOf('.'); + if (dotPos >= 0) { + typeDescr.setNamespace(className.substring(0, dotPos)); + typeDescr.setTypeName(className.substring(dotPos + 1)); + } - if (isEmpty(typeDescr.getNamespace()) && typeDescr.getFields().isEmpty()) { - // might be referencing a class imported with a package import (.*) - PackageRegistry pkgReg = kbuilder.getPackageRegistry(packageDescr.getName()); - if (pkgReg != null) { - try { - Class clz = pkgReg.getTypeResolver().resolveType(typeDescr.getTypeName()); - java.lang.Package pkg = clz.getPackage(); - if (pkg != null) { - typeDescr.setNamespace(pkg.getName()); - int index = typeDescr.getNamespace() != null && !typeDescr.getNamespace().isEmpty() ? typeDescr.getNamespace().length() + 1 : 0; - typeDescr.setTypeName(clz.getCanonicalName().substring(index)); - } - } catch (Exception e) { - // intentionally eating the exception as we will fallback to default namespace + if (isEmpty(typeDescr.getNamespace()) && typeDescr.getFields().isEmpty()) { + // might be referencing a class imported with a package import (.*) + PackageRegistry pkgReg = kbuilder.getPackageRegistry(packageDescr.getName()); + if (pkgReg != null) { + try { + Class clz = pkgReg.getTypeResolver().resolveType(typeDescr.getTypeName()); + java.lang.Package pkg = clz.getPackage(); + if (pkg != null) { + typeDescr.setNamespace(pkg.getName()); + int index = typeDescr.getNamespace() != null && !typeDescr.getNamespace().isEmpty() ? typeDescr.getNamespace().length() + 1 : 0; + typeDescr.setTypeName(clz.getCanonicalName().substring(index)); } + } catch (Exception e) { + // intentionally eating the exception as we will fallback to default namespace } } + } - if (isEmpty(typeDescr.getNamespace())) { - typeDescr.setNamespace(packageDescr.getNamespace()); // set the default namespace - } + if (isEmpty(typeDescr.getNamespace())) { + typeDescr.setNamespace(packageDescr.getNamespace()); // set the default namespace + } - //identify superclass type and namespace - if (typeDescr instanceof TypeDeclarationDescr) { - fillSuperType((TypeDeclarationDescr) typeDescr, - packageDescr); - AnnotationDescr kind = typeDescr.getAnnotation( TypeDeclaration.Kind.ID ); - if ( typeClass != null && kind != null && kind.hasValue() && TypeDeclaration.Kind.TRAIT == TypeDeclaration.Kind.parseKind( kind.getSingleValue() ) ) { - fillStaticInterfaces( (TypeDeclarationDescr) typeDescr, typeClass ); - } + //identify superclass type and namespace + if (typeDescr instanceof TypeDeclarationDescr) { + fillSuperType((TypeDeclarationDescr) typeDescr, + packageDescr); + AnnotationDescr kind = typeDescr.getAnnotation( TypeDeclaration.Kind.ID ); + if ( typeClass != null && kind != null && kind.hasValue() && TypeDeclaration.Kind.TRAIT == TypeDeclaration.Kind.parseKind( kind.getSingleValue() ) ) { + fillStaticInterfaces( (TypeDeclarationDescr) typeDescr, typeClass ); } + } - //identify field types as well - fillFieldTypes(typeDescr, - packageDescr); + //identify field types as well + fillFieldTypes(typeDescr, + packageDescr); - if (!typeDescr.getNamespace().equals(packageDescr.getNamespace())) { - // If the type declaration is for a different namespace, process that separately. - PackageDescr altDescr; + if (!typeDescr.getNamespace().equals(packageDescr.getNamespace())) { + // If the type declaration is for a different namespace, process that separately. + PackageDescr altDescr; - if ( foreignPackages == null ) { - foreignPackages = new HashMap( ); - } + if ( foreignPackages == null ) { + foreignPackages = new HashMap( ); + } - if ( foreignPackages.containsKey( typeDescr.getNamespace() ) ) { - altDescr = foreignPackages.get( typeDescr.getNamespace() ); - } else { - altDescr = new PackageDescr(typeDescr.getNamespace()); - foreignPackages.put( typeDescr.getNamespace(), altDescr ); - } + if ( foreignPackages.containsKey( typeDescr.getNamespace() ) ) { + altDescr = foreignPackages.get( typeDescr.getNamespace() ); + } else { + altDescr = new PackageDescr(typeDescr.getNamespace()); + foreignPackages.put( typeDescr.getNamespace(), altDescr ); + } - if (typeDescr instanceof TypeDeclarationDescr) { - altDescr.addTypeDeclaration((TypeDeclarationDescr) typeDescr); - } else if (typeDescr instanceof EnumDeclarationDescr) { - altDescr.addEnumDeclaration((EnumDeclarationDescr) typeDescr); - } + if (typeDescr instanceof TypeDeclarationDescr) { + altDescr.addTypeDeclaration((TypeDeclarationDescr) typeDescr); + } else if (typeDescr instanceof EnumDeclarationDescr) { + altDescr.addEnumDeclaration((EnumDeclarationDescr) typeDescr); + } - for (ImportDescr imp : packageDescr.getImports()) { - altDescr.addImport(imp); - } - if (!kbuilder.getPackageRegistry().containsKey(altDescr.getNamespace())) { - kbuilder.newPackage(altDescr); - } + for (ImportDescr imp : packageDescr.getImports()) { + altDescr.addImport(imp); + } + if (!kbuilder.getPackageRegistry().containsKey(altDescr.getNamespace())) { + kbuilder.newPackage(altDescr); } } } diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java index bfaccd4dfe4..039f15a6865 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java @@ -1173,4 +1173,68 @@ public void testKJarUpgradeSameSessionAddingGlobal() throws Exception { ksession.insert( new Message( "Hello World" ) ); assertEquals( 2, ksession.fireAllRules() ); } + + public static class FooEvent { + private long mytime; + + public FooEvent(long mytime) { + this.mytime = mytime; + } + + public long getMytime() { + return mytime; + } + } + + @Test + public void testUpdateWithDeclarationPresent() throws Exception { + // DROOLS-560 + String header = "package org.drools.compiler\n" + + "import org.drools.compiler.integrationtests.IncrementalCompilationTest.FooEvent\n"; + + String declaration = "declare FooEvent\n" + + " @timestamp( mytime )\n" + + " @role( event )\n" + + "end\n"; + + String rule1 = "rule R1 when\n" + + " $e : FooEvent( )\n" + + "then\n" + + " insert(new Message(\"Hello R1\"));\n" + + "end\n"; + + String rule2 = "rule R1 when\n" + + " $e : FooEvent( )\n" + + "then\n" + + " insert(new Message(\"Hello R2\"));\n" + + "end\n"; + + String file1 = header + declaration + rule1; + String file2 = header + declaration + rule2; + + KieServices ks = KieServices.Factory.get(); + + // Create an in-memory jar for version 1.0.0 + ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-upgrade", "1.0.0" ); + KieModule km = createAndDeployJar( ks, releaseId1, file1 ); + + // Create a session and fire rules + KieContainer kc = ks.newKieContainer( km.getReleaseId() ); + KieSession ksession = kc.newKieSession(); + ksession.insert( new FooEvent( 0 ) ); + assertEquals( 1, ksession.fireAllRules() ); + + // Create a new jar for version 1.1.0 + ReleaseId releaseId2 = ks.newReleaseId( "org.kie", "test-upgrade", "1.1.0" ); + km = createAndDeployJar( ks, releaseId2, file2 ); + + // try to update the container to version 1.1.0 + Results results = kc.updateToVersion( releaseId2 ); + + assertFalse("Errors detected on updateToVersion: " + results.getMessages(org.kie.api.builder.Message.Level.ERROR), results.hasMessages(org.kie.api.builder.Message.Level.ERROR)); + + // continue working with the session + ksession.insert( new FooEvent( 1 ) ); + assertEquals( 2, ksession.fireAllRules() ); + } } \ No newline at end of file From d20b40da38877cf97b7476829e5b8cf59980576f Mon Sep 17 00:00:00 2001 From: Mark Proctor Date: Wed, 23 Jul 2014 05:00:44 +0100 Subject: [PATCH 49/76] Improve TextAdventure --- .../games/adventures/AdventureFrame.java | 127 ++++++++----- .../drools/games/adventures/GameEngine.java | 160 ++++++----------- .../games/adventures/TextAdventure.java | 22 ++- .../drools/games/adventures/UserSession.java | 24 ++- .../games/adventures/model/Character.java | 21 +++ .../games/adventures/model/Command.java | 24 +++ .../drools/games/adventures/model/Door.java | 88 +++++++++ .../games/adventures/model/DropCommand.java | 66 +++++++ .../games/adventures/model/DropEvent.java | 64 +++++++ .../games/adventures/model/EnterEvent.java | 64 +++++++ .../games/adventures/model/ExitEvent.java | 65 +++++++ .../games/adventures/model/GameEvent.java | 7 + .../games/adventures/model/GiveCommand.java | 78 ++++++++ .../games/adventures/model/GiveEvent.java | 78 ++++++++ .../games/adventures/model/Holding.java | 63 +++++++ .../drools/games/adventures/model/Item.java | 39 ++++ .../drools/games/adventures/model/Key.java | 16 ++ .../games/adventures/model/Location.java | 62 +++++++ .../games/adventures/model/LockStatus.java | 5 + .../games/adventures/model/LookCommand.java | 46 +++++ .../games/adventures/model/MoveCommand.java | 66 +++++++ .../games/adventures/model/PickupCommand.java | 65 +++++++ .../games/adventures/model/PickupEvent.java | 63 +++++++ .../drools/games/adventures/model/Room.java | 21 +++ .../drools/games/adventures/model/Thing.java | 66 +++++++ .../org/drools/games/adventures/Commands.drl | 169 +++++++++--------- .../org/drools/games/adventures/Events.drl | 9 +- .../org/drools/games/adventures/General.drl | 24 --- .../org/drools/games/adventures/Model.drl | 127 ------------- .../org/drools/games/adventures/Queries.drl | 18 +- .../org/drools/games/adventures/Response.drl | 34 ---- .../org/drools/games/adventures/UiView.drl | 21 ++- .../org/drools/games/adventures/data.mvel | 52 +++--- 33 files changed, 1382 insertions(+), 472 deletions(-) create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Character.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Command.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Door.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/DropCommand.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/DropEvent.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/EnterEvent.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/ExitEvent.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/GameEvent.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/GiveCommand.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/GiveEvent.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Holding.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Item.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Key.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Location.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/LockStatus.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/LookCommand.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/PickupCommand.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/PickupEvent.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Room.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/Thing.java delete mode 100644 drools-examples/src/main/resources/org/drools/games/adventures/General.drl delete mode 100644 drools-examples/src/main/resources/org/drools/games/adventures/Response.drl diff --git a/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java b/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java index d8aad068fa4..187914cf2bc 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java @@ -20,6 +20,7 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.List; +import java.util.Map; import javax.swing.BoxLayout; import javax.swing.DefaultComboBoxModel; @@ -49,11 +50,20 @@ import javax.swing.border.EmptyBorder; import javax.swing.event.InternalFrameEvent; import javax.swing.event.InternalFrameListener; +import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import net.miginfocom.layout.ConstraintParser; import net.miginfocom.swing.MigLayout; +import org.drools.games.adventures.model.DropCommand; +import org.drools.games.adventures.model.GiveCommand; +import org.drools.games.adventures.model.LookCommand; +import org.drools.games.adventures.model.MoveCommand; +import org.drools.games.adventures.model.PickupCommand; +import org.drools.games.adventures.model.Room; +import org.drools.games.adventures.model.Thing; +import org.drools.games.adventures.model.Character; import org.kie.api.runtime.Channel; public class AdventureFrame extends JFrame { @@ -73,7 +83,7 @@ public class AdventureFrame extends JFrame { private JTable inventoryTable; private JFormattedTextField cmdTextField; - private JTextArea globalEventsTextArea; + //private JTextArea globalEventsTextArea; private GameEngine gameEngine; @@ -86,7 +96,11 @@ public class AdventureFrame extends JFrame { * Create the frame. */ public AdventureFrame(UserSession session, + final GameEngine gameEngine, int onClose) { + + this.session = session; + this.gameEngine = gameEngine; setDefaultCloseOperation( onClose ); setBounds( 100, 100, @@ -131,9 +145,6 @@ public void actionPerformed(ActionEvent e) { createCharacterPanel( test ); createBuildActionsPanel( test ); createSendCommandPanel( test ); - - this.session = session; - } public UserSession getSession() { @@ -179,9 +190,10 @@ public JTable getInventoryTable() { private Component createEventsAndInvetoryPanel() { JSplitPane leftSplitPanel = new JSplitPane(); leftSplitPanel.setOrientation( JSplitPane.VERTICAL_SPLIT ); - leftSplitPanel.setDividerLocation( 500 ); + leftSplitPanel.setDividerLocation( 400 ); - Component eventsPanel = createEventsPanel(); + //Component eventsPanel = createEventsPanel(); + Component eventsPanel = createLocalEventsPanel(); leftSplitPanel.setLeftComponent( eventsPanel ); Component inventoryPanel = createInventoryPanel(); @@ -195,7 +207,7 @@ private Component createEventsPanel() { splitPanel.setResizeWeight( 0.4 ); splitPanel.setOrientation( JSplitPane.VERTICAL_SPLIT ); - splitPanel.setRightComponent( createGlobalEventsPanel() ); + //splitPanel.setRightComponent( createGlobalEventsPanel() ); splitPanel.setLeftComponent( createLocalEventsPanel() ); @@ -216,7 +228,7 @@ private Component createGlobalEventsPanel() { 50, true, true ); - globalEventsTextArea = (JTextArea) ((JViewport) pane1.getComponents()[0]).getComponents()[0]; + //globalEventsTextArea = (JTextArea) ((JViewport) pane1.getComponents()[0]).getComponents()[0]; globalEventsPanel.add( pane1 ); return globalEventsPanel; } @@ -227,7 +239,7 @@ private Component createLocalEventsPanel() { localEventsPanel.setLayout( new BoxLayout( localEventsPanel, BoxLayout.Y_AXIS ) ); - JLabel localEventsLabel = new JLabel( "Local Events" ); + JLabel localEventsLabel = new JLabel( "Events" ); localEventsPanel.add( localEventsLabel ); // JScrollPane pane2 = createTextAreaScroll( "", @@ -282,10 +294,10 @@ public void mouseClicked(MouseEvent e) { } int row = inventoryTable.rowAtPoint( e.getPoint() ); int col = inventoryTable.columnAtPoint( e.getPoint() ); - Object o = inventoryTable.getModel().getValueAt( row, + Thing t = (Thing) inventoryTable.getModel().getValueAt( row, col ); - cmdTextField.setText( cmdTextField.getText() + o.toString() + " " ); - cmd.add( o ); + cmdTextField.setText( cmdTextField.getText() + t.getName() + " " ); + cmd.add( t ); } } ); @@ -325,11 +337,23 @@ private void createCharacterPanel(JPanel parent) { characterSelectCombo.setModel( new DefaultComboBoxModel( new Object[]{null, null} ) ); parent.add( characterSelectCombo, "top, left" ); + + Map characterMap = ( Map ) gameEngine.getData().get("characters"); + Character[] characters = characterMap.values().toArray( new Character[characterMap.size()] ); + + characterSelectCombo.setModel( new DefaultComboBoxModel( characters ) ); + characterSelectCombo.setSelectedItem( characterMap.get("hero")); + characterSelectCombo.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { + + Character c = (Character) characterSelectCombo.getSelectedObjects()[0]; + org.kie.api.runtime.rule.FactHandle fh = gameEngine.getKieSession().getFactHandle(session); + session.setCharacter(c); + gameEngine.getKieSession().update(fh, session); + cmd = new ArrayList(); - cmd.add( Action.SELECT_CHARACTER ); - cmd.add( session ); + cmd.add( LookCommand.class ); cmd.add( characterSelectCombo.getSelectedObjects()[0] ); gameEngine.receiveMessage( session, cmd ); @@ -368,6 +392,7 @@ private void createBuildActionsPanel(JPanel parent) { BoxLayout.Y_AXIS ) ); JButton moveBtn = new JButton( "Move" ); + moveBtn.setToolTipText("Select one Room from the Exits, then press Send"); actionsPanel.add( moveBtn ); // msg = new ACLMessage(); // msg.setPerformative( Performative.REQUEST ); @@ -376,51 +401,55 @@ private void createBuildActionsPanel(JPanel parent) { public void actionPerformed(ActionEvent e) { cmdTextField.setText( "Move " ); cmd = new ArrayList(); - cmd.add( Action.MOVE ); + cmd.add(MoveCommand.class ); cmd.add( characterSelectCombo.getSelectedObjects()[0] ); } } ); JButton pickupBtn = new JButton( "Pick Up" ); + pickupBtn.setToolTipText("Select one from the Items list, then press Send"); actionsPanel.add( pickupBtn ); pickupBtn.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { cmdTextField.setText( "Pickup " ); cmd = new ArrayList(); - cmd.add( Action.PICKUP ); + cmd.add(PickupCommand.class); cmd.add( characterSelectCombo.getSelectedObjects()[0] ); } } ); JButton dropBtn = new JButton( "Drop" ); + dropBtn.setToolTipText("Select one from the Inventory, then press Send"); actionsPanel.add( dropBtn ); dropBtn.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { cmdTextField.setText( "Drop " ); cmd = new ArrayList(); - cmd.add( Action.DROP ); + cmd.add(DropCommand.class); cmd.add( characterSelectCombo.getSelectedObjects()[0] ); } } ); JButton giveBtn = new JButton( "Give" ); + giveBtn.setToolTipText("Select one from the Inventory, then Select the target Character, then press Send"); actionsPanel.add( giveBtn ); giveBtn.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { cmdTextField.setText( "Request Give " ); cmd = new ArrayList(); - cmd.add( Action.GIVE ); + cmd.add(GiveCommand.class); cmd.add( characterSelectCombo.getSelectedObjects()[0] ); } } ); JButton lookBtn = new JButton( "Look" ); + giveBtn.setToolTipText("Just press Send"); actionsPanel.add( lookBtn ); lookBtn.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { cmdTextField.setText( "Look " ); cmd = new ArrayList(); - cmd.add( Action.LOOK ); + cmd.add( LookCommand.class ); cmd.add( characterSelectCombo.getSelectedObjects()[0] ); } } ); @@ -459,10 +488,10 @@ public void mouseClicked(MouseEvent e) { } int row = thingsTable.rowAtPoint( e.getPoint() ); int col = thingsTable.columnAtPoint( e.getPoint() ); - Object o = thingsTable.getModel().getValueAt( row, + Thing t = (Thing) thingsTable.getModel().getValueAt( row, col ); - cmdTextField.setText( cmdTextField.getText() + o.toString() + " " ); - cmd.add( o ); + cmdTextField.setText( cmdTextField.getText() + t.getName() + " " ); + cmd.add( t ); } } ); @@ -502,10 +531,10 @@ public void mouseClicked(MouseEvent e) { } int row = exitsTable.rowAtPoint( e.getPoint() ); int col = exitsTable.columnAtPoint( e.getPoint() ); - Object o = exitsTable.getModel().getValueAt( row, + Room r = (Room) exitsTable.getModel().getValueAt( row, col ); - cmdTextField.setText( cmdTextField.getText() + o.toString() + " " ); - cmd.add( o ); + cmdTextField.setText( cmdTextField.getText() + r.getName() + " " ); + cmd.add( r ); } } ); @@ -875,35 +904,46 @@ public void send(Object object) { } } - public static class JComboBoxChannel - implements - Channel { - private JComboBox jcomboBox; - - public JComboBoxChannel(JComboBox jcomboBox) { - this.jcomboBox = jcomboBox; - } - - public void send(Object object) { - List list = (List) object; - jcomboBox.setModel( new DefaultComboBoxModel( list.toArray() ) ); - //jcomboBox.setModel( new DefaultComboBoxModel( new Object[] { "xxxxx", "yyyyyy" } ) ) ; - } - } +// public static class JComboBoxChannel +// implements +// Channel { +// private JComboBox jcomboBox; +// +// public JComboBoxChannel(JComboBox jcomboBox) { +// this.jcomboBox = jcomboBox; +// } +// +// public void send(Object object) { +// List list = (List) object; +// jcomboBox.setModel( new DefaultComboBoxModel( list.toArray() ) ); +// //jcomboBox.setModel( new DefaultComboBoxModel( new Object[] { "xxxxx", "yyyyyy" } ) ) ; +// } +// } public static class JTableChannel implements Channel { private JTable jTable; - public JTableChannel(JTable exitsTable) { - this.jTable = exitsTable; + public JTableChannel(JTable jTable) { + this.jTable = jTable; + String name = jTable.getColumnName(0); + jTable.getColumn( name ).setCellRenderer(new DefaultTableCellRenderer() { + public void setValue(Object value) { + setText(((Thing) value).getName()); + } + }); + } public void send(Object object) { + List things = (List) object; + addRows( things ); + } + + public void addRows(List list) { DefaultTableModel model = (DefaultTableModel) jTable.getModel(); - List list = (List) object; if ( model.getRowCount() < list.size() ) { Object[][] exits = new Object[list.size()][]; @@ -929,4 +969,5 @@ public void send(Object object) { } } } + } diff --git a/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java b/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java index dfb7b42fa56..b18f14f8d54 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java @@ -1,16 +1,14 @@ package org.drools.games.adventures; import org.apache.commons.io.IOUtils; -import org.drools.core.impl.KnowledgeBaseImpl; -import org.kie.api.KieBase; +import org.drools.games.adventures.model.Command; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; -import org.kie.api.runtime.rule.FactHandle; import org.mvel2.MVEL; -import org.mvel2.integration.impl.MapVariableResolverFactory; import java.io.IOException; +import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -19,127 +17,85 @@ public class GameEngine { KieSession ksession; - ClassLoader classLoader; + Map data; + public void createGame() { KieContainer kc = KieServices.Factory.get().getKieClasspathContainer(); System.out.println(kc.verify().getMessages().toString()); - ksession = kc.newKieSession( "TextAdventureKS"); - - KieBase kbase = ksession.getKieBase(); + ksession = kc.newKieSession("TextAdventureKS"); Counter c = new Counter(); - ksession.setGlobal( "counter", - c ); - - classLoader = ((KnowledgeBaseImpl) kbase).getRootClassLoader(); - ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); + ksession.setGlobal("counter", + c); + Map vars = new HashMap(); + vars.put("c", + c); try { - Thread.currentThread().setContextClassLoader( classLoader ); - Map vars = new HashMap(); - vars.put( "c", - c ); - Map map; - try { - map = (Map) MVEL.executeExpression( MVEL.compileExpression( new String( IOUtils.toByteArray(getClass().getResource("data.mvel").openStream()) ) ), - vars ); - } catch ( IOException e ) { - throw new RuntimeException( e ); - } - - for ( Object o : map.get( "rooms" ).values() ) { - ksession.insert( o ); - } + String mvelContent = new String(IOUtils.toByteArray(getClass().getResource("data.mvel").openStream())); + data = (Map) MVEL.executeExpression(MVEL.compileExpression(mvelContent), vars); + } catch (IOException e) { + throw new RuntimeException(e); + } - for ( Object o : map.get( "doors" ).values() ) { - ksession.insert( o ); - } + for (Object o : data.get("rooms").values()) { + ksession.insert( o ); + } - for ( Object o : map.get( "characters" ).values() ) { - ksession.insert( o ); - } + for ( Object o : data.get( "doors" ).values() ) { + ksession.insert( o ); + } - for ( Object o : map.get( "items" ).values() ) { - ksession.insert( o ); - } + for ( Object o : data.get( "characters" ).values() ) { + ksession.insert( o ); + } - for ( Object o : map.get( "locations" ).values() ) { - ksession.insert( o ); - } + for ( Object o : data.get( "items" ).values() ) { + ksession.insert( o ); + } - MapVariableResolverFactory f = new MapVariableResolverFactory( map ); + for ( Object o : data.get( "keys" ).values() ) { + ksession.insert( o ); + } +// +// for ( Object o : data.get( "locks" ).values() ) { +// ksession.insert( o ); +// } - String baseStr = "import org.drools.games.adventures.*; import org.drools.games.adventures.commands.*;\n"; - FactHandle fh = ksession.insert( MVEL.eval( baseStr + "new EnterEvent( characters['hero'], rooms['first floor hallway'] )", - f ) ); - ksession.fireAllRules(); - } finally { - Thread.currentThread().setContextClassLoader( currentClassLoader ); + for ( Object o : data.get( "locations" ).values() ) { + ksession.insert( o ); } } + public Map getData() { + return data; + } + public void receiveMessage(UserSession session, - List cmd) { - ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - String baseStr = "import org.drools.games.adventures.*; import org.drools.games.adventures.commands.*;\n"; + List cmdList) { try { - Thread.currentThread().setContextClassLoader( classLoader ); - Map vars = new HashMap(); - vars.put( "args", - cmd ); - MapVariableResolverFactory f = new MapVariableResolverFactory( vars ); - Action c = (Action) cmd.get( 0 ); - switch ( c ) { - case MOVE : { - ksession.insert( new Request( session, - MVEL.eval( baseStr + "new MoveCommand(args[1], args[2])", - f ) ) ); - ksession.fireAllRules(); - break; - } - case PICKUP : { - ksession.insert( new Request( session, - MVEL.eval( baseStr + "new PickupCommand(args[1], args[2])", - f ) ) ); - ksession.fireAllRules(); - break; - } - case DROP : { - ksession.insert( new Request( session, - MVEL.eval( baseStr + "new DropCommand(args[1], args[2])", - f ) ) ); - ksession.fireAllRules(); - break; - } - case GIVE : { - ksession.insert( new Request( session, - MVEL.eval( baseStr + "new GiveCommand(args[1], args[2], args[3])", - f ) ) ); - ksession.fireAllRules(); - break; - } - case LOOK : { - ksession.insert( new Request( session, - MVEL.eval( baseStr + "new LookCommand(args[1])", - f ) ) ); - ksession.fireAllRules(); - break; - } - case SELECT_CHARACTER : { - ksession.insert( new Request( session, - MVEL.eval( baseStr + "new SetSessionCharacterCommand(args[1], args[2])", - f ) ) ); - ksession.fireAllRules(); - break; - } + Class cls = (Class) cmdList.get(0); + Class[] constructorParamTypes = new Class[cmdList.size()-1]; + for ( int i = 1; i < cmdList.size(); i++) { + constructorParamTypes[i-1] = cmdList.get(i).getClass(); } + + Object[] args = cmdList.subList(1, cmdList.size() ).toArray(); + + Command cmd = (Command) cls.getDeclaredConstructors()[0].newInstance(args); + cmd.setSession( session ); + ksession.insert( cmd ); + ksession.fireAllRules(); } catch ( Exception e ) { - session.getChannels().get( "output" ).send( "Unable to Execute Command: " + cmd ); - } finally { - Thread.currentThread().setContextClassLoader( currentClassLoader ); + e.printStackTrace(); + session.getChannels().get( "output" ).send( "Unable to Execute Command: " + cmdList ); } } + public KieSession getKieSession() { + return ksession; + } + } diff --git a/drools-examples/src/main/java/org/drools/games/adventures/TextAdventure.java b/drools-examples/src/main/java/org/drools/games/adventures/TextAdventure.java index 60dea835a23..823239d5f7c 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/TextAdventure.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/TextAdventure.java @@ -1,12 +1,14 @@ package org.drools.games.adventures; import java.awt.EventQueue; +import java.util.Map; import javax.swing.JFrame; -import org.drools.games.adventures.AdventureFrame.JComboBoxChannel; import org.drools.games.adventures.AdventureFrame.JTableChannel; import org.drools.games.adventures.AdventureFrame.JTextAreaChannel; +import org.drools.games.adventures.model.*; +import org.drools.games.adventures.model.Character; public class TextAdventure { @@ -32,20 +34,24 @@ public void run() { public static void createFrame(GameEngine engine, int onClose) { UserSession session = new UserSession(); - - AdventureFrame frame = new AdventureFrame(session, onClose); + + Map characterMap = ( Map ) engine.getData().get("characters"); + session.setCharacter(characterMap.get("hero")); + + AdventureFrame frame = new AdventureFrame(session, engine, onClose); frame.setVisible( true ); - + session.getChannels().put( "output", new JTextAreaChannel( frame.getOutputTextArea() ) ); session.getChannels().put( "events", new JTextAreaChannel( frame.getLocalEventsTextArea() ) ); session.getChannels().put( "exits", new JTableChannel( frame.getExitsTable() ) ); session.getChannels().put( "things", new JTableChannel( frame.getThingsTable()) ); session.getChannels().put( "inventory", new JTableChannel( frame.getInventoryTable()) ); - session.getChannels().put( "characters", new JComboBoxChannel( frame.getCharacterSelectCombo() ) ); - - frame.setGameEngine( engine ); - + + engine.ksession.insert( session ); + LookCommand lc = new LookCommand(characterMap.get("hero")); + lc.setSession(session); + engine.getKieSession().insert(lc); engine.ksession.fireAllRules(); } } diff --git a/drools-examples/src/main/java/org/drools/games/adventures/UserSession.java b/drools-examples/src/main/java/org/drools/games/adventures/UserSession.java index 20f5a85cb71..13913b0dfe9 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/UserSession.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/UserSession.java @@ -3,28 +3,38 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import org.drools.games.adventures.model.Character; import org.kie.api.runtime.Channel; public class UserSession { - private int id; + private int id; private Map channels; - - private static AtomicInteger counter = new AtomicInteger(); - + private Character character; + + private static AtomicInteger counter = new AtomicInteger(); + public UserSession() { this.id = counter.getAndIncrement(); this.channels = new HashMap(); } - + public int getId() { return id; } - + public void setId(int id) { this.id = id; } - + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + public Map getChannels() { return channels; } diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Character.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Character.java new file mode 100644 index 00000000000..7165db543ea --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Character.java @@ -0,0 +1,21 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Character extends Thing { + + + public Character(String name) { + super(name); + } + + public Character(long id, String name) { + super(id, name); + } + + @Override + public String toString() { + return "Character{id=" + getId() +", name=" + getName() + "} "; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Command.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Command.java new file mode 100644 index 00000000000..7a56d6991cb --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Command.java @@ -0,0 +1,24 @@ +package org.drools.games.adventures.model; + +import org.drools.games.adventures.UserSession; +import org.kie.api.definition.type.Position; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public abstract class Command { + + @Position(0) + private UserSession session; + + public Command() { + } + + public UserSession getSession() { + return session; + } + + public void setSession(UserSession session) { + this.session = session; + } + +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Door.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Door.java new file mode 100644 index 00000000000..6ecf308dc60 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Door.java @@ -0,0 +1,88 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Door extends Thing { + @Position(2) + private Room fromRoom; + + @Position(3) + private Room toRoom; + + @Position(4) + private LockStatus lockStatus; + + @Position(5) + private Key key; + + public Door(Room fromRoom, Room toRoom) { + super( "Door from " + fromRoom.getName() +" to "+ toRoom.toString() ); + this.fromRoom = fromRoom; + this.toRoom = toRoom; + lockStatus = LockStatus.UNLOCKED; + } + + public Room getFromRoom() { + return fromRoom; + } + + public void setFromRoom(Room fromRoom) { + this.fromRoom = fromRoom; + } + + public Room getToRoom() { + return toRoom; + } + + public void setToRoom(Room toRoom) { + this.toRoom = toRoom; + } + + public LockStatus getLockStatus() { + return lockStatus; + } + + public void setLockStatus(LockStatus lockStatus) { + this.lockStatus = lockStatus; + } + + public Key getKey() { + return key; + } + + public void setKey(Key key) { + this.key = key; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + if (!super.equals(o)) { return false; } + + Door door = (Door) o; + + if (!fromRoom.equals(door.fromRoom)) { return false; } + if (!toRoom.equals(door.toRoom)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + fromRoom.hashCode(); + result = 31 * result + toRoom.hashCode(); + return result; + } + + @Override + public String toString() { + return "Door{" + + "fromRoom=" + fromRoom + + ", toRoom=" + toRoom + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/DropCommand.java b/drools-examples/src/main/java/org/drools/games/adventures/model/DropCommand.java new file mode 100644 index 00000000000..e3d68e91234 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/DropCommand.java @@ -0,0 +1,66 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class DropCommand extends Command { + + @Position(1) + private Character character; + + @Position(2) + private Thing thing; + + public DropCommand(Character character, Thing thing) { + this.character = character; + this.thing = thing; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + if (!super.equals(o)) { return false; } + + DropCommand that = (DropCommand) o; + + if (!character.equals(that.character)) { return false; } + if (!thing.equals(that.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + character.hashCode(); + result = 31 * result + thing.hashCode(); + return result; + } + + @Override + public String toString() { + return "DropCommand{" + + "character=" + character + + ", thing=" + thing + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/DropEvent.java b/drools-examples/src/main/java/org/drools/games/adventures/model/DropEvent.java new file mode 100644 index 00000000000..83fae17eff6 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/DropEvent.java @@ -0,0 +1,64 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class DropEvent extends GameEvent { + + @Position(0) + private Character character; + + @Position(1) + private Thing thing; + + public DropEvent(Character character, Thing thing) { + this.character = character; + this.thing = thing; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + DropEvent that = (DropEvent) o; + + if (!character.equals(that.character)) { return false; } + if (!thing.equals(that.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = character.hashCode(); + result = 31 * result + thing.hashCode(); + return result; + } + + @Override + public String toString() { + return "DropEvent{" + + "character=" + character + + ", thing=" + thing + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/EnterEvent.java b/drools-examples/src/main/java/org/drools/games/adventures/model/EnterEvent.java new file mode 100644 index 00000000000..c01a3427d0f --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/EnterEvent.java @@ -0,0 +1,64 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class EnterEvent extends GameEvent { + + @Position(0) + private Character character; + + @Position(1) + private Room room; + + public EnterEvent(Character character, Room room) { + this.character = character; + this.room = room; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Room getRoom() { + return room; + } + + public void setRoom(Room room) { + this.room = room; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + EnterEvent enterEvent = (EnterEvent) o; + + if (!character.equals(enterEvent.character)) { return false; } + if (!room.equals(enterEvent.room)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = character.hashCode(); + result = 31 * result + room.hashCode(); + return result; + } + + @Override + public String toString() { + return "EnterEvent{" + + "character=" + character + + ", room=" + room + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/ExitEvent.java b/drools-examples/src/main/java/org/drools/games/adventures/model/ExitEvent.java new file mode 100644 index 00000000000..97e1d1fb3e0 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/ExitEvent.java @@ -0,0 +1,65 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class ExitEvent extends GameEvent { + + @Position(0) + private Character character; + + @Position(1) + private Room room; + + public ExitEvent(Character character, Room room) { + this.character = character; + this.room = room; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Room getRoom() { + return room; + } + + public void setRoom(Room room) { + this.room = room; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + ExitEvent exitEvent = (ExitEvent) o; + + if (!character.equals(exitEvent.character)) { return false; } + if (!room.equals(exitEvent.room)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = character.hashCode(); + result = 31 * result + room.hashCode(); + return result; + } + + @Override + public String toString() { + return "ExitEvent{" + + "character=" + character + + ", room=" + room + + '}'; + } +} + diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/GameEvent.java b/drools-examples/src/main/java/org/drools/games/adventures/model/GameEvent.java new file mode 100644 index 00000000000..24b69c5792c --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/GameEvent.java @@ -0,0 +1,7 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class GameEvent { +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/GiveCommand.java b/drools-examples/src/main/java/org/drools/games/adventures/model/GiveCommand.java new file mode 100644 index 00000000000..5a32e8e4a00 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/GiveCommand.java @@ -0,0 +1,78 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class GiveCommand extends Command { + @Position(1) + private Character giver; + + @Position(2) + private Thing thing; + + @Position(3) + private Character receiver; + + public GiveCommand(Character giver, Thing thing, Character receiver) { + this.giver = giver; + this.thing = thing; + this.receiver = receiver; + } + + public Character getGiver() { + return giver; + } + + public void setGiver(Character giver) { + this.giver = giver; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + public Character getReceiver() { + return receiver; + } + + public void setReceiver(Character receiver) { + this.receiver = receiver; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + GiveCommand that = (GiveCommand) o; + + if (!giver.equals(that.giver)) { return false; } + if (!receiver.equals(that.receiver)) { return false; } + if (!thing.equals(that.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = giver.hashCode(); + result = 31 * result + thing.hashCode(); + result = 31 * result + receiver.hashCode(); + return result; + } + + @Override + public String toString() { + return "GiveCommand{" + + "receiver=" + receiver + + ", thing=" + thing + + ", giver=" + giver + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/GiveEvent.java b/drools-examples/src/main/java/org/drools/games/adventures/model/GiveEvent.java new file mode 100644 index 00000000000..cb6f81f0433 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/GiveEvent.java @@ -0,0 +1,78 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class GiveEvent extends GameEvent { + @Position(0) + private Character giver; + + @Position(1) + private Thing thing; + + @Position(2) + private Character receiver; + + public GiveEvent(Character giver, Thing thing, Character receiver) { + this.giver = giver; + this.thing = thing; + this.receiver = receiver; + } + + public Character getGiver() { + return giver; + } + + public void setGiver(Character giver) { + this.giver = giver; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + public Character getReceiver() { + return receiver; + } + + public void setReceiver(Character receiver) { + this.receiver = receiver; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + GiveEvent giveEvent = (GiveEvent) o; + + if (!giver.equals(giveEvent.giver)) { return false; } + if (!receiver.equals(giveEvent.receiver)) { return false; } + if (!thing.equals(giveEvent.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = giver.hashCode(); + result = 31 * result + thing.hashCode(); + result = 31 * result + receiver.hashCode(); + return result; + } + + @Override + public String toString() { + return "GiveEvent{" + + "receiver=" + receiver + + ", thing=" + thing + + ", giver=" + giver + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Holding.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Holding.java new file mode 100644 index 00000000000..c254a035088 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Holding.java @@ -0,0 +1,63 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Holding { + @Position(0) + private Character character; + + @Position(1) + private Thing thing; + + public Holding(Character character, Thing thing) { + this.character = character; + this.thing = thing; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + Holding holding = (Holding) o; + + if (!character.equals(holding.character)) { return false; } + if (!thing.equals(holding.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = character.hashCode(); + result = 31 * result + thing.hashCode(); + return result; + } + + @Override + public String toString() { + return "Holding{" + + "character=" + character + + ", thing=" + thing + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Item.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Item.java new file mode 100644 index 00000000000..5585727aca7 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Item.java @@ -0,0 +1,39 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Item extends Thing { + @Position(2) + private boolean fixed; + + public Item(String name) { + this( name, false); + } + + public Item(String name, boolean fixed) { + super( name ); + this.fixed = fixed; + } + + public Item(long id, String name, boolean fixed) { + super(name ); + this.fixed = fixed; + } + + public boolean isFixed() { + return fixed; + } + + public void setFixed(boolean fixed) { + this.fixed = fixed; + } + + + + @Override + public String toString() { + return "Item{id=" + getId() +", name=" + getName() + "} "; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Key.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Key.java new file mode 100644 index 00000000000..bce84b6d622 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Key.java @@ -0,0 +1,16 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Key extends Thing { + + public Key(String name) { + super(name); + } + + @Override + public String toString() { + return "Key{id=" + getId() +", name=" + getName() + "} "; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Location.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Location.java new file mode 100644 index 00000000000..ad2f4ac431e --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Location.java @@ -0,0 +1,62 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Location { + @Position(0) + private Thing thing; + + @Position(1) + private Thing target; + + public Location(Thing thing, Thing target) { + this.thing = thing; + this.target = target; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + public Thing getTarget() { + return target; + } + + public void setTarget(Thing target) { + this.target = target; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + Location location = (Location) o; + + if (!target.equals(location.target)) { return false; } + if (!thing.equals(location.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = thing.hashCode(); + result = 31 * result + target.hashCode(); + return result; + } + + @Override + public String toString() { + return "Location{" + + "target=" + target + + ", thing=" + thing + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/LockStatus.java b/drools-examples/src/main/java/org/drools/games/adventures/model/LockStatus.java new file mode 100644 index 00000000000..552f566e6d9 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/LockStatus.java @@ -0,0 +1,5 @@ +package org.drools.games.adventures.model; + +public enum LockStatus { + UNLOCKED, LOCKED; +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/LookCommand.java b/drools-examples/src/main/java/org/drools/games/adventures/model/LookCommand.java new file mode 100644 index 00000000000..51e9b779dbc --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/LookCommand.java @@ -0,0 +1,46 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class LookCommand extends Command { + + @Position(1) + private Character character; + + public LookCommand(Character character) { + this.character = character; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + if (!super.equals(o)) { return false; } + + LookCommand that = (LookCommand) o; + + if (!character.equals(that.character)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + character.hashCode(); + return result; + } + + +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java b/drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java new file mode 100644 index 00000000000..89c040853af --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java @@ -0,0 +1,66 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class MoveCommand extends Command { + + @Position(1) + private Character character; + + @Position(2) + private Room room; + + + + public MoveCommand(Character character, Room room) { + this.character = character; + this.room = room; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Room getRoom() { + return room; + } + + public void setRoom(Room room) { + this.room = room; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + MoveCommand that = (MoveCommand) o; + + if (!character.equals(that.character)) { return false; } + if (!room.equals(that.room)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = character.hashCode(); + result = 31 * result + room.hashCode(); + return result; + } + + @Override + public String toString() { + return "MoveCommand{" + + "character=" + character + + ", room=" + room + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/PickupCommand.java b/drools-examples/src/main/java/org/drools/games/adventures/model/PickupCommand.java new file mode 100644 index 00000000000..27a020026a3 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/PickupCommand.java @@ -0,0 +1,65 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class PickupCommand extends Command { + @Position(1) + private Character character; + + @Position(2) + private Thing thing; + + public PickupCommand(Character character, Thing thing) { + this.character = character; + this.thing = thing; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + if (!super.equals(o)) { return false; } + + PickupCommand that = (PickupCommand) o; + + if (!character.equals(that.character)) { return false; } + if (!thing.equals(that.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + character.hashCode(); + result = 31 * result + thing.hashCode(); + return result; + } + + @Override + public String toString() { + return "PickupCommand{" + + "character=" + character + + ", thing=" + thing + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/PickupEvent.java b/drools-examples/src/main/java/org/drools/games/adventures/model/PickupEvent.java new file mode 100644 index 00000000000..034118e2560 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/PickupEvent.java @@ -0,0 +1,63 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.drools.games.adventures.model.Character; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class PickupEvent extends GameEvent{ + @Position(0) + private Character character; + + @Position(1) + private Thing thing; + + public PickupEvent(Character character, Thing thing) { + this.character = character; + this.thing = thing; + } + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + PickupEvent that = (PickupEvent) o; + + if (!character.equals(that.character)) { return false; } + if (!thing.equals(that.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = character.hashCode(); + result = 31 * result + thing.hashCode(); + return result; + } + + @Override + public String toString() { + return "PickupEvent{" + + "character=" + character + + ", thing=" + thing + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Room.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Room.java new file mode 100644 index 00000000000..0a340c8bc6c --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Room.java @@ -0,0 +1,21 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Room extends Thing { + + public Room(String name) { + super(name); + } + + public Room(long id, String name) { + super(id, name); + } + + @Override + public String toString() { + return "Room{id=" + getId() +", name=" + getName() + "} "; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/Thing.java b/drools-examples/src/main/java/org/drools/games/adventures/model/Thing.java new file mode 100644 index 00000000000..849a0e9bc3e --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/Thing.java @@ -0,0 +1,66 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.Position; +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class Thing { + @Position(0) + private long id; + + @Position(1) + private String name; + + public Thing(long id, String name) { + this.id = id; + this.name = name; + } + + public Thing(String name) { + this(-1, name); + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + Thing thing = (Thing) o; + + if (id != thing.id) { return false; } + if (!name.equals(thing.name)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = (int) (id ^ (id >>> 32)); + result = 31 * result + name.hashCode(); + return result; + } + + @Override + public String toString() { + return "Thing{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl index a8f778001ea..d7e33d69a7f 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl @@ -1,129 +1,132 @@ package org.drools.games.adventures -import org.drools.games.adventures.Room; -import org.drools.games.adventures.Thing; - -import org.drools.games.adventures.Request; -import org.drools.games.adventures.Response; -import org.drools.games.adventures.SessionCharacter - -import org.drools.games.adventures.MoveCommand -import org.drools.games.adventures.Command -import org.drools.games.adventures.PickupCommand -import org.drools.games.adventures.DropCommand -import org.drools.games.adventures.LookCommand -import org.drools.games.adventures.SetSessionCharacterCommand +//import org.drools.games.adventures.Room; +//import org.drools.games.adventures.Thing; +// +//import org.drools.games.adventures.Request; +//import org.drools.games.adventures.Response; +//import org.drools.games.adventures.SessionCharacter +// +//import org.drools.games.adventures.MoveCommand +//import org.drools.games.adventures.Command +//import org.drools.games.adventures.PickupCommand +//import org.drools.games.adventures.DropCommand +//import org.drools.games.adventures.LookCommand +//import org.drools.games.adventures.SetSessionCharacterCommand +//import org.drools.games.adventures.model.EnterEvent +//import org.drools.games.adventures.model.ExitEvent + +import org.drools.games.adventures.model.*; +import java.util.List; global org.drools.games.adventures.Counter counter dialect "mvel" +function String thingsToString(List list) { + StringBuilder s = new StringBuilder(); + for( int i = 0; i < list.size(); i++ ) { + if ( i != 0 ) { + s.append( ", " ); + } + s.append( ((Thing)list.get(i)).getName() ); + } + + return s.toString(); +} + +rule processCommand when + Command() +then + setFocus( "commands" ); +end + -rule lookCmd agenda-group "commands" lock-on-active auto-focus when +rule lookCmd agenda-group "commands" when lc : LookCommand( c : character ) Location( thing == c, $room : target ) ?look( c, things, exits; ) then - str = "You are in the " + $room + "\n"; - str +="You can see " + things + "\n"; - str +="Available exits are " + exits + "\n"; + str = "You are in the " + $room.name + "\n"; + str +="You can see " + thingsToString( things ) + "\n"; + str +="Available exits are " + thingsToString( exits ) + "\n"; str +="\n"; - res = new Response( str ); - res.localId = lc.requestId; - insert( res ); + lc.session.channels["output"].send( str ); end -rule setUserSessionCharacter agenda-group "commands" lock-on-active auto-focus when - $c : SetSessionCharacterCommand() - $sc : SessionCharacter( session == $c.session, character != $c.character ) +rule validMove agenda-group "commands" when + mc : MoveCommand( c : character, r : room ) + l : Location( thing == c, ltarget : target ) @watch( !target ) + ?connect( d, r, ltarget; ) then - modify( $sc ) { character = $c.character }; - insert( new CharacterSelectedEvent( $c.character ) ); - - res = new Response( "You have selected the character " + $c.character + "\n" ); - res.localId = $c.requestId; - insert( res ); -end - -rule validMove agenda-group "commands" lock-on-active auto-focus when - mc : MoveCommand( c : character, r : room ) - l : Location( thing == c, ltarget : target ) - exists ?connect( r, ltarget; ) -then - exit = new ExitEvent( c, (Room) l.target ) + exit = new ExitEvent( c, (Room) l.target ); enter = new EnterEvent( c, r ); - + modify( l ) { target = r }; - + insert( exit ); - insert( enter ); - - res = new Response( "You have entered the " + l.target + "\n" ); - res.localId = mc.requestId; - insert( res ); + insert( enter ); + + mc.session.channels["output"].send( "You have entered the " + l.target.name + "\n" ); end -rule validPickup agenda-group "commands" lock-on-active auto-focus when - pc : PickupCommand( c : character, t : thing) - +rule roomLocked agenda-group "commands" salience 10 when + eval( true ) + mc : MoveCommand( c : character, r : room ) + l : Location( thing == c, ltarget : target ) @watch( !target ) + ?connect( d, r, ltarget; ) + Door( lockStatus == LockStatus.LOCKED ) from d +then + mc.session.channels["output"].send( "The room " + l.target.name + " is locked\n" ); + delete( mc ); +end + +rule validPickup agenda-group "commands" when + pc : PickupCommand( c : character, t : thing) + cl : Location( thing == c ) - tl : Location( thing == t, target == cl.target ) + tl : Location( thing == t, target == cl.target ) @watch( !target ) then insert( new Holding( c, t ) ); modify( tl ) { target = c }; insert( new PickupEvent( c, t ) ); - - res = new Response( "You have picked up the " + t + "\n" ); - res.localId = pc.requestId; - insert( res ); + + pc.session.channels["output"].send( "You have picked up the " + t.name + "\n" ); end -rule validDrop agenda-group "commands" lock-on-active auto-focus when - dc : DropCommand( c : character, t : thing) - - cl : Location( thing == c ) - tl : Location( thing == t ) +rule validDrop agenda-group "commands" when + dc : DropCommand( c : character, t : thing) + + cl : Location( thing == c ) + tl : Location( thing == t ) @watch( !target ) h : Holding( c, t;) then modify( tl ) { target = cl.target }; retract ( h ); - insert( new DropEvent( c, t ) ); - - res = new Response( "You have droped the " + t + "\n" ); - res.localId = dc.requestId; - insert( res ); + insert( new DropEvent( c, t ) ); + + dc.session.channels["output"].send( "You have dropped the " + t.name + "\n" ); end -rule validGive agenda-group "commands" lock-on-active auto-focus when - gc : GiveCommand( $giver : giver, $thing : thing ) - +rule validGive agenda-group "commands" when + gc : GiveCommand( $giver : giver, $thing : thing ) + // They are in the same room giverl : Location( thing == gc.giver ) Location( thing == gc.receiver, target == giverl.target ) - // The giver must be holding the thing - h : Holding( $giver, $thing;) + // The giver must be holding the thing + h : Holding( $giver, $thing;) @watch( !character ) then modify( h ) { character = gc.receiver }; - insert( new GiveEvent( gc.giver, gc.thing, gc.receiver ) ); - - res = new Response( "You have given the " + gc.thing + " to " + gc.receiver + "\n" ); - res.localId = gc.requestId; - insert( res ); -end - -rule invalidCommand agenda-group "commands" lock-on-active auto-focus when - $cmd : Command() - not Response( localId == $cmd.requestId ) -then - res = new Response( "Invalid Command: " + $cmd ); - res.localId = $cmd.requestId; - insert( res ); -end + insert( new GiveEvent( gc.giver, gc.thing, gc.receiver ) ); + + gc.session.channels["output"].send( "You have given the " + gc.thing.name + " to " + gc.receiver.name + "\n" ); +end rule retractCommand agenda-group "commands" lock-on-active auto-focus salience -100 when c : Command() then - retract( c ); + delete( c ); end diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Events.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Events.drl index 70bf87cbb64..4fbdd10117d 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Events.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/Events.drl @@ -1,15 +1,16 @@ package org.drools.games.adventures -import org.drools.games.adventures.Room; -import org.drools.games.adventures.Thing; +//import org.drools.games.adventures.Room; +//import org.drools.games.adventures.Thing; +import org.drools.games.adventures.model.*; dialect "mvel" rule printEvent salience 10 when $ge : GameEvent() - SessionCharacter( $us : session ) + session : UserSession( ) then - $us.channels["events"].send( $ge ); + session.channels["events"].send( $ge ); end diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/General.drl b/drools-examples/src/main/resources/org/drools/games/adventures/General.drl deleted file mode 100644 index f08c9fe3b75..00000000000 --- a/drools-examples/src/main/resources/org/drools/games/adventures/General.drl +++ /dev/null @@ -1,24 +0,0 @@ -package org.drools.games.adventures - -import org.drools.games.adventures.Request; -import org.drools.games.adventures.Response; -import org.drools.games.adventures.SessionCharacter - -dialect "mvel" - -rule updateUserSession when - $us : UserSession() - not SessionCharacter( session == $us ) -then - s = new SessionCharacter(); - s.session = $us; - insert( s ); -end - - -rule updateCharacters salience 5 when - $chars : List() from collect( Character() ) - $us : UserSession( ) -then - $us.channels["characters"].send( $chars ); -end \ No newline at end of file diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Model.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Model.drl index 2d2bd94e358..7b1e6268343 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Model.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/Model.drl @@ -1,130 +1,3 @@ package org.drools.games.adventures dialect "mvel" - -// Things - -declare Thing - id : long -end - -declare Character extends Thing - name : String @key -end - -declare Item extends Thing - name : String @key - fixed : boolean -end - -declare Room extends Thing - name : String @key -end - -declare Door extends Thing - fromRoom : Room @key - toRoom : Room @key -end - -declare Key extends Thing -end - -declare Lock extends Thing - key : Key @key - door : Door @key - status : String -end - -// State -declare Location - thing : Thing @key - target : Thing @key -end - -declare Holding - character : Character @key - thing : Thing @key -end - -declare SessionCharacter - session : UserSession - character : Character -end - -// Events -declare GameEvent - @role(event) -end - -declare CharacterSelectedEvent extends GameEvent - @role(event) - character : Character @key -end - -declare ExitEvent extends GameEvent - @role(event) - character : Character @key - room : Room @key -end - -declare EnterEvent extends GameEvent - @role(event) - character : Character @key - room : Room @key -end - -declare PickupEvent extends GameEvent - @role(event) - character : Character @key - thing : Thing @key -end - -declare DropEvent extends GameEvent - @role(event) - character : Character @key - thing : Thing @key -end - -declare GiveEvent extends GameEvent - @role(event) - giver : Character @key - thing : Thing @key - receiver : Character @key -end - - -// Commands -declare Command - requestId : long -end - -declare MoveCommand extends Command - character : Character @key - room : Room @key -end - -declare DropCommand extends Command - character : Character @key - thing : Thing @key -end - -declare GiveCommand extends Command - giver : Character @key - thing : Thing @key - receiver : Character @key -end - -declare PickupCommand extends Command - character : Character @key - thing : Thing @key -end - -declare LookCommand extends Command - character : Character @key -end - -declare SetSessionCharacterCommand extends Command - session : UserSession @key - character : Character @key -end - diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Queries.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Queries.drl index 85ba3b5d613..48750c7b842 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Queries.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/Queries.drl @@ -2,14 +2,16 @@ package org.drools.games.adventures import java.util.List -import org.drools.games.adventures.Character -import org.drools.games.adventures.Room -import org.drools.games.adventures.Location - -query connect( Room $x, Room $y ) - Door($id, $x, $y;) +//import org.drools.games.adventures.Character +//import org.drools.games.adventures.Room +//import org.drools.games.adventures.Location +import org.drools.games.adventures.model.*; +import org.drools.games.adventures.UserSession; + +query connect( Door $d, Room $x, Room $y ) + $d := Door($id, $name, $x, $y;) or - Door($id, $y, $x;) + $d :=Door($id, $name, $y, $x;) end query isContainedIn( Thing $x, Thing $y ) @@ -28,7 +30,7 @@ end query exits(Character $char, List $exits) $char := Character() Location( $char, $room; ) - $exits := List() from accumulate( connect($room, $exit;), + $exits := List() from accumulate( connect($door, $room, $exit;), collectList( $exit ) ) end diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Response.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Response.drl deleted file mode 100644 index 3bc83b43bc8..00000000000 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Response.drl +++ /dev/null @@ -1,34 +0,0 @@ -package org.drools.games.adventures - -import org.drools.games.adventures.Request; -import org.drools.games.adventures.Response; -import org.drools.games.adventures.SessionCharacter - -global org.drools.games.adventures.Counter counter - -dialect "mvel" - -rule insertRequestCommand no-loop when - $rq : Request() - $cmd : Command() from $rq.object -then - modify( $rq ) { localId = counter.getAndIncrement() }; - $cmd.requestId = $rq.localId; - insert( $cmd ); -end - - -rule retractRequest no-loop salience -100 when - $rq : Request() - not Command( requestId == $rq.localId ) -then - retract ( $rq ); -end - -rule handleResponse when - $rq : Request() - $rs : Response( localId == $rq.localId ) -then - $rq.session.channels["output"].send( $rs.object ); - retract ( $rs ); -end \ No newline at end of file diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/UiView.drl b/drools-examples/src/main/resources/org/drools/games/adventures/UiView.drl index fa78c29fc86..0241714aac3 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/UiView.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/UiView.drl @@ -1,10 +1,12 @@ package org.drools.games.adventures -import org.drools.games.adventures.Room; -import org.drools.games.adventures.Thing; +//import org.drools.games.adventures.Room; +//import org.drools.games.adventures.Thing; +import org.drools.games.adventures.model.*; dialect "mvel" +/* rule updateOnCharacterSelected salience 5 when SessionCharacter( $char : character, $us : session ) Location( thing == $char, $room : target ) @@ -16,25 +18,26 @@ then str +="\n"; $us.channels["output"].send( str ); -end +end + */ rule updateThings salience 5 when - SessionCharacter( $char : character, $us : session ) + session : UserSession( $char : character ) things( $char, $things; ) then - $us.channels["things"].send( $things ); + session.channels["things"].send( $things ); end rule updateInventory salience 5 when - SessionCharacter( $char : character, $us : session ) + session : UserSession( $char : character ) inventory( $char, $things; ) then - $us.channels["inventory"].send( $things ); + session.channels["inventory"].send( $things ); end rule updateExits salience 5 when - SessionCharacter($char : character, $us : session ) + session : UserSession( $char : character ) exits( $char, $exits; ) then - $us.channels["exits"].send( $exits ); + session.channels["exits"].send( $exits ); end \ No newline at end of file diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel index 690b4ddf712..af04c01b122 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel +++ b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel @@ -1,17 +1,20 @@ -import org.drools.games.adventures.Thing; -import org.drools.games.adventures.Character; -import org.drools.games.adventures.Item; -import org.drools.games.adventures.Room; -import org.drools.games.adventures.Door; -import org.drools.games.adventures.Location; +import org.drools.games.adventures.model.Thing; +import org.drools.games.adventures.model.Character; +import org.drools.games.adventures.model.Item; +import org.drools.games.adventures.model.Key; +import org.drools.games.adventures.model.Lock; +import org.drools.games.adventures.model.Room; +import org.drools.games.adventures.model.Door; +import org.drools.games.adventures.model.Location; import java.util.HashMap; -rooms = [ - "basement" : new Room("basement"), + +rooms = [ + "basement" : new Room("basement"), "lounge" : new Room("lounge"), "dining room" : new Room("dining room"), - "kitchen" : new Room("kitchen"), - "ground floor hallway" : new Room("ground floor hallway"), + "kitchen" : new Room("kitchen"), + "ground floor hallway" : new Room("ground floor hallway"), "bedroom1" : new Room("bedroom1"), "bedroom2" : new Room("bedroom2"), "bathroom" : new Room("bathroom"), @@ -20,7 +23,7 @@ rooms = [ ]; foreach( room : rooms.values ) { - room.id = c.getAndIncrement(); + room.id = c.getAndIncrement(); } doors = [ @@ -29,20 +32,23 @@ doors = [ "d2" : new Door( rooms["ground floor hallway"], rooms["lounge"]), "d3" : new Door( rooms["ground floor hallway"], rooms["dining room"] ), "d4" : new Door( rooms["ground floor hallway"], rooms["kitchen"]), - "d5" : new Door( rooms["ground floor hallway"], rooms[ "first floor hallway"] ), - + "d5" : new Door( rooms["ground floor hallway"], rooms[ "first floor hallway"] ), + "d6" : new Door( rooms["first floor hallway"], rooms[ "bedroom1"] ), "d7" : new Door( rooms["first floor hallway"], rooms[ "bedroom2"] ), "d8" : new Door( rooms["first floor hallway"], rooms[ "bathroom"] ), - "d9" : new Door( rooms["first floor hallway"], rooms[ "office"] ) + "d9" : new Door( rooms["first floor hallway"], rooms[ "office"] ) ]; -//keys = [ "key1" : new Key() ]; +keys = [ "key1" : new Key("basement key") ]; +for( key : keys.values ) { + key.id = c.getAndIncrement(); +} -//locks = [ "lock1" : new lock().{ +with(doors["d1"]){ lockStatus = LockStatus.LOCKED, key = keys["key1"] }; characters = [ "hero" : new Character( "hero" ), "monster" : new Character( "monster" ) ]; -foreach( character : characters.values ) { +for( character : characters.values ) { character.id = c.getAndIncrement(); } @@ -50,22 +56,22 @@ items = [ "mace" : new Item( "mace" ), "cucumber" : new Item( "cucumber" ), "torch" : new Item( "torch" ), - "umbrella" : new Item( "umbrella" ) + "umbrella" : new Item( "umbrella" ) ]; -foreach( item : items.values ) { +for( item : items.values ) { item.id = c.getAndIncrement(); item.fixed = false; } -locations = [ +locations = [ "mace" : new Location( items["mace"], rooms["basement"] ), "monster" : new Location( characters["monster"], rooms["basement"] ), "cucumber" : new Location( items["cucumber"], rooms["kitchen"] ), - "torch" : new Location( items["torch"], rooms["office"] ), + "torch" : new Location( items["torch"], rooms["office"] ), "hero" : new Location( characters["hero"], rooms["ground floor hallway"] ), - "umbrella" : new Location( items["umbrella"], rooms["ground floor hallway"] ) + "umbrella" : new Location( items["umbrella"], rooms["ground floor hallway"] ) ]; return [ "rooms" : rooms, "doors" : doors, "characters" : characters, - "items" : items, "locations" : locations ]; \ No newline at end of file + "items" : items, "locations" : locations, "keys" : keys ]; \ No newline at end of file From d80c6da6916c1490921f17c757929d690846815f Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 23 Jul 2014 11:50:10 +0200 Subject: [PATCH 50/76] remove wrong import from TextAdventure data file (cherry picked from commit f12606fe6f6d0f999d1d65c82729c35e0950ffd3) --- .../src/main/resources/org/drools/games/adventures/data.mvel | 1 - 1 file changed, 1 deletion(-) diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel index af04c01b122..38cd15b91b6 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel +++ b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel @@ -2,7 +2,6 @@ import org.drools.games.adventures.model.Thing; import org.drools.games.adventures.model.Character; import org.drools.games.adventures.model.Item; import org.drools.games.adventures.model.Key; -import org.drools.games.adventures.model.Lock; import org.drools.games.adventures.model.Room; import org.drools.games.adventures.model.Door; import org.drools.games.adventures.model.Location; From 1fabc3ebcf22c12e0b7332bd7da656ac0acd2f43 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 23 Jul 2014 17:55:47 +0200 Subject: [PATCH 51/76] [DROOLS-561] test case reproducing a NPE when having a shared query node --- .../compiler/integrationtests/Misc2Test.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index 73dc75130aa..1a544bae1a0 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -6268,4 +6268,61 @@ public void testCorrectErrorMessageOnDeclaredTypeCompilation() throws Exception Results results = ks.newKieBuilder( kfs ).buildAll().getResults(); assertEquals(1, results.getMessages().size()); } + + @Test + public void testFieldNameStartingWithUnderscore() throws Exception { + // DROOLS-554 + String str = "import " + Underscore.class.getCanonicalName() + ";\n" + + "rule R when\n" + + " Underscore( _id == \"test\" )\n" + + "then\n" + + "end\n"; + + KieServices ks = KieServices.Factory.get(); + KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); + Results results = ks.newKieBuilder( kfs ).buildAll().getResults(); + assertEquals(0, results.getMessages().size()); + } + + public static class Underscore { + private String _id; + + public String get_id() { + return _id; + } + + public void set_id(String _id) { + this._id = _id; + } + } + + @Test @Ignore + public void testSharedQueryNode() throws Exception { + // DROOLS-561 + String drl = + "query find( Integer $i, String $s )\n" + + " $i := Integer( toString() == $s )\n" + + "end\n" + + "\n" + + "rule R2 salience -1 when\n" + + " $s : String()\n" + + " ?find( i, $s; )\n" + + "then\n" + + "end\n" + + "rule R1 when\n" + + " $s : String()\n" + + " ?find( i, $s; )\n" + + " $i : Integer( this == 1 ) from i\n" + + "then\n" + + " delete( $s );\n" + + "end\n"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ksession = helper.build().newKieSession(); + + ksession.insert("1"); + ksession.insert(1); + ksession.fireAllRules(); + } } \ No newline at end of file From a690ccc9b75209f86919275ab0ff73f69df0f36e Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 24 Jul 2014 10:05:56 +0200 Subject: [PATCH 52/76] [DROOLS-561] pass the right staged tuple set to the PhreakQueryNode (cherry picked from commit 624c43ae5c3de6ba26ae59c886b46974b66705e0) --- .../org/drools/compiler/integrationtests/Misc2Test.java | 2 +- .../java/org/drools/core/phreak/RuleNetworkEvaluator.java | 7 ++++--- .../resources/org/drools/games/adventures/Commands.drl | 6 +----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index 1a544bae1a0..3590e8b2bbd 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -6296,7 +6296,7 @@ public void set_id(String _id) { } } - @Test @Ignore + @Test public void testSharedQueryNode() throws Exception { // DROOLS-561 String drl = diff --git a/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluator.java b/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluator.java index a384d54a2bc..56f830a5ea0 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluator.java +++ b/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluator.java @@ -350,7 +350,7 @@ public void innerEval(LeftInputAdapterNode liaNode, break; } case NodeTypeEnums.QueryElementNode: { - exitInnerEval = evalQueryNode(liaNode, pmem, node, bit, nodeMem, smems, smemIndex, trgTuples, wm, stack, visitedRules, srcTuples, sink); + exitInnerEval = evalQueryNode(liaNode, pmem, node, bit, nodeMem, smems, smemIndex, trgTuples, wm, stack, visitedRules, srcTuples, sink, stagedLeftTuples); break; } case NodeTypeEnums.TimerConditionNode: { @@ -429,7 +429,8 @@ private boolean evalQueryNode(LeftInputAdapterNode liaNode, LinkedList stack, Set visitedRules, LeftTupleSets srcTuples, - LeftTupleSinkNode sink) { + LeftTupleSinkNode sink, + LeftTupleSets stagedLeftTuples) { QueryElementNodeMemory qmem = (QueryElementNodeMemory) nodeMem; if (srcTuples.isEmpty() && qmem.getResultLeftTuples().isEmpty()) { @@ -462,7 +463,7 @@ private boolean evalQueryNode(LeftInputAdapterNode liaNode, stack.add(stackEntry); pQueryNode.doNode(qnode, (QueryElementNodeMemory) nodeMem, stackEntry, sink, - wm, srcTuples, trgTuples, getTargetStagedLeftTuples(node, wm, smems[smemIndex])); + wm, srcTuples, trgTuples, stagedLeftTuples); SegmentMemory qsmem = ((QueryElementNodeMemory) nodeMem).getQuerySegmentMemory(); List qpmems = qsmem.getPathMemories(); diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl index d7e33d69a7f..c1052fd0111 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl @@ -71,11 +71,7 @@ then mc.session.channels["output"].send( "You have entered the " + l.target.name + "\n" ); end -rule roomLocked agenda-group "commands" salience 10 when - eval( true ) - mc : MoveCommand( c : character, r : room ) - l : Location( thing == c, ltarget : target ) @watch( !target ) - ?connect( d, r, ltarget; ) +rule roomLocked extends validMove agenda-group "commands" salience 10 when Door( lockStatus == LockStatus.LOCKED ) from d then mc.session.channels["output"].send( "The room " + l.target.name + " is locked\n" ); From ccf149851be05836f500497d766fe7e08ec6108e Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 24 Jul 2014 16:58:34 +0200 Subject: [PATCH 53/76] [BZ-1122738] fix CompositeMaxDurationTimer (cherry picked from commit cb1e2746afc7d9a2fd8bf5b0a56524f146f75e92) --- .../compiler/integrationtests/CepEspTest.java | 50 +++++++++++++++++++ .../time/impl/CompositeMaxDurationTimer.java | 35 ++++++++----- .../drools/core/time/impl/DurationTimer.java | 26 +++++----- .../impl/CompositeMaxDurationTimerTest.java | 11 ++-- 4 files changed, 93 insertions(+), 29 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java index d59b1f9257b..965058dcfb7 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java @@ -5316,4 +5316,54 @@ public void testDurationMemoryLeakWithAlwaysLinkedRules() throws Exception { } } } + + @Test + public void test2NotsWithTemporalConstraints() { + // BZ-1122738 DROOLS-479 + String drl = "import " + SimpleEvent.class.getCanonicalName() + "\n" + + "import java.util.Date\n" + + "\n" + + "declare OtherFact\n" + + " @role( event )\n" + + "end\n" + + "\n" + + "declare SimpleEvent\n" + + " @role( event )\n" + + " @timestamp( dateEvt )\n" + + "end\n" + + "\n" + + "\n" + + "rule R\n" + + " when\n" + + " $e : SimpleEvent()\n" + + " not OtherFact( this after[0, 1h] $e )\n" + + " not OtherFact( this after[0, 1h] $e )\n" + + " then\n" + + " $e.setCode(\"code2\");\n" + + " end\n " + + ""; + + KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); + kbuilder.add( ResourceFactory.newByteArrayResource( drl.getBytes() ), ResourceType.DRL); + if ( kbuilder.hasErrors() ) { + fail( kbuilder.getErrors().toString() ); + } + KieBaseConfiguration baseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); + baseConfig.setOption( EventProcessingOption.STREAM ); + KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( baseConfig ); + kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); + + KieSessionConfiguration sessionConfig = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); + sessionConfig.setOption( ClockTypeOption.get( ClockType.PSEUDO_CLOCK.getId() ) ); + + final KieSession ksession = kbase.newKieSession(sessionConfig, null); + PseudoClockScheduler clock = ksession.getSessionClock(); + clock.setStartupTime(System.currentTimeMillis()); + + SimpleEvent event = new SimpleEvent("code1"); + event.setDateEvt(System.currentTimeMillis() - (2 * 60 * 60 * 1000)); + ksession.insert(event); + ksession.fireAllRules(); + assertEquals("code2", event.getCode()); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/time/impl/CompositeMaxDurationTimer.java b/drools-core/src/main/java/org/drools/core/time/impl/CompositeMaxDurationTimer.java index bd7b14c24fe..60c9cd16c0d 100644 --- a/drools-core/src/main/java/org/drools/core/time/impl/CompositeMaxDurationTimer.java +++ b/drools-core/src/main/java/org/drools/core/time/impl/CompositeMaxDurationTimer.java @@ -16,15 +16,6 @@ package org.drools.core.time.impl; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.drools.core.WorkingMemory; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.reteoo.LeftTuple; import org.drools.core.rule.ConditionalElement; @@ -33,6 +24,14 @@ import org.drools.core.time.Trigger; import org.kie.api.runtime.Calendars; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + /** * While a rule might have multiple DurationTimers, due to LHS CEP rules, there can only ever * be one timer attribute. Duration rules should be considered a priority over the one timer rule. @@ -72,7 +71,7 @@ public Trigger createTrigger( Activation item, InternalWorkingMemory wm ) { long timestamp = ((InternalWorkingMemory) wm).getTimerService().getCurrentTime(); String[] calendarNames = item.getRule().getCalendars(); Calendars calendars = ((InternalWorkingMemory) wm).getCalendars(); - return createTrigger( timestamp, calendarNames, calendars ); + return createTrigger( getMaxTimestamp(item.getTuple(), timestamp), calendarNames, calendars ); } public Trigger createTrigger(long timestamp, @@ -82,7 +81,7 @@ public Trigger createTrigger(long timestamp, Calendars calendars, Declaration[][] declrs, InternalWorkingMemory wm) { - return createTrigger( timestamp, calendarNames, calendars ); + return createTrigger( getMaxTimestamp(leftTuple, timestamp), calendarNames, calendars ); } public Trigger createTrigger( long timestamp, // current time @@ -92,7 +91,7 @@ public Trigger createTrigger( long timestamp, // current time throw new IllegalStateException( "CompositeMaxDurationTimer cannot have no durations" ); } - Date maxDurationDate = new Date( getMaxDuration() + timestamp ); + Date maxDurationDate = new Date( timer != null ? getMaxDuration() + timestamp : timestamp ); return new CompositeMaxDurationTrigger( maxDurationDate, timer != null ? timer.createTrigger( timestamp, @@ -102,6 +101,18 @@ public Trigger createTrigger( long timestamp, // current time calendars ); } + private long getMaxTimestamp(LeftTuple leftTuple, long timestamp) { + if (timer != null) { + return timestamp; + } + long result = 0; + for ( DurationTimer durationTimer : durations ) { + result = Math.max( result, + durationTimer.getDuration() + durationTimer.getEventTimestamp(leftTuple, timestamp) ); + } + return result; + } + private long getMaxDuration() { long result = 0; for ( DurationTimer durationTimer : durations ) { diff --git a/drools-core/src/main/java/org/drools/core/time/impl/DurationTimer.java b/drools-core/src/main/java/org/drools/core/time/impl/DurationTimer.java index 3ffe5643abf..85e0596284c 100644 --- a/drools-core/src/main/java/org/drools/core/time/impl/DurationTimer.java +++ b/drools-core/src/main/java/org/drools/core/time/impl/DurationTimer.java @@ -16,22 +16,22 @@ package org.drools.core.time.impl; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.Map; - import org.drools.core.common.EventFactHandle; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.reteoo.LeftTuple; import org.drools.core.rule.ConditionalElement; import org.drools.core.rule.Declaration; -import org.drools.core.util.NumberUtils; import org.drools.core.spi.Activation; import org.drools.core.time.Trigger; +import org.drools.core.util.NumberUtils; import org.kie.api.runtime.Calendars; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Map; + public class DurationTimer extends BaseTimer implements Timer, @@ -88,11 +88,13 @@ public Trigger createTrigger(long timestamp, Calendars calendars, Declaration[][] declrs, InternalWorkingMemory wm) { - if ( eventFactHandle != null ) { - EventFactHandle fh = (EventFactHandle) leftTuple.get(eventFactHandle); - timestamp = fh.getStartTimestamp(); - } - return createTrigger(timestamp, calendarNames, calendars); + return createTrigger(getEventTimestamp(leftTuple, timestamp), calendarNames, calendars); + } + + long getEventTimestamp(LeftTuple leftTuple, long timestamp) { + return eventFactHandle != null ? + ((EventFactHandle) leftTuple.get(eventFactHandle)).getStartTimestamp() : + timestamp; } public Trigger createTrigger(long timestamp, diff --git a/drools-core/src/test/java/org/drools/core/time/impl/CompositeMaxDurationTimerTest.java b/drools-core/src/test/java/org/drools/core/time/impl/CompositeMaxDurationTimerTest.java index 01bce7ffc41..e1e0b5cde34 100644 --- a/drools-core/src/test/java/org/drools/core/time/impl/CompositeMaxDurationTimerTest.java +++ b/drools-core/src/test/java/org/drools/core/time/impl/CompositeMaxDurationTimerTest.java @@ -1,11 +1,12 @@ package org.drools.core.time.impl; -import static org.junit.Assert.*; +import org.drools.core.time.Trigger; +import org.junit.Test; import java.util.Date; -import org.drools.core.time.Trigger; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; public class CompositeMaxDurationTimerTest { @@ -16,7 +17,7 @@ public void testJustMaxDuration() { timer.addDurationTimer( new DurationTimer( 50 ) ); timer.addDurationTimer( new DurationTimer( 70 ) ); Date timestamp = new Date(); - Trigger trigger = timer.createTrigger( timestamp.getTime(), null, null ); + Trigger trigger = timer.createTrigger( timestamp.getTime(), null, null, null, null, null, null ); assertEquals( new Date( timestamp.getTime() + 70 ), trigger.hasNextFireTime() ); assertNull( trigger.nextFireTime() ); @@ -33,7 +34,7 @@ public void testMixedDurationAndTimer() { timer.setTimer( new IntervalTimer(null, null, 6, 40, 25) ); Date timestamp = new Date(); - Trigger trigger = timer.createTrigger( timestamp.getTime(), null, null ); + Trigger trigger = timer.createTrigger( timestamp.getTime(), null, null, null, null, null, null ); // ignores the first interval timer at 65 assertEquals( new Date( timestamp.getTime() + 70 ), trigger.hasNextFireTime() ); From 12c083a2dfa0d60b68323c823364077921d60bf8 Mon Sep 17 00:00:00 2001 From: sotty Date: Fri, 25 Jul 2014 01:58:22 +0200 Subject: [PATCH 54/76] [DROOLS-535] fix build on windows platforms --- .../kie/builder/impl/ClasspathKieProject.java | 7 +- .../compiler/lang/dsl/DefaultExpander.java | 14 +- .../drools/compiler/cdi/CDITestRunner.java | 18 +- .../compiler/compiler/DrlParserTest.java | 14 +- .../compiler/integrationtests/CepEspTest.java | 16 +- .../compiler/integrationtests/Misc2Test.java | 3 +- .../TimerAndCalendarTest.java | 4 +- .../compiler/kproject/KieProjectCDITest.java | 10 + .../KieProjectDefaultClasspathTest.java | 10 + .../lang/dsl/DSLMappingEntryTest.java | 25 +- .../compiler/lang/dsl/DSLMappingFileTest.java | 24 +- .../lang/dsl/DSLTokenizedMappingFileTest.java | 11 +- .../lang/dsl/DefaultExpanderTest.java | 300 +++++++++--------- .../java/org/drools/core/util/IoUtils.java | 11 +- .../org/drools/core/util/FileManager.java | 8 +- 15 files changed, 265 insertions(+), 210 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java index 9c4d2c9f73d..134607e0c34 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java @@ -2,6 +2,7 @@ import org.drools.compiler.kie.builder.impl.event.KieModuleDiscovered; import org.drools.compiler.kie.builder.impl.event.KieServicesEventListerner; +import org.drools.core.util.IoUtils; import org.drools.core.util.StringUtils; import org.drools.compiler.kproject.ReleaseIdImpl; import org.drools.compiler.kproject.models.KieModuleModelImpl; @@ -174,7 +175,7 @@ private static InternalKieModule fetchKModule(URL url, String fixedURL) { String rootPath = fixedURL; if ( rootPath.lastIndexOf( ':' ) > 0 ) { - rootPath = fixedURL.substring( rootPath.lastIndexOf( ':' ) + 1 ); + rootPath = IoUtils.asSystemSpecificPath( rootPath, rootPath.lastIndexOf( ':') ); } return createInternalKieModule(url, fixedURL, kieProject, releaseId, rootPath); @@ -191,7 +192,7 @@ public static String getPomProperties(String urlPathToAdd) { String pomProperties = null; String rootPath = urlPathToAdd; if ( rootPath.lastIndexOf( ':' ) > 0 ) { - rootPath = urlPathToAdd.substring( rootPath.lastIndexOf( ':' ) + 1 ); + rootPath = IoUtils.asSystemSpecificPath( rootPath, rootPath.lastIndexOf( ':' ) ); } if ( urlPathToAdd.endsWith( ".jar" ) || urlPathToAdd.endsWith( "/content" ) ) { @@ -354,7 +355,7 @@ public static String fixURLFromKProjectPath(URL url) { int firstSlash = urlPath.indexOf( '/' ); colonIndex = firstSlash > 0 ? urlPath.lastIndexOf( ":", firstSlash ) : urlPath.lastIndexOf( ":" ); if ( colonIndex >= 0 ) { - urlPath = urlPath.substring( colonIndex + 1 ); + urlPath = IoUtils.asSystemSpecificPath(urlPath, colonIndex); } try { diff --git a/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java b/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java index 5f151205b47..9b34682bc41 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java +++ b/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java @@ -188,7 +188,7 @@ public String expand(String drl) { int offset = 0; int nlPos; int iLine = 1; - while ( (nlPos = buf.indexOf( "\n", + while ( (nlPos = buf.indexOf( nl, offset )) >= 0 ) { fmt.format( "%4d %s%n", iLine++, @@ -544,7 +544,7 @@ private String expandLHS(final String lhs, // logger.info( "*** LHS>" + lhs + "<" ); final StringBuilder buf = new StringBuilder(); - final String[] lines = lhs.split( "\n", + final String[] lines = lhs.split( nl, -1 ); // since we assembled the string, we know line breaks are \n final String[] expanded = new String[lines.length]; // buffer for expanded lines int lastExpanded = -1; @@ -599,7 +599,7 @@ private String expandLHS(final String lhs, } for ( int i = 0; i <= lastExpanded; i++ ) { buf.append( expanded[i] ); - buf.append( "\n" ); + buf.append( nl ); } return buf.toString(); @@ -614,7 +614,7 @@ private String expandLHS(final String lhs, private String expandRHS(final String lhs, int lineOffset) { final StringBuilder buf = new StringBuilder(); - final String[] lines = lhs.split( "\n", + final String[] lines = lhs.split( nl, -1 ); // since we assembled the string, we know line breaks are \n final String[] expanded = new String[lines.length]; // buffer for expanded lines @@ -681,11 +681,11 @@ private String expandRHS(final String lhs, for ( int i = 0; i <= lastExpanded; i++ ) { buf.append( expanded[i] ); - buf.append( "\n" ); + buf.append( nl ); } if ( lines.length == 0 ) { - buf.append( "\n" ); + buf.append( nl ); } return buf.toString(); } @@ -697,7 +697,7 @@ private String loadDrlFile(final Reader drl) throws IOException { String line; while ( (line = input.readLine()) != null ) { buf.append( line ); - buf.append( "\n" ); + buf.append( nl ); } return buf.toString(); } diff --git a/drools-compiler/src/test/java/org/drools/compiler/cdi/CDITestRunner.java b/drools-compiler/src/test/java/org/drools/compiler/cdi/CDITestRunner.java index 1bd3af2b1f1..df99786c241 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/cdi/CDITestRunner.java +++ b/drools-compiler/src/test/java/org/drools/compiler/cdi/CDITestRunner.java @@ -77,7 +77,7 @@ public static void setUp(File... files) { public static void tearDown() { try { - if ( CDITestRunner.weld != null ) { + if ( CDITestRunner.weld != null ) { CDITestRunner.weld.shutdown(); CDITestRunner.weld = null; @@ -87,7 +87,21 @@ public static void tearDown() { } } finally { try { - Thread.currentThread().setContextClassLoader( origCl ); + // FIXME Java 7+ + // on Windows, the URLClassLoader will not release all resources, + // so the attempt to delete the temporary files will fail. + // an explicit dispose call is needed, but it has not been introduced until Java7+ + // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4950148 + + /* + try { + ((URLClassLoader) Thread.currentThread().getContextClassLoader()).close(); + } catch (IOException e) { + e.printStackTrace(); + } + */ + + Thread.currentThread().setContextClassLoader( origCl ); } finally { fileManager.tearDown(); } diff --git a/drools-compiler/src/test/java/org/drools/compiler/compiler/DrlParserTest.java b/drools-compiler/src/test/java/org/drools/compiler/compiler/DrlParserTest.java index cd2dce3adcc..036316b2d47 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/compiler/DrlParserTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/compiler/DrlParserTest.java @@ -23,20 +23,22 @@ public class DrlParserTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testExpandDRL() throws Exception { - String dsl = "[condition]Something=Something()\n[then]another=another();"; - String drl = "rule 'foo' \n when \n Something \n then \n another \nend"; + String dsl = "[condition]Something=Something()" + NL + "[then]another=another();"; + String drl = "rule 'foo' " + NL + " when " + NL + " Something " + NL + " then " + NL + " another " + NL + "end"; DrlParser parser = new DrlParser(LanguageLevelOption.DRL5); String result = parser.getExpandedDRL( drl, new StringReader(dsl)); - assertEqualsIgnoreWhitespace( "rule 'foo' \n when \n Something() \n then \n another(); \nend", result ); + assertEqualsIgnoreWhitespace( "rule 'foo' " + NL + " when " + NL + " Something() " + NL + " then " + NL + " another(); " + NL + "end", result ); } @Test public void testExpandDRLUsingInjectedExpander() throws Exception { - String dsl = "[condition]Something=Something()\n[then]another=another();"; - String drl = "rule 'foo' \n when \n Something \n then \n another \nend"; + String dsl = "[condition]Something=Something()" + NL + "[then]another=another();"; + String drl = "rule 'foo' " + NL + " when " + NL + " Something " + NL + " then " + NL + " another " + NL + "end"; DefaultExpanderResolver resolver = new DefaultExpanderResolver(new StringReader(dsl)); @@ -53,7 +55,7 @@ public void testExpandDRLUsingInjectedExpander() throws Exception { DrlParser parser = new DrlParser(LanguageLevelOption.DRL5); String result = parser.getExpandedDRL( drl, resolver); - assertEqualsIgnoreWhitespace( "rule 'foo' \n when \n Something() \n then \n another(); \nend", result ); + assertEqualsIgnoreWhitespace( "rule 'foo' " + NL + " when " + NL + " Something() " + NL + " then " + NL + " another(); " + NL + "end", result ); } private void assertEqualsIgnoreWhitespace(final String expected, diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java index 965058dcfb7..29237614fd5 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java @@ -4086,9 +4086,10 @@ public void testDuplicateFiring1() throws InterruptedException { //init session clock KieSessionConfiguration sessionConfig = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); - sessionConfig.setOption( ClockTypeOption.get("realtime") ); + sessionConfig.setOption( ClockTypeOption.get("pseudo") ); //init stateful knowledge session StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(sessionConfig, null); + SessionPseudoClock clock = ksession.getSessionClock(); ArrayList list = new ArrayList( ); ksession.setGlobal( "list", list ); @@ -4106,11 +4107,11 @@ public void testDuplicateFiring1() throws InterruptedException { System.out.println(i + ". fireAllRules()"); ksession.fireAllRules(); - Thread.sleep(105); + clock.advanceTime(105, TimeUnit.MILLISECONDS); } //let thread sleep for another 1m to see if dereffered rules fire (timers, (not) after rules) - Thread.sleep(100*40*1); + clock.advanceTime(100*40*1, TimeUnit.MILLISECONDS); ksession.fireAllRules(); assertEquals( Arrays.asList( 1L, 2L, 3L, 3L, 3L, 3L, -1 ), list ); @@ -4223,13 +4224,14 @@ public void testPastEventExipration() throws InterruptedException { kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); KieSessionConfiguration sessionConfig = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); - sessionConfig.setOption( ClockTypeOption.get("realtime") ); + sessionConfig.setOption( ClockTypeOption.get("pseudo") ); //init stateful knowledge session StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession( sessionConfig, null ); + SessionPseudoClock clock = ksession.getSessionClock(); ArrayList list = new ArrayList( ); ksession.setGlobal( "list", list ); - long now = new Date().getTime(); + long now = 0; StockTick event1 = new StockTick( 1, "XXX", 1.0, now ); StockTick event2 = new StockTick( 2, "XXX", 1.0, now + 240 ); @@ -4241,11 +4243,11 @@ public void testPastEventExipration() throws InterruptedException { ksession.insert( event3 ); ksession.insert( event4 ); - Thread.sleep( 220 ); + clock.advanceTime( 220, TimeUnit.MILLISECONDS ); ksession.fireAllRules(); - Thread.sleep( 400 ); + clock.advanceTime( 400, TimeUnit.MILLISECONDS ); ksession.fireAllRules(); diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index 3590e8b2bbd..c7cf0a49a6f 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -3146,7 +3146,8 @@ public void testMvelJittingWithTraitProxies() throws Exception { public void testReportErrorOnWrongDateEffective() { // BZ-1013545 String drl = - "rule X date-effective \"9-Luglio-1974\" when\n" + + // ensure no Locale can parse the Date + "rule X date-effective \"9-asbrdfh-1974\" when\n" + " $s : String() " + "then\n" + "end\n"; diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/TimerAndCalendarTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/TimerAndCalendarTest.java index 01bfac8d4cf..498ccc75cb4 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/TimerAndCalendarTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/TimerAndCalendarTest.java @@ -51,8 +51,8 @@ import org.kie.internal.runtime.StatefulKnowledgeSession; public class TimerAndCalendarTest extends CommonTestMethodBase { - - @Test(timeout=10000) + + @Test(timeout=15000) public void testDuration() throws Exception { KnowledgeBase kbase = loadKnowledgeBase("test_Duration.drl"); KieSession ksession = createKnowledgeSession(kbase); diff --git a/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectCDITest.java b/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectCDITest.java index 52bc9530aef..8e934457dd1 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectCDITest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectCDITest.java @@ -116,6 +116,16 @@ public void createMultpleJarAndFileResources() throws IOException, weld.shutdown(); } finally { + // FIXME Java 7+ + // on Windows, the URLClassLoader will not release all resources, + // so the attempt to delete the temporary files will fail. + // an explicit dispose call is needed, but it has not been introduced until Java7+ + // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4950148 + + /* + ((URLClassLoader) Thread.currentThread().getContextClassLoader()).close(); + */ + Thread.currentThread().setContextClassLoader( origCl ); } } diff --git a/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectDefaultClasspathTest.java b/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectDefaultClasspathTest.java index e68da0344f2..ab09708b18e 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectDefaultClasspathTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectDefaultClasspathTest.java @@ -71,6 +71,16 @@ public void onKieModuleDiscovered(KieModuleDiscovered event) { testEntry(new KProjectTestClassImpl( "fol4", kContainer ), "fol4"); } finally { + // FIXME Java 7+ + // on Windows, the URLClassLoader will not release all resources, + // so the attempt to delete the temporary files will fail. + // an explicit dispose call is needed, but it has not been introduced until Java7+ + // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4950148 + + /* + ((URLClassLoader) Thread.currentThread().getContextClassLoader()).close(); + */ + Thread.currentThread().setContextClassLoader( origCl ); } } diff --git a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingEntryTest.java b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingEntryTest.java index fdcaeaa4e3e..d4e4ce95e67 100755 --- a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingEntryTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingEntryTest.java @@ -17,6 +17,7 @@ public class DSLMappingEntryTest { // Due to a bug in JDK 5, a workaround for zero-width lookbehind has to be used. // JDK works correctly with "(?<=^|\\W)" private static final String lookbehind = "(?:(?<=^)|(?<=\\W))"; + private static final String NL = System.getProperty("line.separator"); private DSLMappingEntry createEntry(final String inputKey, final String inputValue) throws IOException { @@ -133,7 +134,7 @@ public void testExpandSpaces() throws IOException { "0_sp_3 ", "0_sp 1_sp 2_sp", " 3_sp 3_sp 1_sp 1_sp_2 " }; StringBuilder sb = new StringBuilder( "rule x\n" + "when\n" ); for( String str: strs ){ - sb.append( "String is \"" + str + "\"\n" ); + sb.append( "String is \"" + str + "\"" + NL ); } sb.append( "then\n" + "end\n" ); String dslr = sb.toString(); @@ -151,10 +152,10 @@ public void testExpandWithDots() throws IOException { DSLMappingEntry entry3 = this.createEntry( "- {prop} is_not {val} ", "{prop} != {val}" ); DefaultExpander ex = makeExpander( entry1, entry2, entry3 ); StringBuilder sb = new StringBuilder( "rule x\n" ).append( "when\n" ); - sb.append( "> Foo()").append( "\n" ); - sb.append( "- type1 is ClientServiceType.TypeGOLD" ).append( "\n" ); - sb.append( "- type2 is_not ClientServiceType.TypeGOLD" ).append( "\n" ); - sb.append( "- type3 is not ClientServiceType.TypeGOLD" ).append( "\n" ); + sb.append( "> Foo()").append( NL ); + sb.append( "- type1 is ClientServiceType.TypeGOLD" ).append( NL ); + sb.append( "- type2 is_not ClientServiceType.TypeGOLD" ).append( NL ); + sb.append( "- type3 is not ClientServiceType.TypeGOLD" ).append( NL ); sb.append( "then\n" ).append( "end\n" ); String dslr = sb.toString(); String drl = ex.expand( dslr ); @@ -205,13 +206,13 @@ public void testExpandWithBrackets() throws IOException { entry5, entry6, entry7 ); StringBuilder sb = new StringBuilder( "rule x\n" ).append( "when\n" ); - sb.append( "attr name is in [ 'Edson', 'Bob' ]" ).append( "\n" ); - sb.append( "he (is) a $xx handsome man" ).append( "\n" ); - sb.append( "DSL sentence with mykey myvalue" ).append( "\n" ); - sb.append( "When the credit rating is AA" ).append( "\n" ); - sb.append( "When the credit rating is 555" ).append( "\n" ); - sb.append( "This is a sentence with line breaks" ).append( "\n" ); - sb.append( "Bedingung-#19-MKM4" ).append( "\n" ); + sb.append( "attr name is in [ 'Edson', 'Bob' ]" ).append( NL ); + sb.append( "he (is) a $xx handsome man" ).append( NL ); + sb.append( "DSL sentence with mykey myvalue" ).append( NL ); + sb.append( "When the credit rating is AA" ).append( NL ); + sb.append( "When the credit rating is 555" ).append( NL ); + sb.append( "This is a sentence with line breaks" ).append( NL ); + sb.append( "Bedingung-#19-MKM4" ).append( NL ); sb.append( "then\n" + "end\n" ); String dslr = sb.toString(); String drl = ex.expand( dslr ); diff --git a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingFileTest.java b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingFileTest.java index dc34cc3d62e..f40485d20ad 100755 --- a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingFileTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLMappingFileTest.java @@ -16,6 +16,8 @@ public class DSLMappingFileTest { private DSLMappingFile file = null; private final String filename = "test_metainfo.dsl"; + private static final String NL = System.getProperty("line.separator"); + @Test public void testParseFile() { @@ -102,8 +104,8 @@ public void testParseFileWithEscaptedCurlyBrackets() { assertEquals( "modify(policy) \\{price = {surcharge}\\}", entry.getMappingValue() ); - String input = "rule x\nwhen\nthen\nAdd surcharge 300 to Policy\nend\n"; - String expected = "rule x\nwhen\nthen\nmodify(policy) {price = 300}\nend\n"; + String input = "rule x" + NL + "when" + NL + "then" + NL + "Add surcharge 300 to Policy" + NL + "end" + NL + ""; + String expected = "rule x" + NL + "when" + NL + "then" + NL + "modify(policy) {price = 300}" + NL + "end" + NL + ""; DefaultExpander de = new DefaultExpander(); de.addDSLMapping( this.file.getMapping() ); @@ -126,9 +128,9 @@ public void testParseFileWithEscaptedCurlyBrackets() { */ @Test public void testNoRHS() { - String file = "[then]TEST=System.out.println(\"DO_SOMETHING\");\n" + - "[when]code {code1} occurs and sum of all digit not equal \\( {code2} \\+ {code3} \\)=AAAA( cd1 == {code1}, cd2 != ( {code2} + {code3} ))\n" - + "[when]code {code1} occurs=BBBB\n"; + String file = "[then]TEST=System.out.println(\"DO_SOMETHING\");" + NL + "" + + "[when]code {code1} occurs and sum of all digit not equal \\( {code2} \\+ {code3} \\)=AAAA( cd1 == {code1}, cd2 != ( {code2} + {code3} ))" + NL + "" + + "[when]code {code1} occurs=BBBB" + NL + ""; try { final Reader reader = new StringReader( file ); this.file = new DSLTokenizedMappingFile(); @@ -141,14 +143,14 @@ public void testNoRHS() { assertTrue( this.file.getErrors().isEmpty() ); final String LHS = "code 1041 occurs and sum of all digit not equal ( 1034 + 1035 )"; - final String rule = "rule \"x\"\nwhen\n" + LHS + "\nthen\nend"; + final String rule = "rule \"x\"" + NL + "when" + NL + "" + LHS + "" + NL + "then" + NL + "end"; DefaultExpander de = new DefaultExpander(); de.addDSLMapping( this.file.getMapping() ); final String ruleAfterExpansion = de.expand( rule ); - final String expected = "rule \"x\"\nwhen\nAAAA( cd1 == 1041, cd2 != ( 1034 + 1035 ))\nthen\nend"; + final String expected = "rule \"x\"" + NL + "when" + NL + "AAAA( cd1 == 1041, cd2 != ( 1034 + 1035 ))" + NL + "then" + NL + "end"; assertEquals( expected, ruleAfterExpansion ); @@ -162,8 +164,8 @@ public void testNoRHS() { @Test public void testParseFileWithEscapes() { - String file = "[then]TEST=System.out.println(\"DO_SOMETHING\");\n" + "[when]code {code1} occurs and sum of all digit not equal \\( {code2} \\+ {code3} \\)=AAAA( cd1 == {code1}, cd2 != ( {code2} + {code3} ))\n" - + "[when]code {code1} occurs=BBBB\n"; + String file = "[then]TEST=System.out.println(\"DO_SOMETHING\");" + NL + "" + "[when]code {code1} occurs and sum of all digit not equal \\( {code2} \\+ {code3} \\)=AAAA( cd1 == {code1}, cd2 != ( {code2} + {code3} ))" + NL + "" + + "[when]code {code1} occurs=BBBB" + NL + ""; try { final Reader reader = new StringReader( file ); this.file = new DSLTokenizedMappingFile(); @@ -176,14 +178,14 @@ public void testParseFileWithEscapes() { assertTrue( this.file.getErrors().isEmpty() ); final String LHS = "code 1041 occurs and sum of all digit not equal ( 1034 + 1035 )"; - final String rule = "rule \"x\"\nwhen\n" + LHS + "\nthen\nTEST\nend"; + final String rule = "rule \"x\"" + NL + "when" + NL + "" + LHS + "" + NL + "then" + NL + "TEST" + NL + "end"; DefaultExpander de = new DefaultExpander(); de.addDSLMapping( this.file.getMapping() ); final String ruleAfterExpansion = de.expand( rule ); - final String expected = "rule \"x\"\nwhen\nAAAA( cd1 == 1041, cd2 != ( 1034 + 1035 ))\nthen\nSystem.out.println(\"DO_SOMETHING\");\nend"; + final String expected = "rule \"x\"" + NL + "when" + NL + "AAAA( cd1 == 1041, cd2 != ( 1034 + 1035 ))" + NL + "then" + NL + "System.out.println(\"DO_SOMETHING\");" + NL + "end"; assertEquals( expected, ruleAfterExpansion ); diff --git a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLTokenizedMappingFileTest.java b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLTokenizedMappingFileTest.java index 6830d022a5a..ee9da32626d 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLTokenizedMappingFileTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DSLTokenizedMappingFileTest.java @@ -18,6 +18,7 @@ public class DSLTokenizedMappingFileTest { // Due to a bug in JDK 5, a workaround for zero-widht lookbehind has to be used. // JDK works correctly with "(?<=^|\\W)" private static final String lookbehind = "(?:(?<=^)|(?<=\\W))"; + private static final String NL = System.getProperty("line.separator"); private DSLMappingFile file = null; private final String filename = "test_metainfo.dsl"; @@ -118,9 +119,9 @@ public void testParseFileWithEscaptedBrackets() { @Test public void testParseFileWithEscapes() { - String file = "[then]TEST=System.out.println(\"DO_SOMETHING\");\n" + - "[when]code {code1} occurs and sum of all digit not equal \\( {code2} \\+ {code3} \\)=AAAA( cd1 == {code1}, cd2 != ( {code2} + {code3} ))\n" + - "[when]code {code1} occurs=BBBB\n"; + String file = "[then]TEST=System.out.println(\"DO_SOMETHING\");" + NL + "" + + "[when]code {code1} occurs and sum of all digit not equal \\( {code2} \\+ {code3} \\)=AAAA( cd1 == {code1}, cd2 != ( {code2} + {code3} ))" + NL + "" + + "[when]code {code1} occurs=BBBB" + NL + ""; try { final Reader reader = new StringReader( file ); this.file = new DSLTokenizedMappingFile(); @@ -133,14 +134,14 @@ public void testParseFileWithEscapes() { assertTrue( this.file.getErrors().isEmpty() ); final String LHS = "code 1041 occurs and sum of all digit not equal ( 1034 + 1035 )"; - final String rule = "rule \"x\"\nwhen\n" + LHS + "\nthen\nTEST\nend"; + final String rule = "rule \"x\"" + NL + "when" + NL + "" + LHS + "" + NL + "then" + NL + "TEST" + NL + "end"; DefaultExpander de = new DefaultExpander(); de.addDSLMapping(this.file.getMapping()); final String ruleAfterExpansion = de.expand(rule); - final String expected = "rule \"x\"\nwhen\nAAAA( cd1 == 1041, cd2 != ( 1034 + 1035 ))\nthen\nSystem.out.println(\"DO_SOMETHING\");\nend"; + final String expected = "rule \"x\"" + NL + "when" + NL + "AAAA( cd1 == 1041, cd2 != ( 1034 + 1035 ))" + NL + "then" + NL + "System.out.println(\"DO_SOMETHING\");" + NL + "end"; assertEquals( expected, ruleAfterExpansion ); diff --git a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DefaultExpanderTest.java b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DefaultExpanderTest.java index 0aec5648178..452d866d9b4 100755 --- a/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DefaultExpanderTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/lang/dsl/DefaultExpanderTest.java @@ -6,11 +6,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.drools.compiler.lang.dsl.DSLMappingFile; -import org.drools.compiler.lang.dsl.DSLTokenizedMappingFile; -import org.drools.compiler.lang.dsl.DefaultExpander; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.*; import static org.junit.Assert.assertEquals; @@ -70,14 +66,14 @@ public void testANTLRRegexp() throws Exception { @Test public void testExpandParts() throws Exception { DSLMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]foo=Foo()\n[then]bar {num}=baz({num});"; + String dsl = "[when]foo=Foo()" + NL + "[then]bar {num}=baz({num});"; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, file.getErrors().size()); DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - //System.err.println(ex.expand( "rule 'x' \n when \n foo \n then \n end" )); + //System.err.println(ex.expand( "rule 'x' " + NL + " when " + NL + " foo " + NL + " then " + NL + " end" )); } @Test @@ -90,47 +86,47 @@ public void testExpandKeyword() throws Exception { DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - String source = "rule x\nwhen\n key 1 \n key 2 \nthen\nend"; + String source = "rule x" + NL + "when" + NL + " key 1 " + NL + " key 2 " + NL + "then" + NL + "end"; String drl = ex.expand(source); System.out.println(drl); assertTrue(drl.contains("attr==1")); assertTrue(drl.contains("attr==2")); - //System.err.println(ex.expand( "rule 'x' \n when \n foo \n then \n end" )); + //System.err.println(ex.expand( "rule 'x' " + NL + " when " + NL + " foo " + NL + " then " + NL + " end" )); } @Test public void testANTLRExpandParts() throws Exception { DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]foo=Foo()\n[then]bar {num}=baz({num});"; + String dsl = "[when]foo=Foo()" + NL + "[then]bar {num}=baz({num});"; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, file.getErrors().size()); DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - //System.err.println(ex.expand( "rule 'x' \n when \n foo \n then \n end" )); + //System.err.println(ex.expand( "rule 'x' " + NL + " when " + NL + " foo " + NL + " then " + NL + " end" )); } @Test public void testExpandFailure() throws Exception { DSLMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]foo=Foo()\n[then]bar {num}=baz({num});"; + String dsl = "[when]foo=Foo()" + NL + "[then]bar {num}=baz({num});"; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, file.getErrors().size()); DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - String source = "rule 'q'\nagenda-group 'x'\nwhen\n foo \nthen\n bar 42\nend"; + String source = "rule 'q'" + NL + "agenda-group 'x'" + NL + "when" + NL + " foo " + NL + "then" + NL + " bar 42" + NL + "end"; String drl = ex.expand(source); assertFalse(ex.hasErrors()); ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - source = "rule 'q' agenda-group 'x'\nwhen\n foos \nthen\n bar 42\n end"; + source = "rule 'q' agenda-group 'x'" + NL + "when" + NL + " foos " + NL + "then" + NL + " bar 42" + NL + " end"; drl = ex.expand(source); //System.out.println( drl ); assertTrue(ex.hasErrors()); @@ -143,21 +139,21 @@ public void testExpandFailure() throws Exception { public void testANTLRExpandFailure() throws Exception { DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]foo=Foo()\n[then]bar {num}=baz({num});"; + String dsl = "[when]foo=Foo()" + NL + "[then]bar {num}=baz({num});"; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, file.getErrors().size()); DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - String source = "rule 'q'\nagenda-group 'x'\nwhen\n foo \nthen\n bar 42\nend"; + String source = "rule 'q'" + NL + "agenda-group 'x'" + NL + "when" + NL + " foo " + NL + "then" + NL + " bar 42" + NL + "end"; String drl = ex.expand(source); assertFalse(ex.hasErrors()); ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - source = "rule 'q' agenda-group 'x'\nwhen\n foos \nthen\n bar 42\n end"; + source = "rule 'q' agenda-group 'x'" + NL + "when" + NL + " foos " + NL + "then" + NL + " bar 42" + NL + " end"; drl = ex.expand(source); //System.out.println( drl ); assertTrue(ex.hasErrors()); @@ -170,15 +166,15 @@ public void testANTLRExpandFailure() throws Exception { public void testExpandWithKeywordClashes() throws Exception { DSLMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]Invoke rule executor=ruleExec: RuleExecutor()\n" + "[then]Execute rule \"{id}\"=ruleExec.ExecuteSubRule( new Long({id}));"; + String dsl = "[when]Invoke rule executor=ruleExec: RuleExecutor()" + NL + "[then]Execute rule \"{id}\"=ruleExec.ExecuteSubRule( new Long({id}));"; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, file.getErrors().size()); DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - String source = "package something;\n\nrule \"1\"\nwhen\n Invoke rule executor\nthen\n Execute rule \"5\"\nend"; - String expected = "package something;\n\nrule \"1\"\nwhen\n ruleExec: RuleExecutor()\nthen\n ruleExec.ExecuteSubRule( new Long(5));\nend\n"; + String source = "package something;" + NL + NL + "rule \"1\"" + NL + "when" + NL + " Invoke rule executor" + NL + "then" + NL + " Execute rule \"5\"" + NL + "end"; + String expected = "package something;" + NL + NL + "rule \"1\"" + NL + "when" + NL + " ruleExec: RuleExecutor()" + NL + "then" + NL + " ruleExec.ExecuteSubRule( new Long(5));" + NL + "end" + NL; String drl = ex.expand(source); // System.out.println("["+drl+"]" ); // System.out.println("["+expected+"]" ); @@ -192,15 +188,15 @@ public void testExpandWithKeywordClashes() throws Exception { public void testANTLRExpandWithKeywordClashes() throws Exception { DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]Invoke rule executor=ruleExec: RuleExecutor()\n" + "[then]Execute rule \"{id}\"=ruleExec.ExecuteSubRule( new Long({id}));"; + String dsl = "[when]Invoke rule executor=ruleExec: RuleExecutor()" + NL + "[then]Execute rule \"{id}\"=ruleExec.ExecuteSubRule( new Long({id}));"; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, file.getErrors().size()); DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - String source = "package something;\n\nrule \"1\"\nwhen\n Invoke rule executor\nthen\n Execute rule \"5\"\nend"; - String expected = "package something;\n\nrule \"1\"\nwhen\n ruleExec: RuleExecutor()\nthen\n ruleExec.ExecuteSubRule( new Long(5));\nend"; + String source = "package something;" + NL + NL + "rule \"1\"" + NL + "when" + NL + " Invoke rule executor" + NL + "then" + NL + " Execute rule \"5\"" + NL + "end"; + String expected = "package something;" + NL + NL + "rule \"1\"" + NL + "when" + NL + " ruleExec: RuleExecutor()" + NL + "then" + NL + " ruleExec.ExecuteSubRule( new Long(5));" + NL + "end"; String drl = ex.expand(source); // System.out.println("["+drl+"]" ); // System.out.println("["+expected+"]" ); @@ -264,29 +260,29 @@ public void testANTLREnumExpand() throws Exception { file.getErrors().size()); DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - String source = "rule \"TestNewDslSetup\"\ndialect \"mvel\"\nwhen\nWhen the credit rating is AA\nthen \nend"; + String source = "rule \"TestNewDslSetup\"" + NL + "dialect \"mvel\"" + NL + "when" + NL + "When the credit rating is AA" + NL + "then " + NL + "end"; - // String source="rule \"TestNewDslSetup\"\n"+ - // "dialect \"mvel\"\n"+ - // "when\n"+ - // "When the credit rating is OK\n"+ - // "then\n"+ - // "end\n"; + // String source="rule \"TestNewDslSetup\"" + NL+ + // "dialect \"mvel\"" + NL+ + // "when" + NL+ + // "When the credit rating is OK" + NL+ + // "then" + NL+ + // "end" + NL; String drl = ex.expand(source); - String expected = "rule \"TestNewDslSetup\"\n" + - "dialect \"mvel\"\n" + - "when\n" + - "applicant:Applicant(credit==AA)\n" + - "then \nend"; + String expected = "rule \"TestNewDslSetup\"" + NL + + "dialect \"mvel\"" + NL + + "when" + NL + + "applicant:Applicant(credit==AA)" + NL + + "then " + NL + "end"; assertFalse(ex.getErrors().toString(), ex.hasErrors()); assertEquals(expected, drl); - //System.err.println(ex.expand( "rule 'x' \n when \n foo \n then \n end" )); + //System.err.println(ex.expand( "rule 'x' " + NL + " when " + NL + " foo " + NL + " then " + NL + " end" )); } private boolean equalsIgnoreWhiteSpace(String expected, @@ -301,75 +297,75 @@ private boolean equalsIgnoreWhiteSpace(String expected, @Test public void testExpandComplex() throws Exception { - String source = "rule \"R\"\n" - + "dialect \"mvel\"\n" - + "when\n" - + "There is an TestObject\n" - + "-startDate is before 01-Jul-2011\n" - + "-endDate is after 01-Jul-2011\n" - + "then\n" - + "end\n"; - - String expected = "rule \"R\"\n" - + "dialect \"mvel\"\n" - + "when\n" - + "TestObject(startDate>DateUtils.parseDate(\"01-Jul-2011\"), endDate>DateUtils.parseDate(\"01-Jul-2011\"))\n" - + "then\n" - + "end\n"; + String source = "rule \"R\"" + NL + + "dialect \"mvel\"" + NL + + "when" + NL + + "There is an TestObject" + NL + + "-startDate is before 01-Jul-2011" + NL + + "-endDate is after 01-Jul-2011" + NL + + "then" + NL + + "end" + NL; + + String expected = "rule \"R\"" + NL + + "dialect \"mvel\"" + NL + + "when" + NL + + "TestObject(startDate>DateUtils.parseDate(\"01-Jul-2011\"), endDate>DateUtils.parseDate(\"01-Jul-2011\"))" + NL + + "then" + NL + + "end" + NL; checkExpansion(source, expected); } @Test public void testDontExpandCommentedLines() throws Exception { - String source = "rule \"R\"\n" - + "dialect \"mvel\"\n" - + "when\n" - + "// There is an TestObject\n" - + "// -startDate is before 01-Jul-2011\n" - + "// -endDate is after 01-Jul-2011\n" - + "then\n" - + "end\n"; - - String expected = "rule \"R\"\n" - + "dialect \"mvel\"\n" - + "when\n" - + "// There is an TestObject\n" - + "// -startDate is before 01-Jul-2011\n" - + "// -endDate is after 01-Jul-2011\n" - + "then\n" - + "end\n"; + String source = "rule \"R\"" + NL + + "dialect \"mvel\"" + NL + + "when" + NL + + "// There is an TestObject" + NL + + "// -startDate is before 01-Jul-2011" + NL + + "// -endDate is after 01-Jul-2011" + NL + + "then" + NL + + "end" + NL; + + String expected = "rule \"R\"" + NL + + "dialect \"mvel\"" + NL + + "when" + NL + + "// There is an TestObject" + NL + + "// -startDate is before 01-Jul-2011" + NL + + "// -endDate is after 01-Jul-2011" + NL + + "then" + NL + + "end" + NL; checkExpansion(source, expected); } @Test public void testDontExpandCommentedBlocks() throws Exception { - String source = "rule \"R\"\n" - + "dialect \"mvel\"\n" - + "when\n" - + "/*\n" - + "There is an TestObject\n" - + "-startDate is before 01-Jul-2011\n" - + "-endDate is after 01-Jul-2011\n" - + "*/\n" - + "then\n" - + "end\n"; - - String expected = "rule \"R\"\n" - + "dialect \"mvel\"\n" - + "when\n" - + "\n" - + "then\n" - + "end\n"; + String source = "rule \"R\"" + NL + + "dialect \"mvel\"" + NL + + "when" + NL + + "/*" + NL + + "There is an TestObject" + NL + + "-startDate is before 01-Jul-2011" + NL + + "-endDate is after 01-Jul-2011" + NL + + "*/" + NL + + "then" + NL + + "end" + NL; + + String expected = "rule \"R\"" + NL + + "dialect \"mvel\"" + NL + + "when" + NL + + "" + NL + + "then" + NL + + "end" + NL; checkExpansion(source, expected); } private void checkExpansion(String source, String expected) throws Exception { DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]There is an TestObject=TestObject()\n" - + "[when]-startDate is before {date}=startDate>DateUtils.parseDate(\"{date}\")\n" + String dsl = "[when]There is an TestObject=TestObject()" + NL + + "[when]-startDate is before {date}=startDate>DateUtils.parseDate(\"{date}\")" + NL + "[when]-endDate is after {date}=endDate>DateUtils.parseDate(\"{date}\")"; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, @@ -387,18 +383,18 @@ private void checkExpansion(String source, String expected) throws Exception { @Test public void testExpandQuery() throws Exception { DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); - String dsl = "[when]There is a person=Person()\n" + - "[when]- {field:\\w*} {operator} {value:\\d*}={field} {operator} {value}\n" + + String dsl = "[when]There is a person=Person()" + NL + + "[when]- {field:\\w*} {operator} {value:\\d*}={field} {operator} {value}" + NL + "[when]is greater than=>"; - String source = "query \"isMature\"\n" + - "There is a person\n" + - "- age is greater than 18\n" + - "end\n"; + String source = "query \"isMature\"" + NL + + "There is a person" + NL + + "- age is greater than 18" + NL + + "end" + NL; - String expected = "query \"isMature\"\n" + - "Person(age > 18)\n" + - "end\n"; + String expected = "query \"isMature\"" + NL + + "Person(age > 18)" + NL + + "end" + NL; file.parseAndLoad(new StringReader(dsl)); assertEquals(0, @@ -418,18 +414,18 @@ public void testExpandExpr() throws Exception { DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); String dsl = "[when]Name of Applicant {nameVar:CF:Applicant.age}= System.out.println({nameVar})"; - String source = "rule \"test rule for custom form in DSL\"\n" + - " dialect \"mvel\"\n" + - " when\n" + - " Name of Applicant Bojan Oklahoma and NJ,Andrew AMW Test\n" + - " then\n" + + String source = "rule \"test rule for custom form in DSL\"" + NL + + " dialect \"mvel\"" + NL + + " when" + NL + + " Name of Applicant Bojan Oklahoma and NJ,Andrew AMW Test" + NL + + " then" + NL + "end"; - String expected = "rule \"test rule for custom form in DSL\"\n" + - " dialect \"mvel\"\n" + - " when\n" + - " System.out.println(Bojan Oklahoma and NJ,Andrew AMW Test)\n" + - " then\n" + + String expected = "rule \"test rule for custom form in DSL\"" + NL + + " dialect \"mvel\"" + NL + + " when" + NL + + " System.out.println(Bojan Oklahoma and NJ,Andrew AMW Test)" + NL + + " then" + NL + "end"; file.parseAndLoad(new StringReader(dsl)); @@ -456,7 +452,7 @@ public void testExpandInfiniteLoop() throws Exception { DefaultExpander ex = new DefaultExpander(); ex.addDSLMapping(file.getMapping()); - String source = "rule 'dsl rule'\nwhen\n Foo with {var} bars\nthen\n\nend"; + String source = "rule 'dsl rule'" + NL + "when" + NL + " Foo with {var} bars" + NL + "then" + NL + NL + "end"; ex.expand(source); assertFalse(ex.hasErrors()); } @@ -465,42 +461,42 @@ public void testExpandInfiniteLoop() throws Exception { public void testEqualSignInTernaryOp() throws Exception { // BZ-1013960 String source = - "declare Person\n" + - " age : int\n" + - " name : String\n" + - "end\n" + - "\n" + - "rule \"Your First Rule\"\n" + - " when\n" + - " There is a Person\n" + - " - with a negative age\n" + - " - with a positive age\n" + - " - with a zero age\n" + - " then\n" + - " print \"Your First Rule\"\n" + - "\n" + - "end\n"; + "declare Person" + NL + + " age : int" + NL + + " name : String" + NL + + "end" + NL + + "" + NL + + "rule \"Your First Rule\"" + NL + + " when" + NL + + " There is a Person" + NL + + " - with a negative age" + NL + + " - with a positive age" + NL + + " - with a zero age" + NL + + " then" + NL + + " print \"Your First Rule\"" + NL + + "" + NL + + "end" + NL; String dsl = - "[when][]There is an? {entity}=${entity!lc}: {entity!ucfirst}()\n" + - "[when][]- with an? {attr} greater than {amount}={attr} > {amount!num}\n" + - "[then]print \"{text}\"=System.out.println(\"{text}\");\n" + - "\n" + - "[when]- with a {what} {attr}={attr} {what!zero?==0/!=0}\n"; + "[when][]There is an? {entity}=${entity!lc}: {entity!ucfirst}()" + NL + + "[when][]- with an? {attr} greater than {amount}={attr} > {amount!num}" + NL + + "[then]print \"{text}\"=System.out.println(\"{text}\");" + NL + + "" + NL + + "[when]- with a {what} {attr}={attr} {what!zero?==0/!=0}" + NL; String expected = - "declare Person\n" + - " age : int\n" + - " name : String\n" + - "end\n" + - "\n" + - "rule \"Your First Rule\"\n" + - " when\n" + - " $person: Person(age !=0, age !=0, age ==0)\n" + - " then\n" + - " System.out.println(\"Your First Rule\");\n" + - "\n" + - "end\n"; + "declare Person" + NL + + " age : int" + NL + + " name : String" + NL + + "end" + NL + + "" + NL + + "rule \"Your First Rule\"" + NL + + " when" + NL + + " $person: Person(age !=0, age !=0, age ==0)" + NL + + " then" + NL + + " System.out.println(\"Your First Rule\");" + NL + + "" + NL + + "end" + NL; DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); file.parseAndLoad(new StringReader(dsl)); @@ -521,25 +517,25 @@ public void testEqualSignInTernaryOp() throws Exception { public void testDotInPattern() throws Exception { // BZ-1013960 String source = - "import org.drools.compiler.Person;\n" - + "global java.util.List list\n" - + "rule R1\n" - + "when\n" - + "then\n" - + "Log X\n" - + "end\n"; + "import org.drools.compiler.Person;" + NL + + "global java.util.List list" + NL + + "rule R1" + NL + + "when" + NL + + "then" + NL + + "Log X" + NL + + "end" + NL; String dsl = "[then]Log {message:.}=list.add(\"{message}\");"; String expected = - "import org.drools.compiler.Person;\n" - + "global java.util.List list\n" - + "rule R1\n" - + "when\n" - + "then\n" - + "list.add(\"X\");\n" - + "end\n"; + "import org.drools.compiler.Person;" + NL + + "global java.util.List list" + NL + + "rule R1" + NL + + "when" + NL + + "then" + NL + + "list.add(\"X\");" + NL + + "end" + NL; DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); file.parseAndLoad(new StringReader(dsl)); diff --git a/drools-core/src/main/java/org/drools/core/util/IoUtils.java b/drools-core/src/main/java/org/drools/core/util/IoUtils.java index 5c0fff54bbf..09337a0e5c1 100644 --- a/drools-core/src/main/java/org/drools/core/util/IoUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/IoUtils.java @@ -138,7 +138,7 @@ public static Map indexZipFile(java.io.File jarFile) { } } return files; - } + } public static List recursiveListFile(File folder) { return recursiveListFile(folder, "", Predicate.PassAll.INSTANCE); @@ -314,4 +314,13 @@ public static boolean areByteArraysEqual(byte[] b1, return true; } + + public static String asSystemSpecificPath(String urlPath, int colonIndex) { + String ic = urlPath.substring( Math.max( 0, colonIndex - 2 ), colonIndex + 1 ); + if ( ic.matches( "\\/[A-Z]:" ) ) { + return urlPath.substring( colonIndex - 2 ); + } else { + return urlPath.substring( colonIndex + 1 ); + } + } } \ No newline at end of file diff --git a/drools-core/src/test/java/org/drools/core/util/FileManager.java b/drools-core/src/test/java/org/drools/core/util/FileManager.java index 19b9edd9571..194af5801c1 100644 --- a/drools-core/src/test/java/org/drools/core/util/FileManager.java +++ b/drools-core/src/test/java/org/drools/core/util/FileManager.java @@ -126,7 +126,13 @@ public void deleteFile(File file) { if ( file.exists() ) { try { - throw new RuntimeException( "Unable to delete file:" + file.getCanonicalPath() ); + if ( System.getProperty( "os.name" ).toLowerCase().contains( "win" ) ) { + // on windows platforms with JDK 6 or lower, a known bug will prevent + // the files from being released until the JVM terminates + // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4950148 + } else { + throw new RuntimeException("Unable to delete file:" + file.getCanonicalPath()); + } } catch ( IOException e ) { throw new RuntimeException( "Unable to delete file", e); } From b7dce2be9e3d359cd2967f82d763ca7010f05681 Mon Sep 17 00:00:00 2001 From: sotty Date: Fri, 25 Jul 2014 12:36:13 +0200 Subject: [PATCH 55/76] [PMML] Remove problematic comments (cherry picked from commit 8b55c3b7f8921f9f3439f304c66cf7fa5d55f7e5) (cherry picked from commit 59973c9345b4c96c6fcfff7ab32975e4507b4878) --- .../org/drools/pmml/pmml_4_1/compiler/pmml_compiler.drl | 1 - .../org/drools/pmml/pmml_4_1/compiler/pmml_visitor.drl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_compiler.drl b/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_compiler.drl index 265e47ca8e4..3f04422ab41 100644 --- a/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_compiler.drl +++ b/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_compiler.drl @@ -941,7 +941,6 @@ then String expr = utils.mapFunction( $f2, $args ); String bit = expr; if ( ! utils.isBuiltIn( $f2 ) ) { - // saving one rule bit = "$" + $f2 + "_return"; $deps.add( utils.mapFunctionAsQuery( $f2, $args ) ); } diff --git a/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_visitor.drl b/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_visitor.drl index ec136be810e..9c8e301cba7 100644 --- a/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_visitor.drl +++ b/drools-pmml/src/main/resources/org/drools/pmml/pmml_4_1/compiler/pmml_visitor.drl @@ -883,8 +883,8 @@ salience -11 when $bin : BayesInput( $dfld : derivedField != null, $fld : fieldName ) then + // only discretization allowed here if ( $dfld.getName() == null ) { - // only allowed derivation is discretization $dfld.setName( $fld + "__Discrete" ); } insertLogical( $dfld ); From ec8b962cae3427fb1a3b6a4dd7eaa432569c1716 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Fri, 25 Jul 2014 17:30:41 +0200 Subject: [PATCH 56/76] [DROOLS-516] register unlinking caused by a delete in a lia node (cherry picked from commit a833097b4738075a80e2d332dd73b5edb037bd3d) --- .../compiler/integrationtests/CepEspTest.java | 6 ++++- .../java/org/drools/core/common/BaseNode.java | 22 +++++++++++++++++-- .../org/drools/core/common/DefaultAgenda.java | 4 ++++ .../drools/core/common/GarbageCollector.java | 1 + .../java/org/drools/core/reteoo/BetaNode.java | 18 +-------------- .../core/reteoo/LeftInputAdapterNode.java | 1 + .../java/org/drools/core/reteoo/NotNode.java | 2 +- .../org/drools/reteoo/common/ReteAgenda.java | 3 +++ 8 files changed, 36 insertions(+), 21 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java index 29237614fd5..6192bf8acea 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java @@ -14,6 +14,8 @@ import org.drools.core.base.evaluators.TimeIntervalParser; import org.drools.core.common.DefaultAgenda; import org.drools.core.common.EventFactHandle; +import org.drools.core.common.GarbageCollector; +import org.drools.core.common.InternalAgenda; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.Memory; @@ -5093,7 +5095,9 @@ public void testRightTupleLeak() throws Exception { } // force gc - ((DefaultAgenda)ksession.getAgenda()).getGarbageCollector().forceGcUnlinkedRules(); + GarbageCollector gc = ((InternalAgenda) ksession.getAgenda()).getGarbageCollector(); + assertEquals(10, gc.getDeleteCounter()); + gc.forceGcUnlinkedRules(); Rete rete = ((KnowledgeBaseImpl)kbase).getRete(); JoinNode joinNode = null; diff --git a/drools-core/src/main/java/org/drools/core/common/BaseNode.java b/drools-core/src/main/java/org/drools/core/common/BaseNode.java index f6fa2ab3c2f..c235115fdf8 100644 --- a/drools-core/src/main/java/org/drools/core/common/BaseNode.java +++ b/drools-core/src/main/java/org/drools/core/common/BaseNode.java @@ -17,9 +17,11 @@ package org.drools.core.common; import org.drools.core.reteoo.EntryPointNode; -import org.drools.core.reteoo.NodeSet; +import org.drools.core.reteoo.NodeTypeEnums; +import org.drools.core.reteoo.PathMemory; import org.drools.core.reteoo.ReteooBuilder; import org.drools.core.reteoo.RuleRemovalContext; +import org.drools.core.reteoo.SegmentMemory; import org.drools.core.reteoo.builder.BuildContext; import org.drools.core.spi.RuleComponent; import org.kie.api.definition.rule.Rule; @@ -197,5 +199,21 @@ public Map getAssociations() { */ public void removeAssociation( Rule rule ) { this.associations.remove( rule ); - } + } + + protected static void registerUnlinkedPaths(InternalWorkingMemory wm, SegmentMemory smem, boolean stagedDeleteWasEmpty) { + if (!smem.isSegmentLinked()) { + GarbageCollector garbageCollector = ((InternalAgenda)wm.getAgenda()).getGarbageCollector(); + garbageCollector.increaseDeleteCounter(); + if (stagedDeleteWasEmpty) { + synchronized (garbageCollector) { + for (PathMemory pmem : smem.getPathMemories()) { + if (pmem.getNodeType() == NodeTypeEnums.RuleTerminalNode) { + garbageCollector.add(pmem.getOrCreateRuleAgendaItem(wm)); + } + } + } + } + } + } } diff --git a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java index 2e7ce73dcab..d92d42597f7 100644 --- a/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java +++ b/drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java @@ -1316,5 +1316,9 @@ public synchronized void remove(RuleAgendaItem item) { public synchronized void add(RuleAgendaItem item) { unlinked.add(item); } + + public int getDeleteCounter() { + return deleteCounter; + } } } diff --git a/drools-core/src/main/java/org/drools/core/common/GarbageCollector.java b/drools-core/src/main/java/org/drools/core/common/GarbageCollector.java index 0344e059c4a..441beb4676c 100644 --- a/drools-core/src/main/java/org/drools/core/common/GarbageCollector.java +++ b/drools-core/src/main/java/org/drools/core/common/GarbageCollector.java @@ -5,6 +5,7 @@ public interface GarbageCollector { void increaseDeleteCounter(); + int getDeleteCounter(); void gcUnlinkedRules(); void forceGcUnlinkedRules(); diff --git a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java index 20c6d746805..e8575b36672 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java @@ -21,8 +21,6 @@ import org.drools.core.common.BetaConstraints; import org.drools.core.common.DoubleBetaConstraints; import org.drools.core.common.DoubleNonIndexSkipBetaConstraints; -import org.drools.core.common.GarbageCollector; -import org.drools.core.common.InternalAgenda; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.Memory; @@ -360,7 +358,7 @@ public void doDeleteRightTuple(final RightTuple rightTuple, log.trace( "{} delete queue={} size={} pctx={} lt={}", getClass().getSimpleName(), System.identityHashCode( memory.getSegmentMemory().getStreamQueue() ), memory.getSegmentMemory().getStreamQueue().size(), PhreakPropagationContext.intEnumToString(rightTuple.getPropagationContext()), rightTuple ); } - registerUnlinkedPaths(wm, memory, stagedDeleteWasEmpty); + registerUnlinkedPaths(wm, memory.getSegmentMemory(), stagedDeleteWasEmpty); } else { stagedDeleteWasEmpty = stagedRightTuples.addDelete(rightTuple); } @@ -373,20 +371,6 @@ public void doDeleteRightTuple(final RightTuple rightTuple, }; } - protected void registerUnlinkedPaths(InternalWorkingMemory wm, BetaMemory memory, boolean stagedDeleteWasEmpty) { - if (stagedDeleteWasEmpty && !memory.getSegmentMemory().isSegmentLinked()) { - GarbageCollector garbageCollector = ((InternalAgenda)wm.getAgenda()).getGarbageCollector(); - synchronized (garbageCollector) { - for (PathMemory pmem : memory.getSegmentMemory().getPathMemories()) { - if (pmem.getNodeType() == NodeTypeEnums.RuleTerminalNode) { - garbageCollector.add(pmem.getOrCreateRuleAgendaItem(wm)); - } - } - garbageCollector.increaseDeleteCounter(); - } - } - } - public void doUpdateRightTuple(final RightTuple rightTuple, final InternalWorkingMemory wm, final BetaMemory memory) { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java index d807331c93a..1e239a5f083 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java @@ -331,6 +331,7 @@ private static void doDeleteSegmentMemory(LeftTuple leftTuple, PropagationContex if ( log.isTraceEnabled() ) { log.trace( "LeftInputAdapterNode delete size={} queue={} pctx={} lt={}", System.identityHashCode( sm.getStreamQueue() ), sm.getStreamQueue().size(), PhreakPropagationContext.intEnumToString(pctx), leftTuple ); } + registerUnlinkedPaths(wm, sm, stagedDeleteWasEmpty); } else { stagedDeleteWasEmpty = leftTuples.addDelete(leftTuple); } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java b/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java index a3f80a51bc8..7479befb549 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/NotNode.java @@ -185,7 +185,7 @@ public void doDeleteRightTuple(final RightTuple rightTuple, PropagationContext pctx = rightTuple.getPropagationContext(); stagedDeleteWasEmpty = memory.getSegmentMemory().getStreamQueue().addDelete(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType())); //log.trace( "NotNode delete queue={} size={} lt={}", System.identityHashCode( memory.getSegmentMemory().getTupleQueue() ), memory.getSegmentMemory().getTupleQueue().size(), rightTuple ); - registerUnlinkedPaths(wm, memory, stagedDeleteWasEmpty); + registerUnlinkedPaths(wm, memory.getSegmentMemory(), stagedDeleteWasEmpty); } else { stagedDeleteWasEmpty = stagedRightTuples.addDelete( rightTuple ); } diff --git a/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java b/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java index 1872077f2ba..ca5473a9d9a 100644 --- a/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java +++ b/drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java @@ -1508,5 +1508,8 @@ public void remove(RuleAgendaItem item) { } @Override public void add(RuleAgendaItem item) { } + + @Override + public int getDeleteCounter() { return 0; } } } From 634260ab7834f9a3a629cff5540ba91f681dd342 Mon Sep 17 00:00:00 2001 From: sotty Date: Fri, 25 Jul 2014 17:03:41 +0200 Subject: [PATCH 57/76] [DROOLS-535] Fix platform dependencies --- .../org/drools/core/base/FieldFactoryTest.java | 2 +- ...DefaultKieSessionFromByteArrayExampleTest.java | 6 ++++-- .../DefaultKieSessionFromFileExampleTest.java | 6 ++++-- .../DefaultKieSessionExampleTest.java | 6 ++++-- .../DefaultKieSessionFromFSExampleTest.java | 9 ++++----- .../KieModuleFromMultipleFilesExampleTest.java | 10 ++++++---- .../KieBaseInclusionExampleTest.java | 10 ++++++---- .../KieContainerFromKieRepoExampleTest.java | 6 ++++-- .../kiefilesystem/KieFileSystemExampleTest.java | 6 ++++-- .../kiemodulemodel/KieModuleModelExampleTest.java | 15 ++++++++------- .../NamedKieSessionExampleTest.java | 5 +++-- .../CDIExampleWithInclusionTest.java | 10 ++++++---- .../example/cdi/cdiexample/CDIExampleTest.java | 6 ++++-- .../cdi/cdiexample/CDIInstanceExampleTest.java | 6 ++++-- .../org/drools/pmml/pmml_4_1/PMML4Helper.java | 10 ++-------- .../pmml_4_1/transformations/FunctionsTest.java | 2 +- .../drools/reteoo/integrationtests/MiscTest.java | 3 ++- .../scorecards/pmml/ScorecardPMMLGenerator.java | 3 ++- .../backend/rule/RuleModelPersistenceHelper.java | 14 ++++++-------- .../helper/KieModuleDeploymentHelperImpl.java | 15 +++++++-------- 20 files changed, 82 insertions(+), 68 deletions(-) diff --git a/drools-core/src/test/java/org/drools/core/base/FieldFactoryTest.java b/drools-core/src/test/java/org/drools/core/base/FieldFactoryTest.java index fae485e847b..02f0a2aa5b3 100644 --- a/drools-core/src/test/java/org/drools/core/base/FieldFactoryTest.java +++ b/drools-core/src/test/java/org/drools/core/base/FieldFactoryTest.java @@ -51,7 +51,7 @@ public void testBigInteger() { @Test public void testDate() throws Exception { - SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy", Locale.UK); + SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH); String s = df.format(df.parse("10-Jul-1974")); final FieldValue val = FieldFactory.getInstance().getFieldValue( s, ValueType.DATE_TYPE, diff --git a/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromByteArrayExampleTest.java b/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromByteArrayExampleTest.java index c75a8beb040..4b3201bd001 100644 --- a/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromByteArrayExampleTest.java +++ b/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromByteArrayExampleTest.java @@ -18,6 +18,8 @@ public class DefaultKieSessionFromByteArrayExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -27,8 +29,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); } diff --git a/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromFileExampleTest.java b/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromFileExampleTest.java index 83215c55d6e..71a8a333300 100644 --- a/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromFileExampleTest.java +++ b/drools-examples-api/default-kiesession-from-file/src/test/java/org/drools/example/api/defaultkiesessionfromfile/DefaultKieSessionFromFileExampleTest.java @@ -10,6 +10,8 @@ public class DefaultKieSessionFromFileExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -19,8 +21,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionExampleTest.java b/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionExampleTest.java index ea9d3a909d5..05f85171a5e 100644 --- a/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionExampleTest.java +++ b/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionExampleTest.java @@ -9,6 +9,8 @@ public class DefaultKieSessionExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -18,8 +20,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionFromFSExampleTest.java b/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionFromFSExampleTest.java index 4ab019ef8de..42a8f3de9fc 100644 --- a/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionFromFSExampleTest.java +++ b/drools-examples-api/default-kiesession/src/test/java/org/drools/example/api/defaultkiesession/DefaultKieSessionFromFSExampleTest.java @@ -14,6 +14,8 @@ public class DefaultKieSessionFromFSExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -22,13 +24,10 @@ public void testGo() { ps.close(); String actual = new String(baos.toByteArray()); - if (File.separatorChar == '\\') { - actual = actual.replaceAll("\r\n", "\n"); - } String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); } diff --git a/drools-examples-api/kie-module-from-multiple-files/src/test/java/org/drools/example/api/kiemodulefrommultiplefiles/KieModuleFromMultipleFilesExampleTest.java b/drools-examples-api/kie-module-from-multiple-files/src/test/java/org/drools/example/api/kiemodulefrommultiplefiles/KieModuleFromMultipleFilesExampleTest.java index f86cb93d689..6d40672b5e5 100644 --- a/drools-examples-api/kie-module-from-multiple-files/src/test/java/org/drools/example/api/kiemodulefrommultiplefiles/KieModuleFromMultipleFilesExampleTest.java +++ b/drools-examples-api/kie-module-from-multiple-files/src/test/java/org/drools/example/api/kiemodulefrommultiplefiles/KieModuleFromMultipleFilesExampleTest.java @@ -10,6 +10,8 @@ public class KieModuleFromMultipleFilesExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -19,10 +21,10 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n" + - "Dave: Open the pod bay doors, HAL.\n" + - "HAL: I'm sorry, Dave. I'm afraid I can't do that.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL + + "Dave: Open the pod bay doors, HAL." + NL + + "HAL: I'm sorry, Dave. I'm afraid I can't do that." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-api/kiebase-inclusion/src/test/java/org/drools/example/api/kiebaseinclusion/KieBaseInclusionExampleTest.java b/drools-examples-api/kiebase-inclusion/src/test/java/org/drools/example/api/kiebaseinclusion/KieBaseInclusionExampleTest.java index b28044eb850..3359db83b80 100644 --- a/drools-examples-api/kiebase-inclusion/src/test/java/org/drools/example/api/kiebaseinclusion/KieBaseInclusionExampleTest.java +++ b/drools-examples-api/kiebase-inclusion/src/test/java/org/drools/example/api/kiebaseinclusion/KieBaseInclusionExampleTest.java @@ -9,6 +9,8 @@ public class KieBaseInclusionExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -18,10 +20,10 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n" + - "Dave: Open the pod bay doors, HAL.\n" + - "HAL: I'm sorry, Dave. I'm afraid I can't do that.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL + + "Dave: Open the pod bay doors, HAL." + NL + + "HAL: I'm sorry, Dave. I'm afraid I can't do that." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-api/kiecontainer-from-kierepo/src/test/java/org/drools/example/api/kiecontainerfromkierepo/KieContainerFromKieRepoExampleTest.java b/drools-examples-api/kiecontainer-from-kierepo/src/test/java/org/drools/example/api/kiecontainerfromkierepo/KieContainerFromKieRepoExampleTest.java index 10365fe05b4..0fbae61d3b5 100644 --- a/drools-examples-api/kiecontainer-from-kierepo/src/test/java/org/drools/example/api/kiecontainerfromkierepo/KieContainerFromKieRepoExampleTest.java +++ b/drools-examples-api/kiecontainer-from-kierepo/src/test/java/org/drools/example/api/kiecontainerfromkierepo/KieContainerFromKieRepoExampleTest.java @@ -10,6 +10,8 @@ public class KieContainerFromKieRepoExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test @Ignore public void testGo() { @@ -20,8 +22,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-api/kiefilesystem-example/src/test/java/org/drools/example/api/kiefilesystem/KieFileSystemExampleTest.java b/drools-examples-api/kiefilesystem-example/src/test/java/org/drools/example/api/kiefilesystem/KieFileSystemExampleTest.java index 0de7b29bc27..0dc51e82280 100644 --- a/drools-examples-api/kiefilesystem-example/src/test/java/org/drools/example/api/kiefilesystem/KieFileSystemExampleTest.java +++ b/drools-examples-api/kiefilesystem-example/src/test/java/org/drools/example/api/kiefilesystem/KieFileSystemExampleTest.java @@ -9,6 +9,8 @@ public class KieFileSystemExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -18,8 +20,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-api/kiemodulemodel-example/src/test/java/org/drools/example/api/kiemodulemodel/KieModuleModelExampleTest.java b/drools-examples-api/kiemodulemodel-example/src/test/java/org/drools/example/api/kiemodulemodel/KieModuleModelExampleTest.java index 7cd45137fb1..2d9edd16799 100644 --- a/drools-examples-api/kiemodulemodel-example/src/test/java/org/drools/example/api/kiemodulemodel/KieModuleModelExampleTest.java +++ b/drools-examples-api/kiemodulemodel-example/src/test/java/org/drools/example/api/kiemodulemodel/KieModuleModelExampleTest.java @@ -10,8 +10,9 @@ public class KieModuleModelExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test - @Ignore public void testGo() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); @@ -20,12 +21,12 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n" + - "Dave: Open the pod bay doors, HAL.\n" + - "HAL: I'm sorry, Dave. I'm afraid I can't do that.\n" + - "Dave: What's the problem?\n" + - "HAL: I think you know what the problem is just as well as I do.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL + + "Dave: Open the pod bay doors, HAL." + NL + + "HAL: I'm sorry, Dave. I'm afraid I can't do that." + NL + + "Dave: What's the problem?" + NL + + "HAL: I think you know what the problem is just as well as I do." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-api/named-kiesession/src/test/java/org/drools/example/api/namedkiesession/NamedKieSessionExampleTest.java b/drools-examples-api/named-kiesession/src/test/java/org/drools/example/api/namedkiesession/NamedKieSessionExampleTest.java index 79addfe5890..ce9f33e231d 100644 --- a/drools-examples-api/named-kiesession/src/test/java/org/drools/example/api/namedkiesession/NamedKieSessionExampleTest.java +++ b/drools-examples-api/named-kiesession/src/test/java/org/drools/example/api/namedkiesession/NamedKieSessionExampleTest.java @@ -8,6 +8,7 @@ import static org.junit.Assert.assertEquals; public class NamedKieSessionExampleTest { + private static final String NL = System.getProperty("line.separator"); @Test public void testGo() { @@ -18,8 +19,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); } } diff --git a/drools-examples-cdi/cdi-example-with-inclusion/src/test/java/org/drools/example/cdi/cdiexamplewithinclusion/CDIExampleWithInclusionTest.java b/drools-examples-cdi/cdi-example-with-inclusion/src/test/java/org/drools/example/cdi/cdiexamplewithinclusion/CDIExampleWithInclusionTest.java index 0055821e3bb..7cf90b3aad0 100644 --- a/drools-examples-cdi/cdi-example-with-inclusion/src/test/java/org/drools/example/cdi/cdiexamplewithinclusion/CDIExampleWithInclusionTest.java +++ b/drools-examples-cdi/cdi-example-with-inclusion/src/test/java/org/drools/example/cdi/cdiexamplewithinclusion/CDIExampleWithInclusionTest.java @@ -11,6 +11,8 @@ public class CDIExampleWithInclusionTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { Weld w = new Weld(); @@ -26,10 +28,10 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n" + - "Dave: Open the pod bay doors, HAL.\n" + - "HAL: I'm sorry, Dave. I'm afraid I can't do that.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL + + "Dave: Open the pod bay doors, HAL." + NL + + "HAL: I'm sorry, Dave. I'm afraid I can't do that." + NL; assertEquals(expected, actual); w.shutdown(); diff --git a/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIExampleTest.java b/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIExampleTest.java index 49ac5d63273..7b987beb9ac 100644 --- a/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIExampleTest.java +++ b/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIExampleTest.java @@ -11,6 +11,8 @@ public class CDIExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { Weld w = new Weld(); @@ -26,8 +28,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); w.shutdown(); diff --git a/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIInstanceExampleTest.java b/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIInstanceExampleTest.java index e50bfc63107..576e0f6ed57 100644 --- a/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIInstanceExampleTest.java +++ b/drools-examples-cdi/cdi-example/src/test/java/org/drools/example/cdi/cdiexample/CDIInstanceExampleTest.java @@ -11,6 +11,8 @@ public class CDIInstanceExampleTest { + private static final String NL = System.getProperty("line.separator"); + @Test public void testGo() { Weld w = new Weld(); @@ -26,8 +28,8 @@ public void testGo() { String actual = new String(baos.toByteArray()); String expected = "" + - "Dave: Hello, HAL. Do you read me, HAL?\n" + - "HAL: Dave. I read you.\n"; + "Dave: Hello, HAL. Do you read me, HAL?" + NL + + "HAL: Dave. I read you." + NL; assertEquals(expected, actual); w.shutdown(); diff --git a/drools-pmml/src/main/java/org/drools/pmml/pmml_4_1/PMML4Helper.java b/drools-pmml/src/main/java/org/drools/pmml/pmml_4_1/PMML4Helper.java index 6e35c6f40fe..6116fcf6256 100644 --- a/drools-pmml/src/main/java/org/drools/pmml/pmml_4_1/PMML4Helper.java +++ b/drools-pmml/src/main/java/org/drools/pmml/pmml_4_1/PMML4Helper.java @@ -34,13 +34,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; +import java.util.*; public class PMML4Helper { @@ -581,7 +575,7 @@ public String mapFunction( String functor, boolean asQuery, String... args ) { } else if ("formatDatetime".equals(functor)) { //TODO : PMML Uses Posix ans += "new java.text.SimpleDateFormat(" + posix2Java(args[1]) + - ").format(new SimpleDateFormat().parse(" + args[0] +"))"; + ").format(new SimpleDateFormat().parse(" + args[0] +", java.util.Locale.ENGLISH))"; } else if ("dateDaysSinceYear".equals(functor)) { ans += "( (new java.text.SimpleDateFormat()).parse(" + args[0] + ").getTime()" + " - (new java.text.SimpleDateFormat()).parse(\"01/01/" + args[1] + "\").getTime() ) / (1000*60*60*24)"; diff --git a/drools-pmml/src/test/java/org/drools/pmml/pmml_4_1/transformations/FunctionsTest.java b/drools-pmml/src/test/java/org/drools/pmml/pmml_4_1/transformations/FunctionsTest.java index 9555b661c6d..1c6ae737cec 100644 --- a/drools-pmml/src/test/java/org/drools/pmml/pmml_4_1/transformations/FunctionsTest.java +++ b/drools-pmml/src/test/java/org/drools/pmml/pmml_4_1/transformations/FunctionsTest.java @@ -90,7 +90,7 @@ public void testFunctionMapping() { assertEquals("(\"testString\".toString().substring(2,6))" , ctx.mapFunction("substring","\"testString\"","3","4")); assertEquals("(new java.util.Formatter(new StringBuilder(),java.util.Locale.getDefault()).format(\"%3d\",3.0))" , ctx.mapFunction("formatNumber","\"%3d\"","3.0")); - assertEquals("(new java.text.SimpleDateFormat(\"format\").format(new SimpleDateFormat().parse(\"date\")))" , ctx.mapFunction("formatDatetime","\"date\"","\"format\"")); + assertEquals("(new java.text.SimpleDateFormat(\"format\").format(new SimpleDateFormat().parse(\"date\", java.util.Locale.ENGLISH)))" , ctx.mapFunction("formatDatetime","\"date\"","\"format\"")); assertEquals("(( (new java.text.SimpleDateFormat()).parse(\"date\").getTime() - (new java.text.SimpleDateFormat()).parse(\"01/01/1956\").getTime() ) / (1000*60*60*24))", ctx.mapFunction("dateDaysSinceYear","\"date\"","1956")); assertEquals("(( (new java.text.SimpleDateFormat()).parse(\"date\").getTime() - (new java.text.SimpleDateFormat()).parse(\"01/01/1956\").getTime() ) / 1000)", ctx.mapFunction("dateSecondsSinceYear","\"date\"","1956")); diff --git a/drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/MiscTest.java b/drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/MiscTest.java index 74cfb178961..da2e8ef8fbf 100644 --- a/drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/MiscTest.java +++ b/drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/MiscTest.java @@ -92,6 +92,7 @@ import org.drools.core.reteoo.LeftTuple; import org.drools.core.rule.MapBackedClassLoader; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.kie.api.KieBaseConfiguration; import org.kie.api.command.Setter; @@ -5891,7 +5892,7 @@ public void testInsertionOrder() { } - @Test + @Test @Ignore public void testFireAllWhenFiringUntilHalt() { KnowledgeBase kbase = getKnowledgeBase(); final StatefulKnowledgeSession ksession = createKnowledgeSession( kbase ); diff --git a/drools-scorecards/src/main/java/org/drools/scorecards/pmml/ScorecardPMMLGenerator.java b/drools-scorecards/src/main/java/org/drools/scorecards/pmml/ScorecardPMMLGenerator.java index 92ce9ffb763..24a67b4e34c 100644 --- a/drools-scorecards/src/main/java/org/drools/scorecards/pmml/ScorecardPMMLGenerator.java +++ b/drools-scorecards/src/main/java/org/drools/scorecards/pmml/ScorecardPMMLGenerator.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; public class ScorecardPMMLGenerator { @@ -53,7 +54,7 @@ public PMML generateDocument(Scorecard pmmlScorecard) { PMML pmml = new PMML(); Header header = new Header(); Timestamp timestamp = new Timestamp(); - timestamp.getContent().add(new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss z").format(new Date())); + timestamp.getContent().add(new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss z", Locale.ENGLISH).format(new Date())); header.setTimestamp(timestamp); header.setDescription("generated by the drools-scorecards module"); header.getExtensions().add(scorecardPackage); diff --git a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java index 349347b7632..27b8230c535 100644 --- a/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java +++ b/drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java @@ -4,10 +4,7 @@ import java.math.BigInteger; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import org.apache.commons.lang.NumberUtils; import org.apache.commons.lang.StringUtils; @@ -74,12 +71,13 @@ static int inferFieldNature( final String dataType, } else if ( DataType.TYPE_DATE.equals( dataType ) ) { try { - new SimpleDateFormat( DateUtils.getDateFormatMask() ).parse( adjustParam( dataType, - value, - Collections.EMPTY_MAP, - isJavaDialect ) ); + new SimpleDateFormat( DateUtils.getDateFormatMask(), Locale.ENGLISH ).parse(adjustParam(dataType, + value, + Collections.EMPTY_MAP, + isJavaDialect)); return FieldNatureType.TYPE_LITERAL; } catch ( ParseException e ) { + e.printStackTrace(); return FieldNatureType.TYPE_FORMULA; } diff --git a/kie-ci/src/main/java/org/kie/api/builder/helper/KieModuleDeploymentHelperImpl.java b/kie-ci/src/main/java/org/kie/api/builder/helper/KieModuleDeploymentHelperImpl.java index 6f93dd63c31..0eb7077369e 100644 --- a/kie-ci/src/main/java/org/kie/api/builder/helper/KieModuleDeploymentHelperImpl.java +++ b/kie-ci/src/main/java/org/kie/api/builder/helper/KieModuleDeploymentHelperImpl.java @@ -420,7 +420,7 @@ static List internalLoadResources(String path, boolean fromDir) th if (resourcePath.startsWith("/")) { resourcePath = resourcePath.substring(1); } - int depth = resourcePath.split(File.separator).length + 1; + int depth = resourcePath.split("/").length + 1; String jarUrlString = urlString.substring("jar:".length(), jarPathIndex); url = new URL(jarUrlString); @@ -429,8 +429,8 @@ static List internalLoadResources(String path, boolean fromDir) th ZipEntry ze = zip.getNextEntry(); while (ze != null) { String name = ze.getName(); - if (name.startsWith(resourcePath) && !name.endsWith(File.separator) - && (name.split(File.separator).length == depth)) { + if (name.startsWith(resourcePath) && !name.endsWith("/") + && (name.split("/").length == depth)) { String shortName = name.substring(name.lastIndexOf("/") + 1); String content = convertFileToString(zip); output.add(new KJarResource(shortName, content)); @@ -544,16 +544,15 @@ private static void addClass(Class userClass, KieFileSystem kfs) { throw new RuntimeException("Unable to read from " + jarPath, e); } } - + String pkgFolder = userClass.getPackage().toString(); - + // @#$%ing Eclipe classloader!! The following 2 lines "normalize" the package name from what Eclipse (and other IDE's?) do with it pkgFolder = pkgFolder.replace("package ", ""); pkgFolder = pkgFolder.replaceAll(",.+$", ""); - - pkgFolder = pkgFolder.replaceAll("\\.", File.separator); + pkgFolder = pkgFolder.replaceAll("\\.", "/" ); String classFilePath = pkgFolder + "/" + classSimpleName + ".class"; - + if( classFilePath.contains(" " ) ) { throw new RuntimeException("Invalid class name ('" + classFilePath + "'), contact the developers."); } From f0681e9bba01af5deae148e91f491ae84555fb24 Mon Sep 17 00:00:00 2001 From: Petr Siroky Date: Fri, 25 Jul 2014 19:30:39 +0200 Subject: [PATCH 58/76] [DROOLS-495] maven-plugin now executes also process-test-resources phase * this phase is needed in order to copy the test resources into target/, so they can be actually used for testing. (cherry picked from commit e5f1dc8cdfa274d751c9bba6641e904e016b9349) --- .../src/main/resources/META-INF/plexus/components.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kie-maven-plugin/src/main/resources/META-INF/plexus/components.xml b/kie-maven-plugin/src/main/resources/META-INF/plexus/components.xml index 1f867d1b480..a6d8019b5cf 100644 --- a/kie-maven-plugin/src/main/resources/META-INF/plexus/components.xml +++ b/kie-maven-plugin/src/main/resources/META-INF/plexus/components.xml @@ -9,9 +9,8 @@ org.apache.maven.plugins:maven-resources-plugin:resources - - org.apache.maven.plugins:maven-compiler-plugin:compile,org.kie:kie-maven-plugin:build - + org.apache.maven.plugins:maven-compiler-plugin:compile,org.kie:kie-maven-plugin:build + org.apache.maven.plugins:maven-resources-plugin:testResources org.apache.maven.plugins:maven-compiler-plugin:testCompile org.apache.maven.plugins:maven-surefire-plugin:test org.apache.maven.plugins:maven-jar-plugin:jar From 3b869cd4013a7a5201fb0f60af65965db7777ee2 Mon Sep 17 00:00:00 2001 From: sotty Date: Fri, 25 Jul 2014 21:37:41 +0200 Subject: [PATCH 59/76] [DROOLS-564] NPE when using globals as query element inputs (cherry picked from commit 9db38d098e67560839b36661bdf24a5f5cdae1df) (cherry picked from commit 855efefd0eab237b4826e9ab4a3a458eccf1732d) --- .../compiler/integrationtests/QueryTest.java | 48 +++++++++++++++++++ .../core/definitions/rule/impl/RuleImpl.java | 5 +- .../reteoo/builder/ReteooRuleBuilder.java | 3 +- .../drools/core/rule/LogicTransformer.java | 11 +++-- .../dialect/asm/ConsequenceGenerator.java | 4 +- .../core/spi/DeclarationScopeResolver.java | 27 +++++------ .../core/rule/LogicTransformerTest.java | 9 ++-- 7 files changed, 78 insertions(+), 29 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java index 914e72cdfba..863dfc962ca 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java @@ -28,6 +28,7 @@ import org.kie.api.builder.Results; import org.kie.api.definition.rule.Rule; import org.kie.api.io.ResourceType; +import org.kie.api.runtime.KieSession; import org.kie.api.runtime.conf.QueryListenerOption; import org.kie.api.runtime.rule.FactHandle; import org.kie.api.runtime.rule.LiveQuery; @@ -43,6 +44,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -942,4 +944,50 @@ public void testQueryWithWrongParamNumber() { assertEquals( 1, results.getMessages( Message.Level.ERROR ).size() ); } + + + @Test + public void testGlobalsInQueries() { + String drl = "\n" + + "package com.sample\n" + + "\n" + + "global java.lang.String AString;\n" + + "global java.util.List list;\n" + + "\n" + + "declare AThing\n" + + " name: String @key\n" + + "end\n" + + "\n" + + "rule init\n" + + " when\n" + + " then\n" + + " insert( new AThing( AString ) );\n" + + " insert( new AThing( 'Holla' ) );\n" + + "end\n" + + "\n" + + "query test( String $in ) \n" + + " AThing( $in; )\n" + + "end\n" + + "\n" + + "rule spot\n" + + " when\n" + + " test( \"Hello\"; )\n" + + " AThing( \"Hello\"; )\n" + + " test( AString; )\n" + + " AThing( AString; )" + + " then\n" + + " list.add( AString + \" World\" );\n" + + "end\n"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ks = helper.build( ).newKieSession(); + + ArrayList list = new ArrayList(); + ks.setGlobal( "AString", "Hello" ); + ks.setGlobal( "list", list ); + ks.fireAllRules(); + + assertEquals( Arrays.asList( "Hello World" ), list ); + } } diff --git a/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java b/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java index 24001fa5e97..2f32ba59810 100644 --- a/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java +++ b/drools-core/src/main/java/org/drools/core/definitions/rule/impl/RuleImpl.java @@ -555,10 +555,11 @@ private GroupElement getExtendedLhs(RuleImpl rule, * @return * @throws org.drools.core.rule.InvalidPatternException */ - public GroupElement[] getTransformedLhs( LogicTransformer transformer ) throws InvalidPatternException { + public GroupElement[] getTransformedLhs( LogicTransformer transformer, Map> globals ) throws InvalidPatternException { //Moved to getExtendedLhs --final GroupElement cloned = (GroupElement) this.lhsRoot.clone(); return transformer.transform( getExtendedLhs( this, - null ) ); + null ), + globals ); } public int getSpecifity() { diff --git a/drools-core/src/main/java/org/drools/core/reteoo/builder/ReteooRuleBuilder.java b/drools-core/src/main/java/org/drools/core/reteoo/builder/ReteooRuleBuilder.java index 7c8ddb38e8e..819d6fb57f6 100755 --- a/drools-core/src/main/java/org/drools/core/reteoo/builder/ReteooRuleBuilder.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/builder/ReteooRuleBuilder.java @@ -102,7 +102,8 @@ public List addRule( final RuleImpl rule, final List nodes = new ArrayList(); // transform rule and gets the array of subrules - final GroupElement[] subrules = rule.getTransformedLhs( kBase.getConfiguration().getComponentFactory().getLogicTransformerFactory().getLogicTransformer() ); + final GroupElement[] subrules = rule.getTransformedLhs( kBase.getConfiguration().getComponentFactory().getLogicTransformerFactory().getLogicTransformer(), + kBase.getGlobals() ); for (int i = 0; i < subrules.length; i++) { diff --git a/drools-core/src/main/java/org/drools/core/rule/LogicTransformer.java b/drools-core/src/main/java/org/drools/core/rule/LogicTransformer.java index a8d577cafd2..22db11f9c8b 100644 --- a/drools-core/src/main/java/org/drools/core/rule/LogicTransformer.java +++ b/drools-core/src/main/java/org/drools/core/rule/LogicTransformer.java @@ -72,7 +72,7 @@ private void addTransformationPair(final GroupElement.Type parent, method ); } - public GroupElement[] transform(final GroupElement cloned) throws InvalidPatternException { + public GroupElement[] transform( final GroupElement cloned, Map> globals ) throws InvalidPatternException { //moved cloned to up //final GroupElement cloned = (GroupElement) and.clone(); @@ -96,7 +96,7 @@ public GroupElement[] transform(final GroupElement cloned) throws InvalidPattern for ( int i = 0; i < ands.length; i++ ) { // fix the cloned declarations - this.fixClonedDeclarations( ands[i] ); + this.fixClonedDeclarations( ands[i], globals ); ands[i].setRoot( true ); } @@ -124,10 +124,11 @@ protected GroupElement[] splitOr( final GroupElement cloned ) { * specially patterns and corresponding declarations. So now * we need to fix any references to cloned declarations. * @param and + * @param globals */ - protected void fixClonedDeclarations(GroupElement and) { + protected void fixClonedDeclarations( GroupElement and, Map> globals ) { Stack contextStack = new Stack(); - DeclarationScopeResolver resolver = new DeclarationScopeResolver( Collections.>emptyMap(), + DeclarationScopeResolver resolver = new DeclarationScopeResolver( globals, contextStack ); contextStack.push( and ); @@ -235,7 +236,7 @@ private void processElement(final DeclarationScopeResolver resolver, for ( int i = 0; i < qe.getDeclIndexes().length; i++ ) { Declaration declr = (Declaration) qe.getArgTemplate()[qe.getDeclIndexes()[i]]; Declaration resolved = resolver.getDeclaration( null, - declr.getIdentifier() ); + declr.getIdentifier() ); if ( resolved != null && resolved != declr && resolved.getPattern() != pattern ) { qe.getArgTemplate()[qe.getDeclIndexes()[i]] = resolved; } diff --git a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ConsequenceGenerator.java b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ConsequenceGenerator.java index 8cff8f67403..6cca08fb090 100644 --- a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ConsequenceGenerator.java +++ b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ConsequenceGenerator.java @@ -36,8 +36,8 @@ public static void generate(final ConsequenceStub stub, KnowledgeHelper knowledg RuleTerminalNode rtn = (RuleTerminalNode) knowledgeHelper.getMatch().getTuple().getLeftTupleSink(); final Declaration[] declarations = rtn.getDeclarations(); final boolean isOrRule = rtn.getRule().getTransformedLhs( - workingMemory.getKnowledgeBase().getConfiguration().getComponentFactory().getLogicTransformerFactory().getLogicTransformer() - ).length > 1; + workingMemory.getKnowledgeBase().getConfiguration().getComponentFactory().getLogicTransformerFactory().getLogicTransformer(), + workingMemory.getKnowledgeBase().getGlobals() ).length > 1; final LeftTuple tuple = (LeftTuple)knowledgeHelper.getTuple(); // Sort declarations based on their offset, so it can ascend the tuple's parents stack only once diff --git a/drools-core/src/main/java/org/drools/core/spi/DeclarationScopeResolver.java b/drools-core/src/main/java/org/drools/core/spi/DeclarationScopeResolver.java index 44b7d7f979c..3a725dd56ea 100644 --- a/drools-core/src/main/java/org/drools/core/spi/DeclarationScopeResolver.java +++ b/drools-core/src/main/java/org/drools/core/spi/DeclarationScopeResolver.java @@ -102,19 +102,19 @@ public Declaration getDeclaration(final RuleImpl rule, // it may be a global or something if ( this.map.containsKey( (identifier) ) ) { - if ( pkg != null ) { - Class cls = this.map.get( identifier ); - ClassObjectType classObjectType = new ClassObjectType( cls ); + Class cls = this.map.get( identifier ); + ClassObjectType classObjectType = new ClassObjectType( cls ); - Declaration declaration; - final Pattern dummy = new Pattern( 0, - classObjectType ); + Declaration declaration; + final Pattern dummy = new Pattern( 0, + classObjectType ); - InternalReadAccessor globalExtractor = getReadAcessor( identifier, - classObjectType ); - declaration = new Declaration( identifier, - globalExtractor, - dummy ); + InternalReadAccessor globalExtractor = getReadAcessor( identifier, + classObjectType ); + declaration = new Declaration( identifier, + globalExtractor, + dummy ); + if ( pkg != null ) { // make sure dummy and globalExtractor are wired up to correct ClassObjectType // and set as targets for rewiring @@ -122,11 +122,8 @@ public Declaration getDeclaration(final RuleImpl rule, dummy ); pkg.getClassFieldAccessorStore().getClassObjectType( classObjectType, ( AcceptsClassObjectType ) globalExtractor ); - - return declaration; - } else { - throw new UnsupportedOperationException( "This shoudln't happen outside of PackageBuilder" ); } + return declaration; } return null; } diff --git a/drools-core/src/test/java/org/drools/core/rule/LogicTransformerTest.java b/drools-core/src/test/java/org/drools/core/rule/LogicTransformerTest.java index 34d84e1399a..d490ea8d85d 100644 --- a/drools-core/src/test/java/org/drools/core/rule/LogicTransformerTest.java +++ b/drools-core/src/test/java/org/drools/core/rule/LogicTransformerTest.java @@ -20,6 +20,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Collections; import org.drools.core.base.ClassObjectType; import org.drools.core.test.model.DroolsTestCase; @@ -347,7 +348,7 @@ public void testNotExistsTransformation() throws InvalidPatternException { and.addChild( a ); and.addChild( b ); - GroupElement[] transformed = LogicTransformer.getInstance().transform( not ); + GroupElement[] transformed = LogicTransformer.getInstance().transform( not, Collections.EMPTY_MAP ); GroupElement wrapper = transformed[0]; GroupElement notR = (GroupElement) wrapper.getChildren().get( 0 ); @@ -469,7 +470,7 @@ public void testEliminateEmptyBranchesAndDuplications() throws InvalidRuleExcept final GroupElement or = GroupElementFactory.newOrInstance(); and1.addChild( or ); - final GroupElement[] result = LogicTransformer.getInstance().transform( and1 ); + final GroupElement[] result = LogicTransformer.getInstance().transform( and1, Collections.EMPTY_MAP ); assertLength( 1, result ); @@ -588,7 +589,7 @@ public void testProcessTree() throws IOException, root.addChild( and3 ); root.addChild( not3 ); - final GroupElement[] result = LogicTransformer.getInstance().transform( root ); + final GroupElement[] result = LogicTransformer.getInstance().transform( root, Collections.EMPTY_MAP ); // ---------------------------------------------------------------------------------- // Now construct the result tree so we can test root against what it @@ -774,7 +775,7 @@ public void testTransform() throws IOException, and2.addChild( or3 ); and.addChild( and2 ); - final GroupElement[] ands = LogicTransformer.getInstance().transform( and ); + final GroupElement[] ands = LogicTransformer.getInstance().transform( and, Collections.EMPTY_MAP ); // Uncomment this when you need to output a new known correct tree // result From f4e899395c0fb2aa8bcd40788a1e2f8f26857f85 Mon Sep 17 00:00:00 2001 From: sotty Date: Sat, 26 Jul 2014 01:34:11 +0200 Subject: [PATCH 60/76] [DROOLS-114] Support defeasible rules (cherry picked from commit 7941a0c8d7e66c6c7719c14ca58d798337d067d8) (cherry picked from commit a1d5e6d065d34673644cde97d6cb5882aace095d) --- .../defeasible/DefeasibilityTest.java | 60 +++++++++++++++++++ .../defeasible/DefeasibleBeliefSet.java | 13 ++-- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/beliefsystem/defeasible/DefeasibilityTest.java b/drools-compiler/src/test/java/org/drools/compiler/beliefsystem/defeasible/DefeasibilityTest.java index ba12904ee52..7d4121aebe8 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/beliefsystem/defeasible/DefeasibilityTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/beliefsystem/defeasible/DefeasibilityTest.java @@ -16,6 +16,7 @@ package org.drools.compiler.beliefsystem.defeasible; import org.drools.core.BeliefSystemType; +import org.drools.core.ClassObjectFilter; import org.drools.core.SessionConfiguration; import org.drools.core.beliefsystem.BeliefSet; import org.drools.core.beliefsystem.defeasible.DefeasibilityStatus; @@ -849,5 +850,64 @@ public void testDefeatersAndDefeasibles() { } + @Test + public void testManyDefeasibles() { + String drl = "package org.drools.defeasible; " + + "declare Fact " + + " fact: String @key " + + "end " + + " " + + "rule init " + + " when " + + " then " + + " insert( new Fact( 'one' ) ); " + + " insert( new Fact( 'two' ) ); " + + " insert( new Fact( 'two' ) ); " + + "end " + + " " + + "rule rule1 " + + " @Defeasible " + + " enabled true " + + " when " + + " Fact( \"one\"; ) " + + " then " + + " System.out.println(\"one causes wibble\"); " + + " insertLogical( new Fact( \"wibble\") ); " + + "end " + + " " + + "rule rule2 " + + " @Defeasible " + + " when " + + " Fact( \"two\"; ) " + + " then " + + " System.out.println(\"two causes wibble\"); " + + " insertLogical( new Fact( \"wibble\") ); " + + "end " + + " " + + "rule rule3 " + + " @Defeater " + + " @Defeats( \"rule2\" ) " + + " when " + + " Fact( \"two\"; ) " + + " then " + + " System.out.println(\"two negates wibble\"); " + + " insertLogical( new Fact( \"wibble\"), \"neg\" ); " + + "end"; + + StatefulKnowledgeSession session = getSessionFromString( drl ); + session.fireAllRules(); + + FactType factType = session.getKieBase().getFactType( "org.drools.defeasible", "Fact" ); + for ( Object o : session.getObjects( new ClassObjectFilter( factType.getFactClass() ) ) ) { + if ( "wibble".equals( factType.get( o, "fact" ) ) ) { + InternalFactHandle handle = (InternalFactHandle) session.getFactHandle( o ); + DefeasibleBeliefSet dbs = (DefeasibleBeliefSet) handle.getEqualityKey().getBeliefSet(); + + assertEquals( 3, dbs.size() ); + assertTrue( dbs.isConflicting() ); + } + } + + } } diff --git a/drools-core/src/main/java/org/drools/core/beliefsystem/defeasible/DefeasibleBeliefSet.java b/drools-core/src/main/java/org/drools/core/beliefsystem/defeasible/DefeasibleBeliefSet.java index 7f4d17c99d4..3f8a45b5e95 100644 --- a/drools-core/src/main/java/org/drools/core/beliefsystem/defeasible/DefeasibleBeliefSet.java +++ b/drools-core/src/main/java/org/drools/core/beliefsystem/defeasible/DefeasibleBeliefSet.java @@ -1,11 +1,8 @@ package org.drools.core.beliefsystem.defeasible; -import org.drools.core.beliefsystem.BeliefSet; import org.drools.core.beliefsystem.BeliefSystem; import org.drools.core.beliefsystem.jtms.JTMSBeliefSet; import org.drools.core.beliefsystem.jtms.JTMSBeliefSetImpl.MODE; -import org.drools.core.beliefsystem.simple.SimpleLogicalDependency; -import org.drools.core.common.DefaultFactHandle; import org.drools.core.common.EqualityKey; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.LogicalDependency; @@ -108,8 +105,9 @@ public void add(LinkedListNode node) { boolean wasDefeated = false; for (LinkedListEntry existingNode = rootUndefeated; existingNode != null; existingNode = existingNode.getNext()) { DefeasibleLogicalDependency existingDep = existingNode.getObject(); - wasDefeated = checkAndApplyIsDefeated(newDep, rule, existingDep); + wasDefeated = checkIsDefeated( newDep, rule, existingDep ); if (wasDefeated) { + existingDep.addDefeated( newDep ); break; } } @@ -121,9 +119,10 @@ public void add(LinkedListNode node) { LinkedListEntry next = existingNode.getNext(); DefeasibleLogicalDependency existingDep = existingNode.getObject(); - if (checkAndApplyIsDefeated(existingDep, existingDep.getJustifier().getRule(), newDep)) { + if ( checkIsDefeated( existingDep, existingDep.getJustifier().getRule(), newDep ) ) { // fist remove it from the undefeated list removeUndefeated(existingDep, existingNode); + newDep.addDefeated(existingDep); if (existingDep.getRootDefeated() != null) { // build up the list of staged deps, that will need to be reprocessed if (stagedDeps == null) { @@ -170,19 +169,17 @@ public void remove(LinkedListNode node) { updateStatus(); } - private boolean checkAndApplyIsDefeated(DefeasibleLogicalDependency potentialInferior, RuleImpl rule, DefeasibleLogicalDependency potentialSuperior) { + private boolean checkIsDefeated( DefeasibleLogicalDependency potentialInferior, RuleImpl rule, DefeasibleLogicalDependency potentialSuperior ) { if ( potentialSuperior.getDefeats() == null ) { return false; } if ( potentialSuperior.getStatus() == DefeasibilityStatus.DEFINITELY && potentialInferior.getStatus() != DefeasibilityStatus.DEFINITELY ) { - potentialSuperior.addDefeated(potentialInferior); return true; } // adds the references that defeat the current node if (Arrays.binarySearch(potentialSuperior.getDefeats(), rule.getName()) >= 0 || Arrays.binarySearch(potentialSuperior.getDefeats(), rule.getPackage() + "." + rule.getName()) >= 0) { if ( "neg".equals( potentialSuperior.getValue() ) ^ "neg".equals( potentialInferior.getValue() ) ) { - potentialSuperior.addDefeated(potentialInferior); return true; } } From ef788ae66f06d069be27349ba356633e30753fdc Mon Sep 17 00:00:00 2001 From: sotty Date: Sat, 26 Jul 2014 01:56:58 +0200 Subject: [PATCH 61/76] [DROOLS-565] Retrieve the rule that caused a RuleRuntimeEvent (cherry picked from commit 785e278a874d8ff4d6f4dc592115f93342c9e405) (cherry picked from commit 2ed3e367aa3d40759326cf656a8442c0353100a9) --- .../drools/core/event/rule/impl/RuleRuntimeEventImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drools-core/src/main/java/org/drools/core/event/rule/impl/RuleRuntimeEventImpl.java b/drools-core/src/main/java/org/drools/core/event/rule/impl/RuleRuntimeEventImpl.java index 1cc17e76aee..b454b823417 100644 --- a/drools-core/src/main/java/org/drools/core/event/rule/impl/RuleRuntimeEventImpl.java +++ b/drools-core/src/main/java/org/drools/core/event/rule/impl/RuleRuntimeEventImpl.java @@ -16,6 +16,7 @@ package org.drools.core.event.rule.impl; +import org.kie.api.definition.rule.Rule; import org.kie.api.event.rule.RuleRuntimeEvent; import org.kie.internal.runtime.KnowledgeRuntime; import org.kie.api.runtime.rule.PropagationContext; @@ -46,6 +47,10 @@ public KnowledgeRuntime getKieRuntime() { public PropagationContext getPropagationContext() { return this.propagationContext; } + + public Rule getRule() { + return this.propagationContext != null ? this.getPropagationContext().getRule() : null; + } public void writeExternal(ObjectOutput out) throws IOException { new SerializablePropagationContext( propagationContext ).writeExternal( out ); From de4c9a506c8424eda5325231d9d4f90d419db751 Mon Sep 17 00:00:00 2001 From: Mark Proctor Date: Mon, 28 Jul 2014 18:25:38 +0100 Subject: [PATCH 62/76] DROOLS-567 Improve Examples -Change back to use BufferedImage. -Improve the synchronisation of paint(). -Make pong, wumpus and invaders all share more code. -Update TextAdventure for lock handling, attacking and general improvements. (cherry picked from commit 3dd405f9e3b4f5658c28e9f079c6e7fdeb98f2c3) --- .../main/java/org/drools/games/GameFrame.java | 39 +++++ .../main/java/org/drools/games/GamePanel.java | 61 +++++++ .../main/java/org/drools/games/GameUI.java | 127 ++++++++------ .../games/adventures/AdventureFrame.java | 70 +++++++- .../drools/games/adventures/GameEngine.java | 8 +- .../games/adventures/model/UseCommand.java | 72 ++++++++ .../invaders/{Invader1.java => Invader.java} | 2 +- .../java/org/drools/games/pong/PongUI.java | 3 +- .../drools/games/wumpus/WumpusWorldMain.java | 6 +- .../org/drools/games/wumpus/view/GameUI.java | 156 +++++------------- .../drools/games/wumpus/view/GameView.java | 9 - .../org/drools/games/adventures/Commands.drl | 57 ++++--- .../org/drools/games/adventures/data.mvel | 34 +--- .../org/drools/games/invaders5/Draw.drl | 4 +- .../org/drools/games/invaders5/Init.drl | 7 +- .../org/drools/games/invaders5/Move.drl | 2 +- .../org/drools/games/invaders6/Bullet.drl | 9 +- .../org/drools/games/invaders6/Draw.drl | 16 +- .../org/drools/games/invaders6/Init.drl | 7 +- .../org/drools/games/invaders6/Main.drl | 1 - .../org/drools/games/invaders6/Move.drl | 2 +- .../drools/games/wumpus/server/commands.drl | 1 - .../org/drools/games/wumpus/server/init.drl | 25 --- .../org/drools/games/wumpus/server/main.drl | 3 +- .../drools/games/wumpus/server/paintCave.drl | 8 +- .../games/wumpus/server/paintSensor.drl | 46 ++---- .../org/drools/games/wumpus/server/reset.drl | 1 - 27 files changed, 454 insertions(+), 322 deletions(-) create mode 100644 drools-examples/src/main/java/org/drools/games/GameFrame.java create mode 100644 drools-examples/src/main/java/org/drools/games/GamePanel.java create mode 100644 drools-examples/src/main/java/org/drools/games/adventures/model/UseCommand.java rename drools-examples/src/main/java/org/drools/games/invaders/{Invader1.java => Invader.java} (88%) diff --git a/drools-examples/src/main/java/org/drools/games/GameFrame.java b/drools-examples/src/main/java/org/drools/games/GameFrame.java new file mode 100644 index 00000000000..f2648b3277b --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/GameFrame.java @@ -0,0 +1,39 @@ +package org.drools.games; + +import javax.swing.*; +import java.awt.*; + +public class GameFrame extends JFrame { + private final Object redrawLock = new Object(); + + public GameFrame() throws HeadlessException { + } + + public GameFrame(String title) throws HeadlessException { + super(title); + } + + @Override + public void paint(Graphics g) { + // this will iterate the children, calling paintComponent + super.paint(g); + Toolkit.getDefaultToolkit().sync(); + resume(); // all the children are redrawn, so resume + } + + public void waitForPaint() { + try { + synchronized (redrawLock) { + repaint(); + redrawLock.wait(); + } + } catch (InterruptedException e) { + } + } + + private void resume() { + synchronized (redrawLock) { + redrawLock.notify(); + } + } +} diff --git a/drools-examples/src/main/java/org/drools/games/GamePanel.java b/drools-examples/src/main/java/org/drools/games/GamePanel.java new file mode 100644 index 00000000000..23d16998718 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/GamePanel.java @@ -0,0 +1,61 @@ +package org.drools.games; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; + +public class GamePanel extends JPanel { + private BufferedImage backbuffer; + private Graphics2D g2d; + private String name; + private Color color; + + public GamePanel(String name, Color color) { + this.name = name; + this.color = color; + } + + + public BufferedImage getBufferedImage() { + if (backbuffer == null) { + backbuffer = new BufferedImage(getWidth(), getHeight(), + BufferedImage.TYPE_INT_RGB); + Graphics2D g = getGraphics2D(); + g.setColor( color ); // background + g.fillRect( 0, 0, getWidth(), getHeight() ); + disposeGraphics2D(); + } + return backbuffer; + } + + public Graphics2D getGraphics2D() { + if ( g2d == null ) { + g2d = (Graphics2D) backbuffer.getGraphics(); + } + return g2d; + } + + public void disposeGraphics2D() { + if ( g2d != null ) { + g2d.dispose(); + g2d = null; + } + } + + private long time; + private int frameCount; + public synchronized void paintComponent(Graphics g) { + // track approx frames per second + long currentTime = System.currentTimeMillis(); + if ( currentTime-time >= 10000 || time == 0) { + System.out.println( "fps(" + name + ") :" + (frameCount/10) ); + frameCount = 0; + time = currentTime; + } + frameCount++; + + // paint the buffered image to the graphics + g.drawImage(backbuffer, 0, 0, this); + Toolkit.getDefaultToolkit().sync(); + } +} diff --git a/drools-examples/src/main/java/org/drools/games/GameUI.java b/drools-examples/src/main/java/org/drools/games/GameUI.java index 3280b3bb2f5..14d267846e8 100644 --- a/drools-examples/src/main/java/org/drools/games/GameUI.java +++ b/drools-examples/src/main/java/org/drools/games/GameUI.java @@ -12,8 +12,8 @@ public class GameUI { private GameConfiguration conf; - - private Canvas canvas; + private GameFrame frame; + private MyJPanel panel; KieSession ksession; @@ -22,69 +22,42 @@ public GameUI(KieSession ksession, GameConfiguration conf) { this.conf = conf; } - public Graphics getGraphics() { - return canvas.getBufferStrategy().getDrawGraphics(); - } - - public Canvas getCanvas() { - return canvas; - } - /** * Initialize the contents of the frame. */ public void init() { - canvas = new Canvas(); - canvas.setBackground(Color.BLACK); - canvas.setSize(new Dimension(conf.getWindowWidth(), conf.getWindowHeight())); - - KeyListener klistener = new GameKeyListener( ksession.getEntryPoint( "KeyPressedStream" ), ksession.getEntryPoint( "KeyReleasedStream" ) ); - canvas.addKeyListener(klistener); - - canvas.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - canvas.requestFocus(); - } - - @Override - public void mousePressed(MouseEvent e) { - - } - - @Override - public void mouseReleased(MouseEvent e) { - - } - - @Override - public void mouseEntered(MouseEvent e) { + frame = new GameFrame(); + frame.setDefaultCloseOperation(conf.isExitOnClose() ? JFrame.EXIT_ON_CLOSE : JFrame.DISPOSE_ON_CLOSE); + frame.setResizable( false ); + frame.setBackground(Color.BLACK); + frame.getContentPane().setBackground(Color.BLACK); + frame.setSize(new Dimension(conf.getWindowWidth(), conf.getWindowHeight())); - } + panel = new MyJPanel("", Color.BLACK); + frame.add( panel ); + panel.init(); + panel.getBufferedImage(); - @Override - public void mouseExited(MouseEvent e) { + frame.setLocationRelativeTo(null); // Center in screen + frame.pack(); + frame.setVisible( true ); + } - } - }); + public JPanel getCanvas() { + return panel; + } - JFrame frame = new JFrame(); - frame.setResizable(false); - frame.setDefaultCloseOperation(conf.isExitOnClose() ? JFrame.EXIT_ON_CLOSE : JFrame.DISPOSE_ON_CLOSE); - frame.setSize(new Dimension(conf.getWindowWidth(), conf.getWindowHeight())); - frame.setBackground(Color.BLACK); - frame.add(canvas); - frame.pack(); - frame.setVisible(true); - frame.setLocationRelativeTo(null); // Center in screen + public Graphics getGraphics() { + return panel.getGraphics2D(); + } - canvas.createBufferStrategy(2); - canvas.requestFocus(); + public void repaint() { + panel.disposeGraphics2D(); + frame.waitForPaint(); } public static class GameKeyListener implements KeyListener { - EntryPoint keyPressedEntryPoint; EntryPoint keyReleasedEntryPoint; @@ -106,8 +79,52 @@ public void keyReleased(KeyEvent e) { } } - public synchronized void show() { - canvas.getBufferStrategy().show(); - Toolkit.getDefaultToolkit().sync(); + public class MyJPanel extends GamePanel { + + public MyJPanel(String name, Color color) { + super(name, color); + } + + public void init() { + KeyListener klistener = new GameKeyListener( ksession.getEntryPoint( "KeyPressedStream" ), ksession.getEntryPoint( "KeyReleasedStream" ) ); + addKeyListener(klistener); + + addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent e) { + requestFocus(); + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + }); + + setPreferredSize(new Dimension(conf.getWindowWidth(), conf.getWindowHeight())); + setSize(new Dimension(conf.getWindowWidth(), conf.getWindowHeight())); + setBackground(Color.BLACK); + setDoubleBuffered(true); + + + setFocusable(true); + requestFocus(); + } + } } diff --git a/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java b/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java index 187914cf2bc..73dfeecdc36 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Vector; import javax.swing.BoxLayout; import javax.swing.DefaultComboBoxModel; @@ -64,6 +65,7 @@ import org.drools.games.adventures.model.Room; import org.drools.games.adventures.model.Thing; import org.drools.games.adventures.model.Character; +import org.drools.games.adventures.model.UseCommand; import org.kie.api.runtime.Channel; public class AdventureFrame extends JFrame { @@ -267,7 +269,7 @@ private Component createLocalEventsPanel() { private Component createInventoryPanel() { inventoryTable = new JTable(); inventoryTable.setBorder( null ); - inventoryTable.setModel( new DefaultTableModel( + inventoryTable.setModel( new NonEditableTableMode( new Object[][]{ }, new String[]{ @@ -365,7 +367,7 @@ public void actionPerformed(ActionEvent e) { characterPropertiesTable.setPreferredScrollableViewportSize( new Dimension( 240, 200 ) ); characterPropertiesTable.setBorder( null ); - characterPropertiesTable.setModel( new DefaultTableModel( + characterPropertiesTable.setModel( new NonEditableTableMode( new Object[][]{ {"strength", "100"}, {"health", "100"}, @@ -435,13 +437,25 @@ public void actionPerformed(ActionEvent e) { actionsPanel.add( giveBtn ); giveBtn.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { - cmdTextField.setText( "Request Give " ); + cmdTextField.setText( "Give " ); cmd = new ArrayList(); cmd.add(GiveCommand.class); cmd.add( characterSelectCombo.getSelectedObjects()[0] ); } } ); + JButton useBtn = new JButton( "Use" ); + useBtn.setToolTipText("Select one from the Inventory, then Select the target Thing or Room"); + actionsPanel.add( useBtn ); + useBtn.addActionListener( new ActionListener() { + public void actionPerformed(ActionEvent e) { + cmdTextField.setText( "Use " ); + cmd = new ArrayList(); + cmd.add(UseCommand.class); + cmd.add( characterSelectCombo.getSelectedObjects()[0] ); + } + } ); + JButton lookBtn = new JButton( "Look" ); giveBtn.setToolTipText("Just press Send"); actionsPanel.add( lookBtn ); @@ -461,7 +475,7 @@ public void actionPerformed(ActionEvent e) { thingsTable.setPreferredScrollableViewportSize( new Dimension( 245, 250 ) ); thingsTable.setBorder( null ); - thingsTable.setModel( new DefaultTableModel( + thingsTable.setModel( new NonEditableTableMode( new Object[][]{ }, new String[]{ @@ -503,7 +517,7 @@ public void mouseClicked(MouseEvent e) { exitsTable.setPreferredScrollableViewportSize( new Dimension( 245, 250 ) ); exitsTable.setBorder( null ); - exitsTable.setModel( new DefaultTableModel( + exitsTable.setModel( new NonEditableTableMode( new Object[][]{ }, new String[]{ @@ -928,9 +942,16 @@ public static class JTableChannel public JTableChannel(JTable jTable) { this.jTable = jTable; String name = jTable.getColumnName(0); + jTable.getColumn( name ).setCellRenderer(new DefaultTableCellRenderer() { public void setValue(Object value) { - setText(((Thing) value).getName()); + if ( value == null ) { + return; + } else if ( value instanceof Thing ) { + setText(((Thing) value).getName()); + } else { + setText( value.toString() ); + } } }); @@ -953,11 +974,17 @@ public void addRows(List list) { 0 ); } for ( int i = model.getRowCount(), length = exits.length; i < length; i++ ) { + if ( list.get( i ) == null ) { + continue; + } model.addRow( new Object[]{list.get( i )} ); } } else { Object[][] exits = new Object[list.size()][]; for ( int i = 0; i < exits.length; i++ ) { + if ( list.get( i ) == null ) { + continue; + } model.setValueAt( list.get( i ), i, 0 ); @@ -970,4 +997,35 @@ public void addRows(List list) { } } + public static class NonEditableTableMode extends DefaultTableModel { + public NonEditableTableMode() { + } + + public NonEditableTableMode(int rowCount, int columnCount) { + super(rowCount, columnCount); + } + + public NonEditableTableMode(Vector columnNames, int rowCount) { + super(columnNames, rowCount); + } + + public NonEditableTableMode(Object[] columnNames, int rowCount) { + super(columnNames, rowCount); + } + + public NonEditableTableMode(Vector data, Vector columnNames) { + super(data, columnNames); + } + + public NonEditableTableMode(Object[][] data, Object[] columnNames) { + super(data, columnNames); + } + + @Override + public boolean isCellEditable(int row, int column) { + //all cells false + return false; + } + } + } diff --git a/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java b/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java index b18f14f8d54..74c0248b6dd 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/GameEngine.java @@ -23,7 +23,7 @@ public class GameEngine { public void createGame() { KieContainer kc = KieServices.Factory.get().getKieClasspathContainer(); - System.out.println(kc.verify().getMessages().toString()); + //System.out.println(kc.verify().getMessages().toString()); ksession = kc.newKieSession("TextAdventureKS"); Counter c = new Counter(); @@ -55,9 +55,9 @@ public void createGame() { ksession.insert( o ); } - for ( Object o : data.get( "keys" ).values() ) { - ksession.insert( o ); - } +// for ( Object o : data.get( "keys" ).values() ) { +// ksession.insert( o ); +// } // // for ( Object o : data.get( "locks" ).values() ) { // ksession.insert( o ); diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/UseCommand.java b/drools-examples/src/main/java/org/drools/games/adventures/model/UseCommand.java new file mode 100644 index 00000000000..9d7a1f1b5e5 --- /dev/null +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/UseCommand.java @@ -0,0 +1,72 @@ +package org.drools.games.adventures.model; + +import org.kie.api.definition.type.PropertyReactive; + +@PropertyReactive +public class UseCommand extends Command { + private Character character; + private Thing thing; + private Thing target; + + public UseCommand(Character character, Thing thing, Thing target) { + this.character = character; + this.thing = thing; + this.target = target; + } + + + public Character getCharacter() { + return character; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Thing getThing() { + return thing; + } + + public void setThing(Thing thing) { + this.thing = thing; + } + + public Thing getTarget() { + return target; + } + + public void setTarget(Thing target) { + this.target = target; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + UseCommand that = (UseCommand) o; + + if (!character.equals(that.character)) { return false; } + if (!target.equals(that.target)) { return false; } + if (!thing.equals(that.thing)) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = character.hashCode(); + result = 31 * result + thing.hashCode(); + result = 31 * result + target.hashCode(); + return result; + } + + @Override + public String toString() { + return "UseCommand{" + + "character=" + character + + ", thing=" + thing + + ", target=" + target + + '}'; + } +} diff --git a/drools-examples/src/main/java/org/drools/games/invaders/Invader1.java b/drools-examples/src/main/java/org/drools/games/invaders/Invader.java similarity index 88% rename from drools-examples/src/main/java/org/drools/games/invaders/Invader1.java rename to drools-examples/src/main/java/org/drools/games/invaders/Invader.java index 378b62fab05..5ca87a5c0a0 100644 --- a/drools-examples/src/main/java/org/drools/games/invaders/Invader1.java +++ b/drools-examples/src/main/java/org/drools/games/invaders/Invader.java @@ -3,7 +3,7 @@ import org.kie.api.definition.type.PropertyReactive; @PropertyReactive -public class Invader1 extends Unit { +public class Invader extends Unit { private boolean alive = true; public boolean isAlive() { diff --git a/drools-examples/src/main/java/org/drools/games/pong/PongUI.java b/drools-examples/src/main/java/org/drools/games/pong/PongUI.java index ad526ce4c4f..cb20849ba1f 100644 --- a/drools-examples/src/main/java/org/drools/games/pong/PongUI.java +++ b/drools-examples/src/main/java/org/drools/games/pong/PongUI.java @@ -38,8 +38,7 @@ public void drawGame(Ball ball, Bat bat1, Bat bat2, Player p1, Player p2) { drawBall(ball); drawBat(bat1); drawBat(bat2); - - show(); + repaint(); } public void clearBall(Ball ball) { diff --git a/drools-examples/src/main/java/org/drools/games/wumpus/WumpusWorldMain.java b/drools-examples/src/main/java/org/drools/games/wumpus/WumpusWorldMain.java index 3e4d87e5b6a..1510f34b27b 100644 --- a/drools-examples/src/main/java/org/drools/games/wumpus/WumpusWorldMain.java +++ b/drools-examples/src/main/java/org/drools/games/wumpus/WumpusWorldMain.java @@ -1,5 +1,6 @@ package org.drools.games.wumpus; +import org.drools.games.wumpus.view.GameUI; import org.drools.games.wumpus.view.GameView; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; @@ -25,7 +26,6 @@ public WumpusWorldMain() { public void init(boolean exitOnClose) { KieContainer kc = KieServices.Factory.get().getKieClasspathContainer(); - System.out.println(kc.verify().getMessages().toString()); final KieSession serverKsession = kc.newKieSession( "WumpusMainKS"); final KieSession clientKsession = kc.newKieSession("WumpusClientKS"); @@ -48,6 +48,10 @@ public void send(Object object) { serverKsession.setGlobal("wumpusWorldConfiguration", wumpusWorldConfiguration); serverKsession.setGlobal("randomInteger",new java.util.Random() ); + GameUI gameUI = new GameUI(serverKsession, wumpusWorldConfiguration); + serverKsession.insert(gameUI ); + serverKsession.insert(gameUI.getGameView() ); + new Thread(new Runnable() { public void run() { diff --git a/drools-examples/src/main/java/org/drools/games/wumpus/view/GameUI.java b/drools-examples/src/main/java/org/drools/games/wumpus/view/GameUI.java index 30b291edca4..d43738b2be2 100644 --- a/drools-examples/src/main/java/org/drools/games/wumpus/view/GameUI.java +++ b/drools-examples/src/main/java/org/drools/games/wumpus/view/GameUI.java @@ -1,9 +1,6 @@ package org.drools.games.wumpus.view; -import java.awt.Color; -import java.awt.FlowLayout; -import java.awt.Graphics; -import java.awt.GridLayout; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; @@ -18,6 +15,8 @@ import net.miginfocom.swing.MigLayout; +import org.drools.games.GameFrame; +import org.drools.games.GamePanel; import org.drools.games.wumpus.ClimbCommand; import org.drools.games.wumpus.GrabCommand; import org.drools.games.wumpus.Move; @@ -27,44 +26,37 @@ import org.drools.games.wumpus.ShootCommand; import org.drools.games.wumpus.WumpusWorldConfiguration; import org.kie.api.runtime.Channel; +import org.kie.api.runtime.KieSession; import org.kie.api.runtime.rule.FactHandle; +import org.kie.internal.runtime.StatefulKnowledgeSession; public class GameUI { private final WumpusWorldConfiguration wumpusWorldConfiguration; - private JFrame frame; + private GameFrame frame; - private GameView gameView; + private GameView gameView; - private CavePanel cavePanel; + private GamePanel cavePanel; - private SensorPanel sensorPanel; - - public GameUI(WumpusWorldConfiguration wumpusWorldConfiguration) { - this.wumpusWorldConfiguration = wumpusWorldConfiguration; - } + private GamePanel sensorPanel; /** * @wbp.parser.entryPoint */ - public GameUI(WumpusWorldConfiguration wumpusWorldConfiguration, GameView gameView) { - this(wumpusWorldConfiguration); - this.gameView = gameView; - if (this.gameView == null ) { - this.gameView = new GameView(); - this.gameView.init( 50, 50, 3, 20, 5, 5 ); - } + public GameUI(KieSession ksession, WumpusWorldConfiguration wumpusWorldConfiguration) { + this.wumpusWorldConfiguration = wumpusWorldConfiguration; + this.gameView = new GameView(); + this.gameView.setKsession((StatefulKnowledgeSession) ksession); + this.gameView.init(50, 50, 3, 20, 5, 5); initialize(); } public void setGameView(GameView gameView) { this.gameView = gameView; - if ( frame == null ) { - initialize(); - } } - + public JFrame getParentJFrame() { return frame; } @@ -73,11 +65,11 @@ public GameView getGameView() { return gameView; } - public CavePanel getCavePanel() { + public GamePanel getCavePanel() { return cavePanel; } - public SensorPanel getSensorPanel() { + public GamePanel getSensorPanel() { return sensorPanel; } @@ -85,12 +77,12 @@ public SensorPanel getSensorPanel() { * Initialize the contents of the frame. */ private void initialize() { - frame = new JFrame( "Wumpus World" ); + frame = new GameFrame( "Wumpus World" ); frame.getContentPane().setBackground( Color.WHITE ); frame.setDefaultCloseOperation(wumpusWorldConfiguration.isExitOnClose() ? JFrame.EXIT_ON_CLOSE : JFrame.DISPOSE_ON_CLOSE); - + frame.setLayout(new MigLayout("", "[540px:n][grow,fill]", "[30px,top][300px,top][100px,top][grow]")); frame.setSize( 926, 603 ); - frame.getContentPane().setLayout( new MigLayout("", "[540px:n][grow,fill]", "[30px,top][300px,top][100px,top][grow]") ); + frame.setLocationRelativeTo(null); // Center in screen JPanel scorePanel = new JPanel(); FlowLayout flowLayout = (FlowLayout) scorePanel.getLayout(); @@ -117,7 +109,7 @@ public void send(Object object) { JPanel actionPanel = new JPanel(); actionPanel.setBackground( Color.WHITE ); - frame.getContentPane().add( actionPanel, "cell 0 1,grow" ); + frame.getContentPane().add(actionPanel, "cell 0 1,grow"); actionPanel.setLayout( new MigLayout("", "[200px,left][320px:n]", "[grow]") ); JPanel controls = new JPanel(); @@ -130,43 +122,43 @@ public void send(Object object) { actionPanel.add( controls, "cell 0 0,grow" ); cavePanel = drawCave(); - actionPanel.add( cavePanel, "cell 1 0,grow" ); + actionPanel.add(cavePanel, "cell 1 0,grow" ); sensorPanel = drawSensorPanel(); - - frame.getContentPane().add( sensorPanel, "cell 0 2,grow" ); + + frame.getContentPane().add(sensorPanel, "cell 0 2,grow"); JPanel blank = new JPanel(); blank.setBackground(Color.WHITE); - frame.getContentPane().add(blank, "cell 0 3,grow"); + frame.add(blank, "cell 0 3,grow"); - frame.setLocationRelativeTo(null); // Center in screen frame.setVisible( true ); - - updateCave(); - updateSensors(); - } - public synchronized void updateCave() { - cavePanel.repaint(); - cavePanel.revalidate(); + cavePanel.getBufferedImage(); + sensorPanel.getBufferedImage(); + + repaint(); + } - public synchronized void updateSensors() { - sensorPanel.repaint(); - sensorPanel.revalidate(); + public void repaint() { + cavePanel.disposeGraphics2D(); + sensorPanel.disposeGraphics2D(); + //frame.repaint(); + frame.waitForPaint(); } - public SensorPanel drawSensorPanel() { - SensorPanel sensorPanel = new SensorPanel( this ); + + public GamePanel drawSensorPanel() { + GamePanel sensorPanel = new GamePanel("sensor", Color.WHITE ); //new SensorPanel( this ); FlowLayout flowLayout = (FlowLayout) sensorPanel.getLayout(); flowLayout.setVgap( 10 ); sensorPanel.setBackground( Color.WHITE ); return sensorPanel; } - public CavePanel drawCave() { - CavePanel cavelPanel = new CavePanel( this ); + public GamePanel drawCave() { + GamePanel cavelPanel = new GamePanel("cave", Color.WHITE ); FlowLayout flowLayout = (FlowLayout) cavelPanel.getLayout(); flowLayout.setVgap( 10 ); cavelPanel.setBackground( Color.WHITE ); @@ -337,72 +329,4 @@ public void mousePressed(MouseEvent e) { } } - public static class SensorPanel extends JPanel { - private GameUI gameUI; - - private BufferedImage bi; - private Graphics sensorG; - - public SensorPanel(GameUI gameUI) { - setOpaque( true ); - this.gameUI = gameUI; - } - - public Graphics getSensorG() { - return sensorG; - } - - @Override - protected void paintComponent(Graphics g) { - if ( bi == null ) { // prepare BufferdImage - bi = new BufferedImage( getWidth(), getHeight(), - BufferedImage.TYPE_INT_RGB ); - sensorG = bi.createGraphics(); - sensorG.setColor( Color.WHITE ); // background - sensorG.fillRect( 0, 0, getWidth(), getHeight() ); - if ( gameUI != null ) { - // we need this to trigger the ksession drawing, otherwise the engine doesn't know it's ready - gameUI.getGameView().getKsession().update( gameUI.getGameView().getKsession().getFactHandle( gameUI ), gameUI ); - gameUI.getGameView().getKsession().fireAllRules(); - } - } - - g.drawImage( bi, 0, 0, null ); - } - } - - public static class CavePanel extends JPanel { - private GameUI gameUI; - - private BufferedImage bi; - private Graphics caveG; - - public CavePanel(GameUI gameUI) { - setOpaque( true ); - this.gameUI = gameUI; - } - - public Graphics getCaveG() { - return caveG; - } - - @Override - protected void paintComponent(Graphics g) { - if ( bi == null ) { // prepare BufferdImage - bi = new BufferedImage( getWidth(), getHeight(), - BufferedImage.TYPE_INT_RGB ); - caveG = bi.createGraphics(); - caveG.setColor( Color.WHITE ); // background - caveG.fillRect( 0, 0, getWidth(), getHeight() ); - if ( gameUI != null ) { - // we need this to trigger the ksession drawing, otherwise the engine doesn't know it's ready - gameUI.getGameView().getKsession().update( gameUI.getGameView().getKsession().getFactHandle( gameUI ), gameUI ); - gameUI.getGameView().getKsession().fireAllRules(); - } - } - - g.drawImage( bi, 0, 0, null ); - } - } - } diff --git a/drools-examples/src/main/java/org/drools/games/wumpus/view/GameView.java b/drools-examples/src/main/java/org/drools/games/wumpus/view/GameView.java index b897367db96..922a1eff7a3 100644 --- a/drools-examples/src/main/java/org/drools/games/wumpus/view/GameView.java +++ b/drools-examples/src/main/java/org/drools/games/wumpus/view/GameView.java @@ -18,7 +18,6 @@ public class GameView { KnowledgeRuntimeLogger klogger; private StatefulKnowledgeSession ksession; - private KnowledgeBase kbase; private boolean showAllCells; private int pittPercentage; @@ -29,14 +28,6 @@ public GameView() { } - public KnowledgeBase getKbase() { - return kbase; - } - - public void setKbase(KnowledgeBase kbase) { - this.kbase = kbase; - } - public void init(Cell[][] cells) { } diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl index c1052fd0111..2fd9b948f64 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl @@ -1,20 +1,5 @@ package org.drools.games.adventures -//import org.drools.games.adventures.Room; -//import org.drools.games.adventures.Thing; -// -//import org.drools.games.adventures.Request; -//import org.drools.games.adventures.Response; -//import org.drools.games.adventures.SessionCharacter -// -//import org.drools.games.adventures.MoveCommand -//import org.drools.games.adventures.Command -//import org.drools.games.adventures.PickupCommand -//import org.drools.games.adventures.DropCommand -//import org.drools.games.adventures.LookCommand -//import org.drools.games.adventures.SetSessionCharacterCommand -//import org.drools.games.adventures.model.EnterEvent -//import org.drools.games.adventures.model.ExitEvent import org.drools.games.adventures.model.*; import java.util.List; @@ -74,15 +59,14 @@ end rule roomLocked extends validMove agenda-group "commands" salience 10 when Door( lockStatus == LockStatus.LOCKED ) from d then - mc.session.channels["output"].send( "The room " + l.target.name + " is locked\n" ); + mc.session.channels["output"].send( "The " + r.name + " Door is locked\n" ); delete( mc ); end rule validPickup agenda-group "commands" when pc : PickupCommand( c : character, t : thing) - - cl : Location( thing == c ) - tl : Location( thing == t, target == cl.target ) @watch( !target ) + cl : Location( thing == pc.character ) + tl : Location( thing == pc.thing, target == cl.target ) @watch( !target ) then insert( new Holding( c, t ) ); modify( tl ) { target = c }; @@ -91,6 +75,41 @@ then pc.session.channels["output"].send( "You have picked up the " + t.name + "\n" ); end +rule unlockingDoors agenda-group "commands" when + uc : UseCommand( c : character, t : thing) + k : Key() from uc.thing + r : Room() from uc.target + cl : Location( thing == c, ltarget : target ) + ?connect( door, ltarget, r; ) + if( door.key != k) break[wrongKey] + if( door.lockStatus == LockStatus.UNLOCKED) break[alreadyUnlocked] +then + modify(door){ lockStatus = LockStatus.UNLOCKED }; + uc.session.channels["output"].send( "You have unlocked the " + r.name + " door\n" ); + retract ( uc ); +then[wrongKey] + uc.session.channels["output"].send( "The selected key cannot open the " + r.name + " door\n" ); + retract ( uc ); +then[alreadyUnlocked] + uc.session.channels["output"].send( "The " + r.name + " door is already unlocked\n" ); + retract ( uc ); +end + +rule killMonster agenda-group "commands" when + uc : UseCommand( c : character, thing.name == "umbrella", uc.target.name == "monster") +then + uc.session.channels["output"].send( "You have killed the Monster\n" ); + retract ( uc ); +end + +rule invalidUse agenda-group "commands" when + uc : UseCommand( c : character) +then + uc.session.channels["output"].send( "The " + uc.thing.name + " cannot be used with the " + uc.target.name + "\n" ); + retract ( uc ); +end + + rule validDrop agenda-group "commands" when dc : DropCommand( c : character, t : thing) diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel index 38cd15b91b6..724da106681 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel +++ b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel @@ -11,12 +11,9 @@ import java.util.HashMap; rooms = [ "basement" : new Room("basement"), "lounge" : new Room("lounge"), - "dining room" : new Room("dining room"), "kitchen" : new Room("kitchen"), "ground floor hallway" : new Room("ground floor hallway"), - "bedroom1" : new Room("bedroom1"), - "bedroom2" : new Room("bedroom2"), - "bathroom" : new Room("bathroom"), + "bedroom1" : new Room("bedroom"), "office" : new Room("office"), "first floor hallway" : new Room("first floor hallway") ]; @@ -27,50 +24,35 @@ foreach( room : rooms.values ) { doors = [ "d1" : new Door( rooms["kitchen"], rooms["basement"] ), - "d2" : new Door( rooms["ground floor hallway"], rooms["lounge"]), - "d3" : new Door( rooms["ground floor hallway"], rooms["dining room"] ), "d4" : new Door( rooms["ground floor hallway"], rooms["kitchen"]), "d5" : new Door( rooms["ground floor hallway"], rooms[ "first floor hallway"] ), - - "d6" : new Door( rooms["first floor hallway"], rooms[ "bedroom1"] ), - "d7" : new Door( rooms["first floor hallway"], rooms[ "bedroom2"] ), "d8" : new Door( rooms["first floor hallway"], rooms[ "bathroom"] ), "d9" : new Door( rooms["first floor hallway"], rooms[ "office"] ) ]; -keys = [ "key1" : new Key("basement key") ]; -for( key : keys.values ) { - key.id = c.getAndIncrement(); -} - -with(doors["d1"]){ lockStatus = LockStatus.LOCKED, key = keys["key1"] }; - characters = [ "hero" : new Character( "hero" ), "monster" : new Character( "monster" ) ]; for( character : characters.values ) { character.id = c.getAndIncrement(); } items = [ - "mace" : new Item( "mace" ), - "cucumber" : new Item( "cucumber" ), - "torch" : new Item( "torch" ), - "umbrella" : new Item( "umbrella" ) + "umbrella" : new Item( "umbrella" ), + "key1" : new Key("basement key") ]; for( item : items.values ) { item.id = c.getAndIncrement(); - item.fixed = false; } +with(doors["d1"]){ lockStatus = LockStatus.LOCKED, key = items["key1"] }; + locations = [ - "mace" : new Location( items["mace"], rooms["basement"] ), "monster" : new Location( characters["monster"], rooms["basement"] ), - "cucumber" : new Location( items["cucumber"], rooms["kitchen"] ), - "torch" : new Location( items["torch"], rooms["office"] ), "hero" : new Location( characters["hero"], rooms["ground floor hallway"] ), - "umbrella" : new Location( items["umbrella"], rooms["ground floor hallway"] ) + "umbrella" : new Location( items["umbrella"], rooms["bedroom"] ), + "key1" : new Location( items["key1"], rooms["office"] ) ]; return [ "rooms" : rooms, "doors" : doors, "characters" : characters, - "items" : items, "locations" : locations, "keys" : keys ]; \ No newline at end of file + "items" : items, "locations" : locations ]; diff --git a/drools-examples/src/main/resources/org/drools/games/invaders5/Draw.drl b/drools-examples/src/main/resources/org/drools/games/invaders5/Draw.drl index 2358e9e4a09..cb9935aefd3 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders5/Draw.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders5/Draw.drl @@ -3,7 +3,7 @@ package org.drools.games.invaders5; import org.drools.games.KeyPressed import org.drools.games.Run import org.drools.games.invaders.Ship -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader import org.drools.games.GameUI import org.drools.games.invaders.InvadersConfiguration @@ -28,7 +28,7 @@ then end rule DrawInvader agenda-group "Draw" when - i : Invader1() + i : Invader() Run() then g = ui.getGraphics(); diff --git a/drools-examples/src/main/resources/org/drools/games/invaders5/Init.drl b/drools-examples/src/main/resources/org/drools/games/invaders5/Init.drl index ab84fc2d245..4b11af06343 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders5/Init.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders5/Init.drl @@ -3,10 +3,11 @@ package org.drools.games.invaders5; import org.drools.games.Run import org.drools.games.invaders.Ship -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader import org.drools.games.invaders.InvadersConfiguration -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader +import org.drools.games.invaders.Invader global InvadersConfiguration conf @@ -28,7 +29,7 @@ rule InitInvader agenda-group "Init" when i : Integer() from [1, 2, 3, 4, 5, 6] Run() then - invader = new Invader1(); + invader = new Invader(); invader.width = conf.invader1Width; invader.height = conf.invader1Height; invader.speed = conf.invader1Speed; diff --git a/drools-examples/src/main/resources/org/drools/games/invaders5/Move.drl b/drools-examples/src/main/resources/org/drools/games/invaders5/Move.drl index 421c5531831..6e0140c6130 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders5/Move.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders5/Move.drl @@ -5,7 +5,7 @@ import org.drools.games.Run import org.drools.games.invaders.Ship import org.drools.games.invaders.Unit -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader import org.drools.games.GameUI import org.drools.games.invaders.InvadersConfiguration diff --git a/drools-examples/src/main/resources/org/drools/games/invaders6/Bullet.drl b/drools-examples/src/main/resources/org/drools/games/invaders6/Bullet.drl index 8d9704f2176..31cf0884bcc 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders6/Bullet.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders6/Bullet.drl @@ -6,7 +6,7 @@ import org.drools.games.Run import org.drools.games.invaders.Ship import org.drools.games.invaders.Unit import org.drools.games.invaders.Bullet -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader import org.drools.games.GameUI import org.drools.games.invaders.InvadersConfiguration @@ -31,20 +31,17 @@ end rule BulletMove agenda-group "Bullet" when - b : Bullet( ) + b : Bullet( y > 0 ) @watch( !y ) Run() then - //System.out.println( b + ":" + b.y + ":" + b.speed); modify( b ) { y = b.y + b.dy } end rule Collision agenda-group "Bullet" when b : Bullet( ) @watch( y ) - i : Invader1( x < b.x, x + width > b.x, y > b.y) + i : Invader( x < b.x, x + width > b.x, y > b.y) Run() then - - //System.out.println( "collision" + i.y + ":" + b.y ); modify( i ) { alive = false } end diff --git a/drools-examples/src/main/resources/org/drools/games/invaders6/Draw.drl b/drools-examples/src/main/resources/org/drools/games/invaders6/Draw.drl index 31b494e0e82..9508ae4ed45 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders6/Draw.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders6/Draw.drl @@ -4,7 +4,7 @@ import org.drools.games.KeyPressed import org.drools.games.Run import org.drools.games.invaders.Ship import org.drools.games.invaders.Bullet -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader import org.drools.games.GameUI import org.drools.games.invaders.InvadersConfiguration @@ -29,7 +29,7 @@ then end rule DrawLiveInvader agenda-group "Draw" when - i : Invader1( alive == true) + i : Invader( alive == true) Run() then g = ui.getGraphics(); @@ -39,7 +39,7 @@ then end rule DrawDeadInvader agenda-group "Draw" when - i : Invader1( alive == false) + i : Invader( alive == false) Run() then g = ui.getGraphics(); @@ -59,12 +59,18 @@ then g.fillRect( b.x , b.y, b.width, b.height ); end -rule DrawBulletOffscreen agenda-group "Bullet" when +rule DrawBulletOffscreen agenda-group "Draw" when b : Bullet( y <= 0 ) Run() then g = ui.getGraphics(); g.setColor( Color.BLACK ); // background - g.fillRect( b.x - b.dx , b.y - b.dy , b.width, b.height ); // restore the previous blackground + g.fillRect( b.x , b.y, b.width, b.height ); // restore the background retract( b ) end + +rule Repaint agenda-group "Draw" salience -100 when + Run() +then + ui.repaint(); +end diff --git a/drools-examples/src/main/resources/org/drools/games/invaders6/Init.drl b/drools-examples/src/main/resources/org/drools/games/invaders6/Init.drl index a150f9aa217..91da4c8227c 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders6/Init.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders6/Init.drl @@ -3,10 +3,11 @@ package org.drools.games.invaders6; import org.drools.games.Run import org.drools.games.invaders.Ship -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader import org.drools.games.invaders.InvadersConfiguration -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader +import org.drools.games.invaders.Invader global InvadersConfiguration conf @@ -28,7 +29,7 @@ rule InitInvader agenda-group "Init" when i : Integer() from [1, 2, 3, 4, 5, 6] Run() then - invader = new Invader1(); + invader = new Invader(); invader.width = conf.invader1Width; invader.height = conf.invader1Height; invader.speed = conf.invader1Speed; diff --git a/drools-examples/src/main/resources/org/drools/games/invaders6/Main.drl b/drools-examples/src/main/resources/org/drools/games/invaders6/Main.drl index 201248cdf32..883b9897176 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders6/Main.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders6/Main.drl @@ -27,6 +27,5 @@ end rule Draw when r : Run() then - ui.show(); modify( r ) {} // force loop end \ No newline at end of file diff --git a/drools-examples/src/main/resources/org/drools/games/invaders6/Move.drl b/drools-examples/src/main/resources/org/drools/games/invaders6/Move.drl index 8c105706a6c..f11006dad04 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders6/Move.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders6/Move.drl @@ -5,7 +5,7 @@ import org.drools.games.Run import org.drools.games.invaders.Ship import org.drools.games.invaders.Unit -import org.drools.games.invaders.Invader1 +import org.drools.games.invaders.Invader import org.drools.games.GameUI import org.drools.games.invaders.InvadersConfiguration diff --git a/drools-examples/src/main/resources/org/drools/games/wumpus/server/commands.drl b/drools-examples/src/main/resources/org/drools/games/wumpus/server/commands.drl index 4f4f4892ab8..7d489f9afe1 100644 --- a/drools-examples/src/main/resources/org/drools/games/wumpus/server/commands.drl +++ b/drools-examples/src/main/resources/org/drools/games/wumpus/server/commands.drl @@ -44,7 +44,6 @@ then retract ( $sc ); modify( $h ) { arrows = 0 }; insert( new Arrow($h.row, $h.col, $h.direction) ); - System.out.println( kcontext.rule ); setFocus( "Shoot" ); end diff --git a/drools-examples/src/main/resources/org/drools/games/wumpus/server/init.drl b/drools-examples/src/main/resources/org/drools/games/wumpus/server/init.drl index cfb4c56113a..fccd71d8638 100644 --- a/drools-examples/src/main/resources/org/drools/games/wumpus/server/init.drl +++ b/drools-examples/src/main/resources/org/drools/games/wumpus/server/init.drl @@ -41,31 +41,6 @@ rule "Insert Score" agenda-group "Init" when then insert( new Score() ); end - -rule "Create GUI" agenda-group "Init" when - not GameUI() -then - insert( new GameUI(wumpusWorldConfiguration) ); -end - -rule "Init Game View" agenda-group "Init" when - Play() - $ui : GameUI() - not GameView() -then - GameView $gv = new GameView(); - $gv.init(50, 50, 3, 20, 5, 5); - $gv.setKsession( (StatefulKnowledgeSession) kcontext.knowledgeRuntime ); - $gv.setKbase( ((StatefulKnowledgeSession) kcontext.knowledgeRuntime).getKieBase() ); - -// new java.io.File("log").mkdir(); -// KnowledgeRuntimeLogger klogger = KnowledgeRuntimeLoggerFactory.newThreadedFileLogger((StatefulKnowledgeSession) kcontext.knowledgeRuntime, "log/wumpus", 500); -// $gv.setKlogger( klogger ); - - $ui.gameView = $gv; - insert( $gv ); -end - rule "Create Cells" agenda-group "Init" when Init() diff --git a/drools-examples/src/main/resources/org/drools/games/wumpus/server/main.drl b/drools-examples/src/main/resources/org/drools/games/wumpus/server/main.drl index 4efc067aa1e..01d13e0450d 100644 --- a/drools-examples/src/main/resources/org/drools/games/wumpus/server/main.drl +++ b/drools-examples/src/main/resources/org/drools/games/wumpus/server/main.drl @@ -27,7 +27,6 @@ rule "Redraw Cave" when $gui : GameUI() $r : Run() then - $gui.updateCave(); - $gui.updateSensors(); + $gui.repaint(); modify( $r ) {} end \ No newline at end of file diff --git a/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintCave.drl b/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintCave.drl index cd2d9d78eec..49ec5bb750c 100644 --- a/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintCave.drl +++ b/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintCave.drl @@ -26,7 +26,7 @@ function void paintCaveCell(String image, Cell cell, GameView gv, GameUI gui) { int y = (4 - cell.getRow()) * 50 - rowPad + rowIndent; int x = cell.getCol() * 50 + colPad + colIndent; - Graphics caveG = gui.getCavePanel().getCaveG(); + Graphics caveG = gui.getCavePanel().getGraphics2D(); caveG.setColor( Color.WHITE ); // background caveG.fillRect( x, y, gv.getCellWidth(), gv.getCellHeight() ); caveG.drawImage( ImageIO.read( GameView.class.getResource( image ) ), x, y, gv.getCellHeight(), gv.getCellWidth(), gui.getCavePanel() ); @@ -126,7 +126,7 @@ then end rule "Paint Hidden Room" agenda-group "PaintCave" when - $gui : GameUI( cavePanel != null && cavePanel.caveG != null ) + $gui : GameUI( ) $gv : GameView(showAllCells == false) $c : Cell(hidden == true) then @@ -135,7 +135,7 @@ end rule "Paint Empty Room" agenda-group "PaintCave" when - $gui : GameUI( cavePanel != null && cavePanel.caveG != null ) + $gui : GameUI( ) ($gv : GameView(showAllCells == true) and $c : Cell() ) or ($gv : GameView(showAllCells == false) and $c : Cell(hidden == false) ) CompositeImageName( cell == $c, pit == "", wumpus == "", gold == "", hero == "" ) @@ -144,7 +144,7 @@ then end rule "Paint Non Empty Room" agenda-group "PaintCave" when - $gui : GameUI( cavePanel != null && cavePanel.caveG != null ) + $gui : GameUI() ($gv : GameView(showAllCells == true) and $c : Cell() ) or ($gv : GameView(showAllCells == false) and $c : Cell(hidden == false) ) $cin : CompositeImageName( cell == $c, ( !(hero != "" && pit != "") && // don't draw a hero on the same square as a pit or an alive wumpus, as the game is over diff --git a/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintSensor.drl b/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintSensor.drl index d262cea5a34..ce63229119e 100644 --- a/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintSensor.drl +++ b/drools-examples/src/main/resources/org/drools/games/wumpus/server/paintSensor.drl @@ -23,15 +23,15 @@ import java.awt.Graphics import javax.swing.JPanel; -function void paintSensorCell(String image, int x, int y, GameUI gui, Graphics sensorG) { - sensorG.setColor( Color.WHITE ); // background - sensorG.fillRect( x, y, 100, 100); - sensorG.drawImage( ImageIO.read( GameView.class.getResource( image ) ), x, y,100,100, gui.getSensorPanel() ); +function void paintSensorCell(String image, int x, int y, GameUI gui, Graphics graphics2D) { + graphics2D.setColor( Color.WHITE ); // background + graphics2D.fillRect( x, y, 100, 100); + graphics2D.drawImage( ImageIO.read( GameView.class.getResource( image ) ), x, y,100,100, gui.getSensorPanel() ); } -function void clearSensorCell(int x, int y, Graphics sensorG) { - sensorG.setColor( Color.WHITE ); // background - sensorG.fillRect( x, y, 100, 100); +function void clearSensorCell(int x, int y, Graphics graphics2D) { + graphics2D.setColor( Color.WHITE ); // background + graphics2D.fillRect( x, y, 100, 100); } dialect "mvel" @@ -45,69 +45,59 @@ end rule "Feel Breeze" extends "Base Sensor" agenda-group "PaintSensor" when FeelBreeze() then - paintSensorCell("breeze.png", 0, 0, $gui, $gui.sensorPanel.sensorG ); + paintSensorCell("breeze.png", 0, 0, $gui, $gui.sensorPanel.graphics2D ); end rule "Breeze Gone" extends "Base Sensor" agenda-group "PaintSensor" when not FeelBreeze() then - clearSensorCell( 0, 0, $gui.sensorPanel.sensorG ); + clearSensorCell( 0, 0, $gui.sensorPanel.graphics2D ); end rule "Smell Stench" extends "Base Sensor" agenda-group "PaintSensor"when SmellStench() then - paintSensorCell("stench.png", 103, 0, $gui, $gui.sensorPanel.sensorG ); + paintSensorCell("stench.png", 103, 0, $gui, $gui.sensorPanel.graphics2D ); end rule "Stench Gone" extends "Base Sensor" agenda-group "PaintSensor"when not SmellStench() then - clearSensorCell( 103, 0, $gui.sensorPanel.sensorG ); + clearSensorCell( 103, 0, $gui.sensorPanel.graphics2D ); end rule "See Glitter" extends "Base Sensor" agenda-group "PaintSensor"when SeeGlitter() then - paintSensorCell("glitter.png", 206, 0, $gui, $gui.sensorPanel.sensorG ); + paintSensorCell("glitter.png", 206, 0, $gui, $gui.sensorPanel.graphics2D ); end rule "Glitter Gone" extends "Base Sensor" agenda-group "PaintSensor" when not SeeGlitter() then - clearSensorCell( 206, 0, $gui.sensorPanel.sensorG ); + clearSensorCell( 206, 0, $gui.sensorPanel.graphics2D ); end rule "Feel Bump" extends "Base Sensor" agenda-group "PaintSensor"when FeelBump() then - paintSensorCell("bump.png", 309, 0, $gui, $gui.sensorPanel.sensorG ); + paintSensorCell("bump.png", 309, 0, $gui, $gui.sensorPanel.graphics2D ); end rule "Bump Gone" extends "Base Sensor" agenda-group "PaintSensor" when not FeelBump() then - clearSensorCell( 309, 0, $gui.sensorPanel.sensorG ); + clearSensorCell( 309, 0, $gui.sensorPanel.graphics2D ); end rule "Hear Scream" extends "Base Sensor" agenda-group "PaintSensor" when HearScream() then - paintSensorCell("scream.png", 412, 0, $gui, $gui.sensorPanel.sensorG ); + paintSensorCell("scream.png", 412, 0, $gui, $gui.sensorPanel.graphics2D ); end rule "Scream Gone" extends "Base Sensor" agenda-group "PaintSensor" when not HearScream() then - clearSensorCell( 412, 0, $gui.sensorPanel.sensorG ); -end - -/* -rule "Redraw Sensors" no-loop salience -100 when - $gui : GameUI() - $sd : SensorDirty( dirty == true ) -then - $gui.updateSensors(); - modify( $sd ) { dirty = false }; -end -*/ \ No newline at end of file + clearSensorCell( 412, 0, $gui.sensorPanel.graphics2D ); +end \ No newline at end of file diff --git a/drools-examples/src/main/resources/org/drools/games/wumpus/server/reset.drl b/drools-examples/src/main/resources/org/drools/games/wumpus/server/reset.drl index 5138626f537..64ad31f5c1a 100644 --- a/drools-examples/src/main/resources/org/drools/games/wumpus/server/reset.drl +++ b/drools-examples/src/main/resources/org/drools/games/wumpus/server/reset.drl @@ -43,7 +43,6 @@ rule "Reset Cells" agenda-group "Reset" when $c : Cell() then retract( $c ); - System.out.println( kcontext ); end rule "Reset Pits" agenda-group "Reset" when From ad24413b9b59de33831a16c79f114763a0b3d57a Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 28 Jul 2014 20:23:00 +0200 Subject: [PATCH 63/76] [DROOLS-567] fix TextAdventure data (cherry picked from commit fa919b3d0cb5df709fcb72d08db6e720e14c10cb) --- .../src/main/resources/org/drools/games/adventures/data.mvel | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel index 724da106681..ee3de8c450c 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel +++ b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel @@ -13,7 +13,7 @@ rooms = [ "lounge" : new Room("lounge"), "kitchen" : new Room("kitchen"), "ground floor hallway" : new Room("ground floor hallway"), - "bedroom1" : new Room("bedroom"), + "bedroom" : new Room("bedroom"), "office" : new Room("office"), "first floor hallway" : new Room("first floor hallway") ]; @@ -27,7 +27,7 @@ doors = [ "d2" : new Door( rooms["ground floor hallway"], rooms["lounge"]), "d4" : new Door( rooms["ground floor hallway"], rooms["kitchen"]), "d5" : new Door( rooms["ground floor hallway"], rooms[ "first floor hallway"] ), - "d8" : new Door( rooms["first floor hallway"], rooms[ "bathroom"] ), + "d8" : new Door( rooms["first floor hallway"], rooms[ "bedroom"] ), "d9" : new Door( rooms["first floor hallway"], rooms[ "office"] ) ]; From f50704687816d53b1dfe3be05c3f9b675c4c0e9f Mon Sep 17 00:00:00 2001 From: Mark Proctor Date: Tue, 29 Jul 2014 06:03:40 +0100 Subject: [PATCH 64/76] DROOLS-567 Improve Examples -Minor corrections (cherry picked from commit b0e442d476ac969cd3a99b38c89a605c74448df9) --- .../games/adventures/AdventureFrame.java | 2 +- .../games/adventures/model/MoveCommand.java | 2 -- .../org/drools/games/adventures/Commands.drl | 32 +++++++++---------- .../org/drools/games/adventures/data.mvel | 2 +- .../org/drools/games/invaders3/Move.drl | 2 +- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java b/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java index 73dfeecdc36..a45eaf13374 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/AdventureFrame.java @@ -479,7 +479,7 @@ public void actionPerformed(ActionEvent e) { new Object[][]{ }, new String[]{ - "Items" + "Things" } ) ); thingsTable.addMouseListener( new MouseListener() { diff --git a/drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java b/drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java index 89c040853af..20c8a637396 100644 --- a/drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java +++ b/drools-examples/src/main/java/org/drools/games/adventures/model/MoveCommand.java @@ -13,8 +13,6 @@ public class MoveCommand extends Command { @Position(2) private Room room; - - public MoveCommand(Character character, Room room) { this.character = character; this.room = room; diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl index 2fd9b948f64..830a27a838b 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl +++ b/drools-examples/src/main/resources/org/drools/games/adventures/Commands.drl @@ -26,7 +26,6 @@ then setFocus( "commands" ); end - rule lookCmd agenda-group "commands" when lc : LookCommand( c : character ) Location( thing == c, $room : target ) @@ -63,18 +62,6 @@ then delete( mc ); end -rule validPickup agenda-group "commands" when - pc : PickupCommand( c : character, t : thing) - cl : Location( thing == pc.character ) - tl : Location( thing == pc.thing, target == cl.target ) @watch( !target ) -then - insert( new Holding( c, t ) ); - modify( tl ) { target = c }; - insert( new PickupEvent( c, t ) ); - - pc.session.channels["output"].send( "You have picked up the " + t.name + "\n" ); -end - rule unlockingDoors agenda-group "commands" when uc : UseCommand( c : character, t : thing) k : Key() from uc.thing @@ -109,13 +96,24 @@ then retract ( uc ); end +rule validPickup agenda-group "commands" when + pc : PickupCommand( c : character, t : thing) + cl : Location( thing == c ) + tl : Location( thing == t, target == cl.target ) +then + insert( new Holding( c, t ) ); + modify( tl ) { target = c }; + insert( new PickupEvent( c, t ) ); + + pc.session.channels["output"].send( "You have picked up the " + t.name + "\n" ); +end rule validDrop agenda-group "commands" when dc : DropCommand( c : character, t : thing) - cl : Location( thing == c ) - tl : Location( thing == t ) @watch( !target ) - h : Holding( c, t;) + cl : Location( thing == c ) + tl : Location( thing == t ) @watch( !target ) + h : Holding( c, t;) then modify( tl ) { target = cl.target }; retract ( h ); @@ -140,7 +138,7 @@ then gc.session.channels["output"].send( "You have given the " + gc.thing.name + " to " + gc.receiver.name + "\n" ); end -rule retractCommand agenda-group "commands" lock-on-active auto-focus salience -100 when +rule retractCommand agenda-group "commands" salience -100 when c : Command() then delete( c ); diff --git a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel index ee3de8c450c..ffe3efd579b 100644 --- a/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel +++ b/drools-examples/src/main/resources/org/drools/games/adventures/data.mvel @@ -50,7 +50,7 @@ with(doors["d1"]){ lockStatus = LockStatus.LOCKED, key = items["key1"] }; locations = [ "monster" : new Location( characters["monster"], rooms["basement"] ), "hero" : new Location( characters["hero"], rooms["ground floor hallway"] ), - "umbrella" : new Location( items["umbrella"], rooms["bedroom"] ), + "umbrella" : new Location( items["umbrella"], rooms["lounge"] ), "key1" : new Location( items["key1"], rooms["office"] ) ]; diff --git a/drools-examples/src/main/resources/org/drools/games/invaders3/Move.drl b/drools-examples/src/main/resources/org/drools/games/invaders3/Move.drl index 864f769ae58..6f06a48f582 100644 --- a/drools-examples/src/main/resources/org/drools/games/invaders3/Move.drl +++ b/drools-examples/src/main/resources/org/drools/games/invaders3/Move.drl @@ -38,7 +38,7 @@ then end rule ShipMove agenda-group "Move" when - s : Unit( dx != 0 ) + s : Ship( dx != 0 ) Run() then modify( s ) { x = s.x + s.dx } From 5c51f5d77505806d31e91b47d61e55a567e91f39 Mon Sep 17 00:00:00 2001 From: lanceleverich Date: Mon, 28 Jul 2014 13:52:25 -0500 Subject: [PATCH 65/76] Merge branch '6.0.x' of https://github.com/droolsjbpm/drools.git Conflicts: drools-compiler/pom.xml drools-compiler/src/main/java/org/drools/compiler/builder/impl/CompositeKnowledgeBuilderImpl.java drools-compiler/src/main/java/org/drools/compiler/builder/impl/KnowledgeBuilderImpl.java drools-compiler/src/main/java/org/drools/compiler/compiler/PMMLCompilerFactory.java drools-compiler/src/main/java/org/drools/compiler/compiler/PackageBuilder.java drools-compiler/src/main/java/org/drools/compiler/compiler/PackageBuilderConfiguration.java drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/AbstractKieModule.java drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/InternalKieScanner.java drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieBuilderSetImpl.java drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieContainerImpl.java drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieMetaInfoBuilder.java drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieRepositoryImpl.java drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieServicesImpl.java drools-compiler/src/main/java/org/drools/compiler/kie/util/CDIHelper.java drools-compiler/src/main/java/org/drools/compiler/kie/util/ChangeSetBuilder.java drools-compiler/src/main/java/org/drools/compiler/kproject/ReleaseIdImpl.java drools-compiler/src/main/java/org/drools/compiler/lang/descr/AnnotationDescr.java drools-compiler/src/main/java/org/drools/compiler/lang/descr/CompositePackageDescr.java drools-compiler/src/main/java/org/drools/compiler/lang/descr/PackageDescr.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/ConditionalBranchBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/MVELConstraintBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/PackageBuildContext.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/PatternBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/QueryElementBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/RuleBuildContext.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/RuleBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaAccumulateBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/JavaDialect.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/mvel/MVELAccumulateBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/mvel/MVELConsequenceBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/mvel/MVELDialect.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/mvel/MVELEnabledBuilder.java drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/mvel/MVELSalienceBuilder.java drools-compiler/src/main/resources/org/drools/compiler/rule/builder/dialect/java/javaRule.mvel drools-compiler/src/test/java/org/drools/compiler/CommonTestMethodBase.java drools-compiler/src/test/java/org/drools/compiler/beliefsystem/defeasible/DefeasibilityTest.java drools-compiler/src/test/java/org/drools/compiler/compiler/PackageBuilderConfigurationTest.java drools-compiler/src/test/java/org/drools/compiler/compiler/TypeDeclarationTest.java drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/LogicalTraitTest.java drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/TraitFieldsAndLegacyClassesTest.java drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/TraitMapCoreTest.java drools-compiler/src/test/java/org/drools/compiler/factmodel/traits/TraitTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/AccumulateTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/AddRemoveRulesTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/AnnotationsTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/CepEspTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/ChangesetUndoTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/DynamicRuleRemovalTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/ExecutionFlowControlTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/ExtendsTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/IndexingTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/KieLoggersTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/KnowledgeBuilderTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/LargeRuleBaseSerializationTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/MiscTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/QueryTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/SerializationHelper.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/TimerAndCalendarTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/TruthMaintenanceTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/marshalling/FactHandleMarshallingTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/marshalling/MarshallingTest.java drools-compiler/src/test/java/org/drools/compiler/integrationtests/sequential/SequentialTest.java drools-compiler/src/test/java/org/drools/compiler/kproject/KieProjectDefaultClasspathTest.java drools-compiler/src/test/java/org/drools/compiler/lang/descr/PackageDescrTest.java drools-compiler/src/test/java/org/drools/compiler/phreak/SegmentPropagationTest.java drools-compiler/src/test/java/org/drools/compiler/rule/builder/dialect/mvel/MVELConsequenceBuilderTest.java drools-compiler/src/test/java/org/drools/compiler/testframework/MockWorkingMemory.java drools-compiler/src/test/resources/org/drools/compiler/beliefsystem/defeasible/defeat.drl drools-compiler/src/test/resources/org/drools/compiler/beliefsystem/defeasible/defeaterOnly.drl drools-compiler/src/test/resources/org/drools/compiler/beliefsystem/defeasible/multiDefeat.drl drools-compiler/src/test/resources/org/drools/compiler/beliefsystem/defeasible/strictOverride.drl drools-core/pom.xml drools-core/src/main/java/org/drools/core/RuleBaseConfiguration.java drools-core/src/main/java/org/drools/core/audit/WorkingMemoryLogger.java drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorFactory.java drools-core/src/main/java/org/drools/core/base/DefaultKnowledgeHelper.java drools-core/src/main/java/org/drools/core/base/DroolsQuery.java drools-core/src/main/java/org/drools/core/base/EvaluatorWrapper.java drools-core/src/main/java/org/drools/core/base/UndefinedCalendarExcption.java drools-core/src/main/java/org/drools/core/base/mvel/MVELReturnValueExpression.java drools-core/src/main/java/org/drools/core/beliefsystem/defeasible/DefeasibleBeliefSet.java drools-core/src/main/java/org/drools/core/beliefsystem/defeasible/DefeasibleBeliefSystem.java drools-core/src/main/java/org/drools/core/beliefsystem/jtms/JTMSBeliefSet.java drools-core/src/main/java/org/drools/core/beliefsystem/jtms/JTMSBeliefSystem.java drools-core/src/main/java/org/drools/core/beliefsystem/simple/BeliefSystemLogicalCallback.java drools-core/src/main/java/org/drools/core/command/impl/CommandBasedStatefulKnowledgeSession.java drools-core/src/main/java/org/drools/core/command/runtime/rule/FireUntilHaltCommand.java drools-core/src/main/java/org/drools/core/command/runtime/rule/GetObjectInEntryPointCommand.java drools-core/src/main/java/org/drools/core/command/runtime/rule/GetObjectsInEntryPointCommand.java drools-core/src/main/java/org/drools/core/common/AbstractWorkingMemory.java drools-core/src/main/java/org/drools/core/common/AgendaGroupQueueImpl.java drools-core/src/main/java/org/drools/core/common/DefaultAgenda.java drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java drools-core/src/main/java/org/drools/core/common/NamedEntryPoint.java drools-core/src/main/java/org/drools/core/common/PhreakWorkingMemoryFactory.java drools-core/src/main/java/org/drools/core/common/ProjectClassLoader.java drools-core/src/main/java/org/drools/core/common/Scheduler.java drools-core/src/main/java/org/drools/core/concurrent/ExecutorProviderImpl.java drools-core/src/main/java/org/drools/core/definitions/impl/KnowledgePackageImpl.java drools-core/src/main/java/org/drools/core/factmodel/DefaultBeanClassBuilder.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitClassBuilderImpl.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitCoreWrapperClassBuilderImpl.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitFactory.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitField.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitMapPropertyWrapperClassBuilderImpl.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitMapProxyClassBuilderImpl.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTriplePropertyWrapperClassBuilderImpl.java drools-core/src/main/java/org/drools/core/factmodel/traits/TraitTripleProxyClassBuilderImpl.java drools-core/src/main/java/org/drools/core/factmodel/traits/TypeCache.java drools-core/src/main/java/org/drools/core/impl/KnowledgeBaseImpl.java drools-core/src/main/java/org/drools/core/impl/StatefulKnowledgeSessionImpl.java drools-core/src/main/java/org/drools/core/impl/StatelessKnowledgeSessionImpl.java drools-core/src/main/java/org/drools/core/io/impl/UrlResource.java drools-core/src/main/java/org/drools/core/marshalling/impl/InputMarshaller.java drools-core/src/main/java/org/drools/core/marshalling/impl/OutputMarshaller.java drools-core/src/main/java/org/drools/core/marshalling/impl/PersisterHelper.java drools-core/src/main/java/org/drools/core/marshalling/impl/ProtobufInputMarshaller.java drools-core/src/main/java/org/drools/core/marshalling/impl/ProtobufOutputMarshaller.java drools-core/src/main/java/org/drools/core/phreak/AddRemoveRule.java drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java drools-core/src/main/java/org/drools/core/phreak/RuleAgendaItem.java drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java drools-core/src/main/java/org/drools/core/phreak/SegmentUtilities.java drools-core/src/main/java/org/drools/core/process/instance/WorkItem.java drools-core/src/main/java/org/drools/core/process/instance/impl/WorkItemImpl.java drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java drools-core/src/main/java/org/drools/core/reteoo/ClassObjectTypeConf.java drools-core/src/main/java/org/drools/core/reteoo/DisposedReteooWorkingMemory.java drools-core/src/main/java/org/drools/core/reteoo/FromNode.java drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java drools-core/src/main/java/org/drools/core/reteoo/NotNode.java drools-core/src/main/java/org/drools/core/reteoo/PathMemory.java drools-core/src/main/java/org/drools/core/reteoo/QueryElementNode.java drools-core/src/main/java/org/drools/core/reteoo/ReteooBuilder.java drools-core/src/main/java/org/drools/core/reteoo/ReteooRuleBase.java drools-core/src/main/java/org/drools/core/reteoo/ReteooStatelessSession.java drools-core/src/main/java/org/drools/core/reteoo/RiaPathMemory.java drools-core/src/main/java/org/drools/core/reteoo/RuleRemovalContext.java drools-core/src/main/java/org/drools/core/reteoo/SegmentMemory.java drools-core/src/main/java/org/drools/core/reteoo/builder/BuildUtils.java drools-core/src/main/java/org/drools/core/reteoo/builder/PhreakNodeFactory.java drools-core/src/main/java/org/drools/core/reteoo/builder/ReteooRuleBuilder.java drools-core/src/main/java/org/drools/core/rule/JavaDialectRuntimeData.java drools-core/src/main/java/org/drools/core/rule/LogicTransformer.java drools-core/src/main/java/org/drools/core/rule/PredicateConstraint.java drools-core/src/main/java/org/drools/core/rule/Rule.java drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/GeneratorHelper.java drools-core/src/main/java/org/drools/core/rule/constraint/MvelConstraint.java drools-core/src/main/java/org/drools/core/spi/PropagationContext.java drools-core/src/main/java/org/drools/core/time/TimeUtils.java drools-core/src/main/java/org/drools/core/util/asm/ClassFieldInspector.java drools-core/src/test/java/org/drools/core/common/DroolsObjectIOTest.java drools-core/src/test/java/org/drools/core/factmodel/ClassBuilderTest.java drools-core/src/test/java/org/drools/core/factmodel/InstancesHashcodedTest.java drools-core/src/test/java/org/drools/core/reteoo/NodeSegmentUnlinkingTest.java drools-core/src/test/java/org/drools/core/reteoo/ReteTest.java drools-core/src/test/java/org/drools/core/reteoo/RuleUnlinkingTest.java drools-core/src/test/java/org/drools/core/reteoo/RuleUnlinkingWithSegmentMemoryTest.java drools-decisiontables/pom.xml drools-distribution/pom.xml drools-docs/drools-expert-docs/pom.xml drools-docs/drools-expert-docs/src/main/docbook/en-US/LanguageReference/Rule.xml drools-docs/drools-fusion-docs/pom.xml drools-docs/pom.xml drools-examples-api/default-kiesession-from-file/pom.xml drools-examples-api/default-kiesession/pom.xml drools-examples-api/kie-module-from-multiple-files/pom.xml drools-examples-api/kiebase-inclusion/pom.xml drools-examples-api/kiecontainer-from-kierepo/pom.xml drools-examples-api/kiefilesystem-example/pom.xml drools-examples-api/kiemodulemodel-example/pom.xml drools-examples-api/multiple-kbases/pom.xml drools-examples-api/named-kiesession-from-file/pom.xml drools-examples-api/named-kiesession/pom.xml drools-examples-api/pom.xml drools-examples-cdi/cdi-example-with-inclusion/pom.xml drools-examples-cdi/cdi-example/pom.xml drools-examples-cdi/pom.xml drools-examples/pom.xml drools-examples/src/main/java/org/drools/examples/state/StateExampleUsingAgendaGroup.java drools-jsr94/pom.xml drools-maven-plugin/.gitignore drools-persistence-jpa/pom.xml drools-persistence-jpa/src/main/java/org/drools/persistence/SingleSessionCommandService.java drools-persistence-jpa/src/main/java/org/drools/persistence/info/WorkItemInfo.java drools-persistence-jpa/src/main/java/org/drools/persistence/jpa/marshaller/JPAPlaceholderResolverStrategy.java drools-persistence-jpa/src/main/java/org/drools/persistence/jpa/processinstance/JPAWorkItemManager.java drools-persistence-jpa/src/test/java/org/drools/persistence/jta/JtaTransactionManagerTest.java drools-persistence-jpa/src/test/java/org/drools/persistence/marshalling/util/CompareViaReflectionUtil.java drools-persistence-jpa/src/test/java/org/drools/persistence/marshalling/util/MarshalledData.java drools-persistence-jpa/src/test/java/org/drools/persistence/marshalling/util/MarshallingTestUtil.java drools-persistence-jpa/src/test/java/org/drools/persistence/marshalling/util/TestMarshallingUtilsTest.java drools-persistence-jpa/src/test/java/org/drools/persistence/session/AgendaRuleFlowGroupsTest.java drools-reteoo/pom.xml drools-reteoo/src/main/java/org/drools/reteoo/builder/ReteNodeFactory.java drools-reteoo/src/main/java/org/drools/reteoo/common/ReteAgenda.java drools-reteoo/src/main/java/org/drools/reteoo/common/ReteWorkingMemory.java drools-reteoo/src/main/java/org/drools/reteoo/common/ReteWorkingMemoryEntryPoint.java drools-reteoo/src/main/java/org/drools/reteoo/common/ReteWorkingMemoryFactory.java drools-reteoo/src/main/java/org/drools/reteoo/nodes/ReteAccumulateNode.java drools-reteoo/src/main/java/org/drools/reteoo/nodes/ReteBetaNodeUtils.java drools-reteoo/src/test/java/org/drools/reteoo/common/AgendaItemTest.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/AccumulateTest.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/AlphaNetworkModifyTest.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/CommonTestMethodBase.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/DynamicRulesTest.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/Misc2Test.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/MiscTest.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/QueryTest.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/marshalling/FactHandleMarshallingTest.java drools-reteoo/src/test/java/org/drools/reteoo/integrationtests/marshalling/MarshallingTest.java drools-reteoo/src/test/resources/org/drools/reteoo/integrationtests/test_salienceExpressionRule.drl drools-reteoo/src/test/resources/org/drools/reteoo/integrationtests/test_salienceIntegerRule.drl drools-reteoo/src/test/resources/testEnumReteoo.jar drools-scorecards/pom.xml drools-scorecards/src/main/java/org/drools/scorecards/drl/AbstractDRLEmitter.java drools-scorecards/src/main/java/org/drools/scorecards/drl/ExternalModelDRLEmitter.java drools-scorecards/src/test/java/org/drools/scorecards/ScorecardsKModuleTest.java drools-templates/pom.xml drools-verifier/pom.xml drools-verifier/src/test/java/org/drools/verifier/consequence/NamedConsequencesTest.java drools-workbench-models/drools-workbench-models-commons/pom.xml drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/ActionCallMethodBuilder.java drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceImpl.java drools-workbench-models/drools-workbench-models-commons/src/main/java/org/drools/workbench/models/commons/backend/rule/RuleModelPersistenceHelper.java drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceTest.java drools-workbench-models/drools-workbench-models-commons/src/test/java/org/drools/workbench/models/commons/backend/rule/RuleModelDRLPersistenceUnmarshallingTest.java drools-workbench-models/drools-workbench-models-datamodel-api/pom.xml drools-workbench-models/drools-workbench-models-guided-dtable/pom.xml drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/backend/util/GuidedDTBRDRLPersistence.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/auditlog/UpdateColumnAuditLogEntry.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionInsertFactFieldsPattern.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionSetFieldCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemInsertFactCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ActionWorkItemSetFieldCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/AttributeCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionColumn.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLActionVariableColumn.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionColumn.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BRLConditionVariableColumn.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/BaseColumnFieldDiffImpl.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/ConditionCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTCellValue52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DTColumnConfig52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/DiffColumn.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionInsertFactCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionRetractFactCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryActionSetFieldCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/LimitedEntryConditionCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/MetadataCol52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/main/java/org/drools/workbench/models/guided/dtable/shared/model/Pattern52.java drools-workbench-models/drools-workbench-models-guided-dtable/src/test/java/org/drools/workbench/models/guided/dtable/backend/BRLRuleModelTest.java drools-workbench-models/drools-workbench-models-guided-scorecard/pom.xml drools-workbench-models/drools-workbench-models-guided-scorecard/src/main/java/org/drools/workbench/models/guided/scorecard/backend/GuidedScoreCardDRLPersistence.java drools-workbench-models/drools-workbench-models-guided-template/pom.xml drools-workbench-models/drools-workbench-models-guided-template/src/main/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceImpl.java drools-workbench-models/drools-workbench-models-guided-template/src/test/java/org/drools/workbench/models/guided/template/backend/RuleTemplateModelDRLPersistenceTest.java drools-workbench-models/drools-workbench-models-test-scenarios/pom.xml drools-workbench-models/drools-workbench-models-test-scenarios/src/main/java/org/drools/workbench/models/testscenarios/backend/ScenarioRunner.java drools-workbench-models/drools-workbench-models-test-scenarios/src/test/java/org/drools/workbench/models/testscenarios/backend/ScenarioRunnerTest.java drools-workbench-models/pom.xml kie-ci-osgi/.gitignore kie-ci-osgi/pom.xml kie-ci/pom.xml kie-ci/src/main/java/org/kie/scanner/Aether.java kie-ci/src/main/java/org/kie/scanner/KieRepositoryScannerImpl.java kie-ci/src/main/java/org/kie/scanner/MavenPomModelGenerator.java kie-ci/src/main/java/org/kie/scanner/MavenRepository.java kie-ci/src/test/java/org/kie/scanner/AbstractKieCiTest.java kie-ci/src/test/java/org/kie/scanner/KieModuleMavenTest.java kie-ci/src/test/java/org/kie/scanner/KieModuleMetaDataTest.java kie-ci/src/test/java/org/kie/scanner/KieRepositoryScannerTest.java kie-maven-plugin-example/.gitignore kie-maven-plugin/pom.xml knowledge-api-legacy5-adapter/pom.xml knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/KnowledgeBuilderFactoryServiceImpl.java knowledge-api-legacy5-adapter/src/main/java/org/drools/impl/adapters/KnowledgeRuntimeAdapter.java knowledge-api-legacy5-adapter/src/test/java/org/drools/integrationtests/MiscTest.java pom.xml (cherry picked from commit 4a8ce96dc1fa17db2aeeb550a4d32e13d45a1014) --- .../java/org/drools/compiler/lang/dsl/DefaultExpander.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java b/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java index 9b34682bc41..d0843d0d0f3 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java +++ b/drools-compiler/src/main/java/org/drools/compiler/lang/dsl/DefaultExpander.java @@ -544,7 +544,8 @@ private String expandLHS(final String lhs, // logger.info( "*** LHS>" + lhs + "<" ); final StringBuilder buf = new StringBuilder(); - final String[] lines = lhs.split( nl, + + final String[] lines = lhs.split( (lhs.indexOf("\r\n") >= 0 ? "\r\n":"\n"), -1 ); // since we assembled the string, we know line breaks are \n final String[] expanded = new String[lines.length]; // buffer for expanded lines int lastExpanded = -1; @@ -614,7 +615,7 @@ private String expandLHS(final String lhs, private String expandRHS(final String lhs, int lineOffset) { final StringBuilder buf = new StringBuilder(); - final String[] lines = lhs.split( nl, + final String[] lines = lhs.split((lhs.indexOf("\r\n") >= 0 ? "\r\n":"\n"), -1 ); // since we assembled the string, we know line breaks are \n final String[] expanded = new String[lines.length]; // buffer for expanded lines From 5b97ca913f0e1b4cd37f5aa156b1c2ab39ce6b9c Mon Sep 17 00:00:00 2001 From: mariofusco Date: Wed, 30 Jul 2014 16:48:30 +0200 Subject: [PATCH 66/76] [DROOLS-569] update the index of a property even when it is explicitly excluded by reactivity (cherry picked from commit 4f2f82e396a0519a89340d145e16d08bd501e0e9) --- .../PropertyReactivityTest.java | 66 +++++++++++++++---- .../java/org/drools/core/reteoo/BetaNode.java | 2 + 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/PropertyReactivityTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/PropertyReactivityTest.java index 69cedc18783..78d40d9e12a 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/PropertyReactivityTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/PropertyReactivityTest.java @@ -3,17 +3,16 @@ import org.drools.compiler.CommonTestMethodBase; import org.drools.core.factmodel.traits.Traitable; import org.drools.core.io.impl.ByteArrayResource; -import org.junit.Ignore; import org.junit.Test; import org.kie.api.definition.type.Modifies; import org.kie.api.definition.type.PropertyReactive; import org.kie.api.io.ResourceType; +import org.kie.api.runtime.KieSession; import org.kie.internal.KnowledgeBase; -import org.kie.internal.KnowledgeBaseFactory; import org.kie.internal.builder.KnowledgeBuilder; import org.kie.internal.builder.KnowledgeBuilderFactory; -import org.kie.internal.io.ResourceFactory; import org.kie.internal.runtime.StatefulKnowledgeSession; +import org.kie.internal.utils.KieHelper; import java.math.BigDecimal; import java.util.ArrayList; @@ -1051,17 +1050,10 @@ public void testModifyAfterInsertWithPropertyReactive() { " list.add( 3 );\n" + "end"; - KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); - kbuilder.add( ResourceFactory.newByteArrayResource(rule1.getBytes()), ResourceType.DRL ); + KieHelper helper = new KieHelper(); + helper.addContent(rule1, ResourceType.DRL); + KieSession ksession = helper.build().newKieSession(); - if ( kbuilder.hasErrors() ) { - fail( kbuilder.getErrors().toString() ); - } - - KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); - kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); - - StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal("list", list); @@ -1162,4 +1154,52 @@ public String getFullName(){ return this.name + " "+ this.lastName; } } + + @Test + public void testIndexedNotWatchedProperty() { + // DROOLS-569 + String rule1 = + "package com.sample;\n" + + "import " + MyClass.class.getCanonicalName() + ";\n" + + "global java.util.List list;\n" + + "rule R1 when\n" + + " $s : String()\n" + + " $m : MyClass( data != null, value == $s ) @watch( !* )\n" + + "then \n" + + " list.add($s);\n" + + " modify( $m ) { setValue(\"2\") };\n" + + "end\n" + + "\n" + + "rule R2 when\n" + + " $i : Integer()\n" + + " $m : MyClass( value == $i.toString(), data == \"x\" ) @watch( !value )\n" + + "then \n" + + " modify( $m ) { setValue(\"3\"), setData(\"y\") };\n" + + "end"; + + KieHelper helper = new KieHelper(); + helper.addContent(rule1, ResourceType.DRL); + KieSession ksession = helper.build().newKieSession(); + + List list = new ArrayList(); + ksession.setGlobal("list", list); + + MyClass myClass = new MyClass(); + myClass.setValue("1"); + myClass.setData("x"); + ksession.insert(myClass); + ksession.insert("1"); + ksession.insert(2); + ksession.fireAllRules(); + + assertEquals(1, list.size()); + assertEquals("1", list.get(0)); + list.clear(); + + ksession.insert("3"); + ksession.fireAllRules(); + + assertEquals(1, list.size()); + assertEquals("3", list.get(0)); + } } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java index e8575b36672..daf761cf326 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java @@ -333,6 +333,8 @@ public void modifyObject(InternalFactHandle factHandle, ModifyPreviousTuples mod BetaMemory bm = getBetaMemory( this, wm ); rightTuple.setPropagationContext( context ); doUpdateRightTuple(rightTuple, wm, bm); + } else if (rightTuple.getMemory() != null) { + getBetaMemory( this, wm ).getRightTupleMemory().removeAdd(rightTuple); } } else { if ( intersect( context.getModificationMask(), getRightInferredMask() ) ) { From 82353d8e658176fdd3fef1961e9e23827d4231b2 Mon Sep 17 00:00:00 2001 From: kiereleaseuser Date: Thu, 31 Jul 2014 13:15:48 +0200 Subject: [PATCH 67/76] upgrade to 6.1.1-SNAPSHOT --- drools-compiler/pom.xml | 2 +- drools-core/pom.xml | 2 +- drools-decisiontables/pom.xml | 2 +- drools-distribution/pom.xml | 2 +- drools-docs/drools-expert-docs/pom.xml | 2 +- drools-docs/drools-fusion-docs/pom.xml | 2 +- drools-docs/pom.xml | 2 +- drools-examples-api/default-kiesession-from-file/pom.xml | 2 +- drools-examples-api/default-kiesession/pom.xml | 2 +- drools-examples-api/kie-module-from-multiple-files/pom.xml | 2 +- drools-examples-api/kiebase-inclusion/pom.xml | 2 +- drools-examples-api/kiecontainer-from-kierepo/pom.xml | 2 +- drools-examples-api/kiefilesystem-example/pom.xml | 2 +- drools-examples-api/kiemodulemodel-example/pom.xml | 2 +- drools-examples-api/multiple-kbases/pom.xml | 2 +- drools-examples-api/named-kiesession-from-file/pom.xml | 2 +- drools-examples-api/named-kiesession/pom.xml | 2 +- drools-examples-api/pom.xml | 2 +- drools-examples-cdi/cdi-example-with-inclusion/pom.xml | 2 +- drools-examples-cdi/cdi-example/pom.xml | 2 +- drools-examples-cdi/pom.xml | 2 +- drools-examples/pom.xml | 2 +- drools-jsr94/pom.xml | 2 +- drools-persistence-jpa/pom.xml | 2 +- drools-pmml/pom.xml | 2 +- drools-reteoo/pom.xml | 2 +- drools-scorecards/pom.xml | 2 +- drools-templates/pom.xml | 2 +- drools-verifier/pom.xml | 2 +- drools-workbench-models/drools-workbench-models-commons/pom.xml | 2 +- .../drools-workbench-models-datamodel-api/pom.xml | 2 +- .../drools-workbench-models-guided-dtable/pom.xml | 2 +- .../drools-workbench-models-guided-scorecard/pom.xml | 2 +- .../drools-workbench-models-guided-template/pom.xml | 2 +- .../drools-workbench-models-test-scenarios/pom.xml | 2 +- drools-workbench-models/pom.xml | 2 +- kie-ci-osgi/pom.xml | 2 +- kie-ci/pom.xml | 2 +- kie-maven-plugin-example/pom.xml | 2 +- kie-maven-plugin/pom.xml | 2 +- knowledge-api-legacy5-adapter/pom.xml | 2 +- pom.xml | 2 +- 42 files changed, 42 insertions(+), 42 deletions(-) diff --git a/drools-compiler/pom.xml b/drools-compiler/pom.xml index 26e8240919a..d948aa58a31 100644 --- a/drools-compiler/pom.xml +++ b/drools-compiler/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-compiler diff --git a/drools-core/pom.xml b/drools-core/pom.xml index 47b6880a5db..b84a777a7ed 100644 --- a/drools-core/pom.xml +++ b/drools-core/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-core diff --git a/drools-decisiontables/pom.xml b/drools-decisiontables/pom.xml index fcad20783a5..f39ada68abc 100644 --- a/drools-decisiontables/pom.xml +++ b/drools-decisiontables/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-decisiontables diff --git a/drools-distribution/pom.xml b/drools-distribution/pom.xml index 34343bdb53f..0af069c01e4 100644 --- a/drools-distribution/pom.xml +++ b/drools-distribution/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-distribution diff --git a/drools-docs/drools-expert-docs/pom.xml b/drools-docs/drools-expert-docs/pom.xml index e84151e2323..8c1919c2f04 100755 --- a/drools-docs/drools-expert-docs/pom.xml +++ b/drools-docs/drools-expert-docs/pom.xml @@ -6,7 +6,7 @@ org.drools drools-docs - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-expert-docs diff --git a/drools-docs/drools-fusion-docs/pom.xml b/drools-docs/drools-fusion-docs/pom.xml index 695fb039b63..928333913a1 100755 --- a/drools-docs/drools-fusion-docs/pom.xml +++ b/drools-docs/drools-fusion-docs/pom.xml @@ -6,7 +6,7 @@ org.drools drools-docs - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-fusion-docs diff --git a/drools-docs/pom.xml b/drools-docs/pom.xml index 67d0b4a953a..cf234dd2960 100755 --- a/drools-docs/pom.xml +++ b/drools-docs/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-docs diff --git a/drools-examples-api/default-kiesession-from-file/pom.xml b/drools-examples-api/default-kiesession-from-file/pom.xml index 8193e87f200..e64c1a5eb9a 100644 --- a/drools-examples-api/default-kiesession-from-file/pom.xml +++ b/drools-examples-api/default-kiesession-from-file/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT default-kiesession-from-file diff --git a/drools-examples-api/default-kiesession/pom.xml b/drools-examples-api/default-kiesession/pom.xml index 85c32c46702..245520f5989 100644 --- a/drools-examples-api/default-kiesession/pom.xml +++ b/drools-examples-api/default-kiesession/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT default-kiesession diff --git a/drools-examples-api/kie-module-from-multiple-files/pom.xml b/drools-examples-api/kie-module-from-multiple-files/pom.xml index 62b4e3092a0..dc390007863 100644 --- a/drools-examples-api/kie-module-from-multiple-files/pom.xml +++ b/drools-examples-api/kie-module-from-multiple-files/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT kie-module-from-multiple-files diff --git a/drools-examples-api/kiebase-inclusion/pom.xml b/drools-examples-api/kiebase-inclusion/pom.xml index c41c9ec62d1..433c8f6d60c 100644 --- a/drools-examples-api/kiebase-inclusion/pom.xml +++ b/drools-examples-api/kiebase-inclusion/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT kiebase-inclusion diff --git a/drools-examples-api/kiecontainer-from-kierepo/pom.xml b/drools-examples-api/kiecontainer-from-kierepo/pom.xml index 7f6875d6c33..bb4f0b95b4e 100644 --- a/drools-examples-api/kiecontainer-from-kierepo/pom.xml +++ b/drools-examples-api/kiecontainer-from-kierepo/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT kiecontainer-from-kierepo diff --git a/drools-examples-api/kiefilesystem-example/pom.xml b/drools-examples-api/kiefilesystem-example/pom.xml index 0a038f9dda8..96412f90caa 100644 --- a/drools-examples-api/kiefilesystem-example/pom.xml +++ b/drools-examples-api/kiefilesystem-example/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT kiefilesystem-example diff --git a/drools-examples-api/kiemodulemodel-example/pom.xml b/drools-examples-api/kiemodulemodel-example/pom.xml index dd10522c538..c55792549ab 100644 --- a/drools-examples-api/kiemodulemodel-example/pom.xml +++ b/drools-examples-api/kiemodulemodel-example/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT kiemodulemodel-example diff --git a/drools-examples-api/multiple-kbases/pom.xml b/drools-examples-api/multiple-kbases/pom.xml index ddbe39002c0..8c54b20c85f 100644 --- a/drools-examples-api/multiple-kbases/pom.xml +++ b/drools-examples-api/multiple-kbases/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT multiple-kbases diff --git a/drools-examples-api/named-kiesession-from-file/pom.xml b/drools-examples-api/named-kiesession-from-file/pom.xml index 8a97390d7ed..6f5623295be 100644 --- a/drools-examples-api/named-kiesession-from-file/pom.xml +++ b/drools-examples-api/named-kiesession-from-file/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT Drools API examples - Named KieSession from File diff --git a/drools-examples-api/named-kiesession/pom.xml b/drools-examples-api/named-kiesession/pom.xml index cbf85f353e1..902f2e3ce64 100644 --- a/drools-examples-api/named-kiesession/pom.xml +++ b/drools-examples-api/named-kiesession/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-api - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT named-kiesession diff --git a/drools-examples-api/pom.xml b/drools-examples-api/pom.xml index 4c83f338d28..f8ed1caec15 100644 --- a/drools-examples-api/pom.xml +++ b/drools-examples-api/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-examples-api diff --git a/drools-examples-cdi/cdi-example-with-inclusion/pom.xml b/drools-examples-cdi/cdi-example-with-inclusion/pom.xml index f7cb6d0873f..b65c2d06804 100644 --- a/drools-examples-cdi/cdi-example-with-inclusion/pom.xml +++ b/drools-examples-cdi/cdi-example-with-inclusion/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-cdi - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT cdi-example-with-inclusion diff --git a/drools-examples-cdi/cdi-example/pom.xml b/drools-examples-cdi/cdi-example/pom.xml index f55a4429213..7ea6bfd8ad6 100644 --- a/drools-examples-cdi/cdi-example/pom.xml +++ b/drools-examples-cdi/cdi-example/pom.xml @@ -6,7 +6,7 @@ org.drools drools-examples-cdi - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT cdi-example diff --git a/drools-examples-cdi/pom.xml b/drools-examples-cdi/pom.xml index c918c79c04c..35b9f99fdb0 100644 --- a/drools-examples-cdi/pom.xml +++ b/drools-examples-cdi/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-examples-cdi diff --git a/drools-examples/pom.xml b/drools-examples/pom.xml index 20933ba4249..b8543e0d9ca 100644 --- a/drools-examples/pom.xml +++ b/drools-examples/pom.xml @@ -5,7 +5,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-examples diff --git a/drools-jsr94/pom.xml b/drools-jsr94/pom.xml index 059d8242b31..93b65fc7e10 100644 --- a/drools-jsr94/pom.xml +++ b/drools-jsr94/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-jsr94 diff --git a/drools-persistence-jpa/pom.xml b/drools-persistence-jpa/pom.xml index dfb81383c40..a0bf891791f 100644 --- a/drools-persistence-jpa/pom.xml +++ b/drools-persistence-jpa/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-persistence-jpa diff --git a/drools-pmml/pom.xml b/drools-pmml/pom.xml index c96cbd74014..f556368cdef 100644 --- a/drools-pmml/pom.xml +++ b/drools-pmml/pom.xml @@ -22,7 +22,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT diff --git a/drools-reteoo/pom.xml b/drools-reteoo/pom.xml index b4b1ccd920c..5f64a1c20c4 100644 --- a/drools-reteoo/pom.xml +++ b/drools-reteoo/pom.xml @@ -7,7 +7,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-reteoo diff --git a/drools-scorecards/pom.xml b/drools-scorecards/pom.xml index b1a1cacf8c1..38ca7f38613 100644 --- a/drools-scorecards/pom.xml +++ b/drools-scorecards/pom.xml @@ -7,7 +7,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-scorecards diff --git a/drools-templates/pom.xml b/drools-templates/pom.xml index 184a9502179..7c0a3c3a12f 100644 --- a/drools-templates/pom.xml +++ b/drools-templates/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-templates diff --git a/drools-verifier/pom.xml b/drools-verifier/pom.xml index 09c12d8dd6d..84194a9f967 100644 --- a/drools-verifier/pom.xml +++ b/drools-verifier/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-verifier diff --git a/drools-workbench-models/drools-workbench-models-commons/pom.xml b/drools-workbench-models/drools-workbench-models-commons/pom.xml index e74c49b0a03..e16d618c9f3 100644 --- a/drools-workbench-models/drools-workbench-models-commons/pom.xml +++ b/drools-workbench-models/drools-workbench-models-commons/pom.xml @@ -6,7 +6,7 @@ org.drools drools-workbench-models - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-workbench-models-commons diff --git a/drools-workbench-models/drools-workbench-models-datamodel-api/pom.xml b/drools-workbench-models/drools-workbench-models-datamodel-api/pom.xml index a63993ab4df..2db57f6b9d8 100644 --- a/drools-workbench-models/drools-workbench-models-datamodel-api/pom.xml +++ b/drools-workbench-models/drools-workbench-models-datamodel-api/pom.xml @@ -23,7 +23,7 @@ org.drools drools-workbench-models - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-workbench-models-datamodel-api diff --git a/drools-workbench-models/drools-workbench-models-guided-dtable/pom.xml b/drools-workbench-models/drools-workbench-models-guided-dtable/pom.xml index af7caaea9d8..eba12c3bcf9 100644 --- a/drools-workbench-models/drools-workbench-models-guided-dtable/pom.xml +++ b/drools-workbench-models/drools-workbench-models-guided-dtable/pom.xml @@ -6,7 +6,7 @@ org.drools drools-workbench-models - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-workbench-models-guided-dtable diff --git a/drools-workbench-models/drools-workbench-models-guided-scorecard/pom.xml b/drools-workbench-models/drools-workbench-models-guided-scorecard/pom.xml index 906c879eaac..ea26a19188c 100644 --- a/drools-workbench-models/drools-workbench-models-guided-scorecard/pom.xml +++ b/drools-workbench-models/drools-workbench-models-guided-scorecard/pom.xml @@ -6,7 +6,7 @@ org.drools drools-workbench-models - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-workbench-models-guided-scorecard diff --git a/drools-workbench-models/drools-workbench-models-guided-template/pom.xml b/drools-workbench-models/drools-workbench-models-guided-template/pom.xml index 8a171b4f5e6..292aecfbf4e 100644 --- a/drools-workbench-models/drools-workbench-models-guided-template/pom.xml +++ b/drools-workbench-models/drools-workbench-models-guided-template/pom.xml @@ -7,7 +7,7 @@ org.drools drools-workbench-models - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-workbench-models-guided-template diff --git a/drools-workbench-models/drools-workbench-models-test-scenarios/pom.xml b/drools-workbench-models/drools-workbench-models-test-scenarios/pom.xml index 4566b74ed7e..8adab232896 100644 --- a/drools-workbench-models/drools-workbench-models-test-scenarios/pom.xml +++ b/drools-workbench-models/drools-workbench-models-test-scenarios/pom.xml @@ -6,7 +6,7 @@ drools-workbench-models org.drools - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-workbench-models-test-scenarios diff --git a/drools-workbench-models/pom.xml b/drools-workbench-models/pom.xml index 0f5059ce583..01d966b4d7d 100644 --- a/drools-workbench-models/pom.xml +++ b/drools-workbench-models/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT drools-workbench-models diff --git a/kie-ci-osgi/pom.xml b/kie-ci-osgi/pom.xml index 2a02dddc212..1fc0ae0ae42 100644 --- a/kie-ci-osgi/pom.xml +++ b/kie-ci-osgi/pom.xml @@ -5,7 +5,7 @@ drools-multiproject org.drools - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT 4.0.0 diff --git a/kie-ci/pom.xml b/kie-ci/pom.xml index 31f69a51327..214560574b0 100644 --- a/kie-ci/pom.xml +++ b/kie-ci/pom.xml @@ -5,7 +5,7 @@ drools-multiproject org.drools - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT 4.0.0 diff --git a/kie-maven-plugin-example/pom.xml b/kie-maven-plugin-example/pom.xml index b529c1ea0b2..cb72c51ab65 100644 --- a/kie-maven-plugin-example/pom.xml +++ b/kie-maven-plugin-example/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT org.kie diff --git a/kie-maven-plugin/pom.xml b/kie-maven-plugin/pom.xml index eb516de7958..2ba02505fca 100644 --- a/kie-maven-plugin/pom.xml +++ b/kie-maven-plugin/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT org.kie diff --git a/knowledge-api-legacy5-adapter/pom.xml b/knowledge-api-legacy5-adapter/pom.xml index 67e84f6914d..ff7a88f3633 100644 --- a/knowledge-api-legacy5-adapter/pom.xml +++ b/knowledge-api-legacy5-adapter/pom.xml @@ -6,7 +6,7 @@ org.drools drools-multiproject - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT knowledge-api diff --git a/pom.xml b/pom.xml index 98aa015bcd3..56030509197 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.kie kie-parent-with-dependencies - 6.1.0-SNAPSHOT + 6.1.1-SNAPSHOT From 3093beb35d60cb662de11ef9e0ea216c89b498a6 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Tue, 5 Aug 2014 09:34:17 +0200 Subject: [PATCH 68/76] [DROOLS-570] fix invocation of LeftTuple.getIndex in generated consequence invoker (cherry picked from commit 2a198035907e919d15b7df44d58b699462a73be4) --- .../compiler/integrationtests/Misc2Test.java | 25 +++++++++++++++++++ .../builder/dialect/asm/GeneratorHelper.java | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java index c7cf0a49a6f..0bac6420035 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/Misc2Test.java @@ -6326,4 +6326,29 @@ public void testSharedQueryNode() throws Exception { ksession.insert(1); ksession.fireAllRules(); } + + @Test + public void testLeftTupleGetIndex() throws Exception { + // DROOLS-570 + String drl = + "rule R1 when\n" + + " $s : String()\n" + + " (or Long(this == 1) Long(this == 2) )\n" + + "then\n" + + "end\n" + + "rule R2 extends R1 when\n" + + " $n : Number() from accumulate( Integer($value : this) sum($value) )\n" + + "then\n" + + " System.out.println($n);\n" + + "end\n"; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ksession = helper.build().newKieSession(); + + ksession.insert("1"); + ksession.insert(1L); + ksession.insert(1); + ksession.fireAllRules(); + } } \ No newline at end of file diff --git a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/GeneratorHelper.java b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/GeneratorHelper.java index c2732f76801..4653fa5b8a0 100644 --- a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/GeneratorHelper.java +++ b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/GeneratorHelper.java @@ -232,7 +232,7 @@ protected void traverseTuplesUntilDeclarationWithOr(int declarIndex, int declarR Label whileExit = new Label(); mv.visitLabel(whileStart); mv.visitVarInsn(ALOAD, tupleReg); - invokeInterface(LeftTuple.class, "getQueueIndex", Integer.TYPE); // tuple.getQueueIndex() + invokeInterface(LeftTuple.class, "getIndex", Integer.TYPE); // tuple.getIndex() mv.visitVarInsn(ILOAD, declarOffsetReg); // declarations[i].getPattern().getOffset() mv.visitJumpInsn(IF_ICMPLE, whileExit); // if tuple.getQueueIndex() <= declarations[i].getPattern().getOffset() jump to whileExit mv.visitVarInsn(ALOAD, tupleReg); From 7482fbe4ac06f8bf6e73f41edfd7c0cdd70b8bd3 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Tue, 5 Aug 2014 18:47:14 +0200 Subject: [PATCH 69/76] [DROOLS-532] add automatic version recognition in PersisterHelper (cherry picked from commit e34a310ebc3649b9e46c5b60c0062acea2df4cf1) --- .../marshalling/impl/PersisterHelper.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drools-core/src/main/java/org/drools/core/marshalling/impl/PersisterHelper.java b/drools-core/src/main/java/org/drools/core/marshalling/impl/PersisterHelper.java index 21b26d45a9a..d8ced36e0cf 100644 --- a/drools-core/src/main/java/org/drools/core/marshalling/impl/PersisterHelper.java +++ b/drools-core/src/main/java/org/drools/core/marshalling/impl/PersisterHelper.java @@ -16,34 +16,34 @@ package org.drools.core.marshalling.impl; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidKeyException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.util.Map.Entry; - +import com.google.protobuf.ByteString; +import com.google.protobuf.ByteString.Output; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.Message; import org.drools.core.beliefsystem.simple.BeliefSystemLogicalCallback; -import org.drools.core.impl.StatefulKnowledgeSessionImpl.WorkingMemoryReteAssertAction; -import org.drools.core.impl.StatefulKnowledgeSessionImpl.WorkingMemoryReteExpireAction; import org.drools.core.common.DroolsObjectInputStream; import org.drools.core.common.DroolsObjectOutputStream; import org.drools.core.common.WorkingMemoryAction; -import org.drools.core.util.KeyStoreHelper; +import org.drools.core.impl.StatefulKnowledgeSessionImpl.WorkingMemoryReteAssertAction; +import org.drools.core.impl.StatefulKnowledgeSessionImpl.WorkingMemoryReteExpireAction; import org.drools.core.marshalling.impl.ProtobufMessages.Header; import org.drools.core.marshalling.impl.ProtobufMessages.Header.StrategyIndex.Builder; import org.drools.core.reteoo.LeftTuple; import org.drools.core.reteoo.PropagationQueuingNode.PropagateAction; import org.drools.core.rule.SlidingTimeWindow.BehaviorExpireWMAction; +import org.drools.core.util.Drools; +import org.drools.core.util.KeyStoreHelper; import org.kie.api.marshalling.ObjectMarshallingStrategy; import org.kie.api.marshalling.ObjectMarshallingStrategy.Context; -import com.google.protobuf.ByteString; -import com.google.protobuf.ByteString.Output; -import com.google.protobuf.ExtensionRegistry; -import com.google.protobuf.Message; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.InvalidKeyException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import java.util.Map.Entry; public class PersisterHelper { public static WorkingMemoryAction readWorkingMemoryAction(MarshallerReaderContext context) throws IOException, @@ -189,11 +189,10 @@ public static ProtobufMessages.Activation createActivation(final String packageN public static void writeToStreamWithHeader( MarshallerWriteContext context, Message payload ) throws IOException { ProtobufMessages.Header.Builder _header = ProtobufMessages.Header.newBuilder(); - // need to automate this version numbering somehow _header.setVersion( ProtobufMessages.Version.newBuilder() - .setVersionMajor( 5 ) - .setVersionMinor( 4 ) - .setVersionRevision( 0 ) + .setVersionMajor( Drools.getMajorVersion() ) + .setVersionMinor( Drools.getMinorVersion() ) + .setVersionRevision( Drools.getRevisionVersion() ) .build() ); writeStrategiesIndex( context, _header ); From 493b9f29896c72e25b4b2c1b11f7d8c55256e736 Mon Sep 17 00:00:00 2001 From: Maciej Swiderski Date: Thu, 7 Aug 2014 17:13:11 +0200 Subject: [PATCH 70/76] JBPM-4400: Problems using persistences with human tasks in OSGi - added missing import package of org.hibernate (cherry picked from commit a73ba51729e9964f1347c63ae8ce1185e460b183) --- drools-persistence-jpa/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/drools-persistence-jpa/pom.xml b/drools-persistence-jpa/pom.xml index a0bf891791f..b5d9833f883 100644 --- a/drools-persistence-jpa/pom.xml +++ b/drools-persistence-jpa/pom.xml @@ -42,6 +42,7 @@ org.drools.container.spring.beans.persistence;resolution:=optional, org.drools.core.marshalling.impl;resolution:=optional, org.hibernate.proxy;resolution:=optional, + org.hibernate;resolution:=optional, org.kie.spring.persistence;resolution:=optional, * From 7e44d6f759e119cca7157f535a03efb6d7e15a1f Mon Sep 17 00:00:00 2001 From: mariofusco Date: Thu, 4 Sep 2014 20:34:43 +0200 Subject: [PATCH 71/76] [BZ-1138420] fix very inefficient algorithm to read a byte array from an InputStream (cherry picked from commit ef77b58dc743140ee4240892e7c161cb3d72d759) Conflicts: drools-core/src/main/java/org/drools/core/util/IoUtils.java --- .../java/org/drools/core/util/IoUtils.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drools-core/src/main/java/org/drools/core/util/IoUtils.java b/drools-core/src/main/java/org/drools/core/util/IoUtils.java index 09337a0e5c1..0520b8b0a42 100644 --- a/drools-core/src/main/java/org/drools/core/util/IoUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/IoUtils.java @@ -8,9 +8,9 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.net.DatagramSocket; import java.net.ServerSocket; import java.nio.channels.FileChannel; @@ -182,19 +182,23 @@ private static File[] safeListFiles(final File file) { } } - public static byte[] readBytesFromInputStream(InputStream is) throws IOException { - byte[] resultBuff = new byte[0]; - byte[] buff = new byte[2048]; - int k = -1; - while ((k = is.read(buff, 0, buff.length)) > -1) { - byte[] tbuff = new byte[resultBuff.length + k]; - System.arraycopy(resultBuff, 0, tbuff, 0, resultBuff.length); - System.arraycopy(buff, 0, tbuff, resultBuff.length, k); - resultBuff = tbuff; + public static byte[] readBytesFromInputStream(InputStream input) throws IOException { + int length = input.available(); + byte[] buffer = new byte[Math.max(length, 8192)]; + ByteArrayOutputStream output = new ByteArrayOutputStream(buffer.length); + + if (length > 0) { + int n = input.read(buffer); + output.write(buffer, 0, n); } - return resultBuff; - } + int n = 0; + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + } + return output.toByteArray(); + } + public static byte[] readBytesFromZipEntry(File file, ZipEntry entry) throws IOException { if ( entry == null ) { return null; @@ -323,4 +327,4 @@ public static String asSystemSpecificPath(String urlPath, int colonIndex) { return urlPath.substring( colonIndex + 1 ); } } -} \ No newline at end of file +} From cbc32017bb20ec618b7bec800bd617a48ab91933 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Fri, 5 Sep 2014 09:47:55 +0200 Subject: [PATCH 72/76] [BZ-1138420] fix very inefficient algorithm to read a byte array from an InputStream --- drools-core/src/main/java/org/drools/core/util/IoUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drools-core/src/main/java/org/drools/core/util/IoUtils.java b/drools-core/src/main/java/org/drools/core/util/IoUtils.java index 0520b8b0a42..21a8b2bdc22 100644 --- a/drools-core/src/main/java/org/drools/core/util/IoUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/IoUtils.java @@ -8,9 +8,9 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.DatagramSocket; import java.net.ServerSocket; import java.nio.channels.FileChannel; From f4390778a403987836d4b72127a00a7ff3efe2bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0iller?= Date: Wed, 10 Sep 2014 15:46:45 +0200 Subject: [PATCH 73/76] Bugfix for DROOLS-354 and DROOLS-540 on Windows Backport of the bugfix from master branch to Drools 6.1.x branch --- .../drools/compiler/kie/builder/impl/ClasspathKieProject.java | 1 + 1 file changed, 1 insertion(+) diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java index 134607e0c34..b84df77cffd 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java @@ -221,6 +221,7 @@ private static String getPomPropertiesFromZipFile(String rootPath) { File actualZipFile = new File( rootPath ); if ( !actualZipFile.exists() ) { log.error( "Unable to load pom.properties from" + rootPath + " as jarPath cannot be found\n" + rootPath ); + return null; } ZipFile zipFile = null; From d0c76dd1042ad790db2a122822f940d64286c893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0iller?= Date: Wed, 10 Sep 2014 15:48:29 +0200 Subject: [PATCH 74/76] Bugfix for DROOLS-354 and DROOLS-540 on Windows Backport of the bugfix from master branch to Drools 6.1.x branch --- drools-core/src/main/java/org/drools/core/util/IoUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drools-core/src/main/java/org/drools/core/util/IoUtils.java b/drools-core/src/main/java/org/drools/core/util/IoUtils.java index 21a8b2bdc22..96f43752bb4 100644 --- a/drools-core/src/main/java/org/drools/core/util/IoUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/IoUtils.java @@ -321,8 +321,10 @@ public static boolean areByteArraysEqual(byte[] b1, public static String asSystemSpecificPath(String urlPath, int colonIndex) { String ic = urlPath.substring( Math.max( 0, colonIndex - 2 ), colonIndex + 1 ); - if ( ic.matches( "\\/[A-Z]:" ) ) { + if ( ic.matches( "\\/[A-Z]:" ) ) { return urlPath.substring( colonIndex - 2 ); + } else if ( ic.matches( "[A-Z]:" ) ) { + return urlPath.substring( colonIndex - 1 ); } else { return urlPath.substring( colonIndex + 1 ); } From 3e53f5e52200abba7d193aa9ea4381d4f561a153 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Fri, 12 Sep 2014 13:25:13 +0200 Subject: [PATCH 75/76] [DROOLS-596] remove tuples from the right memory when gc'ing them (cherry picked from commit 6071eb701bb3f913e55a6121f442480c4e51fde5) --- .../java/org/drools/core/phreak/RuleExecutor.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java index 3c3b0f5e899..3a208b9ae85 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java +++ b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java @@ -26,7 +26,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Comparator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -62,12 +61,20 @@ public synchronized void gcStreamQueue() { if (tupleEntry.getLeftTuple() != null) { LeftTuple leftTuple = tupleEntry.getLeftTuple(); if (leftTuple.getMemory() != null) { - leftTuple.getMemory().remove(leftTuple); + if (tupleEntry.getNodeMemory() instanceof BetaMemory) { + ((BetaMemory)tupleEntry.getNodeMemory()).getLeftTupleMemory().remove(leftTuple); + } else { + leftTuple.getMemory().remove(leftTuple); + } } } else { RightTuple rightTuple = tupleEntry.getRightTuple(); if (rightTuple.getMemory() != null) { - rightTuple.getMemory().remove(rightTuple); + if (tupleEntry.getNodeMemory() instanceof BetaMemory) { + ((BetaMemory) tupleEntry.getNodeMemory()).getRightTupleMemory().remove(rightTuple); + } else { + rightTuple.getMemory().remove(rightTuple); + } } } } From ea0e2f7a8fd31f3edf48bdc31ac4e673f21bead4 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Tue, 9 Sep 2014 17:18:53 +0200 Subject: [PATCH 76/76] [DROOLS-594] fix path mask initialization when a segment as an accumulate as last node (cherry picked from commit e1c0efabeea4b768fc683466ad65ce48c4be6246) --- .../integrationtests/AccumulateTest.java | 79 ++++++++++++++----- .../core/reteoo/AbstractTerminalNode.java | 3 +- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/AccumulateTest.java b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/AccumulateTest.java index 6606c29f603..28764f309e0 100644 --- a/drools-compiler/src/test/java/org/drools/compiler/integrationtests/AccumulateTest.java +++ b/drools-compiler/src/test/java/org/drools/compiler/integrationtests/AccumulateTest.java @@ -1,25 +1,5 @@ package org.drools.compiler.integrationtests; -import static org.hamcrest.CoreMatchers.is; -import static org.mockito.Mockito.*; -import static org.junit.Assert.assertThat; - -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.Serializable; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; - import org.drools.compiler.Cheese; import org.drools.compiler.Cheesery; import org.drools.compiler.CommonTestMethodBase; @@ -59,9 +39,30 @@ import org.kie.internal.builder.KnowledgeBuilderFactory; import org.kie.internal.io.ResourceFactory; import org.kie.internal.runtime.StatefulKnowledgeSession; +import org.kie.internal.utils.KieHelper; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Serializable; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + public class AccumulateTest extends CommonTestMethodBase { @Test (timeout = 10000) @@ -2613,6 +2614,42 @@ public boolean supportsReverse() { public Class getResultType() { return Number.class; } - } + } + @Test + public void testAccumulateWithSharedNode() throws Exception { + // DROOLS-594 + String drl = + "rule A when" + + " Double() " + + "then " + + "end " + + "rule B " + + "when " + + " Double() " + + " String() " + + " $list : java.util.List( this not contains \"XX\" ) " + + " $sum : Double( ) from accumulate ( $i : Integer(), " + + " sum( $i ) ) " + + "then " + + " $list.add( \"XX\" );\n" + + " update( $list );\n" + + " System.out.println(\"FIRED\");\n" + + "end "; + + KieHelper helper = new KieHelper(); + helper.addContent( drl, ResourceType.DRL ); + KieSession ksession = helper.build().newKieSession(); + + List list = new java.util.ArrayList(); + ksession.insert(list); + + ksession.insert(42.0); + ksession.insert(9000); + ksession.insert("a"); + ksession.insert("b"); + ksession.fireAllRules(); + + assertEquals(1, list.size()); + } } diff --git a/drools-core/src/main/java/org/drools/core/reteoo/AbstractTerminalNode.java b/drools-core/src/main/java/org/drools/core/reteoo/AbstractTerminalNode.java index d9218eb1dc3..73156043c9e 100644 --- a/drools-core/src/main/java/org/drools/core/reteoo/AbstractTerminalNode.java +++ b/drools-core/src/main/java/org/drools/core/reteoo/AbstractTerminalNode.java @@ -149,9 +149,9 @@ public static void initPathMemory(PathMemory pmem, LeftTupleSource tupleSource, } if ( updateAllLinkedTest && updateBitInNewSegment && NodeTypeEnums.isBetaNode( tupleSource )) { - updateBitInNewSegment = false; BetaNode bn = ( BetaNode) tupleSource; if ( bn.isRightInputIsRiaNode() ) { + updateBitInNewSegment = false; // only ria's without reactive subnetworks can be disabled and thus need checking // The getNodeMemory will7 call this method recursive for sub networks it reaches RiaNodeMemory rnmem = ( RiaNodeMemory ) wm.getNodeMemory((MemoryFactory) bn.getRightInput()); @@ -160,6 +160,7 @@ public static void initPathMemory(PathMemory pmem, LeftTupleSource tupleSource, } } else if ( ( !(NodeTypeEnums.NotNode == bn.getType() && !((NotNode)bn).isEmptyBetaConstraints()) && NodeTypeEnums.AccumulateNode != bn.getType()) ) { + updateBitInNewSegment = false; // non empty not nodes and accumulates can never be disabled and thus don't need checking allLinkedTestMask = allLinkedTestMask | 1; }