You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Tom Tobin (JIRA)" <ji...@apache.org> on 2015/05/27 14:32:18 UTC
[jira] [Created] (GROOVY-7437) Support comparison between numbers
and strings
Tom Tobin created GROOVY-7437:
---------------------------------
Summary: Support comparison between numbers and strings
Key: GROOVY-7437
URL: https://issues.apache.org/jira/browse/GROOVY-7437
Project: Groovy
Issue Type: Bug
Components: groovy-jdk
Affects Versions: 2.4.3
Environment: Linux/Windows
Reporter: Tom Tobin
Assignee: Guillaume Laforge
Priority: Critical
Would like logical comparison of numbers and strings, e.g. 123.45f > "300.0". Same applies to equality and both directions: "123.45" == 123.45d.
Successful with other operators (plus, minus..) because operator overloading works. It does not work with comparison operators because DefaultTypeTransformations.java tries to do a smart compare but ignores operator overloading (that's why marking as bug vs enhancement).
Simple fix is to add string compares if the string is a number in DefaultTypeTransformations:compareToWithEqualityCheck() (example below). More complete fix would be that plus respect operator overloading of compareTo() and equals(). I would also like to do special handling (e.g. 3rd party data sometimes in form 00012345 and would love for 0.34 > "30%" to work) - could do that if operator overloading worked.
in DefaultTypeTransformations.java:
private static int compareToWithEqualityCheck(Object left, Object right, boolean equalityCheckOnly) {
if (left == right) {
return 0;
}
if (left == null) {
return -1;
}
else if (right == null) {
return 1;
}
if (left instanceof Comparable) {
if (left instanceof Number) {
if (right instanceof Character || right instanceof Number) {
return DefaultGroovyMethods.compareTo((Number) left, castToNumber(right));
}
if (isValidCharacterString(right)) {
return DefaultGroovyMethods.compareTo((Number) left, ShortTypeHandling.castToChar(right));
}
// ********* SNIP *********
if (right instanceof String) {
Number rightNumber = convertToNumber(left.getClass(), (String)right);
if (rightNumber != null) {
return DefaultGroovyMethods.compareTo((Number) left, rightNumber);
}
}
// ********* SNIP *********
}
else if (left instanceof Character) {
if (isValidCharacterString(right)) {
return DefaultGroovyMethods.compareTo((Character)left, ShortTypeHandling.castToChar(right));
}
if (right instanceof Number) {
return DefaultGroovyMethods.compareTo((Character)left,(Number)right);
}
}
else if (right instanceof Number) {
if (isValidCharacterString(left)) {
return DefaultGroovyMethods.compareTo(ShortTypeHandling.castToChar(left),(Number) right);
}
// ********* SNIP *********
if (left instanceof String) {
Number number = convertToNumber(right.getClass(), (String)left);
if (number != null) {
return DefaultGroovyMethods.compareTo(number, (Number) right);
}
}
// ********* SNIP *********
}
else if (left instanceof String && right instanceof Character) {
return ((String) left).compareTo(right.toString());
}
else if (left instanceof String && right instanceof GString) {
return ((String) left).compareTo(right.toString());
}
if (!equalityCheckOnly || left.getClass().isAssignableFrom(right.getClass())
|| (right.getClass() != Object.class && right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
|| (left instanceof GString && right instanceof String)) {
Comparable comparable = (Comparable) left;
return comparable.compareTo(right);
}
}
if (equalityCheckOnly) {
return -1; // anything other than 0
}
throw new GroovyRuntimeException(
MessageFormat.format("Cannot compare {0} with value ''{1}'' and {2} with value ''{3}''",
left.getClass().getName(),
left,
right.getClass().getName(),
right));
}
// ********* SNIP *********
private static Number convertToNumber(Class numberClass, String string) {
Number number = null;
try {
// attempt convert string to number - could be more elegant, like org.apache.commons.lang3.math.NumberUtils.createNumber()
if (numberClass.equals(Integer.class)) {
number = Integer.parseInt(string);
} else if (numberClass.equals(Long.class)) {
number = Long.parseLong(string);
} else if (numberClass.equals(Float.class)) {
number = Float.parseFloat(string);
} else if (numberClass.equals(Double.class)) {
number = Double.parseDouble(string);
} else if (numberClass.equals(BigInteger.class)) {
number = new BigInteger(string);
} else if (numberClass.equals(BigDecimal.class)) {
number = new BigDecimal(string);
}
} catch (NumberFormatException exception) {
return null;
}
return number;
}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)