[jboss-svn-commits] JBL Code SVN: r20340 - in labs/jbossrules/trunk: drools-compiler/src/test/java/org/drools and 3 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Jun 5 10:37:32 EDT 2008
Author: tirelli
Date: 2008-06-05 10:37:32 -0400 (Thu, 05 Jun 2008)
New Revision: 20340
Added:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELShadowFactory.java
Modified:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/mvel/MVELAccumulateBuilder.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Cheesery.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/MVELAccumulator.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java
Log:
Fixing accumulate problems after shadow proxy removal
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/mvel/MVELAccumulateBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/mvel/MVELAccumulateBuilder.java 2008-06-05 14:06:37 UTC (rev 20339)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/dialect/mvel/MVELAccumulateBuilder.java 2008-06-05 14:37:32 UTC (rev 20340)
@@ -18,12 +18,16 @@
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.drools.base.accumulators.AccumulateFunction;
import org.drools.base.accumulators.MVELAccumulatorFunctionExecutor;
import org.drools.base.mvel.DroolsMVELFactory;
+import org.drools.base.mvel.DroolsMVELShadowFactory;
import org.drools.base.mvel.MVELAccumulator;
import org.drools.compiler.Dialect;
import org.drools.lang.descr.AccumulateDescr;
@@ -60,7 +64,7 @@
final AccumulateDescr accumDescr = (AccumulateDescr) descr;
- if( ! accumDescr.hasValidInput() ) {
+ if ( !accumDescr.hasValidInput() ) {
return null;
}
@@ -78,13 +82,6 @@
final Declaration[] sourceDeclArr = (Declaration[]) source.getOuterDeclarations().values().toArray( new Declaration[0] );
- final DroolsMVELFactory factory = new DroolsMVELFactory( context.getDeclarationResolver().getDeclarations(),
- source.getOuterDeclarations(),
- context.getPkg().getGlobals() );
-
- MVELDialectData data = (MVELDialectData) context.getPkg().getDialectDatas().getDialectData( "mvel" );
- factory.setNextFactory( data.getFunctionFactory() );
-
Accumulator accumulator = null;
Declaration[] declarations = null;
@@ -110,6 +107,13 @@
AccumulateFunction function = context.getConfiguration().getAccumulateFunction( accumDescr.getFunctionIdentifier() );
+ final DroolsMVELFactory factory = new DroolsMVELFactory( context.getDeclarationResolver().getDeclarations(),
+ source.getOuterDeclarations(),
+ context.getPkg().getGlobals() );
+
+ MVELDialectData data = (MVELDialectData) context.getPkg().getDialectDatas().getDialectData( "mvel" );
+ factory.setNextFactory( data.getFunctionFactory() );
+
accumulator = new MVELAccumulatorFunctionExecutor( factory,
expression,
function );
@@ -138,11 +142,12 @@
requiredDeclarations.addAll( actionCodeAnalysis.getBoundIdentifiers()[0] );
requiredDeclarations.addAll( resultCodeAnalysis.getBoundIdentifiers()[0] );
+ Dialect.AnalysisResult reverseCodeAnalysis = null;
if ( accumDescr.getReverseCode() != null ) {
- final Dialect.AnalysisResult reverseCodeAnalysis = context.getDialect().analyzeBlock( context,
- accumDescr,
- accumDescr.getActionCode(),
- new Set[]{context.getDeclarationResolver().getDeclarations().keySet(), context.getPkg().getGlobals().keySet()} );
+ reverseCodeAnalysis = context.getDialect().analyzeBlock( context,
+ accumDescr,
+ accumDescr.getActionCode(),
+ new Set[]{context.getDeclarationResolver().getDeclarations().keySet(), context.getPkg().getGlobals().keySet()} );
requiredDeclarations.addAll( reverseCodeAnalysis.getBoundIdentifiers()[0] );
}
@@ -181,6 +186,27 @@
initCodeAnalysis.getMvelVariables(),
context );
+ DroolsMVELFactory factory = null;
+ if ( reverse == null ) {
+ // does not support reverse, so create a regular factory
+ factory = new DroolsMVELFactory( context.getDeclarationResolver().getDeclarations(),
+ source.getOuterDeclarations(),
+ context.getPkg().getGlobals() );
+ } else {
+ Set<String> shadow = new HashSet<String>( source.getOuterDeclarations().keySet() );
+ shadow.retainAll( reverseCodeAnalysis.getNotBoundedIdentifiers() );
+ shadow.addAll( reverseCodeAnalysis.getBoundIdentifiers()[0] );
+
+ // supports reverse, so create a shadowing factory
+ factory = new DroolsMVELShadowFactory( context.getDeclarationResolver().getDeclarations(),
+ source.getOuterDeclarations(),
+ context.getPkg().getGlobals(),
+ shadow );
+ }
+
+ MVELDialectData data = (MVELDialectData) context.getPkg().getDialectDatas().getDialectData( "mvel" );
+ factory.setNextFactory( data.getFunctionFactory() );
+
accumulator = new MVELAccumulator( factory,
init,
action,
@@ -195,5 +221,4 @@
accumulator );
return accumulate;
}
-
}
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Cheesery.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Cheesery.java 2008-06-05 14:06:37 UTC (rev 20339)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/Cheesery.java 2008-06-05 14:37:32 UTC (rev 20340)
@@ -53,6 +53,10 @@
public void removeCheese(final Cheese cheese) {
this.cheeses.remove( cheese );
+ recalculateTotalAmount();
+ }
+
+ private void recalculateTotalAmount() {
this.totalAmount = 0;
for( Iterator it = this.cheeses.iterator(); it.hasNext(); ) {
this.totalAmount += ((Cheese) it.next()).getPrice();
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java 2008-06-05 14:06:37 UTC (rev 20339)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java 2008-06-05 14:37:32 UTC (rev 20340)
@@ -1,6 +1,5 @@
package org.drools.integrationtests;
-import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
@@ -491,7 +490,7 @@
}
- public void FIXME_testAccumulateReverseModifyMVEL2() throws Exception {
+ public void testAccumulateReverseModifyMVEL2() throws Exception {
// read in the source
final Reader reader = new InputStreamReader( getClass().getResourceAsStream( "test_AccumulateReverseModifyMVEL2.drl" ) );
final RuleBase ruleBase = loadRuleBase( reader );
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java 2008-06-05 14:06:37 UTC (rev 20339)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java 2008-06-05 14:37:32 UTC (rev 20340)
@@ -59,7 +59,7 @@
}
public DroolsMVELFactory() {
-
+
}
public DroolsMVELFactory(final Map previousDeclarations,
@@ -89,26 +89,27 @@
}
}
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- tupleObjects = (Object[])in.readObject();
- knowledgeHelper = (KnowledgeHelper)in.readObject();
- object = in.readObject();
- localDeclarations = (Map)in.readObject();
- previousDeclarations = (Map)in.readObject();
- globals = (Map)in.readObject();
- workingMemory = (WorkingMemory)in.readObject();
- localVariables = (Map)in.readObject();
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ tupleObjects = (Object[]) in.readObject();
+ knowledgeHelper = (KnowledgeHelper) in.readObject();
+ object = in.readObject();
+ localDeclarations = (Map) in.readObject();
+ previousDeclarations = (Map) in.readObject();
+ globals = (Map) in.readObject();
+ workingMemory = (WorkingMemory) in.readObject();
+ localVariables = (Map) in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(tupleObjects);
- out.writeObject(knowledgeHelper);
- out.writeObject(object);
- out.writeObject(localDeclarations);
- out.writeObject(previousDeclarations);
- out.writeObject(globals);
- out.writeObject(workingMemory);
- out.writeObject(localVariables);
+ out.writeObject( tupleObjects );
+ out.writeObject( knowledgeHelper );
+ out.writeObject( object );
+ out.writeObject( localDeclarations );
+ out.writeObject( previousDeclarations );
+ out.writeObject( globals );
+ out.writeObject( workingMemory );
+ out.writeObject( localVariables );
}
public static void addStaticImport(StaticMethodImportResolverFactory factory,
@@ -188,7 +189,7 @@
public void setLocalValue(final String identifier,
final Object value) {
- if (this.localVariables == null) {
+ if ( this.localVariables == null ) {
this.localVariables = new HashMap();
}
this.localVariables.put( identifier,
@@ -276,4 +277,32 @@
this.localDeclarations,
this.globals );
}
+
+ /**
+ * @return the localDeclarations
+ */
+ public Map getLocalDeclarations() {
+ return localDeclarations;
+ }
+
+ /**
+ * @return the previousDeclarations
+ */
+ public Map getPreviousDeclarations() {
+ return previousDeclarations;
+ }
+
+ /**
+ * @return the globals
+ */
+ protected Map getGlobals() {
+ return globals;
+ }
+
+ /**
+ * @return the localVariables
+ */
+ protected Map getLocalVariables() {
+ return localVariables;
+ }
}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELShadowFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELShadowFactory.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/DroolsMVELShadowFactory.java 2008-06-05 14:37:32 UTC (rev 20340)
@@ -0,0 +1,159 @@
+package org.drools.base.mvel;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.mvel.integration.VariableResolver;
+
+public class DroolsMVELShadowFactory extends DroolsMVELFactory {
+
+ private static final long serialVersionUID = 400L;
+
+ private Set<String> shadowVariables;
+ private Map<String, Object> shadowValues;
+
+ public DroolsMVELShadowFactory() {
+ }
+
+ public DroolsMVELShadowFactory(final Map previousDeclarations,
+ final Map localDeclarations,
+ final Map globals,
+ final Set<String> shadowVariables) {
+ this( previousDeclarations,
+ localDeclarations,
+ globals,
+ null,
+ shadowVariables );
+ }
+
+ public DroolsMVELShadowFactory(final Map previousDeclarations,
+ final Map localDeclarations,
+ final Map globals,
+ final List[] externals,
+ final Set<String> shadowVariables) {
+ super( previousDeclarations,
+ localDeclarations,
+ globals,
+ externals );
+ this.shadowVariables = shadowVariables;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ super.readExternal( in );
+ shadowVariables = (Set<String>) in.readObject();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ super.writeExternal( out );
+ out.writeObject( shadowVariables );
+ }
+
+ @Override
+ public VariableResolver getVariableResolver(String name) {
+ if ( this.shadowValues != null && this.shadowVariables.contains( name ) ) {
+ return new ShadowVariableResolver( super.getVariableResolver( name ),
+ this.shadowValues,
+ name );
+ }
+ return super.getVariableResolver( name );
+ }
+
+ public Object clone() {
+ return new DroolsMVELShadowFactory( this.getPreviousDeclarations(),
+ this.getLocalDeclarations(),
+ this.getGlobals(),
+ this.shadowVariables );
+ }
+
+ /**
+ * @return the shadowValues
+ */
+ public Map<String, Object> getShadowValues() {
+ return shadowValues;
+ }
+
+ /**
+ * @param shadowValues the shadowValues to set
+ */
+ public void setShadowValues(Map<String, Object> shadowValues) {
+ this.shadowValues = shadowValues;
+ }
+
+ /**
+ * @return the shadowVariables
+ */
+ public Set<String> getShadowVariables() {
+ return shadowVariables;
+ }
+
+ private static class ShadowVariableResolver
+ implements
+ VariableResolver {
+ private final VariableResolver delegate;
+ private final Map<String, Object> shadowValues;
+ private final String identifier;
+
+ public ShadowVariableResolver(final VariableResolver delegate,
+ final Map<String, Object> shadowValues,
+ final String identifier) {
+ super();
+ this.delegate = delegate;
+ this.shadowValues = shadowValues;
+ this.identifier = identifier;
+ }
+
+ /**
+ * @return
+ * @see org.mvel.integration.VariableResolver#getFlags()
+ */
+ public int getFlags() {
+ return delegate.getFlags();
+ }
+
+ /**
+ * @return
+ * @see org.mvel.integration.VariableResolver#getName()
+ */
+ public String getName() {
+ return delegate.getName();
+ }
+
+ /**
+ * @return
+ * @see org.mvel.integration.VariableResolver#getType()
+ */
+ public Class getType() {
+ return delegate.getType();
+ }
+
+ /**
+ * @return
+ * @see org.mvel.integration.VariableResolver#getValue()
+ */
+ public Object getValue() {
+ return this.shadowValues.get( this.identifier );
+ }
+
+ /**
+ * @param type
+ * @see org.mvel.integration.VariableResolver#setStaticType(java.lang.Class)
+ */
+ public void setStaticType(Class type) {
+ delegate.setStaticType( type );
+ }
+
+ /**
+ * @param value
+ * @see org.mvel.integration.VariableResolver#setValue(java.lang.Object)
+ */
+ public void setValue(Object value) {
+ delegate.setValue( value );
+ }
+
+ }
+}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/MVELAccumulator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/MVELAccumulator.java 2008-06-05 14:06:37 UTC (rev 20339)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/mvel/MVELAccumulator.java 2008-06-05 14:37:32 UTC (rev 20340)
@@ -17,10 +17,10 @@
*/
package org.drools.base.mvel;
-import java.io.Serializable;
import java.io.IOException;
+import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.io.ObjectInput;
+import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@@ -42,7 +42,7 @@
implements
Accumulator {
- private static final long serialVersionUID = 400L;
+ private static final long serialVersionUID = 400L;
private DroolsMVELFactory prototype;
private Serializable init;
@@ -66,27 +66,33 @@
this.result = result;
}
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- prototype = (DroolsMVELFactory)in.readObject();
- init = (Serializable)in.readObject();
- action = (Serializable)in.readObject();
- reverse = (Serializable)in.readObject();
- result = (Serializable)in.readObject();
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ prototype = (DroolsMVELFactory) in.readObject();
+ init = (Serializable) in.readObject();
+ action = (Serializable) in.readObject();
+ reverse = (Serializable) in.readObject();
+ result = (Serializable) in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(prototype);
- out.writeObject(init);
- out.writeObject(action);
- out.writeObject(reverse);
- out.writeObject(result);
+ out.writeObject( prototype );
+ out.writeObject( init );
+ out.writeObject( action );
+ out.writeObject( reverse );
+ out.writeObject( result );
}
/* (non-Javadoc)
* @see org.drools.spi.Accumulator#createContext()
*/
public Object createContext() {
- return new HashMap();
+ Map<InternalFactHandle, Map<String, Object>> shadow = null;
+ if ( this.reverse != null ) {
+ shadow = new HashMap<InternalFactHandle, Map<String, Object>>();
+ }
+ return new MVELAccumulatorContext( new HashMap(),
+ shadow );
}
/* (non-Javadoc)
@@ -98,11 +104,17 @@
Declaration[] declarations,
WorkingMemory workingMemory) throws Exception {
DroolsMVELFactory factory = (DroolsMVELFactory) workingMemoryContext;
+ Package pkg = workingMemory.getRuleBase().getPackage( "MAIN" );
+ if ( pkg != null ) {
+ MVELDialectData data = (MVELDialectData) pkg.getDialectDatas().getDialectData( "mvel" );
+ factory.setNextFactory( data.getFunctionFactory() );
+ }
+
factory.setContext( leftTuple,
null,
null,
workingMemory,
- (Map) context );
+ ((MVELAccumulatorContext) context).variables );
MVEL.executeExpression( this.init,
null,
factory );
@@ -123,19 +135,35 @@
null,
handle.getObject(),
workingMemory,
- (Map) context );
+ ((MVELAccumulatorContext) context).variables );
- Package pkg = workingMemory.getRuleBase().getPackage( "MAIN" );
- if ( pkg != null ) {
- MVELDialectData data = ( MVELDialectData ) pkg.getDialectDatas().getDialectData( "mvel" );
- factory.setNextFactory( data.getFunctionFactory() );
+ if ( reverse != null ) {
+ // SNAPSHOT variable values
+ takeSnapshot( context,
+ factory,
+ handle );
}
-
MVEL.executeExpression( this.action,
null,
factory );
}
+ private void takeSnapshot(Object context,
+ DroolsMVELFactory factory,
+ InternalFactHandle handle) {
+ DroolsMVELShadowFactory shad = (DroolsMVELShadowFactory) factory;
+ Map<String, Object> varsMap = ((MVELAccumulatorContext) context).shadow.get( handle );
+ if ( varsMap == null ) {
+ varsMap = new HashMap<String, Object>();
+ ((MVELAccumulatorContext) context).shadow.put( handle,
+ varsMap );
+ }
+ for ( String var : shad.getShadowVariables() ) {
+ varsMap.put( var,
+ shad.getVariableResolver( var ).getValue() );
+ }
+ }
+
public void reverse(Object workingMemoryContext,
Object context,
Tuple leftTuple,
@@ -148,17 +176,19 @@
null,
handle.getObject(),
workingMemory,
- (Map) context );
-
- Package pkg = workingMemory.getRuleBase().getPackage( "MAIN" );
- if ( pkg != null ) {
- MVELDialectData data = ( MVELDialectData ) pkg.getDialectDatas().getDialectData( "mvel" );
- factory.setNextFactory( data.getFunctionFactory() );
- }
+ ((MVELAccumulatorContext) context).variables );
+ // set shadow values overriding actual values
+ // ALSO, since reverse() is called, we know the factory is a shadow factory
+ ((DroolsMVELShadowFactory) factory).setShadowValues( ((MVELAccumulatorContext) context).shadow.get( handle ) );
+
MVEL.executeExpression( this.reverse,
null,
factory );
+
+ // cleaning up shadow values map
+ ((DroolsMVELShadowFactory) factory).setShadowValues( null );
+ ((MVELAccumulatorContext) context).shadow.remove( handle );
}
/* (non-Javadoc)
@@ -174,14 +204,8 @@
null,
null,
workingMemory,
- (Map) context );
+ ((MVELAccumulatorContext) context).variables );
- Package pkg = workingMemory.getRuleBase().getPackage( "MAIN" );
- if ( pkg != null ) {
- MVELDialectData data = ( MVELDialectData ) pkg.getDialectDatas().getDialectData( "mvel" );
- factory.setNextFactory( data.getFunctionFactory() );
- }
-
final Object result = MVEL.executeExpression( this.result,
null,
factory );
@@ -196,4 +220,20 @@
return this.prototype.clone();
}
+ private static class MVELAccumulatorContext
+ implements
+ Serializable {
+
+ private static final long serialVersionUID = -308602705153011537L;
+
+ public final Map variables;
+ public final Map<InternalFactHandle, Map<String, Object>> shadow;
+
+ public MVELAccumulatorContext(final Map variables,
+ final Map<InternalFactHandle, Map<String, Object>> shadow) {
+ this.variables = variables;
+ this.shadow = shadow;
+ }
+ }
+
}
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java 2008-06-05 14:06:37 UTC (rev 20339)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java 2008-06-05 14:37:32 UTC (rev 20340)
@@ -113,7 +113,7 @@
return false;
}
- public Object createWorkingMemoryContext() {
+ public Object createWorkingMemoryContext( ) {
return null;
}
More information about the jboss-svn-commits
mailing list