package org.vertexium.cypher.utils;
import org.vertexium.VertexiumException;
import org.vertexium.cypher.exceptions.VertexiumCypherTypeErrorException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
public class ObjectUtils {
public static boolean equals(Object leftObj, Object rightObj) {
return compare(leftObj, rightObj) == 0;
}
public static int compare(Object leftObj, Object rightObj) {
if (leftObj == null && rightObj == null) {
return 0;
}
if (leftObj == null) {
return 1;
}
if (rightObj == null) {
return -1;
}
if (leftObj instanceof Collection && rightObj instanceof Collection) {
return compareCollections((Collection) leftObj, (Collection) rightObj);
}
if (!(leftObj instanceof Comparable)) {
throw new ClassCastException(leftObj.getClass().getName() + " does not implement " + Comparable.class.getName());
}
Comparable left = (Comparable) leftObj;
try {
if (leftObj instanceof Number && rightObj instanceof Number) {
Number leftNumber = (Number) leftObj;
Number rightNumber = (Number) rightObj;
if (leftObj instanceof Double || leftObj instanceof Float || rightObj instanceof Double || rightObj instanceof Float) {
return Double.compare(leftNumber.doubleValue(), rightNumber.doubleValue());
}
return Long.compare(leftNumber.longValue(), rightNumber.longValue());
}
if (left instanceof Number && !(rightObj instanceof Number)) {
return -1;
}
if (rightObj instanceof Number && !(left instanceof Number)) {
return 1;
}
return left.compareTo(rightObj);
} catch (Exception ex) {
if (ex instanceof ClassCastException) {
throw ex;
}
throw new VertexiumException(
String.format(
"Could not compare \"%s\" (%s) to \"%s\" (%s)",
leftObj,
leftObj == null ? "null" : leftObj.getClass().getName(),
rightObj,
rightObj == null ? "null" : rightObj.getClass().getName()
),
ex
);
}
}
private static int compareCollections(Collection leftObj, Collection rightObj) {
int sizeCompare = Integer.compare(leftObj.size(), rightObj.size());
if (sizeCompare != 0) {
return sizeCompare;
}
Iterator leftIt = leftObj.iterator();
Iterator rightIt = rightObj.iterator();
while (leftIt.hasNext() && rightIt.hasNext()) {
int c = compare(leftIt.next(), rightIt.next());
if (c != 0) {
return c;
}
}
return 0;
}
public static Number addNumbers(Number left, Number right) {
Number leftNumber = left;
Number rightNumber = right;
if (leftNumber instanceof Double || leftNumber instanceof Float
|| rightNumber instanceof Double || rightNumber instanceof Float) {
return leftNumber.doubleValue() + rightNumber.doubleValue();
}
if (leftNumber instanceof Long || rightNumber instanceof Long) {
return leftNumber.longValue() + rightNumber.longValue();
}
return leftNumber.intValue() + rightNumber.intValue();
}
public static Number sumNumbers(List<?> list) {
return list.stream()
.filter(Objects::nonNull)
.map(o -> {
VertexiumCypherTypeErrorException.assertType(o, Number.class);
return (Number) o;
})
.reduce(0L, ObjectUtils::addNumbers);
}
}