package org.test4j.hamcrest.matcher.property.comparator;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.test4j.hamcrest.matcher.property.difference.Difference;
import org.test4j.hamcrest.matcher.property.reflection.ReflectionComparator;
import org.test4j.tools.commons.DateHelper;
/**
* Comparator for simple cases. Following cases are handled: left and right are
* the same instance, left or right have a null value, left or right are
* enumerations, left or right are java.lang classes and left or right are of
* type Character or Number
*/
public class SimpleCasesComparator implements Comparator {
/**
* Returns true if both object are the same instance, have a null value, are
* an Enum/Number/Character or are a java.lang type.
*
* @param left
* The left object
* @param right
* The right object
* @return True for simple cases
*/
public boolean canCompare(Object left, Object right) {
if (left == right) {
return true;
}
if (left == null || right == null) {
return true;
}
if ((left instanceof Character || left instanceof Number)
&& (right instanceof Character || right instanceof Number)) {
return true;
}
if (left.getClass().getName().startsWith("java.lang") || right.getClass().getName().startsWith("java.lang")) {
return true;
}
if (left instanceof Enum && right instanceof Enum) {
return true;
}
return false;
}
/**
* Compares the given values.
*
* @param left
* The left value
* @param right
* The right value
* @param onlyFirstDifference
* True if only the first difference should be returned
* @param reflectionComparator
* The root comparator for inner comparisons, not null
* @return A Difference if both values are different, null otherwise
*/
public Difference compare(Object left, Object right, boolean onlyFirstDifference,
ReflectionComparator reflectionComparator) {
// check if the same instance is referenced
if (left == right) {
return null;
}
// check if the left value is null
if (left == null) {
return new Difference("Left value null", left, right);
}
// check if the right value is null
if (right == null) {
return new Difference("Right value null", left, right);
}
// check if right and left have same number value (including NaN and
// Infinity)
if ((left instanceof Character || left instanceof Number)
&& (right instanceof Character || right instanceof Number)) {
Double leftDouble = getDoubleValue(left);
Double rightDouble = getDoubleValue(right);
if (leftDouble.equals(rightDouble)) {
return null;
}
return new Difference("Different primitive values", left, right);
}
if (left instanceof String && right instanceof Date) {
SimpleDateFormat df = DateHelper.getDateFormat((String) left);
right = df.format((Date) right);
}
// check if java objects are equal
if (left.getClass().getName().startsWith("java.lang") || right.getClass().getName().startsWith("java.lang")) {
if (left.equals(right)) {
return null;
}
return new Difference("Different object values", left, right);
}
// check if enums are equal
if (left instanceof Enum && right instanceof Enum) {
if (left.equals(right)) {
return null;
}
return new Difference("Different enum values", left, right);
}
return null;
}
/**
* Gets the double value for the given left Character or Number instance.
*
* @param object
* the Character or Number, not null
* @return the value as a Double (this way NaN and infinity can be compared)
*/
private Double getDoubleValue(Object object) {
if (object instanceof Number) {
return ((Number) object).doubleValue();
}
return (double) ((Character) object).charValue();
}
}