diff --git a/lib/src/main/java/io/cloudquery/scalar/Binary.java b/lib/src/main/java/io/cloudquery/scalar/Binary.java new file mode 100644 index 0000000..136a920 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/scalar/Binary.java @@ -0,0 +1,97 @@ +package io.cloudquery.scalar; + +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.commons.codec.binary.Base64; + +import java.util.Arrays; + +public class Binary implements Scalar { + protected byte[] value; + protected boolean valid; + + public Binary() { + } + + public Binary(Object value) throws ValidationException { + this.set(value); + } + + @Override + public String toString() { + if (this.valid) { + return Base64.encodeBase64String(this.value); + } + return NULL_VALUE_STRING; + } + + @Override + public boolean isValid() { + return this.valid; + } + + @Override + public ArrowType dataType() { + return ArrowType.Binary.INSTANCE; + } + + @Override + public void set(Object value) throws ValidationException { + if (value == null) { + this.valid = false; + this.value = null; + return; + } + + if (value instanceof Scalar scalar) { + if (!scalar.isValid()) { + this.valid = false; + this.value = null; + return; + } + + this.set(scalar.get()); + return; + } + + if (value instanceof byte[] bytes) { + this.valid = true; + this.value = bytes; + return; + } + + if (value instanceof String string) { + this.valid = true; + this.value = Base64.decodeBase64(string); + return; + } + + if (value instanceof char[] chars) { + this.valid = true; + this.value = Base64.decodeBase64(new String(chars)); + return; + } + + throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + + @Override + public Object get() { + if (this.valid) { + return this.value; + } + return null; + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + + if (!(other instanceof Binary o)) { + return false; + } + + return (this.valid && o.valid) && Arrays.equals(this.value, o.value); + } +} \ No newline at end of file diff --git a/lib/src/main/java/io/cloudquery/scalar/LargeBinary.java b/lib/src/main/java/io/cloudquery/scalar/LargeBinary.java new file mode 100644 index 0000000..11428c2 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/scalar/LargeBinary.java @@ -0,0 +1,18 @@ +package io.cloudquery.scalar; + +import org.apache.arrow.vector.types.pojo.ArrowType; + +public class LargeBinary extends Binary { + + public LargeBinary() { + } + + public LargeBinary(Object value) throws ValidationException { + this.set(value); + } + + @Override + public ArrowType dataType() { + return ArrowType.LargeBinary.INSTANCE; + } +} diff --git a/lib/src/main/java/io/cloudquery/scalar/Scalar.java b/lib/src/main/java/io/cloudquery/scalar/Scalar.java index 5103f44..b6857fd 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Scalar.java +++ b/lib/src/main/java/io/cloudquery/scalar/Scalar.java @@ -3,15 +3,17 @@ import org.apache.arrow.vector.types.pojo.ArrowType; public interface Scalar { - String String(); + String toString(); - Boolean IsValid(); + boolean isValid(); - ArrowType DataType(); + ArrowType dataType(); - void Set(Object obj); + void set(Object value) throws ValidationException; - Object Get(); + Object get(); - Boolean Equal(Scalar other); + boolean equals(Object other); + + String NULL_VALUE_STRING = "(null)"; } diff --git a/lib/src/main/java/io/cloudquery/scalar/ValidationException.java b/lib/src/main/java/io/cloudquery/scalar/ValidationException.java new file mode 100644 index 0000000..7a8d2da --- /dev/null +++ b/lib/src/main/java/io/cloudquery/scalar/ValidationException.java @@ -0,0 +1,42 @@ +package io.cloudquery.scalar; + +import org.apache.arrow.vector.types.pojo.ArrowType; + +public class ValidationException extends Exception { + public Throwable cause; + public String message; + public ArrowType type; + private final Object value; + + static final String NO_CONVERSION_AVAILABLE = "no conversion available"; + + + ValidationException(Throwable cause, String message, ArrowType type, Object value) { + super(message, cause); + this.cause = cause; + this.message = message; + this.type = type; + this.value = value; + } + + ValidationException(String message, ArrowType type, Object value) { + super(message); + this.message = message; + this.type = type; + this.value = value; + } + + public String Error() { + if (this.cause == null) { + return String.format("cannot set `%s` with value `%s`: %s", this.type, this.value, this.message); + } + return String.format("cannot set `%s` with value `%s`: %s (%s)", this.type, this.value, this.message, this.cause); + } + + public String Masked() { + if (this.cause == null) { + return String.format("cannot set `%s`: %s", this.type.toString(), this.message); + } + return String.format("cannot set `%s`: %s (%s)", this.type.toString(), this.message, this.cause); + } +}