Skip to content

Commit e1dce54

Browse files
committed
Major refactoring for fluent configuration and better extendability.
1 parent afbc193 commit e1dce54

File tree

136 files changed

+3730
-3678
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+3730
-3678
lines changed

src/main/java/de/danielbechler/diff/BeanDiffer.java

Lines changed: 53 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
package de.danielbechler.diff;
1818

1919
import de.danielbechler.diff.accessor.*;
20-
import de.danielbechler.diff.accessor.exception.ExceptionListener;
20+
import de.danielbechler.diff.comparison.*;
2121
import de.danielbechler.diff.introspect.*;
22-
import de.danielbechler.diff.node.*;
2322
import de.danielbechler.util.*;
2423

2524
/**
@@ -28,52 +27,62 @@
2827
*
2928
* @author Daniel Bechler
3029
*/
31-
final class BeanDiffer implements Differ<Node>
30+
final class BeanDiffer implements Differ
3231
{
33-
private final NodeInspector nodeInspector;
34-
private Introspector introspector = new StandardIntrospector();
35-
private BeanPropertyComparisonDelegator beanPropertyComparisonDelegator;
36-
private DefaultNodeFactory defaultNodeFactory = new DefaultNodeFactory();
32+
private final IsIntrospectableResolver isIntrospectableResolver;
33+
private final IsReturnableResolver isReturnableResolver;
34+
private final ComparisonStrategyResolver comparisonStrategyResolver;
35+
private final Introspector introspector;
36+
private final DifferDispatcher differDispatcher;
3737

38-
public BeanDiffer(final DifferDelegator delegator, final NodeInspector nodeInspector, final ExceptionListener exceptionListener)
38+
public BeanDiffer(final DifferDispatcher differDispatcher,
39+
final Introspector introspector,
40+
final IsIntrospectableResolver introspectableResolver,
41+
final IsReturnableResolver returnableResolver,
42+
final ComparisonStrategyResolver comparisonStrategyResolver)
3943
{
40-
Assert.notNull(delegator, "delegator");
41-
Assert.notNull(nodeInspector, "configuration");
42-
this.beanPropertyComparisonDelegator = new BeanPropertyComparisonDelegator(delegator, nodeInspector, exceptionListener);
43-
this.nodeInspector = nodeInspector;
44+
Assert.notNull(differDispatcher, "differDispatcher");
45+
this.differDispatcher = differDispatcher;
46+
47+
Assert.notNull(introspector, "introspector");
48+
this.introspector = introspector;
49+
50+
Assert.notNull(introspectableResolver, "introspectableResolver");
51+
this.isIntrospectableResolver = introspectableResolver;
52+
53+
Assert.notNull(returnableResolver, "returnableResolver");
54+
this.isReturnableResolver = returnableResolver;
55+
56+
Assert.notNull(comparisonStrategyResolver, "comparisonStrategyResolver");
57+
this.comparisonStrategyResolver = comparisonStrategyResolver;
4458
}
4559

46-
public final Node compare(final Node parentNode, final Instances instances)
60+
public boolean accepts(final Class<?> type)
4761
{
48-
final Node beanNode = defaultNodeFactory.createNode(parentNode, instances);
49-
if (nodeInspector.isIgnored(beanNode))
50-
{
51-
beanNode.setState(Node.State.IGNORED);
52-
}
53-
else if (nodeInspector.hasEqualsOnlyValueProviderMethod(beanNode)){
54-
String method = nodeInspector.getEqualsOnlyValueProviderMethod(beanNode);
55-
if (instances.areMethodResultsEqual(method))
56-
{
57-
beanNode.setState(Node.State.UNTOUCHED);
58-
}
59-
else
60-
{
61-
beanNode.setState(Node.State.CHANGED);
62-
}
63-
}
64-
else if (instances.areNull() || instances.areSame())
62+
return !type.isPrimitive() && !type.isArray();
63+
}
64+
65+
public final DiffNode compare(final DiffNode parentNode, final Instances instances)
66+
{
67+
final DiffNode beanNode = new DiffNode(parentNode, instances.getSourceAccessor(), instances.getType());
68+
// if (isIgnoredResolver.isIgnored(beanNode))
69+
// {
70+
// beanNode.setState(Node.State.IGNORED);
71+
// }
72+
// else
73+
if (instances.areNull() || instances.areSame())
6574
{
66-
beanNode.setState(Node.State.UNTOUCHED);
75+
beanNode.setState(DiffNode.State.UNTOUCHED);
6776
}
6877
else if (instances.hasBeenAdded())
6978
{
7079
compareUsingAppropriateMethod(beanNode, instances);
71-
beanNode.setState(Node.State.ADDED);
80+
beanNode.setState(DiffNode.State.ADDED);
7281
}
7382
else if (instances.hasBeenRemoved())
7483
{
7584
compareUsingAppropriateMethod(beanNode, instances);
76-
beanNode.setState(Node.State.REMOVED);
85+
beanNode.setState(DiffNode.State.REMOVED);
7786
}
7887
else
7988
{
@@ -82,80 +91,30 @@ else if (instances.hasBeenRemoved())
8291
return beanNode;
8392
}
8493

85-
private void compareUsingAppropriateMethod(final Node beanNode, final Instances instances)
94+
private void compareUsingAppropriateMethod(final DiffNode beanNode, final Instances instances)
8695
{
87-
if (nodeInspector.isCompareToOnly(beanNode))
96+
final ComparisonStrategy comparisonStrategy = comparisonStrategyResolver.resolveComparisonStrategy(beanNode);
97+
if (comparisonStrategy != null)
8898
{
89-
compareUsingCompareTo(beanNode, instances);
99+
comparisonStrategy.compare(beanNode, instances);
90100
}
91-
else if (nodeInspector.isEqualsOnly(beanNode))
101+
else if (isIntrospectableResolver.isIntrospectable(beanNode))
92102
{
93-
compareUsingEquals(beanNode, instances);
103+
compareUsingIntrospection(beanNode, instances);
94104
}
95-
else if (nodeInspector.isIntrospectible(beanNode))
96-
{
97-
compareUsingIntrospection(beanNode, instances);
98-
}
99105
}
100106

101-
private void compareUsingIntrospection(final Node beanNode, final Instances beanInstances)
107+
private void compareUsingIntrospection(final DiffNode beanNode, final Instances beanInstances)
102108
{
103109
final Class<?> beanType = beanInstances.getType();
104-
final Iterable<Accessor> propertyAccessors = introspector.introspect(beanType);
105-
for (final Accessor propertyAccessor : propertyAccessors)
110+
final Iterable<PropertyAwareAccessor> propertyAccessors = introspector.introspect(beanType);
111+
for (final PropertyAwareAccessor propertyAccessor : propertyAccessors)
106112
{
107-
final Node propertyNode = beanPropertyComparisonDelegator.compare(beanNode, beanInstances, propertyAccessor);
108-
if (nodeInspector.isReturnable(propertyNode))
113+
final DiffNode propertyNode = differDispatcher.dispatch(beanNode, beanInstances, propertyAccessor);
114+
if (isReturnableResolver.isReturnable(propertyNode))
109115
{
110116
beanNode.addChild(propertyNode);
111117
}
112118
}
113119
}
114-
115-
@SuppressWarnings({"MethodMayBeStatic"})
116-
private void compareUsingCompareTo(final Node beanNode, final Instances instances)
117-
{
118-
if (instances.areEqualByComparison())
119-
{
120-
beanNode.setState(Node.State.UNTOUCHED);
121-
}
122-
else
123-
{
124-
beanNode.setState(Node.State.CHANGED);
125-
}
126-
}
127-
128-
@SuppressWarnings({"MethodMayBeStatic"})
129-
private void compareUsingEquals(final Node beanNode, final Instances instances)
130-
{
131-
if (instances.areEqual())
132-
{
133-
beanNode.setState(Node.State.UNTOUCHED);
134-
}
135-
else
136-
{
137-
beanNode.setState(Node.State.CHANGED);
138-
}
139-
}
140-
141-
@TestOnly
142-
void setIntrospector(final Introspector introspector)
143-
{
144-
Assert.notNull(introspector, "introspector");
145-
this.introspector = introspector;
146-
}
147-
148-
@TestOnly
149-
void setBeanPropertyComparisonDelegator(final BeanPropertyComparisonDelegator beanPropertyComparisonDelegator)
150-
{
151-
Assert.notNull(beanPropertyComparisonDelegator, "beanPropertyComparisonDelegator");
152-
this.beanPropertyComparisonDelegator = beanPropertyComparisonDelegator;
153-
}
154-
155-
@TestOnly
156-
public void setDefaultNodeFactory(final DefaultNodeFactory defaultNodeFactory)
157-
{
158-
Assert.notNull(defaultNodeFactory, "defaultNodeFactory");
159-
this.defaultNodeFactory = defaultNodeFactory;
160-
}
161120
}

src/main/java/de/danielbechler/diff/BeanPropertyComparisonDelegator.java

Lines changed: 0 additions & 75 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package de.danielbechler.diff;
2+
3+
import de.danielbechler.diff.path.*;
4+
5+
/** @author Daniel Bechler */
6+
public interface CategoryConfiguration
7+
{
8+
Of ofNode(NodePath nodePath);
9+
10+
Of ofType(Class<?> type);
11+
12+
public interface Of
13+
{
14+
CategoryConfiguration toBe(String... categories);
15+
}
16+
}

src/main/java/de/danielbechler/diff/TestOnly.java renamed to src/main/java/de/danielbechler/diff/CategoryResolver.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012 Daniel Bechler
2+
* Copyright 2013 Daniel Bechler
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
1616

1717
package de.danielbechler.diff;
1818

19-
/**
20-
* A simple marker annotation to mark methods that are only needed for testing.
21-
*
22-
* @author Daniel Bechler
23-
*/
24-
@interface TestOnly {
19+
import java.util.*;
20+
21+
/** @author Daniel Bechler */
22+
public interface CategoryResolver
23+
{
24+
Set<String> resolveCategories(DiffNode node);
2525
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package de.danielbechler.diff;
2+
3+
import de.danielbechler.diff.path.*;
4+
5+
import java.util.*;
6+
7+
import static java.util.Arrays.*;
8+
import static java.util.Collections.*;
9+
10+
/**
11+
*
12+
*/
13+
class CategoryService implements CategoryConfiguration, CategoryResolver
14+
{
15+
private final NodePathValueHolder<String[]> nodePathCategories = NodePathValueHolder.of(String[].class);
16+
private final Map<Class<?>, String[]> typeCategories = new HashMap<Class<?>, String[]>();
17+
18+
public Set<String> resolveCategories(final DiffNode node)
19+
{
20+
final Set<String> categories = new TreeSet<String>();
21+
categories.addAll(categoriesFromNodePathConfiguration(node));
22+
categories.addAll(categoriesFromTypeConfiguration(node));
23+
categories.addAll(categoriesFromNode(node));
24+
return categories;
25+
}
26+
27+
private Collection<String> categoriesFromNodePathConfiguration(final DiffNode node)
28+
{
29+
final String[] categories = nodePathCategories.valueForNodePath(node.getPath());
30+
if (categories != null)
31+
{
32+
return asList(categories);
33+
}
34+
return emptySet();
35+
}
36+
37+
private Collection<String> categoriesFromTypeConfiguration(final DiffNode node)
38+
{
39+
final Class<?> nodeType = node.getType();
40+
if (nodeType != null)
41+
{
42+
final String[] categories = typeCategories.get(nodeType);
43+
if (categories != null)
44+
{
45+
return asList(categories);
46+
}
47+
}
48+
return emptySet();
49+
}
50+
51+
private static Collection<String> categoriesFromNode(final DiffNode node)
52+
{
53+
if (node.getCategories() != null)
54+
{
55+
return node.getCategories();
56+
}
57+
return emptySet();
58+
}
59+
60+
public Of ofNode(final NodePath nodePath)
61+
{
62+
return new Of()
63+
{
64+
public CategoryConfiguration toBe(final String... categories)
65+
{
66+
nodePathCategories.put(nodePath, categories);
67+
return CategoryService.this;
68+
}
69+
};
70+
}
71+
72+
public Of ofType(final Class<?> type)
73+
{
74+
return new Of()
75+
{
76+
public CategoryConfiguration toBe(final String... categories)
77+
{
78+
typeCategories.put(type, categories);
79+
return CategoryService.this;
80+
}
81+
};
82+
}
83+
}

0 commit comments

Comments
 (0)