From a3afaac07369b984834372926e893ada7a4f6428 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Thu, 25 Feb 2021 22:01:34 +0000 Subject: [PATCH 1/5] Implemented all type converters. --- build.gradle | 2 +- .../typeconverters/BigDecimalTypeConverter.kt | 46 +++ .../typeconverters/BigIntegerTypeConverter.kt | 83 ++++ .../typeconverters/BooleanTypeConverter.kt | 79 ++++ .../core/typeconverters/ByteTypeConverter.kt | 142 +++++++ .../core/typeconverters/CharTypeConverter.kt | 134 +++++++ .../typeconverters/DoubleTypeConverter.kt | 59 +++ .../core/typeconverters/FloatTypeConverter.kt | 43 ++ .../IllegalTypeConversionException.kt | 50 +++ .../core/typeconverters/IntTypeConverter.kt | 111 ++++++ .../core/typeconverters/LongTypeConverter.kt | 100 +++++ .../core/typeconverters/ShortTypeConverter.kt | 120 ++++++ .../typeconverters/StringTypeConverter.kt | 35 ++ .../core/typeconverters/TypeConverter.kt | 33 ++ .../core/typeconverters/UUIDTypeConverter.kt | 49 +++ .../BigDecimalTypeConverterTests.kt | 185 +++++++++ .../BigIntegerTypeConverterTests.kt | 247 ++++++++++++ .../BooleanTypeConverterTests.kt | 142 +++++++ .../typeconverters/ByteTypeConverterTests.kt | 373 ++++++++++++++++++ .../typeconverters/CharTypeConverterTests.kt | 353 +++++++++++++++++ .../DoubleTypeConverterTests.kt | 187 +++++++++ .../typeconverters/FloatTypeConverterTests.kt | 139 +++++++ .../typeconverters/IntTypeConverterTests.kt | 325 +++++++++++++++ .../typeconverters/LongTypeConverterTests.kt | 293 ++++++++++++++ .../typeconverters/ShortTypeConverterTests.kt | 341 ++++++++++++++++ .../StringTypeConverterTests.kt | 49 +++ .../typeconverters/UUIDTypeConverterTests.kt | 54 +++ 27 files changed, 3773 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/TypeConverter.kt create mode 100644 src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt create mode 100644 src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt diff --git a/build.gradle b/build.gradle index 18cc356..6c6f36a 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ buildscript { } group 'io.onixlabs' -version '1.0.0' +version '1.1.0' allprojects { repositories { diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt new file mode 100644 index 0000000..4add44f --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt @@ -0,0 +1,46 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import java.math.BigDecimal +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [BigDecimal] type. + */ +class BigDecimalTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [BigDecimal] type. + * + * @param value The value to convert. + * @return Returns a [BigDecimal] representation of the specified value. + */ + override fun convert(value: Any): BigDecimal = when (value) { + is Boolean -> if (value) BigDecimal.ONE else BigDecimal.ZERO + is Byte -> BigDecimal.valueOf(value.toLong()) + is Short -> BigDecimal.valueOf(value.toLong()) + is Int -> BigDecimal.valueOf(value.toLong()) + is Long -> BigDecimal.valueOf(value) + is BigInteger -> BigDecimal(value) + is Double -> value.toBigDecimal() + is BigDecimal -> value + is String -> value.toBigDecimal().stripTrailingZeros() + is Char -> BigDecimal.valueOf(value.toLong()) + else -> throw IllegalTypeConversionException(value.javaClass, BigDecimal::class.java) + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt new file mode 100644 index 0000000..4fd715e --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt @@ -0,0 +1,83 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.isInteger +import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION +import java.math.BigDecimal +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [BigInteger] type. + */ +class BigIntegerTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [BigInteger] type. + * + * @param value The value to convert. + * @return Returns an [BigInteger] representation of the specified value. + */ + override fun convert(value: Any): BigInteger = when (value) { + is Boolean -> if (value) BigInteger.ONE else BigInteger.ZERO + is Byte -> BigInteger.valueOf(value.toLong()) + is Short -> BigInteger.valueOf(value.toLong()) + is Int -> BigInteger.valueOf(value.toLong()) + is Long -> BigInteger.valueOf(value) + is BigInteger -> value + is Float -> value.toBigIntegerChecked() + is Double -> value.toBigIntegerChecked() + is BigDecimal -> value.toBigIntegerChecked() + is String -> value.toBigInteger() + is Char -> BigInteger.valueOf(value.toLong()) + else -> throw IllegalTypeConversionException(value.javaClass, BigInteger::class.java) + } + + /** + * Performs a checked conversion from [Float] to [BigInteger]. + * + * @return Returns a [BigInteger] representation of the specified [Float]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [BigInteger]. + */ + private fun Float.toBigIntegerChecked(): BigInteger = when { + isInteger() -> BigInteger.valueOf(toLong()) + else -> throw NUMERIC_LOSS_OF_PRECISION + } + + /** + * Performs a checked conversion from [Double] to [BigInteger]. + * + * @return Returns a [BigInteger] representation of the specified [Double]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [BigInteger]. + */ + private fun Double.toBigIntegerChecked(): BigInteger = when { + isInteger() -> BigInteger.valueOf(toLong()) + else -> throw NUMERIC_LOSS_OF_PRECISION + } + + /** + * Performs a checked conversion from [BigDecimal] to [BigInteger]. + * + * @return Returns a [BigInteger] representation of the specified [BigDecimal]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [BigInteger]. + */ + private fun BigDecimal.toBigIntegerChecked(): BigInteger = when { + isInteger() -> toBigInteger() + else -> throw NUMERIC_LOSS_OF_PRECISION + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt new file mode 100644 index 0000000..54545ad --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt @@ -0,0 +1,79 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +/** + * Provides a mechanism to safely convert the specified value value to the [Boolean] type. + */ +class BooleanTypeConverter : TypeConverter() { + + private companion object { + const val EX_NUM_TO_BOOL = "Illegal type conversion. Numeric value cannot be converted to Boolean." + const val EX_STR_TO_BOOL = "Illegal type conversion. String value cannot be converted to Boolean." + const val EX_CHR_TO_BOOL = "Illegal type conversion. Char value cannot be converted to Boolean." + } + + /** + * Converts the specified value to the [Boolean] type. + * + * @param value The value to convert. + * @return Returns a [Boolean] representation of the specified value. + */ + override fun convert(value: Any): Boolean = when (value) { + is Boolean -> value + is Number -> value.toBooleanChecked() + is String -> value.toBooleanChecked() + is Char -> value.toBooleanChecked() + else -> throw IllegalTypeConversionException(value.javaClass, Boolean::class.java) + } + + /** + * Performs a checked conversion from [Number] to [Boolean]. + * + * @return Returns a [Boolean] representation of the specified [Number]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Boolean]. + */ + private fun Number.toBooleanChecked(): Boolean = when (this) { + 1 -> true + 0 -> false + else -> throw IllegalTypeConversionException(EX_NUM_TO_BOOL) + } + + /** + * Performs a checked conversion from [String] to [Boolean]. + * + * @return Returns a [Boolean] representation of the specified [String]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Boolean]. + */ + private fun String.toBooleanChecked(): Boolean = when (this.toLowerCase()) { + "true", "yes", "y", "1" -> true + "false", "no", "n", "0" -> false + else -> throw IllegalTypeConversionException(EX_STR_TO_BOOL) + } + + /** + * Performs a checked conversion from [Char] to [Boolean]. + * + * @return Returns a [Boolean] representation of the specified [Char]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Boolean]. + */ + private fun Char.toBooleanChecked(): Boolean = when (this.toLowerCase()) { + 'y', '1' -> true + 'n', '0' -> false + else -> throw IllegalTypeConversionException(EX_CHR_TO_BOOL) + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt new file mode 100644 index 0000000..cb9ac5c --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt @@ -0,0 +1,142 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.* +import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW +import java.math.BigDecimal +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [Byte] type. + */ +class ByteTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [Byte] type. + * + * @param value The value to convert. + * @return Returns a [Byte] representation of the specified value. + */ + override fun convert(value: Any): Byte = when (value) { + is Boolean -> if (value) Byte.ONE else Byte.ZERO + is Byte -> value + is Short -> value.toByteChecked() + is Int -> value.toByteChecked() + is Long -> value.toByteChecked() + is BigInteger -> value.toByteChecked() + is Float -> value.toByteChecked() + is Double -> value.toByteChecked() + is BigDecimal -> value.toByteChecked() + is String -> value.toByte() + is Char -> value.toByteChecked() + else -> throw IllegalTypeConversionException(value.javaClass, Byte::class.java) + } + + /** + * Performs a checked conversion from [Short] to [Byte]. + * + * @return Returns a [Byte] representation of the specified [Short]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Byte]. + */ + private fun Short.toByteChecked(): Byte = when (this) { + in Byte.MIN_VALUE..Byte.MAX_VALUE -> toByte() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Int] to [Byte]. + * + * @return Returns a [Byte] representation of the specified [Int]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Byte]. + */ + private fun Int.toByteChecked(): Byte = when (this) { + in Byte.MIN_VALUE..Byte.MAX_VALUE -> toByte() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Long] to [Byte]. + * + * @return Returns a [Byte] representation of the specified [Long]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Byte]. + */ + private fun Long.toByteChecked(): Byte = when (this) { + in Byte.MIN_VALUE..Byte.MAX_VALUE -> toByte() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigInteger] to [Boolean]. + * + * @return Returns a [Boolean] representation of the specified [BigInteger]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Boolean]. + */ + private fun BigInteger.toByteChecked(): Byte = when (this) { + in Byte.MIN_VALUE.toBigInteger()..Byte.MAX_VALUE.toBigInteger() -> toByte() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Float] to [Byte]. + * + * @return Returns a [Byte] representation of the specified [Float]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Byte]. + */ + private fun Float.toByteChecked(): Byte = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Byte.MIN_VALUE.toFloat()..Byte.MAX_VALUE.toFloat() -> toInt().toByte() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Double] to [Byte]. + * + * @return Returns a [Byte] representation of the specified [Double]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Byte]. + */ + private fun Double.toByteChecked(): Byte = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Byte.MIN_VALUE.toDouble()..Byte.MAX_VALUE.toDouble() -> toInt().toByte() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigDecimal] to [Byte]. + * + * @return Returns a [Byte] representation of the specified [BigDecimal]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Byte]. + */ + private fun BigDecimal.toByteChecked(): Byte = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Byte.MIN_VALUE.toBigDecimal()..Byte.MAX_VALUE.toBigDecimal() -> toByte() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Char] to [Byte]. + * + * @return Returns a [Byte] representation of the specified [Char]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Byte]. + */ + private fun Char.toByteChecked(): Byte = when { + toShort() in Byte.MIN_VALUE..Byte.MAX_VALUE -> toByte() + else -> throw NUMERIC_OVERFLOW + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt new file mode 100644 index 0000000..85676c0 --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt @@ -0,0 +1,134 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.isInteger +import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.toBigDecimal +import io.onixlabs.kotlin.core.toBigInteger +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW +import java.math.BigDecimal +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [Char] type. + */ +class CharTypeConverter : TypeConverter() { + + private companion object { + const val EX_STR_TO_CHR = "Illegal type conversion. String value cannot be converted to Char." + } + + /** + * Converts the specified value to the [Char] type. + * + * @param value The value to convert. + * @return Returns a [Char] representation of the specified value. + */ + override fun convert(value: Any): Char = when (value) { + is Boolean -> if (value) '1' else '0' + is Byte -> value.toChar() + is Short -> value.toChar() + is Int -> value.toCharChecked() + is Long -> value.toCharChecked() + is BigInteger -> value.toCharChecked() + is Float -> value.toCharChecked() + is Double -> value.toCharChecked() + is BigDecimal -> value.toCharChecked() + is String -> value.toCharChecked() + is Char -> value + else -> throw IllegalTypeConversionException(value.javaClass, Char::class.java) + } + + /** + * Performs a checked conversion from [Int] to [Char]. + * + * @return Returns a [Char] representation of the specified [Int]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Char]. + */ + private fun Int.toCharChecked(): Char = when (this) { + in Short.MIN_VALUE..Short.MAX_VALUE -> toChar() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Long] to [Char]. + * + * @return Returns a [Char] representation of the specified [Long]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Char]. + */ + private fun Long.toCharChecked(): Char = when (this) { + in Short.MIN_VALUE..Short.MAX_VALUE -> toChar() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigInteger] to [Char]. + * + * @return Returns a [Char] representation of the specified [BigInteger]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Char]. + */ + private fun BigInteger.toCharChecked(): Char = when (this) { + in Short.MIN_VALUE.toBigInteger()..Short.MAX_VALUE.toBigInteger() -> toShort().toChar() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Float] to [Char]. + * + * @return Returns a [Char] representation of the specified [Float]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Char]. + */ + private fun Float.toCharChecked(): Char = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Short.MIN_VALUE.toFloat()..Short.MAX_VALUE.toFloat() -> toChar() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Double] to [Char]. + * + * @return Returns a [Char] representation of the specified [Double]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Char]. + */ + private fun Double.toCharChecked(): Char = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Short.MIN_VALUE.toDouble()..Short.MAX_VALUE.toDouble() -> toChar() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigDecimal] to [Char]. + * + * @return Returns a [Char] representation of the specified [BigDecimal]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Char]. + */ + private fun BigDecimal.toCharChecked(): Char = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Short.MIN_VALUE.toBigDecimal()..Short.MAX_VALUE.toBigDecimal() -> toShort().toChar() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [String] to [Char]. + * + * @return Returns a [Char] representation of the specified [BigInteger]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [String]. + */ + private fun String.toCharChecked(): Char = singleOrNull() ?: throw IllegalTypeConversionException(EX_STR_TO_CHR) +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt new file mode 100644 index 0000000..a973af4 --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt @@ -0,0 +1,59 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import io.onixlabs.kotlin.core.toBigInteger +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [Double] type. + */ +class DoubleTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [Double] type. + * + * @param value The value to convert. + * @return Returns a [Double] representation of the specified value. + */ + override fun convert(value: Any): Double = when (value) { + is Boolean -> if (value) Double.ONE else Double.ZERO + is Byte -> value.toDouble() + is Short -> value.toDouble() + is Int -> value.toDouble() + is Long -> value.toDouble() + is BigInteger -> value.toDoubleChecked() + is Double -> value + is String -> value.toDouble() + is Char -> value.toDouble() + else -> throw IllegalTypeConversionException(value.javaClass, Double::class.java) + } + + /** + * Performs a checked conversion from [BigInteger] to [Double]. + * + * @return Returns a [Double] representation of the specified [BigInteger]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Double]. + */ + private fun BigInteger.toDoubleChecked(): Double = when (this) { + in Double.MIN_VALUE.toBigInteger()..Double.MAX_VALUE.toBigInteger() -> toDouble() + else -> throw NUMERIC_OVERFLOW + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt new file mode 100644 index 0000000..a340e1e --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt @@ -0,0 +1,43 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO + +/** + * Provides a mechanism to safely convert the specified value value to the [Float] type. + */ +class FloatTypeConverter : TypeConverter() { + + /** + * Converts an object from the input type to the output type. + * + * @param value The value to convert. + * @return Returns an instance of the output type. + */ + override fun convert(value: Any): Float = when (value) { + is Boolean -> if (value) Float.ONE else Float.ZERO + is Byte -> value.toFloat() + is Short -> value.toFloat() + is Int -> value.toFloat() + is Float -> value + is String -> value.toFloat() + is Char -> value.toFloat() + else -> throw IllegalTypeConversionException(value.javaClass, Float::class.java) + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt new file mode 100644 index 0000000..6d10133 --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt @@ -0,0 +1,50 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +/** + * Represents the exception that is thrown when a type converter is unable to convert the specified value. + * + * @param message A message detailing the type conversion exception. + * @param cause An underlying cause of the type conversion exception. + */ +class IllegalTypeConversionException(message: String, cause: Throwable? = null) : Exception(message, cause) { + + internal companion object { + + /** + * An [IllegalTypeConversionException] that is thrown when a numeric value overflows. + */ + val NUMERIC_OVERFLOW = IllegalTypeConversionException("Illegal type conversion. Numeric overflow.") + + /** + * An [IllegalTypeConversionException] that is thrown when a floating point value loses precision. + */ + val NUMERIC_LOSS_OF_PRECISION = IllegalTypeConversionException("Illegal type conversion. Loss of precision.") + } + + /** + * Creates an [IllegalTypeConversionException] from the specified input and output classes. + * This exception details that the input class cannot be mapped to the output class. + * + * @param inputClass The input class. + * @param outputClass The output class. + */ + constructor(inputClass: Class<*>, outputClass: Class<*>) : this( + "Illegal type conversion. Cannot convert from '${inputClass.canonicalName}' to '${outputClass.canonicalName}'." + ) +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt new file mode 100644 index 0000000..b16d956 --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt @@ -0,0 +1,111 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import io.onixlabs.kotlin.core.isInteger +import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW +import java.math.BigDecimal +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [Int] type. + */ +class IntTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [Int] type. + * + * @param value The value to convert. + * @return Returns an [Int] representation of the specified value. + */ + override fun convert(value: Any): Int = when (value) { + is Boolean -> if (value) Int.ONE else Int.ZERO + is Byte -> value.toInt() + is Short -> value.toInt() + is Int -> value + is Long -> value.toIntChecked() + is BigInteger -> value.toIntChecked() + is Float -> value.toIntChecked() + is Double -> value.toIntChecked() + is BigDecimal -> value.toIntChecked() + is String -> value.toInt() + is Char -> value.toInt() + else -> throw IllegalTypeConversionException(value.javaClass, Int::class.java) + } + + /** + * Performs a checked conversion from [Long] to [Int]. + * + * @return Returns an [Int] representation of the specified [Long]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Int]. + */ + private fun Long.toIntChecked(): Int = when (this) { + in Int.MIN_VALUE..Int.MAX_VALUE -> toInt() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigInteger] to [Int]. + * + * @return Returns an [Int] representation of the specified [BigInteger]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Int]. + */ + private fun BigInteger.toIntChecked(): Int = when (this) { + in Int.MIN_VALUE.toBigInteger()..Int.MAX_VALUE.toBigInteger() -> toInt() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Float] to [Int]. + * + * @return Returns an [Int] representation of the specified [Float]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Int]. + */ + private fun Float.toIntChecked(): Int = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Int.MIN_VALUE.toFloat()..Int.MAX_VALUE.toFloat() -> toInt() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Double] to [Int]. + * + * @return Returns an [Int] representation of the specified [Double]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Int]. + */ + private fun Double.toIntChecked(): Int = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Int.MIN_VALUE.toDouble()..Int.MAX_VALUE.toDouble() -> toInt() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigDecimal] to [Int]. + * + * @return Returns an [Int] representation of the specified [BigDecimal]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Int]. + */ + private fun BigDecimal.toIntChecked(): Int = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Int.MIN_VALUE.toBigDecimal()..Int.MAX_VALUE.toBigDecimal() -> toInt() + else -> throw NUMERIC_OVERFLOW + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt new file mode 100644 index 0000000..6b6848b --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt @@ -0,0 +1,100 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import io.onixlabs.kotlin.core.isInteger +import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW +import java.math.BigDecimal +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [Long] type. + */ +class LongTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [Long] type. + * + * @param value The value to convert. + * @return Returns a [Long] representation of the specified value. + */ + override fun convert(value: Any): Long = when (value) { + is Boolean -> if (value) Long.ONE else Long.ZERO + is Byte -> value.toLong() + is Short -> value.toLong() + is Int -> value.toLong() + is Long -> value + is BigInteger -> value.toLongChecked() + is Float -> value.toLongChecked() + is Double -> value.toLongChecked() + is BigDecimal -> value.toLongChecked() + is String -> value.toLong() + is Char -> value.toLong() + else -> throw IllegalTypeConversionException(value.javaClass, Long::class.java) + } + + /** + * Performs a checked conversion from [BigInteger] to [Long]. + * + * @return Returns a [Long] representation of the specified [BigInteger]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Long]. + */ + private fun BigInteger.toLongChecked(): Long = when (this) { + in Long.MIN_VALUE.toBigInteger()..Long.MAX_VALUE.toBigInteger() -> toLong() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Float] to [Long]. + * + * @return Returns a [Long] representation of the specified [Float]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Long]. + */ + private fun Float.toLongChecked(): Long = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Long.MIN_VALUE.toFloat()..Long.MAX_VALUE.toFloat() -> toLong() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Double] to [Long]. + * + * @return Returns a [Long] representation of the specified [Double]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Long]. + */ + private fun Double.toLongChecked(): Long = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Long.MIN_VALUE.toDouble()..Long.MAX_VALUE.toDouble() -> toLong() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigDecimal] to [Long]. + * + * @return Returns a [Long] representation of the specified [BigDecimal]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Long]. + */ + private fun BigDecimal.toLongChecked(): Long = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Long.MIN_VALUE.toBigDecimal()..Long.MAX_VALUE.toBigDecimal() -> toLong() + else -> throw NUMERIC_OVERFLOW + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt new file mode 100644 index 0000000..1079ba9 --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt @@ -0,0 +1,120 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.* +import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION +import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW +import java.math.BigDecimal +import java.math.BigInteger + +/** + * Provides a mechanism to safely convert the specified value value to the [Short] type. + */ +class ShortTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [Short] type. + * + * @param value The value to convert. + * @return Returns a [Short] representation of the specified value. + */ + override fun convert(value: Any): Short = when (value) { + is Boolean -> if (value) Short.ONE else Short.ZERO + is Byte -> value.toShort() + is Short -> value + is Int -> value.toShortChecked() + is Long -> value.toShortChecked() + is BigInteger -> value.toShortChecked() + is Float -> value.toShortChecked() + is Double -> value.toShortChecked() + is BigDecimal -> value.toShortChecked() + is String -> value.toShort() + is Char -> value.toShort() + else -> throw IllegalTypeConversionException(value.javaClass, Short::class.java) + } + + /** + * Performs a checked conversion from [Int] to [Short]. + * + * @return Returns a [Short] representation of the specified [Int]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Short]. + */ + private fun Int.toShortChecked(): Short = when (this) { + in Short.MIN_VALUE..Short.MAX_VALUE -> toShort() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Long] to [Short]. + * + * @return Returns a [Short] representation of the specified [Long]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Short]. + */ + private fun Long.toShortChecked(): Short = when (this) { + in Short.MIN_VALUE..Short.MAX_VALUE -> toShort() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigInteger] to [Short]. + * + * @return Returns a [Short] representation of the specified [BigInteger]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Short]. + */ + private fun BigInteger.toShortChecked(): Short = when (this) { + in Short.MIN_VALUE.toBigInteger()..Short.MAX_VALUE.toBigInteger() -> toShort() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Float] to [Short]. + * + * @return Returns a [Short] representation of the specified [Float]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Short]. + */ + private fun Float.toShortChecked(): Short = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Short.MIN_VALUE.toFloat()..Short.MAX_VALUE.toFloat() -> toInt().toShort() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [Double] to [Short]. + * + * @return Returns a [Short] representation of the specified [Double]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Short]. + */ + private fun Double.toShortChecked(): Short = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Short.MIN_VALUE.toDouble()..Short.MAX_VALUE.toDouble() -> toInt().toShort() + else -> throw NUMERIC_OVERFLOW + } + + /** + * Performs a checked conversion from [BigDecimal] to [Short]. + * + * @return Returns a [Short] representation of the specified [BigDecimal]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [Short]. + */ + private fun BigDecimal.toShortChecked(): Short = when { + !isInteger() -> throw NUMERIC_LOSS_OF_PRECISION + this in Short.MIN_VALUE.toBigDecimal()..Short.MAX_VALUE.toBigDecimal() -> toShort() + else -> throw NUMERIC_OVERFLOW + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverter.kt new file mode 100644 index 0000000..db1a9a2 --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverter.kt @@ -0,0 +1,35 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +/** + * Provides a mechanism to safely convert the specified value value to the [String] type. + */ +class StringTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [String] type. + * + * @param value The value to convert. + * @return Returns a [String] representation of the specified value. + */ + override fun convert(value: Any): String = when (value) { + // TODO : [Kotlin 1.3] Push values to TRUE_STRING and FALSE_STRING in Boolean.Companion + is Boolean -> if (value) "True" else "False" + else -> value.toString() + } +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/TypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/TypeConverter.kt new file mode 100644 index 0000000..10e45fb --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/TypeConverter.kt @@ -0,0 +1,33 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +/** + * Represents the base class for implementing type converters. + * + * @param T The underlying type that the type converter will convert to. + */ +abstract class TypeConverter { + + /** + * Converts the specified value to the [T] type. + * + * @param value The value to convert. + * @return Returns a [T] representation of the specified value. + */ + abstract fun convert(value: Any): T +} diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt new file mode 100644 index 0000000..dcacc8c --- /dev/null +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt @@ -0,0 +1,49 @@ +/** + * Copyright 2020 Matthew Layton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.kotlin.core.typeconverters + +import java.util.* + +/** + * Provides a mechanism to safely convert the specified value value to the [UUID] type. + */ +class UUIDTypeConverter : TypeConverter() { + + /** + * Converts the specified value to the [UUID] type. + * + * @param value The value to convert. + * @return Returns a [UUID] representation of the specified value. + */ + override fun convert(value: Any): UUID = when (value) { + is String -> value.toUUIDChecked() + is UUID -> value + else -> throw IllegalTypeConversionException(value.javaClass, UUID::class.java) + } + + /** + * Performs a checked conversion from [String] to [UUID]. + * + * @return Returns a [UUID] representation of the specified [String]. + * @throws IllegalTypeConversionException if the value cannot be safely converted to [UUID]. + */ + private fun String.toUUIDChecked(): UUID = try { + UUID.fromString(this) + } catch (ex: IllegalArgumentException) { + throw IllegalTypeConversionException("Illegal type conversion. ${ex.message}.") + } +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt new file mode 100644 index 0000000..ef32b48 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt @@ -0,0 +1,185 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.math.BigDecimal +import java.math.BigInteger +import java.util.* + +class BigDecimalTypeConverterTests { + + @Test + fun `BigDecimalTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ONE, result) + } + + @Test + fun `BigDecimalTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ZERO, result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ONE, result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ONE, result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ONE, result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = Long.ONE + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ONE, result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = BigInteger.ONE + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ONE, result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = Double.ONE + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE.toBigDecimal(), result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a BigDecimal`() { + + // Arrange + val value = BigDecimal.ONE + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigDecimal.ONE, result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "123.456" + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals((123.456).toBigDecimal(), result) + } + + @Test + fun `BigDecimalTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = BigDecimalTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32.toBigDecimal(), result) + } + + @Test + fun `BigDecimalTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = BigDecimalTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals( + "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'java.math.BigDecimal'.", + result.message + ) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt new file mode 100644 index 0000000..5593354 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt @@ -0,0 +1,247 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.math.BigDecimal +import java.math.BigInteger +import java.util.* + +class BigIntegerTypeConverterTests { + + @Test + fun `BigIntegerTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ZERO, result) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = Long.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = BigInteger.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a Float`() { + + // Arrange + val value = Float.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should throw an exception when a Float loses precision`() { + + // Arrange + val value = 123.456F + val converter = BigIntegerTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = Double.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should throw an exception when a Double loses precision`() { + + // Arrange + val value = 123.456 + val converter = BigIntegerTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a BigDecimal`() { + + // Arrange + val value = BigDecimal.ONE + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should throw an exception when a BigDecimal loses precision`() { + + // Arrange + val value = (123.456).toBigDecimal() + val converter = BigIntegerTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "1" + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(BigInteger.ONE, result) + } + + @Test + fun `BigIntegerTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = BigIntegerTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32.toBigInteger(), result) + } + + @Test + fun `BigIntegerTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = BigIntegerTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals( + "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'java.math.BigInteger'.", + result.message + ) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt new file mode 100644 index 0000000..a198a32 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt @@ -0,0 +1,142 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.util.* + +class BooleanTypeConverterTests { + + @Test + fun `BooleanTypeConverter should return the expected value for a Boolean value true`() { + + // Arrange + val value = true + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertTrue(result) + } + + @Test + fun `BooleanTypeConverter should return the expected value for a Boolean value false`() { + + // Arrange + val value = false + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertFalse(result) + } + + @Test + fun `BooleanTypeConverter should return the expected value for a Numeric value ONE`() { + + // Arrange + val value = Int.ONE + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertTrue(result) + } + + @Test + fun `BooleanTypeConverter should return the expected value for a Numeric value ZERO`() { + + // Arrange + val value = Int.ZERO + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertFalse(result) + } + + @Test + fun `BooleanTypeConverter should return the expected value for a String value true`() { + + // Arrange + val value = "true" + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertTrue(result) + } + + @Test + fun `BooleanTypeConverter should return the expected value for a String value false`() { + + // Arrange + val value = "false" + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertFalse(result) + } + + @Test + fun `BooleanTypeConverter should return the expected value for a Char value Y`() { + + // Arrange + val value = 'Y' + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertTrue(result) + } + + @Test + fun `BooleanTypeConverter should return the expected value for a Char value N`() { + + // Arrange + val value = 'N' + val converter = BooleanTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertFalse(result) + } + + @Test + fun `BooleanTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = BooleanTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals( + "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'boolean'.", + result.message + ) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt new file mode 100644 index 0000000..bfc033b --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt @@ -0,0 +1,373 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.math.BigDecimal +import java.math.BigInteger +import java.util.* + +class ByteTypeConverterTests { + + @Test + fun `ByteTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ZERO, result) + } + + @Test + fun `ByteTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should throw an exception when a Short overflows`() { + + // Arrange + val value = Short.MAX_VALUE + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should throw an exception when an Int overflows`() { + + // Arrange + val value = Int.MAX_VALUE + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = Long.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should throw an exception when a Long overflows`() { + + // Arrange + val value = Long.MAX_VALUE + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = BigInteger.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should throw an exception when a BigInteger overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigInteger() + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should return the expected value for a Float`() { + + // Arrange + val value = Float.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should throw an exception when a Float overflows`() { + + // Arrange + val value = Int.MAX_VALUE.toFloat() + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should throw an exception when a Float loses precision`() { + + // Arrange + val value = 123.456F + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `ByteTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = Double.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should throw an exception when a Double overflows`() { + + // Arrange + val value = Double.MAX_VALUE + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should throw an exception when a Double loses precision`() { + + // Arrange + val value = 123.456 + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `ByteTypeConverter should return the expected value for a BigDecimal`() { + + // Arrange + val value = BigDecimal.ONE + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should throw an exception when a BigDecimal overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigDecimal() + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should throw an exception when a BigDecimal loses precision`() { + + // Arrange + val value = (123.456).toBigDecimal() + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `ByteTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "1" + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Byte.ONE, result) + } + + @Test + fun `ByteTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = ByteTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32.toByte(), result) + } + + @Test + fun `ByteTypeConverter should throw an exception when a Char overflows`() { + + // Arrange + val value = '\u1255' + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ByteTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = ByteTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'byte'.", result.message) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt new file mode 100644 index 0000000..4a0cf6e --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt @@ -0,0 +1,353 @@ +package io.onixlabs.kotlin.core.typeconverters + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.util.* + +class CharTypeConverterTests { + + @Test + fun `CharTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals('1', result) + } + + @Test + fun `CharTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals('0', result) + } + + @Test + fun `CharTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = 32.toByte() + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = 32.toShort() + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = 32 + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception when an Int overflows`() { + + // Arrange + val value = Int.MAX_VALUE + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `CharTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = 32.toLong() + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception when an Long overflows`() { + + // Arrange + val value = Long.MAX_VALUE + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `CharTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = 32.toBigInteger() + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception when a BigInteger overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigInteger() + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `CharTypeConverter should return the expected value for a Float`() { + + // Arrange + val value = 32.toFloat() + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception when a Float overflows`() { + + // Arrange + val value = Float.MAX_VALUE + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `CharTypeConverter should throw an exception when a Float loses precision`() { + + // Arrange + val value = 123.456F + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `CharTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = 32.toDouble() + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception when a Double overflows`() { + + // Arrange + val value = Double.MAX_VALUE + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `CharTypeConverter should throw an exception when a Double loses precision`() { + + // Arrange + val value = 123.456 + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `CharTypeConverter should return the expected value for a BigDecimal`() { + + // Arrange + val value = 32.toBigDecimal() + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception when a BigDecimal overflows`() { + + // Arrange + val value = Double.MAX_VALUE.toBigDecimal() + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `CharTypeConverter should throw an exception when a BigDecimal loses precision`() { + + // Arrange + val value = (123.456).toBigDecimal() + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `CharTypeConverter should return the expected value for a String`() { + + // Arrange + val value = " " + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception when a String contains more than a single Char`() { + + // Arrange + val value = "ab" + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. String value cannot be converted to Char.", result.message) + } + + @Test + fun `CharTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = CharTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(' ', result) + } + + @Test + fun `CharTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = CharTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'char'.", result.message) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt new file mode 100644 index 0000000..2960d82 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt @@ -0,0 +1,187 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.math.BigInteger +import java.util.* + +class DoubleTypeConverterTests { + + @Test + fun `DoubleTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ZERO, result) + } + + @Test + fun `DoubleTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = Long.ONE + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = BigInteger.ONE + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should throw an exception when a BigInteger overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigInteger().pow(2) + val converter = DoubleTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `DoubleTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = Double.ONE + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "1" + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Double.ONE, result) + } + + @Test + fun `DoubleTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = DoubleTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32.0, result) + } + + @Test + fun `DoubleTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = DoubleTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals( + "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'double'.", + result.message + ) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt new file mode 100644 index 0000000..777679b --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt @@ -0,0 +1,139 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.util.* + +class FloatTypeConverterTests { + + @Test + fun `FloatTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Float.ONE, result) + } + + @Test + fun `FloatTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Float.ZERO, result) + } + + @Test + fun `FloatTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Float.ONE, result) + } + + @Test + fun `FloatTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Float.ONE, result) + } + + @Test + fun `FloatTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Float.ONE, result) + } + + @Test + fun `FloatTypeConverter should return the expected value for a Float`() { + + // Arrange + val value = Float.ONE + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Float.ONE, result) + } + + @Test + fun `FloatTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "1" + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Float.ONE, result) + } + + @Test + fun `FloatTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = FloatTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32.0F, result) + } + + @Test + fun `FloatTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = FloatTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'float'.", result.message) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt new file mode 100644 index 0000000..ed38a37 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt @@ -0,0 +1,325 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.math.BigDecimal +import java.math.BigInteger +import java.util.* + +class IntTypeConverterTests { + + @Test + fun `IntTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ZERO, result) + } + + @Test + fun `IntTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = Long.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should throw an exception when a Long overflows`() { + + // Arrange + val value = Long.MAX_VALUE + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `IntTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = BigInteger.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should throw an exception when a BigInteger overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigInteger() + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `IntTypeConverter should return the expected value for a Float`() { + + // Arrange + val value = Float.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should throw an exception when a Float overflows`() { + + // Arrange + val value = Float.MAX_VALUE + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `IntTypeConverter should throw an exception when a Float loses precision`() { + + // Arrange + val value = 123.456F + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `IntTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = Double.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should throw an exception when a Double overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toDouble() + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `IntTypeConverter should throw an exception when a Double loses precision`() { + + // Arrange + val value = 123.456 + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `IntTypeConverter should return the expected value for a BigDecimal`() { + + // Arrange + val value = BigDecimal.ONE + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should throw an exception when a BigDecimal overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigDecimal() + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `IntTypeConverter should throw an exception when a BigDecimal loses precision`() { + + // Arrange + val value = (123.456).toBigDecimal() + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `IntTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "1" + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Int.ONE, result) + } + + @Test + fun `IntTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = IntTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32, result) + } + + @Test + fun `IntTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = IntTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'int'.", result.message) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt new file mode 100644 index 0000000..78f3ea7 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt @@ -0,0 +1,293 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.math.BigDecimal +import java.math.BigInteger +import java.util.* + +class LongTypeConverterTests { + + @Test + fun `LongTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ZERO, result) + } + + @Test + fun `LongTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = Long.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = BigInteger.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should throw an exception when a BigInteger overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigInteger().pow(2) + val converter = LongTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `LongTypeConverter should return the expected value for a Float`() { + + // Arrange + val value = Float.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should throw an exception when a Float loses precision`() { + + // Arrange + val value = 123.456F + val converter = LongTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `LongTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = Double.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should throw an exception when a Double overflows`() { + + // Arrange + val value = Double.MAX_VALUE + val converter = LongTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `LongTypeConverter should throw an exception when a Double loses precision`() { + + // Arrange + val value = 123.456 + val converter = LongTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `LongTypeConverter should return the expected value for a BigDecimal`() { + + // Arrange + val value = BigDecimal.ONE + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should throw an exception when a BigDecimal overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigDecimal().pow(2) + val converter = LongTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `LongTypeConverter should throw an exception when a BigDecimal loses precision`() { + + // Arrange + val value = (123.456).toBigDecimal() + val converter = LongTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `LongTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "1" + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Long.ONE, result) + } + + @Test + fun `LongTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = LongTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32, result) + } + + @Test + fun `LongTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = LongTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'long'.", result.message) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt new file mode 100644 index 0000000..14738a5 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt @@ -0,0 +1,341 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import io.onixlabs.kotlin.core.ZERO +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.math.BigDecimal +import java.math.BigInteger +import java.util.* + +class ShortTypeConverterTests { + + @Test + fun `ShortTypeConverter should return ONE when Boolean is true`() { + + // Arrange + val value = true + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should return ZERO when Boolean is false`() { + + // Arrange + val value = false + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ZERO, result) + } + + @Test + fun `ShortTypeConverter should return the expected value for a Byte`() { + + // Arrange + val value = Byte.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should return the expected value for a Short`() { + + // Arrange + val value = Short.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should return the expected value for an Int`() { + + // Arrange + val value = Int.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should throw an exception when an Int overflows`() { + + // Arrange + val value = Int.MAX_VALUE + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ShortTypeConverter should return the expected value for a Long`() { + + // Arrange + val value = Long.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should throw an exception when a Long overflows`() { + + // Arrange + val value = Long.MAX_VALUE + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ShortTypeConverter should return the expected value for a BigInteger`() { + + // Arrange + val value = BigInteger.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should throw an exception when a BigInteger overflows`() { + + // Arrange + val value = Long.MAX_VALUE.toBigInteger() + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ShortTypeConverter should return the expected value for a Float`() { + + // Arrange + val value = Float.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should throw an exception when a Float overflows`() { + + // Arrange + val value = Int.MAX_VALUE.toFloat() + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ShortTypeConverter should throw an exception when a Float loses precision`() { + + // Arrange + val value = 123.456F + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `ShortTypeConverter should return the expected value for a Double`() { + + // Arrange + val value = Double.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should throw an exception when a Double overflows`() { + + // Arrange + val value = Int.MAX_VALUE.toDouble() + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ShortTypeConverter should throw an exception when a Double loses precision`() { + + // Arrange + val value = 123.456 + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `ShortTypeConverter should return the expected value for a BigDecimal`() { + + // Arrange + val value = BigDecimal.ONE + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should throw an exception when a BigDecimal overflows`() { + + // Arrange + val value = Int.MAX_VALUE.toBigDecimal() + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Numeric overflow.", result.message) + } + + @Test + fun `ShortTypeConverter should throw an exception when a BigDecimal loses precision`() { + + // Arrange + val value = (123.456).toBigDecimal() + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Loss of precision.", result.message) + } + + @Test + fun `ShortTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "1" + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(Short.ONE, result) + } + + @Test + fun `ShortTypeConverter should return the expected value for a Char`() { + + // Arrange + val value = ' ' + val converter = ShortTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(32.toShort(), result) + } + + @Test + fun `ShortTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = UUID.randomUUID() + val converter = ShortTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'short'.", result.message) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt new file mode 100644 index 0000000..6072c38 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt @@ -0,0 +1,49 @@ +package io.onixlabs.kotlin.core.typeconverters + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class StringTypeConverterTests { + + @Test + fun `StringTypeConverter should return the expected value for a Boolean value true`() { + + // Arrange + val value = true + val converter = StringTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals("True", result) + } + + @Test + fun `StringTypeConverter should return the expected value for a Boolean value false`() { + + // Arrange + val value = false + val converter = StringTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals("False", result) + } + + @Test + fun `StringTypeConverter should return the string representation of all types other than Boolean`() { + + // Arrange + val value = 123456 + val converter = StringTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals("123456", result) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt new file mode 100644 index 0000000..7860118 --- /dev/null +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt @@ -0,0 +1,54 @@ +package io.onixlabs.kotlin.core.typeconverters + +import io.onixlabs.kotlin.core.ONE +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.util.* + +class UUIDTypeConverterTests { + + @Test + fun `UUIDTypeConverter should return the expected value for a String`() { + + // Arrange + val value = "3ab57c8d-ab84-4db0-be2b-db9551dd4af6" + val converter = UUIDTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(4, result.version()) + } + + @Test + fun `UUIDTypeConverter should return the expected value for a UUID`() { + + // Arrange + val value = UUID.fromString("3ab57c8d-ab84-4db0-be2b-db9551dd4af6") + val converter = UUIDTypeConverter() + + // Act + val result = converter.convert(value) + + // Assert + assertEquals(value, result) + } + + @Test + fun `UUIDTypeConverter should throw an exception for an unsupported type`() { + + // Arrange + val value = Int.ONE + val converter = UUIDTypeConverter() + + // Act + val result = assertThrows { + converter.convert(value) + } + + // Assert + assertEquals("Illegal type conversion. Cannot convert from 'java.lang.Integer' to 'java.util.UUID'.", result.message) + } +} \ No newline at end of file From ecdc8807ef46d260bab4ed8030579bd915a63402 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Thu, 25 Feb 2021 22:22:33 +0000 Subject: [PATCH 2/5] Refactored all type converters to use KClass instead of Class. --- .../kotlin/core/typeconverters/BigDecimalTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/BigIntegerTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/BooleanTypeConverter.kt | 4 +++- .../kotlin/core/typeconverters/ByteTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/CharTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/DoubleTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/FloatTypeConverter.kt | 3 ++- .../core/typeconverters/IllegalTypeConversionException.kt | 6 ++++-- .../onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/LongTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/ShortTypeConverter.kt | 3 ++- .../kotlin/core/typeconverters/UUIDTypeConverter.kt | 3 ++- .../core/typeconverters/BigDecimalTypeConverterTests.kt | 2 +- .../core/typeconverters/BigIntegerTypeConverterTests.kt | 2 +- .../kotlin/core/typeconverters/BooleanTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/ByteTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/CharTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/DoubleTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/FloatTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/IntTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/LongTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/ShortTypeConverterTests.kt | 4 ++-- .../kotlin/core/typeconverters/StringTypeConverterTests.kt | 2 +- .../kotlin/core/typeconverters/UUIDTypeConverterTests.kt | 4 ++-- 24 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt index 4add44f..2f4979b 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverter.kt @@ -16,6 +16,7 @@ package io.onixlabs.kotlin.core.typeconverters +import io.onixlabs.kotlin.core.reflection.kotlinClass import java.math.BigDecimal import java.math.BigInteger @@ -41,6 +42,6 @@ class BigDecimalTypeConverter : TypeConverter() { is BigDecimal -> value is String -> value.toBigDecimal().stripTrailingZeros() is Char -> BigDecimal.valueOf(value.toLong()) - else -> throw IllegalTypeConversionException(value.javaClass, BigDecimal::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, BigDecimal::class) } } diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt index 4fd715e..227a316 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverter.kt @@ -18,6 +18,7 @@ package io.onixlabs.kotlin.core.typeconverters import io.onixlabs.kotlin.core.isInteger import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.reflection.kotlinClass import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION import java.math.BigDecimal import java.math.BigInteger @@ -45,7 +46,7 @@ class BigIntegerTypeConverter : TypeConverter() { is BigDecimal -> value.toBigIntegerChecked() is String -> value.toBigInteger() is Char -> BigInteger.valueOf(value.toLong()) - else -> throw IllegalTypeConversionException(value.javaClass, BigInteger::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, BigInteger::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt index 54545ad..142208d 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverter.kt @@ -16,6 +16,8 @@ package io.onixlabs.kotlin.core.typeconverters +import io.onixlabs.kotlin.core.reflection.kotlinClass + /** * Provides a mechanism to safely convert the specified value value to the [Boolean] type. */ @@ -38,7 +40,7 @@ class BooleanTypeConverter : TypeConverter() { is Number -> value.toBooleanChecked() is String -> value.toBooleanChecked() is Char -> value.toBooleanChecked() - else -> throw IllegalTypeConversionException(value.javaClass, Boolean::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Boolean::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt index cb9ac5c..02d2a9f 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverter.kt @@ -18,6 +18,7 @@ package io.onixlabs.kotlin.core.typeconverters import io.onixlabs.kotlin.core.* import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.reflection.kotlinClass import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW import java.math.BigDecimal @@ -46,7 +47,7 @@ class ByteTypeConverter : TypeConverter() { is BigDecimal -> value.toByteChecked() is String -> value.toByte() is Char -> value.toByteChecked() - else -> throw IllegalTypeConversionException(value.javaClass, Byte::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Byte::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt index 85676c0..35afd73 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverter.kt @@ -18,6 +18,7 @@ package io.onixlabs.kotlin.core.typeconverters import io.onixlabs.kotlin.core.isInteger import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.reflection.kotlinClass import io.onixlabs.kotlin.core.toBigDecimal import io.onixlabs.kotlin.core.toBigInteger import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION @@ -52,7 +53,7 @@ class CharTypeConverter : TypeConverter() { is BigDecimal -> value.toCharChecked() is String -> value.toCharChecked() is Char -> value - else -> throw IllegalTypeConversionException(value.javaClass, Char::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Char::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt index a973af4..eb30433 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverter.kt @@ -18,6 +18,7 @@ package io.onixlabs.kotlin.core.typeconverters import io.onixlabs.kotlin.core.ONE import io.onixlabs.kotlin.core.ZERO +import io.onixlabs.kotlin.core.reflection.kotlinClass import io.onixlabs.kotlin.core.toBigInteger import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW import java.math.BigInteger @@ -43,7 +44,7 @@ class DoubleTypeConverter : TypeConverter() { is Double -> value is String -> value.toDouble() is Char -> value.toDouble() - else -> throw IllegalTypeConversionException(value.javaClass, Double::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Double::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt index a340e1e..5ed0a6c 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverter.kt @@ -18,6 +18,7 @@ package io.onixlabs.kotlin.core.typeconverters import io.onixlabs.kotlin.core.ONE import io.onixlabs.kotlin.core.ZERO +import io.onixlabs.kotlin.core.reflection.kotlinClass /** * Provides a mechanism to safely convert the specified value value to the [Float] type. @@ -38,6 +39,6 @@ class FloatTypeConverter : TypeConverter() { is Float -> value is String -> value.toFloat() is Char -> value.toFloat() - else -> throw IllegalTypeConversionException(value.javaClass, Float::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Float::class) } } diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt index 6d10133..71b659c 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IllegalTypeConversionException.kt @@ -16,6 +16,8 @@ package io.onixlabs.kotlin.core.typeconverters +import kotlin.reflect.KClass + /** * Represents the exception that is thrown when a type converter is unable to convert the specified value. * @@ -44,7 +46,7 @@ class IllegalTypeConversionException(message: String, cause: Throwable? = null) * @param inputClass The input class. * @param outputClass The output class. */ - constructor(inputClass: Class<*>, outputClass: Class<*>) : this( - "Illegal type conversion. Cannot convert from '${inputClass.canonicalName}' to '${outputClass.canonicalName}'." + constructor(inputClass: KClass<*>, outputClass: KClass<*>) : this( + "Illegal type conversion. Cannot convert from '${inputClass.qualifiedName}' to '${outputClass.qualifiedName}'." ) } diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt index b16d956..b5c7a17 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverter.kt @@ -20,6 +20,7 @@ import io.onixlabs.kotlin.core.ONE import io.onixlabs.kotlin.core.ZERO import io.onixlabs.kotlin.core.isInteger import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.reflection.kotlinClass import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW import java.math.BigDecimal @@ -48,7 +49,7 @@ class IntTypeConverter : TypeConverter() { is BigDecimal -> value.toIntChecked() is String -> value.toInt() is Char -> value.toInt() - else -> throw IllegalTypeConversionException(value.javaClass, Int::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Int::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt index 6b6848b..a5d4994 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverter.kt @@ -20,6 +20,7 @@ import io.onixlabs.kotlin.core.ONE import io.onixlabs.kotlin.core.ZERO import io.onixlabs.kotlin.core.isInteger import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.reflection.kotlinClass import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW import java.math.BigDecimal @@ -48,7 +49,7 @@ class LongTypeConverter : TypeConverter() { is BigDecimal -> value.toLongChecked() is String -> value.toLong() is Char -> value.toLong() - else -> throw IllegalTypeConversionException(value.javaClass, Long::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Long::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt index 1079ba9..ab996df 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverter.kt @@ -18,6 +18,7 @@ package io.onixlabs.kotlin.core.typeconverters import io.onixlabs.kotlin.core.* import io.onixlabs.kotlin.core.math.isInteger +import io.onixlabs.kotlin.core.reflection.kotlinClass import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_LOSS_OF_PRECISION import io.onixlabs.kotlin.core.typeconverters.IllegalTypeConversionException.Companion.NUMERIC_OVERFLOW import java.math.BigDecimal @@ -46,7 +47,7 @@ class ShortTypeConverter : TypeConverter() { is BigDecimal -> value.toShortChecked() is String -> value.toShort() is Char -> value.toShort() - else -> throw IllegalTypeConversionException(value.javaClass, Short::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, Short::class) } /** diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt index dcacc8c..66257bf 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverter.kt @@ -16,6 +16,7 @@ package io.onixlabs.kotlin.core.typeconverters +import io.onixlabs.kotlin.core.reflection.kotlinClass import java.util.* /** @@ -32,7 +33,7 @@ class UUIDTypeConverter : TypeConverter() { override fun convert(value: Any): UUID = when (value) { is String -> value.toUUIDChecked() is UUID -> value - else -> throw IllegalTypeConversionException(value.javaClass, UUID::class.java) + else -> throw IllegalTypeConversionException(value.kotlinClass, UUID::class) } /** diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt index ef32b48..b4daf7e 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigDecimalTypeConverterTests.kt @@ -182,4 +182,4 @@ class BigDecimalTypeConverterTests { result.message ) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt index 5593354..7f433cc 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BigIntegerTypeConverterTests.kt @@ -244,4 +244,4 @@ class BigIntegerTypeConverterTests { result.message ) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt index a198a32..526e6db 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/BooleanTypeConverterTests.kt @@ -135,8 +135,8 @@ class BooleanTypeConverterTests { // Assert assertEquals( - "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'boolean'.", + "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Boolean'.", result.message ) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt index bfc033b..808d2f0 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ByteTypeConverterTests.kt @@ -368,6 +368,6 @@ class ByteTypeConverterTests { } // Assert - assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'byte'.", result.message) + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Byte'.", result.message) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt index 4a0cf6e..bc283a1 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/CharTypeConverterTests.kt @@ -348,6 +348,6 @@ class CharTypeConverterTests { } // Assert - assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'char'.", result.message) + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Char'.", result.message) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt index 2960d82..5c21aea 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/DoubleTypeConverterTests.kt @@ -180,8 +180,8 @@ class DoubleTypeConverterTests { // Assert assertEquals( - "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'double'.", + "Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Double'.", result.message ) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt index 777679b..d4da152 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/FloatTypeConverterTests.kt @@ -134,6 +134,6 @@ class FloatTypeConverterTests { } // Assert - assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'float'.", result.message) + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Float'.", result.message) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt index ed38a37..46fdbd4 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/IntTypeConverterTests.kt @@ -320,6 +320,6 @@ class IntTypeConverterTests { } // Assert - assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'int'.", result.message) + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Int'.", result.message) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt index 78f3ea7..cfddcd6 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/LongTypeConverterTests.kt @@ -288,6 +288,6 @@ class LongTypeConverterTests { } // Assert - assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'long'.", result.message) + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Long'.", result.message) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt index 14738a5..1f84a97 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/ShortTypeConverterTests.kt @@ -336,6 +336,6 @@ class ShortTypeConverterTests { } // Assert - assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'short'.", result.message) + assertEquals("Illegal type conversion. Cannot convert from 'java.util.UUID' to 'kotlin.Short'.", result.message) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt index 6072c38..d57cee1 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/StringTypeConverterTests.kt @@ -46,4 +46,4 @@ class StringTypeConverterTests { // Assert assertEquals("123456", result) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt index 7860118..d202040 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/typeconverters/UUIDTypeConverterTests.kt @@ -49,6 +49,6 @@ class UUIDTypeConverterTests { } // Assert - assertEquals("Illegal type conversion. Cannot convert from 'java.lang.Integer' to 'java.util.UUID'.", result.message) + assertEquals("Illegal type conversion. Cannot convert from 'kotlin.Int' to 'java.util.UUID'.", result.message) } -} \ No newline at end of file +} From f058e9e1bb5c8cdf8a088e3c5b8c1949acc6148e Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Fri, 26 Feb 2021 12:52:45 +0000 Subject: [PATCH 3/5] Updated KType extensions. --- .../core/reflection/Extensions.KType.kt | 9 ++-- .../core/reflection/KTypeExtensionTests.kt | 48 +++++++++---------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/main/kotlin/io/onixlabs/kotlin/core/reflection/Extensions.KType.kt b/src/main/kotlin/io/onixlabs/kotlin/core/reflection/Extensions.KType.kt index 6e8521e..ba6e53f 100644 --- a/src/main/kotlin/io/onixlabs/kotlin/core/reflection/Extensions.KType.kt +++ b/src/main/kotlin/io/onixlabs/kotlin/core/reflection/Extensions.KType.kt @@ -25,17 +25,20 @@ import kotlin.reflect.jvm.jvmErasure /** * Gets the formatted simple name of the type, including any generic type arguments. */ -val KType.name: String get() = "${jvmErasure.simpleName}${getFormattedArguments(false)}$nullableToken" +val KType.formattedSimpleName: String + get() = "${jvmErasure.simpleName}${getFormattedArguments(false)}$nullableToken" /** * Gets the formatted qualified name of the type, including any generic type arguments. */ -val KType.fullName: String get() = "${jvmErasure.qualifiedName}${getFormattedArguments(true)}$nullableToken" +val KType.formattedQualifiedName: String + get() = "${jvmErasure.qualifiedName}${getFormattedArguments(true)}$nullableToken" /** * Gets a nullable token for the specified string, or an empty string if the type is non-nullable. */ -private val KType.nullableToken: String get() = if (isMarkedNullable) "?" else String.EMPTY +private val KType.nullableToken: String + get() = if (isMarkedNullable) "?" else String.EMPTY /** * Gets a formatted list of generic type argument names. diff --git a/src/test/kotlin/io/onixlabs/kotlin/core/reflection/KTypeExtensionTests.kt b/src/test/kotlin/io/onixlabs/kotlin/core/reflection/KTypeExtensionTests.kt index ee70320..95485d9 100644 --- a/src/test/kotlin/io/onixlabs/kotlin/core/reflection/KTypeExtensionTests.kt +++ b/src/test/kotlin/io/onixlabs/kotlin/core/reflection/KTypeExtensionTests.kt @@ -32,7 +32,7 @@ class KTypeExtensionTests { val type = UUID::class.createType(nullable = false) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("UUID", name) @@ -45,7 +45,7 @@ class KTypeExtensionTests { val type = UUID::class.createType(nullable = true) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("UUID?", name) @@ -59,7 +59,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = false) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("ArrayList", name) @@ -73,7 +73,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = false) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("ArrayList", name) @@ -87,7 +87,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = true) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("ArrayList?", name) @@ -101,7 +101,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = true) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("ArrayList?", name) @@ -119,7 +119,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = false) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("Map", name) @@ -137,7 +137,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = false) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("Map", name) @@ -155,7 +155,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = true) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("Map?", name) @@ -173,7 +173,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = true) // Act - val name = type.name + val name = type.formattedSimpleName // Assert assertEquals("Map?", name) @@ -187,7 +187,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = false) // Act - val name = type.name + val name = type.formattedSimpleName // Assert //fail(type.arguments.joinToString()) @@ -202,7 +202,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = true) // Act - val name = type.name + val name = type.formattedSimpleName // Assert //fail(type.arguments.joinToString()) @@ -216,7 +216,7 @@ class KTypeExtensionTests { val type = UUID::class.createType(nullable = false) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.UUID", name) @@ -229,7 +229,7 @@ class KTypeExtensionTests { val type = UUID::class.createType(nullable = true) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.UUID?", name) @@ -243,7 +243,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = false) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.ArrayList", name) @@ -257,7 +257,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = false) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.ArrayList", name) @@ -271,7 +271,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = true) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.ArrayList?", name) @@ -285,7 +285,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = true) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.ArrayList?", name) @@ -303,7 +303,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = false) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("kotlin.collections.Map", name) @@ -321,7 +321,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = false) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("kotlin.collections.Map", name) @@ -339,7 +339,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = true) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("kotlin.collections.Map?", name) @@ -357,7 +357,7 @@ class KTypeExtensionTests { val type = Map::class.createType(arguments = arguments, nullable = true) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("kotlin.collections.Map?", name) @@ -371,7 +371,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = false) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.ArrayList<*>", name) @@ -385,7 +385,7 @@ class KTypeExtensionTests { val type = ArrayList::class.createType(arguments = arguments, nullable = true) // Act - val name = type.fullName + val name = type.formattedQualifiedName // Assert assertEquals("java.util.ArrayList<*>?", name) From 8228da5a791bda0566f61f0d879926ed3e11d5e6 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Fri, 26 Feb 2021 12:53:16 +0000 Subject: [PATCH 4/5] Version bump. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6c6f36a..109048a 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ buildscript { } group 'io.onixlabs' -version '1.1.0' +version '2.0.0' allprojects { repositories { From 9bcc51604a7f0832414e683fe1f5af8e8e01e84d Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Fri, 26 Feb 2021 12:58:44 +0000 Subject: [PATCH 5/5] Updated changelog. --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac303b..3aac6cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,34 @@ This document serves as the change log for the ONIXLabs Kotlin Core API. +## Version 2.0.0 + +#### TypeConverter (abstract class) + +Represents the base class for implementing type converters. Type converters represent a mechanism to convert from one type to another, using type-safe convensions. + +The following type converters are implemented: + +- BigDecimalTypeConverter +- BigIntegerTypeConverter +- BooleanTypeConverter +- ByteTypeConverter +- CharTypeConverter +- DoubleTypeConverter +- FloatTypeConverter +- IntTypeConverter +- LongTypeConverter +- ShortTypeConverter +- StringTypeConverter +- UUIDTypeConverter + +### Extensions + +#### KType Extensions + +- Renamed `name` to `formattedSimpleName`. +- Renamed `fullName` to `formattedQualifiedName`. + ## Version 1.0.0 #### ConsoleColor (enum)