Skip to content

Commit

Permalink
JBRULES-2776 Left and Right Unlinking.
Browse files Browse the repository at this point in the history
  • Loading branch information
leogomes authored and etirelli committed May 18, 2011
1 parent 016be44 commit f2d4eba
Show file tree
Hide file tree
Showing 26 changed files with 1,085 additions and 93 deletions.
@@ -0,0 +1,118 @@
package org.drools.integrationtests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.drools.Person;
import org.drools.RuleBase;
import org.drools.RuleBaseConfiguration;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.common.InternalFactHandle;
import org.drools.compiler.PackageBuilder;
import org.drools.rule.Package;
import org.junit.Test;

public class LRUnlinkingTest {

@Test
public void multipleJoinsUsingSameOTN() throws Exception {

final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_LRUnlinking.drl" ) ) );
final Package pkg = builder.getPackage();

final RuleBaseConfiguration conf = new RuleBaseConfiguration();
conf.setLRUnlinkingEnabled( true );
RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );

ruleBase.addPackage( pkg );
ruleBase = SerializationHelper.serializeObject( ruleBase );

final WorkingMemory wmOne = ruleBase.newStatefulSession();
final WorkingMemory wmTwo = ruleBase.newStatefulSession();

final List<Person> listOne = new ArrayList<Person>();
final List<Person> listTwo = new ArrayList<Person>();

wmOne.setGlobal( "results",
listOne );
wmTwo.setGlobal( "results",
listTwo );

Person name = new Person();
Person likes = new Person();
Person age = new Person();
Person hair = new Person();
Person happy = new Person();
Person match = new Person();

name.setName( "Ana" );
likes.setLikes( "Chocolate" );
age.setAge( 30 );
hair.setHair( "brown" );
happy.setHappy( true );

match.setName( "Leo" );
match.setLikes( "Chocolate" );
match.setAge( 30 );
match.setHair( "brown" );
match.setHappy( true );

// WM One - first round of inserts
wmOne.insert( name );
wmOne.insert( likes );
wmOne.insert( age );

wmOne.fireAllRules();

assertEquals( "Should not have fired",
0,
listOne.size() );

// WM Two - first round o inserts
wmTwo.insert( name );
wmTwo.insert( likes );
wmTwo.insert( age );

wmTwo.fireAllRules();

assertEquals( "Should not have fired",
0,
listTwo.size() );

wmOne.insert( hair );
wmOne.insert( happy );
InternalFactHandle matchHandle = (InternalFactHandle) wmOne.insert( match );

wmOne.fireAllRules();

assertTrue( "Should have fired",
listOne.size() > 0);

assertEquals("Should have inserted the match Person",
matchHandle.getObject(),
listOne.get( 0 ));

wmTwo.fireAllRules();

assertEquals( "Should not have fired",
0,
listTwo.size() );

wmTwo.insert( hair );
wmTwo.insert( happy );
wmTwo.insert( match );

wmTwo.fireAllRules();

assertTrue( "Should have fired",
listTwo.size() > 0);

}

}
@@ -1,20 +1,20 @@
package org.drools.integrationtests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

import org.drools.Cheese;
import org.drools.Cheesery;
import org.drools.KnowledgeBase;
Expand All @@ -36,16 +36,13 @@
import org.drools.command.runtime.BatchExecutionCommandImpl;
import org.drools.compiler.PackageBuilder;
import org.drools.definition.KnowledgePackage;
import org.drools.impl.StatefulKnowledgeSessionImpl;
import org.drools.io.Resource;
import org.drools.io.ResourceFactory;
import org.drools.rule.Package;
import org.drools.runtime.ExecutionResults;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.StatelessKnowledgeSession;
import org.drools.runtime.StatelessKnowledgeSessionResults;
import org.drools.runtime.rule.impl.FlatQueryResults;
import org.drools.spi.GlobalResolver;
import org.junit.Test;

public class StatelessSessionTest {
final List list = new ArrayList();
Expand Down
@@ -0,0 +1,19 @@
package org.drools;

global java.util.List results;

rule "Test LR unlinking with multiple joins on the same object type"
when
$p1 : Person ($name : name != null)
$p2 : Person ($likes : likes != null)
$p3 : Person ($age : age != null)
$p4 : Person ($hair : hair != null)
$p5 : Person ($happy : happy != null)
$p6 : Person (name != $name,
likes == $likes,
age == $age,
hair == $hair,
happy == $happy)
then
results.add( $p6 );
end
49 changes: 49 additions & 0 deletions drools-core/src/main/java/org/drools/RuleBaseConfiguration.java
Expand Up @@ -27,6 +27,7 @@
import java.util.Properties;

import org.drools.builder.conf.ClassLoaderCacheOption;
import org.drools.builder.conf.LRUnlinkingOption;
import org.drools.common.AgendaGroupFactory;
import org.drools.common.ArrayAgendaGroupFactory;
import org.drools.common.PriorityQueueAgendaGroupFactory;
Expand Down Expand Up @@ -102,6 +103,7 @@
* drools.multithreadEvaluation = &lt;true|false&gt;
* drools.mbeans = &lt;enabled|disabled&gt;
* drools.classLoaderCacheEnabled = &lt;true|false&gt;
* drools.lrUnlinkingEnabled = &lt;true|false&gt;
* </pre>
*/
public class RuleBaseConfiguration
Expand Down Expand Up @@ -133,6 +135,7 @@ public class RuleBaseConfiguration
private String consequenceExceptionHandler;
private String ruleBaseUpdateHandler;
private boolean classLoaderCacheEnabled;
private boolean lrUnlinkingEnabled;

private EventProcessingOption eventProcessingMode;

Expand Down Expand Up @@ -184,6 +187,7 @@ public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt( maxThreads );
out.writeObject( eventProcessingMode );
out.writeBoolean( classLoaderCacheEnabled );
out.writeBoolean( lrUnlinkingEnabled );
}

public void readExternal(ObjectInput in) throws IOException,
Expand Down Expand Up @@ -211,6 +215,7 @@ public void readExternal(ObjectInput in) throws IOException,
maxThreads = in.readInt();
eventProcessingMode = (EventProcessingOption) in.readObject();
classLoaderCacheEnabled = in.readBoolean();
lrUnlinkingEnabled = in.readBoolean();
}

/**
Expand Down Expand Up @@ -302,6 +307,8 @@ public void setProperty(String name,
setMBeansEnabled( MBeansOption.isEnabled( value ) );
} else if ( name.equals( ClassLoaderCacheOption.PROPERTY_NAME ) ) {
setClassLoaderCacheEnabled( StringUtils.isEmpty( value ) ? true : Boolean.valueOf( value ) );
} else if ( name.equals( LRUnlinkingOption.PROPERTY_NAME ) ) {
setLRUnlinkingEnabled( StringUtils.isEmpty( value ) ? false : Boolean.valueOf( value ) );
}
}

Expand Down Expand Up @@ -355,6 +362,8 @@ public String getProperty(String name) {
return isMBeansEnabled() ? "enabled" : "disabled";
} else if ( name.equals( ClassLoaderCacheOption.PROPERTY_NAME ) ) {
return Boolean.toString( isClassLoaderCacheEnabled() );
} else if ( name.equals( LRUnlinkingOption.PROPERTY_NAME ) ) {
return Boolean.toString( isLRUnlinkingEnabled() );
}

return null;
Expand Down Expand Up @@ -451,6 +460,10 @@ private void init(Properties properties,

setClassLoaderCacheEnabled( Boolean.valueOf( this.chainedProperties.getProperty( ClassLoaderCacheOption.PROPERTY_NAME,
"true" ) ) );

setLRUnlinkingEnabled( Boolean.valueOf( this.chainedProperties.getProperty( LRUnlinkingOption.PROPERTY_NAME,
"false" ) ) );

}

/**
Expand Down Expand Up @@ -478,6 +491,9 @@ private void checkCanChange() {

public void setSequential(boolean sequential) {
this.sequential = sequential;
if (sequential && isLRUnlinkingEnabled()) {
throw new IllegalArgumentException( "Sequential mode cannot be used when Left & Right unlinking is enabled." );
}
}

public boolean isSequential() {
Expand Down Expand Up @@ -648,6 +664,9 @@ public void setSequentialAgenda(final SequentialAgenda sequentialAgenda) {
public void setMultithreadEvaluation(boolean enableMultithread) {
checkCanChange();
this.multithread = enableMultithread;
if (multithread && isLRUnlinkingEnabled()) {
throw new IllegalArgumentException( "Multithread evaluation cannot be used when Left & Right Unlinking is enabled." );
}
}

/**
Expand Down Expand Up @@ -693,6 +712,32 @@ public void setClassLoaderCacheEnabled(final boolean classLoaderCacheEnabled) {
this.classLoaderCacheEnabled = classLoaderCacheEnabled;
this.classLoader.setCachingEnabled( this.classLoaderCacheEnabled );
}

/**
* @return whether or not Left & Right Unlinking is enabled.
*/
public boolean isLRUnlinkingEnabled() {
return this.lrUnlinkingEnabled;
}

/**
* Enable Left & Right Unlinking. It will also disable sequential mode
* and multithread evaluation as these are incompatible with L&R unlinking.
* @param enabled
*/
public void setLRUnlinkingEnabled(boolean enabled) {
checkCanChange(); // throws an exception if a change isn't possible;
this.lrUnlinkingEnabled = enabled;

if ( enabled && isSequential() ) {
throw new IllegalArgumentException( "Sequential mode cannot be used when Left & Right Unlinking is enabled." );
}

if ( enabled && isMultithreadEvaluation() ) {
throw new IllegalArgumentException( "Multithread evaluation cannot be used when Left & Right Unlinking is enabled." );
}
}


public List<Map<String, Object>> getWorkDefinitions() {
if ( this.workDefinitions == null ) {
Expand Down Expand Up @@ -1080,6 +1125,8 @@ public <T extends SingleValueKnowledgeBaseOption> T getOption(Class<T> option) {
return (T) (this.isMBeansEnabled() ? MBeansOption.ENABLED : MBeansOption.DISABLED);
} else if ( ClassLoaderCacheOption.class.equals( option ) ) {
return (T) (this.isClassLoaderCacheEnabled() ? ClassLoaderCacheOption.ENABLED : ClassLoaderCacheOption.DISABLED);
} else if ( LRUnlinkingOption.class.equals( option ) ) {
return (T) (this.isLRUnlinkingEnabled() ? LRUnlinkingOption.ENABLED : LRUnlinkingOption.DISABLED);
}
return null;

Expand Down Expand Up @@ -1122,6 +1169,8 @@ public <T extends KnowledgeBaseOption> void setOption(T option) {
setMBeansEnabled( ((MBeansOption) option).isEnabled() );
} else if ( option instanceof ClassLoaderCacheOption ) {
setClassLoaderCacheEnabled( ((ClassLoaderCacheOption) option).isClassLoaderCacheEnabled() );
} else if ( option instanceof LRUnlinkingOption ) {
setLRUnlinkingEnabled( ((LRUnlinkingOption) option).isLRUnlinkingEnabled() );
}

}
Expand Down

0 comments on commit f2d4eba

Please sign in to comment.