Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Signed-off-by: unknown <jonathan.lee@WKS-E32.hq.vistair.com>
  • Loading branch information
unknown authored and unknown committed Jul 25, 2013
commit 2271bf37ce086bfb420692cee80dba1747ac2b59
11 changes: 11 additions & 0 deletions src/main/java/de/danielbechler/diff/BeanDiffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ public final Node compare(final Node parentNode, final Instances instances)
{
beanNode.setState(Node.State.IGNORED);
}
else if (nodeInspector.isWithMethodEquals(beanNode)){
String method = nodeInspector.getWithMethodEqualsMethod(beanNode);
if (instances.areMethodResultEqual(method))
{
beanNode.setState(Node.State.UNTOUCHED);
}
else
{
beanNode.setState(Node.State.CHANGED);
}
}
else if (instances.areNull() || instances.areSame())
{
beanNode.setState(Node.State.UNTOUCHED);
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/de/danielbechler/diff/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ public enum PrimitiveDefaultValueMode
private final Collection<PropertyPath> includedProperties = new HashSet<PropertyPath>(10);
private final Collection<PropertyPath> excludedProperties = new HashSet<PropertyPath>(10);
private final Collection<PropertyPath> equalsOnlyProperties = new LinkedHashSet<PropertyPath>(10);
private final Collection<MethodEqualPropertyPathAndMethod> methodEqualProperties = new LinkedHashSet<MethodEqualPropertyPathAndMethod>(10);
private final Collection<PropertyPathAndMethod> methodEqualProperties = new LinkedHashSet<PropertyPathAndMethod>(10);
private final Collection<Class<?>> compareToOnlyTypes = new LinkedHashSet<Class<?>>(10);
private final Collection<Class<?>> equalsOnlyTypes = new LinkedHashSet<Class<?>>(10);
private final Collection<MethodEqualClassAndMethod> methodEqualTypes = new LinkedHashSet<MethodEqualClassAndMethod>(10);
private final Collection<ClassAndMethod> methodEqualTypes = new LinkedHashSet<ClassAndMethod>(10);
private boolean returnUnchangedNodes = false;
private boolean returnIgnoredNodes = false;
private boolean returnCircularNodes = true;
Expand Down Expand Up @@ -147,11 +147,11 @@ public Configuration withEqualsOnlyProperty(final PropertyPath propertyPath)
}

public Configuration withMethodEqualsProperty(final PropertyPath propertyPath, final String methodName) {
this.methodEqualProperties.add(new MethodEqualPropertyPathAndMethod(propertyPath, methodName));
this.methodEqualProperties.add(new PropertyPathAndMethod(propertyPath, methodName));
return this;
}

public Configuration withMethodEqualsProperty(MethodEqualPropertyPathAndMethod propertyPathEqualsMethod) {
public Configuration withMethodEqualsProperty(PropertyPathAndMethod propertyPathEqualsMethod) {
this.methodEqualProperties.add(propertyPathEqualsMethod);
return this;
}
Expand Down Expand Up @@ -337,7 +337,7 @@ public String getWithMethodEqualsMethod(Node node){
return annotation.method();
}

MethodEqualClassAndMethod applicable = findMethodEqualPropertyForClass(propertyType);
ClassAndMethod applicable = findMethodEqualPropertyForClass(propertyType);
if (applicable != null)
{
return applicable.getMethod();
Expand All @@ -347,16 +347,16 @@ public String getWithMethodEqualsMethod(Node node){
{
return node.getWithMethodEqualsMethod();
}
MethodEqualPropertyPathAndMethod applicable = findMethodEqualPropertyForPath(node.getPropertyPath());
PropertyPathAndMethod applicable = findMethodEqualPropertyForPath(node.getPropertyPath());
if (applicable != null)
{
return applicable.getMethod();
}
return null;
}

private MethodEqualClassAndMethod findMethodEqualPropertyForClass(Class<?> clazz){
for(MethodEqualClassAndMethod propertyPathEqualsMethod: methodEqualTypes){
private ClassAndMethod findMethodEqualPropertyForClass(Class<?> clazz){
for(ClassAndMethod propertyPathEqualsMethod: methodEqualTypes){
if(clazz.equals(propertyPathEqualsMethod.getClazz())){
return propertyPathEqualsMethod;
}
Expand All @@ -365,8 +365,8 @@ private MethodEqualClassAndMethod findMethodEqualPropertyForClass(Class<?> clazz

}

private MethodEqualPropertyPathAndMethod findMethodEqualPropertyForPath(PropertyPath propertyPath){
for(MethodEqualPropertyPathAndMethod propertyPathEqualsMethod: methodEqualProperties){
private PropertyPathAndMethod findMethodEqualPropertyForPath(PropertyPath propertyPath){
for(PropertyPathAndMethod propertyPathEqualsMethod: methodEqualProperties){
if(propertyPath.equals(propertyPathEqualsMethod.getPropertyPath())){
return propertyPathEqualsMethod;
}
Expand Down
52 changes: 34 additions & 18 deletions src/main/java/de/danielbechler/diff/example/MethodEqualExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import de.danielbechler.diff.Configuration;
import de.danielbechler.diff.ObjectDifferFactory;
import de.danielbechler.diff.annotation.ObjectDiffMethodEqualsType;
import de.danielbechler.diff.annotation.ObjectDiffProperty;
import de.danielbechler.diff.example.IgnoreExample.User;
import de.danielbechler.diff.node.Node;
import de.danielbechler.diff.path.PropertyPath;
import de.danielbechler.diff.visitor.PrintingVisitor;
Expand All @@ -18,17 +18,15 @@ private MethodEqualExample()

public static void main(final String[] args)
{
List<Object> baseItems = new ArrayList<Object>();
baseItems.add("baseitem");
final EncompassingClass base = new EncompassingClass(baseItems);
List<Object> workingItems = new ArrayList<Object>();
workingItems.add("workingitem");
final EncompassingClass working = new EncompassingClass(workingItems);
PropertyClass prop = new PropertyClass("1", "2");
final EncompassingClass base = new EncompassingClass(prop);
PropertyClass prop2 = new PropertyClass("1", "3");
final EncompassingClass working = new EncompassingClass(prop2);

final Configuration configuration = new Configuration();

// (Option 1) Causes the ObjectDiffer to use the method "size" on the 'items' property of the root object
configuration.withMethodEqualsProperty(PropertyPath.buildWith("items"), "size");
// (Option 1) Causes the ObjectDiffer to compare using the method "getProp1" on the 'prop' property of the root object
configuration.withMethodEqualsProperty(PropertyPath.buildWith("prop"), "getProp1");

final Node node = ObjectDifferFactory.getInstance(configuration).compare(working, base);

Expand All @@ -37,24 +35,42 @@ public static void main(final String[] args)
// Output with ignore:
// Property at path '/' has not changed
// Output without ignore:
// Property at path '/items[workingitem]' has been added => [ workingitem ]
// Property at path '/items[baseitem]' with value [ baseitem ] has been removed
// Property at path '/prop/prop2' has changed from [ 2 ] to [ 3 ]
}

public static class EncompassingClass
{
private final List<Object> items;
private final PropertyClass prop;

public EncompassingClass(final List<Object> items)
public EncompassingClass(final PropertyClass prop)
{
this.items = items;
this.prop = prop;
}

/* (Option 2) This annotation causes the ObjectDiffer to always ignore this property */
@ObjectDiffProperty(methodEqual = "size")
public List<Object> getItems()
/* (Option 2) This annotation causes the ObjectDiffer to use getProp1 method to compare */
//@ObjectDiffProperty(methodEqual = "getProp1")
public PropertyClass getProp() {
return prop;
}
}

/* (Option 3) This annotation causes the ObjectDiffer to use getProp1 method to compare */
//@ObjectDiffMethodEqualsType(method="getProp1")
public static class PropertyClass
{
private String prop1;
private String prop2;

public PropertyClass(String prop1, String prop2)
{
return items;
this.prop1 = prop1;
this.prop2 = prop2;
}
public String getProp1() {
return prop1;
}
public String getProp2() {
return prop2;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package de.danielbechler.diff.path;

public class MethodEqualClassAndMethod {
public class ClassAndMethod {
private Class<?> clazz;
private String method;
public MethodEqualClassAndMethod(Class<?> clazz, String method){
public ClassAndMethod(Class<?> clazz, String method){
this.clazz = clazz;
this.method = method;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package de.danielbechler.diff.path;

public class MethodEqualPropertyPathAndMethod {
public class PropertyPathAndMethod {
private PropertyPath propertyPath;
private String method;

public MethodEqualPropertyPathAndMethod(){}
public MethodEqualPropertyPathAndMethod(PropertyPath propertyPath, String method){
public PropertyPathAndMethod(){}
public PropertyPathAndMethod(PropertyPath propertyPath, String method){
this.propertyPath = propertyPath;
this.method = method;
}
Expand Down
30 changes: 30 additions & 0 deletions src/test/java/de/danielbechler/diff/BeanDifferShould.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.mockito.Mock;
import org.testng.annotations.*;

import static de.danielbechler.diff.node.Node.State.CHANGED;
import static de.danielbechler.diff.node.Node.State.UNTOUCHED;
import static de.danielbechler.diff.node.NodeAssertions.assertThat;
import static java.util.Arrays.*;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -120,6 +122,34 @@ public void compare_bean_via_equals()

assertThat(node).self().isUntouched();
}

@Test
public void detect_no_change_when_comparing_using_with_method_equals_and_result_is_same()
{
final ObjectWithNestedObject working = new ObjectWithNestedObject("foo");
working.setObject(new ObjectWithNestedObject("childid"));
final ObjectWithNestedObject base = new ObjectWithNestedObject("foo");
base.setObject(new ObjectWithNestedObject("differentchildid"));
configuration.withMethodEqualsProperty(PropertyPath.buildRootPath(), "getId");

final Node node = differ.compare(Node.ROOT, Instances.of(working, base));

assertThat(node).self().isUntouched();
}

@Test
public void detect_change_when_comparing_using_with_method_equals_and_result_is_different()
{
final ObjectWithNestedObject working = new ObjectWithNestedObject("foo");
working.setObject(new ObjectWithNestedObject("childid"));
final ObjectWithNestedObject base = new ObjectWithNestedObject("bar");
base.setObject(new ObjectWithNestedObject("differentchildid"));
configuration.withMethodEqualsProperty(PropertyPath.buildRootPath(), "getId");

final Node node = differ.compare(Node.ROOT, Instances.of(working, base));

assertThat(node).self().hasChanges();
}

@Test
public void compare_bean_via_introspection_and_delegate_comparison_of_properties()
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/de/danielbechler/diff/CollectionDifferShould.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

import java.util.*;

import static de.danielbechler.diff.node.Node.State.CHANGED;
import static de.danielbechler.diff.node.Node.State.UNTOUCHED;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import static org.mockito.Mockito.*;
Expand Down Expand Up @@ -118,6 +120,26 @@ public void compare_only_via_equals_if_equals_only_is_enabled()
compare();
verify(collectionNode).setState(Node.State.UNTOUCHED);
}

@Test
public void detect_no_change_when_comparing_using_with_method_equals_and_result_is_same()
{
when(nodeInspector.isWithMethodEquals(collectionNode)).thenReturn(true);
when(nodeInspector.getWithMethodEqualsMethod(collectionNode)).thenReturn("somemethod");
when(instances.areMethodResultEqual("somemethod")).thenReturn(true);
compare();
verify(collectionNode).setState(Node.State.UNTOUCHED);
}

@Test
public void detect_change_when_comparing_using_with_method_equals_and_result_is_different()
{
when(nodeInspector.isWithMethodEquals(collectionNode)).thenReturn(true);
when(nodeInspector.getWithMethodEqualsMethod(collectionNode)).thenReturn("somemethod");
when(instances.areMethodResultEqual("somemethod")).thenReturn(false);
compare();
verify(collectionNode).setState(CHANGED);
}

@Test
public void detect_changes_if_equals_only_is_enabled()
Expand Down
47 changes: 47 additions & 0 deletions src/test/java/de/danielbechler/diff/InstancesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package de.danielbechler.diff;

import de.danielbechler.diff.accessor.*;
import de.danielbechler.diff.mock.ObjectWithString;

import org.testng.annotations.*;

import java.lang.reflect.*;
Expand Down Expand Up @@ -120,6 +122,51 @@ public void testIsPrimitiveTypeReturnsFalseForComplexType()
assertThat(new Instances(RootAccessor.getInstance(), "1", "2", null).isPrimitiveType()).isFalse();
}

@Test
public void testMethodResultNotEqual() throws Exception
{
final Method readMethod = getClass().getDeclaredMethod("getTestValue");
final PropertyAccessor accessor = new PropertyAccessor("testValue", readMethod, null);

ObjectWithString working = new ObjectWithString("string1");
ObjectWithString base = new ObjectWithString("string2");

final Instances instances = new Instances(accessor, working, base, null);
assertThat(instances.areMethodResultEqual("getValue")).isFalse();
}

@Test
public void testMethodResultEqual() throws Exception
{
final Method readMethod = getClass().getDeclaredMethod("getTestValue");
final PropertyAccessor accessor = new PropertyAccessor("testValue", readMethod, null);

ObjectWithString working = new ObjectWithString("string");
ObjectWithString base = new ObjectWithString("string");

final Instances instances = new Instances(accessor, working, base, null);
assertThat(instances.areMethodResultEqual("getValue")).isTrue();
}

@Test
public void testMethodResultEqualInvalidMethod() throws Exception
{
final Method readMethod = getClass().getDeclaredMethod("getTestValue");
final PropertyAccessor accessor = new PropertyAccessor("testValue", readMethod, null);

ObjectWithString working = new ObjectWithString("string");
ObjectWithString base = new ObjectWithString("string");

final Instances instances = new Instances(accessor, working, base, null);
try {
instances.areMethodResultEqual("invalid");
fail("no exception thrown");
}
catch(RuntimeException e){
assertThat(e.getCause() instanceof NoSuchMethodException).isTrue();
}
}

@SuppressWarnings({"MethodMayBeStatic", "UnusedDeclaration"})
public long getTestValue()
{
Expand Down
24 changes: 24 additions & 0 deletions src/test/java/de/danielbechler/diff/MapDifferShould.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,30 @@ public void detect_no_change_when_comparing_using_equals()
verify(node).setState(UNTOUCHED);
}

@Test
public void detect_no_change_when_comparing_using_with_method_equals_and_result_is_same()
{
when(nodeInspector.isWithMethodEquals(internalNode)).thenReturn(true);
when(nodeInspector.getWithMethodEqualsMethod(internalNode)).thenReturn("somemethod");
when(instances.areMethodResultEqual("somemethod")).thenReturn(true);

node = compare(working, base);

verify(node).setState(UNTOUCHED);
}

@Test
public void detect_change_when_comparing_using_with_method_equals_and_result_is_different()
{
when(nodeInspector.isWithMethodEquals(internalNode)).thenReturn(true);
when(nodeInspector.getWithMethodEqualsMethod(internalNode)).thenReturn("somemethod");
when(instances.areMethodResultEqual("somemethod")).thenReturn(false);

node = compare(working, base);

verify(node).setState(CHANGED);
}

@Test
public void detect_addition()
{
Expand Down
Loading