[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