/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.compiler.integrationtests; import java.util.ArrayList; import java.util.List; import org.drools.core.base.ClassObjectType; import org.drools.core.common.AgendaItem; import org.drools.core.common.InternalAgenda; import org.drools.core.common.InternalAgendaGroup; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.MemoryFactory; import org.drools.core.impl.KnowledgeBaseImpl; import org.drools.core.impl.StatefulKnowledgeSessionImpl; import org.drools.core.phreak.RuleAgendaItem; import org.drools.core.phreak.RuleExecutor; import org.drools.core.phreak.SegmentUtilities; import org.drools.core.reteoo.BetaMemory; import org.drools.core.reteoo.EvalConditionNode; import org.drools.core.reteoo.ExistsNode; import org.drools.core.reteoo.JoinNode; import org.drools.core.reteoo.LeftInputAdapterNode; import org.drools.core.reteoo.LeftInputAdapterNode.LiaNodeMemory; import org.drools.core.reteoo.NotNode; import org.drools.core.reteoo.ObjectTypeNode; import org.drools.core.reteoo.PathMemory; import org.drools.core.reteoo.RightInputAdapterNode; import org.drools.core.reteoo.RuleTerminalNode; import org.drools.core.reteoo.SegmentMemory; import org.junit.Test; import org.kie.api.io.ResourceType; import org.kie.api.runtime.rule.FactHandle; 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 static org.junit.Assert.*; public class LinkingTest { public static class A { private int value; public A() { } public A(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } public static class B { private int value; public B() { } public B(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } public static class C { private int value; public C() { } public C(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } public static class D { private int value; public D() { } public D(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } public static class E { private int value; public E() { } public E(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } public static class F { private int value; public F() { } public F(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } public static class G { private int value; public G() { } public G(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } @Test public void testSubNetworkSharing() throws Exception { // Checks the network is correctly formed, with sharing String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " B() \n"; str += " C() \n"; str += " D() \n"; str += "then \n"; str += "end \n"; str += "rule rule2 when \n"; str += " A() \n"; str += " exists( B() and C() ) \n"; str += " D() \n"; str += "then \n"; str += "end \n"; str += "rule rule3 when \n"; str += " A() \n"; str += " exists( B() and C() and D() ) \n"; str += " E() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; assertEquals( 3, liaNode.getSinkPropagator().size() ); ExistsNode existsNode2 = ( ExistsNode) liaNode.getSinkPropagator().getSinks()[1]; ExistsNode existsNode3 = ( ExistsNode) liaNode.getSinkPropagator().getSinks()[2]; JoinNode joinNodeB = ( JoinNode) liaNode.getSinkPropagator().getSinks()[0]; assertSame( joinNodeB.getRightInput(), getObjectTypeNode(kbase, B.class ) ); JoinNode joinNodeC = ( JoinNode) joinNodeB.getSinkPropagator().getSinks()[0]; assertSame( joinNodeC.getRightInput(), getObjectTypeNode(kbase, C.class ) ); assertEquals( 2, joinNodeC.getSinkPropagator().size() ); JoinNode joinNodeD = ( JoinNode) joinNodeC.getSinkPropagator().getSinks()[0]; assertSame( joinNodeD.getRightInput(), getObjectTypeNode(kbase, D.class ) ); assertEquals( 2, joinNodeD.getSinkPropagator().size() ); assertSame( existsNode2, (( RightInputAdapterNode) joinNodeC.getSinkPropagator().getSinks()[1]).getObjectSinkPropagator().getSinks()[0] ); assertSame( existsNode3, (( RightInputAdapterNode) joinNodeD.getSinkPropagator().getSinks()[1]).getObjectSinkPropagator().getSinks()[0] ); } @Test public void testSubNetworkSharingMemories() throws Exception { // checks the memory sharing works, and linking, uses the already checked network from testSubNetworkSharing String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " B() \n"; str += " C() \n"; str += " D() \n"; str += "then \n"; str += "end \n"; str += "rule rule2 when \n"; str += " A() \n"; str += " exists( B() and C() ) \n"; str += " D() \n"; str += "then \n"; str += "end \n"; str += "rule rule3 when \n"; str += " A() \n"; str += " exists( B() and C() and D() ) \n"; str += " E() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNodeA = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; ExistsNode existsNode2 = ( ExistsNode) liaNodeA.getSinkPropagator().getSinks()[1]; ExistsNode existsNode3 = ( ExistsNode) liaNodeA.getSinkPropagator().getSinks()[2]; JoinNode joinNodeB = ( JoinNode) liaNodeA.getSinkPropagator().getSinks()[0]; JoinNode joinNodeC = ( JoinNode) joinNodeB.getSinkPropagator().getSinks()[0]; JoinNode joinNodeD1 = ( JoinNode) joinNodeC.getSinkPropagator().getSinks()[0]; JoinNode joinNodeD2 = ( JoinNode) existsNode2.getSinkPropagator().getSinks()[0]; JoinNode joinNodeE = ( JoinNode) existsNode3.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn1 = ( RuleTerminalNode ) joinNodeD1.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn2 = ( RuleTerminalNode ) joinNodeD2.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn3 = ( RuleTerminalNode ) joinNodeE.getSinkPropagator().getSinks()[0]; FactHandle fha = wm.insert( new A() ); wm.insert( new B() ); wm.insert( new C() ); wm.insert( new D() ); wm.flushPropagations(); BetaMemory bm = null; LiaNodeMemory liam = ( LiaNodeMemory ) wm.getNodeMemory( liaNodeA ); BetaMemory bm1 = ( BetaMemory ) wm.getNodeMemory( joinNodeB ); BetaMemory bm2 = ( BetaMemory ) wm.getNodeMemory( joinNodeC ); BetaMemory bm3 = ( BetaMemory ) wm.getNodeMemory( joinNodeD1 ); assertEquals(1, liam.getNodePosMaskBit() ); assertEquals(1, bm1.getNodePosMaskBit() ); assertEquals(2, bm2.getNodePosMaskBit() ); assertEquals(1, bm3.getNodePosMaskBit() ); assertNotSame( liam.getSegmentMemory(), bm1.getSegmentMemory() ); assertSame( bm1.getSegmentMemory(), bm2.getSegmentMemory() ); assertNotSame( bm2.getSegmentMemory(), bm3.getSegmentMemory() ); BetaMemory bm4 = ( BetaMemory ) wm.getNodeMemory( existsNode2 ); BetaMemory bm5 = ( BetaMemory ) wm.getNodeMemory( joinNodeD2 ); assertEquals(1, bm4.getNodePosMaskBit() ); assertEquals(2, bm5.getNodePosMaskBit() ); assertSame( bm4.getSegmentMemory(), bm5.getSegmentMemory() ); PathMemory rs1 = (PathMemory) wm.getNodeMemory( rtn1 ); PathMemory rs2 = (PathMemory) wm.getNodeMemory( rtn2 ); PathMemory rs3 = (PathMemory) wm.getNodeMemory( rtn3 ); assertTrue( rs1.isRuleLinked() ); assertTrue( rs2.isRuleLinked() ); assertFalse( rs3.isRuleLinked() ); // no E yet wm.insert( new E() ); wm.flushPropagations(); BetaMemory bm6 = ( BetaMemory ) wm.getNodeMemory( existsNode3 ); BetaMemory bm7 = ( BetaMemory ) wm.getNodeMemory( joinNodeE ); assertEquals(1, bm6.getNodePosMaskBit() ); assertEquals(2, bm7.getNodePosMaskBit() ); assertSame( bm6.getSegmentMemory(), bm7.getSegmentMemory() ); assertTrue( rs1.isRuleLinked() ); assertTrue( rs2.isRuleLinked() ); assertTrue( rs3.isRuleLinked() ); wm.retract( fha ); wm.fireAllRules(); // need to have rules evalulated, for unlinking to happen assertFalse( rs1.isRuleLinked() ); assertFalse( rs2.isRuleLinked() ); assertFalse( rs3.isRuleLinked() ); } @Test public void testSubNetworkRiaLinking() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " B() \n"; str += " exists( C() and D() ) \n"; str += " E() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; assertEquals( 1, liaNode.getSinkPropagator().size() ); JoinNode bNode = ( JoinNode) liaNode.getSinkPropagator().getSinks()[0]; assertEquals( 2, bNode.getSinkPropagator().size() ); ExistsNode exists1n = ( ExistsNode) bNode.getSinkPropagator().getSinks()[1]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; JoinNode dNode = ( JoinNode) cNode.getSinkPropagator().getSinks()[0]; assertEquals( 1, dNode.getSinkPropagator().size() ); RightInputAdapterNode riaNode1 = ( RightInputAdapterNode ) dNode.getSinkPropagator().getSinks()[0]; JoinNode eNode = ( JoinNode ) exists1n.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn = ( RuleTerminalNode ) eNode.getSinkPropagator().getSinks()[0]; SegmentUtilities.createSegmentMemory( exists1n, wm ); BetaMemory existsBm = ( BetaMemory ) wm.getNodeMemory( exists1n ); assertEquals( 0, existsBm.getSegmentMemory().getLinkedNodeMask() ); FactHandle fhc = wm.insert( new C() ); FactHandle fhd = wm.insert( new D() ); wm.flushPropagations(); assertEquals( 1, existsBm.getSegmentMemory().getLinkedNodeMask() ); // exists is start of new segment wm.retract( fhd ); wm.flushPropagations(); assertEquals( 0, existsBm.getSegmentMemory().getLinkedNodeMask() ); PathMemory rs = (PathMemory) wm.getNodeMemory( rtn ); assertFalse( rs.isRuleLinked() ); wm.insert( new A() ); wm.flushPropagations(); assertFalse(rs.isRuleLinked()); wm.insert(new B()); wm.flushPropagations(); assertFalse(rs.isRuleLinked()); wm.insert(new E()); wm.flushPropagations(); assertFalse( rs.isRuleLinked() ); wm.insert( new D() ); wm.flushPropagations(); assertTrue( rs.isRuleLinked() ); wm.retract( fhc ); wm.flushPropagations(); assertFalse( rs.isRuleLinked() ); wm.insert( new C() ); wm.flushPropagations(); assertTrue( rs.isRuleLinked() ); } @Test public void testNonReactiveSubNetworkInShareMasks() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " exists( B() and C() ) \n"; str += " exists( eval(1==1) ) \n"; str += " D() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; assertEquals( 2, liaNode.getSinkPropagator().size() ); JoinNode bNode = ( JoinNode) liaNode.getSinkPropagator().getSinks()[0]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; ExistsNode exists1n = ( ExistsNode) liaNode.getSinkPropagator().getSinks()[1]; EvalConditionNode evalNode = ( EvalConditionNode) exists1n.getSinkPropagator().getSinks()[0]; ExistsNode exists2n = ( ExistsNode) exists1n.getSinkPropagator().getSinks()[1]; JoinNode dNode = ( JoinNode) exists2n.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn = ( RuleTerminalNode) dNode.getSinkPropagator().getSinks()[0]; wm.insert( new A() ); PathMemory pmem = ( PathMemory ) wm.getNodeMemory(rtn); assertEquals( 3, pmem.getSegmentMemories().length ); assertEquals( 7, pmem.getAllLinkedMaskTest() ); // D is in the exists segment BetaMemory bm = ( BetaMemory ) wm.getNodeMemory(dNode); assertNull(bm.getSegmentMemory()); // check lazy initialization wm.insert(new D()); wm.flushPropagations(); assertEquals(2, bm.getSegmentMemory().getAllLinkedMaskTest()); // only D can be linked in } @Test public void testNonReactiveSubNetworkOwnSegmentMasks() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " exists( B() and C() ) \n"; str += " exists( eval(1==1) ) \n"; str += " D() \n"; str += "then \n"; str += "end \n"; str += "rule rule2 when \n"; str += " A() \n"; str += " exists( B() and C() ) \n"; str += " exists( eval(1==1) ) \n"; str += " E() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; assertEquals( 2, liaNode.getSinkPropagator().size() ); JoinNode bNode = ( JoinNode) liaNode.getSinkPropagator().getSinks()[0]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; ExistsNode exists1n = ( ExistsNode) liaNode.getSinkPropagator().getSinks()[1]; EvalConditionNode evalNode = ( EvalConditionNode) exists1n.getSinkPropagator().getSinks()[0]; ExistsNode exists2n = ( ExistsNode) exists1n.getSinkPropagator().getSinks()[1]; JoinNode dNode = ( JoinNode) exists2n.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn = ( RuleTerminalNode) dNode.getSinkPropagator().getSinks()[0]; wm.insert( new A() ); PathMemory pmem = ( PathMemory ) wm.getNodeMemory(rtn); assertEquals( 4, pmem.getSegmentMemories().length ); assertEquals( 11, pmem.getAllLinkedMaskTest() ); // the exists eval segment does not need to be linked in RightInputAdapterNode.RiaNodeMemory riaMem = (RightInputAdapterNode.RiaNodeMemory) wm.getNodeMemory((MemoryFactory) exists1n.getRightInput()); assertEquals( 2, riaMem.getRiaPathMemory().getAllLinkedMaskTest() ); // second segment must be linked in wm.insert( new B() ); wm.insert( new C() ); assertEquals( 2, riaMem.getRiaPathMemory().getSegmentMemories().length ); riaMem = (RightInputAdapterNode.RiaNodeMemory) wm.getNodeMemory((MemoryFactory) exists2n.getRightInput()); assertEquals( 0, riaMem.getRiaPathMemory().getAllLinkedMaskTest() ); // no segments to be linked in } @Test public void testNestedSubNetwork() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " B() \n"; str += " exists( C() and D() and exists( E() and F() ) ) \n"; str += " G() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; assertEquals( 1, liaNode.getSinkPropagator().size() ); JoinNode bNode = ( JoinNode) liaNode.getSinkPropagator().getSinks()[0]; assertEquals( 2, bNode.getSinkPropagator().size() ); ExistsNode exists1n = ( ExistsNode) bNode.getSinkPropagator().getSinks()[1]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; JoinNode dNode = ( JoinNode) cNode.getSinkPropagator().getSinks()[0]; assertEquals( 2, dNode.getSinkPropagator().size() ); ExistsNode exists2n = ( ExistsNode) dNode.getSinkPropagator().getSinks()[1]; JoinNode eNode = ( JoinNode) dNode.getSinkPropagator().getSinks()[0]; JoinNode fNode = ( JoinNode) eNode.getSinkPropagator().getSinks()[0]; RightInputAdapterNode riaNode2 = ( RightInputAdapterNode ) fNode.getSinkPropagator().getSinks()[0]; assertEquals( exists2n, riaNode2.getObjectSinkPropagator().getSinks()[0] ); RightInputAdapterNode riaNode1 = ( RightInputAdapterNode ) exists2n.getSinkPropagator().getSinks()[0]; assertEquals( exists1n, riaNode1.getObjectSinkPropagator().getSinks()[0] ); JoinNode gNode = ( JoinNode) exists1n.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn = ( RuleTerminalNode) gNode.getSinkPropagator().getSinks()[0]; wm.insert( new A() ); wm.insert( new B() ); wm.insert( new C() ); wm.insert( new D() ); wm.insert( new F() ); wm.insert( new G() ); PathMemory rs = (PathMemory) wm.getNodeMemory( rtn ); assertFalse( rs.isRuleLinked() ); FactHandle fhE1 = wm.insert( new E() ); FactHandle fhE2 = wm.insert( new E() ); wm.flushPropagations(); assertTrue( rs.isRuleLinked() ); wm.retract( fhE1 ); wm.flushPropagations(); assertTrue( rs.isRuleLinked() ); wm.retract( fhE2 ); wm.flushPropagations(); assertFalse( rs.isRuleLinked() ); } @Test public void testNestedSubNetworkMasks() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " B() \n"; str += " exists( C() and D() and exists( E() and F() ) ) \n"; str += " G() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; JoinNode bNode = ( JoinNode) liaNode.getSinkPropagator().getSinks()[0]; ExistsNode exists1n = ( ExistsNode) bNode.getSinkPropagator().getSinks()[1]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; JoinNode dNode = ( JoinNode) cNode.getSinkPropagator().getSinks()[0]; ExistsNode exists2n = ( ExistsNode) dNode.getSinkPropagator().getSinks()[1]; JoinNode eNode = ( JoinNode) dNode.getSinkPropagator().getSinks()[0]; JoinNode fNode = ( JoinNode) eNode.getSinkPropagator().getSinks()[0]; RightInputAdapterNode riaNode2 = ( RightInputAdapterNode ) fNode.getSinkPropagator().getSinks()[0]; RightInputAdapterNode riaNode1 = ( RightInputAdapterNode ) exists2n.getSinkPropagator().getSinks()[0]; JoinNode gNode = ( JoinNode) exists1n.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn = ( RuleTerminalNode) gNode.getSinkPropagator().getSinks()[0]; wm.insert( new A() ); wm.insert( new B() ); wm.insert( new C() ); wm.insert( new D() ); wm.insert( new G() ); wm.flushPropagations(); LiaNodeMemory liaMem = ( LiaNodeMemory ) wm.getNodeMemory( liaNode ); BetaMemory bMem = ( BetaMemory ) wm.getNodeMemory( bNode ); BetaMemory exists1Mem = ( BetaMemory ) wm.getNodeMemory( exists1n ); BetaMemory cMem = ( BetaMemory ) wm.getNodeMemory( cNode ); BetaMemory dMem = ( BetaMemory ) wm.getNodeMemory( dNode ); BetaMemory exists2Mem = ( BetaMemory ) wm.getNodeMemory( exists2n ); BetaMemory eMem = ( BetaMemory ) wm.getNodeMemory( eNode ); BetaMemory fMem = ( BetaMemory ) wm.getNodeMemory( fNode ); BetaMemory gMem = ( BetaMemory ) wm.getNodeMemory( gNode ); RightInputAdapterNode.RiaNodeMemory riaMem1 = (RightInputAdapterNode.RiaNodeMemory) wm.getNodeMemory( riaNode1 ); RightInputAdapterNode.RiaNodeMemory riaMem2 = (RightInputAdapterNode.RiaNodeMemory) wm.getNodeMemory( riaNode2 ); PathMemory rs = (PathMemory) wm.getNodeMemory( rtn ); assertFalse( rs.isRuleLinked() ); //E and F are not inserted yet, so rule is unlinked //--- // assert a and b in same segment assertSame( liaMem.getSegmentMemory(), bMem.getSegmentMemory() ); // exists1 and b not in same segment assertNotSame( bMem.getSegmentMemory(), exists1Mem.getSegmentMemory() ); // exists1 and b are in same segment assertSame( exists1Mem.getSegmentMemory(), gMem.getSegmentMemory() ); // check segment masks assertEquals( 2, rs.getSegmentMemories().length ); assertEquals( 3, rs.getAllLinkedMaskTest() ); assertEquals( 1, rs.getLinkedSegmentMask() ); assertEquals( 3, liaMem.getSegmentMemory().getAllLinkedMaskTest() ); assertEquals( 1, liaMem.getNodePosMaskBit() ); assertEquals( 2, bMem.getNodePosMaskBit() ); assertEquals( 3, exists1Mem.getSegmentMemory().getAllLinkedMaskTest() ); assertEquals( 1, exists1Mem.getNodePosMaskBit() ); assertEquals( 2, gMem.getNodePosMaskBit() ); // assert c, d are in the same segment, and that this is the only segment in ria1 memory assertSame( dMem.getSegmentMemory(), cMem.getSegmentMemory() ); // assert d and exists are not in the same segment assertNotSame( exists2Mem.getSegmentMemory(), dMem.getSegmentMemory() ); assertEquals( 3, riaMem1.getRiaPathMemory().getSegmentMemories().length ); assertEquals( null, riaMem1.getRiaPathMemory().getSegmentMemories()[0] ); // only needs to know about segments in the subnetwork assertEquals( dMem.getSegmentMemory(), riaMem1.getRiaPathMemory().getSegmentMemories()[1] ); assertEquals( 1, dMem.getSegmentMemory().getPathMemories().size() ); assertSame( riaMem1.getRiaPathMemory(), cMem.getSegmentMemory().getPathMemories().get(0) ); assertEquals( 3, cMem.getSegmentMemory().getAllLinkedMaskTest() ); assertEquals( 3, cMem.getSegmentMemory().getLinkedNodeMask() ); // E and F is not yet inserted, so bit is not set assertEquals( 1, cMem.getNodePosMaskBit() ); assertEquals( 2, dMem.getNodePosMaskBit() ); assertEquals( 0, exists2Mem.getNodePosMaskBit() ); FactHandle fhE1 = wm.insert( new E() ); // insert to lazy initialize exists2Mem segment FactHandle fhF1 = wm.insert( new F() ); wm.flushPropagations(); assertEquals( 1, exists2Mem.getNodePosMaskBit() ); assertEquals( 6, riaMem1.getRiaPathMemory().getAllLinkedMaskTest() ); // only cares that the segment for c, E and exists1 are set, ignores the outer first segment assertEquals( 6, riaMem1.getRiaPathMemory().getLinkedSegmentMask() ); // E and F are inerted, so 6 wm.delete(fhE1); wm.delete(fhF1); wm.flushPropagations(); assertEquals(2, riaMem1.getRiaPathMemory().getLinkedSegmentMask()); // E deleted // assert e, f are in the same segment, and that this is the only segment in ria2 memory assertNotNull( null, eMem.getSegmentMemory() ); //subnetworks are recursively created, so segment already exists assertSame( fMem.getSegmentMemory(), eMem.getSegmentMemory() ); assertEquals( 3, riaMem2.getRiaPathMemory().getSegmentMemories().length ); assertEquals( null, riaMem2.getRiaPathMemory().getSegmentMemories()[0] ); // only needs to know about segments in the subnetwork assertEquals( null, riaMem2.getRiaPathMemory().getSegmentMemories()[1] ); // only needs to know about segments in the subnetwork assertEquals( fMem.getSegmentMemory(), riaMem2.getRiaPathMemory().getSegmentMemories()[2] ); assertSame( riaMem2.getRiaPathMemory(), eMem.getSegmentMemory().getPathMemories().get(0) ); assertEquals( 3, eMem.getSegmentMemory().getAllLinkedMaskTest() ); assertEquals( 0, eMem.getSegmentMemory().getLinkedNodeMask() ); assertEquals( 4, riaMem2.getRiaPathMemory().getAllLinkedMaskTest() ); // only cares that the segment for e and f set, ignores the outer two segment assertEquals( 0, riaMem2.getRiaPathMemory().getLinkedSegmentMask() ); // E and F is not yet inserted, so bit is not set fhE1 = wm.insert( new E() ); wm.insert( new F() ); wm.flushPropagations(); assertTrue( rs.isRuleLinked() ); //E and F are now inserted yet, so rule is linked assertEquals( 3, rs.getAllLinkedMaskTest() ); assertEquals( 3, rs.getLinkedSegmentMask() ); // retest bits assertEquals( 3, cMem.getSegmentMemory().getAllLinkedMaskTest() ); assertEquals( 3, cMem.getSegmentMemory().getLinkedNodeMask() ); assertEquals( 6, riaMem1.getRiaPathMemory().getAllLinkedMaskTest() ); assertEquals( 6, riaMem1.getRiaPathMemory().getLinkedSegmentMask() ); assertEquals( 3, eMem.getSegmentMemory().getAllLinkedMaskTest() ); assertEquals( 3, eMem.getSegmentMemory().getLinkedNodeMask() ); assertEquals( 4, riaMem2.getRiaPathMemory().getAllLinkedMaskTest() ); assertEquals( 4, riaMem2.getRiaPathMemory().getLinkedSegmentMask() ); wm.delete( fhE1); wm.flushPropagations(); // retest bits assertFalse( rs.isRuleLinked() ); assertEquals( 3, cMem.getSegmentMemory().getLinkedNodeMask() ); assertEquals( 2, riaMem1.getRiaPathMemory().getLinkedSegmentMask() ); assertEquals( 2, eMem.getSegmentMemory().getLinkedNodeMask() ); assertEquals( 0, riaMem2.getRiaPathMemory().getLinkedSegmentMask() ); } @Test public void testJoinNodes() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " $b : B() \n"; str += " $c : C() \n"; str += "then \n"; str += " list.add( $a.getValue() + \":\"+ $b.getValue() + \":\" + $c.getValue() ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode aotn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode botn = getObjectTypeNode(kbase, B.class ); ObjectTypeNode cotn = getObjectTypeNode(kbase, C.class ); InternalWorkingMemory wm = (InternalWorkingMemory)kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); wm.setGlobal( "list", list ); for ( int i = 0; i < 3; i++ ) { wm.insert( new A(i) ); } for ( int i = 0; i < 3; i++ ) { wm.insert( new B(i) ); } for ( int i = 0; i < 29; i++ ) { wm.insert( new C(i) ); } wm.flushPropagations(); LeftInputAdapterNode aNode = (LeftInputAdapterNode) aotn.getObjectSinkPropagator().getSinks()[0]; JoinNode bNode = ( JoinNode) aNode.getSinkPropagator().getSinks()[0]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; LiaNodeMemory amem = ( LiaNodeMemory ) wm.getNodeMemory( aNode ); BetaMemory bmem = ( BetaMemory ) wm.getNodeMemory( bNode ); BetaMemory cmem = ( BetaMemory ) wm.getNodeMemory( cNode ); // amem.getSegmentMemory().getStagedLeftTuples().insertSize() == 3 assertNotNull( amem.getSegmentMemory().getStagedLeftTuples().getInsertFirst() ); assertNotNull( amem.getSegmentMemory().getStagedLeftTuples().getInsertFirst().getStagedNext() ); assertNotNull( amem.getSegmentMemory().getStagedLeftTuples().getInsertFirst().getStagedNext().getStagedNext() ); assertNull( amem.getSegmentMemory().getStagedLeftTuples().getInsertFirst().getStagedNext().getStagedNext().getStagedNext() ); //assertEquals( 3, bmem.getStagedRightTuples().insertSize() ); assertNotNull( bmem.getStagedRightTuples().getInsertFirst() ); assertNotNull( bmem.getStagedRightTuples().getInsertFirst().getStagedNext() ); assertNotNull( bmem.getStagedRightTuples().getInsertFirst().getStagedNext().getStagedNext() ); assertNull( bmem.getStagedRightTuples().getInsertFirst().getStagedNext().getStagedNext().getStagedNext() ); wm.fireAllRules(); assertNull( amem.getSegmentMemory().getStagedLeftTuples().getInsertFirst() ); assertNull( bmem.getStagedRightTuples().getInsertFirst() ); assertNull( cmem.getStagedRightTuples().getInsertFirst() ); assertEquals( 261, list.size() ); assertTrue( list.contains( "2:2:14") ); assertTrue( list.contains( "1:0:6") ); assertTrue( list.contains( "0:1:1") ); assertTrue( list.contains( "2:2:14") ); assertTrue( list.contains( "0:0:25") ); } @Test public void testExistsNodes1() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " exists A() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); StatefulKnowledgeSession wm = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); wm.setGlobal( "list", list ); wm.fireAllRules(); assertEquals( 0, list.size() ); wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); list = new ArrayList(); wm.setGlobal( "list", list ); FactHandle fh = wm.insert( new A(1) ); wm.fireAllRules(); assertEquals( 1, list.size() ); wm.retract( fh ); wm.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testExistsNodes2() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " exists B() \n"; str += " $c : C() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); StatefulKnowledgeSession wm = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); wm.setGlobal( "list", list ); for ( int i = 0; i < 3; i++ ) { wm.insert( new A(i) ); } for ( int i = 0; i < 3; i++ ) { wm.insert( new C(i) ); } wm.fireAllRules(); assertEquals( 0, list.size() ); wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); list = new ArrayList(); wm.setGlobal( "list", list ); for ( int i = 0; i < 3; i++ ) { wm.insert( new A(i) ); } FactHandle fh = wm.insert( new B(1) ); for ( int i = 0; i < 3; i++ ) { wm.insert( new C(i) ); } wm.fireAllRules(); assertEquals( 9, list.size() ); wm.retract( fh ); wm.fireAllRules(); assertEquals( 9, list.size() ); } @Test public void testNotNodeUnlinksWithNoConstriants() { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " not B() \n"; str += " $c : C() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode aotn = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); List list = new ArrayList(); wm.setGlobal( "list", list ); LeftInputAdapterNode aNode = (LeftInputAdapterNode) aotn.getObjectSinkPropagator().getSinks()[0]; NotNode bNode = ( NotNode) aNode.getSinkPropagator().getSinks()[0]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; SegmentUtilities.createSegmentMemory( cNode, wm ); LiaNodeMemory amem = ( LiaNodeMemory ) wm.getNodeMemory( aNode ); // Only NotNode is linked in assertEquals( 2, amem.getSegmentMemory().getLinkedNodeMask() ); FactHandle fha = wm.insert( new A() ); FactHandle fhb = wm.insert( new B() ); FactHandle fhc = wm.insert( new C() ); wm.fireAllRules(); assertEquals( 0, list.size() ); // NotNode unlinks, which is allowed because it has no variable constraints assertEquals( 5, amem.getSegmentMemory().getLinkedNodeMask() ); // NotNode links back in again, which is allowed because it has no variable constraints wm.retract( fhb); wm.flushPropagations(); assertEquals( 7, amem.getSegmentMemory().getLinkedNodeMask() ); wm.fireAllRules(); assertEquals( 1, list.size() ); // Now try with lots of facthandles on NotNode list.clear(); List<FactHandle> handles = new ArrayList<FactHandle>(); for ( int i = 0; i < 5; i++ ) { handles.add( wm.insert( new B() ) ); } wm.fireAllRules(); assertEquals( 0, list.size() ); assertEquals( 5, amem.getSegmentMemory().getLinkedNodeMask() ); for ( FactHandle fh : handles ) { wm.retract( fh ); } wm.flushPropagations(); assertEquals( 7, amem.getSegmentMemory().getLinkedNodeMask() ); wm.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testNotNodeDoesNotUnlinksWithConstriants() { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " not B( value == $a.value ) \n"; str += " $c : C() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode aotn = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); List list = new ArrayList(); wm.setGlobal( "list", list ); LeftInputAdapterNode aNode = (LeftInputAdapterNode) aotn.getObjectSinkPropagator().getSinks()[0]; NotNode bNode = ( NotNode) aNode.getSinkPropagator().getSinks()[0]; JoinNode cNode = ( JoinNode) bNode.getSinkPropagator().getSinks()[0]; SegmentUtilities.createSegmentMemory( cNode, wm ); LiaNodeMemory amem = ( LiaNodeMemory ) wm.getNodeMemory( aNode ); // Only NotNode is linked in assertEquals( 2, amem.getSegmentMemory().getLinkedNodeMask() ); FactHandle fha = wm.insert( new A() ); FactHandle fhb = wm.insert( new B(1) ); FactHandle fhc = wm.insert( new C() ); wm.flushPropagations(); // All nodes are linked in assertEquals( 7, amem.getSegmentMemory().getLinkedNodeMask() ); // NotNode does not unlink, due to variable constraint wm.retract( fhb); wm.flushPropagations(); assertEquals( 7, amem.getSegmentMemory().getLinkedNodeMask() ); } @Test public void testNotNodes1() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " not A() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); List list = new ArrayList(); wm.setGlobal( "list", list ); wm.fireAllRules(); assertEquals( 1, list.size() ); wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); list = new ArrayList(); wm.setGlobal( "list", list ); FactHandle fh = wm.insert( new A(1) ); wm.fireAllRules(); assertEquals( 0, list.size() ); wm.retract( fh ); wm.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testNotNodes2() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " not B() \n"; str += " $c : C() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode aotn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode botn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode cotn = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); List list = new ArrayList(); wm.setGlobal( "list", list ); for ( int i = 0; i < 3; i++ ) { wm.insert( new A(i) ); } for ( int i = 0; i < 3; i++ ) { wm.insert( new C(i) ); } wm.fireAllRules(); assertEquals( 9, list.size() ); wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); list = new ArrayList(); wm.setGlobal( "list", list ); for ( int i = 0; i < 3; i++ ) { wm.insert( new A(i) ); } FactHandle fh = wm.insert( new B(1) ); for ( int i = 0; i < 3; i++ ) { wm.insert( new C(i) ); } wm.fireAllRules(); assertEquals( 0, list.size() ); wm.retract( fh ); wm.fireAllRules(); assertEquals( 9, list.size() ); } @Test public void testNotNodeMasksWithConstraints() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " not( B( value == $a.value ) ) \n"; str += " C() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; assertEquals( 1, liaNode.getSinkPropagator().size() ); wm.insert( new A() ); wm.flushPropagations(); NotNode notNode = ( NotNode) liaNode.getSinkPropagator().getSinks()[0]; JoinNode cNode = ( JoinNode) notNode.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn = ( RuleTerminalNode ) cNode.getSinkPropagator().getSinks()[0]; PathMemory pmem = ( PathMemory ) wm.getNodeMemory(rtn); assertEquals( 1, pmem.getSegmentMemories().length ); assertEquals( 1, pmem.getAllLinkedMaskTest() ); SegmentMemory sm = pmem.getSegmentMemories()[0]; assertEquals( 5, sm.getAllLinkedMaskTest() ); assertEquals( 3, sm.getLinkedNodeMask() ); assertFalse( sm.isSegmentLinked() ); assertFalse( pmem.isRuleLinked() ); wm.insert( new C()); wm.flushPropagations(); assertEquals( 7, sm.getLinkedNodeMask() ); // only 5 is needed to link, the 'not' turns on but it has no unfleunce either way assertTrue( sm.isSegmentLinked() ); assertTrue( pmem.isRuleLinked() ); } @Test public void testNotNodeMasksWithoutConstraints() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " not( B( ) ) \n"; str += " C() \n"; str += "then \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode node = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); LeftInputAdapterNode liaNode = (LeftInputAdapterNode) node.getObjectSinkPropagator().getSinks()[0]; assertEquals( 1, liaNode.getSinkPropagator().size() ); wm.insert( new A() ); wm.flushPropagations(); NotNode notNode = ( NotNode) liaNode.getSinkPropagator().getSinks()[0]; JoinNode cNode = ( JoinNode) notNode.getSinkPropagator().getSinks()[0]; RuleTerminalNode rtn = ( RuleTerminalNode ) cNode.getSinkPropagator().getSinks()[0]; PathMemory pmem = ( PathMemory ) wm.getNodeMemory(rtn); assertEquals( 1, pmem.getSegmentMemories().length ); assertEquals( 1, pmem.getAllLinkedMaskTest() ); SegmentMemory sm = pmem.getSegmentMemories()[0]; assertEquals( 7, sm.getAllLinkedMaskTest() ); assertEquals( 3, sm.getLinkedNodeMask() ); assertFalse( sm.isSegmentLinked() ); assertFalse( pmem.isRuleLinked() ); wm.insert( new C() ); wm.flushPropagations(); assertEquals( 7, sm.getLinkedNodeMask() ); assertTrue( sm.isSegmentLinked() ); assertTrue( pmem.isRuleLinked() ); } @Test public void testForallNodes() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " forall( B() )\n"; str += " $c : C() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode aotn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode botn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode cotn = getObjectTypeNode(kbase, A.class ); StatefulKnowledgeSession wm = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); // wm.setGlobal( "list", list ); // // for ( int i = 0; i < 3; i++ ) { // wm.insert( new A(i) ); // } // // wm.insert( new B(2) ); // // for ( int i = 0; i < 3; i++ ) { // wm.insert( new C(i) ); // } // // wm.fireAllRules(); // assertEquals( 0, list.size() ); wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); list = new ArrayList(); wm.setGlobal( "list", list ); for ( int i = 0; i < 2; i++ ) { wm.insert( new A(i) ); } for ( int i = 0; i < 27; i++ ) { wm.insert( new B(1) ); } for ( int i = 0; i < 2; i++ ) { wm.insert( new C(i) ); } wm.fireAllRules(); assertEquals( 4, list.size() ); // wm.retract( fh ); // wm.fireAllRules(); // assertEquals( 9, list.size() ); } @Test public void testAccumulateNodes1() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " accumulate( $a : A(); $l : collectList( $a ) ) \n"; str += "then \n"; str += " list.add( $l.size() ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); StatefulKnowledgeSession wm = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); wm.setGlobal( "list", list ); wm.fireAllRules(); assertEquals( 1, list.size() ); wm = kbase.newStatefulKnowledgeSession(); list = new ArrayList(); wm.setGlobal( "list", list ); FactHandle fh1 = wm.insert( new A(1) ); FactHandle fh2 = wm.insert( new A(2) ); FactHandle fh3 = wm.insert( new A(3) ); FactHandle fh4 = wm.insert( new A(4) ); wm.fireAllRules(); assertEquals( 4, list.get(0)); } @Test public void testAccumulateNodes2() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " A() \n"; str += " accumulate( $a : B(); $l : collectList( $a ) ) \n"; str += " C() \n"; str += "then \n"; str += " list.add( $l.size() ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); StatefulKnowledgeSession wm = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); wm.setGlobal( "list", list ); wm.fireAllRules(); assertEquals( 0, list.size() ); wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); list = new ArrayList(); wm.setGlobal( "list", list ); FactHandle fh1 = wm.insert( new B(1) ); FactHandle fh2 = wm.insert( new B(2) ); FactHandle fh3 = wm.insert( new B(3) ); FactHandle fh4 = wm.insert( new B(4) ); FactHandle fha = wm.insert( new A(1) ); FactHandle fhc = wm.insert( new C(1) ); wm.fireAllRules(); assertEquals( 4, list.get(0)); } @Test public void testSubnetwork() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " exists ( B() and C() ) \n"; str += " $e : D() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode aotn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode botn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode cotn = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); List list = new ArrayList(); wm.setGlobal( "list", list ); wm.insert( new A() ); wm.insert( new B() ); for ( int i = 0; i < 28; i++ ) { wm.insert( new C() ); } wm.insert( new D() ); wm.flushPropagations(); InternalAgenda agenda = ( InternalAgenda ) wm.getAgenda(); InternalAgendaGroup group = (InternalAgendaGroup) agenda.getNextFocus(); AgendaItem item = (AgendaItem) group.remove(); RuleExecutor ruleExecutor = ((RuleAgendaItem)item).getRuleExecutor(); int count = ruleExecutor.evaluateNetworkAndFire(wm, null, 0, -1); //assertEquals(3, count ); wm.fireAllRules(); assertEquals( 1, list.size() ); wm.fireAllRules(); assertEquals( 1, list.size() ); // check it doesn't double fire } @Test public void testNestedSubnetwork() throws Exception { String str = ""; str += "package org.kie \n"; str += "import " + A.class.getCanonicalName() + "\n" ; str += "import " + B.class.getCanonicalName() + "\n" ; str += "import " + C.class.getCanonicalName() + "\n" ; str += "import " + D.class.getCanonicalName() + "\n" ; str += "import " + E.class.getCanonicalName() + "\n" ; str += "import " + F.class.getCanonicalName() + "\n" ; str += "import " + G.class.getCanonicalName() + "\n" ; str += "global java.util.List list \n"; str += "rule rule1 when \n"; str += " $a : A() \n"; str += " exists ( B() and exists( C() and D() ) and E() ) \n"; str += " $f : F() \n"; str += "then \n"; str += " list.add( 'x' ); \n"; str += "end \n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource(str.getBytes()), ResourceType.DRL ); assertFalse( kbuilder.getErrors().toString(), kbuilder.hasErrors() ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); ObjectTypeNode aotn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode botn = getObjectTypeNode(kbase, A.class ); ObjectTypeNode cotn = getObjectTypeNode(kbase, A.class ); InternalWorkingMemory wm = ((StatefulKnowledgeSessionImpl)kbase.newStatefulKnowledgeSession()); List list = new ArrayList(); wm.setGlobal( "list", list ); wm.insert( new A() ); wm.insert( new B() ); for ( int i = 0; i < 28; i++ ) { wm.insert( new C() ); } for ( int i = 0; i < 29; i++ ) { wm.insert( new D() ); } wm.insert( new E() ); wm.insert( new F() ); // DefaultAgenda agenda = ( DefaultAgenda ) wm.getAgenda(); // InternalAgendaGroup group = (InternalAgendaGroup) agenda.getNextFocus(); // AgendaItem item = (AgendaItem) group.remove(); // int count = ((RuleAgendaItem)item).evaluateNetworkAndFire( wm ); // //assertEquals(7, count ); // proves we correctly track nested sub network staged propagations // // agenda.addActivation( item, true ); // agenda = ( DefaultAgenda ) wm.getAgenda(); // group = (InternalAgendaGroup) agenda.getNextFocus(); // item = (AgendaItem) group.remove(); // // agenda.fireActivation( item ); // assertEquals( 1, list.size() ); // // agenda = ( DefaultAgenda ) wm.getAgenda(); // group = (InternalAgendaGroup) agenda.getNextFocus(); // item = (AgendaItem) group.remove(); // count = ((RuleAgendaItem)item).evaluateNetworkAndFire( wm ); // //assertEquals(0, count ); wm.fireAllRules(); assertEquals( 1, list.size() ); wm.fireAllRules(); assertEquals( 1, list.size() ); } public static ObjectTypeNode getObjectTypeNode(KnowledgeBase kbase, Class<?> nodeClass) { List<ObjectTypeNode> nodes = ((KnowledgeBaseImpl)kbase).getRete().getObjectTypeNodes(); for ( ObjectTypeNode n : nodes ) { if ( ((ClassObjectType)n.getObjectType()).getClassType() == nodeClass ) { return n; } } return null; } }