[jboss-svn-commits] JBL Code SVN: r13088 - in labs/jbossrules/trunk: drools-core/src/main/java/org/drools and 7 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Jul 4 14:06:02 EDT 2007


Author: tirelli
Date: 2007-07-04 14:06:02 -0400 (Wed, 04 Jul 2007)
New Revision: 13088

Modified:
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/evaluators/ObjectFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java
Log:
JBRULES-966: fixing problem when asserting collection objects into working memory

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -61,7 +61,6 @@
 import org.drools.TestParam;
 import org.drools.WorkingMemory;
 import org.drools.Cheesery.Maturity;
-import org.drools.brms.client.modeldriven.brl.RuleAttribute;
 import org.drools.common.AbstractWorkingMemory;
 import org.drools.common.DroolsObjectInputStream;
 import org.drools.compiler.DrlParser;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -19,7 +19,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Serializable;
-import java.util.Set;
 
 import org.drools.rule.Package;
 import org.drools.ruleflow.common.core.Process;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -24,5 +24,7 @@
     public void updateProxy();
 
     public Object getShadowedObject();
+    
+    public void setShadowedObject(Object object);
 
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -19,6 +19,7 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -37,6 +38,8 @@
  */
 public class ShadowProxyFactory {
     private static final String UPDATE_PROXY         = "updateProxy";
+    private static final String SET_SHADOWED_OBJECT  = "setShadowedObject";
+    private static final String GET_SHADOWED_OBJECT  = "getShadowedObject";
 
     private static final String BASE_INTERFACE       = Type.getInternalName( ShadowProxy.class );
 
@@ -84,22 +87,24 @@
             throw new RuntimeDroolsException( e );
         }
     }
-    
-    protected static boolean isPossibleToGenerateTheProxyFor( final Class clazz) throws Exception {
+
+    protected static boolean isPossibleToGenerateTheProxyFor(final Class clazz) throws Exception {
         if ( (clazz.getModifiers() & Modifier.FINAL) != 0 ) {
             return false;
         }
         try {
-            Method equals = clazz.getMethod( "equals", new Class[] { Object.class } );
-            if( Modifier.isFinal( equals.getModifiers() ) ) {
+            Method equals = clazz.getMethod( "equals",
+                                             new Class[]{Object.class} );
+            if ( Modifier.isFinal( equals.getModifiers() ) ) {
                 return false;
             }
         } catch ( NoSuchMethodException e ) {
             // that's fine
         }
         try {
-            Method hashcode = clazz.getMethod( "hashCode", new Class[0] );
-            if( Modifier.isFinal( hashcode.getModifiers() ) ) {
+            Method hashcode = clazz.getMethod( "hashCode",
+                                               new Class[0] );
+            if ( Modifier.isFinal( hashcode.getModifiers() ) ) {
                 return false;
             }
         } catch ( NoSuchMethodException e ) {
@@ -114,9 +119,7 @@
      */
     public static String getInternalProxyClassNameForClass(final Class clazz) {
         String className = null;
-        if ( clazz.getPackage() != null && (
-                clazz.getPackage().getName().startsWith( "java." ) || clazz.getPackage().getName().startsWith( "javax." ) )
-                ) {
+        if ( clazz.getPackage() != null && (clazz.getPackage().getName().startsWith( "java." ) || clazz.getPackage().getName().startsWith( "javax." )) ) {
             className = "org/drools/shadow/" + Type.getInternalName( clazz ) + "ShadowProxy";
         } else {
             className = Type.getInternalName( clazz ) + "ShadowProxy";
@@ -127,9 +130,7 @@
     public static String getProxyClassNameForClass(final Class clazz) {
         String className = null;
         Package pkg = clazz.getPackage();
-        if ( pkg != null && 
-                (pkg.getName().startsWith( "java." ) || pkg.getName().startsWith( "javax." ) )
-                ) {
+        if ( pkg != null && (pkg.getName().startsWith( "java." ) || pkg.getName().startsWith( "javax." )) ) {
             className = "org.drools.shadow." + clazz.getName() + "ShadowProxy";
         } else {
             className = clazz.getName() + "ShadowProxy";
@@ -150,8 +151,10 @@
                     Type.getDescriptor( clazz ),
                     cw );
 
-        final Method getShadowed = ShadowProxy.class.getDeclaredMethod( "getShadowedObject",
-                                                                  new Class[]{} );
+        final Method getShadowed = ShadowProxy.class.getDeclaredMethod( GET_SHADOWED_OBJECT,
+                                                                        new Class[]{} );
+        final Method setShadowed = ShadowProxy.class.getDeclaredMethod( SET_SHADOWED_OBJECT,
+                                                                        new Class[]{Object.class} );
         buildSimpleGetMethod( ShadowProxyFactory.DELEGATE_FIELD_NAME,
                               clazz,
                               getShadowed,
@@ -159,6 +162,41 @@
                               clazz,
                               cw );
 
+        buildSetShadowedObject( clazz,
+                                className,
+                                setShadowed,
+                                cw );
+
+        if ( Collection.class.isAssignableFrom( clazz ) ) {
+            buildCollectionClass( clazz,
+                                  className,
+                                  cw );
+        } else {
+            buildRegularClass( clazz,
+                               className,
+                               cw );
+        }
+
+        return cw.toByteArray();
+    }
+
+    private static void buildCollectionClass(final Class clazz,
+                                             final String className,
+                                             final ClassWriter cw) {
+
+        buildConstructor( clazz,
+                          className,
+                          cw );
+
+        buildCollectionUpdateProxyMethod( clazz,
+                                          className,
+                                          cw );
+
+    }
+
+    private static void buildRegularClass(final Class clazz,
+                                          final String className,
+                                          final ClassWriter cw) {
         final Map fieldTypes = new HashMap();
         final Method[] methods = getMethods( clazz );
         for ( int i = 0; i < methods.length; i++ ) {
@@ -213,8 +251,6 @@
                        className,
                        clazz,
                        fieldTypes );
-
-        return cw.toByteArray();
     }
 
     /**
@@ -650,6 +686,115 @@
         mv.visitEnd();
     }
 
+    protected static void buildSetShadowedObject(final Class clazz,
+                                                 final String className,
+                                                 final Method setShadowed,
+                                                 final ClassWriter cw) {
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 setShadowed.getName(),
+                                                 Type.getMethodDescriptor( setShadowed ),
+                                                 null,
+                                                 null );
+        mv.visitCode();
+        Label l0 = new Label();
+        mv.visitLabel( l0 );
+        // this.delegate = (<clazz>) object;
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         1 );
+        mv.visitTypeInsn( Opcodes.CHECKCAST,
+                          Type.getInternalName( clazz ) );
+        mv.visitFieldInsn( Opcodes.PUTFIELD,
+                           className,
+                           DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+        if ( Collection.class.isAssignableFrom( clazz ) ) {
+            Label l1 = new Label();
+            mv.visitLabel( l1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                className,
+                                UPDATE_PROXY,
+                                Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                          new Type[0] ) );
+        }
+        Label l2 = new Label();
+        mv.visitLabel( l2 );
+        mv.visitInsn( Opcodes.RETURN );
+        Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l3,
+                               0 );
+        mv.visitLocalVariable( "object",
+                               Type.getDescriptor( Object.class ),
+                               null,
+                               l0,
+                               l3,
+                               1 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    protected static void buildCollectionUpdateProxyMethod(final Class clazz,
+                                                           final String className,
+                                                           final ClassWriter cw) {
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 ShadowProxyFactory.UPDATE_PROXY,
+                                                 Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                                           new Type[]{} ),
+                                                 null,
+                                                 null );
+        mv.visitCode();
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        // this.clear();
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                            className,
+                            "clear",
+                            Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                      new Type[0] ) );
+        Label l1 = new Label();
+        mv.visitLabel( l1 );
+        // this.addAll( this.delegate );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                            className,
+                            "addAll",
+                            Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                      new Type[]{Type.getType( Collection.class )} ) );
+        mv.visitInsn( Opcodes.POP );
+        Label l2 = new Label();
+        mv.visitLabel( l2 );
+        mv.visitInsn( Opcodes.RETURN );
+        Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l3,
+                               0 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
     protected static void buildDelegateMethod(final Method method,
                                               final Class clazz,
                                               final String className,
@@ -725,20 +870,33 @@
             final Label l0 = new Label();
             mv.visitLabel( l0 );
 
-            // if ( this == object )
+            // if ( this == object || this.delegate == object )
             mv.visitVarInsn( Opcodes.ALOAD,
                              0 );
             mv.visitVarInsn( Opcodes.ALOAD,
                              1 );
             final Label l1 = new Label();
-            mv.visitJumpInsn( Opcodes.IF_ACMPNE,
+            mv.visitJumpInsn( Opcodes.IF_ACMPEQ,
                               l1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            Label l2 = new Label();
+            mv.visitJumpInsn( Opcodes.IF_ACMPNE,
+                              l2 );
+            mv.visitLabel( l1 );
+
             //      return true;
             mv.visitInsn( Opcodes.ICONST_1 );
             mv.visitInsn( Opcodes.IRETURN );
 
             // if (( object == null ) || ( ! ( object instanceof <class> ) ) ) 
-            mv.visitLabel( l1 );
+            mv.visitLabel( l2 );
             mv.visitVarInsn( Opcodes.ALOAD,
                              1 );
             final Label l3 = new Label();
@@ -989,25 +1147,75 @@
         }
     }
 
+    protected static void buildCollectionEquals(final ClassWriter cw,
+                                                final String className,
+                                                final Class clazz) {
+
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 "equals",
+                                                 Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                                           new Type[]{Type.getType( Object.class )} ),
+                                                 null,
+                                                 null );
+        // if ( this == object ) {
+        Label l0 = new Label();
+        mv.visitLabel( l0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         1 );
+        Label l1 = new Label();
+        mv.visitJumpInsn( Opcodes.IF_ACMPNE,
+                          l1 );
+        //    return true;
+        Label l2 = new Label();
+        mv.visitLabel( l2 );
+        mv.visitInsn( Opcodes.ICONST_1 );
+        mv.visitInsn( Opcodes.IRETURN );
+        // }
+        mv.visitLabel( l1 );
+        // return this.delegate.equals( object );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         1 );
+        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                            Type.getInternalName( clazz ),
+                            "equals",
+                            Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                      new Type[]{Type.getType( Object.class )} ) );
+        mv.visitInsn( Opcodes.IRETURN );
+        Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l3,
+                               0 );
+        mv.visitLocalVariable( "object",
+                               Type.getDescriptor( Object.class ),
+                               null,
+                               l0,
+                               l3,
+                               1 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
     /**
      *  Sample of generated code for all primitive + object types
      *  
      *  public int hashCode() {
-     *       if( ___hashCache != 0 ) {
-     *           return __hashCache;
+     *       if( ___hashCache == 0 ) {
+     *           __hashCache = this.delegate.hashCode();
      *       }
-     *       final int PRIME = 31;
-     *       int result = 1;
-     *       result = PRIME * result + (booleanAttr ? 1231 : 1237);
-     *       result = PRIME * result + charAttr;
-     *       long temp = Double.doubleToLongBits( doubleAttr );
-     *       result = PRIME * result + (int) (temp ^ (temp >>> 32));
-     *       result = PRIME * result + Float.floatToIntBits( floatAttr );
-     *       result = PRIME * result + intAttr;
-     *       result = PRIME * result + ((listAttr == null) ? 0 : listAttr.hashCode());
-     *       result = PRIME * result + (int) (longAttr ^ (longAttr >>> 32));
-     *       result = PRIME * result + shortAttr;
-     *       return result;
+     *       return this.__hashCache;
      *   }
      * 
      * @param cw
@@ -1020,7 +1228,6 @@
                                         final Class clazz,
                                         final Map fieldTypes) {
         MethodVisitor mv;
-        boolean hasDoubleAttr = false;
         // Building hashcode method
         {
             mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
@@ -1031,293 +1238,59 @@
                                  null );
             mv.visitCode();
 
-            // if( __hashCache != 0 ) {
-            final Label ls = new Label();
-            mv.visitLabel( ls );
+            // if( this.__hashCache == 0 ) {
+            Label l0 = new Label();
+            mv.visitLabel( l0 );
             mv.visitVarInsn( Opcodes.ALOAD,
                              0 );
             mv.visitFieldInsn( Opcodes.GETFIELD,
                                className,
-                               ShadowProxyFactory.HASHCACHE_FIELD_NAME,
-                               Type.getDescriptor( int.class ) );
-            final Label afterIfCachedLabel = new Label();
-            mv.visitJumpInsn( Opcodes.IFEQ,
-                              afterIfCachedLabel );
-            //     return __hashCache;
-            // }
+                               HASHCACHE_FIELD_NAME,
+                               Type.INT_TYPE.getDescriptor() );
+            Label l1 = new Label();
+            mv.visitJumpInsn( Opcodes.IFNE,
+                              l1 );
+            Label l2 = new Label();
+            
+            //    this.__hashCache = this.delegate.hashCode();
+            mv.visitLabel( l2 );
             mv.visitVarInsn( Opcodes.ALOAD,
                              0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
             mv.visitFieldInsn( Opcodes.GETFIELD,
                                className,
-                               ShadowProxyFactory.HASHCACHE_FIELD_NAME,
-                               Type.getDescriptor( int.class ) );
-            mv.visitInsn( Opcodes.IRETURN );
-            mv.visitLabel( afterIfCachedLabel );
-
-            // final int PRIME = 31;
-            final Label l0 = new Label();
-            mv.visitLabel( l0 );
-            mv.visitIntInsn( Opcodes.BIPUSH,
-                             31 );
-            mv.visitVarInsn( Opcodes.ISTORE,
-                             1 );
-
-            // int result = 1;
-            final Label l1 = new Label();
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                Type.getInternalName( clazz ),
+                                "hashCode",
+                                Type.getMethodDescriptor( Type.INT_TYPE,
+                                                          new Type[0] ) );
+            mv.visitFieldInsn( Opcodes.PUTFIELD,
+                               className,
+                               HASHCACHE_FIELD_NAME,
+                               Type.INT_TYPE.getDescriptor() );
+            // }
             mv.visitLabel( l1 );
-            mv.visitInsn( Opcodes.ICONST_1 );
-            mv.visitVarInsn( Opcodes.ISTORE,
-                             2 );
-
-            // for each field:
-            int count = 0;
-            for ( final Iterator it = fieldTypes.entrySet().iterator(); it.hasNext(); ) {
-                final Map.Entry entry = (Map.Entry) it.next();
-                final String fieldName = (String) entry.getKey();
-                final Method method = (Method) entry.getValue();
-                final Class fieldType = method.getReturnType();
-                final String fieldFlag = fieldName + ShadowProxyFactory.FIELD_SET_FLAG;
-                count++;
-                final Label goNext = new Label();
-
-                // if ( ! _fieldIsSet ) {
-                final Label l5 = new Label();
-                mv.visitLabel( l5 );
-                mv.visitVarInsn( Opcodes.ALOAD,
-                                 0 );
-                mv.visitFieldInsn( Opcodes.GETFIELD,
-                                   className,
-                                   fieldFlag,
-                                   Type.BOOLEAN_TYPE.getDescriptor() );
-                final Label l6 = new Label();
-                mv.visitJumpInsn( Opcodes.IFNE,
-                                  l6 );
-
-                //     __field = this.delegate.method();
-                final Label l7 = new Label();
-                mv.visitLabel( l7 );
-                mv.visitVarInsn( Opcodes.ALOAD,
-                                 0 );
-                mv.visitVarInsn( Opcodes.ALOAD,
-                                 0 );
-                mv.visitFieldInsn( Opcodes.GETFIELD,
-                                   className,
-                                   ShadowProxyFactory.DELEGATE_FIELD_NAME,
-                                   Type.getDescriptor( clazz ) );
-                if ( clazz.isInterface() ) {
-                    mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
-                                        Type.getInternalName( clazz ),
-                                        method.getName(),
-                                        Type.getMethodDescriptor( method ) );
-                } else {
-                    mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
-                                        Type.getInternalName( clazz ),
-                                        method.getName(),
-                                        Type.getMethodDescriptor( method ) );
-                }
-                mv.visitFieldInsn( Opcodes.PUTFIELD,
-                                   className,
-                                   fieldName,
-                                   Type.getDescriptor( fieldType ) );
-
-                //     __fieldIsSet = true;
-                final Label l8 = new Label();
-                mv.visitLabel( l8 );
-                mv.visitVarInsn( Opcodes.ALOAD,
-                                 0 );
-                mv.visitInsn( Opcodes.ICONST_1 );
-                mv.visitFieldInsn( Opcodes.PUTFIELD,
-                                   className,
-                                   fieldFlag,
-                                   Type.BOOLEAN_TYPE.getDescriptor() );
-
-                // }
-                mv.visitLabel( l6 );
-
-                if ( fieldType.isPrimitive() ) {
-                    // for primitive types
-                    // result = PRIME * result + <att hashcode>
-                    final Label l2 = new Label();
-                    if ( fieldType == Double.TYPE ) {
-                        hasDoubleAttr = true;
-                        mv.visitVarInsn( Opcodes.ALOAD,
-                                         0 );
-                        mv.visitFieldInsn( Opcodes.GETFIELD,
-                                           className,
-                                           fieldName,
-                                           Type.getDescriptor( fieldType ) );
-                        mv.visitMethodInsn( Opcodes.INVOKESTATIC,
-                                            Type.getInternalName( Double.class ),
-                                            "doubleToLongBits",
-                                            "(D)J" );
-                        mv.visitVarInsn( Opcodes.LSTORE,
-                                         3 );
-                    }
-
-                    mv.visitLabel( l2 );
-                    mv.visitIntInsn( Opcodes.BIPUSH,
-                                     31 );
-                    mv.visitVarInsn( Opcodes.ILOAD,
-                                     2 );
-                    mv.visitInsn( Opcodes.IMUL );
-
-                    if ( fieldType != Double.TYPE ) {
-                        mv.visitVarInsn( Opcodes.ALOAD,
-                                         0 );
-                        mv.visitFieldInsn( Opcodes.GETFIELD,
-                                           className,
-                                           fieldName,
-                                           Type.getDescriptor( fieldType ) );
-                    }
-
-                    if ( fieldType == Boolean.TYPE ) {
-                        // att_hashcode ::= ( boolean_attribute ) ? 1231 : 1237;
-                        final Label z1 = new Label();
-                        mv.visitJumpInsn( Opcodes.IFEQ,
-                                          z1 );
-                        mv.visitIntInsn( Opcodes.SIPUSH,
-                                         1231 );
-                        final Label z2 = new Label();
-                        mv.visitJumpInsn( Opcodes.GOTO,
-                                          z2 );
-                        mv.visitLabel( z1 );
-                        mv.visitIntInsn( Opcodes.SIPUSH,
-                                         1237 );
-                        mv.visitLabel( z2 );
-                    } else if ( fieldType == Double.TYPE ) {
-                        // long temp = Double.doubleToLongBits( doubleAttr );
-                        // att_hashcode ::= (int) (temp ^ ( temp >>> 32 ) );
-                        final Label d1 = new Label();
-                        mv.visitLabel( d1 );
-                        mv.visitVarInsn( Opcodes.LLOAD,
-                                         3 );
-                        mv.visitVarInsn( Opcodes.LLOAD,
-                                         3 );
-                        mv.visitIntInsn( Opcodes.BIPUSH,
-                                         32 );
-                        mv.visitInsn( Opcodes.LUSHR );
-                        mv.visitInsn( Opcodes.LXOR );
-                        mv.visitInsn( Opcodes.L2I );
-                    } else if ( fieldType == Float.TYPE ) {
-                        // att_hashcode ::= Float.floatToIntBits( floatAttr );
-                        mv.visitMethodInsn( Opcodes.INVOKESTATIC,
-                                            Type.getInternalName( Float.class ),
-                                            "floatToIntBits",
-                                            "(F)I" );
-
-                    } else if ( fieldType == Long.TYPE ) {
-                        // att_hashcode ::= (int) (lontattr ^( longattr >>> 32 ) );
-                        mv.visitVarInsn( Opcodes.ALOAD,
-                                         0 );
-                        mv.visitFieldInsn( Opcodes.GETFIELD,
-                                           className,
-                                           fieldName,
-                                           Type.getDescriptor( fieldType ) );
-                        mv.visitIntInsn( Opcodes.BIPUSH,
-                                         32 );
-                        mv.visitInsn( Opcodes.LUSHR );
-                        mv.visitInsn( Opcodes.LXOR );
-                        mv.visitInsn( Opcodes.L2I );
-
-                    }
-                    mv.visitInsn( Opcodes.IADD );
-                    mv.visitVarInsn( Opcodes.ISTORE,
-                                     2 );
-
-                } else {
-                    // for non primitive types
-                    // result = PRIME * result + <att hashcode>
-                    final Label l2 = new Label();
-                    mv.visitLabel( l2 );
-                    mv.visitIntInsn( Opcodes.BIPUSH,
-                                     31 );
-                    mv.visitVarInsn( Opcodes.ILOAD,
-                                     2 );
-                    mv.visitInsn( Opcodes.IMUL );
-
-                    mv.visitVarInsn( Opcodes.ALOAD,
-                                     0 );
-                    mv.visitFieldInsn( Opcodes.GETFIELD,
-                                       className,
-                                       fieldName,
-                                       Type.getDescriptor( fieldType ) );
-
-                    final Label np1 = new Label();
-                    mv.visitJumpInsn( Opcodes.IFNONNULL,
-                                      np1 );
-                    mv.visitInsn( Opcodes.ICONST_0 );
-                    final Label np2 = new Label();
-                    mv.visitJumpInsn( Opcodes.GOTO,
-                                      np2 );
-                    mv.visitLabel( np1 );
-                    mv.visitVarInsn( Opcodes.ALOAD,
-                                     0 );
-                    mv.visitFieldInsn( Opcodes.GETFIELD,
-                                       className,
-                                       fieldName,
-                                       Type.getDescriptor( fieldType ) );
-                    if ( fieldType.isInterface() ) {
-                        mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
-                                            Type.getInternalName( fieldType ),
-                                            "hashCode",
-                                            "()I" );
-                    } else {
-                        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
-                                            Type.getInternalName( fieldType ),
-                                            "hashCode",
-                                            "()I" );
-                    }
-                    mv.visitLabel( np2 );
-                    mv.visitInsn( Opcodes.IADD );
-                    mv.visitVarInsn( Opcodes.ISTORE,
-                                     2 );
-                }
-                mv.visitLabel( goNext );
-            }
-
-            // __hashCache = result;
+            
+            // return this.__hashCache;
             mv.visitVarInsn( Opcodes.ALOAD,
                              0 );
-            mv.visitVarInsn( Opcodes.ILOAD,
-                             2 );
-            mv.visitFieldInsn( Opcodes.PUTFIELD,
+            mv.visitFieldInsn( Opcodes.GETFIELD,
                                className,
-                               ShadowProxyFactory.HASHCACHE_FIELD_NAME,
-                               Type.getDescriptor( int.class ) );
-
-            // return result;
-            mv.visitVarInsn( Opcodes.ILOAD,
-                             2 );
+                               HASHCACHE_FIELD_NAME,
+                               Type.INT_TYPE.getDescriptor() );
             mv.visitInsn( Opcodes.IRETURN );
-            final Label lastLabel = new Label();
-            mv.visitLabel( lastLabel );
-
+            Label l3 = new Label();
+            mv.visitLabel( l3 );
             mv.visitLocalVariable( "this",
                                    "L" + className + ";",
                                    null,
                                    l0,
-                                   lastLabel,
+                                   l3,
                                    0 );
-            mv.visitLocalVariable( "PRIME",
-                                   Type.INT_TYPE.getDescriptor(),
-                                   null,
-                                   l0,
-                                   lastLabel,
-                                   1 );
-            mv.visitLocalVariable( "result",
-                                   Type.INT_TYPE.getDescriptor(),
-                                   null,
-                                   l1,
-                                   lastLabel,
-                                   2 );
-            if ( hasDoubleAttr ) {
-                mv.visitLocalVariable( "temp",
-                                       Type.LONG_TYPE.getDescriptor(),
-                                       null,
-                                       l1,
-                                       lastLabel,
-                                       3 );
-            }
+
             mv.visitMaxs( 0,
                           0 );
             mv.visitEnd();

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/evaluators/ObjectFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/evaluators/ObjectFactory.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/evaluators/ObjectFactory.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -19,6 +19,7 @@
 import java.util.Collection;
 
 import org.drools.base.BaseEvaluator;
+import org.drools.base.ShadowProxy;
 import org.drools.base.ValueType;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
@@ -104,6 +105,9 @@
             if ( value1 == null ) {
                 return value2 == null;
             }
+            if( value2 != null && value2 instanceof ShadowProxy ) {
+                return value2.equals( value1 );
+            }
             return value1.equals( value2 );
         }
 
@@ -113,6 +117,9 @@
             if ( value == null ) {
                 return ((ObjectVariableContextEntry) context).right == null;
             }
+            if( ((ObjectVariableContextEntry) context).right != null && ((ObjectVariableContextEntry) context).right instanceof ShadowProxy ) {
+                return ((ObjectVariableContextEntry) context).right.equals( value );
+            }
             return value.equals( ((ObjectVariableContextEntry) context).right );
         }
 
@@ -122,6 +129,9 @@
             if ( ((ObjectVariableContextEntry) context).left == null ) {
                 return value == null;
             }
+            if( value != null && value instanceof ShadowProxy ) {
+                return value.equals( ((ObjectVariableContextEntry) context).left );
+            }
             return ((ObjectVariableContextEntry) context).left.equals( value );
         }
 
@@ -134,6 +144,9 @@
             if ( value1 == null ) {
                 return value2 == null;
             }
+            if( value2 != null && value2 instanceof ShadowProxy ) {
+                return value2.equals( value1 );
+            }
             return value1.equals( value2 );
         }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -16,7 +16,6 @@
 
 package org.drools.base.extractors;
 
-import org.drools.base.ShadowProxy;
 import org.drools.base.ValueType;
 import org.drools.common.InternalWorkingMemory;
 
@@ -37,7 +36,8 @@
     }
 
     public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
-        return (object instanceof ShadowProxy) ? ((ShadowProxy) object).getShadowedObject() : object;
+        //return (object instanceof ShadowProxy) ? ((ShadowProxy) object).getShadowedObject() : object;
+        return object;
     }   
     
     public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -1167,7 +1167,7 @@
                                                                                       this.agenda.getDormantActivations() );
             doRetract( handle,
                        propagationContext );
-
+            
             if ( (originalObject != object) || (this.ruleBase.getConfiguration().getAssertBehaviour() != AssertBehaviour.IDENTITY) ) {
                 // as assertMap may be using an "identity" equality comparator,
                 // we need to remove the handle from the map, before replacing the object

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -23,7 +23,6 @@
 import org.drools.spi.PropagationContext;
 import org.drools.util.FactEntry;
 import org.drools.util.Iterator;
-import org.drools.util.AbstractHashTable.FactEntryImpl;
 
 /**
  * <code>ExistsNode</code> extends <code>BetaNode</code> to perform tests for

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -22,7 +22,6 @@
 import org.drools.spi.PropagationContext;
 import org.drools.util.FactEntry;
 import org.drools.util.Iterator;
-import org.drools.util.AbstractHashTable.FactEntryImpl;
 
 /**
  * <code>JoinNode</code> extends <code>BetaNode</code> to perform

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -23,7 +23,6 @@
 import org.drools.spi.PropagationContext;
 import org.drools.util.FactEntry;
 import org.drools.util.Iterator;
-import org.drools.util.AbstractHashTable.FactEntryImpl;
 
 /**
  * <code>NotNode</code> extends <code>BetaNode</code> to perform tests for

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -19,8 +19,8 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 import org.drools.FactException;
@@ -310,7 +310,6 @@
         protected boolean                      shadowEnabled;
         protected Class                        shadowClass;
         protected transient ObjectInstantiator instantiator;
-        protected transient Field              delegate;
 
         //private final InternalRuleBase ruleBase;
 
@@ -355,7 +354,6 @@
                 this.shadowClass = shadowClass;
                 this.shadowEnabled = true;
                 setInstantiator();
-                setDelegateFieldObject();
             }
         }
 
@@ -372,32 +370,25 @@
             this.instantiator = OBJENESIS.getInstantiatorOf( this.shadowClass );
         }
 
-        /**
-         * 
-         */
-        private void setDelegateFieldObject() {
-            try {
-                this.delegate = this.shadowClass.getDeclaredField( ShadowProxyFactory.DELEGATE_FIELD_NAME );
-                this.delegate.setAccessible( true );
-            } catch ( final Exception e ) {
-                throw new RuntimeDroolsException( "Error retriving delegate field for shadow proxy class: " + this.shadowClass.getName(),
-                                                  e );
-            }
-        }
-
         public Object getShadow(final Object fact) throws RuntimeDroolsException {
             ShadowProxy proxy = null;
             if ( isShadowEnabled() ) {
                 try {
-                    if ( this.delegate == null ) {
-                        this.setDelegateFieldObject();
+                    if( Collection.class.isAssignableFrom( this.shadowClass ) ) {
+                        // if it is a collection, try to instantiate using constructor
+                        try {
+                            proxy = (ShadowProxy) this.shadowClass.getConstructor( new Class[] { cls } ).newInstance( new Object[] { fact } );
+                        } catch ( Exception e ) {
+                            // not possible to instantiate using constructor
+                        }
                     }
-                    if ( this.instantiator == null ) {
-                        this.setInstantiator();
+                    if( proxy == null ) {
+                        if ( this.instantiator == null ) {
+                            this.setInstantiator();
+                        }
+                        proxy = (ShadowProxy) this.instantiator.newInstance();
                     }
-                    proxy = (ShadowProxy) this.instantiator.newInstance();
-                    this.delegate.set( proxy,
-                                       fact );
+                    proxy.setShadowedObject( fact );
                 } catch ( final Exception e ) {
                     throw new RuntimeDroolsException( "Error creating shadow fact for object: " + fact,
                                                       e );

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -173,12 +173,12 @@
             final Cheese cheeseProxy1 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
             final Cheese cheeseProxy2 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
 
-            final int cheesehash = cheeseHashCode( cheese );
+            int cheeseHash = cheese.hashCode();
             Assert.assertEquals( cheeseProxy1,
                                  cheeseProxy2 );
             Assert.assertEquals( cheeseProxy2,
                                  cheeseProxy1 );
-            Assert.assertEquals( cheesehash,
+            Assert.assertEquals( cheeseHash,
                                  cheeseProxy1.hashCode() );
 
             // changing original values
@@ -187,13 +187,14 @@
             cheese.setType( actualType );
             cheese.setPrice( actualPrice );
 
-            Assert.assertEquals( cheesehash,
+            Assert.assertEquals( cheeseHash,
                                  cheeseProxy1.hashCode() );
 
             // updating proxy1
             ((ShadowProxy) cheeseProxy1).updateProxy();
+            cheeseHash = cheese.hashCode();
 
-            Assert.assertEquals( cheeseHashCode( cheese ),
+            Assert.assertEquals( cheeseHash,
                                  cheeseProxy1.hashCode() );
 
             // now they are different
@@ -234,13 +235,13 @@
     //        }
     //    }
 
-    private int cheeseHashCode(final Cheese cheese) {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ((cheese.getType() == null) ? 0 : cheese.getType().hashCode());
-        result = PRIME * result + cheese.getPrice();
-        return result;
-    }
+//    private int cheeseHashCode(final Cheese cheese) {
+//        final int PRIME = 31;
+//        int result = 1;
+//        result = PRIME * result + ((cheese.getType() == null) ? 0 : cheese.getType().hashCode());
+//        result = PRIME * result + cheese.getPrice();
+//        return result;
+//    }
 
     public void testClassWithStaticMethod() {
         try {
@@ -255,7 +256,7 @@
             final Cheese cheeseProxy1 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
             final Cheese cheeseProxy2 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
 
-            final int cheesehash = cheeseHashCode( cheese );
+            final int cheesehash = cheese.hashCode();
             Assert.assertEquals( cheeseProxy1,
                                  cheeseProxy2 );
             Assert.assertEquals( cheeseProxy2,
@@ -282,7 +283,7 @@
             final Cheese cheeseProxy1 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
             final Cheese cheeseProxy2 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
 
-            final int cheesehash = cheeseHashCode( cheese );
+            final int cheesehash = cheese.hashCode();
             Assert.assertEquals( cheeseProxy1,
                                  cheeseProxy2 );
             Assert.assertEquals( cheeseProxy2,
@@ -296,4 +297,47 @@
         }
     }
 
+    public void testProxyForCollections() {
+        try {
+            // creating original object
+            List originalList = new ArrayList();
+            originalList.add( "a" );
+            originalList.add( "b" );
+            originalList.add( "c" );
+            originalList.add( "d" );
+            
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( originalList.getClass() );
+            final List listProxy = (List) proxy.getConstructor( new Class[]{originalList.getClass()} ).newInstance( new Object[]{originalList} );
+            ((ShadowProxy)listProxy).setShadowedObject( originalList );
+
+            // proxy is proxying the values
+            Assert.assertEquals( "a",
+                                 listProxy.get( 0 ) );
+            Assert.assertTrue( listProxy.contains( "c" ) );
+            Assert.assertSame( originalList,
+                               ((ShadowProxy) listProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( listProxy,
+                                 originalList );
+            
+            originalList.remove( "c" );
+            originalList.add( "e" );
+            Assert.assertTrue( listProxy.contains( "c" ) );
+            Assert.assertFalse( listProxy.contains( "e" ) );
+            
+            ((ShadowProxy)listProxy).updateProxy();
+            Assert.assertFalse( listProxy.contains( "c" ) );
+            Assert.assertTrue( listProxy.contains( "e" ) );
+            
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( listProxy,
+                                 originalList );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
 }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java	2007-07-04 18:03:06 UTC (rev 13087)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java	2007-07-04 18:06:02 UTC (rev 13088)
@@ -33,7 +33,6 @@
 import org.drools.spi.PropagationContext;
 import org.drools.util.FactEntry;
 import org.drools.util.Iterator;
-import org.drools.util.AbstractHashTable.FactEntryImpl;
 
 public class JoinNodeTest extends DroolsTestCase {
     Rule                rule;




More information about the jboss-svn-commits mailing list