Skip to content

Commit e2038f7

Browse files
committed
CellConversionException
1 parent b427eae commit e2038f7

File tree

4 files changed

+57
-17
lines changed

4 files changed

+57
-17
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.jetbrains.kotlinx.dataframe.exceptions
2+
3+
import kotlin.reflect.KType
4+
5+
public class CellConversionException(
6+
value: Any?,
7+
from: KType,
8+
to: KType,
9+
public val column: String,
10+
public val row: Int?,
11+
override val cause: Throwable?
12+
) : TypeConversionException(value, from, to) {
13+
override val message: String
14+
get() = "${super.message} in column $column, row $row"
15+
}

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/exceptions/TypeConversionException.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package org.jetbrains.kotlinx.dataframe.exceptions
22

3-
import kotlin.reflect.*
3+
import kotlin.reflect.KType
44

5-
public class TypeConversionException(public val value: Any?, public val from: KType, public val to: KType) : RuntimeException() {
5+
public open class TypeConversionException(public val value: Any?, public val from: KType, public val to: KType) : RuntimeException() {
66

77
override val message: String
88
get() = "Failed to convert '$value' from $from to $to"

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/convert.kt

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import org.jetbrains.kotlinx.dataframe.api.to
2727
import org.jetbrains.kotlinx.dataframe.columns.values
2828
import org.jetbrains.kotlinx.dataframe.dataTypes.IFRAME
2929
import org.jetbrains.kotlinx.dataframe.dataTypes.IMG
30+
import org.jetbrains.kotlinx.dataframe.exceptions.CellConversionException
3031
import org.jetbrains.kotlinx.dataframe.exceptions.TypeConversionException
3132
import org.jetbrains.kotlinx.dataframe.exceptions.TypeConverterNotFoundException
3233
import org.jetbrains.kotlinx.dataframe.impl.columns.DataColumnInternal
@@ -79,31 +80,50 @@ internal fun AnyCol.convertToTypeImpl(to: KType): AnyCol {
7980
else -> throw TypeConversionException(null, from, to)
8081
}
8182

82-
return when {
83-
from == to -> this
84-
from.isSubtypeOf(to) -> (this as DataColumnInternal<*>).changeType(to.withNullability(hasNulls()))
85-
else -> when (val converter = getConverter(from, to, ParserOptions(locale = Locale.getDefault()))) {
86-
null -> when (from.classifier) {
87-
Any::class, Number::class, java.io.Serializable::class -> {
83+
fun applyConverter(converter: TypeConverter): AnyCol {
84+
var currentRow = 0
85+
try {
86+
val values = values.mapIndexed { row, value ->
87+
currentRow = row
88+
value?.let { converter(value) }.checkNulls()
89+
}
90+
return DataColumn.createValueColumn(name, values, to.withNullability(nullsFound))
91+
} catch (e: TypeConversionException) {
92+
throw CellConversionException(e.value, e.from, e.to, this.name(), currentRow, e)
93+
}
94+
}
95+
96+
fun convertPerCell(): AnyCol {
97+
var currentRow = 0
98+
try {
99+
return when (from.classifier) {
100+
Any::class, Comparable::class, Number::class, java.io.Serializable::class -> {
88101
// find converter for every value
89-
val values = values.map {
90-
it?.let {
102+
val values = values.mapIndexed { row, value ->
103+
currentRow = row
104+
value?.let {
91105
val clazz = it.javaClass.kotlin
92106
val type = clazz.createStarProjectedType(false)
93-
val converter = getConverter(type, to, ParserOptions(locale = Locale.getDefault())) ?: throw TypeConverterNotFoundException(from, to)
107+
val converter = getConverter(type, to, ParserOptions(locale = Locale.getDefault()))
108+
?: throw TypeConverterNotFoundException(from, to)
94109
converter(it)
95110
}.checkNulls()
96111
}
97112
DataColumn.createValueColumn(name, values, to.withNullability(nullsFound))
98113
}
99114
else -> throw TypeConverterNotFoundException(from, to)
100115
}
101-
else -> {
102-
val values = values.map {
103-
it?.let { converter(it) }.checkNulls()
104-
}
105-
DataColumn.createValueColumn(name, values, to.withNullability(nullsFound))
106-
}
116+
} catch (e: TypeConversionException) {
117+
throw CellConversionException(e.value, e.from, e.to, this.name(), currentRow, e)
118+
}
119+
}
120+
121+
return when {
122+
from == to -> this
123+
from.isSubtypeOf(to) -> (this as DataColumnInternal<*>).changeType(to.withNullability(hasNulls()))
124+
else -> when (val converter = getConverter(from, to, ParserOptions(locale = Locale.getDefault()))) {
125+
null -> convertPerCell()
126+
else -> applyConverter(converter)
107127
}
108128
}
109129
}

core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import kotlinx.datetime.Instant
88
import org.jetbrains.kotlinx.dataframe.DataColumn
99
import org.jetbrains.kotlinx.dataframe.DataFrame
1010
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
11+
import org.jetbrains.kotlinx.dataframe.exceptions.CellConversionException
1112
import org.jetbrains.kotlinx.dataframe.exceptions.TypeConversionException
1213
import org.jetbrains.kotlinx.dataframe.exceptions.TypeConverterNotFoundException
1314
import org.jetbrains.kotlinx.dataframe.hasNulls
@@ -80,6 +81,10 @@ class ConvertTests {
8081
columnOf("a").convertTo<IntClass>()
8182
}
8283

84+
shouldThrow<CellConversionException> {
85+
columnOf("1", "10", "a").convertTo<IntClass>()
86+
}.row shouldBe 2
87+
8388
shouldThrow<TypeConverterNotFoundException> {
8489
columnOf(EnumClass.A).convertTo<IntClass>()
8590
}

0 commit comments

Comments
 (0)