Skip to content

Commit

Permalink
index for MvelConstraint
Browse files Browse the repository at this point in the history
  • Loading branch information
mariofusco committed Dec 16, 2011
1 parent e52e50c commit b321385
Show file tree
Hide file tree
Showing 27 changed files with 763 additions and 403 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@
import org.drools.compiler.DescrBuildError;
import org.drools.lang.descr.BaseDescr;
import org.drools.lang.descr.LiteralRestrictionDescr;
import org.drools.rule.Declaration;
import org.drools.rule.LiteralConstraint;
import org.drools.rule.LiteralRestriction;
import org.drools.rule.MVELDialectRuntimeData;
import org.drools.rule.VariableConstraint;
import org.drools.rule.constraint.BooleanConversionHandler;
import org.drools.rule.constraint.MvelLiteralConstraint;
import org.drools.rule.constraint.SoundexLiteralContraint;
import org.drools.rule.constraint.MvelConstraint;
import org.drools.spi.Constraint;
import org.drools.spi.Evaluator;
import org.drools.spi.FieldValue;
import org.drools.spi.InternalReadAccessor;
import org.drools.spi.Restriction;
import org.mvel2.DataConversion;
import org.mvel2.ParserConfiguration;

import java.util.Date;
import java.util.Set;

public class ConstraintBuilder {

Expand All @@ -32,15 +33,30 @@ public class ConstraintBuilder {
}
}

public static Constraint buildConstraint(RuleBuildContext context,
ValueType vtype,
FieldValue field,
String expr,
String value1,
String operator,
String value2,
InternalReadAccessor extractor,
LiteralRestrictionDescr restrictionDescr) {
public static Constraint buildVariableConstraint(RuleBuildContext context,
String expr,
Declaration[] declrations,
String operator,
InternalReadAccessor extractor,
Restriction restriction) {
if (USE_MVEL_EXPRESSION) {
String packageName = context.getPkg().getName();
ParserConfiguration conf = getParserConfiguration(context);
return new MvelConstraint(conf, packageName, expr, operator, declrations, extractor);
} else {
return new VariableConstraint(extractor, restriction);
}
}

public static Constraint buildLiteralConstraint(RuleBuildContext context,
ValueType vtype,
FieldValue field,
String expr,
String value1,
String operator,
String value2,
InternalReadAccessor extractor,
LiteralRestrictionDescr restrictionDescr) {
if (USE_MVEL_EXPRESSION) {
return buildMVELConstraint(context, vtype, field, expr, value1, operator, value2, restrictionDescr);
} else {
Expand All @@ -61,15 +77,16 @@ private static Constraint buildMVELConstraint(RuleBuildContext context,
String rightValue,
LiteralRestrictionDescr restrictionDescr) {
String packageName = context.getPkg().getName();
MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData( "mvel" );
ParserConfiguration conf = data.getParserConfiguration();

if (operator.equals("soundslike")) {
return new SoundexLiteralContraint(conf, packageName, leftValue, operator, rightValue);
}
ParserConfiguration conf = getParserConfiguration(context);

String mvelExpr = normalizeMVELExpression(vtype, field, expr, leftValue, operator, rightValue, restrictionDescr);
return new MvelLiteralConstraint(conf, packageName, vtype, mvelExpr, leftValue, operator, rightValue);

return new MvelConstraint(conf, packageName, mvelExpr, operator, null, null);
}

private static ParserConfiguration getParserConfiguration(RuleBuildContext context) {
MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData( "mvel" );
return data.getParserConfiguration();
}

private static String normalizeMVELExpression(ValueType vtype,
Expand All @@ -90,6 +107,12 @@ private static String normalizeMVELExpression(ValueType vtype,
}
return (restrictionDescr.isNegated() ? "!" : "") + leftValue + "." + method + "(" + rightValue + ")";
}
if (operator.equals("soundslike")) {
return "if (" + leftValue + " == null || " + rightValue + " == null) return false;\n" +
"String soundex1 = soundex(" + leftValue + ");\n" +
"if (soundex1 == null) return false;\n" +
"return soundex1.equals(soundex(" + rightValue + "));";
}
return expr;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
import org.drools.rule.SlidingTimeWindow;
import org.drools.rule.TypeDeclaration;
import org.drools.rule.UnificationRestriction;
import org.drools.rule.VariableConstraint;
import org.drools.rule.VariableRestriction;
import org.drools.rule.builder.dialect.mvel.MVELDialect;
import org.drools.spi.AcceptsReadAccessor;
Expand Down Expand Up @@ -627,7 +626,7 @@ private boolean addConstraintToPattern( final RuleBuildContext context,
if (restrictionDescr != null) {
FieldValue field = getFieldValue(context, vtype, restrictionDescr);
if (field != null) {
Constraint constraint = buildConstraint(context, vtype, field, expr, value1, operator, value2, extractor, restrictionDescr);
Constraint constraint = buildLiteralConstraint(context, vtype, field, expr, value1, operator, value2, extractor, restrictionDescr);
if (constraint != null) {
pattern.addConstraint(constraint);
return true;
Expand All @@ -636,11 +635,11 @@ private boolean addConstraintToPattern( final RuleBuildContext context,
}

Restriction restriction = null;
Declaration[] declarations = null;
Declaration declr = null;

if ( value2.indexOf( '(' ) < 0 && value2.indexOf( '.' ) < 0 && value2.indexOf( '[' ) < 0 ) {
declr = context.getDeclarationResolver().getDeclaration( context.getRule(),
value2 );
declr = context.getDeclarationResolver().getDeclaration( context.getRule(), value2 );

if ( declr == null ) {
// trying to create implicit declaration
Expand Down Expand Up @@ -688,6 +687,8 @@ private boolean addConstraintToPattern( final RuleBuildContext context,
// if a declaration exists, then it may be a variable direct property access
if ( declr != null ) {
if ( declr.isPatternDeclaration() ) {
// TODO: no need to extract inner declaration when using mvel constraint
declarations = new Declaration[] { declr };
declr = this.createDeclarationObject( context,
parts[1].trim(),
declr.getPattern() );
Expand Down Expand Up @@ -757,8 +758,33 @@ private boolean addConstraintToPattern( final RuleBuildContext context,
// something failed and an error should already have been reported
return false;
}
pattern.addConstraint( new VariableConstraint( extractor,
restriction ) );

if (declr == null) {
ReturnValueRestriction returnValueRestriction = (ReturnValueRestriction)restriction;
Declaration[] requiredDeclarations = restriction.getRequiredDeclarations();
String[] requiredGlobals = returnValueRestriction.getRequiredGlobals();
declarations = new Declaration[(requiredDeclarations != null ? requiredDeclarations.length : 0) + (requiredGlobals != null ? requiredGlobals.length : 0)];
int i = 0;
if (requiredDeclarations != null) {
for (Declaration requiredDeclaration : requiredDeclarations)
declarations[i++] = requiredDeclaration;
}
if (requiredGlobals != null) {
for (String requiredGlobal : requiredGlobals)
declarations[i++] = context.getDeclarationResolver().getDeclaration(context.getRule(), requiredGlobal);
}
} else {
if (declarations == null) declarations = new Declaration[] { declr };
/*
else {
Declaration[] redefinedDeclaration = new Declaration[declarations.length+1];
for (int i = 0; i < declarations.length; i++) redefinedDeclaration[i] = declarations[i];
redefinedDeclaration[declarations.length] = declr;
declarations = redefinedDeclaration;
}
*/
}
pattern.addConstraint(buildVariableConstraint(context, expr, declarations, operator, extractor, restriction));
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
Expand Down Expand Up @@ -384,12 +385,12 @@ public void addImport(String importEntry) {

public void addStaticImport(String staticImportEntry) {
if ( staticImportEntry.endsWith( "*" ) ) {
addStaticPackageImport(staticImportEntry);
return;
}

int index = staticImportEntry.lastIndexOf( '.' );
String className = staticImportEntry.substring( 0,
index );
String className = staticImportEntry.substring( 0, index );
String methodName = staticImportEntry.substring( index + 1 );

try {
Expand All @@ -399,26 +400,46 @@ public void addStaticImport(String staticImportEntry) {
// First try and find a matching method
for ( Method method : cls.getDeclaredMethods() ) {
if ( method.getName().equals( methodName ) ) {
this.data.addImport( methodName,
method );
this.data.addImport( methodName, method );
return;
}
}

//no matching method, so now try and find a matching public property
for ( Field field : cls.getFields() ) {
if ( field.isAccessible() && field.getName().equals( methodName ) ) {
this.data.addImport( methodName,
field );
this.data.addImport( methodName, field );
return;
}
}
}
} catch ( ClassNotFoundException e ) {
}
// we never managed to make the import, so log an error
this.results.add( new ImportError( staticImportEntry,
-1 ) );
this.results.add( new ImportError( staticImportEntry, -1 ) );
}

public void addStaticPackageImport(String staticImportEntry) {
int index = staticImportEntry.lastIndexOf( '.' );
String className = staticImportEntry.substring(0, index);
Class cls = null;
try {
cls = pkgBuilder.getRootClassLoader().loadClass( className );
} catch ( ClassNotFoundException e ) { }
if (cls == null) results.add( new ImportError( staticImportEntry, -1 ) );

for (Method method : cls.getDeclaredMethods()) {
if ((method.getModifiers() | Modifier.STATIC) > 0) {
this.data.addImport(method.getName(), method);
}
}

for (Field field : cls.getFields()) {
if (field.isAccessible() && (field.getModifiers() | Modifier.STATIC) > 0) {
this.data.addImport(field.getName(), field);
return;
}
}
}

// private Map staticFieldImports = new HashMap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,28 +99,28 @@ public void testBuildsIndexedMemory() {
JoinNode j11 = ( JoinNode ) j10.getSinkPropagator().getSinks()[0]; // $p11

SingleBetaConstraints c = ( SingleBetaConstraints ) j2.getRawConstraints();
assertEquals( "$name", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "$name", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertTrue( c.isIndexed() );
BetaMemory bm = ( BetaMemory ) wm.getNodeMemory( j2 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleIndexHashTable );
assertTrue( bm.getRightTupleMemory() instanceof RightTupleIndexHashTable );

c = ( SingleBetaConstraints ) j3.getRawConstraints();
assertEquals( "name", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
// assertEquals( "name", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertTrue( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j3 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleIndexHashTable );
assertTrue( bm.getRightTupleMemory() instanceof RightTupleIndexHashTable );

c = ( SingleBetaConstraints ) j4.getRawConstraints();
assertEquals( "$p1", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "$p1", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertFalse( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j4 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleList );
assertTrue( bm.getRightTupleMemory() instanceof RightTupleList );

c = ( SingleBetaConstraints ) j5.getRawConstraints();
assertEquals( "name", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "name", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertTrue( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j5 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleIndexHashTable );
Expand All @@ -135,35 +135,35 @@ public void testBuildsIndexedMemory() {
// assertTrue( bm.getRightTupleMemory() instanceof RightTupleList );

c = ( SingleBetaConstraints ) j7.getRawConstraints();
assertEquals( "name", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "name", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertTrue( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j7 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleIndexHashTable );
assertTrue( bm.getRightTupleMemory() instanceof RightTupleIndexHashTable );

c = ( SingleBetaConstraints ) j8.getRawConstraints();
assertEquals( "name", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "name", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertTrue( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j8 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleIndexHashTable );
assertTrue( bm.getRightTupleMemory() instanceof RightTupleIndexHashTable );

c = ( SingleBetaConstraints ) j9.getRawConstraints();
assertEquals( "$p1", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "$p1", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertFalse( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j9 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleList );
assertTrue( bm.getRightTupleMemory() instanceof RightTupleList );

c = ( SingleBetaConstraints ) j10.getRawConstraints();
assertEquals( "name", ((VariableConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "name", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertTrue( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j10 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleIndexHashTable );
assertTrue( bm.getRightTupleMemory() instanceof RightTupleIndexHashTable );

c = ( SingleBetaConstraints ) j11.getRawConstraints();
assertEquals( "$p1", ((PredicateConstraint)c.getConstraint()).getRequiredDeclarations()[0].getIdentifier() );
assertEquals( "$p1", c.getConstraint().getRequiredDeclarations()[0].getIdentifier() );
assertFalse( c.isIndexed() );
bm = ( BetaMemory ) wm.getNodeMemory( j11 );
assertTrue( bm.getLeftTupleMemory() instanceof LeftTupleList );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1992,15 +1992,16 @@ public void testBigDecimal() throws Exception {

final PersonInterface bill = new Person( "bill",
null,
12 );
42 );
bill.setBigDecimal( new BigDecimal( "42" ) );

final PersonInterface ben = new Person( "ben",
null,
13 );
43 );
ben.setBigDecimal( new BigDecimal( "43" ) );

session.insert( bill );
session.insert(new Cheese("gorgonzola", 43));
session.insert( ben );
session = SerializationHelper.getSerialisedStatefulSession( session,
ruleBase );
Expand Down Expand Up @@ -2992,7 +2993,9 @@ public void testReturnValueException() throws Exception {
workingMemory.fireAllRules();
fail( "Should throw an Exception from the ReturnValue" );
} catch ( final Exception e ) {
e.getCause().getMessage().contains( "this should throw an exception" );
Throwable root = e;
while (root.getCause() != null) root = root.getCause();
root.getMessage().contains( "this should throw an exception" );
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#created on: 27-Mar-2006
package org.drools.test

import org.drools.Cheese;
import org.drools.Person;
import java.math.BigDecimal;

Expand All @@ -9,8 +10,8 @@ global java.util.List list;
rule "BigDec"

when
Person($b : bigDecimal )
p : Person(bigDecimal < $b)
Cheese($price : price)
p : Person(bigDecimal < $price)
then
list.add( p );
end
Loading

0 comments on commit b321385

Please sign in to comment.