From 7c4d69ec1b2f8f4f48f97428b7aa10c2727f7f25 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 9 Dec 2020 12:04:10 +0300 Subject: [PATCH] Refactor Value. --- CHANGELOG.md | 2 + .../kotlin/hep/dataforge/provider/Provider.kt | 2 +- .../io/yaml/FrontMatterEnvelopeFormat.kt | 1 + .../hep/dataforge/io/BinaryMetaFormat.kt | 79 +++++++++-------- .../kotlin/hep/dataforge/io/Envelope.kt | 4 +- .../hep/dataforge/io/EnvelopeFormatTest.kt | 2 +- .../kotlin/hep/dataforge/io/MetaFormatTest.kt | 1 + dataforge-meta/api/dataforge-meta.api | 32 ++----- .../kotlin/hep/dataforge/meta/JsonMeta.kt | 18 ++-- .../kotlin/hep/dataforge/meta/Meta.kt | 7 +- .../hep/dataforge/meta/MutableItemDelegate.kt | 8 +- .../kotlin/hep/dataforge/values/Value.kt | 86 ++++++++----------- .../hep/dataforge/values/ValueSerializer.kt | 2 + .../hep/dataforge/values/exoticValues.kt | 7 +- .../hep/dataforge/values/valueExtensions.kt | 5 +- .../hep/dataforge/meta/DynamicMetaTest.kt | 1 + .../hep/dataforge/tables/ColumnHeader.kt | 1 + .../hep/dataforge/tables/io/TextRows.kt | 4 +- .../hep/dataforge/tables/io/TextRowsTest.kt | 1 + .../hep/dataforge/workspace/fileData.kt | 6 +- 20 files changed, 117 insertions(+), 152 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e83f215..fc102680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - Yaml meta format based on yaml.kt - `Path` builders +- Special ValueType for lists ### Changed - `ListValue` and `DoubleArrayValue` implement `Iterable`. @@ -11,6 +12,7 @@ - `Meta{}` builder made inline - Moved `Envelope` builder to a top level function. Companion invoke is deprecated. - Context logging moved to the extension +- `number` and `string` methods on `Value` moved to extensions (breaking change) ### Deprecated diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt index 3a153d86..8d3ae30d 100644 --- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt +++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt @@ -84,6 +84,6 @@ public fun Provider.top(target: String, type: KClass): Map Provider.top(target: String): Map = top(target, T::class) +public inline fun Provider.top(target: String ): Map = top(target, T::class) diff --git a/dataforge-io/dataforge-io-yaml/src/jvmMain/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/jvmMain/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt index 56a01d92..5abcec3f 100644 --- a/dataforge-io/dataforge-io-yaml/src/jvmMain/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt +++ b/dataforge-io/dataforge-io-yaml/src/jvmMain/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt @@ -17,6 +17,7 @@ public class FrontMatterEnvelopeFormat( ) : EnvelopeFormat { override fun readPartial(input: Input): PartialEnvelope { + @Suppress("VARIABLE_WITH_REDUNDANT_INITIALIZER") var line = "" var offset = 0u do { diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt index 547d567c..ab6f94bb 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt @@ -32,57 +32,56 @@ public object BinaryMetaFormat : MetaFormat, MetaFormatFactory { writeUtf8String(str) } - public fun Output.writeValue(value: Value) { - if (value.isList()) { + public fun Output.writeValue(value: Value): Unit = when (value.type) { + ValueType.NUMBER -> when (value.value) { + is Short -> { + writeChar('s') + writeShort(value.short) + } + is Int -> { + writeChar('i') + writeInt(value.int) + } + is Long -> { + writeChar('l') + writeLong(value.long) + } + is Float -> { + writeChar('f') + writeFloat(value.float) + } + else -> { + writeChar('d') + writeDouble(value.double) + } + } + ValueType.STRING -> { + writeChar('S') + writeString(value.string) + } + ValueType.BOOLEAN -> { + if (value.boolean) { + writeChar('+') + } else { + writeChar('-') + } + } + ValueType.NULL -> { + writeChar('N') + } + ValueType.LIST -> { writeChar('L') writeInt(value.list.size) value.list.forEach { writeValue(it) } - } else when (value.type) { - ValueType.NUMBER -> when (value.value) { - is Short -> { - writeChar('s') - writeShort(value.number.toShort()) - } - is Int -> { - writeChar('i') - writeInt(value.number.toInt()) - } - is Long -> { - writeChar('l') - writeLong(value.number.toLong()) - } - is Float -> { - writeChar('f') - writeFloat(value.number.toFloat()) - } - else -> { - writeChar('d') - writeDouble(value.number.toDouble()) - } - } - ValueType.STRING -> { - writeChar('S') - writeString(value.string) - } - ValueType.BOOLEAN -> { - if (value.boolean) { - writeChar('+') - } else { - writeChar('-') - } - } - ValueType.NULL -> { - writeChar('N') - } } } override fun writeMeta( output: kotlinx.io.Output, meta: hep.dataforge.meta.Meta, - descriptor: hep.dataforge.meta.descriptors.NodeDescriptor? + descriptor: hep.dataforge.meta.descriptors.NodeDescriptor?, ) { output.writeChar('M') output.writeInt(meta.items.size) diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt index d938fe5a..123da62c 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt @@ -29,9 +29,7 @@ public interface Envelope { /** * Build a static envelope using provided builder */ - @Deprecated("Use top level function instead", - replaceWith = ReplaceWith("Envelope(block)", "hep.dataforge.io.Envelope") - ) + @Deprecated("Use top level function instead") public inline operator fun invoke(block: EnvelopeBuilder.() -> Unit): Envelope = EnvelopeBuilder().apply(block).seal() } diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt index 8bcc54cd..2ce87c19 100644 --- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt +++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt @@ -7,7 +7,7 @@ import kotlin.test.assertEquals class EnvelopeFormatTest { - val envelope = Envelope.invoke { + val envelope = Envelope { type = "test.format" meta{ "d" put 22.2 diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt index cb8ba54b..af33cfde 100644 --- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt +++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt @@ -2,6 +2,7 @@ package hep.dataforge.io import hep.dataforge.meta.* import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY +import hep.dataforge.values.number import kotlinx.io.asBinary import kotlinx.serialization.json.* import kotlin.test.Test diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index 4100ccb7..76de2263 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -817,9 +817,6 @@ public final class hep/dataforge/values/DoubleArrayValue : hep/dataforge/values/ public fun ([D)V public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Double; - public synthetic fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public synthetic fun getValue ()Ljava/lang/Object; public fun getValue ()[D @@ -832,8 +829,6 @@ public final class hep/dataforge/values/EnumValue : hep/dataforge/values/Value { public fun (Ljava/lang/Enum;)V public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Enum; public synthetic fun getValue ()Ljava/lang/Object; @@ -850,8 +845,6 @@ public final class hep/dataforge/values/False : hep/dataforge/values/Value { public static final field INSTANCE Lhep/dataforge/values/False; public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Object; public fun hashCode ()I @@ -862,8 +855,7 @@ public final class hep/dataforge/values/LazyParsedValue : hep/dataforge/values/V public fun (Ljava/lang/String;)V public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; + public final fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Object; public fun hashCode ()I @@ -874,8 +866,6 @@ public final class hep/dataforge/values/ListValue : hep/dataforge/values/Value, public fun (Ljava/util/List;)V public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public synthetic fun getValue ()Ljava/lang/Object; public fun getValue ()Ljava/util/List; @@ -888,8 +878,6 @@ public final class hep/dataforge/values/Null : hep/dataforge/values/Value { public static final field INSTANCE Lhep/dataforge/values/Null; public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Object; public fun hashCode ()I @@ -900,8 +888,7 @@ public final class hep/dataforge/values/NumberValue : hep/dataforge/values/Value public fun (Ljava/lang/Number;)V public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; + public final fun getNumber ()Ljava/lang/Number; public fun getType ()Lhep/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Object; public fun hashCode ()I @@ -912,8 +899,7 @@ public final class hep/dataforge/values/StringValue : hep/dataforge/values/Value public fun (Ljava/lang/String;)V public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; + public final fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Object; public fun hashCode ()I @@ -924,8 +910,6 @@ public final class hep/dataforge/values/True : hep/dataforge/values/Value { public static final field INSTANCE Lhep/dataforge/values/True; public fun equals (Ljava/lang/Object;)Z public fun getList ()Ljava/util/List; - public fun getNumber ()Ljava/lang/Number; - public fun getString ()Ljava/lang/String; public fun getType ()Lhep/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Object; public fun hashCode ()I @@ -934,18 +918,16 @@ public final class hep/dataforge/values/True : hep/dataforge/values/Value { public abstract interface class hep/dataforge/values/Value { public static final field Companion Lhep/dataforge/values/Value$Companion; - public static final field TARGET Ljava/lang/String; + public static final field TYPE Ljava/lang/String; public abstract fun equals (Ljava/lang/Object;)Z public abstract fun getList ()Ljava/util/List; - public abstract fun getNumber ()Ljava/lang/Number; - public abstract fun getString ()Ljava/lang/String; public abstract fun getType ()Lhep/dataforge/values/ValueType; public abstract fun getValue ()Ljava/lang/Object; public abstract fun hashCode ()I } public final class hep/dataforge/values/Value$Companion { - public static final field TARGET Ljava/lang/String; + public static final field TYPE Ljava/lang/String; public final fun of (Ljava/lang/Object;)Lhep/dataforge/values/Value; } @@ -978,6 +960,9 @@ public final class hep/dataforge/values/ValueKt { public static final fun asValue ([I)Lhep/dataforge/values/Value; public static final fun asValue ([J)Lhep/dataforge/values/Value; public static final fun asValue ([S)Lhep/dataforge/values/Value; + public static final fun getNumber (Lhep/dataforge/values/Value;)Ljava/lang/Number; + public static final fun getNumberOrNull (Lhep/dataforge/values/Value;)Ljava/lang/Number; + public static final fun getString (Lhep/dataforge/values/Value;)Ljava/lang/String; public static final fun parseValue (Ljava/lang/String;)Lhep/dataforge/values/Value; } @@ -993,6 +978,7 @@ public final class hep/dataforge/values/ValueSerializer : kotlinx/serialization/ public final class hep/dataforge/values/ValueType : java/lang/Enum { public static final field BOOLEAN Lhep/dataforge/values/ValueType; public static final field Companion Lhep/dataforge/values/ValueType$Companion; + public static final field LIST Lhep/dataforge/values/ValueType; public static final field NULL Lhep/dataforge/values/ValueType; public static final field NUMBER Lhep/dataforge/values/ValueType; public static final field STRING Lhep/dataforge/values/ValueType; diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt index 2cabc8f1..6dcfe76a 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt @@ -16,20 +16,16 @@ import kotlinx.serialization.json.* /** * @param descriptor reserved for custom serialization in future */ -public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement { - return if (isList()) { - JsonArray(list.map { it.toJson() }) - } else { - when (type) { - ValueType.NUMBER -> JsonPrimitive(number) - ValueType.STRING -> JsonPrimitive(string) - ValueType.BOOLEAN -> JsonPrimitive(boolean) - ValueType.NULL -> JsonNull - } - } +public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement = when (type) { + ValueType.NUMBER -> JsonPrimitive(numberOrNull) + ValueType.STRING -> JsonPrimitive(string) + ValueType.BOOLEAN -> JsonPrimitive(boolean) + ValueType.LIST -> JsonArray(list.map { it.toJson() }) + ValueType.NULL -> JsonNull } //Use these methods to customize JSON key mapping +@Suppress("NULLABLE_EXTENSION_OPERATOR_WITH_SAFE_CALL_RECEIVER") private fun String.toJsonKey(descriptor: ItemDescriptor?) = descriptor?.attributes["jsonName"].string ?: toString() //private fun NodeDescriptor?.getDescriptor(key: String) = this?.items?.get(key) diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt index c8ed6755..fb014593 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt @@ -4,10 +4,7 @@ import hep.dataforge.meta.Meta.Companion.VALUE_KEY import hep.dataforge.meta.MetaItem.NodeItem import hep.dataforge.meta.MetaItem.ValueItem import hep.dataforge.names.* -import hep.dataforge.values.EnumValue -import hep.dataforge.values.Null -import hep.dataforge.values.Value -import hep.dataforge.values.boolean +import hep.dataforge.values.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json @@ -245,7 +242,7 @@ public val MetaItem<*>?.value: Value? public val MetaItem<*>?.string: String? get() = value?.string public val MetaItem<*>?.boolean: Boolean? get() = value?.boolean -public val MetaItem<*>?.number: Number? get() = value?.number +public val MetaItem<*>?.number: Number? get() = value?.numberOrNull public val MetaItem<*>?.double: Double? get() = number?.toDouble() public val MetaItem<*>?.float: Float? get() = number?.toFloat() public val MetaItem<*>?.int: Int? get() = number?.toInt() diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt index 32a7c7d4..6e5cfc96 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt @@ -3,10 +3,7 @@ package hep.dataforge.meta import hep.dataforge.meta.transformations.MetaConverter import hep.dataforge.names.Name import hep.dataforge.names.asName -import hep.dataforge.values.DoubleArrayValue -import hep.dataforge.values.Value -import hep.dataforge.values.asValue -import hep.dataforge.values.doubleArray +import hep.dataforge.values.* import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -72,7 +69,6 @@ public fun MutableItemDelegate.convert( } - /* Read-write delegates for [MutableItemProvider] */ /** @@ -171,7 +167,7 @@ public fun MutableItemProvider.numberList( vararg default: Number, key: Name? = null, ): ReadWriteProperty> = item(key).convert( - reader = { it?.value?.list?.map { value -> value.number } ?: listOf(*default) }, + reader = { it?.value?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) }, writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() } ) diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt index c81651df..d3b08b1f 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt @@ -11,7 +11,7 @@ import kotlinx.serialization.Serializable */ @Serializable public enum class ValueType { - NUMBER, STRING, BOOLEAN, NULL + NUMBER, STRING, BOOLEAN, LIST, NULL } /** @@ -31,16 +31,6 @@ public interface Value { */ public val type: ValueType - /** - * get this value represented as Number - */ - public val number: Number - - /** - * get this value represented as String - */ - public val string: String - /** * get this value represented as List */ @@ -51,7 +41,7 @@ public interface Value { override fun hashCode(): Int public companion object { - public const val TARGET: String = "value" + public const val TYPE: String = "value" /** * Convert object to value @@ -86,16 +76,27 @@ public interface Value { } } +public val Value.string: String get() = toString() + +/** + * get this value represented as Number + */ +public val Value.numberOrNull: Number? + get() = if (this is NumberValue) number else string.toDoubleOrNull() + +/** + * Return [Value] number content or throw error if value is not a number + */ +public val Value.number: Number + get() = (if (this is NumberValue) number else numberOrNull ?: error("The value is not a number")) + /** * A singleton null value */ public object Null : Value { override val value: Any? get() = null override val type: ValueType get() = ValueType.NULL - override val number: Number get() = Double.NaN - override val string: String get() = "@null" - - override fun toString(): String = value.toString() + override fun toString(): String = "@null" override fun equals(other: Any?): Boolean = other === Null override fun hashCode(): Int = 0 @@ -107,9 +108,6 @@ public object Null : Value { public object True : Value { override val value: Any get() = true override val type: ValueType get() = ValueType.BOOLEAN - override val number: Number get() = 1.0 - override val string: String get() = "true" - override fun toString(): String = value.toString() override fun equals(other: Any?): Boolean = other === True @@ -122,42 +120,40 @@ public object True : Value { public object False : Value { override val value: Any get() = false override val type: ValueType get() = ValueType.BOOLEAN - override val number: Number get() = -1.0 - override val string: String get() = "false" - override fun toString(): String = value.toString() override fun equals(other: Any?): Boolean = other === False override fun hashCode(): Int = -1 } -public class NumberValue(override val number: Number) : Value { +public class NumberValue(public val number: Number) : Value { override val value: Any get() = number override val type: ValueType get() = ValueType.NUMBER - override val string: String get() = number.toString() + + override fun toString(): String = number.toString() override fun equals(other: Any?): Boolean { if (other !is Value) return false - return when (number) { - is Short -> number.toShort() == other.number.toShort() - is Long -> number.toLong() == other.number.toLong() - is Byte -> number.toByte() == other.number.toByte() - is Int -> number.toInt() == other.number.toInt() - is Float -> number.toFloat() == other.number.toFloat() - is Double -> number.toDouble() == other.number.toDouble() - else -> number.toString() == other.number.toString() + + val otherNumber = other.numberOrNull ?: return false + + return when (numberOrNull) { + is Short -> number.toShort() == otherNumber.toShort() + is Long -> number.toLong() == otherNumber.toLong() + is Byte -> number.toByte() == otherNumber.toByte() + is Int -> number.toInt() == otherNumber.toInt() + is Float -> number.toFloat() == otherNumber.toFloat() + is Double -> number.toDouble() == otherNumber.toDouble() + else -> number.toString() == otherNumber.toString() } } - override fun hashCode(): Int = number.hashCode() - - override fun toString(): String = value.toString() + override fun hashCode(): Int = numberOrNull.hashCode() } -public class StringValue(override val string: String) : Value { +public class StringValue(public val string: String) : Value { override val value: Any get() = string override val type: ValueType get() = ValueType.STRING - override val number: Number get() = string.toDouble() override fun equals(other: Any?): Boolean { return this.string == (other as? Value)?.string @@ -165,21 +161,19 @@ public class StringValue(override val string: String) : Value { override fun hashCode(): Int = string.hashCode() - override fun toString(): String = "\"${value.toString()}\"" + override fun toString(): String = string } public class EnumValue>(override val value: E) : Value { override val type: ValueType get() = ValueType.STRING - override val number: Number get() = value.ordinal - override val string: String get() = value.name + + override fun toString(): String = value.toString() override fun equals(other: Any?): Boolean { return string == (other as? Value)?.string } override fun hashCode(): Int = value.hashCode() - - override fun toString(): String = value.toString() } public class ListValue(override val list: List) : Value, Iterable { @@ -188,9 +182,7 @@ public class ListValue(override val list: List) : Value, Iterable } override val value: List get() = list - override val type: ValueType get() = list.first().type - override val number: Number get() = list.first().number - override val string: String get() = list.first().string + override val type: ValueType get() = ValueType.LIST override fun toString(): String = list.joinToString(prefix = "[", postfix = "]") @@ -200,7 +192,7 @@ public class ListValue(override val list: List) : Value, Iterable if (this === other) return true if (other !is Value) return false if (other is DoubleArrayValue) { - return DoubleArray(list.size) { list[it].number.toDouble() }.contentEquals(other.value) + return DoubleArray(list.size) { list[it].numberOrNull?.toDouble() ?: Double.NaN }.contentEquals(other.value) } return list == other.list } @@ -208,8 +200,6 @@ public class ListValue(override val list: List) : Value, Iterable override fun hashCode(): Int { return list.hashCode() } - - } public fun Number.asValue(): Value = NumberValue(this) diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt index 9dd15b7d..d46dd4be 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt @@ -24,6 +24,7 @@ public object ValueSerializer : KSerializer { ValueType.NUMBER -> decodeDouble().asValue() //TODO differentiate? ValueType.BOOLEAN -> decodeBoolean().asValue() ValueType.STRING -> decodeString().asValue() + ValueType.LIST -> decodeSerializableValue(ListSerializer(ValueSerializer)).asValue() } } @@ -45,6 +46,7 @@ public object ValueSerializer : KSerializer { ValueType.NUMBER -> encodeDouble(value.double) ValueType.BOOLEAN -> encodeBoolean(value.boolean) ValueType.STRING -> encodeString(value.string) + ValueType.LIST -> encodeSerializableValue(ListSerializer(ValueSerializer),value.list) } } diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt index d961b4a9..b04524dc 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt @@ -4,12 +4,11 @@ package hep.dataforge.values /** * A value built from string which content and type are parsed on-demand */ -public class LazyParsedValue(override val string: String) : Value { +public class LazyParsedValue(public val string: String) : Value { private val parsedValue by lazy { string.parseValue() } override val value: Any? get() = parsedValue.value override val type: ValueType get() = parsedValue.type - override val number: Number get() = parsedValue.number override fun toString(): String = string @@ -24,9 +23,7 @@ public fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this) * A performance optimized version of list value for doubles */ public class DoubleArrayValue(override val value: DoubleArray) : Value, Iterable { - override val type: ValueType get() = ValueType.NUMBER - override val number: Double get() = value.first() - override val string: String get() = value.first().toString() + override val type: ValueType get() = ValueType.LIST override val list: List get() = value.map { NumberValue(it) } override fun equals(other: Any?): Boolean { diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt index 50b15aed..9347642b 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt @@ -9,10 +9,9 @@ import hep.dataforge.meta.MetaBuilder public fun Value.isNull(): Boolean = this == Null /** - * Check if value is list. This method checks the type of the value, not the number of the elements. - * So it will return `true` for empty lists and lists of one elements. + * Check if value is list. */ -public fun Value.isList(): Boolean = this is Iterable<*> +public fun Value.isList(): Boolean = this.type == ValueType.LIST public val Value.boolean: Boolean get() = this == True diff --git a/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt b/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt index b546ae6d..a2dc2de9 100644 --- a/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt +++ b/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt @@ -19,6 +19,7 @@ class DynamicMetaTest { d.ob.booleanNode = true val meta = DynamicMeta(d) + println(meta) assertEquals(true, meta["ob.booleanNode"].boolean) assertEquals(2, meta["array"].value?.list?.get(1)?.int) assertEquals(4, meta.items.size) diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt index a226de26..4aeb3124 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt @@ -32,5 +32,6 @@ public val ColumnHeader.textWidth: Int ValueType.STRING -> 16 ValueType.BOOLEAN -> 5 ValueType.NULL -> 5 + ValueType.LIST -> 32 null -> 16 } diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt index 31f5baaa..e9e6e31e 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt @@ -111,8 +111,8 @@ public class TextTable( private fun Output.writeValue(value: Value, width: Int, left: Boolean = true) { require(width > 5) { "Width could not be less than 5" } val str: String = when (value.type) { - ValueType.NUMBER -> value.number.toString() //TODO apply decimal format - ValueType.STRING -> value.string.take(width) + ValueType.NUMBER -> value.numberOrNull.toString() //TODO apply decimal format + ValueType.STRING, ValueType.LIST -> value.string.take(width) ValueType.BOOLEAN -> if (value.boolean) { "true" } else { diff --git a/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt b/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt index 02d97caf..d97484ed 100644 --- a/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt +++ b/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt @@ -6,6 +6,7 @@ import hep.dataforge.tables.get import hep.dataforge.tables.row import hep.dataforge.values.Value import hep.dataforge.values.int +import hep.dataforge.values.string import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking import kotlinx.io.ExperimentalIoApi diff --git a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt index 97ae77e6..8dfcc63d 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt @@ -16,9 +16,7 @@ import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream import kotlin.reflect.KClass -typealias FileFormatResolver = (Path, Meta) -> IOFormat - - +public typealias FileFormatResolver = (Path, Meta) -> IOFormat private fun newZFS(path: Path): FileSystem { val fsProvider = FileSystemProvider.installedProviders().find { it.scheme == "jar" } @@ -84,7 +82,7 @@ public fun DataTreeBuilder.file( * Read the directory as a data node. If [path] is a zip archive, read it as directory */ @DFExperimental -fun IOPlugin.readDataDirectory( +public fun IOPlugin.readDataDirectory( path: Path, type: KClass, formatResolver: FileFormatResolver