![JAR search and dependency download from the Maven repository](/logo.png)
org.crazyyak.dev.common.EqualsUtils Maven / Gradle / Ivy
package org.crazyyak.dev.common;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
public class EqualsUtils {
private EqualsUtils() {
}
/** Helper method for testing equality of objects while handling the issue of nulls */
public static boolean objectsEqual(T valueA, T valueB) {
if (valueA == valueB) {
return true; // Same instance or both null
} else if (valueA == null || valueB == null) {
return false; // One but not both are null
} else {
return valueA.equals(valueB);
}
}
public static boolean objectsNotEqual(T valueA, T valueB) {
return objectsEqual(valueA, valueB) == false;
}
static public boolean datesEqual(Date dateA, Date dateB) {
if (dateA == null && dateB == null) {
return true;
} else if (dateA == null || dateB == null) {
return false;
} else {
GregorianCalendar calA = new GregorianCalendar();
calA.setTime(dateA);
GregorianCalendar calB = new GregorianCalendar();
calB.setTime(dateB);
return (calA.get(Calendar.DATE) == calB.get(Calendar.DATE) &&
calA.get(Calendar.MONTH) == calB.get(Calendar.MONTH) &&
calA.get(Calendar.YEAR) == calB.get(Calendar.YEAR));
}
}
static public boolean datesNotEqual(Date dateA, Date dateB) {
return datesEqual(dateA, dateB) == false;
}
public static List compare(Object objectA, Object objectB) {
List results = new ArrayList<>();
return compare(results, null, objectA, objectB, "root");
}
private static List compare(List results, Field field, Object objectA, Object objectB, final String beanName) {
Object valueA = (field == null) ? objectA : ReflectUtils.getFieldValue(objectA, field);
Object valueB = (field == null) ? objectB : ReflectUtils.getFieldValue(objectB, field);
if (valueA == valueB) {
return results;
} else if (valueA == null) {
return build(results, beanName, "Object A is null", "-some value-");
} else if (valueB == null) {
return build(results, beanName, "-some value-", "Object B is null");
} else if (valueA.getClass().equals(valueB.getClass()) == false) {
return build(results, beanName, valueA.getClass().getName(), valueB.getClass().getName());
}
Class type = valueA.getClass();
if (String.class.equals(type)) {
System.out.print("");
}
if (isPrimitive(type)) {
if (EqualsUtils.objectsEqual(valueA, valueB)) {
return results;
} else {
return build(results, beanName, valueA, valueB);
}
} else if (type.isArray()) {
List collectionA = Arrays.asList((Object[]) valueA);
List collectionB = Arrays.asList((Object[]) valueB);
return compareCollection(results, collectionA, collectionB, beanName);
} else if (valueA instanceof Collection && valueB instanceof Collection) {
Collection collectionA = (Collection)valueA;
Collection collectionB = (Collection)valueB;
return compareCollection(results, new ArrayList(collectionA), new ArrayList(collectionB), beanName);
} else if (valueA instanceof Map && valueB instanceof Map) {
return compareMaps(results, (Map) valueA, (Map) valueB, beanName);
}
List fields = ReflectUtils.getFields(valueA.getClass());
for (Field nextField : fields) {
boolean isStatic = Modifier.isStatic(nextField.getModifiers());
boolean isTransient = Modifier.isTransient(nextField.getModifiers());
if (isStatic == false && isTransient == false) {
// no point in comparing static or transient values
compare(results, nextField, valueA, valueB, beanName + "." + nextField.getName());
}
}
return results;
}
private static List compareMaps(List results, Map mapA, Map mapB, String beanName) {
int countA = mapA.size();
int countB = mapB.size();
if (countA != countB) {
build(results, beanName+":count()", countA, countB);
}
Set keysA = mapA.keySet();
Set keysB = mapB.keySet();
List intersection = BeanUtils.intersection(keysA, keysB);
for (Object key : intersection) {
Object valueA = mapA.get(key);
Object valueB = mapB.get(key);
compare(results, null, valueA, valueB, beanName+"["+key+"]");
}
for (Object key : mapA.keySet()) {
if (intersection.contains(key) == false) {
compare(results, null, "-contained-", "-missing-", beanName+"["+key+"]");
}
}
for (Object key : mapB.keySet()) {
if (intersection.contains(key) == false) {
compare(results, null, "-missing-", "-contained-", beanName+"["+key+"]");
}
}
return results;
}
private static List build(List result, String message, Object valueA, Object valueB) {
String msg = String.format("%s:\n %s\n %s", message, valueA, valueB);
result.add(msg);
return result;
}
private static List compareCollection(List results, List listA, List listB, String beanName) {
int countA = listA.size();
int countB = listB.size();
if (countA != countB) {
build(results, beanName+":count()", countA, countB);
}
int max = Math.min(countA, countB);
for (int i = 0; i < max; i++) {
Object valueA = listA.get(i);
Object valueB = listB.get(i);
compare(results, null, valueA, valueB, beanName+"["+i+"]");
}
for (int i = max; i < listA.size(); i++) {
compare(results, null, "-contained-", "-missing-", beanName+"["+i+"]");
}
for (int i = max; i < listB.size(); i++) {
compare(results, null, "-missing-", "-contained-", beanName+"["+i+"]");
}
return results;
}
private static boolean isPrimitive(Class type) {
List types = Arrays.asList(
Boolean.class,
Character.class, Byte.class, Short.class,
Integer.class, Long.class, Float.class, Double.class,
String.class,
LocalDate.class, LocalTime.class, LocalDateTime.class
);
return type.isPrimitive() || types.contains(type);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy