Class DeepComparator
java.lang.Object
com.graphql_java_generator.plugin.test.helper.DeepComparator
- All Implemented Interfaces:
Cloneable
This class deep compares two objects, say a and b. It:
- Checks that a and b are of the same class
- Compares each field of a to each field of b (the fields defined in their superclasses are also scanned):
- If the field is an id field, and a.id.equals(b.id), then a and b are considered as being the same. The comparison
will check that there other attributes are equals, and if not these differences are registered as differences of the
same object (with the key being the value of the id field, like the key in a Map). See
addIdField(Class, String)
for more information on this - If the field is an ignored field, this field is skipped
- If the field is of a basic type: use the equals method. All enums should be registered in the basic type list.
- If the field is a List: do a deep non-ordered comparison. Each list must be of the same size, and each object in a's field must be deep equal to one object of the b's list. To do this, for each item in a's list, a recursive deepEquals call is done on each item of the b's list until this deepEquals call returns true. If no such call returns true, then this item of the a's list is not present in the b's list: they are different
- If the field is a known object type (see parameters): a recursive call to the deep comparison is done, to compare the a's field to the b's field.
- Otherwise an error is thrown (non managed type for comparison). This insure that the proper comparison mode is used
#differences(Object, Object)
method, to allow further processing. This makes it possible to correct these
differences.- Author:
- etienne-sf
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic interface
This interface allows to define a class that will execute specific comparison.static class
static enum
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionvoid
addBasicClass
(Class<?> clazz) Add a Class as an basic class, that is a class that is compared by using theObject.equals(Object)
methodvoid
addIdField
(Class<?> clazz, String fieldName) Add an idField for a class.void
addIgnoredClass
(Class<?> clazz) Add a Class as an ignored class, that is that if a field to compare is of this class, the comparison is skippedvoid
addIgnoredFields
(Class<?> clazz, String fieldName) Add a field of a class as ignored.void
addSpecificComparisonRules
(Class<?> clazz, String fieldName, DeepComparator.ComparisonRule comparator) Add a comparison rule, for the given field of the given classe.protected DeepComparator
clone()
Returns a fresh comparator, that is ready to execute a new Comparison.boolean
Executes a deep comparison between the two given objects.differences
(Object o1, Object o2, int nbMaxDifferences) Executes a deep comparison between the two given objects.boolean
Executes a deep comparison between the two given objects.
-
Constructor Details
-
DeepComparator
public DeepComparator() -
DeepComparator
public DeepComparator(org.slf4j.Logger logger)
-
-
Method Details
-
equals
Executes a deep comparison between the two given objects.- Parameters:
o1
-o2
-- Returns:
- true if no differences have been found, during the deep comparison. False if at least one difference has been found.
-
differences
Executes a deep comparison between the two given objects. All differences are reported.
If you just want to know if these two objects are different, you can use the#differences(Object, Object)
method, which will stop the comparison as soon as a difference is found. It may be much faster.- Parameters:
o1
-o2
-nbMaxDifferences
- The maximum number of differences to return. This allows to limit the size of the returned list, and to accelerate the comparison.
Setting 1 here will stop as soon as a difference is found.
Setting it to a negative value prevents any comparison to occur.
Set it to Integer.MAX_VALUE to have (almost) no limit on the number of returned differences- Returns:
- The list of differences. Always non null. If this list is empty, then the two objects are identical
-
compare
Executes a deep comparison between the two given objects. This method is internal: it used when recursing into objects of a collection. The path parameter allows to log where the comparison is located, when in debug log level.
This method stops after the first difference found.- Parameters:
o1
-o2
-- Returns:
- true if no differences have been found, during the deep comparison. False if at least one difference has been found.
-
addBasicClass
Add a Class as an basic class, that is a class that is compared by using theObject.equals(Object)
method- Parameters:
clazz
-
-
addIgnoredClass
Add a Class as an ignored class, that is that if a field to compare is of this class, the comparison is skipped- Parameters:
clazz
-
-
addIdField
Add an idField for a class. An idField is a field that identify an instance of a given class.Two objects with the same value in their id field are same (for instance two persons of the same name), but may not be equals (other attributes differ). This allows to trace differences in two objects that are the same.
For classes that has such a field, the rules are :- If the id field of the two instances are differents, generates a difference with the current difference's path
- If the id field of the two instances are equals, add /Xxx(idField:id) to the difference's path (where Xxx is the classname, idField is name if the field/attribute that has been compared and id is the value for this id field as a String), and loop for the other attributes
- Parameters:
clazz
-fieldName
-
-
addIgnoredFields
Add a field of a class as ignored. That is: when comparing this class as an object, this field will be skipped.- Parameters:
clazz
-fieldName
-
-
addSpecificComparisonRules
public void addSpecificComparisonRules(Class<?> clazz, String fieldName, DeepComparator.ComparisonRule comparator) Add a comparison rule, for the given field of the given classe. ThisDeepComparator.ComparisonRule
will be called for each such field of such class that is encountered during the deep comparison.
This allows to break cycles (and avoid Stack Overflow exception): if the A.b field is of class B, and the B.a field is of class A, then you can define specific comparison rule in the#comparisonPredicates
map, so that when comparing the B.a field, you don't cycle back into the A class. This comparison can be a non operation method, or a any comparison of you own.- Parameters:
clazz
-fieldName
-comparator
-
-
clone
Returns a fresh comparator, that is ready to execute a new Comparison. TheexecutedComparisons
map is free. The various configuration lists are set in the clone with the exact same list as the original one. That means that added (for instance) a basic class, will add it for both the clone and the original object.
But theexecutedComparisons
remains specific to each instance.
-