From 2358257c1080b7ce78270535f82f0b960d48261a Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 6 Jun 2022 16:21:21 +0200 Subject: refactor(trace/api): Introduce type system for trace API This change updates the trace API by introducing a limited type system for the table columns. Previously, the table columns could have any possible type representable by the JVM. With this change, we limit the available types to a small type system. --- .../main/kotlin/org/opendc/trace/TableReader.kt | 222 ++++++++++++++++----- 1 file changed, 176 insertions(+), 46 deletions(-) (limited to 'opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/TableReader.kt') diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/TableReader.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/TableReader.kt index 8a796e6c..42b1c690 100644 --- a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/TableReader.kt +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/TableReader.kt @@ -22,8 +22,12 @@ package org.opendc.trace +import java.time.Duration +import java.time.Instant +import java.util.UUID + /** - * Base class for reading entities from a workload trace table in streaming fashion. + * Base class for reading entities from a [Table] in streaming fashion. */ public interface TableReader : AutoCloseable { /** @@ -34,20 +38,15 @@ public interface TableReader : AutoCloseable { public fun nextRow(): Boolean /** - * Resolve the index of the specified [column] for this reader. + * Resolve the index of the column by its [name]. * - * @param column The column to lookup. + * @param name The name of the column to lookup. * @return The zero-based index of the column or a negative value if the column is not present in this table. */ - public fun resolve(column: TableColumn<*>): Int - - /** - * Determine whether the [TableReader] supports the specified [column]. - */ - public fun hasColumn(column: TableColumn<*>): Boolean = resolve(column) >= 0 + public fun resolve(name: String): Int /** - * Determine whether the specified [column] has a `null` value for the current row. + * Determine whether the column with the specified [index] has a `null` value for the current row. * * @param index The zero-based index of the column to check for a null value. * @throws IllegalArgumentException if the column index is not valid for this reader. @@ -55,15 +54,6 @@ public interface TableReader : AutoCloseable { */ public fun isNull(index: Int): Boolean - /** - * Obtain the object value of the column with the specified [index]. - * - * @param index The zero-based index of the column to obtain the value for. - * @throws IllegalArgumentException if the column index is not valid for this reader. - * @return The object value of the column. - */ - public fun get(index: Int): Any? - /** * Obtain the boolean value of the column with the specified [index]. * @@ -74,7 +64,7 @@ public interface TableReader : AutoCloseable { public fun getBoolean(index: Int): Boolean /** - * Obtain the integer value of the column with the specified [index]. + * Obtain the boolean value of the column with the specified [index]. * * @param index The zero-based index of the column to obtain the value for. * @throws IllegalArgumentException if the column index is not valid for this reader. @@ -91,6 +81,15 @@ public interface TableReader : AutoCloseable { */ public fun getLong(index: Int): Long + /** + * Obtain the float value of the column with the specified [index]. + * + * @param index The zero-based index of the column to obtain the value for. + * @throws IllegalArgumentException if the column index is not valid for this reader. + * @return The float value of the column or [Float.NaN] if the column is `null`. + */ + public fun getFloat(index: Int): Float + /** * Obtain the double value of the column with the specified [index]. * @@ -101,62 +100,193 @@ public interface TableReader : AutoCloseable { public fun getDouble(index: Int): Double /** - * Determine whether the specified [column] has a `null` value for the current row. + * Obtain the [String] value of the column with the specified [index]. * - * @param column The column to lookup. - * @throws IllegalArgumentException if the column is not valid for this table. - * @return `true` if the column value for the current value has a `null` value, `false` otherwise. + * @param index The zero-based index of the column to obtain the value for. + * @throws IllegalArgumentException if the column index is not valid for this reader. + * @return The [String] value of the column or `null` if the column is `null`. */ - public fun isNull(column: TableColumn<*>): Boolean = isNull(resolve(column)) + public fun getString(index: Int): String? /** - * Obtain the value of the current column with type [T]. + * Obtain the [UUID] value of the column with the specified [index]. * - * @param column The column to obtain the value for. - * @throws IllegalArgumentException if the column is not valid for this reader. - * @return The object value of the column. + * @param index The zero-based index of the column to obtain the value for. + * @throws IllegalArgumentException if the column index is not valid for this reader. + * @return The [UUID] value of the column or `null` if the column is `null`. + */ + public fun getUUID(index: Int): UUID? + + /** + * Obtain the [Instant] value of the column with the specified [index]. + * + * @param index The zero-based index of the column to obtain the value for. + * @throws IllegalArgumentException if the column index is not valid for this reader. + * @return The [Instant] value of the column or `null` if the column is `null`. + */ + public fun getInstant(index: Int): Instant? + + /** + * Obtain the [Duration] value of the column with the specified [index]. + * + * @param index The zero-based index of the column to obtain the value for. + * @throws IllegalArgumentException if the column index is not valid for this reader. + * @return The [Duration] value of the column or `null` if the column is `null`. + */ + public fun getDuration(index: Int): Duration? + + /** + * Obtain the value of the column with the specified [index] as [List]. + * + * @param index The zero-based index of the column to obtain the value for. + * @param elementType Class representing the Java data type to convert elements of the designated column to. + * @throws IllegalArgumentException if the column index is not valid for this reader or this type. + * @return The value of the column as `List` or `null` if the column is null. + */ + public fun getList(index: Int, elementType: Class): List? + + /** + * Obtain the value of the column with the specified [index] as [Set]. + * + * @param index The zero-based index of the column to obtain the value for. + * @param elementType Class representing the Java data type to convert elements of the designated column to. + * @throws IllegalArgumentException if the column index is not valid for this reader or this type. + * @return The value of the column as `Set` or `null` if the column is null. + */ + public fun getSet(index: Int, elementType: Class): Set? + + /** + * Obtain the value of the column with the specified [index] as [Set]. + * + * @param index The zero-based index of the column to obtain the value for. + * @param keyType Class representing the Java data type to convert the keys of the designated column to. + * @param valueType Class representing the Java data type to convert the values of the designated column to. + * @throws IllegalArgumentException if the column index is not valid for this reader or this type. + * @return The value of the column as `Map` or `null` if the column is null. + */ + public fun getMap(index: Int, keyType: Class, valueType: Class): Map? + + /** + * Determine whether a column named [name] has a `null` value for the current row. + * + * @param name The name of the column to lookup. + * @throws IllegalArgumentException if the column is not valid for this table. + * @return `true` if the column value for the current value has a `null` value, `false` otherwise. */ - public fun get(column: TableColumn): T { - // This cast should always succeed since the resolve the index of the typed column - @Suppress("UNCHECKED_CAST") - return get(resolve(column)) as T - } + public fun isNull(name: String): Boolean = isNull(resolve(name)) /** - * Read the specified [column] as boolean. + * Read the column named [name] as boolean. * - * @param column The column to obtain the value for. + * @param name The name of the column to get the value for. * @throws IllegalArgumentException if the column is not valid for this reader. * @return The boolean value of the column or `false` if the column is `null`. */ - public fun getBoolean(column: TableColumn): Boolean = getBoolean(resolve(column)) + public fun getBoolean(name: String): Boolean = getBoolean(resolve(name)) /** - * Read the specified [column] as integer. + * Read the column named [name] as integer. * - * @param column The column to obtain the value for. + * @param name The name of the column to get the value for. * @throws IllegalArgumentException if the column is not valid for this reader. * @return The integer value of the column or `0` if the column is `null`. */ - public fun getInt(column: TableColumn): Int = getInt(resolve(column)) + public fun getInt(name: String): Int = getInt(resolve(name)) /** - * Read the specified [column] as long. + * Read the column named [name] as long. * - * @param column The column to obtain the value for. + * @param name The name of the column to get the value for * @throws IllegalArgumentException if the column is not valid for this reader. * @return The long value of the column or `0` if the column is `null`. */ - public fun getLong(column: TableColumn): Long = getLong(resolve(column)) + public fun getLong(name: String): Long = getLong(resolve(name)) + + /** + * Read the column named [name] as float. + * + * @param name The name of the column to get the value for. + * @throws IllegalArgumentException if the column is not valid for this reader. + * @return The float value of the column or [Float.NaN] if the column is `null`. + */ + public fun getFloat(name: String): Float = getFloat(resolve(name)) /** - * Read the specified [column] as double. + * Read the column named [name] as double. * - * @param column The column to obtain the value for. + * @param name The name of the column to get the value for. * @throws IllegalArgumentException if the column is not valid for this reader. * @return The double value of the column or [Double.NaN] if the column is `null`. */ - public fun getDouble(column: TableColumn): Double = getDouble(resolve(column)) + public fun getDouble(name: String): Double = getDouble(resolve(name)) + + /** + * Read the column named [name] as [String]. + * + * @param name The name of the column to get the value for. + * @throws IllegalArgumentException if the column is not valid for this reader. + * @return The [String] value of the column or `null` if the column is `null`. + */ + public fun getString(name: String): String? = getString(resolve(name)) + + /** + * Read the column named [name] as [UUID]. + * + * @param name The name of the column to get the value for. + * @throws IllegalArgumentException if the column is not valid for this reader. + * @return The [UUID] value of the column or `null` if the column is `null`. + */ + public fun getUUID(name: String): UUID? = getUUID(resolve(name)) + + /** + * Read the column named [name] as [Instant]. + * + * @param name The name of the column to get the value for. + * @throws IllegalArgumentException if the column is not valid for this reader. + * @return The [Instant] value of the column or `null` if the column is `null`. + */ + public fun getInstant(name: String): Instant? = getInstant(resolve(name)) + + /** + * Read the column named [name] as [Duration]. + * + * @param name The name of the column to get the value for. + * @throws IllegalArgumentException if the column is not valid for this reader. + * @return The [Duration] value of the column or `null` if the column is `null`. + */ + public fun getDuration(name: String): Duration? = getDuration(resolve(name)) + + /** + * Obtain the value of the column named [name] as [List]. + * + * @param name The name of the column to get the value for. + * @param elementType Class representing the Java data type to convert elements of the designated column to. + * @throws IllegalArgumentException if the column index is not valid for this reader or this type. + * @return The value of the column as `List` or `null` if the column is null. + */ + public fun getList(name: String, elementType: Class): List? = getList(resolve(name), elementType) + + /** + * Obtain the value of the column named [name] as [Set]. + * + * @param name The name of the column to get the value for. + * @param elementType Class representing the Java data type to convert elements of the designated column to. + * @throws IllegalArgumentException if the column index is not valid for this reader or this type. + * @return The value of the column as `Set` or `null` if the column is null. + */ + public fun getSet(name: String, elementType: Class): Set? = getSet(resolve(name), elementType) + + /** + * Obtain the value of the column named [name] as [Set]. + * + * @param name The name of the column to get the value for. + * @param keyType Class representing the Java data type to convert the keys of the designated column to. + * @param valueType Class representing the Java data type to convert the values of the designated column to. + * @throws IllegalArgumentException if the column index is not valid for this reader or this type. + * @return The value of the column as `Map` or `null` if the column is null. + */ + public fun getMap(name: String, keyType: Class, valueType: Class): Map? = + getMap(resolve(name), keyType, valueType) /** * Closes the reader so that no further iteration or data access can be made. -- cgit v1.2.3