From 11606d03ad4a701ee31984eae57394709671ea1b Mon Sep 17 00:00:00 2001 From: faberf Date: Mon, 14 Oct 2024 23:19:09 +0200 Subject: [PATCH] decompose function into two --- .../source/exif/ExifMetadataExtractor.kt | 126 +++++++++--------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataExtractor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataExtractor.kt index 8ece78c2..b5c51bc5 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataExtractor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataExtractor.kt @@ -26,7 +26,6 @@ val logger: KLogger = KotlinLogging.logger {} private val NON_ALPHANUMERIC_REGEX = Regex("[^a-zA-Z0-9]") - private val DATE_FORMAT_PATTERNS = listOf( "yyyy:MM:dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss", @@ -45,65 +44,57 @@ private fun convertDate(date: String): Date? { return null } - -private fun convertType(directory: Directory, tagType: Int, type: Type): Value<*>? = when (type) { - Type.Boolean -> Value.Boolean(directory.getBoolean(tagType)) - Type.Byte -> Value.Byte(directory.getObject(tagType) as Byte) - Type.Datetime -> convertDate(directory.getString(tagType))?.let { Value.DateTime(it) } - Type.Double -> Value.Double(directory.getDouble(tagType)) - Type.Float -> Value.Float(directory.getFloat(tagType)) - Type.Int -> Value.Int(directory.getInt(tagType)) - Type.Long -> Value.Long(directory.getLong(tagType)) - Type.Short -> Value.Short(directory.getObject(tagType) as Short) - Type.String -> Value.String(directory.getString(tagType)) - Type.Text -> Value.String(directory.getString(tagType)) - Type.UUID -> Value.UUIDValue(UUID.fromString(directory.getString(tagType))) - is Type.BooleanVector -> throw IllegalArgumentException("Unsupported type: $type") - is Type.DoubleVector -> throw IllegalArgumentException("Unsupported type: $type") - is Type.FloatVector -> throw IllegalArgumentException("Unsupported type: $type") - is Type.IntVector -> throw IllegalArgumentException("Unsupported type: $type") - is Type.LongVector -> throw IllegalArgumentException("Unsupported type: $type") -} - -private fun JsonElement.convertType(type: Type): Value<*>? { +fun JsonElement.toValue(): Value<*>? { return when (this) { is JsonPrimitive -> { - if (this.isString) { - when (type) { - Type.String -> Value.String(this.content) - Type.Text -> Value.String(this.content) - Type.Datetime -> convertDate(this.content)?.let { Value.DateTime(it) } - else -> null - } - } else { - when (type) { - Type.Boolean -> this.booleanOrNull?.let { Value.Boolean(it) } - Type.Byte -> this.intOrNull?.let { Value.Byte(it.toByte()) } - Type.Short -> this.intOrNull?.let { Value.Short(it.toShort()) } - Type.Int -> this.intOrNull?.let { Value.Int(it) } - Type.Long -> this.longOrNull?.let { Value.Long(it) } - Type.Float -> this.floatOrNull?.let { Value.Float(it) } - Type.Double -> this.doubleOrNull?.let { Value.Double(it) } - else -> null - } - } - } - is JsonObject, is JsonArray -> { - when (type) { - Type.Text -> Value.String(this.toString()) - Type.String -> Value.String(this.toString()) - Type.UUID -> Value.UUIDValue(UUID.fromString(this.toString())) - else -> throw IllegalArgumentException("Cannot convert non-primitive JsonElement to type $type") + when { + this.booleanOrNull != null -> Value.Boolean(this.boolean) + this.intOrNull != null -> Value.Int(this.int) + this.longOrNull != null -> Value.Long(this.long) + this.floatOrNull != null -> Value.Float(this.float) + this.doubleOrNull != null -> Value.Double(this.double) + this.isString -> Value.String(this.content) // Only isString exists + else -> null } } - else -> { - throw IllegalStateException("Unsupported JsonElement type") - } + is JsonArray, is JsonObject -> Value.String(this.toString()) + else -> null } } -class ExifMetadataExtractor(input: Operator, analyser: ExifMetadata, field: Schema.Field, AnyMapStructDescriptor>?, parameters: Map) : AbstractExtractor, AnyMapStructDescriptor>(input, analyser, field, parameters) { +fun Value<*>.convertToType(type: Type): Value<*>? { + return when (type) { + Type.Boolean -> if (this is Value.Boolean) this else null + Type.Byte -> if (this is Value.Int) Value.Byte(this.value.toByte()) else null + Type.Short -> if (this is Value.Int) Value.Short(this.value.toShort()) else null + Type.Int -> if (this is Value.Int) this else null + Type.Long -> if (this is Value.Long) this else null + Type.Float -> if (this is Value.Float) this else null + Type.Double -> if (this is Value.Double) this else null + Type.String -> if (this is Value.String) this else null + + Type.Text -> if (this is Value.String) { + Value.Text(this.value) + } else null + + Type.Datetime -> if (this is Value.String) { + convertDate(this.value)?.let { Value.DateTime(it) } + } else null + + Type.UUID -> if (this is Value.String) { + Value.UUIDValue(UUID.fromString(this.value)) + } else null + + else -> null + } +} +class ExifMetadataExtractor( + input: Operator, + analyser: ExifMetadata, + field: Schema.Field, AnyMapStructDescriptor>?, + parameters: Map +) : AbstractExtractor, AnyMapStructDescriptor>(input, analyser, field, parameters) { override fun matches(retrievable: Retrievable): Boolean = retrievable.filteredAttribute(SourceAttribute::class.java)?.source is FileSource @@ -113,22 +104,23 @@ class ExifMetadataExtractor(input: Operator, analyser: ExifMetadata val columnValues = mutableMapOf>() val attributes = this.field?.parameters?.map { (k, v) -> k to Attribute(k, Type.valueOf(v)) }?.toMap() ?: emptyMap() + for (directory in metadata.directories) { for (tag in directory.tags) { val tagname = tag.tagName.replace(NON_ALPHANUMERIC_REGEX, "") val fullname = "${directory.name.replace(NON_ALPHANUMERIC_REGEX, "")}_$tagname" if (fullname == "ExifSubIFD_UserComment" || fullname == "JpegComment_JPEGComment") { - if (fullname in attributes){ + if (fullname in attributes) { columnValues[fullname] = Value.String(tag.description) } try { - val json = Json.parseToJsonElement(tag.description).jsonObject - json.forEach { (key, value) -> - attributes[key]?.let { attribute -> - value.convertType(attribute.type)?.let { converted -> - columnValues[key] = converted - } + val jsonElement = Json.parseToJsonElement(tag.description) + val jsonValue = jsonElement.toValue() + val attribute = attributes[fullname] + if (attribute != null && jsonValue != null) { + jsonValue.convertToType(attribute.type)?.let { converted -> + columnValues[fullname] = converted } } } catch (e: SerializationException) { @@ -140,7 +132,6 @@ class ExifMetadataExtractor(input: Operator, analyser: ExifMetadata columnValues[fullname] = converted } } - } } } @@ -149,3 +140,18 @@ class ExifMetadataExtractor(input: Operator, analyser: ExifMetadata return listOf(AnyMapStructDescriptor(UUID.randomUUID(), retrievable.id, attributes.values.toList(), columnValues.mapValues { it.value }, field = this.field)) } } + +private fun convertType(directory: Directory, tagType: Int, type: Type): Value<*>? = when (type) { + Type.Boolean -> Value.Boolean(directory.getBoolean(tagType)) + Type.Byte -> Value.Byte(directory.getObject(tagType) as Byte) + Type.Datetime -> convertDate(directory.getString(tagType))?.let { Value.DateTime(it) } + Type.Double -> Value.Double(directory.getDouble(tagType)) + Type.Float -> Value.Float(directory.getFloat(tagType)) + Type.Int -> Value.Int(directory.getInt(tagType)) + Type.Long -> Value.Long(directory.getLong(tagType)) + Type.Short -> Value.Short(directory.getObject(tagType) as Short) + Type.String -> Value.String(directory.getString(tagType)) + Type.Text -> Value.Text(directory.getString(tagType)) // Ensure Type.Text returns Value.Text + Type.UUID -> Value.UUIDValue(UUID.fromString(directory.getString(tagType))) + is Type.BooleanVector, is Type.DoubleVector, is Type.FloatVector, is Type.IntVector, is Type.LongVector -> throw IllegalArgumentException("Unsupported type: $type") +}