Skip to content

Commit

Permalink
Merge pull request #1 from brianwernick/enum_converter_nullability
Browse files Browse the repository at this point in the history
Updated the `EnumValueConverter` to be nullable & added tests
  • Loading branch information
brianwernick authored Jun 21, 2023
2 parents 7f4cdc2 + 748fb9a commit 2b31145
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,27 @@ import kotlin.reflect.KClass
* [Enum] in preferences. The [String] value represents
* the `name` of the [Enum]
*/
class EnumValueConverter<T: Enum<T>>(
private val enumClass: KClass<T>,
private val errorHandler: ErrorHandler<T> = DefaultErrorHandler()
): ValueConverter<T, String> {
override fun toConverted(originalValue: T): String {
return originalValue.name
class EnumValueConverter<E: Enum<E>, T: E?>(
private val enumClass: KClass<E>,
private val errorHandler: ErrorHandler<E, T> = DefaultErrorHandler<E,T>()
): ValueConverter<T, String?> {
override fun toConverted(originalValue: T): String? {
return originalValue?.name
}

override fun toOriginal(convertedValue: String): T {
return enumClass.java.enumConstants?.first {
it.name.equals(convertedValue, true)
} ?: errorHandler.onUnknownName(convertedValue, enumClass)
@Suppress("UNCHECKED_CAST")
override fun toOriginal(convertedValue: String?): T {
return convertedValue?.let { name ->
enumClass.java.enumConstants?.firstOrNull {
it.name.equals(name, true)
} ?: errorHandler.onUnknownName(convertedValue, enumClass)
} as T
}

/**
* Defines how [EnumValueConverter] errors should be handled.
*/
fun interface ErrorHandler<T: Enum<T>> {
fun interface ErrorHandler<E: Enum<E>, T:E?> {
/**
* Called when a name (stored value) doesn't map to a defined Enum value for [enumClass].
* This can happen if the name of a value is changed after it was stored.
Expand All @@ -34,15 +37,15 @@ class EnumValueConverter<T: Enum<T>>(
* @param enumClass the [KClass] representing the destination Enum
* @return The Enum value to use for the given [name]
*/
fun onUnknownName(name: String, enumClass: KClass<T>): T
fun onUnknownName(name: String?, enumClass: KClass<E>): T
}

/**
* An implementation of [ErrorHandler] that throws an [IllegalArgumentException] when
* any error occurs.
*/
class DefaultErrorHandler<T: Enum<T>>: ErrorHandler<T> {
override fun onUnknownName(name: String, enumClass: KClass<T>): T {
class DefaultErrorHandler<E: Enum<E>, T: E?>: ErrorHandler<E, T> {
override fun onUnknownName(name: String?, enumClass: KClass<E>): T {
throw IllegalArgumentException("No Enum value of \"$name\" can be found for ${enumClass.simpleName}")
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.devbrackets.android.datastore.converter.core

import org.junit.Assert
import org.junit.Test

class EnumValueConverterTest {

@Test
fun toConvertedNull() {
// Given
val converter = EnumValueConverter(TestEnum::class)

// When
val actual = converter.toConverted(null)

// Then
Assert.assertNull(actual)
}

@Test
fun toConvertedExists() {
// Given
val converter = EnumValueConverter(TestEnum::class)

// When
val actual = converter.toConverted(TestEnum.FIRST)

// Then
Assert.assertEquals("FIRST", actual)
}

@Test
fun toOriginalNull() {
// Given
val converter = EnumValueConverter(TestEnum::class)

// When
val actual = converter.toOriginal(null)

// Then
Assert.assertNull(actual)
}

@Test
fun toOriginalExists() {
// Given
val converter = EnumValueConverter(TestEnum::class)

// When
val actual = converter.toOriginal(TestEnum.SECOND.name)

// Then
Assert.assertEquals(TestEnum.SECOND, actual)
}

@Test
fun toOriginalNotExists() {
// Given
val converter = EnumValueConverter(TestEnum::class)

// When / Then
Assert.assertThrows(IllegalArgumentException::class.java) {
converter.toOriginal("FOURTH")
}
}

private enum class TestEnum {
FIRST,
SECOND,
THIRD
}
}
6 changes: 3 additions & 3 deletions libraryInfo.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARTIFACT_ID = datastore
GROUP_ID = com.devbrackets.android

VERSION_MAJOR = 0
VERSION_MAJOR = 1
VERSION_MINOR = 0
VERSION_PATCH = 1
VERSION_PRE_RELEASE = preview01
VERSION_PATCH = 0
VERSION_PRE_RELEASE = preview01

0 comments on commit 2b31145

Please sign in to comment.