From: <iro...@us...> - 2010-03-31 04:58:17
|
Revision: 198 http://pojomatic.svn.sourceforge.net/pojomatic/?rev=198&view=rev Author: iroberts Date: 2010-03-31 04:58:11 +0000 (Wed, 31 Mar 2010) Log Message: ----------- Expose the ability to determine if two classes are compatible for equality Modified Paths: -------------- trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomatic.java trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomator.java trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/internal/PojomatorImpl.java trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/PojomaticTest.java trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/internal/PojomatorImplTest.java Modified: trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomatic.java =================================================================== --- trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomatic.java 2010-03-12 06:49:21 UTC (rev 197) +++ trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomatic.java 2010-03-31 04:58:11 UTC (rev 198) @@ -124,6 +124,17 @@ return pojomator(getClass(pojo)).doEquals(pojo, other); } + /** + * Compute whether {@code classA} and {@code classB} are compatible for equality as specified + * by the documentation for {@link Pojomator#isCompatibleForEquality(Class)}. + * @param classA the first class to check for compatibility for equality + * @param classB the second class to check for compatibility for equality + * @return {@code true} if the two classes are compatible for equality, or {@code false} + * otherwise. + */ + public static boolean areCompatibleForEquals(Class<?> classA, Class<?> classB) { + return pojomator(classA).isCompatibleForEquality(classB); + } /** * Compute the differences between {@code pojo} and {@code other} among the properties Modified: trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomator.java =================================================================== --- trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomator.java 2010-03-12 06:49:21 UTC (rev 197) +++ trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/Pojomator.java 2010-03-31 04:58:11 UTC (rev 198) @@ -15,7 +15,8 @@ /** * A provider of the three standard {@code Object} methods, - * {@link Object#equals(Object)}, {@link Object#hashCode()} and {@link Object#toString()}. + * {@link Object#equals(Object)}, {@link Object#hashCode()} and {@link Object#toString()}, as + * well as a usefull method to aid in debugging, {@link #doDiff(Object, Object)}}. * * @param <T> the class this {@code Pojomator} is generated for. */ @@ -76,30 +77,17 @@ /** * Compute whether {@code instance} and {@code other} are equal to each other in the sense of - * {@code Object}'s {@link Object#equals(Object) equals} method. - * <p> - * For two instances to be considered equal, the first requirement is that their classes must be - * compatible for equality. Classes {@code A} and {@code B} are compatible for equality if - * they share a common superclass {@code C}, and for every class {@code D} which - * is a proper subclass of {@code C} and a superclass of {@code A} or {@code B} (including - * the classes {@code A} and {@code B} themselves), the following hold: - * <ul> - * <li>{@code D} has not added additional properties for inclusion in the {@code equals} calculation, and</li> - * <li>{@code D} has not been annotated with {@link OverridesEquals}</li> - * </ul> - * If {@code T} is an interface or is annotated with {@link SubclassCannotOverrideEquals}, - * then all subclasses of {@code T} are automatically assumed by {@code T}'s {@code Pojomator} - * to be comapatible for equals with each other and with {@code T}. Note that in this case. - * to add an {@link OverridesEquals} annotation or additional - * properties for inclusion in {@code equals} to a subclass of {@code T} will - * result in a violation of the contract for {@link Object#equals(Object)}. + * {@code Object}'s {@link Object#equals(Object) equals} method. For two instances to be + * considered equal, the first requirement is that their classes must be compatible for equality, + * as described in the documentation for {@link #isCompatibleForEquality(Class)}. * </p> * <p> - * More precisely, if {@code other} is null, this method returns {@code false}. Otherwise, it is verified that - * the class of {@code other} is compatible for {@code equals} with {@code T}; if not, then this method - * returns false. Otherwise, this method will return true provided that each property of {@code - * instance} which has a {@code PojomaticPolicy} other than {@code TO_STRING} or - * {@code NONE} is equal to the corresponding property of {@code other} in the following sense: + * More precisely, if {@code other} is null, this method returns {@code false}. Otherwise, if + * {@link #isCompatibleForEquality(Class) isCompatibleForEquals(other.getClass())} would return + * false, then this method will return false. Otherwise, this method will return true provided + * that each property of {@code instance} which has a {@code PojomaticPolicy} other than + * {@code TO_STRING} or {@code NONE} is equal to the corresponding property of {@code other} in + * the following sense: * <ul> * <li>Both are {@code null}, or</li> * <li>Both are reference-equals (==) to each other, or</li> @@ -122,6 +110,28 @@ boolean doEquals(T instance, Object other); /** + * Compute whether {@code otherClass} is compatible for equality with {@code T}. + * Classes {@code A} and {@code B} are compatible for equality if + * they share a common superclass {@code C}, and for every class {@code D} which + * is a proper subclass of {@code C} and a superclass of {@code A} or {@code B} (including + * the classes {@code A} and {@code B} themselves), the following hold: + * <ul> + * <li>{@code D} has not added additional properties for inclusion in the {@code equals} calculation, and</li> + * <li>{@code D} has not been annotated with {@link OverridesEquals}</li> + * </ul> + * If {@code T} is an interface or is annotated with {@link SubclassCannotOverrideEquals}, + * then all subclasses of {@code T} are automatically assumed by {@code T}'s {@code Pojomator} + * to be comapatible for equals with each other and with {@code T}. Note that in this case. + * to add an {@link OverridesEquals} annotation or additional + * properties for inclusion in {@code equals} to a subclass of {@code T} will + * result in a violation of the contract for {@link Object#equals(Object)}. + * @param otherClass the class to check for compatibility for equality with {@code T} + * @return {@code true} if {@code otherClass} is compatible for equality with {@code T}, and + * {@code false} otherwise. + */ + boolean isCompatibleForEquality(Class<?> otherClass); + + /** * Compute the differences between {@code instance} and {@code other} among the properties * examined by {@link #doEquals(Object, Object)}. Assuming that {@code instance} and {@code other} * are both non-null and have types which are compatible for equals, it is guaranteed that invoking Modified: trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/internal/PojomatorImpl.java =================================================================== --- trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/internal/PojomatorImpl.java 2010-03-12 06:49:21 UTC (rev 197) +++ trunk/PojomaticAll/Pojomatic/src/main/java/org/pojomatic/internal/PojomatorImpl.java 2010-03-31 04:58:11 UTC (rev 198) @@ -80,7 +80,7 @@ return false; } if (!instance.getClass().equals(other.getClass())) { - if (!classProperties.isCompatibleForEquals(other.getClass())) { + if (!isCompatibleForEquality(other.getClass())) { return false; } } @@ -93,6 +93,10 @@ return true; } + public boolean isCompatibleForEquality(Class<?> otherClass) { + return classProperties.isCompatibleForEquals(otherClass); + } + public int doHashCode(T instance) { int hashCode = HASH_CODE_SEED; if (instance == null) { Modified: trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/PojomaticTest.java =================================================================== --- trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/PojomaticTest.java 2010-03-12 06:49:21 UTC (rev 197) +++ trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/PojomaticTest.java 2010-03-31 04:58:11 UTC (rev 198) @@ -18,6 +18,7 @@ public static class Bean { @Property public final int x; public Bean(int x) { this.x = x; } + public Bean() { x = 0; } } private static Pojomator<Bean> BEAN_POJOMATOR = new PojomatorImpl<Bean>(Bean.class); @@ -70,4 +71,16 @@ assertTrue(Pojomatic.equals(new Bean(3), new Bean(3))); assertFalse(Pojomatic.equals(new Bean(3), new Bean(4))); } + + @Test + public void testCompatibleForEquality() { + class BeanSubClass extends Bean{}; + + class BeanWithExtraData extends Bean { + @Property public int getY() { return 0; } + } + assertTrue(Pojomatic.areCompatibleForEquals(Bean.class, BeanSubClass.class)); + assertFalse(Pojomatic.areCompatibleForEquals(Bean.class, BeanWithExtraData.class)); + assertFalse(Pojomatic.areCompatibleForEquals(BeanWithExtraData.class, Bean.class)); + } } Modified: trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/internal/PojomatorImplTest.java =================================================================== --- trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/internal/PojomatorImplTest.java 2010-03-12 06:49:21 UTC (rev 197) +++ trunk/PojomaticAll/Pojomatic/src/test/java/org/pojomatic/internal/PojomatorImplTest.java 2010-03-31 04:58:11 UTC (rev 198) @@ -332,7 +332,6 @@ public String getString() { return string; } } - assertEquals("Interface{int: {2}, string: {hello}}", pojomator.doToString(new Impl1())); assertEquals(( HASH_CODE_MULTIPLIER + 2)*HASH_CODE_MULTIPLIER + "hello".hashCode(), pojomator.doHashCode(new Impl1())); @@ -341,6 +340,15 @@ assertFalse(pojomator.doEquals(new Impl1(), "not even in the right hierarchy")); } + @Test public void testIsCompatibleForEquals() { + assertTrue(OBJECT_PROPERTY_POJOMATOR.isCompatibleForEquality(ObjectProperty.class)); + assertFalse(OBJECT_PROPERTY_POJOMATOR.isCompatibleForEquality(ObjectPairProperty.class)); + assertTrue(makePojomatorImpl(Interface.class).isCompatibleForEquality(new Interface() { + public int getInt() { return 0; } + public String getString() { return null; } + }.getClass())); + } + @Test public void testToString() { @SuppressWarnings("unused") class SimplePojo { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |