[jboss-svn-commits] JBL Code SVN: r7116 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/base test/java/org/drools/base

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Oct 25 17:12:48 EDT 2006


Author: tirelli
Date: 2006-10-25 17:12:40 -0400 (Wed, 25 Oct 2006)
New Revision: 7116

Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java
Log:
JBRULES-44: fixing equals() and hashCode() methods to use local cached fields instead of delegating

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	2006-10-25 20:02:25 UTC (rev 7115)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java	2006-10-25 21:12:40 UTC (rev 7116)
@@ -114,26 +114,30 @@
         final Method[] methods = clazz.getMethods();
         for ( int i = 0; i < methods.length; i++ ) {
             if ( (!Modifier.isFinal( methods[i].getModifiers() )) && Modifier.isPublic( methods[i].getModifiers() ) ) {
-                if ( (!methods[i].getReturnType().equals( Void.TYPE )) && (methods[i].getParameterTypes().length == 0) ) {
+                if ( (!methods[i].getReturnType().equals( Void.TYPE )) && (methods[i].getParameterTypes().length == 0) &&
+                     (!methods[i].getName().equals( "hashCode" )) &&
+                     (!methods[i].getName().equals( "toString" )) ) {
+
                     final String fieldName = methods[i].getName();
 
-                    buildField( /*FIELD_NAME_PREFIX +*/fieldName,
+                    buildField( fieldName,
                                 Type.getDescriptor( methods[i].getReturnType() ),
                                 cw );
-                    fieldTypes.put( /*FIELD_NAME_PREFIX +*/fieldName,
-                                    methods[i].getReturnType() );
+                    fieldTypes.put( fieldName,
+                                    methods[i] );
 
-                    buildField( /*FIELD_NAME_PREFIX +*/fieldName + ShadowProxyFactory.FIELD_SET_FLAG,
+                    buildField( fieldName + ShadowProxyFactory.FIELD_SET_FLAG,
                                 Type.BOOLEAN_TYPE.getDescriptor(),
                                 cw );
-                    buildGetMethod( /*FIELD_NAME_PREFIX +*/fieldName,
+                    buildGetMethod( fieldName,
                                     methods[i].getReturnType(),
-                                    /*FIELD_NAME_PREFIX +*/fieldName + ShadowProxyFactory.FIELD_SET_FLAG,
+                                    fieldName + ShadowProxyFactory.FIELD_SET_FLAG,
                                     methods[i],
                                     className,
                                     clazz,
                                     cw );
-                } else {
+                } else if ( (!methods[i].getName().equals( "hashCode" )) && 
+                            (!methods[i].getName().equals( "equals" ) ) ) {
                     buildDelegateMethod( methods[i],
                                          clazz,
                                          className,
@@ -150,6 +154,16 @@
                                 className,
                                 cw );
 
+        buildEquals( cw,
+                     className,
+                     clazz,
+                     fieldTypes );
+
+        buildHashCode( cw,
+                     className,
+                     clazz,
+                     fieldTypes );
+
         return cw.toByteArray();
     }
 
@@ -472,6 +486,17 @@
         mv.visitJumpInsn( Opcodes.IFNE,
                           l1 );
 
+        //     __fieldIsSet = true;
+        final Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitInsn( Opcodes.ICONST_1 );
+        mv.visitFieldInsn( Opcodes.PUTFIELD,
+                           className,
+                           fieldFlag,
+                           Type.BOOLEAN_TYPE.getDescriptor() );
+
         //     __field = this.delegate.method();
         final Label l2 = new Label();
         mv.visitLabel( l2 );
@@ -499,17 +524,6 @@
                            fieldName,
                            Type.getDescriptor( fieldType ) );
 
-        //     __fieldIsSet = true;
-        final Label l3 = new Label();
-        mv.visitLabel( l3 );
-        mv.visitVarInsn( Opcodes.ALOAD,
-                         0 );
-        mv.visitInsn( Opcodes.ICONST_1 );
-        mv.visitFieldInsn( Opcodes.PUTFIELD,
-                           className,
-                           fieldFlag,
-                           Type.BOOLEAN_TYPE.getDescriptor() );
-
         // }
         // return __field;
         mv.visitLabel( l1 );
@@ -665,7 +679,7 @@
             final Map.Entry entry = (Map.Entry) it.next();
             final String fieldName = (String) entry.getKey();
             final String fieldFlag = fieldName + ShadowProxyFactory.FIELD_SET_FLAG;
-            final Class fieldType = (Class) entry.getValue();
+            final Class fieldType = (Class) ((Method) entry.getValue()).getReturnType();
             final Label l1 = new Label();
             mv.visitLabel( l1 );
             mv.visitVarInsn( Opcodes.ALOAD,
@@ -768,6 +782,464 @@
         mv.visitEnd();
     }
 
+    private static void buildEquals(ClassWriter cw,
+                                    String className,
+                                    final Class clazz,
+                                    Map fieldTypes) {
+        MethodVisitor mv;
+        // Building equals method
+        {
+            mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                 "equals",
+                                 Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                           new Type[]{Type.getType( Object.class )} ),
+                                 null,
+                                 null );
+            mv.visitCode();
+            Label l0 = new Label();
+            mv.visitLabel( l0 );
+
+            // if ( this == object )
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            Label l1 = new Label();
+            mv.visitJumpInsn( Opcodes.IF_ACMPNE,
+                              l1 );
+            //      return true;
+            mv.visitInsn( Opcodes.ICONST_1 );
+            mv.visitInsn( Opcodes.IRETURN );
+
+            // if (( object == null ) || ( ! ( object instanceof <class> ) ) ) 
+            mv.visitLabel( l1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            Label l3 = new Label();
+            mv.visitJumpInsn( Opcodes.IFNULL,
+                              l3 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitTypeInsn( Opcodes.INSTANCEOF,
+                              className );
+            Label l4 = new Label();
+            mv.visitJumpInsn( Opcodes.IFNE,
+                              l4 );
+
+            //       return false;
+            mv.visitLabel( l3 );
+            mv.visitInsn( Opcodes.ICONST_0 );
+            mv.visitInsn( Opcodes.IRETURN );
+
+            // <class> other = (<class>) object;
+            mv.visitLabel( l4 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitTypeInsn( Opcodes.CHECKCAST,
+                              className );
+            mv.visitVarInsn( Opcodes.ASTORE,
+                             2 );
+
+            // for each field:
+            int count = 0;
+            for ( Iterator it = fieldTypes.entrySet().iterator(); it.hasNext(); ) {
+                Map.Entry entry = (Map.Entry) it.next();
+                String name = (String) entry.getKey();
+                Method method = (Method) entry.getValue();
+                Class fieldType = method.getReturnType();
+                String fieldFlag = name + ShadowProxyFactory.FIELD_SET_FLAG;
+                count++;
+                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,
+                                   name,
+                                   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
+                    // if ( this.field != other.field ) 
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     0 );
+                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                                       className,
+                                       name,
+                                       Type.getDescriptor( fieldType ) );
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     2 );
+                    if ( clazz.isInterface() ) {
+                        mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                            className,
+                                            method.getName(),
+                                            Type.getMethodDescriptor( method ) );
+                    } else {
+                        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                            className,
+                                            method.getName(),
+                                            Type.getMethodDescriptor( method ) );
+                    }
+
+                    //                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                    //                                       className,
+                    //                                       name,
+                    //                                       Type.getDescriptor( fieldType ) );
+                    if ( fieldType.equals( Long.TYPE ) ) {
+                        mv.visitInsn( Opcodes.LCMP );
+                        mv.visitJumpInsn( Opcodes.IFEQ,
+                                          goNext );
+                    } else if ( fieldType.equals( Double.TYPE ) ) {
+                        mv.visitInsn( Opcodes.DCMPL );
+                        mv.visitJumpInsn( Opcodes.IFEQ,
+                                          goNext );
+                    } else if ( fieldType.equals( Float.TYPE ) ) {
+                        mv.visitInsn( Opcodes.FCMPL );
+                        mv.visitJumpInsn( Opcodes.IFEQ,
+                                          goNext );
+                    } else {
+                        mv.visitJumpInsn( Opcodes.IF_ICMPEQ,
+                                          goNext );
+                    }
+                    //     return false;
+                    mv.visitInsn( Opcodes.ICONST_0 );
+                    mv.visitInsn( Opcodes.IRETURN );
+                } else {
+                    // for non primitive types
+                    // if( ( ( this.field == null ) && ( other.field != null ) ) ||
+                    //     ( ( this.field != null ) && ( ! this.field.equals( other.field ) ) ) )
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     0 );
+                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                                       className,
+                                       name,
+                                       Type.getDescriptor( fieldType ) );
+                    Label secondIfPart = new Label();
+                    mv.visitJumpInsn( Opcodes.IFNONNULL,
+                                      secondIfPart );
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     2 );
+                    if ( clazz.isInterface() ) {
+                        mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                            className,
+                                            method.getName(),
+                                            Type.getMethodDescriptor( method ) );
+                    } else {
+                        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                            className,
+                                            method.getName(),
+                                            Type.getMethodDescriptor( method ) );
+                    }
+                    Label returnFalse = new Label();
+                    mv.visitJumpInsn( Opcodes.IFNONNULL,
+                                      returnFalse );
+                    mv.visitLabel( secondIfPart );
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     0 );
+                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                                       className,
+                                       name,
+                                       Type.getDescriptor( fieldType ) );
+                    mv.visitJumpInsn( Opcodes.IFNULL,
+                                      goNext );
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     0 );
+                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                                       className,
+                                       name,
+                                       Type.getDescriptor( fieldType ) );
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     2 );
+                    if ( clazz.isInterface() ) {
+                        mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                            className,
+                                            method.getName(),
+                                            Type.getMethodDescriptor( method ) );
+                    } else {
+                        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                            className,
+                                            method.getName(),
+                                            Type.getMethodDescriptor( method ) );
+                    }
+                    mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                        Type.getInternalName( fieldType ),
+                                        "equals",
+                                        Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                                  new Type[]{Type.getType( Object.class )} ) );
+                    mv.visitJumpInsn( Opcodes.IFNE,
+                                      goNext );
+                    //       return false;
+                    mv.visitLabel( returnFalse );
+                    mv.visitInsn( Opcodes.ICONST_0 );
+                    mv.visitInsn( Opcodes.IRETURN );
+                }
+                mv.visitLabel( goNext );
+            }
+            // if all fields were ok
+            if ( count > 0 ) {
+                // return true;
+                mv.visitInsn( Opcodes.ICONST_1 );
+                // if no fields exists
+            } else {
+                // return false;
+                mv.visitInsn( Opcodes.ICONST_0 );
+            }
+            mv.visitInsn( Opcodes.IRETURN );
+            Label lastLabel = new Label();
+            mv.visitLabel( lastLabel );
+
+            mv.visitLocalVariable( "this",
+                                   "L" + className + ";",
+                                   null,
+                                   l0,
+                                   lastLabel,
+                                   0 );
+            mv.visitLocalVariable( "object",
+                                   Type.getDescriptor( Object.class ),
+                                   null,
+                                   l0,
+                                   lastLabel,
+                                   1 );
+            mv.visitLocalVariable( "other",
+                                   "L" + className + ";",
+                                   null,
+                                   l0,
+                                   lastLabel,
+                                   2 );
+
+            mv.visitMaxs( 0,
+                          0 );
+            mv.visitEnd();
+        }
+    }
+
+    private static void buildHashCode(ClassWriter cw,
+                                      String className,
+                                      final Class clazz,
+                                      Map fieldTypes) {
+        MethodVisitor mv;
+        // Building hashcode method
+        {
+            mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                 "hashCode",
+                                 Type.getMethodDescriptor( Type.INT_TYPE,
+                                                           new Type[]{} ),
+                                 null,
+                                 null );
+            mv.visitCode();
+
+            // final int PRIME = 31;
+            Label l0 = new Label();
+            mv.visitLabel( l0 );
+            mv.visitIntInsn( Opcodes.BIPUSH,
+                             31 );
+            mv.visitVarInsn( Opcodes.ISTORE,
+                             1 );
+
+            // int result = 1;
+            Label l1 = new Label();
+            mv.visitLabel( l1 );
+            mv.visitInsn( Opcodes.ICONST_1 );
+            mv.visitVarInsn( Opcodes.ISTORE,
+                             2 );
+
+            // for each field:
+            int count = 0;
+            for ( Iterator it = fieldTypes.entrySet().iterator(); it.hasNext(); ) {
+                Map.Entry entry = (Map.Entry) it.next();
+                String name = (String) entry.getKey();
+                Method method = (Method) entry.getValue();
+                Class fieldType = method.getReturnType();
+                String fieldFlag = name + ShadowProxyFactory.FIELD_SET_FLAG;
+                count++;
+                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,
+                                   name,
+                                   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 );
+
+                // result = PRIME * result + <att hashcode>
+                Label l2 = new Label();
+                mv.visitLabel( l2 );
+                mv.visitIntInsn( Opcodes.BIPUSH,
+                                 31 );
+                mv.visitVarInsn( Opcodes.ILOAD,
+                                 2 );
+                mv.visitInsn( Opcodes.IMUL );
+
+                if ( fieldType.isPrimitive() ) {
+                    // for primitive types
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     0 );
+                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                                       className,
+                                       name,
+                                       Type.getDescriptor( fieldType ) );
+
+                    mv.visitInsn( Type.getType( fieldType ).getOpcode( Opcodes.IADD ) );
+                    mv.visitVarInsn( Type.getType( fieldType ).getOpcode( Opcodes.ISTORE ),
+                                     2 );
+
+                } else {
+                    // for non primitive types
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     0 );
+                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                                       className,
+                                       name,
+                                       Type.getDescriptor( fieldType ) );
+
+                    Label np1 = new Label();
+                    mv.visitJumpInsn( Opcodes.IFNONNULL,
+                                      np1 );
+                    mv.visitInsn( Opcodes.ICONST_0 );
+                    Label np2 = new Label();
+                    mv.visitJumpInsn( Opcodes.GOTO,
+                                      np2 );
+                    mv.visitLabel( np1 );
+                    mv.visitVarInsn( Opcodes.ALOAD,
+                                     0 );
+                    mv.visitFieldInsn( Opcodes.GETFIELD,
+                                       className,
+                                       name,
+                                       Type.getDescriptor( fieldType ) );
+                    mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                        Type.getInternalName( fieldType ),
+                                        "hashCode",
+                                        "()I" );
+                    mv.visitLabel( np2 );
+                    mv.visitInsn( Opcodes.IADD );
+                    mv.visitVarInsn( Opcodes.ISTORE,
+                                     2 );
+                }
+                mv.visitLabel( goNext );
+            }
+            mv.visitVarInsn( Opcodes.ILOAD,
+                             2 );
+            mv.visitInsn( Opcodes.IRETURN );
+            Label lastLabel = new Label();
+            mv.visitLabel( lastLabel );
+
+            mv.visitLocalVariable( "this",
+                                   "L"+className+";",
+                                   null,
+                                   l0,
+                                   lastLabel,
+                                   0 );
+            mv.visitLocalVariable( "PRIME",
+                                   Type.INT_TYPE.getDescriptor(),
+                                   null,
+                                   l0,
+                                   lastLabel,
+                                   1 );
+            mv.visitLocalVariable( "result",
+                                   Type.INT_TYPE.getDescriptor(),
+                                   null,
+                                   l1,
+                                   lastLabel,
+                                   2 );
+            mv.visitMaxs( 0,
+                          0 );
+            mv.visitEnd();
+        }
+    }
+
     /**
      * @param exceptionTypes
      * @return

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	2006-10-25 20:02:25 UTC (rev 7115)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java	2006-10-25 21:12:40 UTC (rev 7116)
@@ -281,5 +281,60 @@
             fail( "Error: " + e.getMessage() );
         }
     }
+    
+    public void testEqualsHashCodeForClass() {
+        try {
+            // creating original object
+            final String originalType = "stilton";
+            final int originalPrice = 15;
+            final Cheese cheese = new Cheese( originalType,
+                                        originalPrice );
 
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( Cheese.class );
+            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} );
+
+            int cheesehash = cheeseHashCode( cheese );
+            Assert.assertEquals( cheeseProxy1, cheeseProxy2 );
+            Assert.assertEquals( cheeseProxy2, cheeseProxy1 );
+            Assert.assertEquals( cheesehash, cheeseProxy1.hashCode() );
+            
+            // changing original values
+            final String actualType = "rotten stilton";
+            final int actualPrice = 1;
+            cheese.setType( actualType );
+            cheese.setPrice( actualPrice );
+
+            Assert.assertEquals( cheesehash, cheeseProxy1.hashCode() );
+            
+            // updating proxy1
+            ((ShadowProxy) cheeseProxy1).updateProxy();
+            
+            Assert.assertEquals( cheeseHashCode( cheese ), cheeseProxy1.hashCode() );
+
+            // now they are different
+            Assert.assertFalse( cheeseProxy1.equals( cheeseProxy2 ) );
+            Assert.assertFalse( cheeseProxy2.equals( cheeseProxy1 ) );
+            
+            // updating proxy2
+            ((ShadowProxy) cheeseProxy2).updateProxy();
+
+            // now they are equal again
+            Assert.assertEquals( cheeseProxy1, cheeseProxy2 );
+            Assert.assertEquals( cheeseProxy2, cheeseProxy1 );
+            
+        } catch ( final Exception e ) {
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+    
+    private int cheeseHashCode(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;
+    }
+
 }




More information about the jboss-svn-commits mailing list