From 0a2b3e42815390e40c1b2296c39ee460c0a6df91 Mon Sep 17 00:00:00 2001 From: Timo Date: Thu, 5 Jul 2018 15:18:25 +0200 Subject: [PATCH] [#398] Add support for comparison of different PropertyValue number types (#853) * [398] Add support for comparing different number types * [398] Minor changes * [#398] Update outdated test --- .../model/impl/properties/PropertyValue.java | 23 ++-- .../impl/properties/PropertyValueUtils.java | 98 ++++++++++++++ .../impl/properties/PropertyValueTest.java | 120 +++++++++++++++--- 3 files changed, 214 insertions(+), 27 deletions(-) diff --git a/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValue.java b/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValue.java index 418f722923d2..5989de05475e 100644 --- a/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValue.java +++ b/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValue.java @@ -318,6 +318,15 @@ public boolean isDateTime() { return rawBytes[0] == TYPE_DATETIME; } + /** + * True, if the wrapped value is a subtype of {@code Number}. + * + * @return true, if {@code Number} value + */ + public boolean isNumber() { + return !isNull() && Number.class.isAssignableFrom(getType()); + } + //---------------------------------------------------------------------------- // Getter //---------------------------------------------------------------------------- @@ -848,22 +857,12 @@ public int compareTo(PropertyValue o) { if (this.isNull() && o.isNull()) { result = 0; + } else if (this.isNumber() && o.isNumber()) { + result = PropertyValueUtils.Numeric.compare(this, o); } else if (this.isBoolean() && o.isBoolean()) { result = Boolean.compare(this.getBoolean(), o.getBoolean()); - } else if (this.isShort() && o.isShort()) { - result = Short.compare(this.getShort(), o.getShort()); - } else if (this.isInt() && o.isInt()) { - result = Integer.compare(this.getInt(), o.getInt()); - } else if (this.isLong() && o.isLong()) { - result = Long.compare(this.getLong(), o.getLong()); - } else if (this.isFloat() && o.isFloat()) { - result = Float.compare(this.getFloat(), o.getFloat()); - } else if (this.isDouble() && o.isDouble()) { - result = Double.compare(this.getDouble(), o.getDouble()); } else if (this.isString() && o.isString()) { result = this.getString().compareTo(o.getString()); - } else if (this.isBigDecimal() && o.isBigDecimal()) { - result = this.getBigDecimal().compareTo(o.getBigDecimal()); } else if (this.isGradoopId() && o.isGradoopId()) { result = this.getGradoopId().compareTo(o.getGradoopId()); } else if (this.isDate() && o.isDate()) { diff --git a/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValueUtils.java b/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValueUtils.java index 42f145515fa1..b877d38546de 100644 --- a/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValueUtils.java +++ b/gradoop-common/src/main/java/org/gradoop/common/model/impl/properties/PropertyValueUtils.java @@ -284,6 +284,104 @@ public static PropertyValue multiply( return aValue; } + /** + * Compares two numerical property values + * + * @param aValue first value + * @param bValue second value + * + * @return 0 if a is equal to b, < 0 if a is less than b and > 0 if a is greater than b + */ + public static int compare(PropertyValue aValue, PropertyValue bValue) { + + int aType = checkNumericalAndGetType(aValue); + int bType = checkNumericalAndGetType(bValue); + + boolean sameType = aType == bType; + + int maxType = Math.max(aType, bType); + + int result; + + if (maxType == SHORT) { + result = Short.compare(aValue.getShort(), bValue.getShort()); + + } else if (maxType == INT) { + int a; + int b; + + if (sameType) { + a = aValue.getInt(); + b = bValue.getInt(); + } else { + a = aType == INT ? aValue.getInt() : aValue.getShort(); + b = bType == INT ? bValue.getInt() : bValue.getShort(); + } + + result = Integer.compare(a, b); + + } else if (maxType == FLOAT) { + float a; + float b; + + if (sameType) { + a = aValue.getFloat(); + b = bValue.getFloat(); + } else { + a = aType == FLOAT ? aValue.getFloat() : floatValue(aValue, aType); + b = bType == FLOAT ? bValue.getFloat() : floatValue(bValue, bType); + } + + result = Float.compare(a, b); + + } else if (maxType == LONG) { + long a; + long b; + + if (sameType) { + a = aValue.getLong(); + b = bValue.getLong(); + } else { + a = aType == LONG ? aValue.getLong() : longValue(aValue, aType); + b = bType == LONG ? bValue.getLong() : longValue(bValue, bType); + } + + result = Long.compare(a, b); + + } else if (maxType == DOUBLE) { + double a; + double b; + + if (sameType) { + a = aValue.getDouble(); + b = bValue.getDouble(); + } else { + a = aType == DOUBLE ? aValue.getDouble() : doubleValue(aValue, aType); + b = bType == DOUBLE ? bValue.getDouble() : doubleValue(bValue, bType); + } + + result = Double.compare(a, b); + + } else { + BigDecimal a; + BigDecimal b; + + if (sameType) { + a = aValue.getBigDecimal(); + b = bValue.getBigDecimal(); + } else { + a = aType == BIG_DECIMAL ? aValue.getBigDecimal() : + bigDecimalValue(aValue, aType); + b = bType == BIG_DECIMAL ? bValue.getBigDecimal() : + bigDecimalValue(bValue, bType); + } + + result = a.compareTo(b); + } + + return result; + } + /** * Compares two numerical property values and returns the smaller one. * diff --git a/gradoop-common/src/test/java/org/gradoop/common/model/impl/properties/PropertyValueTest.java b/gradoop-common/src/test/java/org/gradoop/common/model/impl/properties/PropertyValueTest.java index 6575326a948c..d33ae681052a 100644 --- a/gradoop-common/src/test/java/org/gradoop/common/model/impl/properties/PropertyValueTest.java +++ b/gradoop-common/src/test/java/org/gradoop/common/model/impl/properties/PropertyValueTest.java @@ -709,6 +709,40 @@ public void testSetDateTime() throws Exception { assertEquals(DATETIME_VAL_d, p.getDateTime()); } + @Test + public void testIsNumber() throws Exception { + PropertyValue p = PropertyValue.create(SHORT_VAL_e); + assertTrue(p.isNumber()); + p = PropertyValue.create(INT_VAL_2); + assertTrue(p.isNumber()); + p = PropertyValue.create(LONG_VAL_3); + assertTrue(p.isNumber()); + p = PropertyValue.create(FLOAT_VAL_4); + assertTrue(p.isNumber()); + p = PropertyValue.create(DOUBLE_VAL_5); + assertTrue(p.isNumber()); + p = PropertyValue.create(BIG_DECIMAL_VAL_7); + assertTrue(p.isNumber()); + + p = PropertyValue.create(NULL_VAL_0); + assertFalse(p.isNumber()); + p = PropertyValue.create(BOOL_VAL_1); + assertFalse(p.isNumber()); + p = PropertyValue.create(STRING_VAL_6); + assertFalse(p.isNumber()); + p = PropertyValue.create(GRADOOP_ID_VAL_8); + assertFalse(p.isNumber()); + p = PropertyValue.create(MAP_VAL_9); + assertFalse(p.isNumber()); + p = PropertyValue.create(LIST_VAL_a); + assertFalse(p.isNumber()); + p = PropertyValue.create(DATE_VAL_b); + assertFalse(p.isNumber()); + p = PropertyValue.create(TIME_VAL_c); + assertFalse(p.isNumber()); + p = PropertyValue.create(DATETIME_VAL_d); + assertFalse(p.isNumber()); + } @Test public void testEqualsAndHashCode() throws Exception { @@ -782,41 +816,97 @@ private void validateEqualsAndHashCode(PropertyValue p1, PropertyValue p2, assertEquals(p1, p2); assertNotEquals(p1, p3); - assertTrue(p1.hashCode() == p1.hashCode()); - assertTrue(p1.hashCode() == p2.hashCode()); - assertFalse(p1.hashCode() == p3.hashCode()); + assertEquals(p1.hashCode(), p1.hashCode()); + assertEquals(p1.hashCode(), p2.hashCode()); + assertNotEquals(p1.hashCode(), p3.hashCode()); } @Test public void testCompareTo() throws Exception { // null - assertTrue(create(null).compareTo(create(null)) == 0); + assertEquals(create(null).compareTo(create(null)), 0); // boolean validateCompareTo(create(false), create(false), create(true)); // short - validateCompareTo(create((short)-10), create((short)-10), create((short)10)); + validateCompareTo(create((short)-10), create((short)-10), create((short)12)); validateCompareTo(create((short)10), create((short)10), create((short)12)); + validateCompareTo(create((short)-10), create(-10), create(12)); + validateCompareTo(create((short)10), create(10), create(12)); + validateCompareTo(create((short)-10), create(-10L), create(12L)); + validateCompareTo(create((short)10), create(10L), create(12L)); + validateCompareTo(create((short)-10), create(-10F), create(12F)); + validateCompareTo(create((short)10), create(10F), create(12F)); + validateCompareTo(create((short)-10), create(-10D), create(12D)); + validateCompareTo(create((short)10), create(10D), create(12D)); + validateCompareTo(create((short)-10), create(BigDecimal.valueOf(-10)), create(BigDecimal.valueOf(12))); + validateCompareTo(create((short)10), create(BigDecimal.valueOf(10)), create(BigDecimal.valueOf(12))); // int - validateCompareTo(create(-10), create(-10), create(10)); + validateCompareTo(create(-10), create((short)-10), create((short)12)); + validateCompareTo(create(10), create((short)10), create((short)12)); + validateCompareTo(create(-10), create(-10), create(12)); validateCompareTo(create(10), create(10), create(12)); + validateCompareTo(create(-10), create(-10L), create(12L)); + validateCompareTo(create(10), create(10L), create(12L)); + validateCompareTo(create(-10), create(-10F), create(12F)); + validateCompareTo(create(10), create(10F), create(12F)); + validateCompareTo(create(-10), create(-10D), create(12D)); + validateCompareTo(create(10), create(10D), create(12D)); + validateCompareTo(create(-10), create(BigDecimal.valueOf(-10)), create(BigDecimal.valueOf(12))); + validateCompareTo(create(10), create(BigDecimal.valueOf(10)), create(BigDecimal.valueOf(12))); // long + validateCompareTo(create(-10L), create((short)-10), create((short)12)); + validateCompareTo(create(10L), create((short)10), create((short)12)); + validateCompareTo(create(-10L), create(-10), create(12)); + validateCompareTo(create(10L), create(10), create(12)); validateCompareTo(create(-10L), create(-10L), create(12L)); validateCompareTo(create(10L), create(10L), create(12L)); + validateCompareTo(create(-10L), create(-10F), create(12F)); + validateCompareTo(create(10L), create(10F), create(12F)); + validateCompareTo(create(-10L), create(-10D), create(12D)); + validateCompareTo(create(10L), create(10D), create(12D)); + validateCompareTo(create(-10L), create(BigDecimal.valueOf(-10)), create(BigDecimal.valueOf(12))); + validateCompareTo(create(10L), create(BigDecimal.valueOf(10)), create(BigDecimal.valueOf(12))); // float + validateCompareTo(create(-10F), create((short)-10), create((short)12)); + validateCompareTo(create(10F), create((short)10), create((short)12)); + validateCompareTo(create(-10F), create(-10), create(12)); + validateCompareTo(create(10F), create(10), create(12)); + validateCompareTo(create(-10F), create(-10L), create(12L)); + validateCompareTo(create(10F), create(10L), create(12L)); validateCompareTo(create(-10F), create(-10F), create(12F)); validateCompareTo(create(10F), create(10F), create(12F)); + validateCompareTo(create(-10F), create(-10D), create(12D)); + validateCompareTo(create(10F), create(10D), create(12D)); + validateCompareTo(create(-10F), create(BigDecimal.valueOf(-10)), create(BigDecimal.valueOf(12))); + validateCompareTo(create(10F), create(BigDecimal.valueOf(10)), create(BigDecimal.valueOf(12))); // double - validateCompareTo(create(-10.), create(-10.), create(12.)); - validateCompareTo(create(10.), create(10.), create(12.)); + validateCompareTo(create(-10D), create((short)-10), create((short)12)); + validateCompareTo(create(10D), create((short)10), create((short)12)); + validateCompareTo(create(-10D), create(-10), create(12)); + validateCompareTo(create(10D), create(10), create(12)); + validateCompareTo(create(-10D), create(-10L), create(12L)); + validateCompareTo(create(10D), create(10L), create(12L)); + validateCompareTo(create(-10D), create(-10F), create(12F)); + validateCompareTo(create(10D), create(10F), create(12F)); + validateCompareTo(create(-10D), create(-10D), create(12D)); + validateCompareTo(create(10D), create(10D), create(12D)); + validateCompareTo(create(-10D), create(BigDecimal.valueOf(-10)), create(BigDecimal.valueOf(12))); + validateCompareTo(create(10D), create(BigDecimal.valueOf(10)), create(BigDecimal.valueOf(12))); //string validateCompareTo(create("10"), create("10"), create("12")); // BigDecimal - validateCompareTo(create(new BigDecimal(-10)), - create(new BigDecimal(-10)), - create(new BigDecimal(11))); - validateCompareTo(create(new BigDecimal(10)), - create(new BigDecimal(10)), - create(new BigDecimal(11))); + validateCompareTo(create(BigDecimal.valueOf(-10)), create((short)-10), create((short)12)); + validateCompareTo(create(BigDecimal.valueOf(10)), create((short)10), create((short)12)); + validateCompareTo(create(BigDecimal.valueOf(-10)), create(-10), create(12)); + validateCompareTo(create(BigDecimal.valueOf(10)), create(10), create(12)); + validateCompareTo(create(BigDecimal.valueOf(-10)), create(-10L), create(12L)); + validateCompareTo(create(BigDecimal.valueOf(10)), create(10L), create(12L)); + validateCompareTo(create(BigDecimal.valueOf(-10)), create(-10F), create(12F)); + validateCompareTo(create(BigDecimal.valueOf(10)), create(10F), create(12F)); + validateCompareTo(create(BigDecimal.valueOf(-10)), create(-10D), create(12D)); + validateCompareTo(create(BigDecimal.valueOf(10)), create(10D), create(12D)); + validateCompareTo(create(BigDecimal.valueOf(-10)), create(BigDecimal.valueOf(-10)), create(BigDecimal.valueOf(12))); + validateCompareTo(create(BigDecimal.valueOf(10)), create(BigDecimal.valueOf(10)), create(BigDecimal.valueOf(12))); // GradoopId validateCompareTo( create(GradoopId.fromString("583ff8ffbd7d222690a90999")), @@ -845,7 +935,7 @@ public void testCompareTo() throws Exception { @Test(expected = IllegalArgumentException.class) public void testCompareToWithIncompatibleTypes() { - create(10).compareTo(create(10L)); + create(10).compareTo(create("10")); } @Test(expected = UnsupportedOperationException.class)