diff --git a/lib/src/main/java/io/cloudquery/scalar/Binary.java b/lib/src/main/java/io/cloudquery/scalar/Binary.java index c21259f..76844ae 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Binary.java +++ b/lib/src/main/java/io/cloudquery/scalar/Binary.java @@ -59,9 +59,9 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { + if (value instanceof CharSequence sequence) { this.valid = true; - this.value = Base64.decodeBase64(string); + this.value = Base64.decodeBase64(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/Bool.java b/lib/src/main/java/io/cloudquery/scalar/Bool.java index 2fb4f03..27b2955 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Bool.java +++ b/lib/src/main/java/io/cloudquery/scalar/Bool.java @@ -56,9 +56,9 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { + if (value instanceof CharSequence sequence) { this.valid = true; - this.value = Boolean.parseBoolean(string); + this.value = Boolean.parseBoolean(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/DateDay.java b/lib/src/main/java/io/cloudquery/scalar/DateDay.java index 843c0bb..cfd3d7f 100644 --- a/lib/src/main/java/io/cloudquery/scalar/DateDay.java +++ b/lib/src/main/java/io/cloudquery/scalar/DateDay.java @@ -63,9 +63,9 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { + if (value instanceof CharSequence sequence) { this.valid = true; - this.value = Integer.parseInt(string); + this.value = Integer.parseInt(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/DateMilli.java b/lib/src/main/java/io/cloudquery/scalar/DateMilli.java index 0201eef..eb6c9fa 100644 --- a/lib/src/main/java/io/cloudquery/scalar/DateMilli.java +++ b/lib/src/main/java/io/cloudquery/scalar/DateMilli.java @@ -69,9 +69,9 @@ public void set(Object value) throws ValidationException { return; } - if (value instanceof String string) { + if (value instanceof CharSequence sequence) { this.valid = true; - this.value = Long.parseLong(string); + this.value = Long.parseLong(sequence.toString()); return; } diff --git a/lib/src/main/java/io/cloudquery/scalar/Duration.java b/lib/src/main/java/io/cloudquery/scalar/Duration.java new file mode 100644 index 0000000..3691428 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/scalar/Duration.java @@ -0,0 +1,99 @@ +package io.cloudquery.scalar; + +import org.apache.arrow.vector.types.TimeUnit; +import org.apache.arrow.vector.types.pojo.ArrowType; + +public class Duration implements Scalar { + protected java.time.Duration value; + + // TODO: add more units support later + private static final ArrowType dt = new ArrowType.Duration(TimeUnit.MILLISECOND); + + public Duration() { + } + + public Duration(Object value) throws ValidationException { + this.set(value); + } + + @Override + public String toString() { + if (this.value != null) { + return this.value.toString(); + } + return NULL_VALUE_STRING; + } + + @Override + public boolean isValid() { + return this.value != null; + } + + @Override + public ArrowType dataType() { + return dt; + } + + @Override + public void set(Object value) throws ValidationException { + if (value == null) { + this.value = null; + return; + } + + if (value instanceof Scalar scalar) { + if (!scalar.isValid()) { + this.value = null; + return; + } + + if (scalar instanceof Duration duration) { + this.value = duration.value; + return; + } + + this.set(scalar.get()); + return; + } + + if (value instanceof java.time.Duration duration) { + this.value = duration; + return; + } + + if (value instanceof Integer integer) { + this.value = java.time.Duration.ofMillis(integer); + return; + } + + if (value instanceof Long longValue) { + this.value = java.time.Duration.ofMillis(longValue); + return; + } + + if (value instanceof CharSequence sequence) { + this.value = java.time.Duration.parse(sequence); + return; + } + + throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + + @Override + public Object get() { + return this.value; // null or proper value + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + + if (!(other instanceof Duration o)) { + return false; + } + + return this.value == o.value || this.value.equals(o.value); + } +} diff --git a/lib/src/test/java/io/cloudquery/scalar/DurationTest.java b/lib/src/test/java/io/cloudquery/scalar/DurationTest.java new file mode 100644 index 0000000..1003226 --- /dev/null +++ b/lib/src/test/java/io/cloudquery/scalar/DurationTest.java @@ -0,0 +1,133 @@ +package io.cloudquery.scalar; + +import org.apache.arrow.vector.types.TimeUnit; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + +public class DurationTest { + @Test + public void testNew() { + assertDoesNotThrow(() -> { + new Duration(); + }); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow(() -> { + new Duration(1); + new Duration("PT8H6M12.345S"); + new Duration(java.time.Duration.ZERO); + new Duration(java.time.Duration.ofNanos(1)); + + Scalar s = new Duration(java.time.Duration.ZERO); + new Duration(s); + }); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows(ValidationException.class, () -> { + new Duration(false); + }); + } + + @Test + public void testToString() { + Duration duration = new Duration(); + assertEquals(Scalar.NULL_VALUE_STRING, duration.toString()); + + assertDoesNotThrow(() -> { + duration.set(1); + }); + assertEquals("PT0.001S", duration.toString()); + + assertDoesNotThrow(() -> { + duration.set(java.time.Duration.ofDays(1L)); + }); + assertEquals("PT24H", duration.toString()); + } + + @Test + public void testDataType() { + Duration duration = new Duration(); + assertEquals(new ArrowType.Duration(TimeUnit.MILLISECOND), duration.dataType()); + } + + @Test + public void testIsValid() { + Duration duration = new Duration(); + assertFalse(duration.isValid()); + + assertDoesNotThrow(() -> { + duration.set(1L); + }); + assertTrue(duration.isValid()); + } + + @Test + public void testSet() { + Duration duration = new Duration(); + assertDoesNotThrow(() -> { + duration.set(1); + duration.set(1L); + duration.set("PT8H6M12.345S"); + duration.set(java.time.Duration.ZERO); + + Scalar s = new Duration(java.time.Duration.ZERO); + duration.set(s); + }); + } + + @Test + public void testSetWithInvalidParam() { + Duration duration = new Duration(); + assertThrows(ValidationException.class, () -> { + duration.set(false); + }); + } + + @Test + public void testGet() { + Duration duration = new Duration(); + assertFalse(duration.isValid()); + assertNull(duration.get()); + + assertDoesNotThrow(() -> { + duration.set(-1L); + }); + assertTrue(duration.isValid()); + assertEquals(java.time.Duration.ofMillis(-1L), duration.get()); + + assertDoesNotThrow(() -> { + duration.set(java.time.Duration.ZERO); + }); + assertTrue(duration.isValid()); + assertEquals(java.time.Duration.ZERO, duration.get()); + } + + @Test + public void testEquals() { + Duration a = new Duration(); + Duration b = new Duration(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Bool()); // we can't cast Bool to Duration + assertNotEquals(null, a); + + assertDoesNotThrow(() -> { + a.set(-1L); + }); + assertNotEquals(a, b); + + assertDoesNotThrow(() -> { + for (Object obj : new Object[]{null, 0, 0L, -1, -1L, 1, 1L, "PT8H6M12.345S", java.time.Duration.ZERO}) { + a.set(obj); + assertEquals(a, new Duration(obj)); + } + }); + } +}