diff --git a/example-configs/ingestion/example/image.json b/example-configs/ingestion/example/image.json index 326a939b7..c100364b3 100644 --- a/example-configs/ingestion/example/image.json +++ b/example-configs/ingestion/example/image.json @@ -1,7 +1,6 @@ { - "schemas": [ - { - "name": "example", + "schemas": { + "example": { "connection": { "database": "CottontailConnectionProvider", "parameters": { @@ -9,58 +8,50 @@ "port": "1865" } }, - "fields": [ - { - "name": "averagecolor", + "fields": { + "averagecolor": { "factory": "AverageColor" }, - { - "name": "file", + "file": { "factory": "FileSourceMetadata" }, - { - "name": "clip", + "clip": { "factory": "DenseEmbedding", "parameters": { "host": "http://127.0.0.1:8888", "model": "open-clip-vit-b32", - "length":"512" + "length": "512" } }, - { - "name": "dino", + "dino": { "factory": "DenseEmbedding", "parameters": { "host": "http://127.0.0.1:8888/", "model": "dino-v2-vits14", - "length":"384" + "length": "384" } }, - { - "name": "whisper", + "whisper": { "factory": "ASR", "parameters": { "host": "http://127.0.0.1:8888/", "model": "whisper" } }, - { - "name": "ocr", + "ocr": { "factory": "OCR", "parameters": { "host": "http://127.0.0.1:8888/", "model": "tesseract" } }, - { - "name": "time", + "time": { "factory": "TemporalMetadata" }, - { - "name": "video", + "video": { "factory": "VideoSourceMetadata" - }, - ], + } + }, "resolvers": { "disk": { "factory": "DiskResolver", @@ -69,9 +60,8 @@ } } }, - "exporters": [ - { - "name": "thumbnail", + "exporters": { + "thumbnail": { "factory": "ThumbnailExporter", "resolverName": "disk", "parameters": { @@ -79,8 +69,8 @@ "mimeType": "JPG" } } - ], - "extractionPipelines": [] + }, + "extractionPipelines": {} } - ] + } } diff --git a/example-configs/schema/dense.json b/example-configs/schema/dense.json index d77bc4dac..1acc27c67 100644 --- a/example-configs/schema/dense.json +++ b/example-configs/schema/dense.json @@ -1,7 +1,6 @@ { - "schemas": [ - { - "name": "dense", + "schemas": { + "dense": { "connection": { "database": "PgVectorConnectionProvider", "parameters": { @@ -11,113 +10,100 @@ "password": "admin" } }, - "fields": [ - { - "name": "averagecolor", + "fields": { + "averagecolor": { "factory": "AverageColor" }, - { - "name": "file", + "file": { "factory": "FileSourceMetadata" }, - { - "name": "time", + "time": { "factory": "TemporalMetadata" }, - { - "name": "video", + "video": { "factory": "VideoSourceMetadata" }, - { - "name": "asrSparse", + "asrSparse": { "factory": "ASR", "parameters": { "host": "http://10.34.64.84:8888/", "model": "whisper", "timeoutSeconds": "100", - "retries":"1000" + "retries": "1000" } }, - { - "name": "asrDense", + "asrDense": { "factory": "DenseEmbedding", "parameters": { "host": "http://10.34.64.84:8888/", "model": "e5mistral7b-instruct", "length": "4096", "timeoutSeconds": "100", - "retries":"1000" + "retries": "1000" } }, - { - "name": "clip", + "clip": { "factory": "DenseEmbedding", "parameters": { "host": "http://10.34.64.84:8888/", "model": "open-clip-vit-b32", "length": "512", "timeoutSeconds": "100", - "retries":"1000" + "retries": "1000" } }, - - { - "name": "documentType", + "documentType": { "factory": "ImageClassification", "parameters": { "host": "http://10.34.64.84:8888/", "model": "open-clip-vit-b32", "timeoutSeconds": "100", - "retries":"1000", + "retries": "1000", "classes": "text document,photograph", "threshold": "0.1", "top_k": "1" } }, - { - "name": "captionSparse", + "captionSparse": { "factory": "ImageCaption", "parameters": { "host": "http://10.34.64.84:8888/", "timeoutSeconds": "100", - "retries":"1000", + "retries": "1000", "model": "gpt4o", "prompt": "Describe the contents of this image to help document the image and to aid archivists in searching for the image. Use information from the internet to enhance the description. The image is part of the PTT Archive which preserves the history (1848-1997) of Swiss Post, Telegraphy and Telephony (PTT)." } }, - { - "name": "captionDense", + "captionDense": { "factory": "DenseEmbedding", "parameters": { "host": "http://10.34.64.84:8888/", "model": "e5mistral7b-instruct", "length": "4096", "timeoutSeconds": "100", - "retries":"1000" + "retries": "1000" } }, - { - "name": "ocrSparse", + "ocrSparse": { "factory": "OCR", "parameters": { "host": "http://10.34.64.84:8888/", "model": "tesseract", "timeoutSeconds": "100", - "retries":"1000" + "retries": "1000" } }, - { - "name": "ocrDense", + "ocrDense": { "factory": "DenseEmbedding", "parameters": { "host": "http://10.34.64.84:8888/", "model": "e5mistral7b-instruct", "length": "4096", "timeoutSeconds": "100", - "retries":"1000" + "retries": "1000" } } - ], + }, "resolvers": { "disk": { "factory": "DiskResolver", @@ -126,9 +112,8 @@ } } }, - "exporters": [ - { - "name": "thumbnail", + "exporters": { + "thumbnail": { "factory": "ThumbnailExporter", "resolverName": "disk", "parameters": { @@ -136,13 +121,12 @@ "mimeType": "JPG" } } - ], - "extractionPipelines": [ - { - "name": "wit1", + }, + "extractionPipelines": { + "wit1": { "path": "./pipelines/wit1.json" } - ] + } } - ] + } } diff --git a/example-configs/schema/example.json b/example-configs/schema/example.json index bc1ab23ae..c23fff8cc 100644 --- a/example-configs/schema/example.json +++ b/example-configs/schema/example.json @@ -1,7 +1,6 @@ { - "schemas": [ - { - "name": "example", + "schemas": { + "example": { "connection": { "database": "CottontailConnectionProvider", "parameters": { @@ -9,58 +8,50 @@ "port": "1865" } }, - "fields": [ - { - "name": "averagecolor", + "fields": { + "averagecolor": { "factory": "AverageColor" }, - { - "name": "file", + "file": { "factory": "FileSourceMetadata" }, - { - "name": "clip", + "clip": { "factory": "DenseEmbedding", "parameters": { "host": "http://127.0.0.1:8888", "model": "open-clip-vit-b32", - "length":"512" + "length": "512" } }, - { - "name": "dino", + "dino": { "factory": "DenseEmbedding", "parameters": { "host": "http://127.0.0.1:8888/", "model": "dino-v2-vits14", - "length":"384" + "length": "384" } }, - { - "name": "whisper", + "whisper": { "factory": "ASR", "parameters": { "host": "http://127.0.0.1:8888/", "model": "whisper" } }, - { - "name": "ocr", + "ocr": { "factory": "OCR", "parameters": { "host": "http://127.0.0.1:8888/", "model": "tesseract" } }, - { - "name": "time", + "time": { "factory": "TemporalMetadata" }, - { - "name": "video", + "video": { "factory": "VideoSourceMetadata" - }, - ], + } + }, "resolvers": { "disk": { "factory": "DiskResolver", @@ -69,9 +60,8 @@ } } }, - "exporters": [ - { - "name": "thumbnail", + "exporters": { + "thumbnail": { "factory": "ThumbnailExporter", "resolverName": "disk", "parameters": { @@ -79,17 +69,15 @@ "mimeType": "JPG" } } - ], - "extractionPipelines": [ - { - "name": "video", + }, + "extractionPipelines": { + "video": { "path": "./example/video.json" }, - { - "name": "image", + "image": { "path": "./example/image.json" } - ] + } } - ] + } } diff --git a/example-configs/schema/metadata.json b/example-configs/schema/metadata.json index 2bfc0a67a..1fd27f2d6 100644 --- a/example-configs/schema/metadata.json +++ b/example-configs/schema/metadata.json @@ -1,7 +1,6 @@ { - "schemas": [ - { - "name": "metadata", + "schemas": { + "metadata": { "connection": { "database": "CottontailConnectionProvider", "parameters": { @@ -9,17 +8,14 @@ "port": "1865" } }, - "fields": [ - { - "name": "file", + "fields": { + "file": { "factory": "FileSourceMetadata" }, - { - "name": "time", + "time": { "factory": "TemporalMetadata" }, - { - "name": "exif", + "exif": { "factory": "ExifMetadata", "parameters": { "ExifSubIFD_FocalLength": "INT", @@ -29,15 +25,15 @@ "time_zone": "STRING" } } - ], - "resolvers": { - "disk": { - "factory": "DiskResolver", - "parameters": { - "location": "./thumbnails/vitrivr" - } - } + }, + "resolvers": { + "disk": { + "factory": "DiskResolver", + "parameters": { + "location": "./thumbnails/vitrivr" + } } + } } - ] + } } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 621647862..e2de8b7ea 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,4 +13,3 @@ include 'vitrivr-engine-module-pgvector' include 'vitrivr-engine-module-features' include 'vitrivr-engine-module-m3d' include 'vitrivr-engine-module-fes' -include 'vitrivr-engine-module-statistics' diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilder.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilder.kt index a786bd5ff..dbb34f6c7 100755 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilder.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilder.kt @@ -55,8 +55,10 @@ class IngestionPipelineBuilder(val config: IngestionConfig) { @Suppress("UNCHECKED_CAST") fun build(stream: Stream<*>? = null): List> { return parseOperations().map { root -> + val config = root.opConfig as? OperatorConfig.Enumerator ?: throw IllegalArgumentException("Root stage must always be an enumerator!") val built = HashMap>() + root.opName ?: throw IllegalArgumentException("Root stage cannot be passthrough!") built[root.name] = buildEnumerator(root.opName, config, stream) for (output in root.output) { @@ -82,7 +84,7 @@ class IngestionPipelineBuilder(val config: IngestionConfig) { /** * This is an internal function that can be called recursively to build the [Operator] DAG. * - * @param operation The [Operation] to build. + * @param operation The [BaseOperation] to build. * @param memoizationTable The memoization table that holds the already built operators. * @return The built [Operator]. */ @@ -107,11 +109,21 @@ class IngestionPipelineBuilder(val config: IngestionConfig) { } /* Prepare and cache operator. */ - var operator = buildOperator(operation.opName, op, operation.opConfig) - if (operation.output.size > 1) { - operator = BroadcastOperator(operator) + if (operation.opName != null && operation.opConfig != null) { + val operator = buildOperator(operation.opName, op, operation.opConfig) + if (operation.output.size > 1) { + memoizationTable[operation.name] = BroadcastOperator(operator) + } else { + memoizationTable[operation.name] = operator + } + } else { + if (operation.output.size > 1) { + memoizationTable[operation.name] = BroadcastOperator(op) + } else { + memoizationTable[operation.name] = op + } } - memoizationTable[operation.name] = operator + /* Process output operators. */ for (output in operation.output) { @@ -134,16 +146,28 @@ class IngestionPipelineBuilder(val config: IngestionConfig) { /* Build trees with entry points as roots. */ return entrypoints.map { val stages = HashMap() - val root = Operation(it.key, it.value.operator, config.operators[it.value.operator] ?: throw IllegalArgumentException("Undefined operator '${it.value.operator}'"), it.value.merge) + it.value.operator ?: throw IllegalArgumentException("Entrypoints must have an operator!") + val root = Operation(it.key, it.value.operator!!, config.operators[it.value.operator] ?: throw IllegalArgumentException("Undefined operator '${it.value.operator}'"), it.value.merge) stages[it.key] = root for (operation in this.config.operations) { if (!stages.containsKey(operation.key)) { - stages[operation.key] = Operation(operation.key, operation.value.operator, config.operators[operation.value.operator] ?: throw IllegalArgumentException("Undefined operator '${operation.value.operator}'"), operation.value.merge) + when(operation.value.operator) { + is String -> + stages[operation.key] = Operation( + name = operation.key, + opName = operation.value.operator!!, + opConfig = config.operators[operation.value.operator!!] ?: throw IllegalArgumentException("Undefined operator '${operation.value.operator}'"), + merge = operation.value.merge + ) + + null -> + stages[operation.key] = Operation(name = operation.key, opName = null, opConfig = null, merge = operation.value.merge) + } } for (inputKey in operation.value.inputs) { if (!stages.containsKey(inputKey)) { val op = this.config.operations[inputKey] ?: throw IllegalArgumentException("Undefined operation '${inputKey}'") - stages[inputKey] = Operation(inputKey, op.operator, config.operators[op.operator] ?: throw IllegalArgumentException("Undefined operator '${op.operator}'"), op.merge) + stages[inputKey] = Operation(inputKey, op.operator!!, config.operators[op.operator] ?: throw IllegalArgumentException("Undefined operator '${op.operator}'"), op.merge) } stages[operation.key]?.addInput(stages[inputKey]!!) } @@ -267,7 +291,7 @@ class IngestionPipelineBuilder(val config: IngestionConfig) { logger.info { "Built extractor by name field name: ${config.fieldName}" } } } else if (!config.factory.isNullOrBlank()) { - val factory = loadFactory, Descriptor>>(config.factory) + val factory = loadFactory, Descriptor<*>>>(config.factory) return factory.newExtractor(name, parent, this.context).apply { logger.info { "Built extractor by factory: ${config.factory}" } } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/Operation.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/Operation.kt index c619d6ec1..41a9f6280 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/Operation.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/Operation.kt @@ -5,12 +5,9 @@ import org.vitrivr.engine.core.operators.transform.shape.MergeType import java.util.* /** - * This [Operation] class represents a single operation in the ingest pipeline. - * - * @author Ralph Gasser - * @version 1.0.0 + * This sealed class represents a base operation in the ingest pipeline. */ -data class Operation(val name: String, val opName: String, val opConfig: OperatorConfig, val merge: MergeType? = null) { +class Operation(val name: String, val opName: String?, val opConfig: OperatorConfig?, val merge: MergeType?) { /** A [LinkedList] of all input [Operation]s. */ private val _input = LinkedList() @@ -45,4 +42,5 @@ data class Operation(val name: String, val opName: String, val opConfig: Operato this._output.add(operation) operation._input.add(this) } -} \ No newline at end of file +} + diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/OperationConfig.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/OperationConfig.kt index a5a6d0920..8bc203683 100755 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/OperationConfig.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/ingest/operation/OperationConfig.kt @@ -15,7 +15,7 @@ import org.vitrivr.engine.core.operators.transform.shape.MergeType @Serializable data class OperationConfig( /** The name of the [OperatorConfig] at this stage. Must be a name of the [IngestionConfig.operators] property. */ - val operator: String, + val operator: String? = null, /** The names of the [OperationConfig] that follow this operation. Must be a name of the [IngestionConfig.operations] property. */ val inputs: List = emptyList(), diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/pipeline/execution/RetrievalPipeline.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/pipeline/execution/RetrievalPipeline.kt index 4ec039c6c..d6e58f635 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/pipeline/execution/RetrievalPipeline.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/config/pipeline/execution/RetrievalPipeline.kt @@ -6,8 +6,6 @@ import org.vitrivr.engine.core.operators.Operator /** * A pipeline for retrieval. It wraps a (query) [Operator] that returns [Retrieved] objects. * - * TODO: Builder for this must be implemented. - * * @author Ralph Gasser * @version 1.0.0 */ diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/context/Context.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/context/Context.kt index ad03b9a25..75927fb0b 100755 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/context/Context.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/context/Context.kt @@ -2,7 +2,6 @@ package org.vitrivr.engine.core.context import io.javalin.openapi.OpenApiIgnore import kotlinx.serialization.Serializable -import kotlinx.serialization.Transient import org.vitrivr.engine.core.model.metamodel.Schema /** @@ -11,7 +10,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema * This is applicable for index and query phases. */ @Serializable -sealed class Context() { +sealed class Context { /** * Configuration per named operator. */ diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnection.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnection.kt index 5fea05969..4936bf97f 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnection.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnection.kt @@ -17,13 +17,13 @@ import org.vitrivr.engine.core.model.metamodel.Schema abstract class AbstractConnection(override val schemaName: String, override val provider: ConnectionProvider) : Connection { /** An internal [Map] of registered [Reader], [Writer] and [Initializer] instances. */ - private val readers: Map, DescriptorReader<*>> = HashMap() + private val readers: Map>, DescriptorReader<*>> = HashMap() /** An internal [Map] of registered [Reader], [Writer] and [Initializer] instances. */ - private val writers: Map, DescriptorWriter<*>> = HashMap() + private val writers: Map>, DescriptorWriter<*>> = HashMap() /** */ - private val initializers: Map, DescriptorInitializer<*>> = HashMap() + private val initializers: Map>, DescriptorInitializer<*>> = HashMap() /** * Initializes the database layer with the [Schema] used by this [Connection]. @@ -47,12 +47,12 @@ abstract class AbstractConnection(override val schemaName: String, override val * @param field The [Analyser] to return the [DescriptorInitializer] for. * @return The [DescriptorInitializer] */ - override fun getDescriptorInitializer(field: Schema.Field<*,D>): DescriptorInitializer { - var initializer = this.initializers[field as Schema.Field<*, Descriptor>] + override fun > getDescriptorInitializer(field: Schema.Field<*, D>): DescriptorInitializer { + var initializer = this.initializers[field as Schema.Field<*, Descriptor<*>>] if (initializer == null) { val descriptorProvider = this.provider.obtain(field.analyser.descriptorClass) ?: throw IllegalArgumentException("Unhandled describer $field for provided schema.") - initializer = descriptorProvider.newInitializer(this, field as Schema.Field<*, Descriptor>) + initializer = descriptorProvider.newInitializer(this, field as Schema.Field<*, Descriptor<*>>) (this.initializers as HashMap)[field] = initializer } require(initializer.field == field) { "Misconfigured initializer; describers do not match. This is a programmer's error." } @@ -67,12 +67,12 @@ abstract class AbstractConnection(override val schemaName: String, override val * @param field The [Analyser] to return the [DescriptorReader] for. * @return The [DescriptorReader] */ - override fun getDescriptorReader(field: Schema.Field<*,D>): DescriptorReader { - var reader = this.readers[field as Schema.Field<*, Descriptor>] + override fun > getDescriptorReader(field: Schema.Field<*, D>): DescriptorReader { + var reader = this.readers[field as Schema.Field<*, Descriptor<*>>] if (reader == null) { - val descriptorProvider = provider.obtain(field.analyser.descriptorClass) + val descriptorProvider = this.provider.obtain(field.analyser.descriptorClass) ?: throw IllegalArgumentException("Unhandled describer $field for provided schema.") - reader = descriptorProvider.newReader(this, field as Schema.Field<*, Descriptor>) + reader = descriptorProvider.newReader(this, field as Schema.Field<*, Descriptor<*>>) (this.readers as HashMap)[field] = reader } require(reader.field == field) { "Misconfigured reader; describers do not match. This is a programmer's error." } @@ -87,12 +87,12 @@ abstract class AbstractConnection(override val schemaName: String, override val * @param field The [Analyser] to return the [DescriptorWriter] for. * @return The [DescriptorWriter] */ - override fun getDescriptorWriter(field: Schema.Field<*,D>): DescriptorWriter { - var writer = this.writers[field as Schema.Field<*, Descriptor>] + override fun > getDescriptorWriter(field: Schema.Field<*, D>): DescriptorWriter { + var writer = this.writers[field as Schema.Field<*, Descriptor<*>>] if (writer == null) { - val descriptorProvider = provider.obtain(field.analyser.descriptorClass) + val descriptorProvider = this.provider.obtain(field.analyser.descriptorClass) ?: throw IllegalArgumentException("Unhandled describer $field for provided schema.") - writer = descriptorProvider.newWriter(this, field as Schema.Field<*, Descriptor>) + writer = descriptorProvider.newWriter(this, field as Schema.Field<*, Descriptor<*>>) (this.writers as HashMap)[field] = writer } require(writer.field == field) { "Misconfigured writer; describers do not match. This is a programmer's error." } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnectionProvider.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnectionProvider.kt index a20582a23..181fed59c 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnectionProvider.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/AbstractConnectionProvider.kt @@ -32,7 +32,7 @@ abstract class AbstractConnectionProvider: ConnectionProvider { * @param descriptorClass The [KClass] of the [Descriptor] to register [DescriptorProvider] for. * @param provider The [DescriptorProvider] to register. */ - override fun register(descriptorClass: KClass, provider: DescriptorProvider<*>) { + override fun > register(descriptorClass: KClass, provider: DescriptorProvider<*>) { this.registered[descriptorClass] = provider } @@ -43,7 +43,7 @@ abstract class AbstractConnectionProvider: ConnectionProvider { * @return The registered [DescriptorProvider] . */ @Suppress("UNCHECKED_CAST") - override fun obtain(descriptorClass: KClass): DescriptorProvider { + override fun > obtain(descriptorClass: KClass): DescriptorProvider { val provider = this.registered[descriptorClass] ?: throw IllegalStateException("No DescriptorProvider registered for $descriptorClass.") return provider as DescriptorProvider } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/Connection.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/Connection.kt index e1e039d93..f68781f70 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/Connection.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/Connection.kt @@ -78,7 +78,7 @@ sealed interface Connection: Closeable { * re-used or re-created every time the method is being called. */ @OpenApiIgnore - fun getDescriptorInitializer(field: Schema.Field<*,D>): DescriptorInitializer + fun > getDescriptorInitializer(field: Schema.Field<*, D>): DescriptorInitializer /** * Returns a [DescriptorWriter]. @@ -89,7 +89,7 @@ sealed interface Connection: Closeable { * re-used or re-created every time the method is being called. */ @OpenApiIgnore - fun getDescriptorWriter(field: Schema.Field<*,D>): DescriptorWriter + fun > getDescriptorWriter(field: Schema.Field<*, D>): DescriptorWriter /** * Returns a [DescriptorReader]. @@ -100,7 +100,7 @@ sealed interface Connection: Closeable { * re-used or re-created every time the method is being called. */ @OpenApiIgnore - fun getDescriptorReader(field: Schema.Field<*,D>): DescriptorReader + fun > getDescriptorReader(field: Schema.Field<*, D>): DescriptorReader /** * Returns a human-readable descriptor of this [Connection]. diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/ConnectionProvider.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/ConnectionProvider.kt index d34933b54..f8d1320b7 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/ConnectionProvider.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/ConnectionProvider.kt @@ -40,7 +40,7 @@ interface ConnectionProvider { * @param descriptorClass The [KClass] of the [Descriptor] to register [DescriptorProvider] for. * @param provider The [DescriptorProvider] to register. */ - fun register(descriptorClass: KClass, provider: DescriptorProvider<*>) + fun > register(descriptorClass: KClass, provider: DescriptorProvider<*>) /** * Obtains an [DescriptorProvider] for a particular [KClass] of [Descriptor], that has been registered with this [ConnectionProvider]. @@ -48,5 +48,5 @@ interface ConnectionProvider { * @param descriptorClass The [KClass] of the [Descriptor] to lookup [DescriptorProvider] for. * @return The registered [DescriptorProvider] . */ - fun obtain(descriptorClass: KClass): DescriptorProvider? + fun > obtain(descriptorClass: KClass): DescriptorProvider? } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/BlackholeConnection.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/BlackholeConnection.kt new file mode 100755 index 000000000..19c22969a --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/BlackholeConnection.kt @@ -0,0 +1,68 @@ +package org.vitrivr.engine.core.database.blackhole + +import io.github.oshai.kotlinlogging.KLogger +import io.github.oshai.kotlinlogging.KotlinLogging.logger +import io.github.oshai.kotlinlogging.Marker +import org.vitrivr.engine.core.database.AbstractConnection +import org.vitrivr.engine.core.database.ConnectionProvider +import org.vitrivr.engine.core.database.blackhole.descriptors.BlackholeDescriptorInitializer +import org.vitrivr.engine.core.database.blackhole.descriptors.BlackholeDescriptorReader +import org.vitrivr.engine.core.database.blackhole.descriptors.BlackholeDescriptorWriter +import org.vitrivr.engine.core.database.blackhole.retrievable.BlackholeRetrievableInitializer +import org.vitrivr.engine.core.database.blackhole.retrievable.BlackholeRetrievableReader +import org.vitrivr.engine.core.database.blackhole.retrievable.BlackholeRetrievableWriter +import org.vitrivr.engine.core.database.descriptor.DescriptorReader +import org.vitrivr.engine.core.database.retrievable.RetrievableInitializer +import org.vitrivr.engine.core.database.retrievable.RetrievableReader +import org.vitrivr.engine.core.database.retrievable.RetrievableWriter +import org.vitrivr.engine.core.model.descriptor.Descriptor +import org.vitrivr.engine.core.model.metamodel.Schema + + +/** Defines [KLogger] of the class. */ +internal val LOGGER: KLogger = logger {} + +/** + * An [AbstractConnection] that swallows all data and does not store anything. However, it can be used to log operations. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeConnection(schemaName: String, provider: ConnectionProvider, private val log: Boolean = false) : AbstractConnection(schemaName, provider) { + + + + init { + LOGGER.warn { "You are using the blackhole connection with schema $schemaName. No data will be stored!" } + } + + /** [Marker] used for logging. */ + private val marker: Marker = object : Marker { + override fun getName(): String = this@BlackholeConnection.description() + } + + override fun initialize() = this.logIf("Initializing schema '$schemaName'.") + override fun truncate() = this.logIf("Truncating schema '$schemaName'.") + override fun withTransaction(action: (Unit) -> T): T { + LOGGER.warn { "Transactions are not supported by blackhole connection. Ignoring transaction." } + return action(Unit) + } + + override fun getRetrievableInitializer(): RetrievableInitializer = BlackholeRetrievableInitializer(this) + override fun getRetrievableWriter(): RetrievableWriter = BlackholeRetrievableWriter(this) + override fun getRetrievableReader(): RetrievableReader = BlackholeRetrievableReader(this) + override fun > getDescriptorInitializer(field: Schema.Field<*, D>) = BlackholeDescriptorInitializer(this, field) + override fun > getDescriptorWriter(field: Schema.Field<*, D>) = BlackholeDescriptorWriter(this, field) + override fun > getDescriptorReader(field: Schema.Field<*, D>): DescriptorReader = BlackholeDescriptorReader(this, field) + override fun description(): String = "'$schemaName'@blackhole" + override fun close() = this.logIf("Closing connection to blackhole database.") + + /** + * Conditionally logs a message if logging is enabled. + * + * @param message The message to log. + */ + internal fun logIf(message: String) { + if (this.log) LOGGER.info(throwable = null, marker = this.marker) { message } + } +} diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/BlackholeConnectionProvider.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/BlackholeConnectionProvider.kt new file mode 100755 index 000000000..f6837bfa1 --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/BlackholeConnectionProvider.kt @@ -0,0 +1,21 @@ +package org.vitrivr.engine.core.database.blackhole + +import org.vitrivr.engine.core.database.ConnectionProvider +import org.vitrivr.engine.core.database.blackhole.descriptors.BlackholeDescriptionProvider +import org.vitrivr.engine.core.database.descriptor.DescriptorProvider +import org.vitrivr.engine.core.model.descriptor.Descriptor +import kotlin.reflect.KClass + +/** + * A [ConnectionProvider] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeConnectionProvider : ConnectionProvider { + override val databaseName: String = "blackhole" + override val version: String = "1.0.0" + override fun openConnection(schemaName: String, parameters: Map) = BlackholeConnection(schemaName, this, parameters["log"]?.toBoolean() == true) + override fun > register(descriptorClass: KClass, provider: DescriptorProvider<*>) { /* No op. */ } + override fun > obtain(descriptorClass: KClass) = BlackholeDescriptionProvider() +} diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptionProvider.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptionProvider.kt new file mode 100644 index 000000000..98f072e57 --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptionProvider.kt @@ -0,0 +1,21 @@ +package org.vitrivr.engine.core.database.blackhole.descriptors + +import org.vitrivr.engine.core.database.Connection +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.descriptor.DescriptorProvider +import org.vitrivr.engine.core.database.descriptor.DescriptorReader +import org.vitrivr.engine.core.database.descriptor.DescriptorWriter +import org.vitrivr.engine.core.model.descriptor.Descriptor +import org.vitrivr.engine.core.model.metamodel.Schema + +/** + * A [DescriptorProvider] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeDescriptionProvider>: DescriptorProvider { + override fun newInitializer(connection: Connection, field: Schema.Field<*, T>)= BlackholeDescriptorInitializer(connection as BlackholeConnection, field) + override fun newReader(connection: Connection, field: Schema.Field<*, T>): DescriptorReader = BlackholeDescriptorReader(connection as BlackholeConnection, field) + override fun newWriter(connection: Connection, field: Schema.Field<*, T>): DescriptorWriter = BlackholeDescriptorWriter(connection as BlackholeConnection, field) +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorInitializer.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorInitializer.kt new file mode 100644 index 000000000..b8b1a973e --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorInitializer.kt @@ -0,0 +1,19 @@ +package org.vitrivr.engine.core.database.blackhole.descriptors + +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.descriptor.DescriptorInitializer +import org.vitrivr.engine.core.model.descriptor.Descriptor +import org.vitrivr.engine.core.model.metamodel.Schema + +/** + * A [DescriptorInitializer] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeDescriptorInitializer>(private val connection: BlackholeConnection, override val field: Schema.Field<*, T>): DescriptorInitializer { + override fun initialize() = this.connection.logIf("Initializing descriptor entity '${this.field.fieldName}'.") + override fun deinitialize() = this.connection.logIf("De-initializing descriptor entity '${this.field.fieldName}'.") + override fun isInitialized(): Boolean = false + override fun truncate() = this.connection.logIf("Truncating descriptor entity '${this.field.fieldName}'.") +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorReader.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorReader.kt new file mode 100644 index 000000000..707cd70a1 --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorReader.kt @@ -0,0 +1,28 @@ +package org.vitrivr.engine.core.database.blackhole.descriptors + +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.descriptor.DescriptorReader +import org.vitrivr.engine.core.model.descriptor.Descriptor +import org.vitrivr.engine.core.model.descriptor.DescriptorId +import org.vitrivr.engine.core.model.metamodel.Schema +import org.vitrivr.engine.core.model.query.Query +import org.vitrivr.engine.core.model.retrievable.RetrievableId +import org.vitrivr.engine.core.model.retrievable.Retrieved + +/** + * A [DescriptorReader] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeDescriptorReader>(override val connection: BlackholeConnection, override val field: Schema.Field<*, T>) : DescriptorReader { + override fun exists(descriptorId: DescriptorId): Boolean = false + override fun get(descriptorId: DescriptorId): T? = null + override fun getAll(descriptorIds: Iterable) = emptySequence() + override fun getAll() = emptySequence() + override fun getForRetrievable(retrievableId: RetrievableId) = emptySequence() + override fun getAllForRetrievable(retrievableIds: Iterable) = emptySequence() + override fun query(query: Query) = emptySequence() + override fun queryAndJoin(query: Query) = emptySequence() + override fun count() = 0L +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorWriter.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorWriter.kt new file mode 100644 index 000000000..f1414f9d3 --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/descriptors/BlackholeDescriptorWriter.kt @@ -0,0 +1,39 @@ +package org.vitrivr.engine.core.database.blackhole.descriptors + +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.descriptor.DescriptorWriter +import org.vitrivr.engine.core.model.descriptor.Descriptor +import org.vitrivr.engine.core.model.metamodel.Schema + +/** + * A [DescriptorWriter] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeDescriptorWriter>(override val connection: BlackholeConnection, override val field: Schema.Field<*, T>): DescriptorWriter { + override fun add(item: T): Boolean { + this.connection.logIf("Adding descriptor '${item.id}' to entity '${this.field.fieldName}'.") + return false + } + + override fun addAll(items: Iterable): Boolean { + items.forEach { item -> this.connection.logIf("Adding descriptor '${item.id}' to entity '${this.field.fieldName}'.") } + return false + } + + override fun update(item: T): Boolean { + this.connection.logIf("Updating descriptor '${item.id}' in entity '${this.field.fieldName}'.") + return false + } + + override fun delete(item: T): Boolean { + this.connection.logIf("Deleting descriptor '${item.id}' in entity '${this.field.fieldName}'.") + return false + } + + override fun deleteAll(items: Iterable): Boolean { + items.forEach { item -> this.connection.logIf("Deleting descriptor '${item.id}' from entity '${this.field.fieldName}'.") } + return false + } +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableInitializer.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableInitializer.kt new file mode 100644 index 000000000..cbc2b06c7 --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableInitializer.kt @@ -0,0 +1,17 @@ +package org.vitrivr.engine.core.database.blackhole.retrievable + +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.retrievable.RetrievableInitializer + +/** + * A [RetrievableInitializer] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeRetrievableInitializer(private val connection: BlackholeConnection): RetrievableInitializer { + override fun initialize() = this.connection.logIf("Initializing entities 'retrievable' and 'relationship'.") + override fun deinitialize() = this.connection.logIf("De-initializing entities 'retrievable' and 'relationship'.") + override fun isInitialized(): Boolean = false + override fun truncate() = this.connection.logIf("Truncating entities 'retrievable' and 'relationship'.") +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableReader.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableReader.kt new file mode 100644 index 000000000..d4e287078 --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableReader.kt @@ -0,0 +1,22 @@ +package org.vitrivr.engine.core.database.blackhole.retrievable + +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.retrievable.RetrievableReader +import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.RetrievableId + + +/** + * A [RetrievableReader] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeRetrievableReader(override val connection: BlackholeConnection) : RetrievableReader { + override fun get(id: RetrievableId): Retrievable? = null + override fun exists(id: RetrievableId): Boolean = false + override fun getAll(ids: Iterable) = emptySequence() + override fun getAll() = emptySequence() + override fun getConnections(subjectIds: Collection, predicates: Collection, objectIds: Collection) = emptySequence>() + override fun count(): Long = 0L +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableWriter.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableWriter.kt new file mode 100644 index 000000000..26888832f --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/BlackholeRetrievableWriter.kt @@ -0,0 +1,60 @@ +package org.vitrivr.engine.core.database.blackhole.retrievable + +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.retrievable.RetrievableWriter +import org.vitrivr.engine.core.model.relationship.Relationship +import org.vitrivr.engine.core.model.retrievable.Retrievable + + +/** + * A [RetrievableWriter] for the [BlackholeConnection]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +class BlackholeRetrievableWriter(override val connection: BlackholeConnection): RetrievableWriter { + override fun connect(relationship: Relationship): Boolean { + this.connection.logIf("Adding relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.") + return false + } + + override fun connectAll(relationships: Iterable): Boolean { + relationships.forEach { relationship -> this.connection.logIf("Adding relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.")} + return false + } + + override fun disconnect(relationship: Relationship): Boolean { + this.connection.logIf("Removing relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.") + return false + } + + override fun disconnectAll(relationships: Iterable): Boolean { + relationships.forEach { relationship -> this.connection.logIf("Removing relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.")} + return false + } + + override fun add(item: Retrievable): Boolean { + this.connection.logIf("Adding retrievable '${item.id}' to entity 'retrievable'.") + return false + } + + override fun addAll(items: Iterable): Boolean { + items.forEach { item -> this.connection.logIf("Adding retrievable '${item.id}' to entity 'retrievable'.") } + return false + } + + override fun update(item: Retrievable): Boolean { + this.connection.logIf("Updating retrievable '${item.id}' in entity 'retrievable'.") + return false + } + + override fun delete(item: Retrievable): Boolean { + this.connection.logIf("Deleting retrievable '${item.id}' from entity 'retrievable'.") + return false + } + + override fun deleteAll(items: Iterable): Boolean { + items.forEach { item -> this.connection.logIf("Deleting retrievable '${item.id}' from entity 'retrievable'.") } + return false + } +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorInitializer.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorInitializer.kt index 659c8404f..16c7d6214 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorInitializer.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorInitializer.kt @@ -11,7 +11,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema * @author Luca Rossetto * @author Ralph Gasser */ -interface DescriptorInitializer : Initializer { +interface DescriptorInitializer> : Initializer { /** The [Analyser] this [DescriptorInitializer] belongs to. */ val field: Schema.Field<*,D> } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorProvider.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorProvider.kt index 640ad9291..15f812519 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorProvider.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorProvider.kt @@ -10,7 +10,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema * @author Ralph Gasser * @version 1.0.0 */ -interface DescriptorProvider { +interface DescriptorProvider> { /** * Returns a [DescriptorInitializer]. * diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorReader.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorReader.kt index 5df0973d9..9df83336b 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorReader.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorReader.kt @@ -19,7 +19,7 @@ import org.vitrivr.engine.core.model.retrievable.Retrieved * @author Ralph Gasser * @version 2.0.1 */ -interface DescriptorReader : Reader { +interface DescriptorReader> : Reader { /** The [Analyser] this [DescriptorReader] belongs to. */ val field: Schema.Field<*,D> diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorWriter.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorWriter.kt index 0ab85ad9f..7d3ef0108 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorWriter.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/DescriptorWriter.kt @@ -11,7 +11,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema * @author Ralph Gasser * @version 1.0.0 */ -interface DescriptorWriter : Writer { +interface DescriptorWriter> : Writer { /** The [Schema.Field] this [DescriptorWriter] belongs to. */ val field: Schema.Field<*,D> } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/NoDescriptorInitializer.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/NoDescriptorInitializer.kt index 773d1798f..c3179e404 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/NoDescriptorInitializer.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/database/descriptor/NoDescriptorInitializer.kt @@ -11,7 +11,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema * @author Luca Rossetto * @version 1.0.0 */ -class NoDescriptorInitializer(override val field: Schema.Field<*,D>) : DescriptorInitializer { +class NoDescriptorInitializer>(override val field: Schema.Field<*, D>) : DescriptorInitializer { override fun initialize() { /* No op. */ } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractBatchedExtractor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractBatchedExtractor.kt index d0f8b8420..3097ee6c7 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractBatchedExtractor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractBatchedExtractor.kt @@ -3,9 +3,7 @@ package org.vitrivr.engine.core.features import io.github.oshai.kotlinlogging.KLogger import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.onCompletion -import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.* import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.descriptor.Descriptor import org.vitrivr.engine.core.model.metamodel.Analyser @@ -14,7 +12,6 @@ import org.vitrivr.engine.core.model.retrievable.Retrievable import org.vitrivr.engine.core.model.retrievable.attributes.DescriptorAuthorAttribute import org.vitrivr.engine.core.operators.Operator import org.vitrivr.engine.core.operators.ingest.Extractor -import java.util.* /** * An abstract [Extractor] implementation that is suitable for [Extractor] implementations which extract descriptors in batches of multiple retrievables. @@ -23,7 +20,7 @@ import java.util.* * @author Ralph Gasser * @version 1.0.0 */ -abstract class AbstractBatchedExtractor, D : Descriptor> +abstract class AbstractBatchedExtractor, D : Descriptor<*>> private constructor( final override val input: Operator, final override val analyser: Analyser, @@ -54,6 +51,11 @@ abstract class AbstractBatchedExtractor, D : Descriptor> private val logger: KLogger = KotlinLogging.logger {} + + init { + require(field == null || this.field.analyser == this.analyser) { "Field and analyser do not match! This is a programmer's error!" } + } + /** * A default [Extractor] implementation for batched extraction. It executes the following steps: * @@ -65,59 +67,62 @@ abstract class AbstractBatchedExtractor, D : Descriptor> * @return [Flow] of [Retrievable] */ final override fun toFlow(scope: CoroutineScope): Flow { + return flow { + val batch = mutableListOf() - val batch = mutableListOf() - - /* Prepare and return flow. */ - return this.input.toFlow(scope).onEach { retrievable -> - try { - if (this.matches(retrievable)) { - batch.add(retrievable) - } - if (batch.size >= bufferSize) { - val descriptors = extract(batch) - // zip descriptors and batch - for (i in batch.indices) { - val r = batch[i] - if (descriptors[i].isNotEmpty()) { + this@AbstractBatchedExtractor.input.toFlow(scope).collect { retrievable -> + try { + if (this@AbstractBatchedExtractor.matches(retrievable)) { + batch.add(retrievable) + } + else { + emit(retrievable) + } + if (batch.size >= bufferSize) { + logger.debug { "Batch size reached for field ${field?.fieldName}, extracting descriptors" } + val descriptors = extract(batch) + batch.forEachIndexed { i, r -> val sourceAttribute = DescriptorAuthorAttribute() - for (d in descriptors[i]) { + descriptors[i].forEach { d -> r.addDescriptor(d) - sourceAttribute.add(d, this.name) + sourceAttribute.add(d, name) } r.addAttribute(sourceAttribute) } + emitAll(batch.asFlow()) + batch.clear() } - batch.clear() - } - } catch (e: Exception) { - "Error during extraction: ${e.message}".let { - logger.error { it } + } catch (e: Exception) { + logger.error(e) { "Error during extraction" } } } - }.onCompletion { - /* Persist buffer if necessary. */ + + // Emit any remaining items in the batch if (batch.isNotEmpty()) { val descriptors = extract(batch) - // zip descriptors and batch - for (i in batch.indices) { - val r = batch[i] - for (d in descriptors[i]) { + batch.forEachIndexed { i, r -> + descriptors[i].forEach { d -> r.addDescriptor(d) } } + emitAll(batch.asFlow()) batch.clear() } } } + /** * Internal method to check, if [Retrievable] matches this [Extractor] and should thus be processed. * + * By default, a [Retrievable] matches this [Extractor] if it contains at least one [ContentElement] that matches the [Analyser.contentClasses]. + * * @param retrievable The [Retrievable] to check. * @return True on match, false otherwise, */ - protected abstract fun matches(retrievable: Retrievable): Boolean + protected open fun matches(retrievable: Retrievable): Boolean = retrievable.content.any { content -> + this.analyser.contentClasses.any { it.isInstance(content) } + } /** * Internal method to perform extraction on batch of [Retrievable]. diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractExtractor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractExtractor.kt index d701651a2..7776c612d 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractExtractor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractExtractor.kt @@ -20,7 +20,7 @@ import org.vitrivr.engine.core.operators.ingest.Extractor * @author Ralph Gasser * @version 1.2.0 */ -abstract class AbstractExtractor, D : Descriptor> private constructor( +abstract class AbstractExtractor, D : Descriptor<*>> private constructor( final override val input: Operator, final override val analyser: Analyser, final override val field: Schema.Field? = null, @@ -40,7 +40,6 @@ abstract class AbstractExtractor, D : Descriptor> private null, name ) - protected val logger: KLogger = KotlinLogging.logger {} init { @@ -61,7 +60,7 @@ abstract class AbstractExtractor, D : Descriptor> private if (this.matches(retrievable)) { /* Perform extraction. */ val descriptors = try { - logger.debug { "Extraction for retrievable: $retrievable" } + logger.debug{"Extraction on field ${field?.fieldName} for retrievable: $retrievable" } extract(retrievable) } catch (e: Throwable) { logger.error(e) { "Error during extraction of $retrievable" } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractRetriever.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractRetriever.kt index a1ca4c716..859523f55 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractRetriever.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/AbstractRetriever.kt @@ -22,7 +22,7 @@ import org.vitrivr.engine.core.operators.retrieve.Retriever * @author Rahel Arnold * @version 1.0.0 */ -abstract class AbstractRetriever, D : Descriptor>(override val field: Schema.Field, val query: Query, val context: QueryContext) : Retriever { +abstract class AbstractRetriever, D : Descriptor<*>>(override val field: Schema.Field, val query: Query, val context: QueryContext) : Retriever { /** The [DescriptorReader] instance used by this [AbstractRetriever]. */ protected val reader: DescriptorReader by lazy { this.field.getReader() } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadata.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadata.kt index 208ba6336..8417365da 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadata.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadata.kt @@ -4,7 +4,7 @@ import org.vitrivr.engine.core.context.IndexContext import org.vitrivr.engine.core.context.QueryContext import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.descriptor.Attribute -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor +import org.vitrivr.engine.core.model.descriptor.struct.AnyMapStructDescriptor import org.vitrivr.engine.core.model.metamodel.Analyser import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.query.Query @@ -16,13 +16,13 @@ import org.vitrivr.engine.core.operators.ingest.Extractor import org.vitrivr.engine.core.operators.retrieve.Retriever import java.util.* -class ExifMetadata : Analyser, MapStructDescriptor> { +class ExifMetadata : Analyser, AnyMapStructDescriptor> { override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = MapStructDescriptor::class - override fun prototype(field: Schema.Field<*, *>): MapStructDescriptor { + override val descriptorClass = AnyMapStructDescriptor::class + override fun prototype(field: Schema.Field<*, *>): AnyMapStructDescriptor { val parameters = field.parameters.map { (k, v) -> Attribute(k, Type.valueOf(v)) } - return MapStructDescriptor( + return AnyMapStructDescriptor( UUID.randomUUID(), UUID.randomUUID(), parameters, @@ -50,12 +50,12 @@ class ExifMetadata : Analyser, MapStructDescriptor> { * * @return A new [Extractor] instance for this [Analyser] */ - override fun newExtractor(field: Schema.Field, MapStructDescriptor>, input: Operator, context: IndexContext) = ExifMetadataExtractor(input, this, field) + override fun newExtractor(field: Schema.Field, AnyMapStructDescriptor>, input: Operator, context: IndexContext) = ExifMetadataExtractor(input, this, field) /** * */ - override fun newRetrieverForQuery(field: Schema.Field, MapStructDescriptor>, query: Query, context: QueryContext): Retriever, MapStructDescriptor> { + override fun newRetrieverForQuery(field: Schema.Field, AnyMapStructDescriptor>, query: Query, context: QueryContext): Retriever, AnyMapStructDescriptor> { require(field.analyser == this) { "Field type is incompatible with analyser. This is a programmer's error!" } require(query is SimpleBooleanQuery<*>) { "Query is not a Query." } return ExifMetadataRetriever(field, query, context) @@ -64,7 +64,7 @@ class ExifMetadata : Analyser, MapStructDescriptor> { /** * */ - override fun newRetrieverForContent(field: Schema.Field, MapStructDescriptor>, content: Collection>, context: QueryContext): ExifMetadataRetriever { + override fun newRetrieverForContent(field: Schema.Field, AnyMapStructDescriptor>, content: Collection>, context: QueryContext): ExifMetadataRetriever { throw UnsupportedOperationException("ExifMetadata does not support the creation of a Retriever instance from content.") } } \ No newline at end of file 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 e005e594b..da3ad5ac8 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 @@ -10,7 +10,7 @@ import org.vitrivr.engine.core.features.AbstractExtractor import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor +import org.vitrivr.engine.core.model.descriptor.struct.AnyMapStructDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.Retrievable import org.vitrivr.engine.core.model.retrievable.attributes.SourceAttribute @@ -38,7 +38,7 @@ private fun convertDate(date: String): Date? { for (pattern in DATE_FORMAT_PATTERNS) { try { return SimpleDateFormat(pattern).parse(date) - } catch (_: ParseException) { + } catch (e: ParseException) { } } logger.warn { "Failed to parse date: $date" } @@ -87,15 +87,15 @@ private fun JsonObject.convertType(type: Type): Value<*>? { } } -class ExifMetadataExtractor : AbstractExtractor, MapStructDescriptor> { +class ExifMetadataExtractor : AbstractExtractor, AnyMapStructDescriptor> { - constructor(input: Operator, analyser: ExifMetadata, field: Schema.Field, MapStructDescriptor>) : super(input, analyser, field) + constructor(input: Operator, analyser: ExifMetadata, field: Schema.Field, AnyMapStructDescriptor>) : super(input, analyser, field) constructor(input: Operator, analyser: ExifMetadata, name: String): super(input, analyser, name) override fun matches(retrievable: Retrievable): Boolean = retrievable.filteredAttribute(SourceAttribute::class.java)?.source is FileSource - override fun extract(retrievable: Retrievable): List { + override fun extract(retrievable: Retrievable): List { val metadata = ImageMetadataReader.readMetadata((retrievable.filteredAttribute(SourceAttribute::class.java)?.source as FileSource).path.toFile()) val columnValues = mutableMapOf>() @@ -133,6 +133,6 @@ class ExifMetadataExtractor : AbstractExtractor, MapStructDesc } logger.info { "Extracted fields: ${columnValues.entries.joinToString { (key, value) -> "$key = ${value.value}" }}" } - return listOf(MapStructDescriptor(UUID.randomUUID(), retrievable.id, attributes.values.toList(), columnValues.mapValues { it.value }, field = this.field)) + return listOf(AnyMapStructDescriptor(UUID.randomUUID(), retrievable.id, attributes.values.toList(), columnValues.mapValues { it.value }, field = this.field)) } } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataRetriever.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataRetriever.kt index 3312c1405..7fe887881 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataRetriever.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/exif/ExifMetadataRetriever.kt @@ -3,8 +3,8 @@ package org.vitrivr.engine.core.features.metadata.source.exif import org.vitrivr.engine.core.context.QueryContext import org.vitrivr.engine.core.features.AbstractRetriever import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor +import org.vitrivr.engine.core.model.descriptor.struct.AnyMapStructDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.query.Query -class ExifMetadataRetriever(field: Schema.Field, MapStructDescriptor>, query: Query, context: QueryContext) : AbstractRetriever, MapStructDescriptor>(field, query, context) \ No newline at end of file +class ExifMetadataRetriever(field: Schema.Field, AnyMapStructDescriptor>, query: Query, context: QueryContext) : AbstractRetriever, AnyMapStructDescriptor>(field, query, context) \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/video/VideoSourceMetadataExtractor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/video/VideoSourceMetadataExtractor.kt index 2bc3e5f01..ffdc1aa60 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/video/VideoSourceMetadataExtractor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/metadata/source/video/VideoSourceMetadataExtractor.kt @@ -53,6 +53,7 @@ class VideoSourceMetadataExtractor : mapOf( "width" to Value.Int(source.width() ?: 0), "height" to Value.Int(source.height() ?: 0), + "duration" to Value.Long(source.duration() ?: 0L), "fps" to Value.Double(source.fps() ?: 0.0), "channels" to Value.Int(source.channels() ?: 0), "sampleRate" to Value.Int(source.sampleRate() ?: 0), diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/MediaDimensions.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/MediaDimensions.kt deleted file mode 100644 index 2cbc46ea3..000000000 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/MediaDimensions.kt +++ /dev/null @@ -1,34 +0,0 @@ -package org.vitrivr.engine.core.features.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.struct.metadata.MediaDimensionsDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever - -class MediaDimensions : Analyser, MediaDimensionsDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = MediaDimensionsDescriptor::class - override fun prototype(field: Schema.Field<*,*>) = MediaDimensionsDescriptor.PROTOTYPE - override fun newRetrieverForContent(field: Schema.Field, MediaDimensionsDescriptor>, content: Collection>, context: QueryContext): Retriever, MediaDimensionsDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, MediaDimensionsDescriptor>, query: Query, context: QueryContext): Retriever, MediaDimensionsDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, MediaDimensionsDescriptor>, input: Operator, context: IndexContext): Extractor, MediaDimensionsDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, MediaDimensionsDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/VideoDuration.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/VideoDuration.kt deleted file mode 100644 index c389b9a4f..000000000 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/VideoDuration.kt +++ /dev/null @@ -1,34 +0,0 @@ -package org.vitrivr.engine.core.features.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.scalar.FloatDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class VideoDuration : Analyser, FloatDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatDescriptor(UUID.randomUUID(), UUID.randomUUID(), value = Value.Float(.0f)) - override fun newRetrieverForContent(field: Schema.Field, FloatDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatDescriptor> { - TODO("Not yet implemented") - } - override fun newRetrieverForQuery(field: Schema.Field, FloatDescriptor>, query: Query, context: QueryContext): Retriever, FloatDescriptor> { - TODO("Not yet implemented") - } - override fun newExtractor(field: Schema.Field, FloatDescriptor>, input: Operator, context: IndexContext): Extractor, FloatDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/VideoFPS.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/VideoFPS.kt deleted file mode 100644 index 012c8b4ab..000000000 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/features/migration/VideoFPS.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.engine.core.features.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.scalar.FloatDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class VideoFPS : Analyser, FloatDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatDescriptor(UUID.randomUUID(), UUID.randomUUID(), value = Value.Float(.0f)) - override fun newRetrieverForQuery(field: Schema.Field, FloatDescriptor>, query: Query, context: QueryContext): Retriever, FloatDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForContent(field: Schema.Field, FloatDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatDescriptor>, input: Operator, context: IndexContext): Extractor, FloatDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/ContentElement.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/ContentElement.kt index ef5de14af..a50c3ba59 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/ContentElement.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/ContentElement.kt @@ -1,7 +1,12 @@ package org.vitrivr.engine.core.model.content.element +import kotlinx.serialization.Serializable import org.vitrivr.engine.core.model.content.Content import org.vitrivr.engine.core.model.content.ContentType +import org.vitrivr.engine.core.model.serializer.UUIDSerializer +import java.util.UUID + +typealias ContentId = @Serializable(UUIDSerializer::class) UUID /** * A [Content] element is a piece of [Content] that is tied to some actual [Content]. @@ -19,6 +24,9 @@ sealed interface ContentElement: Content { */ val content: T + val id: ContentId + /** The [ContentType] of this [ContentElement]. */ val type: ContentType + } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/Model3DContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/Model3DContent.kt index b4082087d..a2311c74a 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/Model3DContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/element/Model3DContent.kt @@ -2,7 +2,6 @@ package org.vitrivr.engine.core.model.content.element import org.vitrivr.engine.core.model.content.ContentType import org.vitrivr.engine.core.model.mesh.Model3D -import java.awt.image.BufferedImage /** * A 3D [ContentElement]. @@ -13,9 +12,6 @@ import java.awt.image.BufferedImage interface Model3DContent: ContentElement{ /** The [ContentType] of a [Model3DContent] is always [ContentType.MESH]. */ - val id: String - get() = this.content.id - override val type: ContentType get() = ContentType.MESH } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/CachedContentFactory.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/CachedContentFactory.kt index 3dac1e44e..13fc7aff0 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/CachedContentFactory.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/CachedContentFactory.kt @@ -8,6 +8,7 @@ import org.vitrivr.engine.core.model.content.impl.cache.CachedAudioContent import org.vitrivr.engine.core.model.content.impl.cache.CachedContent import org.vitrivr.engine.core.model.content.impl.cache.CachedImageContent import org.vitrivr.engine.core.model.content.impl.cache.CachedTextContent +import org.vitrivr.engine.core.model.content.impl.memory.InMemoryMeshContent import org.vitrivr.engine.core.model.mesh.Model3D import org.vitrivr.engine.core.model.metamodel.Schema import java.awt.image.BufferedImage @@ -119,7 +120,9 @@ class CachedContentFactory : ContentFactoriesFactory { override fun newMeshContent(model3D: Model3D): Model3DContent { check(!this.closed) { "CachedContentFactory has been closed." } - TODO() + val content = InMemoryMeshContent(model3D) /* TODO: Caching. */ + logger.warn { "Caching of MeshContent is not yet implemented. Using in-memory content instead." } + return content } @@ -142,7 +145,6 @@ class CachedContentFactory : ContentFactoriesFactory { } } - /** * Closes this [CachedContentFactory] and purges all remaining items. A closed [CachedContentFactory] cannot be used anymore. */ diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/InMemoryContentFactory.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/InMemoryContentFactory.kt index 6af446eea..a3e5a8327 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/InMemoryContentFactory.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/factory/InMemoryContentFactory.kt @@ -1,7 +1,9 @@ package org.vitrivr.engine.core.model.content.factory import org.vitrivr.engine.core.context.Context -import org.vitrivr.engine.core.model.content.element.* +import org.vitrivr.engine.core.model.content.element.ContentElement +import org.vitrivr.engine.core.model.content.element.Model3DContent +import org.vitrivr.engine.core.model.content.element.TextContent import org.vitrivr.engine.core.model.content.impl.memory.InMemoryAudioContent import org.vitrivr.engine.core.model.content.impl.memory.InMemoryImageContent import org.vitrivr.engine.core.model.content.impl.memory.InMemoryMeshContent @@ -15,21 +17,14 @@ import java.nio.ShortBuffer * A [ContentFactory] that keeps [ContentElement]s in memory. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.0.1 */ class InMemoryContentFactory : ContentFactoriesFactory { - override fun newContentFactory(schema: Schema, context: Context): ContentFactory = Instance() - private class Instance() : ContentFactory { - - override fun newImageContent(bufferedImage: BufferedImage): ImageContent = InMemoryImageContent(bufferedImage) - - override fun newAudioContent(channels: Short, samplingRate: Int, audio: ShortBuffer): AudioContent = - InMemoryAudioContent(channels, samplingRate, audio) - + override fun newImageContent(bufferedImage: BufferedImage) = InMemoryImageContent(bufferedImage) + override fun newAudioContent(channels: Short, sampleRate: Int, audio: ShortBuffer) = InMemoryAudioContent(channels, sampleRate, audio) override fun newTextContent(text: String): TextContent = InMemoryTextContent(text) - override fun newMeshContent(model3D: Model3D): Model3DContent = InMemoryMeshContent(model3D) } } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedAudioContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedAudioContent.kt index 3b9128934..2a3d60eed 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedAudioContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedAudioContent.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.core.model.content.impl.cache import org.vitrivr.engine.core.model.content.element.AudioContent +import org.vitrivr.engine.core.model.content.element.ContentId import java.lang.ref.SoftReference import java.nio.ByteBuffer import java.nio.ByteOrder @@ -8,6 +9,7 @@ import java.nio.ShortBuffer import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardOpenOption +import java.util.* /** * A [AudioContent] implementation that is backed by a cache file. @@ -15,7 +17,7 @@ import java.nio.file.StandardOpenOption * @author Ralph Gasser * @version 1.0.0 */ -class CachedAudioContent(override val path: Path, override val channels: Short, override val samplingRate: Int, buffer: ShortBuffer) : AudioContent, CachedContent { +class CachedAudioContent(override val path: Path, override val channels: Short, override val samplingRate: Int, buffer: ShortBuffer, override val id: ContentId = ContentId.randomUUID()) : AudioContent, CachedContent { /** The [SoftReference] of the [ByteBuffer] used for caching. */ private var reference: SoftReference = SoftReference(buffer) @@ -36,6 +38,7 @@ class CachedAudioContent(override val path: Path, override val channels: Short, return buffer.asReadOnlyBuffer() } + init { val outBuffer = ByteBuffer.allocate(this.size).order(ByteOrder.LITTLE_ENDIAN) for (i in 0 until buffer.limit()) { diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedImageContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedImageContent.kt index 8b1e271b3..498511401 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedImageContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedImageContent.kt @@ -1,11 +1,13 @@ package org.vitrivr.engine.core.model.content.impl.cache +import org.vitrivr.engine.core.model.content.element.ContentId import org.vitrivr.engine.core.model.content.element.ImageContent import java.awt.image.BufferedImage import java.lang.ref.SoftReference import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardOpenOption +import java.util.* import javax.imageio.ImageIO /** @@ -14,7 +16,7 @@ import javax.imageio.ImageIO * @author Ralph Gasser * @version 1.0.0 */ -class CachedImageContent(override val path: Path, image: BufferedImage) : ImageContent, CachedContent { +class CachedImageContent(override val path: Path, image: BufferedImage, override val id: ContentId = ContentId.randomUUID()) : ImageContent, CachedContent { /** The [SoftReference] of the [BufferedImage] used for caching. */ private var reference: SoftReference = SoftReference(image) diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedTextContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedTextContent.kt index d816f2ae1..4038e3c8a 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedTextContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/cache/CachedTextContent.kt @@ -1,10 +1,12 @@ package org.vitrivr.engine.core.model.content.impl.cache +import org.vitrivr.engine.core.model.content.element.ContentId import org.vitrivr.engine.core.model.content.element.TextContent import java.lang.ref.SoftReference import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardOpenOption +import java.util.* /** * A [TextContent] implementation that is backed by a cache file. @@ -12,7 +14,7 @@ import java.nio.file.StandardOpenOption * @author Ralph Gasser * @version 1.0.0 */ -class CachedTextContent(override val path: Path, text: String) : TextContent, CachedContent { +class CachedTextContent(override val path: Path, text: String, override val id: ContentId = ContentId.randomUUID()) : TextContent, CachedContent { /** The [SoftReference] of the [String] used for caching. */ private var reference: SoftReference = SoftReference(text) diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryAudioContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryAudioContent.kt index deb768698..668443655 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryAudioContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryAudioContent.kt @@ -1,7 +1,9 @@ package org.vitrivr.engine.core.model.content.impl.memory import org.vitrivr.engine.core.model.content.element.AudioContent +import org.vitrivr.engine.core.model.content.element.ContentId import java.nio.ShortBuffer +import java.util.* /** * A naive in-memory implementation of the [AudioContent] interface. @@ -11,4 +13,5 @@ import java.nio.ShortBuffer * @author Ralph Gasser * @version 1.0.0 */ -data class InMemoryAudioContent(override val channels: Short, override val samplingRate: Int, override val content: ShortBuffer) : AudioContent +data class InMemoryAudioContent(override val channels: Short, override val samplingRate: Int, override val content: ShortBuffer, override val id: ContentId = ContentId.randomUUID()) : AudioContent { +} diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryImageContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryImageContent.kt index 40a9c2b0b..2a9f89289 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryImageContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryImageContent.kt @@ -1,7 +1,9 @@ package org.vitrivr.engine.core.model.content.impl.memory +import org.vitrivr.engine.core.model.content.element.ContentId import org.vitrivr.engine.core.model.content.element.ImageContent import java.awt.image.BufferedImage +import java.util.* /** * A naive in-memory implementation of the [ImageContent] interface. @@ -11,4 +13,4 @@ import java.awt.image.BufferedImage * @author Luca Rossetto. * @version 1.0.0 */ -data class InMemoryImageContent(override val content: BufferedImage) : ImageContent +data class InMemoryImageContent(override val content: BufferedImage, override val id: ContentId = ContentId.randomUUID()) : ImageContent diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryMeshContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryMeshContent.kt index a1818ad3c..025aeb675 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryMeshContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryMeshContent.kt @@ -1,8 +1,10 @@ package org.vitrivr.engine.core.model.content.impl.memory +import org.vitrivr.engine.core.model.content.element.ContentId import org.vitrivr.engine.core.model.content.element.ImageContent import org.vitrivr.engine.core.model.content.element.Model3DContent import org.vitrivr.engine.core.model.mesh.Model3D +import java.util.* /** * A naive in-memory implementation of the [ImageContent] interface. @@ -12,4 +14,4 @@ import org.vitrivr.engine.core.model.mesh.Model3D * @author Luca Rossetto. * @version 1.0.0 */ -data class InMemoryMeshContent(override val content: Model3D) : Model3DContent +data class InMemoryMeshContent(override val content: Model3D, override val id: ContentId = ContentId.randomUUID()) : Model3DContent diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryTextContent.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryTextContent.kt index 3e7d449d9..4b8b04a83 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryTextContent.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/content/impl/memory/InMemoryTextContent.kt @@ -1,7 +1,9 @@ package org.vitrivr.engine.core.model.content.impl.memory import kotlinx.serialization.Serializable +import org.vitrivr.engine.core.model.content.element.ContentId import org.vitrivr.engine.core.model.content.element.TextContent +import java.util.UUID /** * A naive in-memory implementation of the [TextContent] interface. @@ -9,5 +11,5 @@ import org.vitrivr.engine.core.model.content.element.TextContent * @author Luca Rossetto. * @version 1.0.0 */ -@Serializable -data class InMemoryTextContent(override val content: String) : TextContent + +data class InMemoryTextContent(override val content: String, override val id: ContentId = ContentId.randomUUID()) : TextContent \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/Descriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/Descriptor.kt index 3a64f4591..a9c668acb 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/Descriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/Descriptor.kt @@ -19,15 +19,15 @@ typealias DescriptorId = @Serializable(UUIDSerializer::class) UUID * @author Ralph Gasser * @version 1.0.0 */ -interface Descriptor : Persistable { +interface Descriptor> : Persistable { /** The [DescriptorId] held by this [Descriptor]. */ - var id: DescriptorId + val id: DescriptorId /** The [RetrievableId] of the [Retrievable] that is being described by this [Descriptor]. */ - var retrievableId: RetrievableId? + val retrievableId: RetrievableId? /** The [Schema.Field] backing this [Descriptor]. */ - val field: Schema.Field<*, out Descriptor>? + val field: Schema.Field<*, out T>? /** Flag indicating whether this [Descriptor] is persistent or not. */ override val transient: Boolean @@ -46,4 +46,15 @@ interface Descriptor : Persistable { * @return A [Map] of this [Descriptor]'s fields (without the IDs). */ fun values(): Map?> + + /** + * Returns a copy of this [Descriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [Descriptor]. + * @param retrievableId [RetrievableId] of the new [Descriptor]. + * @param field [Schema.Field] the new [Descriptor] belongs to. + * + * @return Copy of this [Descriptor]. + */ + fun copy(id: DescriptorId = this.id, retrievableId: RetrievableId? = this.retrievableId, field: Schema.Field<*, T>? = null): T } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/BooleanDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/BooleanDescriptor.kt index 356b582a6..bda7d6269 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/BooleanDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/BooleanDescriptor.kt @@ -12,15 +12,15 @@ import org.vitrivr.engine.core.model.types.Value * A [ScalarDescriptor] using a [Boolean] value. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.1.0 */ data class BooleanDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, override val value: Value.Boolean, override val field: Schema.Field<*, BooleanDescriptor>? = null -) : ScalarDescriptor { +) : ScalarDescriptor { companion object { private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Boolean)) } @@ -31,4 +31,13 @@ data class BooleanDescriptor( * @return [List] of [Attribute] */ override fun layout(): List = SCHEMA + /** + * Returns a copy of this [BooleanDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [BooleanDescriptor]. + * @param retrievableId [RetrievableId] of the new [BooleanDescriptor]. + * @param field [Schema.Field] the new [BooleanDescriptor] belongs to. + * @return Copy of this [BooleanDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, BooleanDescriptor>?) = BooleanDescriptor(id, retrievableId, this.value, field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ByteDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ByteDescriptor.kt new file mode 100644 index 000000000..b13e1fa8b --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ByteDescriptor.kt @@ -0,0 +1,43 @@ +package org.vitrivr.engine.core.model.descriptor.scalar + +import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.DescriptorId +import org.vitrivr.engine.core.model.descriptor.scalar.ScalarDescriptor.Companion.VALUE_ATTRIBUTE_NAME +import org.vitrivr.engine.core.model.metamodel.Schema +import org.vitrivr.engine.core.model.retrievable.RetrievableId +import org.vitrivr.engine.core.model.types.Type +import org.vitrivr.engine.core.model.types.Value + +/** + * A [ScalarDescriptor] using an [Value.Byte]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +data class ByteDescriptor( + override val id: DescriptorId, + override val retrievableId: RetrievableId?, + override val value: Value.Byte, + override val field: Schema.Field<*, ByteDescriptor>? = null +) : ScalarDescriptor { + companion object { + private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Byte)) + } + + /** + * Returns the [Attribute] [List] of this [IntDescriptor]. + * + * @return [List] of [Attribute] + */ + override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [ByteDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [ByteDescriptor]. + * @param retrievableId [RetrievableId] of the new [ByteDescriptor]. + * @param field [Schema.Field] the new [ByteDescriptor] belongs to. + * @return Copy of this [ByteDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, ByteDescriptor>?) = ByteDescriptor(id, retrievableId, this.value, field) +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/DoubleDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/DoubleDescriptor.kt index 828408f43..5cde74692 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/DoubleDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/DoubleDescriptor.kt @@ -12,15 +12,14 @@ import org.vitrivr.engine.core.model.types.Value * A [ScalarDescriptor] using a [Double] value. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.1.0 */ - data class DoubleDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, override val value: Value.Double, override val field: Schema.Field<*, DoubleDescriptor>? = null -) : ScalarDescriptor { +) : ScalarDescriptor { companion object { private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Double)) } @@ -31,4 +30,14 @@ data class DoubleDescriptor( * @return [List] of [Attribute] */ override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [DoubleDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [DoubleDescriptor]. + * @param retrievableId [RetrievableId] of the new [DoubleDescriptor]. + * @param field [Schema.Field] the new [DoubleDescriptor] belongs to. + * @return Copy of this [DoubleDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, DoubleDescriptor>?) = DoubleDescriptor(id, retrievableId, this.value, field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/FloatDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/FloatDescriptor.kt index 00efb0211..455271fef 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/FloatDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/FloatDescriptor.kt @@ -1,6 +1,5 @@ package org.vitrivr.engine.core.model.descriptor.scalar -import kotlinx.serialization.Serializable import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.scalar.ScalarDescriptor.Companion.VALUE_ATTRIBUTE_NAME @@ -13,14 +12,14 @@ import org.vitrivr.engine.core.model.types.Value * A [ScalarDescriptor] using a [Float] value. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.1.0 */ data class FloatDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, override val value: Value.Float, override val field: Schema.Field<*, FloatDescriptor>? = null -) : ScalarDescriptor { +) : ScalarDescriptor { companion object { private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Float)) } @@ -31,4 +30,14 @@ data class FloatDescriptor( * @return [List] of [Attribute] */ override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [FloatDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [FloatDescriptor]. + * @param retrievableId [RetrievableId] of the new [FloatDescriptor]. + * @param field [Schema.Field] the new [FloatDescriptor] belongs to. + * @return Copy of this [FloatDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, FloatDescriptor>?) = FloatDescriptor(id, retrievableId, this.value, field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/IntDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/IntDescriptor.kt index b56daff34..1ed030f86 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/IntDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/IntDescriptor.kt @@ -16,11 +16,11 @@ import org.vitrivr.engine.core.model.types.Value */ data class IntDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, override val value: Value.Int, override val field: Schema.Field<*, IntDescriptor>? = null -) : ScalarDescriptor { +) : ScalarDescriptor { companion object { private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Int)) } @@ -31,4 +31,14 @@ data class IntDescriptor( * @return [List] of [Attribute] */ override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [IntDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [IntDescriptor]. + * @param retrievableId [RetrievableId] of the new [IntDescriptor]. + * @param field [Schema.Field] the new [FloatDescriptor] belongs to. + * @return Copy of this [IntDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, IntDescriptor>?) = IntDescriptor(id, retrievableId, this.value, field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/LongDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/LongDescriptor.kt index 6e6fb06db..6fe000b87 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/LongDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/LongDescriptor.kt @@ -13,14 +13,14 @@ import org.vitrivr.engine.core.model.types.Value * A [ScalarDescriptor] using a [Long] value. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.1.0 */ data class LongDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, override val value: Value.Long, override val field: Schema.Field<*, LongDescriptor>? = null -) : ScalarDescriptor { +) : ScalarDescriptor { companion object { private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Long)) } @@ -31,4 +31,14 @@ data class LongDescriptor( * @return [List] of [Attribute] */ override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [LongDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [LongDescriptor]. + * @param retrievableId [RetrievableId] of the new [LongDescriptor]. + * @param field [Schema.Field] the new [LongDescriptor] belongs to. + * @return Copy of this [LongDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, LongDescriptor>?) = LongDescriptor(id, retrievableId, this.value, field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ScalarDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ScalarDescriptor.kt index 508dd38b6..61c726a83 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ScalarDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ScalarDescriptor.kt @@ -1,30 +1,28 @@ package org.vitrivr.engine.core.model.descriptor.scalar -import kotlinx.serialization.Serializable import org.vitrivr.engine.core.model.descriptor.AttributeName import org.vitrivr.engine.core.model.descriptor.Descriptor import org.vitrivr.engine.core.model.types.Value /** - * A [Descriptor] with a scalar value [T]. + * A [Descriptor] with a scalar value [V]. * * @author Ralph Gasser * @version 1.1.0 */ -@Serializable -sealed interface ScalarDescriptor> : Descriptor { +sealed interface ScalarDescriptor, V : Value.ScalarValue<*>> : Descriptor { companion object { const val VALUE_ATTRIBUTE_NAME = "value" } /** The [Value] held by this [ScalarDescriptor]. */ - val value: T + val value: V /** * Returns the fields and its values of this [ScalarDescriptor] as a [Map]. * * @return A [Map] of this [ScalarDescriptor]'s fields (without the IDs). */ - override fun values(): Map = mapOf("value" to this.value) + override fun values(): Map = mapOf("value" to this.value) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ShortDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ShortDescriptor.kt new file mode 100644 index 000000000..9089d1896 --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/ShortDescriptor.kt @@ -0,0 +1,43 @@ +package org.vitrivr.engine.core.model.descriptor.scalar + +import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.DescriptorId +import org.vitrivr.engine.core.model.descriptor.scalar.ScalarDescriptor.Companion.VALUE_ATTRIBUTE_NAME +import org.vitrivr.engine.core.model.metamodel.Schema +import org.vitrivr.engine.core.model.retrievable.RetrievableId +import org.vitrivr.engine.core.model.types.Type +import org.vitrivr.engine.core.model.types.Value + +/** + * A [ScalarDescriptor] using an [Value.Short]. + * + * @author Ralph Gasser + * @version 1.0.0 + */ +data class ShortDescriptor( + override val id: DescriptorId, + override val retrievableId: RetrievableId?, + override val value: Value.Short, + override val field: Schema.Field<*, ShortDescriptor>? = null +) : ScalarDescriptor { + companion object { + private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Short)) + } + + /** + * Returns the [Attribute] [List] of this [IntDescriptor]. + * + * @return [List] of [Attribute] + */ + override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [ShortDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [ShortDescriptor]. + * @param retrievableId [RetrievableId] of the new [ShortDescriptor]. + * @param field [Schema.Field] the new [ShortDescriptor] belongs to. + * @return Copy of this [ShortDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, ShortDescriptor>?) = ShortDescriptor(id, retrievableId, this.value, field) +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/StringDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/StringDescriptor.kt index 3a1bfa07e..270682ac7 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/StringDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/StringDescriptor.kt @@ -12,15 +12,15 @@ import org.vitrivr.engine.core.model.types.Value * A [ScalarDescriptor] using a [String] value. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.1.0 */ data class StringDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, override val value: Value.String, override val field: Schema.Field<*, StringDescriptor>? = null -) : ScalarDescriptor { +) : ScalarDescriptor { companion object { private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.String)) } @@ -31,4 +31,14 @@ data class StringDescriptor( * @return [List] of [Attribute] */ override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [StringDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [StringDescriptor]. + * @param retrievableId [RetrievableId] of the new [StringDescriptor]. + * @param field [Schema.Field] the new [StringDescriptor] belongs to. + * @return Copy of this [StringDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, StringDescriptor>?) = StringDescriptor(id, retrievableId, this.value, field) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/TextDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/TextDescriptor.kt index 35bc8fda5..b0a036594 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/TextDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/scalar/TextDescriptor.kt @@ -18,20 +18,30 @@ import org.vitrivr.engine.core.model.types.Value * @version 1.0.0 */ data class TextDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, override val value: Value.Text, override val field: Schema.Field<*, TextDescriptor>? = null -) : ScalarDescriptor { - +) : ScalarDescriptor { companion object { private val SCHEMA = listOf(Attribute(VALUE_ATTRIBUTE_NAME, Type.Text)) } + /** * Returns the [Attribute] [List ]of this [StringDescriptor]. * * @return [List] of [Attribute] */ override fun layout(): List = SCHEMA + + /** + * Returns a copy of this [TextDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [TextDescriptor]. + * @param retrievableId [RetrievableId] of the new [TextDescriptor]. + * @param field [Schema.Field] the new [TextDescriptor] belongs to. + * @return Copy of this [TextDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, TextDescriptor>?) = TextDescriptor(id, retrievableId, this.value, field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/AnyMapStructDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/AnyMapStructDescriptor.kt new file mode 100644 index 000000000..9fa707bfa --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/AnyMapStructDescriptor.kt @@ -0,0 +1,33 @@ +package org.vitrivr.engine.core.model.descriptor.struct + +import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.AttributeName +import org.vitrivr.engine.core.model.descriptor.DescriptorId +import org.vitrivr.engine.core.model.metamodel.Schema +import org.vitrivr.engine.core.model.retrievable.RetrievableId +import org.vitrivr.engine.core.model.types.Value + +/** + * A [StructDescriptor] implementation that can be configured to store any type of [Value] in its fields. + * + * @author Ralph Gasser + * @version 1.2.0 + */ +class AnyMapStructDescriptor( + id: DescriptorId, + retrievableId: RetrievableId?, + layout: List, + values: Map?>, + override val field: Schema.Field<*, AnyMapStructDescriptor>? = null +) : StructDescriptor(id, retrievableId, layout, values, field) { + + /** + * Returns a copy of this [StructDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [AnyMapStructDescriptor]. + * @param retrievableId [RetrievableId] of the new [AnyMapStructDescriptor]. + * @param field [Schema.Field] the new [AnyMapStructDescriptor] belongs to. + * @return Copy of this [AnyMapStructDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, AnyMapStructDescriptor>?) = AnyMapStructDescriptor(id, retrievableId, this.layout, HashMap(this.values), field) +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/LabelDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/LabelDescriptor.kt index 33e7896eb..15d42437e 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/LabelDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/LabelDescriptor.kt @@ -1,8 +1,8 @@ package org.vitrivr.engine.core.model.descriptor.struct -import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.AttributeName +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId import org.vitrivr.engine.core.model.types.Type @@ -15,11 +15,11 @@ import org.vitrivr.engine.core.model.types.Value * @version 2.0.0 */ class LabelDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, values: Map?>, override val field: Schema.Field<*, LabelDescriptor>? = null -) : MapStructDescriptor(id, retrievableId, SCHEMA, values, field) { +) : StructDescriptor(id, retrievableId, SCHEMA, values, field) { companion object { private val SCHEMA = listOf( Attribute("label", Type.String), @@ -32,4 +32,14 @@ class LabelDescriptor( /** The associated confidence. */ val confidence: Value.Float by this.values + + /** + * Returns a copy of this [LabelDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [LabelDescriptor]. + * @param retrievableId [RetrievableId] of the new [LabelDescriptor]. + * @param field [Schema.Field] the new [LabelDescriptor] belongs to. + * @return Copy of this [LabelDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, LabelDescriptor>?) = LabelDescriptor(id, retrievableId, HashMap(this.values), this.field) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/MapStructDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/MapStructDescriptor.kt deleted file mode 100644 index bf12ba567..000000000 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/MapStructDescriptor.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.core.model.descriptor.struct - -import org.vitrivr.engine.core.model.descriptor.Attribute -import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.Descriptor -import org.vitrivr.engine.core.model.descriptor.DescriptorId -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.retrievable.RetrievableId -import org.vitrivr.engine.core.model.types.Value - -/** - * An abstract [StructDescriptor] implementation that is backed by a [Map] of [Value]s. - * - * @author Ralph Gasser - * @version 1.0.0 - */ -open class MapStructDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, - protected val layout: List, - protected val values: Map?>, - override val field: Schema.Field<*, out StructDescriptor>? = null -) : StructDescriptor { - /** - * Returns a [Attribute] [List] for this [Descriptor]. - * - * @return [List] of [Attribute] - */ - final override fun layout(): List = this.layout - - /** - * Returns the fields and its values of this [Descriptor] as a [Map]. - * - * @return A [Map] of this [Descriptor]'s fields (without the IDs). - */ - final override fun values(): Map?> = this.values -} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/StructDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/StructDescriptor.kt index 533f525e6..ccc2e0780 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/StructDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/StructDescriptor.kt @@ -1,18 +1,37 @@ package org.vitrivr.engine.core.model.descriptor.struct +import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.AttributeName import org.vitrivr.engine.core.model.descriptor.Descriptor +import org.vitrivr.engine.core.model.descriptor.DescriptorId +import org.vitrivr.engine.core.model.metamodel.Schema +import org.vitrivr.engine.core.model.retrievable.RetrievableId +import org.vitrivr.engine.core.model.types.Value /** - * A [Descriptor] that uses a complex structure. - * - * **Caution: Respect the constructor arguments:** - * - * 1. First: descriptorId - * 2. Second: retrievableId - * 3. Then: Custom - * 4. Last: field + * An abstract [StructDescriptor] implementation that is backed by a [Map] of [Value]s. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.2.0 */ -interface StructDescriptor : Descriptor +abstract class StructDescriptor>( + override val id: DescriptorId, + override val retrievableId: RetrievableId?, + protected val layout: List, + protected val values: Map?>, + override val field: Schema.Field<*, out T>? = null +) : Descriptor { + /** + * Returns a [Attribute] [List] for this [Descriptor]. + * + * @return [List] of [Attribute] + */ + final override fun layout(): List = this.layout + + /** + * Returns the fields and its values of this [Descriptor] as a [Map]. + * + * @return A [Map] of this [Descriptor]'s fields (without the IDs). + */ + final override fun values(): Map?> = this.values +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/MediaDimensionsDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/MediaDimensionsDescriptor.kt index f38028ba3..3d6b7b1a4 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/MediaDimensionsDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/MediaDimensionsDescriptor.kt @@ -1,9 +1,8 @@ package org.vitrivr.engine.core.model.descriptor.struct.metadata -import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.struct.StructDescriptor import org.vitrivr.engine.core.model.descriptor.struct.metadata.source.VideoSourceMetadataDescriptor import org.vitrivr.engine.core.model.metamodel.Schema @@ -16,14 +15,14 @@ import java.util.* * A [StructDescriptor] used to store metadata about a 2D raster graphic. * * @author Ralph Gasser - * @version 2.0.0 + * @version 2.1.0 */ class MediaDimensionsDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, values: Map?>, override val field: Schema.Field<*, MediaDimensionsDescriptor>? = null -) : MapStructDescriptor(id, retrievableId, SCHEMA, values, field) { +) : StructDescriptor(id, retrievableId, SCHEMA, values, field) { companion object { /** The field schema associated with a [VideoSourceMetadataDescriptor]. */ private val SCHEMA = listOf( @@ -47,4 +46,14 @@ class MediaDimensionsDescriptor( /** The height of this image. */ val height: Value.Int by this.values + + /** + * Returns a copy of this [MediaDimensionsDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [MediaDimensionsDescriptor]. + * @param retrievableId [RetrievableId] of the new [MediaDimensionsDescriptor]. + * @param field [Schema.Field] the new [MediaDimensionsDescriptor] belongs to. + * @return Copy of this [MediaDimensionsDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, MediaDimensionsDescriptor>?) = MediaDimensionsDescriptor(id, retrievableId, HashMap(this.values), field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/Rectangle2DMetadataDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/Rectangle2DMetadataDescriptor.kt index acba69ce4..6ac260dc3 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/Rectangle2DMetadataDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/Rectangle2DMetadataDescriptor.kt @@ -1,9 +1,8 @@ package org.vitrivr.engine.core.model.descriptor.struct.metadata -import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.struct.StructDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -15,14 +14,14 @@ import java.util.* * A [StructDescriptor] used to store spatial metadata in a 2D raster graphic. * * @author Ralph Gasser - * @version 2.0.0 + * @version 2.1.0 */ class Rectangle2DMetadataDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, values: Map?>, override val field: Schema.Field<*, Rectangle2DMetadataDescriptor>? = null -) : MapStructDescriptor(id, retrievableId, SCHEMA, values, field) { +) : StructDescriptor(id, retrievableId, SCHEMA, values, field) { companion object { /** The field schema associated with a [Rectangle2DMetadataDescriptor]. */ @@ -57,4 +56,15 @@ class Rectangle2DMetadataDescriptor( /** The height of the rectangle. */ val height: Value.Int by this.values + + /** + * Returns a copy of this [Rectangle2DMetadataDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [Rectangle2DMetadataDescriptor]. + * @param retrievableId [RetrievableId] of the new [Rectangle2DMetadataDescriptor]. + * @param field [Schema.Field] the new [Rectangle2DMetadataDescriptor] belongs to. + * @return Copy of this [Rectangle2DMetadataDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, Rectangle2DMetadataDescriptor>?) = Rectangle2DMetadataDescriptor(id, retrievableId, HashMap(this.values), field) + } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/TemporalMetadataDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/TemporalMetadataDescriptor.kt index 8f0272268..afd67ec9b 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/TemporalMetadataDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/TemporalMetadataDescriptor.kt @@ -1,9 +1,8 @@ package org.vitrivr.engine.core.model.descriptor.struct.metadata -import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.struct.StructDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -18,11 +17,11 @@ import java.util.* * @version 2.0.0 */ class TemporalMetadataDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, //retrievable Id must come first, due to reflection + override val id: DescriptorId, + override val retrievableId: RetrievableId?, //retrievable Id must come first, due to reflection values: Map?>, override val field: Schema.Field<*, TemporalMetadataDescriptor>? = null -) : MapStructDescriptor(id, retrievableId, SCHEMA, values, field) { +) : StructDescriptor(id, retrievableId, SCHEMA, values, field) { companion object { /** The field schema associated with a [TemporalMetadataDescriptor]. */ @@ -40,4 +39,14 @@ class TemporalMetadataDescriptor( /** The end timestamp in nanoseconds. */ val end: Value.Long by this.values + + /** + * Returns a copy of this [TemporalMetadataDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [TemporalMetadataDescriptor]. + * @param retrievableId [RetrievableId] of the new [TemporalMetadataDescriptor]. + * @param field [Schema.Field] the new [TemporalMetadataDescriptor] belongs to. + * @return Copy of this [TemporalMetadataDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, TemporalMetadataDescriptor>?) = TemporalMetadataDescriptor(id, retrievableId, HashMap(this.values), field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/FileSourceMetadataDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/FileSourceMetadataDescriptor.kt index 273f51593..9fa7d07b5 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/FileSourceMetadataDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/FileSourceMetadataDescriptor.kt @@ -3,7 +3,6 @@ package org.vitrivr.engine.core.model.descriptor.struct.metadata.source import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.AttributeName import org.vitrivr.engine.core.model.descriptor.DescriptorId -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor import org.vitrivr.engine.core.model.descriptor.struct.StructDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -15,14 +14,14 @@ import java.util.* * A [StructDescriptor] used to store metadata about a file. * * @author Ralph Gasser - * @version 2.0.0 + * @version 2.1.0 */ class FileSourceMetadataDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, values: Map?>, override val field: Schema.Field<*, FileSourceMetadataDescriptor>? = null -) : MapStructDescriptor(id, retrievableId, SCHEMA, values, field) { +) : StructDescriptor(id, retrievableId, SCHEMA, values, field) { constructor(id: DescriptorId, retrievableId: RetrievableId?, path: Value.String, size: Value.Long, field: Schema.Field<*, FileSourceMetadataDescriptor>) : this(id, retrievableId, mapOf("path" to path, "size" to size), field) @@ -43,4 +42,14 @@ class FileSourceMetadataDescriptor( /** The prototype [FileSourceMetadataDescriptor]. */ val PROTOTYPE = FileSourceMetadataDescriptor(UUID.randomUUID(), UUID.randomUUID(), mapOf("path" to Value.String(""), "size" to Value.Long(0L))) } + + /** + * Returns a copy of this [FileSourceMetadataDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [FileSourceMetadataDescriptor]. + * @param retrievableId [RetrievableId] of the new [FileSourceMetadataDescriptor]. + * @param field [Schema.Field] the new [FileSourceMetadataDescriptor] belongs to. + * @return Copy of this [FileSourceMetadataDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, FileSourceMetadataDescriptor>?) = FileSourceMetadataDescriptor(id, retrievableId, HashMap(this.values), field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/VideoSourceMetadataDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/VideoSourceMetadataDescriptor.kt index 8572f3da5..7ee9891e1 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/VideoSourceMetadataDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/struct/metadata/source/VideoSourceMetadataDescriptor.kt @@ -1,9 +1,8 @@ package org.vitrivr.engine.core.model.descriptor.struct.metadata.source -import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.Attribute import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.struct.StructDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -15,14 +14,14 @@ import java.util.* * A [StructDescriptor] used to store metadata about a video source (e.g., a file). * * @author Ralph Gasser - * @version 2.0.0 + * @version 2.1.0 */ class VideoSourceMetadataDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, + override val id: DescriptorId, + override val retrievableId: RetrievableId?, values: Map?>, override val field: Schema.Field<*, VideoSourceMetadataDescriptor>? = null, -) : MapStructDescriptor(id, retrievableId, SCHEMA, values, field) { +) : StructDescriptor(id, retrievableId, SCHEMA, values, field) { /** The width of the video source in pixels. */ val width: Value.Int by this.values @@ -30,6 +29,9 @@ class VideoSourceMetadataDescriptor( /** The width of the video source in pixels. */ val height: Value.Int by this.values + /** The duration of the video source in pixels. */ + val duration: Value.Double by this.values + /** The number of visual frames per seconds. */ val fps: Value.Double by this.values @@ -47,6 +49,7 @@ class VideoSourceMetadataDescriptor( private val SCHEMA = listOf( Attribute("width", Type.Int), Attribute("height", Type.Int), + Attribute("duration", Type.Long), Attribute("fps", Type.Double), Attribute("channels", Type.Int), Attribute("sampleRate", Type.Int), @@ -60,6 +63,7 @@ class VideoSourceMetadataDescriptor( mapOf( "width" to Value.Int(0), "height" to Value.Int(0), + "duration" to Value.Long(0L), "fps" to Value.Double(0.0), "channels" to Value.Int(0), "sampleRate" to Value.Int(0), @@ -67,4 +71,14 @@ class VideoSourceMetadataDescriptor( ) ) } + + /** + * Returns a copy of this [VideoSourceMetadataDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [VideoSourceMetadataDescriptor]. + * @param retrievableId [RetrievableId] of the new [VideoSourceMetadataDescriptor]. + * @param field [Schema.Field] the new [VideoSourceMetadataDescriptor] belongs to. + * @return Copy of this [VideoSourceMetadataDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, VideoSourceMetadataDescriptor>?) = VideoSourceMetadataDescriptor(id, retrievableId, HashMap(this.values), this.field) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/tensor/TensorDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/tensor/TensorDescriptor.kt deleted file mode 100644 index b52b83539..000000000 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/tensor/TensorDescriptor.kt +++ /dev/null @@ -1,13 +0,0 @@ -package org.vitrivr.engine.core.model.descriptor.tensor - -import org.vitrivr.engine.core.model.descriptor.Descriptor - -/** - * TODO - * - * @author Ralph Gasser - * @version 1.0.0 - */ -interface TensorDescriptor : Descriptor { - -} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/BooleanVectorDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/BooleanVectorDescriptor.kt index 52b29910e..1b8d138db 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/BooleanVectorDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/BooleanVectorDescriptor.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.core.model.descriptor.vector import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.vector.VectorDescriptor.Companion.VECTOR_ATTRIBUTE_NAME import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -13,19 +14,29 @@ import java.util.* * * @author Luca Rossetto * @author Ralph Gasser - * @version 1.1.0 + * @version 1.2.0 */ data class BooleanVectorDescriptor( - override var id: UUID = UUID.randomUUID(), - override var retrievableId: RetrievableId? = null, + override val id: UUID = UUID.randomUUID(), + override val retrievableId: RetrievableId? = null, override val vector: Value.BooleanVector, override val field: Schema.Field<*, BooleanVectorDescriptor>? = null -) : VectorDescriptor { +) : VectorDescriptor { /** * Returns the [Attribute] [List ]of this [BooleanVectorDescriptor]. * * @return [List] of [Attribute] */ override fun layout(): List = listOf(Attribute(VECTOR_ATTRIBUTE_NAME, Type.BooleanVector(this.dimensionality))) + + /** + * Returns a copy of this [BooleanVectorDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [BooleanVectorDescriptor]. + * @param retrievableId [RetrievableId] of the new [BooleanVectorDescriptor]. + * @param field [Schema.Field] the new [BooleanVectorDescriptor] belongs to. + * @return Copy of this [BooleanVectorDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, BooleanVectorDescriptor>?) = BooleanVectorDescriptor(id, retrievableId, Value.BooleanVector(this.vector.value.copyOf()), field) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/DoubleVectorDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/DoubleVectorDescriptor.kt index a5c1f0288..77fb30c3b 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/DoubleVectorDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/DoubleVectorDescriptor.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.core.model.descriptor.vector import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.vector.VectorDescriptor.Companion.VECTOR_ATTRIBUTE_NAME import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -13,19 +14,29 @@ import java.util.* * * @author Luca Rossetto * @author Ralph Gasser - * @version 1.1.0 + * @version 1.2.0 */ data class DoubleVectorDescriptor( - override var id: UUID = UUID.randomUUID(), - override var retrievableId: RetrievableId? = null, + override val id: UUID = UUID.randomUUID(), + override val retrievableId: RetrievableId? = null, override val vector: Value.DoubleVector, override val field: Schema.Field<*, DoubleVectorDescriptor>? = null -) : VectorDescriptor { +) : VectorDescriptor { /** * Returns the [Attribute] [List ]of this [DoubleVectorDescriptor]. * * @return [List] of [Attribute] */ override fun layout(): List = listOf(Attribute(VECTOR_ATTRIBUTE_NAME, Type.DoubleVector(this.dimensionality))) + + /** + * Returns a copy of this [DoubleVectorDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [DoubleVectorDescriptor]. + * @param retrievableId [RetrievableId] of the new [DoubleVectorDescriptor]. + * @param field [Schema.Field] the new [DoubleVectorDescriptor] belongs to. + * @return Copy of this [DoubleVectorDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, DoubleVectorDescriptor>?) = DoubleVectorDescriptor(id, retrievableId, Value.DoubleVector(this.vector.value.copyOf()), field) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/FloatVectorDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/FloatVectorDescriptor.kt index d1205f529..c6940080a 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/FloatVectorDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/FloatVectorDescriptor.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.core.model.descriptor.vector import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.vector.VectorDescriptor.Companion.VECTOR_ATTRIBUTE_NAME import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -8,25 +9,33 @@ import org.vitrivr.engine.core.model.types.Type import org.vitrivr.engine.core.model.types.Value import java.util.* - /** * A [VectorDescriptor] that uses a [FloatArray]. * * @author Luca Rossetto * @author Ralph Gasser - * @version 1.1.0 + * @version 1.2.0 */ - data class FloatVectorDescriptor( - override var id: UUID = UUID.randomUUID(), - override var retrievableId: RetrievableId? = null, + override val id: UUID = UUID.randomUUID(), + override val retrievableId: RetrievableId? = null, override val vector: Value.FloatVector, override val field: Schema.Field<*, FloatVectorDescriptor>? = null -) : VectorDescriptor { +) : VectorDescriptor { /** * Returns the [Attribute] [List ]of this [FloatVectorDescriptor]. * * @return [List] of [Attribute] */ override fun layout(): List = listOf(Attribute(VECTOR_ATTRIBUTE_NAME, Type.FloatVector(this.dimensionality))) + + /** + * Returns a copy of this [FloatVectorDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [FloatVectorDescriptor]. + * @param retrievableId [RetrievableId] of the new [FloatVectorDescriptor]. + * @param field [Schema.Field] the new [DoubleVectorDescriptor] belongs to. + * @return Copy of this [FloatVectorDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, FloatVectorDescriptor>?) = FloatVectorDescriptor(id, retrievableId, Value.FloatVector(this.vector.value.copyOf()), field) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/IntVectorDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/IntVectorDescriptor.kt index dbea9d171..71b853d1b 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/IntVectorDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/IntVectorDescriptor.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.core.model.descriptor.vector import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.vector.VectorDescriptor.Companion.VECTOR_ATTRIBUTE_NAME import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -13,19 +14,28 @@ import java.util.* * * @author Luca Rossetto * @author Ralph Gasser - * @version 1.1.0 + * @version 1.2.0 */ - data class IntVectorDescriptor( - override var id: UUID = UUID.randomUUID(), - override var retrievableId: RetrievableId? = null, + override val id: UUID = UUID.randomUUID(), + override val retrievableId: RetrievableId? = null, override val vector: Value.IntVector, override val field: Schema.Field<*, IntVectorDescriptor>? = null -) : VectorDescriptor { +) : VectorDescriptor { /** * Returns the [Attribute] [List ]of this [IntVectorDescriptor]. * * @return [List] of [Attribute] */ override fun layout(): List = listOf(Attribute(VECTOR_ATTRIBUTE_NAME, Type.Int)) + + /** + * Returns a copy of this [IntVectorDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [IntVectorDescriptor]. + * @param retrievableId [RetrievableId] of the new [IntVectorDescriptor]. + * @param field [Schema.Field] the new [IntVectorDescriptor] belongs to. + * @return Copy of this [IntVectorDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, IntVectorDescriptor>?) = IntVectorDescriptor(id, retrievableId, Value.IntVector(this.vector.value.copyOf()), field) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/LongVectorDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/LongVectorDescriptor.kt index 825f02264..e290bbd10 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/LongVectorDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/LongVectorDescriptor.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.core.model.descriptor.vector import org.vitrivr.engine.core.model.descriptor.Attribute +import org.vitrivr.engine.core.model.descriptor.DescriptorId import org.vitrivr.engine.core.model.descriptor.vector.VectorDescriptor.Companion.VECTOR_ATTRIBUTE_NAME import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.RetrievableId @@ -13,19 +14,29 @@ import java.util.* * * @author Luca Rossetto * @author Ralph Gasser - * @version 1.1.0 + * @version 1.2.0 */ data class LongVectorDescriptor( - override var id: UUID = UUID.randomUUID(), - override var retrievableId: RetrievableId? = null, + override val id: UUID = UUID.randomUUID(), + override val retrievableId: RetrievableId? = null, override val vector: Value.LongVector, override val field: Schema.Field<*, LongVectorDescriptor>? = null -) : VectorDescriptor { +) : VectorDescriptor { /** * Returns the [Attribute] [List ]of this [LongVectorDescriptor]. * * @return [List] of [Attribute] */ override fun layout(): List = listOf(Attribute(VECTOR_ATTRIBUTE_NAME, Type.Long)) + + /** + * Returns a copy of this [LongVectorDescriptor] with new [RetrievableId] and/or [DescriptorId] + * + * @param id [DescriptorId] of the new [LongVectorDescriptor]. + * @param retrievableId [RetrievableId] of the new [LongVectorDescriptor]. + * @param field [Schema.Field] the new [LongVectorDescriptor] belongs to. + * @return Copy of this [LongVectorDescriptor]. + */ + override fun copy(id: DescriptorId, retrievableId: RetrievableId?, field: Schema.Field<*, LongVectorDescriptor>?) = LongVectorDescriptor(id, retrievableId, Value.LongVector(this.vector.value.copyOf()), field) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/VectorDescriptor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/VectorDescriptor.kt index bb02b8a48..dc45468bb 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/VectorDescriptor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/descriptor/vector/VectorDescriptor.kt @@ -6,13 +6,13 @@ import org.vitrivr.engine.core.model.descriptor.scalar.ScalarDescriptor import org.vitrivr.engine.core.model.types.Value /** - * A [Descriptor] that uses a [List] (vector) of values [T] of some sort. + * A [Descriptor] that uses a [List] (vector) of values [V] of some sort. * * @author Luca Rossetto * @author Ralph Gasser * @version 1.1.0 */ -sealed interface VectorDescriptor> : Descriptor { +sealed interface VectorDescriptor, V : Value.Vector<*>> : Descriptor { companion object { const val VECTOR_ATTRIBUTE_NAME = "vector" } @@ -21,13 +21,13 @@ sealed interface VectorDescriptor> : Descriptor { val dimensionality: Int get() = this.vector.size - /** The [List] of values [T]. */ - val vector: T + /** The [List] of values [V]. */ + val vector: V /** * Returns the fields and its values of this [ScalarDescriptor] as a [Map]. * * @return A [Map] of this [ScalarDescriptor]'s fields (without the IDs). */ - override fun values(): Map = mapOf(VECTOR_ATTRIBUTE_NAME to this.vector) + override fun values(): Map = mapOf(VECTOR_ATTRIBUTE_NAME to this.vector) } \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/Mesh.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/Mesh.kt index dedb2f2b5..a937639be 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/Mesh.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/Mesh.kt @@ -2,6 +2,7 @@ package org.vitrivr.engine.core.model.mesh import org.joml.Vector3f import org.joml.Vector3i +import org.vitrivr.engine.core.model.mesh.Mesh.Face import kotlin.math.sign import kotlin.math.sqrt diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/MinimalBoundingBox.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/MinimalBoundingBox.kt index 6a31a60f7..903be0a18 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/MinimalBoundingBox.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/mesh/MinimalBoundingBox.kt @@ -63,7 +63,6 @@ open class MinimalBoundingBox { * * @param positions List of vertices. */ - @Suppress("unused") constructor(positions: List) { update(positions) } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Analyser.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Analyser.kt index 4a678a740..5007c6ff5 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Analyser.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Analyser.kt @@ -20,7 +20,7 @@ import kotlin.reflect.KClass * @author Ralph Gasser * @version 1.4.0 */ -interface Analyser, D : Descriptor> : ExtractorFactory { +interface Analyser, D : Descriptor<*>> : ExtractorFactory { companion object { diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Schema.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Schema.kt index a0dacb116..1af5176c8 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Schema.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/Schema.kt @@ -35,7 +35,7 @@ typealias FieldName = String open class Schema(val name: String = "vitrivr", val connection: Connection) : Closeable { /** The [List] of [Field]s contained in this [Schema]. */ - private val fields: MutableList, Descriptor>> = mutableListOf() + private val fields: MutableList, Descriptor<*>>> = mutableListOf() /** The [List] of [Exporter]s contained in this [Schema]. */ private val exporters: MutableList = mutableListOf() @@ -55,7 +55,7 @@ open class Schema(val name: String = "vitrivr", val connection: Connection) : Cl * @param indexes List of [IndexConfig]s that can be used to configure indexes on the [Field]. * @return [Field] instance. */ - fun addField(name: String, analyser: Analyser, Descriptor>, parameters: Map = emptyMap(), indexes: List) { + fun addField(name: String, analyser: Analyser, Descriptor<*>>, parameters: Map = emptyMap(), indexes: List) { this.fields.add(Field(name, analyser, parameters, indexes)) } @@ -99,7 +99,7 @@ open class Schema(val name: String = "vitrivr", val connection: Connection) : Cl * * @return Unmodifiable list of [Schema.Field]. */ - fun fields(): List, Descriptor>> = Collections.unmodifiableList(this.fields) + fun fields(): List, Descriptor<*>>> = Collections.unmodifiableList(this.fields) /** * Returns the field at the provided [index]. @@ -155,7 +155,7 @@ open class Schema(val name: String = "vitrivr", val connection: Connection) : Cl * * A [Field] always has a unique name and is backed by an existing [Analyser]. */ - inner class Field, D : Descriptor>( + inner class Field, D : Descriptor<*>>( val fieldName: FieldName, val analyser: Analyser, val parameters: Map = emptyMap(), @@ -238,14 +238,14 @@ open class Schema(val name: String = "vitrivr", val connection: Connection) : Cl * * @return [DescriptorReader] */ - fun getReader(): DescriptorReader = this@Schema.connection.getDescriptorReader(this as Field<*, D>) + fun getReader(): DescriptorReader = this.connection.getDescriptorReader(this as Field<*, D>) /** * Convenience method to generate and return a [DescriptorWriter] for this [Field]. * * @return [DescriptorWriter] */ - fun getWriter(): DescriptorWriter = this@Schema.connection.getDescriptorWriter(this as Field<*, D>) + fun getWriter(): DescriptorWriter = this.connection.getDescriptorWriter(this as Field<*, D>) } /** diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/SchemaManager.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/SchemaManager.kt index d6bfd0ac5..7405f8fb5 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/SchemaManager.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/metamodel/SchemaManager.kt @@ -55,7 +55,7 @@ class SchemaManager { throw IllegalArgumentException("Field names must not have a dot (.) in their name.") } @Suppress("UNCHECKED_CAST") - schema.addField(fieldName, analyser as Analyser, Descriptor>, fieldConfig.parameters, fieldConfig.indexes) + schema.addField(fieldName, analyser as Analyser, Descriptor<*>>, fieldConfig.parameters, fieldConfig.indexes) } config.resolvers.forEach { (resolverName, resolverConfig) -> schema.addResolver(resolverName, (loadServiceForName(resolverConfig.factory) ?: throw IllegalArgumentException("Failed to find resolver factory implementation for '${resolverConfig.factory}'.")).newResolver(schema, resolverConfig.parameters)) diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/AbstractRetrievable.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/AbstractRetrievable.kt index 2d126e9c0..da2a78449 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/AbstractRetrievable.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/AbstractRetrievable.kt @@ -20,7 +20,7 @@ abstract class AbstractRetrievable(override val id: UUID, override val type: Str private val contentList = mutableListOf>() /** A set of [Descriptor]s held by this [AbstractRetrievable]. */ - private val descriptorSet = mutableSetOf() + private val descriptorSet = mutableSetOf>() /** A set of [RetrievableAttribute]s held by this [AbstractRetrievable]. */ private val attributeSet = mutableSetOf() @@ -33,7 +33,7 @@ abstract class AbstractRetrievable(override val id: UUID, override val type: Str get() = Collections.unmodifiableList(this.contentList) /** [Collection] of [Descriptor]s held by this [AbstractRetrievable]. */ - override val descriptors: Collection + override val descriptors: Collection> get() = Collections.unmodifiableSet(this.descriptorSet) /** [Collection] of [RetrievableAttribute]s held by this [AbstractRetrievable]. */ @@ -139,7 +139,7 @@ abstract class AbstractRetrievable(override val id: UUID, override val type: Str * @return True on success, false otherwise. */ @Synchronized - override fun addDescriptor(descriptor: Descriptor): Boolean = this.descriptorSet.add(descriptor) + override fun addDescriptor(descriptor: Descriptor<*>): Boolean = this.descriptorSet.add(descriptor) /** * Removes a [Descriptor] from this [AbstractRetrievable]. @@ -148,7 +148,7 @@ abstract class AbstractRetrievable(override val id: UUID, override val type: Str * @return True on success, false otherwise. */ @Synchronized - override fun removeDescriptor(descriptor: Descriptor): Boolean = this.descriptorSet.remove(descriptor) + override fun removeDescriptor(descriptor: Descriptor<*>): Boolean = this.descriptorSet.remove(descriptor) /** * Adds a [Relationship] to this [AbstractRetrievable]. diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/Retrievable.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/Retrievable.kt index 86cdc765a..e43df8936 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/Retrievable.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/Retrievable.kt @@ -31,7 +31,7 @@ interface Retrievable : Persistable { val content: List> /** The [Descriptor]s held by this [Retrievable]- */ - val descriptors: Collection + val descriptors: Collection> /** The [RetrievableAttribute]s held by this [Retrievable]. */ val attributes: Collection @@ -112,7 +112,7 @@ interface Retrievable : Persistable { * @param descriptor The [Descriptor] to add. * @return True on success, false otherwise. */ - fun addDescriptor(descriptor: Descriptor): Boolean + fun addDescriptor(descriptor: Descriptor<*>): Boolean /** * Removes a [Descriptor] from this [Retrievable]. @@ -120,7 +120,7 @@ interface Retrievable : Persistable { * @param descriptor The [Descriptor] to remove. * @return True on success, false otherwise. */ - fun removeDescriptor(descriptor: Descriptor): Boolean + fun removeDescriptor(descriptor: Descriptor<*>): Boolean /** * Finds all [Descriptor]s held by this [Retrievable] that satisfy the given [Predicate]. @@ -128,7 +128,7 @@ interface Retrievable : Persistable { * @param predicate The [Predicate] to test the [Descriptor]s against. * @return List of matching [Descriptor]s */ - fun findDescriptor(predicate: Predicate): List = this.descriptors.filter { predicate.test(it) } + fun findDescriptor(predicate: Predicate>): List> = this.descriptors.filter { predicate.test(it) } /** * Adds a [Relationship] to this [Retrievable]. diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/attributes/ContentAuthorAttribute.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/attributes/ContentAuthorAttribute.kt new file mode 100644 index 000000000..ebd9b524c --- /dev/null +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/attributes/ContentAuthorAttribute.kt @@ -0,0 +1,42 @@ +package org.vitrivr.engine.core.model.retrievable.attributes + +import org.vitrivr.engine.core.model.content.element.ContentId +import java.util.* +import kotlin.collections.HashMap + +const val CONTENT_AUTHORS_KEY = "contentSources" + +class ContentAuthorAttribute private constructor( + private val authorMap: HashMap>, + private val contentMap: HashMap> +) : MergingRetrievableAttribute { + + constructor(contentId: ContentId, author: String) : this(hashMapOf(contentId to hashSetOf(author)), hashMapOf(author to hashSetOf(contentId))) + + override fun merge(other: MergingRetrievableAttribute): MergingRetrievableAttribute { + val otherAuthorMap = (other as ContentAuthorAttribute).authorMap + for ((contentId, authors) in otherAuthorMap) { + authorMap.computeIfAbsent(contentId) { hashSetOf() }.addAll(authors) + } + + val otherContentMap = other.contentMap + for ((author, contentIds) in otherContentMap) { + contentMap.computeIfAbsent(author) { hashSetOf() }.addAll(contentIds) + } + + return ContentAuthorAttribute(authorMap, contentMap) + } + + fun getAuthors(contentId: ContentId): Set { + return authorMap[contentId] ?: emptySet() + } + + fun getContentIds(author: String): Set { + return contentMap[author] ?: emptySet() + } + + fun getContentIds(authors: Set): Set { + return authors.flatMap { contentMap[it] ?: emptySet() }.toSet() + } + +} \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/attributes/DescriptorAuthorAttribute.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/attributes/DescriptorAuthorAttribute.kt index e76fd62ab..320b98198 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/attributes/DescriptorAuthorAttribute.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/retrievable/attributes/DescriptorAuthorAttribute.kt @@ -26,7 +26,7 @@ class DescriptorAuthorAttribute() : MergingRetrievableAttribute { return this } - fun add(descriptor: Descriptor, author: String) = add(descriptor.id, author) + fun add(descriptor: Descriptor<*>, author: String) = add(descriptor.id, author) @Synchronized fun getAuthor(id: DescriptorId): String? = idToAuthorMap[id] diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/serializer/UUIDSerializer.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/serializer/UUIDSerializer.kt index 8cffbf8cd..cac372a2d 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/serializer/UUIDSerializer.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/model/serializer/UUIDSerializer.kt @@ -5,7 +5,7 @@ import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder -import java.util.UUID +import java.util.* object UUIDSerializer: KSerializer { override val descriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/Extractor.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/Extractor.kt index c666853da..6cabf3502 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/Extractor.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/Extractor.kt @@ -18,7 +18,7 @@ import org.vitrivr.engine.core.operators.Operator * @author Ralph Gasser * @version 1.2.0 */ -interface Extractor, D : Descriptor> : Operator.Unary { +interface Extractor, D : Descriptor<*>> : Operator.Unary { /** The [Schema.Field] populated by this [Extractor]. */ val field: Schema.Field? diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/ExtractorFactory.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/ExtractorFactory.kt index 8e2f888fc..b9f4852f7 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/ExtractorFactory.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/ingest/ExtractorFactory.kt @@ -13,7 +13,7 @@ import org.vitrivr.engine.core.operators.Operator * @author Ralph Gasser * @version 1.1.0 */ -interface ExtractorFactory, D : Descriptor> { +interface ExtractorFactory, D : Descriptor<*>> { /** * Creates a new [Extractor] instance from this [ExtractorFactory]. * diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/persistence/PersistingSink.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/persistence/PersistingSink.kt index 5ce61ff38..44772d8c6 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/persistence/PersistingSink.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/persistence/PersistingSink.kt @@ -31,7 +31,7 @@ class PersistingSink(override val input: Operator, val context: Ind } /** A [HashMap] of cached [DescriptorWriter] instances. */ - private val descriptorWriters = HashMap,DescriptorWriter>() + private val descriptorWriters = HashMap, DescriptorWriter>>() /** * Converts this [PersistingSink] to a [Flow] @@ -57,7 +57,7 @@ class PersistingSink(override val input: Operator, val context: Ind /* Collection all entites that should be persisted. */ val retrievables = mutableSetOf() val relationships = mutableSetOf() - val descriptors = mutableMapOf, MutableSet>() + val descriptors = mutableMapOf, MutableSet>>() collect(retrievable, Triple(retrievables, relationships, descriptors)) /* Write entities to database. */ @@ -65,18 +65,20 @@ class PersistingSink(override val input: Operator, val context: Ind this.writer.addAll(retrievables) this.writer.connectAll(relationships) for ((f, d) in descriptors) { - val writer = f.let { field -> this.descriptorWriters.computeIfAbsent(field) { it.getWriter() } } as? DescriptorWriter + val writer = f.let { field -> this.descriptorWriters.computeIfAbsent(field) { it.getWriter() } } as? DescriptorWriter> if (writer?.addAll(d) != true) { logger.error { "Failed to persist descriptors for field ${f.fieldName}." } } } } + + logger.debug { "Persisted ${retrievables.size} retrievables, ${relationships.size} relationships and ${descriptors.values.sumOf { it.size }} descriptors." } } /** * Collects all [Retrievable]s, [Relationship]s and [Descriptor]s that are reachable from the given [Retrievable] and should be persisted.s */ - private fun collect(retrievable: Retrievable, into: Triple, MutableSet, MutableMap, MutableSet>>) { + private fun collect(retrievable: Retrievable, into: Triple, MutableSet, MutableMap, MutableSet>>>) { if (retrievable.transient) return /* Add retrievable. */ diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/Retriever.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/Retriever.kt index 56f0df77d..9167786e1 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/Retriever.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/Retriever.kt @@ -14,7 +14,7 @@ import org.vitrivr.engine.core.operators.Operator * @author Ralph Gasser * @version 1.1.0 */ -interface Retriever, D: Descriptor> : Operator.Nullary { +interface Retriever, D : Descriptor<*>> : Operator.Nullary { /** The [Schema.Field] queried by this [Retriever]. */ val field: Schema.Field diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/StructRetrieverFactory.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/StructRetrieverFactory.kt index 8d7aea7fa..419604825 100755 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/StructRetrieverFactory.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/operators/retrieve/StructRetrieverFactory.kt @@ -9,5 +9,5 @@ import org.vitrivr.engine.core.model.metamodel.Schema */ interface StructRetrieverFactory { - fun >newRetriever(schema: Schema, properties: Map): Retriever + fun > newRetriever(schema: Schema, properties: Map): Retriever> } diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Metadata.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Metadata.kt index 87d41146f..91d34278e 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Metadata.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Metadata.kt @@ -9,6 +9,7 @@ package org.vitrivr.engine.core.source object Metadata { const val METADATA_KEY_IMAGE_WIDTH = "image.width" const val METADATA_KEY_IMAGE_HEIGHT = "image.height" + const val METADATA_KEY_AV_DURATION = "av.duration" const val METADATA_KEY_VIDEO_FPS = "video.fps" const val METADATA_KEY_AUDIO_CHANNELS = "audio.channels" const val METADATA_KEY_AUDIO_SAMPLERATE = "audio.samplerate" diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Source.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Source.kt index 59918e4c7..8d0c488b2 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Source.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/Source.kt @@ -52,6 +52,14 @@ interface Source { */ fun height(): Int? = this.metadata[Metadata.METADATA_KEY_IMAGE_HEIGHT] as? Int + /** + * Duration of the [Source] in milliseconds (if applicable and available). + * + * Only applicable for [MediaType.VIDEO] and [MediaType.AUDIO]. + * @return [Long] + */ + fun duration(): Long? = this.metadata[Metadata.METADATA_KEY_AV_DURATION] as? Long + /** * Frames per second (FPS) of the [Source] in pixels (if applicable and available). * diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/file/MimeType.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/file/MimeType.kt index 5f435018d..5669a31bc 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/file/MimeType.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/source/file/MimeType.kt @@ -3,7 +3,6 @@ package org.vitrivr.engine.core.source.file import org.vitrivr.engine.core.source.MediaType import java.io.File import java.nio.file.Path -import kotlin.enums.EnumEntries /** * A range of known [MimeType]s used for internal conversion. diff --git a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/util/math/ScoringFunctions.kt b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/util/math/ScoringFunctions.kt index 463b2ea0a..faf5a316e 100644 --- a/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/util/math/ScoringFunctions.kt +++ b/vitrivr-engine-core/src/main/kotlin/org/vitrivr/engine/core/util/math/ScoringFunctions.kt @@ -3,7 +3,6 @@ package org.vitrivr.engine.core.util.math import org.vitrivr.engine.core.model.retrievable.Retrieved import org.vitrivr.engine.core.model.retrievable.attributes.DistanceAttribute import org.vitrivr.engine.core.model.retrievable.attributes.ScoreAttribute -import kotlin.math.sqrt /** * A collection of [ScoringFunctions] that can be used to score [Retrieved] object that come with a [DistanceAttribute]. diff --git a/vitrivr-engine-core/src/main/resources/META-INF/services/org.vitrivr.engine.core.database.ConnectionProvider b/vitrivr-engine-core/src/main/resources/META-INF/services/org.vitrivr.engine.core.database.ConnectionProvider new file mode 100644 index 000000000..78e279142 --- /dev/null +++ b/vitrivr-engine-core/src/main/resources/META-INF/services/org.vitrivr.engine.core.database.ConnectionProvider @@ -0,0 +1 @@ +org.vitrivr.engine.core.database.blackhole.BlackholeConnectionProvider \ No newline at end of file diff --git a/vitrivr-engine-core/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser b/vitrivr-engine-core/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser index 736805a45..f3d140936 100644 --- a/vitrivr-engine-core/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser +++ b/vitrivr-engine-core/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser @@ -2,7 +2,4 @@ org.vitrivr.engine.core.features.averagecolor.AverageColor org.vitrivr.engine.core.features.metadata.source.file.FileSourceMetadata org.vitrivr.engine.core.features.metadata.source.exif.ExifMetadata org.vitrivr.engine.core.features.metadata.source.video.VideoSourceMetadata -org.vitrivr.engine.core.features.metadata.temporal.TemporalMetadata -org.vitrivr.engine.core.features.migration.MediaDimensions -org.vitrivr.engine.core.features.migration.VideoFPS -org.vitrivr.engine.core.features.migration.VideoDuration \ No newline at end of file +org.vitrivr.engine.core.features.metadata.temporal.TemporalMetadata \ No newline at end of file diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilderTest.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilderTest.kt index 926a30dbf..c0eac6510 100755 --- a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilderTest.kt +++ b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/config/ingest/IngestionPipelineBuilderTest.kt @@ -6,7 +6,8 @@ import org.junit.jupiter.api.fail import org.vitrivr.engine.core.config.ingest.operation.OperationConfig import org.vitrivr.engine.core.config.ingest.operator.OperatorConfig import org.vitrivr.engine.core.context.IngestionContextConfig -import org.vitrivr.engine.core.database.MockConnection +import org.vitrivr.engine.core.database.blackhole.BlackholeConnection +import org.vitrivr.engine.core.database.blackhole.BlackholeConnectionProvider import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.resolver.impl.DiskResolver @@ -45,7 +46,8 @@ class IngestionPipelineBuilderTest { output = listOf("file") ) - val mockSchema = Schema("test-schema", MockConnection("test-schema")) + val provider = BlackholeConnectionProvider() + val mockSchema = Schema("test-schema", BlackholeConnection("test-schema", provider, true)) mockSchema.addResolver("disk", DiskResolver().newResolver(mockSchema, mapOf("location" to "./thumbnails/testing"))) config.context.schema = mockSchema val testSubject = IngestionPipelineBuilder(config) diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/MockConnection.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/MockConnection.kt deleted file mode 100755 index 6d682b498..000000000 --- a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/MockConnection.kt +++ /dev/null @@ -1,62 +0,0 @@ -package org.vitrivr.engine.core.database - -import org.vitrivr.engine.core.database.descriptor.DescriptorInitializer -import org.vitrivr.engine.core.database.descriptor.DescriptorReader -import org.vitrivr.engine.core.database.descriptor.DescriptorWriter -import org.vitrivr.engine.core.database.retrievable.RetrievableInitializer -import org.vitrivr.engine.core.database.retrievable.RetrievableReader -import org.vitrivr.engine.core.database.retrievable.RetrievableWriter -import org.vitrivr.engine.core.model.descriptor.Descriptor -import org.vitrivr.engine.core.model.metamodel.Schema - -class MockConnection(schemaName: String, provider: ConnectionProvider = MockConnectionProvider(schemaName)) : AbstractConnection(schemaName, provider) { - override val provider: ConnectionProvider - get() = TODO("Not yet implemented") - - override fun withTransaction(action: (Unit) -> T): T { - TODO("Not yet implemented") - } - - override val schemaName: String - get() = TODO("Not yet implemented") - - override fun initialize() { - TODO("Not yet implemented") - } - - override fun truncate() { - TODO("Not yet implemented") - } - - override fun getRetrievableInitializer(): RetrievableInitializer { - TODO("Not yet implemented") - } - - override fun getRetrievableWriter(): RetrievableWriter { - TODO("Not yet implemented") - } - - override fun getRetrievableReader(): RetrievableReader { - TODO("Not yet implemented") - } - - override fun getDescriptorInitializer(field: Schema.Field<*, D>): DescriptorInitializer { - TODO("Not yet implemented") - } - - override fun getDescriptorWriter(field: Schema.Field<*, D>): DescriptorWriter { - TODO("Not yet implemented") - } - - override fun getDescriptorReader(field: Schema.Field<*, D>): DescriptorReader { - TODO("Not yet implemented") - } - - override fun description(): String { - TODO("Not yet implemented") - } - - override fun close() { - TODO("Not yet implemented") - } -} diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/MockConnectionProvider.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/MockConnectionProvider.kt deleted file mode 100755 index 1154af8aa..000000000 --- a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/MockConnectionProvider.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.vitrivr.engine.core.database - -import org.vitrivr.engine.core.database.descriptor.DescriptorProvider -import org.vitrivr.engine.core.model.descriptor.Descriptor -import kotlin.reflect.KClass - -class MockConnectionProvider(override val databaseName: String, override val version: String = "TEST-1") : ConnectionProvider { - override fun openConnection(schemaName: String, parameters: Map): Connection { - TODO("Not yet implemented") - } - - override fun register( - descriptorClass: KClass, - provider: DescriptorProvider<*> - ) { - TODO("Not yet implemented") - } - - override fun obtain(descriptorClass: KClass): DescriptorProvider? { - TODO("Not yet implemented") - } -} diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/DescriptorInitializerTest.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/DescriptorInitializerTest.kt new file mode 100644 index 000000000..f3a7e165f --- /dev/null +++ b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/DescriptorInitializerTest.kt @@ -0,0 +1,8 @@ +package org.vitrivr.engine.core.database.blackhole.descriptor + +import org.junit.jupiter.api.Disabled +import org.vitrivr.engine.core.database.descriptor.AbstractDescriptorInitializerTest + + +@Disabled("Blackhole database connect tests are skipped.") +class DescriptorInitializerTest : AbstractDescriptorInitializerTest("no-schema.json") \ No newline at end of file diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/struct/FileMetadataDescriptorReaderTest.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/struct/FileMetadataDescriptorReaderTest.kt new file mode 100644 index 000000000..8751affb6 --- /dev/null +++ b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/struct/FileMetadataDescriptorReaderTest.kt @@ -0,0 +1,7 @@ +package org.vitrivr.engine.core.database.blackhole.descriptor.struct + +import org.junit.jupiter.api.Disabled +import org.vitrivr.engine.core.database.descriptor.struct.AbstractFileMetadataDescriptorReaderTest + +@Disabled("Blackhole database connect tests are skipped.") +class FileMetadataDescriptorReaderTest : AbstractFileMetadataDescriptorReaderTest("no-schema.json") \ No newline at end of file diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/vector/FloatVectorDescriptorReaderTest.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/vector/FloatVectorDescriptorReaderTest.kt new file mode 100644 index 000000000..85dc3afbe --- /dev/null +++ b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/descriptor/vector/FloatVectorDescriptorReaderTest.kt @@ -0,0 +1,7 @@ +package org.vitrivr.engine.core.database.blackhole.descriptor.vector + +import org.junit.jupiter.api.Disabled +import org.vitrivr.engine.core.database.descriptor.vector.AbstractFloatVectorDescriptorReaderTest + +@Disabled("Blackhole database connect tests are skipped.") +class FloatVectorDescriptorReaderTest : AbstractFloatVectorDescriptorReaderTest("no-schema.json") \ No newline at end of file diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/RetrievableInitializerTest.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/RetrievableInitializerTest.kt new file mode 100644 index 000000000..5440ea8a6 --- /dev/null +++ b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/RetrievableInitializerTest.kt @@ -0,0 +1,8 @@ +package org.vitrivr.engine.core.database.blackhole.retrievable + +import org.junit.jupiter.api.Disabled +import org.vitrivr.engine.core.database.retrievable.AbstractRetrievableWriterTest + + +@Disabled("Blackhole database connect tests are skipped.") +class RetrievableInitializerTest : AbstractRetrievableWriterTest("no-schema.json") \ No newline at end of file diff --git a/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/RetrievableWriterTest.kt b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/RetrievableWriterTest.kt new file mode 100644 index 000000000..a0fff4a1f --- /dev/null +++ b/vitrivr-engine-core/src/test/kotlin/org/vitrivr/engine/core/database/blackhole/retrievable/RetrievableWriterTest.kt @@ -0,0 +1,8 @@ +package org.vitrivr.engine.core.database.blackhole.retrievable + +import org.junit.jupiter.api.Disabled +import org.vitrivr.engine.core.database.retrievable.AbstractRetrievableWriterTest + + +@Disabled("Blackhole database connect tests are skipped.") +class RetrievableWriterTest : AbstractRetrievableWriterTest("no-schema.json") \ No newline at end of file diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/AbstractAggregator.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/AbstractAggregator.kt index cd52d00ec..344a782c2 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/AbstractAggregator.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/AbstractAggregator.kt @@ -7,8 +7,11 @@ import org.vitrivr.engine.core.context.Context import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.retrievable.Ingested import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.attributes.CONTENT_AUTHORS_KEY +import org.vitrivr.engine.core.model.retrievable.attributes.ContentAuthorAttribute import org.vitrivr.engine.core.operators.Operator import org.vitrivr.engine.core.operators.general.Transformer +import java.util.* /** * An abstract [Transformer] implementation for aggregators; aggregators are used to aggregate the content of [Ingested] objects. @@ -16,7 +19,7 @@ import org.vitrivr.engine.core.operators.general.Transformer * @author Ralph Gasser * @version 1.1.0 */ -abstract class AbstractAggregator(override val input: Operator, protected open val context: Context) : Transformer { +abstract class AbstractAggregator(override val input: Operator, protected open val context: Context, override val name: String, val newContent: Boolean = true) : Transformer { /** * Creates a flow for this [AbstractAggregator]. * @@ -25,10 +28,18 @@ abstract class AbstractAggregator(override val input: Operator, * @param scope [CoroutineScope] to use for the [Flow]. */ override fun toFlow(scope: CoroutineScope): Flow = this.input.toFlow(scope).map { + val contentSources = context.getProperty(name, CONTENT_AUTHORS_KEY)?.split(",")?.toSet() + val contentIds = contentSources?.flatMap { source -> it.filteredAttribute(ContentAuthorAttribute::class.java)?.getContentIds(source) ?: emptySet() }?.toSet() + + if (it.content.isNotEmpty()) { - val aggregated = this.aggregate(it.content) - it.clearContent() - aggregated.forEach { c -> it.addContent(c) } + val aggregated = this.aggregate(it.content.filter { c -> contentIds?.contains(c.id) ?: true}) + aggregated.forEach { c -> + if (newContent) { + it.addContent(c) + } + it.addAttribute(ContentAuthorAttribute(c.id, name)) + } it } else { it diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/FirstContentAggregator.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/FirstContentAggregator.kt index bb4d1f746..837b2caf1 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/FirstContentAggregator.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/FirstContentAggregator.kt @@ -30,7 +30,7 @@ class FirstContentAggregator : TransformerFactory { /** * The [Instance] returned by the [FirstContentAggregator] */ - private class Instance(override val input: Operator, context: Context, override val name: String) : AbstractAggregator(input, context) { + private class Instance(override val input: Operator, context: Context, name: String) : AbstractAggregator(input, context, name) { override fun aggregate(content: List>): List> = content.groupBy { it.type }.mapNotNull { (_, elements) -> elements.firstOrNull() } } } diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/LastContentAggregator.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/LastContentAggregator.kt index b50edece5..c63066db2 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/LastContentAggregator.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/LastContentAggregator.kt @@ -30,7 +30,7 @@ class LastContentAggregator : TransformerFactory { /** * The [Instance] returns by the [LastContentAggregator] */ - private class Instance(override val input: Operator, context: Context, override val name: String) : AbstractAggregator(input, context) { + private class Instance(override val input: Operator, context: Context, name: String) : AbstractAggregator(input, context, name) { override fun aggregate(content: List>): List> = content.groupBy { it.type }.mapNotNull { (_, elements) -> elements.lastOrNull() } } } diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/MiddleContentAggregator.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/MiddleContentAggregator.kt index 645b0728c..00b81362f 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/MiddleContentAggregator.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/content/MiddleContentAggregator.kt @@ -30,7 +30,7 @@ class MiddleContentAggregator : TransformerFactory { /** * The [Instance] returns by the [MiddleContentAggregator] */ - private class Instance(override val input: Operator, context: Context, override val name: String) : AbstractAggregator(input, context) { + private class Instance(override val input: Operator, context: Context, name: String) : AbstractAggregator(input, context, name) { override fun aggregate(content: List>): List> = content.groupBy { it.type }.mapNotNull { (_, elements) -> if (elements.isNotEmpty()) { elements[Math.floorDiv(elements.size, 2)] diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/descriptor/VectorDescriptorAggregator.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/descriptor/VectorDescriptorAggregator.kt index 19e5c5a75..79959f87c 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/descriptor/VectorDescriptorAggregator.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/descriptor/VectorDescriptorAggregator.kt @@ -20,11 +20,11 @@ class VectorDescriptorAggregator : TransformerFactory { enum class AggregationStrategy { FIRST { - override fun aggregate(collection: Collection>): VectorDescriptor<*> = + override fun aggregate(collection: Collection>): VectorDescriptor<*, *> = collection.first() }, MEAN { - override fun aggregate(collection: Collection>): VectorDescriptor<*> { + override fun aggregate(collection: Collection>): VectorDescriptor<*, *> { val vec = FloatArray(collection.first().vector.size) @@ -74,7 +74,7 @@ class VectorDescriptorAggregator : TransformerFactory { } }; - abstract fun aggregate(collection: Collection>): VectorDescriptor<*> + abstract fun aggregate(collection: Collection>): VectorDescriptor<*, *> } @@ -103,7 +103,7 @@ class VectorDescriptorAggregator : TransformerFactory { ingested.filteredAttribute(DescriptorAuthorAttribute::class.java)?.getDescriptorIds(authorName) ?: emptySet() val descriptors = - ingested.descriptors.filter { it.id in descriptorIds }.filterIsInstance>() + ingested.descriptors.filter { it.id in descriptorIds }.filterIsInstance>() if (descriptors.isEmpty()) { return@map ingested //nothing to do diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/AverageImageContentAggregator.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/AverageImageContentAggregator.kt index e59a50ff6..9bdedbe98 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/AverageImageContentAggregator.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/AverageImageContentAggregator.kt @@ -40,9 +40,8 @@ class AverageImageContentAggregator : TransformerFactory { /** * The [Instance] returns by the [AverageImageContentAggregator] */ - private class Instance(override val input: Operator, override val context: IndexContext, - override val name: String - ) : AbstractAggregator(input, context) { + private class Instance(override val input: Operator, override val context: IndexContext, name: String + ) : AbstractAggregator(input, context, name) { override fun aggregate(content: List>): List> { /* Filter out images. */ val images = content.filterIsInstance() diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/RepresentativeImageContentAggregator.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/RepresentativeImageContentAggregator.kt index d01fd5a5b..5a9c9c6fe 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/RepresentativeImageContentAggregator.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/aggregators/image/RepresentativeImageContentAggregator.kt @@ -37,9 +37,8 @@ class RepresentativeImageContentAggregator : TransformerFactory { /** * The [Instance] returns by the [RepresentativeImageContentAggregator] */ - private class Instance(override val input: Operator, override val context: IndexContext, - override val name: String - ) : AbstractAggregator(input, context) { + private class Instance(override val input: Operator, override val context: IndexContext, name: String + ) : AbstractAggregator(input, context, name) { override fun aggregate(content: List>): List> { val images = content.filterIsInstance() if (images.isEmpty()) { diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/analyzer/DescriptorFieldMapper.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/analyzer/DescriptorFieldMapper.kt index 70bf0b0b6..72b30bf33 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/analyzer/DescriptorFieldMapper.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/analyzer/DescriptorFieldMapper.kt @@ -26,10 +26,10 @@ import org.vitrivr.engine.core.operators.retrieve.Retriever import java.util.* import kotlin.reflect.KClass -class DescriptorFieldMapper : Analyser, Descriptor> { +class DescriptorFieldMapper : Analyser, Descriptor<*>> { override val contentClasses: Set>> = emptySet() //no content is processed - override val descriptorClass: KClass = Descriptor::class + override val descriptorClass: KClass> = Descriptor::class companion object { const val TYPE_PARAMETER_NAME = "type" @@ -52,7 +52,7 @@ class DescriptorFieldMapper : Analyser, Descriptor> { // } // } - override fun prototype(field: Schema.Field<*, *>): Descriptor { + override fun prototype(field: Schema.Field<*, *>): Descriptor<*> { val descriptorType = DescriptorType.valueOf( field.parameters[TYPE_PARAMETER_NAME] ?: throw IllegalArgumentException("'$TYPE_PARAMETER_NAME' is not defined") @@ -91,10 +91,10 @@ class DescriptorFieldMapper : Analyser, Descriptor> { } override fun newExtractor( - field: Schema.Field, Descriptor>, + field: Schema.Field, Descriptor<*>>, input: Operator, context: IndexContext - ): Extractor, Descriptor> { + ): Extractor, Descriptor<*>> { val authorName = field.parameters[AUTHORNAME_PARAMETER_NAME] ?: throw IllegalArgumentException("'$AUTHORNAME_PARAMETER_NAME' is not defined") return Mapper(input, field, authorName) @@ -102,9 +102,9 @@ class DescriptorFieldMapper : Analyser, Descriptor> { inner class Mapper( override val input: Operator, - override val field: Schema.Field, Descriptor>, + override val field: Schema.Field, Descriptor<*>>, private val authorName: String - ) : Extractor, Descriptor> { + ) : Extractor, Descriptor<*>> { override val analyser = this@DescriptorFieldMapper override val name = field.fieldName override val persisting = true @@ -149,7 +149,7 @@ class DescriptorFieldMapper : Analyser, Descriptor> { } - private fun toFloatDescriptor(descriptor: Descriptor): FloatDescriptor { + private fun toFloatDescriptor(descriptor: Descriptor<*>): FloatDescriptor { field as Schema.Field<*, FloatDescriptor> return when(descriptor) { is FloatDescriptor -> descriptor.copy(field = field) @@ -160,7 +160,7 @@ class DescriptorFieldMapper : Analyser, Descriptor> { } } - private fun toDoubleDescriptor(descriptor: Descriptor): DoubleDescriptor { + private fun toDoubleDescriptor(descriptor: Descriptor<*>): DoubleDescriptor { field as Schema.Field<*, DoubleDescriptor> return when(descriptor) { is FloatDescriptor -> DoubleDescriptor(descriptor.id, descriptor.retrievableId, Value.Double(descriptor.value.value.toDouble()), field) @@ -171,7 +171,7 @@ class DescriptorFieldMapper : Analyser, Descriptor> { } } - private fun toIntDescriptor(descriptor: Descriptor): IntDescriptor { + private fun toIntDescriptor(descriptor: Descriptor<*>): IntDescriptor { field as Schema.Field<*, IntDescriptor> return when(descriptor) { is FloatDescriptor -> IntDescriptor(descriptor.id, descriptor.retrievableId, Value.Int(descriptor.value.value.toInt()), field) @@ -182,7 +182,7 @@ class DescriptorFieldMapper : Analyser, Descriptor> { } } - private fun toFloatVectorDescriptor(descriptor: Descriptor): FloatVectorDescriptor { + private fun toFloatVectorDescriptor(descriptor: Descriptor<*>): FloatVectorDescriptor { field as Schema.Field<*, FloatVectorDescriptor> return when(descriptor) { is FloatVectorDescriptor -> descriptor.copy(field = field) @@ -193,7 +193,7 @@ class DescriptorFieldMapper : Analyser, Descriptor> { } } - private fun toDoubleVectorDescriptor(descriptor: Descriptor): DoubleVectorDescriptor { + private fun toDoubleVectorDescriptor(descriptor: Descriptor<*>): DoubleVectorDescriptor { field as Schema.Field<*, DoubleVectorDescriptor> return when(descriptor) { is FloatVectorDescriptor -> DoubleVectorDescriptor(descriptor.id, descriptor.retrievableId, Value.DoubleVector(DoubleArray(descriptor.vector.size){descriptor.vector.value[it].toDouble()}), field) @@ -204,7 +204,7 @@ class DescriptorFieldMapper : Analyser, Descriptor> { } } - private fun toIntVectorDescriptor(descriptor: Descriptor): IntVectorDescriptor { + private fun toIntVectorDescriptor(descriptor: Descriptor<*>): IntVectorDescriptor { field as Schema.Field<*, IntVectorDescriptor> return when(descriptor) { is FloatVectorDescriptor -> IntVectorDescriptor(descriptor.id, descriptor.retrievableId, Value.IntVector(IntArray(descriptor.vector.size){descriptor.vector.value[it].toInt()}), field) @@ -222,31 +222,31 @@ class DescriptorFieldMapper : Analyser, Descriptor> { name: String, input: Operator, context: IndexContext - ): Extractor, Descriptor> { + ): Extractor, Descriptor<*>> { throw UnsupportedOperationException("DescriptorPersister required backing field") } override fun newRetrieverForQuery( - field: Schema.Field, Descriptor>, + field: Schema.Field, Descriptor<*>>, query: Query, context: QueryContext - ): Retriever, Descriptor> { + ): Retriever, Descriptor<*>> { throw UnsupportedOperationException("DescriptorPersister does not support retrieval") } override fun newRetrieverForContent( - field: Schema.Field, Descriptor>, + field: Schema.Field, Descriptor<*>>, content: Collection>, context: QueryContext - ): Retriever, Descriptor> { + ): Retriever, Descriptor<*>> { throw UnsupportedOperationException("DescriptorPersister does not support retrieval") } override fun newRetrieverForDescriptors( - field: Schema.Field, Descriptor>, - descriptors: Collection, + field: Schema.Field, Descriptor<*>>, + descriptors: Collection>, context: QueryContext - ): Retriever, Descriptor> { + ): Retriever, Descriptor<*>> { throw UnsupportedOperationException("DescriptorPersister does not support retrieval") } } \ No newline at end of file diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/ImageDecoder.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/ImageDecoder.kt index c5ac213fc..cebe055e2 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/ImageDecoder.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/ImageDecoder.kt @@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.mapNotNull import org.vitrivr.engine.core.context.IndexContext import org.vitrivr.engine.core.model.content.element.ImageContent import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.attributes.ContentAuthorAttribute import org.vitrivr.engine.core.model.retrievable.attributes.SourceAttribute import org.vitrivr.engine.core.operators.ingest.Decoder import org.vitrivr.engine.core.operators.ingest.DecoderFactory @@ -54,6 +55,7 @@ class ImageDecoder : DecoderFactory { this.context.contentFactory.newImageContent(ImageIO.read(it)) } sourceRetrievable.addContent(content) + sourceRetrievable.addAttribute(ContentAuthorAttribute(content.id, this.name)) logger.info { "Finished decoding image from source '${source.name}' (${source.sourceId})." } /* Return ingested. */ diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/VideoDecoder.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/VideoDecoder.kt index fe34af502..8e43a07cc 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/VideoDecoder.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/decode/VideoDecoder.kt @@ -20,6 +20,7 @@ import org.vitrivr.engine.core.model.content.element.ImageContent import org.vitrivr.engine.core.model.relationship.Relationship import org.vitrivr.engine.core.model.retrievable.Ingested import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.attributes.ContentAuthorAttribute import org.vitrivr.engine.core.model.retrievable.attributes.SourceAttribute import org.vitrivr.engine.core.model.retrievable.attributes.time.TimeRangeAttribute import org.vitrivr.engine.core.operators.ingest.Decoder @@ -60,7 +61,7 @@ class VideoDecoder : DecoderFactory { private val video: Boolean = true, private val audio: Boolean = true, private val keyFrames: Boolean = false, - private val timeWindowMs: Long = 500L + private val timeWindowMs: Long = 500L, ) : Decoder { /** [KLogger] instance. */ @@ -116,12 +117,13 @@ class VideoDecoder : DecoderFactory { grabber.imageMode = FrameGrabber.ImageMode.COLOR grabber.sampleMode = FrameGrabber.SampleMode.SHORT - logger.info { "Start decoding source ${source.name} (${source.sourceId})" } + logger.info { "Start decoding source ${source.name} (${source.sourceId}): ${sourceRetrievable.id}" } try { grabber.start() /* Extract and enrich source metadata. */ source.metadata[Metadata.METADATA_KEY_VIDEO_FPS] = grabber.videoFrameRate + source.metadata[Metadata.METADATA_KEY_AV_DURATION] = TimeUnit.MICROSECONDS.toMillis(grabber.lengthInTime) source.metadata[Metadata.METADATA_KEY_IMAGE_WIDTH] = grabber.imageWidth source.metadata[Metadata.METADATA_KEY_IMAGE_HEIGHT] = grabber.imageHeight source.metadata[Metadata.METADATA_KEY_AUDIO_CHANNELS] = grabber.audioChannels @@ -178,7 +180,7 @@ class VideoDecoder : DecoderFactory { emit(imageBuffer, audioBuffer, grabber, windowEnd, sourceRetrievable, channel) } - logger.info { "Finished decoding video from source '${source.name}' (${source.sourceId})." } + logger.info { "Finished decoding video from source '${source.name}' (${source.sourceId}): ${sourceRetrievable.id}" } } catch (exception: Exception) { error = true logger.error(exception) { "Failed to decode video from source '${source.name}' (${source.sourceId})." } @@ -188,6 +190,7 @@ class VideoDecoder : DecoderFactory { /* Send source retrievable downstream as a signal that file has been decoded. */ if (!error) { + logger.debug { "Emitting source ${sourceRetrievable.id} as signal that video has been decoded." } channel.send(sourceRetrievable) } } @@ -242,13 +245,18 @@ class VideoDecoder : DecoderFactory { samples.clear() val audio = this.context.contentFactory.newAudioContent(grabber.audioChannels.toShort(), grabber.sampleRate, samples) ingested.addContent(audio) + ingested.addAttribute(ContentAuthorAttribute(audio.id, name)) } /* Prepare and append image content element. */ for (image in emitImage) { - ingested.addContent(this.context.contentFactory.newImageContent(image)) + val imageContent = this.context.contentFactory.newImageContent(image) + ingested.addContent(imageContent) + ingested.addAttribute(ContentAuthorAttribute(imageContent.id, name)) } + logger.debug { "Emitting ingested ${ingested.id} with ${emitImage.size} images and ${emitAudio.size} audio samples: ${ingested.id}" } + /* Emit ingested. */ channel.send(ingested) } diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/segment/DescriptorDistanceSegmenter.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/segment/DescriptorDistanceSegmenter.kt index db5d546c4..f9a210704 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/segment/DescriptorDistanceSegmenter.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/segment/DescriptorDistanceSegmenter.kt @@ -46,7 +46,7 @@ class DescriptorDistanceSegmenter : TransformerFactory { override val name: String ) : Transformer { - private fun compare(comparisonAnchor: Value.Vector<*>, descriptor: VectorDescriptor<*>): Boolean { + private fun compare(comparisonAnchor: Value.Vector<*>, descriptor: VectorDescriptor<*, *>): Boolean { val dist = when (comparisonAnchor) { is Value.FloatVector -> { distance(comparisonAnchor, (descriptor as FloatVectorDescriptor).vector) @@ -74,7 +74,7 @@ class DescriptorDistanceSegmenter : TransformerFactory { ingested.filteredAttribute(DescriptorAuthorAttribute::class.java)?.getDescriptorIds(authorName) ?: emptySet() val descriptors = - ingested.descriptors.filter { it.id in descriptorIds }.filterIsInstance>() + ingested.descriptors.filter { it.id in descriptorIds }.filterIsInstance>() if (descriptors.isEmpty()) { return@collect } diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/transform/DescriptorAsContentTransformer.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/transform/DescriptorAsContentTransformer.kt index a01c8dd1a..4b99ed895 100644 --- a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/transform/DescriptorAsContentTransformer.kt +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/transform/DescriptorAsContentTransformer.kt @@ -10,7 +10,11 @@ import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.content.factory.ContentFactory import org.vitrivr.engine.core.model.descriptor.Descriptor import org.vitrivr.engine.core.model.descriptor.scalar.StringDescriptor +import org.vitrivr.engine.core.model.descriptor.scalar.TextDescriptor +import org.vitrivr.engine.core.model.descriptor.struct.metadata.source.FileSourceMetadataDescriptor +import org.vitrivr.engine.core.model.retrievable.Ingested import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.attributes.ContentAuthorAttribute import org.vitrivr.engine.core.operators.Operator import org.vitrivr.engine.core.operators.general.Transformer import org.vitrivr.engine.core.operators.general.TransformerFactory @@ -30,8 +34,7 @@ class DescriptorAsContentTransformer : TransformerFactory { input = input, name = name, contentFactory = (context as IndexContext).contentFactory, - fieldName = context[name, "field"] ?: throw IllegalArgumentException("The descriptor as content transformer requires a field name."), - removeContent = context[name, "removeContent"]?.toBoolean() ?: false + fieldName = context[name, "field"] ?: throw IllegalArgumentException("The descriptor as content transformer requires a field name.") ) } @@ -39,34 +42,32 @@ class DescriptorAsContentTransformer : TransformerFactory { override val input: Operator, override val name: String, val contentFactory: ContentFactory, - val fieldName : String, - val removeContent: Boolean + val fieldName : String ) : Transformer { override fun toFlow(scope: CoroutineScope): Flow = flow { input.toFlow(scope).collect { retrievable : Retrievable -> - if (removeContent) { - retrievable.clearContent().also { - logger.debug { "Content of retrievable ${retrievable.id} has been removed." } - } - } retrievable.descriptors.filter{ descriptor -> descriptor.field?.fieldName == fieldName }.forEach{ descriptor -> - retrievable.addContent(convertDescriptorToContent(descriptor)).also { - logger.debug { "Descriptor ${descriptor.id} of retrievable ${retrievable.id} has been converted to content element." } - } + val content = convertDescriptorToContent(descriptor) + retrievable.addContent(content) + retrievable.addAttribute(ContentAuthorAttribute(content.id, name)) + logger.debug { "Descriptor ${descriptor.id} of retrievable ${retrievable.id} has been converted to content element." } } emit(retrievable) } } - private fun convertDescriptorToContent(descriptor: Descriptor): ContentElement<*> { + private fun convertDescriptorToContent(descriptor: Descriptor<*>): ContentElement<*> { return when (descriptor) { is StringDescriptor -> contentFactory.newTextContent(descriptor.value.value) + is TextDescriptor -> contentFactory.newTextContent(descriptor.value.value) + is FileSourceMetadataDescriptor -> contentFactory.newTextContent(descriptor.path.value) else -> throw IllegalArgumentException("Descriptor type not supported.") } + } } } \ No newline at end of file diff --git a/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/transform/TemplateTextTransformer.kt b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/transform/TemplateTextTransformer.kt new file mode 100644 index 000000000..896317f43 --- /dev/null +++ b/vitrivr-engine-index/src/main/kotlin/org/vitrivr/engine/index/transform/TemplateTextTransformer.kt @@ -0,0 +1,75 @@ +package org.vitrivr.engine.index.transform + +import io.github.oshai.kotlinlogging.KotlinLogging +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import org.vitrivr.engine.core.context.Context +import org.vitrivr.engine.core.context.IndexContext +import org.vitrivr.engine.core.model.content.ContentType +import org.vitrivr.engine.core.model.content.factory.ContentFactory +import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.attributes.ContentAuthorAttribute +import org.vitrivr.engine.core.operators.Operator +import org.vitrivr.engine.core.operators.general.Transformer +import org.vitrivr.engine.core.operators.general.TransformerFactory + +private val logger = KotlinLogging.logger {} + +private val TEMPLATE_REGEX = "\\$\\{([^}]+)\\}".toRegex() +private const val DEFAULT_VALUE = "No content available." + +/** + * A [Transformer] that takes an input template with placeholders and inserts content from fields in their place. + * + * @author Laura Rettig + * @version 1.0.0 + */ +class TemplateTextTransformer : TransformerFactory { + override fun newTransformer(name: String, input: Operator, context: Context): Transformer { + val template = context[name, "template"] ?: throw IllegalArgumentException("The template text transformer requires a template.") + val contentFields = TEMPLATE_REGEX.findAll(template).map { it.groupValues[1] }.toList() + val defaultValue = context[name, "defaultValue"] ?: DEFAULT_VALUE + return Instance( + input = input, + contentFactory = (context as IndexContext).contentFactory, + template = template, + contentFields = contentFields, + defaultValue = defaultValue, + name = name + ) + } + + private class Instance(override val input: Operator, val contentFactory: ContentFactory, val template: String, val contentFields: List, val defaultValue: String, override val name: String) : Transformer { + override fun toFlow(scope: CoroutineScope): Flow = flow { + input.toFlow(scope).collect { retrievable: Retrievable -> + var mergedContent = template + + contentFields.forEach { fieldName -> + val placeholder = "\${${fieldName}}" + val contentIds = retrievable.filteredAttribute(ContentAuthorAttribute::class.java)?.getContentIds(fieldName) + + val fieldContent = StringBuilder() + contentIds?.forEach{ id -> + retrievable.content.find { + it.id == id && it.type == ContentType.TEXT + }?.content?.let { + fieldContent.append(it) + } + } + + val finalContent = if (fieldContent.isEmpty()) defaultValue else fieldContent.toString() + mergedContent = mergedContent.replace(placeholder, finalContent) + } + + if (mergedContent.isNotBlank()) { + val content = contentFactory.newTextContent(mergedContent.trim()) + retrievable.addContent(content) + retrievable.addAttribute(ContentAuthorAttribute(content.id, name)) + logger.debug { "Contents from retrievable ${retrievable.id} have been merged into a single content element using template." } + } + emit(retrievable) + } + } + } +} \ No newline at end of file diff --git a/vitrivr-engine-index/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.general.TransformerFactory b/vitrivr-engine-index/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.general.TransformerFactory index 1f2768251..1d3813f42 100644 --- a/vitrivr-engine-index/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.general.TransformerFactory +++ b/vitrivr-engine-index/src/main/resources/META-INF/services/org.vitrivr.engine.core.operators.general.TransformerFactory @@ -1,4 +1,5 @@ org.vitrivr.engine.index.transform.ContentSamplingTransformer +org.vitrivr.engine.index.transform.TemplateTextTransformer org.vitrivr.engine.index.transform.DescriptorAsContentTransformer org.vitrivr.engine.index.transform.LabelFilterTransformer diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/Common.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/Common.kt index 911a377cc..2a41b854b 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/Common.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/Common.kt @@ -141,15 +141,17 @@ internal fun Value<*>.toCottontailValue(): PublicValue = when (this) { * * @return [PublicValue] for this [ScalarDescriptor] */ -internal fun ScalarDescriptor<*>.toCottontailValue(): PublicValue = this.value.toCottontailValue() +internal fun ScalarDescriptor<*, *>.toCottontailValue(): PublicValue = this.value.toCottontailValue() /** * Converts this [ScalarDescriptor] to a [Types]. * * @return [Types] for this [ScalarDescriptor] */ -internal fun ScalarDescriptor<*>.toType() = when (this) { +internal fun ScalarDescriptor<*, *>.toType() = when (this) { is BooleanDescriptor -> Types.Boolean + is ByteDescriptor -> Types.Byte + is ShortDescriptor -> Types.Short is IntDescriptor -> Types.Int is LongDescriptor -> Types.Long is FloatDescriptor -> Types.Float @@ -180,14 +182,14 @@ internal fun List>.toCottontailValue(): PublicValue { * * @return [PublicValue] for this [VectorDescriptor] */ -internal fun VectorDescriptor<*>.toCottontailValue(): PublicValue = this.vector.toCottontailValue() +internal fun VectorDescriptor<*, *>.toCottontailValue(): PublicValue = this.vector.toCottontailValue() /** * Converts this [VectorDescriptor] to a [Types]. * * @return [Types] for this [VectorDescriptor] */ -internal fun VectorDescriptor<*>.toType() = when (this) { +internal fun VectorDescriptor<*, *>.toType() = when (this) { is BooleanVectorDescriptor -> Types.BooleanVector(this.dimensionality) is IntVectorDescriptor -> Types.IntVector(this.dimensionality) is LongVectorDescriptor -> Types.LongVector(this.dimensionality) diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/AbstractDescriptorReader.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/AbstractDescriptorReader.kt index bf4805ef2..6f4b36ffc 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/AbstractDescriptorReader.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/AbstractDescriptorReader.kt @@ -23,7 +23,7 @@ import java.util.* * @author Ralph Gasser * @version 1.0.1 */ -abstract class AbstractDescriptorReader(final override val field: Schema.Field<*, D>, override val connection: CottontailConnection) : DescriptorReader { +abstract class AbstractDescriptorReader>(final override val field: Schema.Field<*, D>, override val connection: CottontailConnection) : DescriptorReader { /** The [Name.EntityName] used by this [Descriptor]. */ protected val entityName: Name.EntityName = Name.EntityName.create(this.field.schema.name, "${DESCRIPTOR_ENTITY_PREFIX}_${this.field.fieldName.lowercase()}") diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorInitializer.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorInitializer.kt index 3e8727e79..0944bf62d 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorInitializer.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorInitializer.kt @@ -18,7 +18,7 @@ import org.vitrivr.engine.plugin.cottontaildb.* * @author Ralph Gasser * @version 1.1.0 */ -open class CottontailDescriptorInitializer(final override val field: Schema.Field<*, D>, protected val connection: CottontailConnection) : DescriptorInitializer { +open class CottontailDescriptorInitializer>(final override val field: Schema.Field<*, D>, protected val connection: CottontailConnection) : DescriptorInitializer { /** The [Name.EntityName] used by this [Descriptor]. */ protected val entityName: Name.EntityName = Name.EntityName.create(this.field.schema.name, "${DESCRIPTOR_ENTITY_PREFIX}_${this.field.fieldName.lowercase()}") diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorWriter.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorWriter.kt index f62f22a5a..e7527e181 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorWriter.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/CottontailDescriptorWriter.kt @@ -22,7 +22,7 @@ import org.vitrivr.engine.plugin.cottontaildb.* * @author Ralph Gasser * @version 1.1.0 */ -open class CottontailDescriptorWriter(final override val field: Schema.Field<*, D>, override val connection: CottontailConnection) : DescriptorWriter { +open class CottontailDescriptorWriter>(final override val field: Schema.Field<*, D>, override val connection: CottontailConnection) : DescriptorWriter { /** The [Name.EntityName] used by this [Descriptor]. */ protected val entityName: Name.EntityName = Name.EntityName.create(this.field.schema.name, "${DESCRIPTOR_ENTITY_PREFIX}_${this.field.fieldName.lowercase()}") diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorProvider.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorProvider.kt index b27c560c3..9a19546f3 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorProvider.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorProvider.kt @@ -14,8 +14,8 @@ import org.vitrivr.engine.plugin.cottontaildb.descriptors.CottontailDescriptorWr * @author Ralph Gasser * @version 1.1.0 */ -internal object ScalarDescriptorProvider : DescriptorProvider> { - override fun newInitializer(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*>>) = CottontailDescriptorInitializer(field, connection as CottontailConnection) - override fun newReader(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*>>) = ScalarDescriptorReader(field, connection as CottontailConnection) - override fun newWriter(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*>>) = CottontailDescriptorWriter(field, connection as CottontailConnection) +internal object ScalarDescriptorProvider : DescriptorProvider> { + override fun newInitializer(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*, *>>) = CottontailDescriptorInitializer(field, connection as CottontailConnection) + override fun newReader(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*, *>>) = ScalarDescriptorReader(field, connection as CottontailConnection) + override fun newWriter(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*, *>>) = CottontailDescriptorWriter(field, connection as CottontailConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorReader.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorReader.kt index 47cc4cef5..f6c5eab3f 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorReader.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/scalar/ScalarDescriptorReader.kt @@ -23,7 +23,7 @@ import org.vitrivr.engine.plugin.cottontaildb.descriptors.AbstractDescriptorRead * @author Ralph Gasser * @version 1.1.0 */ -class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connection: CottontailConnection) : AbstractDescriptorReader>(field, connection) { +class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*, *>>, connection: CottontailConnection) : AbstractDescriptorReader>(field, connection) { /** Prototype [ScalarDescriptor] used to create new instances. */ private val prototype = this.field.analyser.prototype(this.field) @@ -33,7 +33,7 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * * @param query The [Query] to execute. */ - override fun query(query: Query): Sequence> = when (query) { + override fun query(query: Query): Sequence> = when (query) { is SimpleFulltextQuery -> this.queryFulltext(query) is SimpleBooleanQuery<*> -> this.queryBoolean(query) else -> throw UnsupportedOperationException("The provided query type ${query::class.simpleName} is not supported by this reader.") @@ -45,13 +45,15 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * @param tuple The [Tuple] to convert. * @return The resulting [ScalarDescriptor]. */ - override fun tupleToDescriptor(tuple: Tuple): ScalarDescriptor<*> { + override fun tupleToDescriptor(tuple: Tuple): ScalarDescriptor<*, *> { val retrievableId = tuple.asUuidValue(RETRIEVABLE_ID_COLUMN_NAME)?.value ?: throw IllegalArgumentException("The provided tuple is missing the required field '${RETRIEVABLE_ID_COLUMN_NAME}'.") val descriptorId = tuple.asUuidValue(DESCRIPTOR_ID_COLUMN_NAME)?.value ?: throw IllegalArgumentException("The provided tuple is missing the required field '${DESCRIPTOR_ID_COLUMN_NAME}'.") return when (this.prototype) { is BooleanDescriptor -> BooleanDescriptor(retrievableId, descriptorId, tuple.asBoolean(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) is DoubleDescriptor -> DoubleDescriptor(retrievableId, descriptorId, tuple.asDouble(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) is FloatDescriptor -> FloatDescriptor(retrievableId, descriptorId, tuple.asFloat(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) + is ByteDescriptor -> ByteDescriptor(retrievableId, descriptorId, tuple.asByte(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) + is ShortDescriptor -> ShortDescriptor(retrievableId, descriptorId, tuple.asShort(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) is IntDescriptor -> IntDescriptor(retrievableId, descriptorId, tuple.asInt(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) is LongDescriptor -> LongDescriptor(retrievableId, descriptorId, tuple.asLong(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) is StringDescriptor -> StringDescriptor(retrievableId, descriptorId, tuple.asString(VALUE_ATTRIBUTE_NAME)?.toValue() ?: throw IllegalArgumentException("The provided tuple is missing the required field '$VECTOR_ATTRIBUTE_NAME'.")) @@ -65,7 +67,7 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * @param query The [SimpleFulltextQuery] to execute. * @return [Sequence] of [ScalarDescriptor]s. */ - private fun queryFulltext(query: SimpleFulltextQuery): Sequence> { + private fun queryFulltext(query: SimpleFulltextQuery): Sequence> { val cottontailQuery = org.vitrivr.cottontail.client.language.dql.Query(this.entityName) .select("*") .fulltext(VALUE_ATTRIBUTE_NAME, query.value.value, "score") @@ -86,7 +88,7 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * @param query The [SimpleBooleanQuery] to execute. * @return [Sequence] of [ScalarDescriptor]s. */ - private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> { + private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> { /* Prepare query. */ val cottontailQuery = org.vitrivr.cottontail.client.language.dql.Query(this.entityName) .select(RETRIEVABLE_ID_COLUMN_NAME) diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorProvider.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorProvider.kt index 7629868e8..dc546d8ae 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorProvider.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorProvider.kt @@ -15,8 +15,8 @@ import org.vitrivr.engine.plugin.cottontaildb.descriptors.CottontailDescriptorWr * @author Ralph Gasser * @version 1.1.0 */ -object StructDescriptorProvider : DescriptorProvider { - override fun newInitializer(connection: Connection, field: Schema.Field<*, StructDescriptor>) = CottontailDescriptorInitializer(field, connection as CottontailConnection) - override fun newReader(connection: Connection, field: Schema.Field<*, StructDescriptor>) = StructDescriptorReader(field, connection as CottontailConnection) - override fun newWriter(connection: Connection, field: Schema.Field<*, StructDescriptor>) = CottontailDescriptorWriter(field, connection as CottontailConnection) +object StructDescriptorProvider : DescriptorProvider> { + override fun newInitializer(connection: Connection, field: Schema.Field<*, StructDescriptor<*>>) = CottontailDescriptorInitializer(field, connection as CottontailConnection) + override fun newReader(connection: Connection, field: Schema.Field<*, StructDescriptor<*>>) = StructDescriptorReader(field, connection as CottontailConnection) + override fun newWriter(connection: Connection, field: Schema.Field<*, StructDescriptor<*>>) = CottontailDescriptorWriter(field, connection as CottontailConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorReader.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorReader.kt index 8a2611a1e..232f4f5bd 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorReader.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/struct/StructDescriptorReader.kt @@ -24,7 +24,7 @@ import kotlin.reflect.full.primaryConstructor * @author Ralph Gasser * @version 1.1.0 */ -class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connection: CottontailConnection) : AbstractDescriptorReader(field, connection) { +class StructDescriptorReader(field: Schema.Field<*, StructDescriptor<*>>, connection: CottontailConnection) : AbstractDescriptorReader>(field, connection) { /** An internal [Map] that maps field name to Cottontail DB [Types]. */ private val fieldMap = mutableListOf>>() @@ -41,7 +41,7 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio * @param query The [Query] to execute. * @return [Sequence] of [StructDescriptor]s that match the query. */ - override fun query(query: Query): Sequence = when (query) { + override fun query(query: Query): Sequence> = when (query) { is SimpleFulltextQuery -> this.queryFulltext(query) is SimpleBooleanQuery<*> -> this.queryBoolean(query) else -> throw UnsupportedOperationException("The provided query type ${query::class.simpleName} is not supported by this reader.") @@ -53,7 +53,7 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio * @param tuple The [Tuple] to convert. * @return The resulting [StructDescriptor]. */ - override fun tupleToDescriptor(tuple: Tuple): StructDescriptor { + override fun tupleToDescriptor(tuple: Tuple): StructDescriptor<*> { val constructor = this.field.analyser.descriptorClass.primaryConstructor ?: throw IllegalStateException("Provided type ${this.field.analyser.descriptorClass} does not have a primary constructor.") val valueMap = mutableMapOf>() val parameters: MutableList = mutableListOf( @@ -96,7 +96,7 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio * @param query The [SimpleFulltextQuery] to execute. * @return [Sequence] of [StructDescriptor]s. */ - private fun queryFulltext(query: SimpleFulltextQuery): Sequence { + private fun queryFulltext(query: SimpleFulltextQuery): Sequence> { require(query.attributeName != null) { "Fulltext query on a struct field requires specification of a field's attribute name." } val cottontailQuery = org.vitrivr.cottontail.client.language.dql.Query(this.entityName).select(RETRIEVABLE_ID_COLUMN_NAME).select(DESCRIPTOR_ID_COLUMN_NAME) for ((name, _) in this.fieldMap) { @@ -119,7 +119,7 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio * @param query The [SimpleBooleanQuery] to execute. * @return [Sequence] of [StructDescriptor]s. */ - private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence { + private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> { require(query.attributeName != null) { "Boolean query on a struct field requires specification of a field's attribute name." } val cottontailQuery = org.vitrivr.cottontail.client.language.dql.Query(this.entityName).select(RETRIEVABLE_ID_COLUMN_NAME).select(DESCRIPTOR_ID_COLUMN_NAME) for ((name, _) in this.fieldMap) { diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorProvider.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorProvider.kt index ec87c41e3..76e4bd032 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorProvider.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorProvider.kt @@ -14,8 +14,8 @@ import org.vitrivr.engine.plugin.cottontaildb.descriptors.CottontailDescriptorWr * @author Ralph Gasser * @version 1.0.0 */ -internal object VectorDescriptorProvider : DescriptorProvider> { - override fun newInitializer(connection: Connection, field: Schema.Field<*, VectorDescriptor<*>>) = CottontailDescriptorInitializer(field, connection as CottontailConnection) - override fun newReader(connection: Connection, field: Schema.Field<*, VectorDescriptor<*>>) = VectorDescriptorReader(field, connection as CottontailConnection) - override fun newWriter(connection: Connection, field: Schema.Field<*, VectorDescriptor<*>>) = CottontailDescriptorWriter(field, connection as CottontailConnection) +internal object VectorDescriptorProvider : DescriptorProvider> { + override fun newInitializer(connection: Connection, field: Schema.Field<*, VectorDescriptor<*, *>>) = CottontailDescriptorInitializer(field, connection as CottontailConnection) + override fun newReader(connection: Connection, field: Schema.Field<*, VectorDescriptor<*, *>>) = VectorDescriptorReader(field, connection as CottontailConnection) + override fun newWriter(connection: Connection, field: Schema.Field<*, VectorDescriptor<*, *>>) = CottontailDescriptorWriter(field, connection as CottontailConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorReader.kt b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorReader.kt index 50157301d..6f1610482 100644 --- a/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorReader.kt +++ b/vitrivr-engine-module-cottontaildb/src/main/kotlin/org/vitrivr/engine/plugin/cottontaildb/descriptors/vector/VectorDescriptorReader.kt @@ -20,17 +20,17 @@ import org.vitrivr.engine.plugin.cottontaildb.descriptors.AbstractDescriptorRead * @author Ralph Gasser * @version 1.3.1 */ -internal class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*>>, connection: CottontailConnection) : AbstractDescriptorReader>(field, connection) { +internal class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*, *>>, connection: CottontailConnection) : AbstractDescriptorReader>(field, connection) { /** The [VectorDescriptor] prototype handled by this [VectorDescriptorReader]. */ - private val prototype: VectorDescriptor<*> = this.field.analyser.prototype(this.field) + private val prototype: VectorDescriptor<*, *> = this.field.analyser.prototype(this.field) /** * Executes the provided [Query] and returns a [Sequence] of [Retrieved]s that match it. * * @param query The [Query] to execute. */ - override fun query(query: Query): Sequence> = when (query) { + override fun query(query: Query): Sequence> = when (query) { is ProximityQuery<*> -> queryProximity(query) else -> throw UnsupportedOperationException("Query of typ ${query::class} is not supported by FloatVectorDescriptorReader.") } @@ -54,7 +54,7 @@ internal class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*> * @param tuple The [Tuple] to convert. * @return The resulting [VectorDescriptor]. */ - override fun tupleToDescriptor(tuple: Tuple): VectorDescriptor<*> { + override fun tupleToDescriptor(tuple: Tuple): VectorDescriptor<*, *> { val descriptorId = tuple.asUuidValue(DESCRIPTOR_ID_COLUMN_NAME)?.value ?: throw IllegalArgumentException("The provided tuple is missing the required field '${DESCRIPTOR_ID_COLUMN_NAME}'.") val retrievableId = tuple.asUuidValue(RETRIEVABLE_ID_COLUMN_NAME)?.value @@ -141,7 +141,7 @@ internal class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*> * @param query The [ProximityQuery] to execute. * @return [Sequence] of [VectorDescriptor]s. */ - private fun queryProximity(query: ProximityQuery<*>): Sequence> { + private fun queryProximity(query: ProximityQuery<*>): Sequence> { val cottontailQuery = org.vitrivr.cottontail.client.language.dql.Query(this.entityName) .select(RETRIEVABLE_ID_COLUMN_NAME) .distance( diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringConnection.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringConnection.kt deleted file mode 100644 index 816f80df1..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringConnection.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.vitrivr.engine.module.features.database.string - -import io.github.oshai.kotlinlogging.KLogger -import io.github.oshai.kotlinlogging.KotlinLogging.logger -import org.vitrivr.engine.core.database.AbstractConnection -import org.vitrivr.engine.core.database.retrievable.NoRetrievableInitializer -import org.vitrivr.engine.core.database.retrievable.RetrievableInitializer -import org.vitrivr.engine.core.database.retrievable.RetrievableReader -import org.vitrivr.engine.core.database.retrievable.RetrievableWriter -import org.vitrivr.engine.core.model.Persistable -import org.vitrivr.engine.module.features.database.string.writer.StringRetrievableWriter - - - -/** Defines [KLogger] of the class. */ -internal val LOGGER: KLogger = logger("org.vitrivr.engine.module.database.string.StringConnection") - -class StringConnection(override val provider: StringConnectionProvider, schemaName: String, internal val stringify: (Persistable) -> String) : AbstractConnection(schemaName, provider) { - /** - * [StringConnection] does not support transactions. - */ - override fun withTransaction(action: (Unit) -> T): T { - LOGGER.warn { "Transactions are not supported by the StringConnection." } - return action.invoke(Unit) - } - - override fun getRetrievableInitializer(): RetrievableInitializer = NoRetrievableInitializer() - - override fun getRetrievableWriter(): RetrievableWriter = StringRetrievableWriter(this, provider.targetStream, stringify) - - override fun getRetrievableReader(): RetrievableReader { - TODO("Not yet implemented") - } - - /** - * - */ - override fun description(): String = "" - - override fun close() { - this.provider.targetStream.flush() - this.provider.targetStream.close() - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringConnectionProvider.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringConnectionProvider.kt deleted file mode 100644 index 552a5b86d..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringConnectionProvider.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.engine.module.features.database.string - -import org.vitrivr.engine.core.database.ConnectionProvider -import org.vitrivr.engine.core.database.descriptor.DescriptorProvider -import org.vitrivr.engine.core.model.Persistable -import org.vitrivr.engine.core.model.descriptor.Descriptor -import org.vitrivr.engine.core.model.descriptor.scalar.StringDescriptor -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import java.io.OutputStream -import kotlin.reflect.KClass - -class StringConnectionProvider(internal val targetStream: OutputStream = System.out, val stringify: (Persistable) -> String = { persistable -> persistable.toString() }) : ConnectionProvider { - - override val databaseName = "String" - override val version = "1.0" - - private val registered = HashMap, DescriptorProvider<*>>() - - init { - /* Register all providers known to this CottontailConnection. */ - this.register(FloatVectorDescriptor::class, StringWriterProvider()) - this.register(StringDescriptor::class, StringWriterProvider()) - - } - - override fun openConnection(schemaName: String, parameters: Map): StringConnection = StringConnection(this, schemaName, stringify) - - @Suppress("UNCHECKED_CAST") - override fun register(descriptorClass: KClass, provider: DescriptorProvider<*>) { - require(!this.registered.containsKey(descriptorClass as KClass)) { "Descriptor of class $descriptorClass cannot be registered twice."} - this.registered[descriptorClass] = provider - } - - @Suppress("UNCHECKED_CAST") - override fun obtain(descriptorClass: KClass): DescriptorProvider? = this.registered[descriptorClass as KClass] as DescriptorProvider? -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringWriterProvider.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringWriterProvider.kt deleted file mode 100644 index 67615e2c4..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/StringWriterProvider.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.vitrivr.engine.module.features.database.string - -import org.vitrivr.engine.module.features.database.string.writer.StringDescriptorWriter -import org.vitrivr.engine.core.database.Connection -import org.vitrivr.engine.core.database.descriptor.DescriptorProvider -import org.vitrivr.engine.core.database.descriptor.DescriptorReader -import org.vitrivr.engine.core.database.descriptor.DescriptorWriter -import org.vitrivr.engine.core.database.descriptor.NoDescriptorInitializer -import org.vitrivr.engine.core.model.descriptor.Descriptor -import org.vitrivr.engine.core.model.metamodel.Schema - -class StringWriterProvider : DescriptorProvider { - - override fun newInitializer(connection: Connection, field: Schema.Field<*,D>): NoDescriptorInitializer = NoDescriptorInitializer(field) - - override fun newReader(connection: Connection, field: Schema.Field<*,D>): DescriptorReader { - throw UnsupportedOperationException("StringWriter is append only") - } - - override fun newWriter(connection: Connection, field: Schema.Field<*,D>): DescriptorWriter = StringDescriptorWriter(connection as StringConnection, field) - -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringDescriptorWriter.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringDescriptorWriter.kt deleted file mode 100644 index 66c631056..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringDescriptorWriter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package org.vitrivr.engine.module.features.database.string.writer - -import org.vitrivr.engine.core.database.descriptor.DescriptorWriter -import org.vitrivr.engine.core.model.descriptor.Descriptor -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.module.features.database.string.StringConnection - -class StringDescriptorWriter(connection: StringConnection, override val field: Schema.Field<*,D>) : DescriptorWriter, StringWriter(connection, connection.provider.targetStream, connection.stringify) \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringRetrievableWriter.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringRetrievableWriter.kt deleted file mode 100644 index 4dbed8d2b..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringRetrievableWriter.kt +++ /dev/null @@ -1,26 +0,0 @@ -package org.vitrivr.engine.module.features.database.string.writer - -import org.vitrivr.engine.core.database.retrievable.RetrievableWriter -import org.vitrivr.engine.core.model.Persistable -import org.vitrivr.engine.core.model.relationship.Relationship -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.module.features.database.string.StringConnection -import java.io.OutputStream - -class StringRetrievableWriter(connection: StringConnection, outputStream: OutputStream, stringify: (Persistable) -> String) : StringWriter(connection, outputStream, stringify), RetrievableWriter { - override fun connect(relationship: Relationship): Boolean { - TODO("Not yet implemented") - } - - override fun connectAll(relationships: Iterable): Boolean { - TODO("Not yet implemented") - } - - override fun disconnect(relationship: Relationship): Boolean { - TODO("Not yet implemented") - } - - override fun disconnectAll(relationships: Iterable): Boolean { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringWriter.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringWriter.kt deleted file mode 100644 index 3dea5891c..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/database/string/writer/StringWriter.kt +++ /dev/null @@ -1,49 +0,0 @@ -package org.vitrivr.engine.module.features.database.string.writer - -import org.vitrivr.engine.core.database.Writer -import org.vitrivr.engine.core.model.Persistable -import org.vitrivr.engine.module.features.database.string.StringConnection -import java.io.IOException -import java.io.OutputStream -import java.io.PrintWriter - -open class StringWriter(override val connection: StringConnection, outputStream: OutputStream, private val stringify: (Persistable) -> String) : Writer { - - private val writer = PrintWriter(outputStream) - - private fun write(item: T) { - writer.println(stringify(item)) - } - - override fun add(item: T): Boolean { - return try { - write(item) - writer.flush() - true - } catch (e: IOException) { - false - } - } - - override fun addAll(items: Iterable): Boolean { - return try { - items.forEach { write(it) } - writer.flush() - true - } catch (e: IOException) { - false - } - } - - override fun update(item: T): Boolean { - throw UnsupportedOperationException("StringWriter is append only") - } - - override fun delete(item: T): Boolean { - throw UnsupportedOperationException("StringWriter is append only") - } - - override fun deleteAll(items: Iterable): Boolean { - throw UnsupportedOperationException("StringWriter is append only") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/averagecolorraster/AverageColorRaster.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/averagecolorraster/AverageColorRaster.kt deleted file mode 100644 index e20dc1798..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/averagecolorraster/AverageColorRaster.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.averagecolorraster - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class AverageColorRaster: Analyser, RasterDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = RasterDescriptor::class - override fun prototype(field: Schema.Field<*, *>): RasterDescriptor = - RasterDescriptor(id = UUID.randomUUID(), retrievableId = UUID.randomUUID(), mapOf("hist" to Value.FloatVector(FloatArray(15)), "raster" to Value.FloatVector(FloatArray(64)))) - - override fun newRetrieverForContent(field: Schema.Field, RasterDescriptor>, content: Collection>, context: QueryContext): Retriever, RasterDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, RasterDescriptor>, query: Query, context: QueryContext): Retriever, RasterDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, RasterDescriptor>, input: Operator, context: IndexContext): Extractor, RasterDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, RasterDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/averagecolorraster/RasterDescriptor.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/averagecolorraster/RasterDescriptor.kt deleted file mode 100644 index 486919e89..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/averagecolorraster/RasterDescriptor.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.averagecolorraster - -import org.vitrivr.engine.core.model.descriptor.DescriptorId -import org.vitrivr.engine.core.model.descriptor.Attribute -import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.retrievable.RetrievableId -import org.vitrivr.engine.core.model.types.Type -import org.vitrivr.engine.core.model.types.Value - -/** - * A struct vector descriptor that stores the average color and raster of an image. - * - * @author Ralph Gasser - * @version 1.0.0 - */ -class RasterDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, - values: Map?>, - override val field: Schema.Field<*, RasterDescriptor>? = null -) : MapStructDescriptor(id, retrievableId, LAYOUT, values, field) { - - companion object { - private val LAYOUT = listOf( - Attribute("hist", Type.FloatVector(15)), - Attribute("raster", Type.FloatVector(4)) - ) - } - - /** The histogram vector. */ - val hist: Value.FloatVector by this.values - - /** The raster vector. */ - val raster: Value.FloatVector by this.values -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/ErrorStatus.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/ErrorStatus.kt deleted file mode 100644 index 226adb116..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/ErrorStatus.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.vitrivr.engine.module.features.feature.external - -import kotlinx.serialization.Serializable - -/** - * An [ErrorStatus] as returned by the Feature Extraction Server - * - * @author Rahel Arnold - */ -@Serializable -data class ErrorStatus(val code: Int, val description: String) \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/ExternalAnalyser.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/ExternalAnalyser.kt index 686ad68c8..071d6b01f 100644 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/ExternalAnalyser.kt +++ b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/ExternalAnalyser.kt @@ -27,7 +27,7 @@ import java.util.* * @version 1.2.0 */ -abstract class ExternalAnalyser, U : Descriptor> : Analyser { +abstract class ExternalAnalyser, U : Descriptor<*>> : Analyser { companion object { /** Name of the host parameter */ const val HOST_PARAMETER_NAME = "host" @@ -48,7 +48,7 @@ abstract class ExternalAnalyser, U : Descriptor> : Analyse */ @OptIn(ExperimentalSerializationApi::class) @JvmStatic - protected inline fun httpRequest( + protected inline fun > httpRequest( url: String, requestBody: String, contentType: String = "application/x-www-form-urlencoded", diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/common/ExternalWithFloatVectorDescriptorAnalyser.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/common/ExternalWithFloatVectorDescriptorAnalyser.kt deleted file mode 100644 index 787eb7240..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/external/common/ExternalWithFloatVectorDescriptorAnalyser.kt +++ /dev/null @@ -1,114 +0,0 @@ -package org.vitrivr.engine.module.features.feature.external.common - -import io.github.oshai.kotlinlogging.KLogger -import io.github.oshai.kotlinlogging.KotlinLogging -import kotlinx.serialization.builtins.ListSerializer -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.json.Json -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.content.element.ImageContent -import org.vitrivr.engine.core.model.content.element.TextContent -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.module.features.feature.external.ExternalAnalyser -import java.io.* -import java.net.HttpURLConnection -import java.net.URI -import java.net.URLEncoder -import java.nio.charset.StandardCharsets -import java.util.* - -/** - * Abstract base class for external analyzers that generate [FloatVectorDescriptor] from [ContentElement]. - * - * @param C Type parameter for the [ContentElement] being analyzed. - * - * @author Rahel Arnold - * @version 1.0.0 - */ -abstract class ExternalWithFloatVectorDescriptorAnalyser> : ExternalAnalyser() { - - private val logger: KLogger = KotlinLogging.logger {} - - /** - * Executes an API request to the given [url] with the specified [requestBody] and returns the response as a list of floats. - * - * @param url The URL for the API request. - * @param requestBody The body of the API request. - * @return A list of floats representing the API response. - */ - private fun executeApiRequest(content: ContentElement<*>, url: String): List { - - val base64 = when (content) { - is TextContent -> Base64.getEncoder().encodeToString(content.content.toByteArray(StandardCharsets.UTF_8)) - is ImageContent -> content.toDataUrl() - else -> throw IllegalArgumentException("Unsupported content type") - } - - val requestBody = URLEncoder.encode("data:text/plain;charset=utf-8,$base64", StandardCharsets.UTF_8.toString()) - - // Create an HttpURLConnection - val connection = URI(url).toURL().openConnection() as HttpURLConnection - - try { - // Set up the connection for a POST request - connection.requestMethod = "POST" - connection.doOutput = true - connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") - - logger.debug { "Initialised external API request" } - - // Write the request body to the output stream - val outputStream: OutputStream = connection.outputStream - val writer = BufferedWriter(OutputStreamWriter(outputStream)) - writer.write("data=$requestBody") - writer.flush() - writer.close() - outputStream.close() - - logger.debug { "Wrote request: $requestBody" } - - // Get the response code (optional, but useful for error handling) - val responseCode = connection.responseCode - - logger.debug{"Received response code: $responseCode"} - - // Read the response as a JSON string - val responseJson = if (responseCode == HttpURLConnection.HTTP_OK) { - val inputStream = BufferedReader(InputStreamReader(connection.inputStream)) - val response = inputStream.readLine() - inputStream.close() - logger.trace { "Received $response" } - response - } else { - logger.warn { "Non OK response" } - null - } - - - // Parse the JSON string to List using Gson - return if (responseJson != null) { - try { - Json.decodeFromString(ListSerializer(Float.serializer()), responseJson).map { Value.Float(it) } - } catch (e: Exception) { - e.printStackTrace() - logger.catching(e) - logger.warn { "Exception during json decode. Sending empty list" } - emptyList() - } - } else { - logger.warn { "No response. Sending empty list" } - emptyList() - } - - } catch (e: Exception) { - e.printStackTrace() - logger.catching(e) - logger.error { "An error occurred during external API call, $e" } - } finally { - connection.disconnect() - logger.trace { "Disconnected" } - } - return emptyList() - } -} diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AudioTranscription.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AudioTranscription.kt deleted file mode 100644 index ac4ed61da..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AudioTranscription.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.scalar.StringDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class AudioTranscription : Analyser, StringDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = StringDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = StringDescriptor(id = UUID.randomUUID(), retrievableId = UUID.randomUUID(), value = Value.String("")) - - override fun newRetrieverForContent(field: Schema.Field, StringDescriptor>, content: Collection>, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - override fun newRetrieverForQuery(field: Schema.Field, StringDescriptor>, query: Query, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - override fun newExtractor(field: Schema.Field, StringDescriptor>, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageColorGrid8.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageColorGrid8.kt deleted file mode 100644 index d83590ec8..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageColorGrid8.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class AverageColorGrid8 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(192)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageColorGrid8Reduced15.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageColorGrid8Reduced15.kt deleted file mode 100644 index f0779e2e4..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageColorGrid8Reduced15.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class AverageColorGrid8Reduced15 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(192)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageFuzzyHist.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageFuzzyHist.kt deleted file mode 100644 index 765f50fa7..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageFuzzyHist.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class AverageFuzzyHist : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(15)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageFuzzyHistNormalized.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageFuzzyHistNormalized.kt deleted file mode 100644 index e2ee9aec8..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/AverageFuzzyHistNormalized.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class AverageFuzzyHistNormalized : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(15)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/CLD.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/CLD.kt deleted file mode 100644 index caf1090f5..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/CLD.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class CLD : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(12)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/CLDReduced15.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/CLDReduced15.kt deleted file mode 100644 index e28484d9e..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/CLDReduced15.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class CLDReduced15 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(12)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/ConceptMasksADE20k.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/ConceptMasksADE20k.kt deleted file mode 100644 index d8ea266fe..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/ConceptMasksADE20k.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class ConceptMasksADE20k : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(2048)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantColor.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantColor.kt deleted file mode 100644 index 3815b753b..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantColor.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.scalar.StringDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class DominantColor : Analyser, StringDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = StringDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = StringDescriptor(id = UUID.randomUUID(), retrievableId = UUID.randomUUID(), value = Value.String("")) - - override fun newRetrieverForContent(field: Schema.Field, StringDescriptor>, content: Collection>, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, StringDescriptor>, query: Query, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, StringDescriptor>, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid.kt deleted file mode 100644 index 89c050aad..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class DominantEdgeGrid : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(64)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid16.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid16.kt deleted file mode 100644 index f6cd65a95..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid16.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class DominantEdgeGrid16 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(256)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid8.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid8.kt deleted file mode 100644 index 6c50f83dc..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/DominantEdgeGrid8.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class DominantEdgeGrid8 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(64)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EHD.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EHD.kt deleted file mode 100644 index 6e2ebad55..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EHD.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class EHD : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(80)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EdgeARP88.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EdgeARP88.kt deleted file mode 100644 index 342328fb5..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EdgeARP88.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class EdgeARP88 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(64)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EdgeGrid16.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EdgeGrid16.kt deleted file mode 100644 index 8158b51fa..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/EdgeGrid16.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class EdgeGrid16 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(256)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/HOGMF25k512.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/HOGMF25k512.kt deleted file mode 100644 index f20686f74..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/HOGMF25k512.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class HOGMF25k512 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(512)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/HueHistogram.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/HueHistogram.kt deleted file mode 100644 index 2cf63783f..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/HueHistogram.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class HueHistogram : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(16)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/InceptionResNetV2.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/InceptionResNetV2.kt deleted file mode 100644 index 866516d3c..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/InceptionResNetV2.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class InceptionResNetV2 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(1536)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/MedianColor.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/MedianColor.kt deleted file mode 100644 index 19ed1bf9d..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/MedianColor.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class MedianColor : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(3)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/MedianFuzzyHist.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/MedianFuzzyHist.kt deleted file mode 100644 index 6486f1a74..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/MedianFuzzyHist.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class MedianFuzzyHist : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(15)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/OpenCLIP.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/OpenCLIP.kt deleted file mode 100644 index 5edb01240..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/OpenCLIP.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class OpenCLIP : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(512)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/ProvidedOCR.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/ProvidedOCR.kt deleted file mode 100644 index 382724fd9..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/ProvidedOCR.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.scalar.StringDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class ProvidedOCR : Analyser, StringDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = StringDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = StringDescriptor(id = UUID.randomUUID(), retrievableId = UUID.randomUUID(), value = Value.String("")) - override fun newRetrieverForContent(field: Schema.Field, StringDescriptor>, content: Collection>, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, StringDescriptor>, query: Query, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, StringDescriptor>, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/SURFMF25K512.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/SURFMF25K512.kt deleted file mode 100644 index b1367835a..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/SURFMF25K512.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class SURFMF25K512 : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(512)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/VisualTextCoEmbedding.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/VisualTextCoEmbedding.kt deleted file mode 100644 index eeced2b9f..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/VisualTextCoEmbedding.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class VisualTextCoEmbedding : Analyser, FloatVectorDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = FloatVectorDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), Value.FloatVector(256)) - - override fun newRetrieverForContent(field: Schema.Field, FloatVectorDescriptor>, content: Collection>, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, FloatVectorDescriptor>, query: Query, context: QueryContext): Retriever, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, FloatVectorDescriptor>, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, FloatVectorDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/WhisperASR.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/WhisperASR.kt deleted file mode 100644 index 638bb9a7d..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/migration/WhisperASR.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.engine.module.features.feature.migration - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.descriptor.scalar.StringDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import java.util.* - -class WhisperASR : Analyser, StringDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = StringDescriptor::class - override fun prototype(field: Schema.Field<*, *>) = StringDescriptor(id = UUID.randomUUID(), retrievableId = UUID.randomUUID(), value = Value.String("")) - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForContent(field: Schema.Field, StringDescriptor>, content: Collection>, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, StringDescriptor>, query: Query, context: QueryContext): Retriever, StringDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, StringDescriptor>, input: Operator, context: IndexContext): Extractor, StringDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/skeleton/SkeletonDescriptor.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/skeleton/SkeletonDescriptor.kt deleted file mode 100644 index 4a6231c7c..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/skeleton/SkeletonDescriptor.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.vitrivr.engine.module.features.feature.skeleton - -import org.vitrivr.engine.core.model.descriptor.DescriptorId -import org.vitrivr.engine.core.model.descriptor.Attribute -import org.vitrivr.engine.core.model.descriptor.AttributeName -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.retrievable.RetrievableId -import org.vitrivr.engine.core.model.types.Type -import org.vitrivr.engine.core.model.types.Value - -class SkeletonDescriptor( - override var id: DescriptorId, - override var retrievableId: RetrievableId?, - values: Map?>, - override val field: Schema.Field<*, SkeletonDescriptor>? = null -) : MapStructDescriptor(id, retrievableId, LAYOUT, values, field) { - - companion object { - private val LAYOUT = listOf( - Attribute("person", Type.Int), - Attribute("skeleton", Type.FloatVector(12)), - Attribute("weights", Type.FloatVector(12)) - ) - } - - /** The person index. */ - val person: Value.Int by this.values - - /** The vector describing the skeleton. */ - val skeleton: List by this.values - - /** The vector describing the skeleto weights. */ - val weights: List by this.values - - -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/skeleton/SkeletonPose.kt b/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/skeleton/SkeletonPose.kt deleted file mode 100644 index 9d696cf35..000000000 --- a/vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/skeleton/SkeletonPose.kt +++ /dev/null @@ -1,49 +0,0 @@ -package org.vitrivr.engine.module.features.feature.skeleton - -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.content.element.ContentElement -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever - -/** - * A descriptor used to store a skeleton pose. - * - * @author Ralph Gasser - * @version 1.0.0 - */ -class SkeletonPose : Analyser, SkeletonDescriptor> { - override val contentClasses = setOf(ContentElement::class) - override val descriptorClass = SkeletonDescriptor::class - override fun prototype(field: Schema.Field<*, *>): SkeletonDescriptor = SkeletonDescriptor( - id = java.util.UUID.randomUUID(), - retrievableId = java.util.UUID.randomUUID(), - mapOf( - "person" to Value.Int(0), - "skeleton" to Value.FloatVector(FloatArray(12)), - "weights" to Value.FloatVector(FloatArray(12)) - ) - ) - - override fun newRetrieverForContent(field: Schema.Field, SkeletonDescriptor>, content: Collection>, context: QueryContext): Retriever, SkeletonDescriptor> { - TODO("Not yet implemented") - } - - override fun newRetrieverForQuery(field: Schema.Field, SkeletonDescriptor>, query: Query, context: QueryContext): Retriever, SkeletonDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(field: Schema.Field, SkeletonDescriptor>, input: Operator, context: IndexContext): Extractor, SkeletonDescriptor> { - TODO("Not yet implemented") - } - - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor, SkeletonDescriptor> { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/resources/META-INF/services/org.vitrivr.engine.core.database.ConnectionProvider b/vitrivr-engine-module-features/src/main/resources/META-INF/services/org.vitrivr.engine.core.database.ConnectionProvider deleted file mode 100644 index fef2bf145..000000000 --- a/vitrivr-engine-module-features/src/main/resources/META-INF/services/org.vitrivr.engine.core.database.ConnectionProvider +++ /dev/null @@ -1 +0,0 @@ -org.vitrivr.engine.module.features.database.string.StringConnectionProvider \ No newline at end of file diff --git a/vitrivr-engine-module-features/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser b/vitrivr-engine-module-features/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser index a8c5e73b6..d4ef3f422 100644 --- a/vitrivr-engine-module-features/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser +++ b/vitrivr-engine-module-features/src/main/resources/META-INF/services/org.vitrivr.engine.core.model.metamodel.Analyser @@ -1,29 +1,2 @@ org.vitrivr.engine.module.features.feature.external.implementations.dino.DINO org.vitrivr.engine.module.features.feature.external.implementations.clip.CLIP -org.vitrivr.engine.module.features.feature.migration.WhisperASR -org.vitrivr.engine.module.features.feature.migration.ProvidedOCR -org.vitrivr.engine.module.features.feature.migration.AudioTranscription -org.vitrivr.engine.module.features.feature.skeleton.SkeletonPose -org.vitrivr.engine.module.features.feature.migration.MedianColor -org.vitrivr.engine.module.features.feature.migration.CLD -org.vitrivr.engine.module.features.feature.migration.CLDReduced15 -org.vitrivr.engine.module.features.feature.migration.AverageFuzzyHistNormalized -org.vitrivr.engine.module.features.feature.migration.AverageFuzzyHist -org.vitrivr.engine.module.features.feature.migration.MedianFuzzyHist -org.vitrivr.engine.module.features.feature.migration.HueHistogram -org.vitrivr.engine.module.features.feature.migration.DominantEdgeGrid -org.vitrivr.engine.module.features.feature.migration.EHD -org.vitrivr.engine.module.features.feature.migration.AverageColorGrid8 -org.vitrivr.engine.module.features.feature.migration.AverageColorGrid8Reduced15 -org.vitrivr.engine.module.features.feature.migration.EdgeGrid16 -org.vitrivr.engine.module.features.feature.migration.DominantEdgeGrid16 -org.vitrivr.engine.module.features.feature.migration.VisualTextCoEmbedding -org.vitrivr.engine.module.features.feature.migration.OpenCLIP -org.vitrivr.engine.module.features.feature.migration.HOGMF25k512 -org.vitrivr.engine.module.features.feature.migration.SURFMF25K512 -org.vitrivr.engine.module.features.feature.migration.InceptionResNetV2 -org.vitrivr.engine.module.features.feature.migration.ConceptMasksADE20k -org.vitrivr.engine.module.features.feature.averagecolorraster.AverageColorRaster -org.vitrivr.engine.module.features.feature.migration.EdgeARP88 -org.vitrivr.engine.module.features.feature.migration.DominantColor -org.vitrivr.engine.module.features.feature.migration.DominantEdgeGrid8 \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AbstractApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AbstractApi.kt index 542ff601b..ecd93c32f 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AbstractApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AbstractApi.kt @@ -85,6 +85,47 @@ abstract class AbstractApi(protected val host: String, protected val model null } + fun analyseBatched(input: List): List = runBlocking { + var retriesLeft = retries + outer@ while (retriesLeft > 0) { + /* Start job. */ + val jobStatus = this@AbstractApi.startBatchedJob(input) + if (jobStatus.status == JobState.failed) { + retriesLeft -= 1 + continue + } + + /* Poll for result. */ + var jobResult = this@AbstractApi.pollBatchedJob(jobStatus.id) + inner@ while (jobResult.status != JobState.complete) { + if (jobResult.status == JobState.failed) { + logger.error { "$model job on host $host with ID: ${jobStatus.id} failed." } + retriesLeft -= 1 + continue@outer + } + + logger.debug { "Waiting for $model job completion on host $host with ID ${jobStatus.id}. Current status: ${jobResult.status}" } + delay(this@AbstractApi.pollingIntervalMs) + jobResult = this@AbstractApi.pollBatchedJob(jobStatus.id) + } + + /* Extract results. */ + val result = jobResult.result + if (result == null) { + logger.error { "$model job on host $host with ID: ${jobStatus.id} returned no result." } + retriesLeft -= 1 + continue@outer + } else { + logger.info { "Job result: $result" } + } + + /* Return results. */ + return@runBlocking result + } + throw IllegalStateException("Failed to analyse batched input.") + + } + /** * This method is used to start a job on the API. * @@ -93,6 +134,14 @@ abstract class AbstractApi(protected val host: String, protected val model */ protected abstract suspend fun startJob(input: I): JobStatus + /** + * This method is used to start a batched job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + protected abstract suspend fun startBatchedJob(input: List): JobStatus + /** * This method is used to poll for results of a job on the API. * @@ -100,4 +149,12 @@ abstract class AbstractApi(protected val host: String, protected val model * @return The [JobResult] */ protected abstract suspend fun pollJob(jobId: String): JobResult + + /** + * This method is used to poll for results of a batched job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + protected abstract suspend fun pollBatchedJob(jobId: String): JobResult> } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AsrApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AsrApi.kt index 88b30cb26..2e88e4214 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AsrApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/AsrApi.kt @@ -2,6 +2,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.AutomatedSpeechRecognitionApi import org.openapitools.client.models.AutomatedSpeechRecognitionInput +import org.openapitools.client.models.BatchedAutomatedSpeechRecognitionInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus import org.vitrivr.engine.base.features.external.api.model.JobResult @@ -35,6 +36,22 @@ class AsrApi(host: String, model: String, timeoutMs: Long, pollingIntervalMs: Lo } } + /** + * This method is used to start a batched ASR job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + override suspend fun startBatchedJob(input: List): JobStatus { + logger.debug { "Starting batched ASR job for audio." } + val wrapped = BatchedAutomatedSpeechRecognitionInput(input.map { it.toDataURL() }) + return try { + this.automatedSpeechRecognitionApi.newBatchedJobApiTasksAutomatedSpeechRecognitionBatchedModelJobsPost(this.model, wrapped).body() + } catch (e: Throwable) { + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of an ASR job on the API. * @@ -53,4 +70,23 @@ class AsrApi(host: String, model: String, timeoutMs: Long, pollingIntervalMs: Lo } catch (e: Throwable) { JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched ASR job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult> = try { + this.automatedSpeechRecognitionApi.getBatchedJobResultsApiTasksAutomatedSpeechRecognitionBatchedJobsJobGet(jobId).body().let { result -> + val values = result.result?.map { it.transcript.trim() } + if (!values.isNullOrEmpty()) { + JobResult(result.status, values.map { Value.Text(it) }) + } else { + JobResult(result.status, null) + } + } + } catch (e: Throwable) { + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ConditionalImageCaptioningApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ConditionalImageCaptioningApi.kt index 587f44973..a80d49cd8 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ConditionalImageCaptioningApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ConditionalImageCaptioningApi.kt @@ -1,6 +1,8 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.ConditionalImageCaptioningApi +import org.openapitools.client.infrastructure.map +import org.openapitools.client.models.BatchedConditionalImageCaptioningInput import org.openapitools.client.models.ConditionalImageCaptioningInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus @@ -15,9 +17,20 @@ import org.vitrivr.engine.core.model.types.Value * @author Ralph Gasser * @version 1.0.0 */ -class ConditionalImageCaptioningApi(host: String, model: String, timeoutMs: Long, pollingIntervalMs: Long, retries: Int) : AbstractApi, Value.Text>(host, model, timeoutMs, pollingIntervalMs, retries) { +class ConditionalImageCaptioningApi( + host: String, + model: String, + timeoutMs: Long, + pollingIntervalMs: Long, + retries: Int +) : AbstractApi, Value.Text>(host, model, timeoutMs, pollingIntervalMs, retries) { /** The API used for FES conditional image captioning. */ - private val conditionalImageCaptioningApi by lazy { ConditionalImageCaptioningApi(baseUrl = this.host, httpClientConfig = this.httpClientConfig) } + private val conditionalImageCaptioningApi by lazy { + ConditionalImageCaptioningApi( + baseUrl = this.host, + httpClientConfig = this.httpClientConfig + ) + } /** * This method is used to start a conditional image captioning job on the API. @@ -29,13 +42,40 @@ class ConditionalImageCaptioningApi(host: String, model: String, timeoutMs: Long logger.debug { "Starting conditional image captioning job for image." } val wrapped = ConditionalImageCaptioningInput(input.first.toDataUrl(), input.second.content) return try { - this.conditionalImageCaptioningApi.newJobApiTasksConditionalImageCaptioningModelJobsPost(this.model, wrapped).body() + this.conditionalImageCaptioningApi.newJobApiTasksConditionalImageCaptioningModelJobsPost( + this.model, + wrapped + ).body() } catch (e: Throwable) { logger.error(e) { "Failed to start conditional image captioning job." } JobStatus("unknown", JobState.failed) } } + /** + * This method is used to start a batched conditional image captioning job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + override suspend fun startBatchedJob(input: List>): JobStatus { + logger.debug { "Starting batched conditional image captioning job for images." } + val wrapped = BatchedConditionalImageCaptioningInput(image = input.map { it.first.toDataUrl() }, + text = input.map { it.second.content }) + return try { + val result = + this.conditionalImageCaptioningApi.newBatchedJobApiTasksConditionalImageCaptioningBatchedModelJobsPost( + this.model, + wrapped + ) + return result.takeIf { it.success }?.body() + ?: throw IllegalStateException("Api Error. Status: ${result.response.status}") + } catch (ex: Throwable) { + logger.error(ex) { "Error in startBatchedJob" } + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of a conditional image captioning job on the API. * @@ -43,16 +83,36 @@ class ConditionalImageCaptioningApi(host: String, model: String, timeoutMs: Long * @return The [JobResult] */ override suspend fun pollJob(jobId: String): JobResult = try { - this.conditionalImageCaptioningApi.getJobResultsApiTasksConditionalImageCaptioningJobsJobGet(jobId).body().let { result -> - val value = result.result?.caption?.trim() - if (!value.isNullOrBlank()) { - JobResult(result.status, Value.Text(value)) - } else { - JobResult(result.status, null) + this.conditionalImageCaptioningApi.getJobResultsApiTasksConditionalImageCaptioningJobsJobGet(jobId).body() + .let { result -> + val value = result.result?.caption?.trim() + if (!value.isNullOrBlank()) { + JobResult(result.status, Value.Text(value)) + } else { + JobResult(result.status, null) + } } - } } catch (e: Throwable) { logger.error(e) { "Failed to poll for status of conditional image captioning job." } JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched conditional image captioning job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult> { + this.conditionalImageCaptioningApi.getBatchedJobResultsApiTasksConditionalImageCaptioningBatchedJobsJobGet( + jobId + ).body().let { result -> + val value = result.result?.map { it.caption.trim() } + if (value != null) { + return JobResult(result.status, value.map { Value.Text(it) }) + } else { + return JobResult(result.status, null) + } + } + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/FaceEmbeddingApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/FaceEmbeddingApi.kt index e28e0f1e3..ac80fcdcf 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/FaceEmbeddingApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/FaceEmbeddingApi.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.FaceEmbeddingApi +import org.openapitools.client.models.BatchedFaceEmbeddingInput import org.openapitools.client.models.FaceEmbeddingInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus @@ -36,6 +37,23 @@ class FaceEmbeddingApi(host: String, model: String, timeoutMs: Long, pollingInte } } + /** + * This method is used to start a batched face embedding job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + override suspend fun startBatchedJob(input: List): JobStatus { + val wrapped = BatchedFaceEmbeddingInput(input.map { it.toDataUrl() }) + return try { + logger.debug { "Starting batched face embedding for images." } + this.faceEmbeddingApi.newBatchedJobApiTasksFaceEmbeddingBatchedModelJobsPost(this.model, wrapped).body() + } catch (e: Throwable) { + logger.error(e) { "Failed to start batched face embedding job." } + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of a face embedding job on the API. * @@ -50,4 +68,19 @@ class FaceEmbeddingApi(host: String, model: String, timeoutMs: Long, pollingInte logger.error(e) { "Failed to poll for status of face embedding job." } JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched face embedding job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult> = try { + this.faceEmbeddingApi.getBatchedJobResultsApiTasksFaceEmbeddingBatchedJobsJobGet(jobId).body().let { result -> + JobResult(result.status, result.result?.map { r -> r.embedding.let { e -> Value.FloatVector(FloatArray(e.size) { i -> e[i].toFloat() }) } }) + } + } catch (e: Throwable) { + logger.error(e) { "Failed to poll for status of batched face embedding job." } + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageCaptioningApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageCaptioningApi.kt index 27bf8f295..a2602c5e6 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageCaptioningApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageCaptioningApi.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.ImageCaptioningApi +import org.openapitools.client.models.BatchedImageCaptioningInput import org.openapitools.client.models.ImageCaptioningInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus @@ -35,6 +36,23 @@ class ImageCaptioningApi(host: String, model: String, timeoutMs: Long, pollingIn } } + /** + * This method is used to start a batched image captioning job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + override suspend fun startBatchedJob(input: List): JobStatus { + logger.debug { "Starting batched image captioning job for images." } + val wrapped = BatchedImageCaptioningInput(input.map { it.toDataUrl() }) + return try { + this.imageCaptioningApi.newBatchedJobApiTasksImageCaptioningBatchedModelJobsPost(this.model, wrapped).body() + } catch (e: Throwable) { + logger.error(e) { "Failed to start batched image captioning job." } + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of an image captioning job on the API. * @@ -54,4 +72,21 @@ class ImageCaptioningApi(host: String, model: String, timeoutMs: Long, pollingIn logger.error(e) { "Failed to poll for status of image captioning job." } JobResult(JobState.failed, null) } + + + /** + * This method is used to poll for results of a batched image captioning job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult> = try { + this.imageCaptioningApi.getBatchedJobResultsApiTasksImageCaptioningBatchedJobsJobGet(jobId).body().let { result -> + val values = result.result?.map { Value.Text(it.caption.trim() ?: "") } + JobResult(result.status, values) + } + } catch (e: Throwable) { + logger.error(e) { "Failed to poll for status of batched image captioning job." } + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageEmbeddingApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageEmbeddingApi.kt index 4dbe22ee6..1d5754ef7 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageEmbeddingApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ImageEmbeddingApi.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.ImageEmbeddingApi +import org.openapitools.client.models.BatchedImageEmbeddingInput import org.openapitools.client.models.ImageEmbeddingInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus @@ -36,6 +37,16 @@ class ImageEmbeddingApi(host: String, model: String, timeoutMs: Long, pollingInt } } + override suspend fun startBatchedJob(input: List): JobStatus { + val wrapped = BatchedImageEmbeddingInput(input.map { it.toDataUrl() }) + return try { + logger.debug { "Starting batched image embedding for images." } + this.imageEmbeddingApi.newBatchedJobApiTasksImageEmbeddingBatchedModelJobsPost(this.model, wrapped).body() + } catch (e: Throwable) { + logger.error(e) { "Failed to start batched image embedding job." } + JobStatus("unknown", JobState.failed) + } + } /** * This method is used to poll for results of an image embedding job on the API. * @@ -50,4 +61,19 @@ class ImageEmbeddingApi(host: String, model: String, timeoutMs: Long, pollingInt logger.error(e) { "Failed to poll for status of image embedding job." } JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched image embedding job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult> = try { + this.imageEmbeddingApi.getBatchedJobResultsApiTasksImageEmbeddingBatchedJobsJobGet(jobId).body().let { result -> + JobResult(result.status, result.result?.map { r -> Value.FloatVector(FloatArray(r.embedding.size) { i -> r.embedding[i].toFloat() }) }) + } + } catch (e: Throwable) { + logger.error(e) { "Failed to poll for status of batched image embedding job." } + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ObjectDetectionApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ObjectDetectionApi.kt index 429766f21..0449508ef 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ObjectDetectionApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ObjectDetectionApi.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.ObjectDetectionApi +import org.openapitools.client.models.BatchedObjectDetectionInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus import org.openapitools.client.models.ObjectDetectionInput @@ -36,6 +37,17 @@ class ObjectDetectionApi(host: String, model: String, timeoutMs: Long, pollingIn } } + override suspend fun startBatchedJob(input: List): JobStatus { + logger.debug { "Starting batched object detection job for images." } + val wrapped = BatchedObjectDetectionInput(input.map { it.toDataUrl() }) + return try { + this.objectDetectionApi.newBatchedJobApiTasksObjectDetectionBatchedModelJobsPost(this.model, wrapped).body() + } catch (e: Throwable) { + logger.error(e) { "Failed to start batched object detection job." } + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of an object detection job on the API. * @@ -50,4 +62,19 @@ class ObjectDetectionApi(host: String, model: String, timeoutMs: Long, pollingIn logger.error(e) { "Failed to poll for status of object detection job." } JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched object detection job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult>> = try { + this.objectDetectionApi.getBatchedJobResultsApiTasksObjectDetectionBatchedJobsJobGet(jobId).body().let { result -> + JobResult(result.status, result.result?.map { it.labels.map { Value.String(it.trim()) } }) + } + } catch (e: Throwable) { + logger.error(e) { "Failed to poll for status of batched object detection job." } + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/OcrApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/OcrApi.kt index a6e0291c9..2da3e8109 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/OcrApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/OcrApi.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.OpticalCharacterRecognitionApi +import org.openapitools.client.models.BatchedOpticalCharacterRecognitionInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus import org.openapitools.client.models.OpticalCharacterRecognitionInput @@ -35,6 +36,23 @@ class OcrApi(host: String, model: String, timeoutMs: Long, pollingIntervalMs: Lo } } + /** + * This method is used to start a batched OCR job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + override suspend fun startBatchedJob(input: List): JobStatus { + logger.debug { "Starting batched OCR job for images." } + val wrapped = BatchedOpticalCharacterRecognitionInput(input.map { it.toDataUrl() }) + return try { + this.opticalCharacterRecognitionApi.newBatchedJobApiTasksOpticalCharacterRecognitionBatchedModelJobsPost(this.model, wrapped).body() + } catch (e: Throwable) { + logger.error(e) { "Failed to start batched OCR job." } + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of an OCR job on the API. * @@ -54,4 +72,19 @@ class OcrApi(host: String, model: String, timeoutMs: Long, pollingIntervalMs: Lo logger.error(e) { "Failed to poll for status of OCR job." } JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched OCR job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult> = try { + this.opticalCharacterRecognitionApi.getBatchedJobResultsApiTasksOpticalCharacterRecognitionBatchedJobsJobGet(jobId).body().let { result -> + JobResult(result.status, result.result?.map { Value.Text(it.text.trim()) }) + } + } catch (e: Throwable) { + logger.error(e) { "Failed to poll for status of batched OCR job." } + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/TextEmbeddingApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/TextEmbeddingApi.kt index 1cf22254f..587064745 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/TextEmbeddingApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/TextEmbeddingApi.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.TextEmbeddingApi +import org.openapitools.client.models.BatchedTextEmbeddingInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus import org.openapitools.client.models.TextEmbeddingInput @@ -36,6 +37,23 @@ class TextEmbeddingApi(host: String, model: String, timeoutMs: Long, pollingInte } } + /** + * This method is used to start a batched text embedding job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + override suspend fun startBatchedJob(input: List): JobStatus { + val wrapped = BatchedTextEmbeddingInput(input.map { it.content }) + return try { + logger.debug { "Starting batched text embedding for texts." } + this.textEmbeddingApi.newBatchedJobApiTasksTextEmbeddingBatchedModelJobsPost(this.model, wrapped).body() + } catch (e: Throwable) { + logger.error(e) { "Failed to start batched text embedding job." } + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of an text embedding job on the API. * @@ -50,4 +68,19 @@ class TextEmbeddingApi(host: String, model: String, timeoutMs: Long, pollingInte logger.error(e) { "Failed to poll for status of text embedding job." } JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched text embedding job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult> = try { + this.textEmbeddingApi.getBatchedJobResultsApiTasksTextEmbeddingBatchedJobsJobGet(jobId).body().let { result -> + JobResult(result.status, result.result?.map { r -> Value.FloatVector(FloatArray(r.embedding.size) { i -> r.embedding[i].toFloat() }) }) + } + } catch (e: Throwable) { + logger.error(e) { "Failed to poll for status of batched text embedding job." } + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ZeroShotClassificationApi.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ZeroShotClassificationApi.kt index 0d7c08bad..4edf0646a 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ZeroShotClassificationApi.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/api/ZeroShotClassificationApi.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.base.features.external.api import org.openapitools.client.apis.ZeroShotImageClassificationApi +import org.openapitools.client.models.BatchedZeroShotImageClassificationInput import org.openapitools.client.models.JobState import org.openapitools.client.models.JobStatus import org.openapitools.client.models.ZeroShotImageClassificationInput @@ -36,6 +37,30 @@ class ZeroShotClassificationApi(host: String, model: String, timeoutMs: Long, po } } + /** + * This method is used to start a batched zero shot image classification job on the API. + * + * @param input The input for the job. + * @return The [JobStatus] + */ + override suspend fun startBatchedJob(input: List>>): JobStatus { + logger.debug { "Starting batched zero shot image classification job for images." } + val classes = input.map { it.second }.toSet() + if (classes.size > 1) { + throw IllegalArgumentException("All classes must be the same for batched zero shot image classification.") + } + val wrapped = BatchedZeroShotImageClassificationInput(input.map { it.first.toDataUrl() }, classes.first()) + return try { + this.zeroShotImageClassificationApi.newBatchedJobApiTasksZeroShotImageClassificationBatchedModelJobsPost( + this.model, + wrapped + ).body() + } catch (e: Throwable) { + logger.error(e) { "Failed to start batched zero shot image classification job." } + JobStatus("unknown", JobState.failed) + } + } + /** * This method is used to poll for results of an object detection job on the API. * @@ -50,4 +75,19 @@ class ZeroShotClassificationApi(host: String, model: String, timeoutMs: Long, po logger.error(e) { "Failed to poll for status of object detection job." } JobResult(JobState.failed, null) } + + /** + * This method is used to poll for results of a batched object detection job on the API. + * + * @param jobId The ID of the job to poll. + * @return The [JobResult] + */ + override suspend fun pollBatchedJob(jobId: String): JobResult>> = try { + this.zeroShotImageClassificationApi.getBatchedJobResultsApiTasksZeroShotImageClassificationBatchedJobsJobGet(jobId).body().let { result -> + JobResult(result.status, result.result?.map { it.probabilities.map { Value.Double(it) } }) + } + } catch (e: Throwable) { + logger.error(e) { "Failed to poll for status of batched object detection job." } + JobResult(JobState.failed, null) + } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/ExternalFesAnalyser.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/ExternalFesAnalyser.kt index a2ba4d9b3..c4a649550 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/ExternalFesAnalyser.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/ExternalFesAnalyser.kt @@ -12,7 +12,7 @@ import org.vitrivr.engine.core.model.metamodel.Analyser * @param C The type of the [ContentElement] to analyse. * @param D The type of the [Descriptor] to generate. */ -abstract class ExternalFesAnalyser, D : Descriptor> : Analyser { +abstract class ExternalFesAnalyser, D : Descriptor<*>> : Analyser { companion object { const val HOST_PARAMETER_DEFAULT = "http://localhost:8888/" const val HOST_PARAMETER_NAME = "host" diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/FesExtractor.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/FesExtractor.kt index 5e133ece1..497a8d926 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/FesExtractor.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/common/FesExtractor.kt @@ -7,11 +7,15 @@ import org.vitrivr.engine.base.features.external.common.ExternalFesAnalyser.Comp import org.vitrivr.engine.base.features.external.common.ExternalFesAnalyser.Companion.POLLINGINTERVAL_MS_PARAMETER_NAME import org.vitrivr.engine.base.features.external.common.ExternalFesAnalyser.Companion.RETRIES_PARAMETER_DEFAULT import org.vitrivr.engine.base.features.external.common.ExternalFesAnalyser.Companion.RETRIES_PARAMETER_NAME +import org.vitrivr.engine.base.features.external.common.ExternalFesAnalyser.Companion.TIMEOUT_MS_PARAMETER_DEFAULT +import org.vitrivr.engine.core.features.AbstractBatchedExtractor import org.vitrivr.engine.core.features.AbstractExtractor import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.descriptor.Descriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.attributes.CONTENT_AUTHORS_KEY +import org.vitrivr.engine.core.model.retrievable.attributes.ContentAuthorAttribute import org.vitrivr.engine.core.operators.Operator import org.vitrivr.engine.core.operators.ingest.Extractor @@ -21,17 +25,19 @@ import org.vitrivr.engine.core.operators.ingest.Extractor * @author Fynn Faber * @version 1.1.0 */ -abstract class FesExtractor, D : Descriptor> : AbstractExtractor { +abstract class FesExtractor, D : Descriptor<*>> : AbstractBatchedExtractor { protected val parameters: Map + private val contentSources: Set? constructor( input: Operator, field: Schema.Field, analyser: ExternalFesAnalyser, parameters: Map - ) : super(input, analyser, field) { + ) : super(input, analyser, field, parameters["batchSize"]?.toIntOrNull() ?: 1) { this.parameters = parameters + this.contentSources = parameters[CONTENT_AUTHORS_KEY]?.split(",")?.toSet() } constructor( @@ -39,11 +45,12 @@ abstract class FesExtractor, D : Descriptor> : AbstractExt name: String, analyser: ExternalFesAnalyser, parameters: Map - ) : super(input, analyser, name) { + ) : super(input, analyser, name, parameters["batchSize"]?.toIntOrNull() ?: 1) { this.parameters = parameters + this.contentSources = parameters[CONTENT_AUTHORS_KEY]?.split(",")?.toSet() } - /** Host of the FES API. */ + protected val host: String get() = this.parameters[HOST_PARAMETER_NAME] ?: HOST_PARAMETER_DEFAULT @@ -54,7 +61,7 @@ abstract class FesExtractor, D : Descriptor> : AbstractExt /** */ protected val timeoutMs: Long get() = this.parameters[POLLINGINTERVAL_MS_PARAMETER_NAME]?.toLongOrNull() - ?: POLLINGINTERVAL_MS_PARAMETER_DEFAULT + ?: TIMEOUT_MS_PARAMETER_DEFAULT /** */ protected val pollingIntervalMs: Long @@ -71,7 +78,19 @@ abstract class FesExtractor, D : Descriptor> : AbstractExt * @param retrievable The [Retrievable] to check. * @return True on match, false otherwise, */ - override fun matches(retrievable: Retrievable): Boolean = retrievable.content.any { content -> - this.analyser.contentClasses.any { it.isInstance(content) } + override fun matches(retrievable: Retrievable): Boolean { + val contentIds = this.contentSources?.let { retrievable.filteredAttribute(ContentAuthorAttribute::class.java)?.getContentIds(it) } + return retrievable.content.any { content -> + this.analyser.contentClasses.any { it.isInstance(content) && (contentIds?.contains(content.id) ?: false) } + } + } + + fun filterContent(retrievable: Retrievable): List { + val contentIds = this.contentSources?.let { + retrievable.filteredAttribute(ContentAuthorAttribute::class.java)?.getContentIds(it) + } + return retrievable.content.filter { content -> + this.analyser.contentClasses.any { it.isInstance(content) && (contentIds?.contains(content.id) ?: false) } + }.map { it as C } } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/asr/ASRExtractor.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/asr/ASRExtractor.kt index f676a2e8a..4b62c2c72 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/asr/ASRExtractor.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/asr/ASRExtractor.kt @@ -36,20 +36,21 @@ class ASRExtractor : FesExtractor { /** The [AsrApi] used to perform extraction with. */ private val api = AsrApi(this.host, this.model, this.timeoutMs, this.pollingIntervalMs, this.retries) + /** * Internal method to perform extraction on [Retrievable]. ** - * @param retrievable The [Retrievable] to process. - * @return List of resulting [Descriptor]s. + * @param retrievables The [Retrievable]s to process. + * @return List of resulting [Descriptor]s grouped by [Retrievable]. */ - override fun extract(retrievable: Retrievable): List { - val content = retrievable.content.filterIsInstance() - return content.mapNotNull { audio -> - val result = this.api.analyse(audio) - if (result != null) { - TextDescriptor(UUID.randomUUID(), retrievable.id, result, this.field) - } else { - null + override fun extract(retrievables: List): List> { + val flatResults = this.api.analyseBatched(retrievables.flatMap { this.filterContent(it) }).mapNotNull { result -> TextDescriptor(UUID.randomUUID(), null, result, this.field)} + + var index = 0 + + return retrievables.map { retrievable -> + this.filterContent(retrievable).map { + flatResults[index++].also { TextDescriptor(it.id, retrievable.id, it.value, it.field) } } } } diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaption.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaption.kt index d3821cd3b..74caa9fbc 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaption.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaption.kt @@ -5,9 +5,11 @@ import org.vitrivr.engine.base.features.external.common.ExternalFesAnalyser import org.vitrivr.engine.core.context.IndexContext import org.vitrivr.engine.core.context.QueryContext import org.vitrivr.engine.core.features.fulltext.FulltextRetriever +import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.content.element.ImageContent import org.vitrivr.engine.core.model.content.element.TextContent import org.vitrivr.engine.core.model.descriptor.scalar.TextDescriptor +import org.vitrivr.engine.core.model.metamodel.Analyser import org.vitrivr.engine.core.model.metamodel.Analyser.Companion.merge import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.query.Query @@ -15,6 +17,7 @@ import org.vitrivr.engine.core.model.query.fulltext.SimpleFulltextQuery import org.vitrivr.engine.core.model.retrievable.Retrievable import org.vitrivr.engine.core.model.types.Value import org.vitrivr.engine.core.operators.Operator +import org.vitrivr.engine.core.operators.ingest.Extractor import org.vitrivr.engine.core.operators.retrieve.Retriever import java.util.* @@ -25,11 +28,11 @@ import java.util.* * @author Fynn Faber * @version 1.0.0 */ -class ImageCaption : ExternalFesAnalyser() { +class ImageCaption : ExternalFesAnalyser, TextDescriptor>() { companion object { const val PROMPT_PARAMETER_NAME = "prompt" } - override val contentClasses = setOf(ImageContent::class) + override val contentClasses = setOf(ImageContent::class, TextContent::class) override val descriptorClass = TextDescriptor::class /** @@ -48,7 +51,7 @@ class ImageCaption : ExternalFesAnalyser() { * @param context The [IndexContext] to use with the [ImageCaptionExtractor]. * @return [ImageCaptionExtractor] */ - override fun newExtractor(name: String, input: Operator, context: IndexContext) = ImageCaptionExtractor(input, name, this, context.local[name] ?: emptyMap()) + override fun newExtractor(name: String, input: Operator, context: IndexContext) = TODO("type mismatch") // = ImageCaptionExtractor(input, name, this, emptyMap()) /** * Generates and returns a new [ImageCaptionExtractor] instance for this [ImageCaption]. @@ -58,7 +61,7 @@ class ImageCaption : ExternalFesAnalyser() { * @param context The [IndexContext] to use with the [ImageCaptionExtractor]. * @return [ImageCaptionExtractor] */ - override fun newExtractor(field: Schema.Field, input: Operator, context: IndexContext) = ImageCaptionExtractor(input, field, this, merge(field, context)) + override fun newExtractor(field: Schema.Field, TextDescriptor>, input: Operator, context: IndexContext) = TODO("type mismatch") //ImageCaptionExtractor(input, field, this, merge(field, context) ) /** * Generates and returns a new [FulltextRetriever] instance for this [ExternalFesAnalyser]. @@ -69,7 +72,7 @@ class ImageCaption : ExternalFesAnalyser() { * * @return A new [FulltextRetriever] instance for this [ExternalFesAnalyser] */ - override fun newRetrieverForQuery(field: Schema.Field, query: Query, context: QueryContext): Retriever { + override fun newRetrieverForQuery(field: Schema.Field, TextDescriptor>, query: Query, context: QueryContext): Retriever, TextDescriptor> { require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" } require(query is SimpleFulltextQuery) { "The query is not a fulltext query. This is a programmer's error!" } return FulltextRetriever(field, query, context) @@ -79,11 +82,11 @@ class ImageCaption : ExternalFesAnalyser() { * Generates and returns a new [FulltextRetriever] instance for this [ExternalFesAnalyser]. * * @param field The [Schema.Field] to create an [Retriever] for. - * @param content An array of [ImageContent] elements to use with the [Retriever] + * @param content An array of [ContentElement] elements to use with the [Retriever] * @param context The [QueryContext] to use with the [Retriever] * @return [FulltextRetriever] */ - override fun newRetrieverForContent(field: Schema.Field, content: Collection, context: QueryContext): Retriever { + override fun newRetrieverForContent(field: Schema.Field, TextDescriptor>, content: Collection>, context: QueryContext): Retriever, TextDescriptor> { require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" } /* Prepare query parameters. */ val text = content.filterIsInstance().firstOrNull() ?: throw IllegalArgumentException("No text content found in the provided content.") diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaptionExtractor.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaptionExtractor.kt index 3a2f199c9..b3947c52f 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaptionExtractor.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/caption/ImageCaptionExtractor.kt @@ -1,11 +1,14 @@ package org.vitrivr.engine.base.features.external.implementations.caption +import io.github.oshai.kotlinlogging.KotlinLogging import org.vitrivr.engine.base.features.external.api.ConditionalImageCaptioningApi import org.vitrivr.engine.base.features.external.api.ImageCaptioningApi import org.vitrivr.engine.base.features.external.common.ExternalFesAnalyser import org.vitrivr.engine.base.features.external.common.FesExtractor import org.vitrivr.engine.base.features.external.implementations.caption.ImageCaption.Companion.PROMPT_PARAMETER_NAME +import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.content.element.ImageContent +import org.vitrivr.engine.core.model.content.element.TextContent import org.vitrivr.engine.core.model.content.impl.memory.InMemoryTextContent import org.vitrivr.engine.core.model.descriptor.Descriptor import org.vitrivr.engine.core.model.descriptor.scalar.TextDescriptor @@ -14,6 +17,8 @@ import org.vitrivr.engine.core.model.retrievable.Retrievable import org.vitrivr.engine.core.operators.Operator import java.util.* +val logger = KotlinLogging.logger {} + /** * * @author Ralph Gasser @@ -35,35 +40,70 @@ class ImageCaptionExtractor : FesExtractor { parameters: Map ) : super(input, name, analyser, parameters) + /** The [ImageCaptioningApi] used to perform extraction with. */ private val captioningApi by lazy { ImageCaptioningApi(this.host, this.model, this.timeoutMs, this.pollingIntervalMs, this.retries) } /** The [ConditionalImageCaptioningApi] used to perform extraction with. */ private val conditionalCaptioningApi by lazy { ConditionalImageCaptioningApi(this.host, this.model, this.timeoutMs, this.pollingIntervalMs, this.retries) } - /** - * Internal method to perform extraction on [Retrievable]. - ** - * @param retrievable The [Retrievable] to process. - * @return List of resulting [Descriptor]s. - */ - override fun extract(retrievable: Retrievable): List { - val prompt = this.field?.parameters?.get(PROMPT_PARAMETER_NAME)?.let { InMemoryTextContent(it) } - return retrievable.content.mapNotNull { - if (it is ImageContent) { - val result = if (prompt == null) { - this.captioningApi.analyse(it) - } else { - this.conditionalCaptioningApi.analyse(it to prompt) + private fun makeCaption(imageContent: List, text: List) : List { + val withTextIndices = text.mapIndexedNotNull { index, t -> if (t != null) index to t else null } + val withoutTextIndices = text.mapIndexedNotNull { index, t -> if (t == null) index else null } + + + val withTextResults = if (withTextIndices.isEmpty()) { + emptyList() + } else { + this.conditionalCaptioningApi.analyseBatched(withTextIndices.map { imageContent[it.first] to InMemoryTextContent(it.second) }) + } + val withoutTextResults = if (withoutTextIndices.isEmpty()) { + emptyList() + } else { + this.captioningApi.analyseBatched(withoutTextIndices.map { imageContent[it] }) + } + + // merge results so they are in the same order as the input + val results = mutableListOf() + var withTextIndex = 0 + var withoutTextIndex = 0 + for (i in text.indices) { + if (text[i] != null) { + results.add(TextDescriptor(UUID.randomUUID(),null,withTextResults[withTextIndex++],this.field)) + } else { + results.add(TextDescriptor(UUID.randomUUID(),null,withoutTextResults[withoutTextIndex++])) + } + } + return results + } + + override fun extract(retrievables: List): List> { + + val content = retrievables.map { this.filterContent(it) } + val imageContents = content.map { it.filterIsInstance() } + + val texts : List> = content.map { it.filterIsInstance().map { it.content } }.mapIndexed { index, text -> if (text.isEmpty()) { + List(imageContents[index].size) { this.parameters[PROMPT_PARAMETER_NAME] } + } else { + if (text.size != 1) { + logger.warn { "Text content has more than one element. Only the first element will be used as an image captioning prompt." } } - if (result != null) { - TextDescriptor(UUID.randomUUID(), retrievable.id, result, this.field) - } else { + List(imageContents[index].size) { text.first() } + } + } + + val flatResults = makeCaption(imageContents.flatten(), texts.flatten()) + + var index = 0 + + return retrievables.map { retrievable -> + this.filterContent(retrievable).map { + if (it !is ImageContent) { null + } else{ + flatResults[index++].also { TextDescriptor(it.id, retrievable.id, it.value, it.field) } } - } else { - null - } + }.filterNotNull() } } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/classification/ImageClassificationExtractor.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/classification/ImageClassificationExtractor.kt index d3f9e7dd7..fa86d6914 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/classification/ImageClassificationExtractor.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/classification/ImageClassificationExtractor.kt @@ -7,7 +7,6 @@ import org.vitrivr.engine.base.features.external.implementations.classification. import org.vitrivr.engine.base.features.external.implementations.classification.ImageClassification.Companion.THRESHOLD_PARAMETER_NAME import org.vitrivr.engine.base.features.external.implementations.classification.ImageClassification.Companion.TOPK_PARAMETER_NAME import org.vitrivr.engine.core.model.content.element.ImageContent -import org.vitrivr.engine.core.model.descriptor.Descriptor import org.vitrivr.engine.core.model.descriptor.struct.LabelDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.Retrievable @@ -37,28 +36,40 @@ class ImageClassificationExtractor : FesExtractor ) : super(input, name, analyser, parameters) /** The [ZeroShotClassificationApi] used to perform extraction with. */ - private val api by lazy { ZeroShotClassificationApi(this.host, this.model, this.timeoutMs, this.pollingIntervalMs, this.retries) } + private val api by lazy { + ZeroShotClassificationApi( + this.host, + this.model, + this.timeoutMs, + this.pollingIntervalMs, + this.retries + ) + } + + + override fun extract(retrievables: List): List> { + val classes = this.parameters[CLASSES_PARAMETER_NAME]?.split(",") + ?: throw IllegalArgumentException("No classes provided.") - /** - * Internal method to perform extraction on [Retrievable]. - ** - * @param retrievable The [Retrievable] to process. - * @return List of resulting [Descriptor]s. - */ - override fun extract(retrievable: Retrievable): List { - val classes = this.parameters[CLASSES_PARAMETER_NAME]?.split(",") ?: throw IllegalArgumentException("No classes provided.") val topK = this.parameters[TOPK_PARAMETER_NAME]?.toInt() ?: 1 val threshold = this.parameters[THRESHOLD_PARAMETER_NAME]?.toFloat() ?: 0.0f - return retrievable.content.flatMap { content -> - if (content is ImageContent) { - val result = this.api.analyse(content to classes) - result?.mapIndexed { index, score -> - LabelDescriptor(UUID.randomUUID(), retrievable.id, mapOf("label" to Value.String(classes[index]), "confidence" to score), this.field) - }?.filter { it.confidence.value >= threshold }?.sortedByDescending { it.confidence.value }?.take(topK) - ?: emptyList() - } else { - emptyList() - } + + val flatResults = this.api.analyseBatched( + retrievables.flatMap { + this.filterContent(it).map { it to classes } + }).mapIndexed { idx, result -> + result.mapIndexed { idy, confidence -> + LabelDescriptor( + UUID.randomUUID(), + retrievables[idx].id, + mapOf( + "label" to Value.String(classes[idy]), + "confidence" to Value.Float(confidence.value.toFloat()) + ), + this.field + ) + }.filter { it.confidence.value >= threshold }.sortedByDescending { it.confidence.value }.take(topK) } + return flatResults } } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/dense/DenseEmbeddingExtractor.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/dense/DenseEmbeddingExtractor.kt index 8fdbf5e92..8beb128a9 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/dense/DenseEmbeddingExtractor.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/dense/DenseEmbeddingExtractor.kt @@ -9,6 +9,7 @@ import org.vitrivr.engine.core.model.content.element.ContentElement import org.vitrivr.engine.core.model.content.element.ImageContent import org.vitrivr.engine.core.model.content.element.TextContent import org.vitrivr.engine.core.model.descriptor.Descriptor +import org.vitrivr.engine.core.model.descriptor.scalar.TextDescriptor import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.retrievable.Retrievable @@ -42,22 +43,48 @@ class DenseEmbeddingExtractor : FesExtractor, FloatVectorDescr /** The [AsrApi] used to perform extraction with. */ private val imageApi by lazy { ImageEmbeddingApi(this.host, model, this.timeoutMs, this.pollingIntervalMs, this.retries) } + /** * Internal method to perform extraction on [Retrievable]. ** - * @param retrievable The [Retrievable] to process. - * @return List of resulting [Descriptor]s. + * @param retrievables The [Retrievable]s to process. + * @return List of resulting [Descriptor]s grouped by [Retrievable]. */ - override fun extract(retrievable: Retrievable): List = retrievable.content.mapNotNull { - val result = when (it) { - is ImageContent -> this.imageApi.analyse(it) - is TextContent -> this.textApi.analyse(it) - else -> null + override fun extract(retrievables: List): List> { + val content = retrievables.flatMap { this.filterContent(it) } + val textContent = content.mapIndexed { index, contentElement -> if (contentElement is TextContent) index to contentElement else null }.filterNotNull().toMap() + val imageContent = content.mapIndexed { index, contentElement -> if (contentElement is ImageContent) index to contentElement else null }.filterNotNull().toMap() + + val textResults: List = if (textContent.isNotEmpty()) { + this.textApi.analyseBatched(textContent.map { it.value }) + .map { FloatVectorDescriptor(UUID.randomUUID(), null, it, this.field) } + } else { + emptyList() } - if (result != null) { - FloatVectorDescriptor(UUID.randomUUID(), retrievable.id, result, this.field) + + val imageResults: List = if (imageContent.isNotEmpty()) { + this.imageApi.analyseBatched(imageContent.map { it.value }) + .map { FloatVectorDescriptor(UUID.randomUUID(), null, it, this.field) } } else { - null + emptyList() + } + + + val textResultMap = textContent.keys.zip(textResults).toMap() + val imageResultMap = imageContent.keys.zip(imageResults).toMap() + + return retrievables.indices.map { index -> + val descriptors = mutableListOf() + textResultMap[index]?.let { + + descriptors.add(FloatVectorDescriptor(it.id, retrievables[index].id, it.vector, it.field)) + } + imageResultMap[index]?.let { + descriptors.add(FloatVectorDescriptor(it.id, retrievables[index].id, it.vector, it.field)) + } + descriptors } } + + } \ No newline at end of file diff --git a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/ocr/OCRExtractor.kt b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/ocr/OCRExtractor.kt index f0a70642b..85c19c7a7 100644 --- a/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/ocr/OCRExtractor.kt +++ b/vitrivr-engine-module-fes/src/main/kotlin/org/vitrivr/engine/base/features/external/implementations/ocr/OCRExtractor.kt @@ -36,20 +36,23 @@ class OCRExtractor : FesExtractor { /** The [OcrApi] used to perform extraction with. */ private val api = OcrApi(this.host, this.model, this.timeoutMs, this.pollingIntervalMs, this.retries) + /** * Internal method to perform extraction on [Retrievable]. ** - * @param retrievable The [Retrievable] to process. - * @return List of resulting [Descriptor]s. + * @param retrievables The [Retrievable]s to process. + * @return List of resulting [Descriptor]s grouped by [Retrievable]. */ - override fun extract(retrievable: Retrievable): List { - val content = retrievable.content.filterIsInstance() - return content.mapNotNull { audio -> - val result = this.api.analyse(audio) - if (result != null) { - TextDescriptor(UUID.randomUUID(), retrievable.id, result, this.field) - } else { - null + override fun extract(retrievables: List): List> { + val flatResults = this.api.analyseBatched(retrievables.flatMap { this.filterContent(it) }).mapNotNull { result -> + TextDescriptor(UUID.randomUUID(), null, result, this.field) + } + + var index = 0 + + return retrievables.map { retrievable -> + this.filterContent(retrievable).map { + flatResults[index++].also { TextDescriptor(it.id, retrievable.id, it.value, it.field) } } } } diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlProvider.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlProvider.kt index 25d5fad29..0f92ee58d 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlProvider.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlProvider.kt @@ -7,7 +7,7 @@ import org.vitrivr.engine.core.database.descriptor.DescriptorWriter import org.vitrivr.engine.core.model.descriptor.Descriptor import org.vitrivr.engine.core.model.metamodel.Schema -abstract class AbstractJsonlProvider : DescriptorProvider { +abstract class AbstractJsonlProvider> : DescriptorProvider { override fun newInitializer(connection: Connection, field: Schema.Field<*, D>): DescriptorInitializer = JsonlInitializer( diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlReader.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlReader.kt index 2d7bf6b65..3eff781d5 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlReader.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/AbstractJsonlReader.kt @@ -10,13 +10,11 @@ import org.vitrivr.engine.core.model.query.Query import org.vitrivr.engine.core.model.retrievable.RetrievableId import org.vitrivr.engine.core.model.retrievable.Retrieved import org.vitrivr.engine.database.jsonl.model.AttributeContainerList -import org.vitrivr.engine.database.jsonl.retrievable.JsonlRetrievableReader import java.io.BufferedReader -import java.io.FileReader import java.io.InputStreamReader import kotlin.io.path.inputStream -abstract class AbstractJsonlReader( +abstract class AbstractJsonlReader>( final override val field: Schema.Field<*, D>, final override val connection: JsonlConnection ) : diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnection.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnection.kt index 8cf018bd6..eb5b42fe6 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnection.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnection.kt @@ -48,10 +48,10 @@ class JsonlConnection( companion object { /** The column name of a retrievable ID. */ - const val RETRIEVABLE_ID_COLUMN_NAME = "retrievableId" + const val RETRIEVABLE_ID_COLUMN_NAME = "retrievableid" /** The column name of a descriptor ID. */ - const val DESCRIPTOR_ID_COLUMN_NAME = "descriptorId" + const val DESCRIPTOR_ID_COLUMN_NAME = "descriptorid" } } \ No newline at end of file diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnectionProvider.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnectionProvider.kt index c6fbca90d..8e17a49b3 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnectionProvider.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlConnectionProvider.kt @@ -3,8 +3,8 @@ package org.vitrivr.engine.database.jsonl import org.vitrivr.engine.core.database.AbstractConnectionProvider import org.vitrivr.engine.core.database.Connection import org.vitrivr.engine.core.model.descriptor.scalar.* +import org.vitrivr.engine.core.model.descriptor.struct.AnyMapStructDescriptor import org.vitrivr.engine.core.model.descriptor.struct.LabelDescriptor -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor import org.vitrivr.engine.core.model.descriptor.struct.metadata.MediaDimensionsDescriptor import org.vitrivr.engine.core.model.descriptor.struct.metadata.Rectangle2DMetadataDescriptor import org.vitrivr.engine.core.model.descriptor.struct.metadata.TemporalMetadataDescriptor @@ -17,7 +17,7 @@ import org.vitrivr.engine.database.jsonl.vector.VectorJsonlProvider import java.nio.file.Path -class JsonlConnectionProvider() : AbstractConnectionProvider() { +class JsonlConnectionProvider : AbstractConnectionProvider() { override val databaseName = "JSONL File Connection" override val version = "1.0.0" @@ -53,7 +53,7 @@ class JsonlConnectionProvider() : AbstractConnectionProvider() { this.register(TemporalMetadataDescriptor::class, StructJsonlProvider) this.register(Rectangle2DMetadataDescriptor::class, StructJsonlProvider) this.register(MediaDimensionsDescriptor::class, StructJsonlProvider) - this.register(MapStructDescriptor::class, StructJsonlProvider) + this.register(AnyMapStructDescriptor::class, StructJsonlProvider) } } \ No newline at end of file diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlInitializer.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlInitializer.kt index 68b7a113c..a9c961d0a 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlInitializer.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlInitializer.kt @@ -6,7 +6,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema import java.io.IOException import kotlin.io.path.* -class JsonlInitializer( +class JsonlInitializer>( override val field: Schema.Field<*, D>, connection: JsonlConnection ) : DescriptorInitializer { diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlWriter.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlWriter.kt index 44b5ca44f..9635b9574 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlWriter.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/JsonlWriter.kt @@ -17,7 +17,7 @@ import java.nio.file.StandardOpenOption import kotlin.io.path.writer -class JsonlWriter(override val field: Schema.Field<*, D>, override val connection: JsonlConnection) : +class JsonlWriter>(override val field: Schema.Field<*, D>, override val connection: JsonlConnection) : DescriptorWriter, AutoCloseable { private val writer = connection.getPath(field).writer(Charsets.UTF_8, StandardOpenOption.APPEND) diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlProvider.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlProvider.kt index 5e6e9b95a..960c45367 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlProvider.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlProvider.kt @@ -7,6 +7,6 @@ import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.database.jsonl.AbstractJsonlProvider import org.vitrivr.engine.database.jsonl.JsonlConnection -object ScalarJsonlProvider: AbstractJsonlProvider>() { - override fun newReader(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*>>): DescriptorReader> = ScalarJsonlReader(field, connection as JsonlConnection) +object ScalarJsonlProvider : AbstractJsonlProvider>() { + override fun newReader(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*, *>>): DescriptorReader> = ScalarJsonlReader(field, connection as JsonlConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlReader.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlReader.kt index 3f9eb154b..6403a518b 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlReader.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/scalar/ScalarJsonlReader.kt @@ -3,23 +3,21 @@ package org.vitrivr.engine.database.jsonl.scalar import org.vitrivr.engine.core.model.descriptor.scalar.* import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.query.basics.ComparisonOperator import org.vitrivr.engine.core.model.query.bool.SimpleBooleanQuery import org.vitrivr.engine.core.model.query.fulltext.SimpleFulltextQuery -import org.vitrivr.engine.core.model.retrievable.Retrieved import org.vitrivr.engine.core.model.types.Value import org.vitrivr.engine.database.jsonl.AbstractJsonlReader -import org.vitrivr.engine.database.jsonl.model.AttributeContainerList import org.vitrivr.engine.database.jsonl.JsonlConnection import org.vitrivr.engine.database.jsonl.JsonlConnection.Companion.DESCRIPTOR_ID_COLUMN_NAME import org.vitrivr.engine.database.jsonl.JsonlConnection.Companion.RETRIEVABLE_ID_COLUMN_NAME +import org.vitrivr.engine.database.jsonl.model.AttributeContainerList class ScalarJsonlReader( - field: Schema.Field<*, ScalarDescriptor<*>>, + field: Schema.Field<*, ScalarDescriptor<*, *>>, connection: JsonlConnection -) : AbstractJsonlReader>(field, connection) { +) : AbstractJsonlReader>(field, connection) { - override fun toDescriptor(list: AttributeContainerList): ScalarDescriptor<*> { + override fun toDescriptor(list: AttributeContainerList): ScalarDescriptor<*, *> { val map = list.list.associateBy { it.attribute.name } val retrievableId = (map[DESCRIPTOR_ID_COLUMN_NAME]?.value!!.toValue() as Value.UUIDValue).value @@ -40,14 +38,14 @@ class ScalarJsonlReader( } - override fun query(query: Query): Sequence> = when (query) { + override fun query(query: Query): Sequence> = when (query) { is SimpleFulltextQuery -> this.queryFulltext(query) is SimpleBooleanQuery<*> -> this.queryBoolean(query) else -> throw UnsupportedOperationException("The provided query type ${query::class.simpleName} is not supported by this reader.") } - private fun queryFulltext(fulltextQuery: SimpleFulltextQuery): Sequence> { + private fun queryFulltext(fulltextQuery: SimpleFulltextQuery): Sequence> { val queryString = fulltextQuery.value.value val attributeName = fulltextQuery.attributeName ?: return emptySequence() @@ -58,7 +56,7 @@ class ScalarJsonlReader( } - private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> = + private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> = getAll().filter { descriptor -> query.comparison.compare(descriptor.value, query.value) } diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlProvider.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlProvider.kt index 0d9a9b504..b378e23b5 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlProvider.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlProvider.kt @@ -7,6 +7,6 @@ import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.database.jsonl.AbstractJsonlProvider import org.vitrivr.engine.database.jsonl.JsonlConnection -object StructJsonlProvider: AbstractJsonlProvider() { - override fun newReader(connection: Connection, field: Schema.Field<*, StructDescriptor>): DescriptorReader = StructJsonlReader(field, connection as JsonlConnection) +object StructJsonlProvider : AbstractJsonlProvider>() { + override fun newReader(connection: Connection, field: Schema.Field<*, StructDescriptor<*>>): DescriptorReader> = StructJsonlReader(field, connection as JsonlConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlReader.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlReader.kt index 4bdcbc967..a730ae619 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlReader.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/struct/StructJsonlReader.kt @@ -6,22 +6,20 @@ import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.core.model.query.Query import org.vitrivr.engine.core.model.query.bool.SimpleBooleanQuery import org.vitrivr.engine.core.model.query.fulltext.SimpleFulltextQuery -import org.vitrivr.engine.core.model.retrievable.Retrieved import org.vitrivr.engine.core.model.types.Value import org.vitrivr.engine.database.jsonl.AbstractJsonlReader import org.vitrivr.engine.database.jsonl.JsonlConnection import org.vitrivr.engine.database.jsonl.JsonlConnection.Companion.DESCRIPTOR_ID_COLUMN_NAME import org.vitrivr.engine.database.jsonl.JsonlConnection.Companion.RETRIEVABLE_ID_COLUMN_NAME import org.vitrivr.engine.database.jsonl.model.AttributeContainerList -import org.vitrivr.engine.database.jsonl.retrievable.JsonlRetrievableReader import kotlin.reflect.full.primaryConstructor class StructJsonlReader( - field: Schema.Field<*, StructDescriptor>, + field: Schema.Field<*, StructDescriptor<*>>, connection: JsonlConnection -) : AbstractJsonlReader(field, connection) { +) : AbstractJsonlReader>(field, connection) { - override fun toDescriptor(list: AttributeContainerList): StructDescriptor { + override fun toDescriptor(list: AttributeContainerList): StructDescriptor<*> { val map = list.list.associateBy { it.attribute.name } val constructor = this.field.analyser.descriptorClass.primaryConstructor @@ -45,14 +43,14 @@ class StructJsonlReader( return constructor.call(*parameters.toTypedArray()) } - override fun query(query: Query): Sequence = when (query) { + override fun query(query: Query): Sequence> = when (query) { is SimpleFulltextQuery -> this.queryFulltext(query) is SimpleBooleanQuery<*> -> this.queryBoolean(query) else -> throw UnsupportedOperationException("The provided query type ${query::class.simpleName} is not supported by this reader.") } - private fun queryFulltext(fulltextQuery: SimpleFulltextQuery): Sequence { + private fun queryFulltext(fulltextQuery: SimpleFulltextQuery): Sequence> { val queryString = fulltextQuery.value.value val attributeName = fulltextQuery.attributeName ?: return emptySequence() @@ -63,7 +61,7 @@ class StructJsonlReader( } - private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence = getAll().filter { descriptor -> + private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> = getAll().filter { descriptor -> query.comparison.compare(descriptor.values()[query.attributeName!!]!!, query.value) } diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlProvider.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlProvider.kt index 4cb88c3c3..87abdfbe7 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlProvider.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlProvider.kt @@ -7,6 +7,6 @@ import org.vitrivr.engine.core.model.metamodel.Schema import org.vitrivr.engine.database.jsonl.AbstractJsonlProvider import org.vitrivr.engine.database.jsonl.JsonlConnection -object VectorJsonlProvider: AbstractJsonlProvider>() { - override fun newReader(connection: Connection, field: Schema.Field<*, VectorDescriptor<*>>): DescriptorReader> = VectorJsonlReader(field, connection as JsonlConnection) +object VectorJsonlProvider : AbstractJsonlProvider>() { + override fun newReader(connection: Connection, field: Schema.Field<*, VectorDescriptor<*, *>>): DescriptorReader> = VectorJsonlReader(field, connection as JsonlConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlReader.kt b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlReader.kt index 79aae4f96..50ac8471b 100644 --- a/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlReader.kt +++ b/vitrivr-engine-module-jsonl/src/main/kotlin/org/vitrivr/engine/database/jsonl/vector/VectorJsonlReader.kt @@ -10,17 +10,17 @@ import org.vitrivr.engine.core.model.retrievable.attributes.DistanceAttribute import org.vitrivr.engine.core.model.types.Value import org.vitrivr.engine.core.util.knn.FixedSizePriorityQueue import org.vitrivr.engine.database.jsonl.AbstractJsonlReader -import org.vitrivr.engine.database.jsonl.model.AttributeContainerList import org.vitrivr.engine.database.jsonl.JsonlConnection import org.vitrivr.engine.database.jsonl.JsonlConnection.Companion.DESCRIPTOR_ID_COLUMN_NAME import org.vitrivr.engine.database.jsonl.JsonlConnection.Companion.RETRIEVABLE_ID_COLUMN_NAME +import org.vitrivr.engine.database.jsonl.model.AttributeContainerList class VectorJsonlReader( - field: Schema.Field<*, VectorDescriptor<*>>, + field: Schema.Field<*, VectorDescriptor<*, *>>, connection: JsonlConnection -) : AbstractJsonlReader>(field, connection) { +) : AbstractJsonlReader>(field, connection) { - override fun toDescriptor(list: AttributeContainerList): VectorDescriptor<*> { + override fun toDescriptor(list: AttributeContainerList): VectorDescriptor<*, *> { val map = list.list.associateBy { it.attribute.name } val retrievableId = (map[RETRIEVABLE_ID_COLUMN_NAME]?.value!!.toValue() as Value.UUIDValue).value @@ -60,7 +60,7 @@ class VectorJsonlReader( } } - override fun query(query: Query): Sequence> = when (query) { + override fun query(query: Query): Sequence> = when (query) { is ProximityQuery<*> -> queryProximity(query) else -> throw UnsupportedOperationException("Query of typ ${query::class} is not supported by this reader.") } @@ -87,15 +87,15 @@ class VectorJsonlReader( } - private fun queryProximity(query: ProximityQuery<*>): Sequence> = + private fun queryProximity(query: ProximityQuery<*>): Sequence> = knn(query).asSequence().map { it.first } - private fun knn(query: ProximityQuery<*>): FixedSizePriorityQueue, Float>> { + private fun knn(query: ProximityQuery<*>): FixedSizePriorityQueue, Float>> { val queue = FixedSizePriorityQueue(query.k.toInt(), when (query.order) { - SortOrder.ASC -> Comparator, Float>> { p0, p1 -> + SortOrder.ASC -> Comparator, Float>> { p0, p1 -> p0.second.compareTo(p1.second) } diff --git a/vitrivr-engine-module-m3d/src/main/kotlin/org/vitrivr/engine/model3d/decoder/MeshDecoder.kt b/vitrivr-engine-module-m3d/src/main/kotlin/org/vitrivr/engine/model3d/decoder/MeshDecoder.kt index 816e327e6..7ab7eac0f 100644 --- a/vitrivr-engine-module-m3d/src/main/kotlin/org/vitrivr/engine/model3d/decoder/MeshDecoder.kt +++ b/vitrivr-engine-module-m3d/src/main/kotlin/org/vitrivr/engine/model3d/decoder/MeshDecoder.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.mapNotNull import org.vitrivr.engine.core.context.IndexContext import org.vitrivr.engine.core.model.retrievable.Retrievable +import org.vitrivr.engine.core.model.retrievable.attributes.ContentAuthorAttribute import org.vitrivr.engine.core.model.retrievable.attributes.SourceAttribute import org.vitrivr.engine.core.operators.ingest.Decoder import org.vitrivr.engine.core.operators.ingest.DecoderFactory @@ -61,6 +62,7 @@ class MeshDecoder : DecoderFactory { } val modelContent = this.context.contentFactory.newMeshContent(model) sourceRetrievable.addContent(modelContent) + sourceRetrievable.addAttribute(ContentAuthorAttribute(modelContent.id, this.name)) sourceRetrievable } catch (e: IOException) { logger.error(e) { "Failed to decode 3D model from $source due to an IO exception." } diff --git a/vitrivr-engine-module-m3d/src/test/kotlin/org/vitrivr/engine/model3d/ModelHandlerTest.kt b/vitrivr-engine-module-m3d/src/test/kotlin/org/vitrivr/engine/model3d/ModelHandlerTest.kt index 49af98429..e26e984c5 100644 --- a/vitrivr-engine-module-m3d/src/test/kotlin/org/vitrivr/engine/model3d/ModelHandlerTest.kt +++ b/vitrivr-engine-module-m3d/src/test/kotlin/org/vitrivr/engine/model3d/ModelHandlerTest.kt @@ -1,6 +1,5 @@ package org.vitrivr.engine.model3d -import org.joml.Vector3f import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import java.nio.file.Files @@ -26,6 +25,5 @@ class ModelHandlerTest { val mesh = model.getMaterials().first().meshes.first() Assertions.assertEquals(4968, mesh.numberOfFaces) Assertions.assertEquals(2503, mesh.numberOfVertices) - //TODO: Maybe more tests? } } \ No newline at end of file diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/Constants.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/Constants.kt index 735a41cde..07df55db5 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/Constants.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/Constants.kt @@ -4,7 +4,7 @@ package org.vitrivr.engine.database.pgvector const val RETRIEVABLE_ENTITY_NAME = "retrievable" /** The column name of a retrievable ID. */ -const val RETRIEVABLE_ID_COLUMN_NAME = "retrievableId" +const val RETRIEVABLE_ID_COLUMN_NAME = "retrievableid" /** The column name of a retrievable ID. */ const val RETRIEVABLE_TYPE_COLUMN_NAME = "type" @@ -13,10 +13,10 @@ const val RETRIEVABLE_TYPE_COLUMN_NAME = "type" const val RELATIONSHIP_ENTITY_NAME = "relationships" /** The column name of a retrievable ID. */ -const val SUBJECT_ID_COLUMN_NAME = "subjectId" +const val SUBJECT_ID_COLUMN_NAME = "subjectid" /** The column name of a retrievable ID. */ -const val OBJECT_ID_COLUMN_NAME = "objectId" +const val OBJECT_ID_COLUMN_NAME = "objectid" /** The column name of a retrievable ID. */ const val PREDICATE_COLUMN_NAME = "predicate" @@ -25,7 +25,7 @@ const val PREDICATE_COLUMN_NAME = "predicate" const val DESCRIPTOR_ENTITY_PREFIX = "descriptor" /** The column name of a descriptor ID. */ -const val DESCRIPTOR_ID_COLUMN_NAME = "descriptorId" +const val DESCRIPTOR_ID_COLUMN_NAME = "descriptorid" /** The column name used to describe a distance.*/ const val DISTANCE_COLUMN_NAME = "distance" \ No newline at end of file diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnection.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnection.kt index 1b256dc45..5578bd6e8 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnection.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnection.kt @@ -17,7 +17,7 @@ import java.sql.SQLException internal val LOGGER: KLogger = logger("org.vitrivr.engine.database.pgvector.PgVectorConnection") /** - * A [AbstractConnection] to connect to a PostgreSQL instance with the pgVector extension. + * An [AbstractConnection] to connect to a PostgreSQL instance with the pgVector extension. * * @author Ralph Gasser * @version 1.0.0 @@ -37,7 +37,7 @@ class PgVectorConnection(provider: PgVectorConnectionProvider, schemaName: Strin /* Create necessary schema. */ try { - this.jdbc.prepareStatement("CREATE SCHEMA \"${schemaName}\";").use { + this.jdbc.prepareStatement("CREATE SCHEMA \"${schemaName.lowercase()}\";").use { it.execute() } } catch (e: SQLException) { @@ -50,7 +50,7 @@ class PgVectorConnection(provider: PgVectorConnectionProvider, schemaName: Strin } try { - this.jdbc.prepareStatement("SET search_path TO \"$schemaName\", public;").use { + this.jdbc.prepareStatement("SET search_path TO \"${schemaName.lowercase()}\", public;").use { it.execute() } } catch (e: SQLException) { diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnectionProvider.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnectionProvider.kt index 945dcf336..f625b1d8c 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnectionProvider.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/PgVectorConnectionProvider.kt @@ -5,8 +5,8 @@ import org.vitrivr.engine.core.database.Connection import org.vitrivr.engine.core.database.ConnectionProvider import org.vitrivr.engine.core.database.descriptor.DescriptorProvider import org.vitrivr.engine.core.model.descriptor.scalar.* +import org.vitrivr.engine.core.model.descriptor.struct.AnyMapStructDescriptor import org.vitrivr.engine.core.model.descriptor.struct.LabelDescriptor -import org.vitrivr.engine.core.model.descriptor.struct.MapStructDescriptor import org.vitrivr.engine.core.model.descriptor.struct.metadata.MediaDimensionsDescriptor import org.vitrivr.engine.core.model.descriptor.struct.metadata.Rectangle2DMetadataDescriptor import org.vitrivr.engine.core.model.descriptor.struct.metadata.TemporalMetadataDescriptor @@ -92,7 +92,7 @@ class PgVectorConnectionProvider: AbstractConnectionProvider() { this.register(TemporalMetadataDescriptor::class, StructDescriptorProvider) this.register(Rectangle2DMetadataDescriptor::class, StructDescriptorProvider) this.register(MediaDimensionsDescriptor::class, StructDescriptorProvider) - this.register(MapStructDescriptor::class, StructDescriptorProvider) + this.register(AnyMapStructDescriptor::class, StructDescriptorProvider) } /** diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/AbstractDescriptorReader.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/AbstractDescriptorReader.kt index 5a7beac7a..1c552d56f 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/AbstractDescriptorReader.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/AbstractDescriptorReader.kt @@ -17,7 +17,7 @@ import java.util.* * @author Ralph Gasser * @version 1.0.0 */ -abstract class AbstractDescriptorReader(final override val field: Schema.Field<*, D>, override val connection: PgVectorConnection) : DescriptorReader { +abstract class AbstractDescriptorReader>(final override val field: Schema.Field<*, D>, override val connection: PgVectorConnection) : DescriptorReader { /** The name of the table backing this [AbstractDescriptorReader]. */ protected val tableName: String = "${DESCRIPTOR_ENTITY_PREFIX}_${this.field.fieldName}" diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorInitializer.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorInitializer.kt index 4e7879dd3..bcd906e00 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorInitializer.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorInitializer.kt @@ -17,7 +17,7 @@ import java.sql.SQLException * @author Ralph Gasser * @version 1.0.0 */ -open class PgDescriptorInitializer(final override val field: Schema.Field<*, D>, protected val connection: PgVectorConnection): DescriptorInitializer { +open class PgDescriptorInitializer>(final override val field: Schema.Field<*, D>, protected val connection: PgVectorConnection) : DescriptorInitializer { companion object { /** Set of scalar index structures supported by PostgreSQL. */ @@ -37,29 +37,29 @@ open class PgDescriptorInitializer(final override val field: Sch * Initializes the PostgreSQL table entity backing this [PgDescriptorInitializer]. */ override fun initialize() { - val statement = StringBuilder("CREATE TABLE IF NOT EXISTS \"${tableName}\" (") + val statement = StringBuilder("CREATE TABLE IF NOT EXISTS \"${tableName.lowercase()}\" (") statement.append("$DESCRIPTOR_ID_COLUMN_NAME uuid NOT NULL, ") statement.append("$RETRIEVABLE_ID_COLUMN_NAME uuid NOT NULL, ") /* Add columns for each field in the struct. */ for (field in this.prototype.layout()) { when (field.type) { - Type.String -> statement.append("\"${field.name}\" varchar(255), ") - Type.Text -> statement.append("\"${field.name}\" text, ") - Type.Boolean -> statement.append("\"${field.name}\" boolean, ") - Type.Byte -> statement.append("\"${field.name}\" smallint, ") - Type.Short -> statement.append("\"${field.name}\" smallint, ") - Type.Int -> statement.append("\"${field.name}\" integer, ") - Type.Long -> statement.append("\"${field.name}\" bigint, ") - Type.Float -> statement.append("\"${field.name}\" real, ") - Type.Double -> statement.append("\"${field.name}\" double precision, ") - Type.Datetime -> statement.append("\"${field.name}\" datetime, ") - Type.UUID -> statement.append("\"${field.name}\" uuid, ") - is Type.BooleanVector -> statement.append("\"${field.name}\" bit(${field.type.dimensions}), ") - is Type.DoubleVector -> statement.append("\"${field.name}\" vector(${field.type.dimensions}), ") - is Type.FloatVector -> statement.append("\"${field.name}\" vector(${field.type.dimensions}), ") - is Type.IntVector -> statement.append("\"${field.name}\" vector(${field.type.dimensions}), ") - is Type.LongVector -> statement.append("\"${field.name}\" vector(${field.type.dimensions}), ") + Type.String -> statement.append("\"${field.name.lowercase()}\" varchar(255), ") + Type.Text -> statement.append("\"${field.name.lowercase()}\" text, ") + Type.Boolean -> statement.append("\"${field.name.lowercase()}\" boolean, ") + Type.Byte -> statement.append("\"${field.name.lowercase()}\" smallint, ") + Type.Short -> statement.append("\"${field.name.lowercase()}\" smallint, ") + Type.Int -> statement.append("\"${field.name.lowercase()}\" integer, ") + Type.Long -> statement.append("\"${field.name.lowercase()}\" bigint, ") + Type.Float -> statement.append("\"${field.name.lowercase()}\" real, ") + Type.Double -> statement.append("\"${field.name.lowercase()}\" double precision, ") + Type.Datetime -> statement.append("\"${field.name.lowercase()}\" datetime, ") + Type.UUID -> statement.append("\"${field.name.lowercase()}\" uuid, ") + is Type.BooleanVector -> statement.append("\"${field.name.lowercase()}\" bit(${field.type.dimensions}), ") + is Type.DoubleVector -> statement.append("\"${field.name.lowercase()}\" vector(${field.type.dimensions}), ") + is Type.FloatVector -> statement.append("\"${field.name.lowercase()}\" vector(${field.type.dimensions}), ") + is Type.IntVector -> statement.append("\"${field.name.lowercase()}\" vector(${field.type.dimensions}), ") + is Type.LongVector -> statement.append("\"${field.name.lowercase()}\" vector(${field.type.dimensions}), ") } } @@ -97,7 +97,7 @@ open class PgDescriptorInitializer(final override val field: Sch } this.connection.jdbc.prepareStatement(/* sql = postgres */ indexStatement).use { it.execute() } } catch (e: SQLException) { - LOGGER.error(e) { "Failed to create index ${index.type} for entity '$tableName' due to exception." } + LOGGER.error(e) { "Failed to create index ${index.type} for entity \"${tableName.lowercase()}\" due to exception." } throw e } } @@ -109,7 +109,7 @@ open class PgDescriptorInitializer(final override val field: Sch override fun deinitialize() { try { /* Create 'retrievable' entity and index. */ - this.connection.jdbc.prepareStatement(/* sql = postgres */ "DROP TABLE IF EXISTS \"${tableName}\" CASCADE;").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "DROP TABLE IF EXISTS \"${tableName.lowercase()}\" CASCADE;").use { it.execute() } } catch (e: SQLException) { @@ -124,7 +124,7 @@ open class PgDescriptorInitializer(final override val field: Sch */ override fun isInitialized(): Boolean { try { - this.connection.jdbc.prepareStatement(/* sql = postgres */ "SELECT count(*) FROM $tableName").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "SELECT count(*) FROM \"${tableName.lowercase()}\"").use { it.execute() } } catch (e: SQLException) { @@ -138,7 +138,7 @@ open class PgDescriptorInitializer(final override val field: Sch */ override fun truncate() { try { - this.connection.jdbc.prepareStatement(/* sql = postgres */ "TRUNCATE $tableName").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "TRUNCATE \"${tableName.lowercase()}\"").use { it.execute() } } catch (e: SQLException) { diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorWriter.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorWriter.kt index b2300d00a..8b4972bd1 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorWriter.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/PgDescriptorWriter.kt @@ -13,7 +13,7 @@ import java.sql.* * @author Ralph Gasser * @version 1.0.0 */ -open class PgDescriptorWriter(final override val field: Schema.Field<*, D>, override val connection: PgVectorConnection): DescriptorWriter { +open class PgDescriptorWriter>(final override val field: Schema.Field<*, D>, override val connection: PgVectorConnection) : DescriptorWriter { /** The name of the table backing this [PgDescriptorInitializer]. */ protected val tableName: String = "${DESCRIPTOR_ENTITY_PREFIX}_${this.field.fieldName}" @@ -43,7 +43,7 @@ open class PgDescriptorWriter(final override val field: Schema.F return stmt.executeUpdate() == 1 } } catch (e: SQLException) { - LOGGER.error(e) { "Failed to INSERT descriptor ${item.id} into '$tableName' due to SQL error." } + LOGGER.error(e) { "Failed to INSERT descriptor ${item.id} into \"${tableName.lowercase()}\" due to SQL error." } return false } } @@ -74,7 +74,7 @@ open class PgDescriptorWriter(final override val field: Schema.F return stmt.executeBatch().all { it == 1 } } } catch (e: SQLException) { - LOGGER.error(e) { "Failed to INSERT descriptors into '$tableName' due to SQL error." } + LOGGER.error(e) { "Failed to INSERT descriptors into \"${tableName.lowercase()}\" due to SQL error." } return false } } @@ -102,7 +102,7 @@ open class PgDescriptorWriter(final override val field: Schema.F return stmt.execute() } } catch (e: SQLException) { - LOGGER.error(e) { "Failed to UPDATE descriptors in '$tableName' due to SQL error." } + LOGGER.error(e) { "Failed to UPDATE descriptors in \"${tableName.lowercase()}\" due to SQL error." } return false } } @@ -115,7 +115,7 @@ open class PgDescriptorWriter(final override val field: Schema.F */ override fun delete(item: D): Boolean { try { - this.connection.jdbc.prepareStatement("DELETE FROM $tableName WHERE $DESCRIPTOR_ID_COLUMN_NAME = ?;").use { stmt -> + this.connection.jdbc.prepareStatement("DELETE FROM \"${tableName.lowercase()}\" WHERE $DESCRIPTOR_ID_COLUMN_NAME = ?;").use { stmt -> stmt.setObject(1, item.id) return stmt.executeUpdate() == 1 } @@ -133,7 +133,7 @@ open class PgDescriptorWriter(final override val field: Schema.F */ override fun deleteAll(items: Iterable): Boolean { try { - this.connection.jdbc.prepareStatement("DELETE FROM $tableName WHERE $DESCRIPTOR_ID_COLUMN_NAME = ANY (?);").use { stmt -> + this.connection.jdbc.prepareStatement("DELETE FROM \"${tableName.lowercase()}\" WHERE $DESCRIPTOR_ID_COLUMN_NAME = ANY (?);").use { stmt -> val values = items.map { it.id }.toTypedArray() stmt.setArray(1, this.connection.jdbc.createArrayOf("uuid", values)) return stmt.executeUpdate() > 0 @@ -151,9 +151,9 @@ open class PgDescriptorWriter(final override val field: Schema.F * @return [PreparedStatement] */ protected fun prepareUpdateStatement(): PreparedStatement { - val statement = StringBuilder("UPDATE $tableName SET $RETRIEVABLE_ID_COLUMN_NAME = ?") + val statement = StringBuilder("UPDATE \"${tableName.lowercase()}\" SET $RETRIEVABLE_ID_COLUMN_NAME = ?") for (field in this.prototype.layout()) { - statement.append(", \"${field.name}\" = ?") + statement.append(", \"${field.name.lowercase()}\" = ?") } statement.append("WHERE $DESCRIPTOR_ID_COLUMN_NAME = ?;") return this.connection.jdbc.prepareStatement(statement.toString()) @@ -165,9 +165,9 @@ open class PgDescriptorWriter(final override val field: Schema.F * @return [PreparedStatement] */ protected fun prepareInsertStatement(): PreparedStatement { - val statement = StringBuilder("INSERT INTO $tableName ($DESCRIPTOR_ID_COLUMN_NAME, $RETRIEVABLE_ID_COLUMN_NAME") + val statement = StringBuilder("INSERT INTO \"${tableName.lowercase()}\" ($DESCRIPTOR_ID_COLUMN_NAME, $RETRIEVABLE_ID_COLUMN_NAME") for (field in this.prototype.layout()) { - statement.append(", \"${field.name}\"") + statement.append(", \"${field.name.lowercase()}\"") } statement.append(") VALUES (?, ?") for (field in this.field.analyser.prototype(this.field).layout()) { diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorProvider.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorProvider.kt index 8fb2ff599..ae0de387a 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorProvider.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorProvider.kt @@ -15,8 +15,8 @@ import org.vitrivr.engine.database.pgvector.descriptor.PgDescriptorWriter * @author Ralph Gasser * @version 1.0.0 */ -object ScalarDescriptorProvider: DescriptorProvider> { - override fun newInitializer(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*>>) = PgDescriptorInitializer(field, connection as PgVectorConnection) - override fun newReader(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*>>) = ScalarDescriptorReader(field, connection as PgVectorConnection) - override fun newWriter(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*>>) = PgDescriptorWriter(field, connection as PgVectorConnection) +object ScalarDescriptorProvider : DescriptorProvider> { + override fun newInitializer(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*, *>>) = PgDescriptorInitializer(field, connection as PgVectorConnection) + override fun newReader(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*, *>>) = ScalarDescriptorReader(field, connection as PgVectorConnection) + override fun newWriter(connection: Connection, field: Schema.Field<*, ScalarDescriptor<*, *>>) = PgDescriptorWriter(field, connection as PgVectorConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorReader.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorReader.kt index c6729dd54..362b7eea3 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorReader.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/scalar/ScalarDescriptorReader.kt @@ -21,7 +21,7 @@ import java.util.* * @author Ralph Gasser * @version 1.0.0 */ -class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connection: PgVectorConnection) : AbstractDescriptorReader>(field, connection) { +class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*, *>>, connection: PgVectorConnection) : AbstractDescriptorReader>(field, connection) { /** * Executes the provided [Query] and returns a [Sequence] of [Retrieved]s that match it. @@ -29,7 +29,7 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * @param query The [Query] to execute. * @return [Sequence] of [StructDescriptor]s that match the query. */ - override fun query(query: Query): Sequence> = when (query) { + override fun query(query: Query): Sequence> = when (query) { is SimpleFulltextQuery -> queryFulltext(query) is SimpleBooleanQuery<*> -> queryBoolean(query) else -> throw IllegalArgumentException("Query of type ${query::class} is not supported by ScalarDescriptorReader.") @@ -41,11 +41,13 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * @param result The [ResultSet] to convert. * @return The resulting [VectorDescriptor]. */ - override fun rowToDescriptor(result: ResultSet): ScalarDescriptor<*> { + override fun rowToDescriptor(result: ResultSet): ScalarDescriptor<*, *> { val descriptorId = result.getObject(DESCRIPTOR_ID_COLUMN_NAME, UUID::class.java) val retrievableId = result.getObject(RETRIEVABLE_ID_COLUMN_NAME, UUID::class.java) return when (this.prototype) { is BooleanDescriptor -> BooleanDescriptor(descriptorId, retrievableId, Value.Boolean(result.getBoolean(VALUE_ATTRIBUTE_NAME))) + is ByteDescriptor -> ByteDescriptor(descriptorId, retrievableId, Value.Byte(result.getByte(VALUE_ATTRIBUTE_NAME))) + is ShortDescriptor -> ShortDescriptor(descriptorId, retrievableId, Value.Short(result.getShort(VALUE_ATTRIBUTE_NAME))) is IntDescriptor -> IntDescriptor(descriptorId, retrievableId, Value.Int(result.getInt(VALUE_ATTRIBUTE_NAME))) is LongDescriptor -> LongDescriptor(descriptorId, retrievableId, Value.Long(result.getLong(VALUE_ATTRIBUTE_NAME))) is FloatDescriptor -> FloatDescriptor(descriptorId, retrievableId, Value.Float(result.getFloat(VALUE_ATTRIBUTE_NAME))) @@ -61,7 +63,7 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * @param query The [SimpleFulltextQuery] to execute. * @return [Sequence] of [ScalarDescriptor]s. */ - private fun queryFulltext(query: SimpleFulltextQuery): Sequence> { + private fun queryFulltext(query: SimpleFulltextQuery): Sequence> { val statement = "SELECT * FROM \"$tableName\" WHERE $VALUE_ATTRIBUTE_NAME @@ plainto_tsquery(?)" return sequence { this@ScalarDescriptorReader.connection.jdbc.prepareStatement(statement).use { stmt -> @@ -81,7 +83,7 @@ class ScalarDescriptorReader(field: Schema.Field<*, ScalarDescriptor<*>>, connec * @param query The [SimpleBooleanQuery] to execute. * @return [Sequence] of [ScalarDescriptor]s. */ - private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> { + private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> { val statement = "SELECT * FROM \"$tableName\" WHERE $VALUE_ATTRIBUTE_NAME ${query.comparison.toSql()} ?" return sequence { this@ScalarDescriptorReader.connection.jdbc.prepareStatement(statement).use { stmt -> diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorProvider.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorProvider.kt index edbccb8cd..bcfef20b4 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorProvider.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorProvider.kt @@ -15,8 +15,8 @@ import org.vitrivr.engine.database.pgvector.descriptor.PgDescriptorWriter * @author Ralph Gasser * @version 1.0.0 */ -object StructDescriptorProvider : DescriptorProvider { - override fun newInitializer(connection: Connection, field: Schema.Field<*, StructDescriptor>) = PgDescriptorInitializer(field, connection as PgVectorConnection) - override fun newReader(connection: Connection, field: Schema.Field<*, StructDescriptor>) = StructDescriptorReader(field, connection as PgVectorConnection) - override fun newWriter(connection: Connection, field: Schema.Field<*, StructDescriptor>) = PgDescriptorWriter(field, connection as PgVectorConnection) +object StructDescriptorProvider : DescriptorProvider> { + override fun newInitializer(connection: Connection, field: Schema.Field<*, StructDescriptor<*>>) = PgDescriptorInitializer(field, connection as PgVectorConnection) + override fun newReader(connection: Connection, field: Schema.Field<*, StructDescriptor<*>>) = StructDescriptorReader(field, connection as PgVectorConnection) + override fun newWriter(connection: Connection, field: Schema.Field<*, StructDescriptor<*>>) = PgDescriptorWriter(field, connection as PgVectorConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorReader.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorReader.kt index 7ac1461b6..ef87ccb7d 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorReader.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/struct/StructDescriptorReader.kt @@ -23,14 +23,14 @@ import kotlin.reflect.full.primaryConstructor * @author Ralph Gasser * @version 1.0.0 */ -class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connection: PgVectorConnection) : AbstractDescriptorReader(field, connection) { +class StructDescriptorReader(field: Schema.Field<*, StructDescriptor<*>>, connection: PgVectorConnection) : AbstractDescriptorReader>(field, connection) { /** * Executes the provided [Query] and returns a [Sequence] of [Retrieved]s that match it. * * @param query The [Query] to execute. * @return [Sequence] of [StructDescriptor]s that match the query. */ - override fun query(query: Query): Sequence = when (query) { + override fun query(query: Query): Sequence> = when (query) { is SimpleFulltextQuery -> queryFulltext(query) is SimpleBooleanQuery<*> -> queryBoolean(query) else -> throw IllegalArgumentException("Query of typ ${query::class} is not supported by StructDescriptorReader.") @@ -42,7 +42,7 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio * @param result The [ResultSet] to convert. * @return The resulting [StructDescriptor]. */ - override fun rowToDescriptor(result: ResultSet): StructDescriptor { + override fun rowToDescriptor(result: ResultSet): StructDescriptor<*> { val constructor = this.field.analyser.descriptorClass.primaryConstructor ?: throw IllegalStateException("Provided type ${this.field.analyser.descriptorClass} does not have a primary constructor.") val values = TreeMap?>() val parameters: MutableList = mutableListOf( @@ -55,22 +55,22 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio /* Append dynamic parameters of struct. */ for (field in this.prototype.layout()) { values[field.name] = when(field.type) { - Type.String -> result.getString(field.name)?.let { Value.String(it) } - Type.Text -> result.getString(field.name)?.let { Value.Text(it) } - Type.Boolean -> result.getBoolean(field.name).let { Value.Boolean(it) } - Type.Byte -> result.getByte(field.name).let { Value.Byte(it) } - Type.Short -> result.getShort(field.name).let { Value.Short(it) } - Type.Int -> result.getInt(field.name).let { Value.Int(it) } - Type.Long -> result.getLong(field.name).let { Value.Long(it) } - Type.Float -> result.getFloat(field.name).let { Value.Float(it) } - Type.Double -> result.getDouble(field.name).let { Value.Double(it) } - Type.Datetime -> result.getDate(field.name).toInstant().let { Value.DateTime(Date(it.toEpochMilli())) } - Type.UUID -> result.getObject(field.name, UUID::class.java).let { Value.UUIDValue(it) } - is Type.BooleanVector -> result.getObject(field.name, PgBitVector::class.java).toBooleanVector() - is Type.IntVector -> result.getObject(field.name, PgVector::class.java)?.toIntVector() - is Type.LongVector -> result.getObject(field.name, PgVector::class.java)?.toLongVector() - is Type.FloatVector -> result.getObject(field.name, PgVector::class.java)?.toFloatVector() - is Type.DoubleVector -> result.getObject(field.name, PgVector::class.java)?.toDoubleVector() + Type.String -> result.getString(field.name.lowercase())?.let { Value.String(it) } + Type.Text -> result.getString(field.name.lowercase())?.let { Value.Text(it) } + Type.Boolean -> result.getBoolean(field.name.lowercase()).let { Value.Boolean(it) } + Type.Byte -> result.getByte(field.name.lowercase()).let { Value.Byte(it) } + Type.Short -> result.getShort(field.name.lowercase()).let { Value.Short(it) } + Type.Int -> result.getInt(field.name.lowercase()).let { Value.Int(it) } + Type.Long -> result.getLong(field.name.lowercase()).let { Value.Long(it) } + Type.Float -> result.getFloat(field.name.lowercase()).let { Value.Float(it) } + Type.Double -> result.getDouble(field.name.lowercase()).let { Value.Double(it) } + Type.Datetime -> result.getDate(field.name.lowercase()).toInstant().let { Value.DateTime(Date(it.toEpochMilli())) } + Type.UUID -> result.getObject(field.name.lowercase(), UUID::class.java).let { Value.UUIDValue(it) } + is Type.BooleanVector -> result.getObject(field.name.lowercase(), PgBitVector::class.java).toBooleanVector() + is Type.IntVector -> result.getObject(field.name.lowercase(), PgVector::class.java)?.toIntVector() + is Type.LongVector -> result.getObject(field.name.lowercase(), PgVector::class.java)?.toLongVector() + is Type.FloatVector -> result.getObject(field.name.lowercase(), PgVector::class.java)?.toFloatVector() + is Type.DoubleVector -> result.getObject(field.name.lowercase(), PgVector::class.java)?.toDoubleVector() } as Value<*>? } @@ -84,9 +84,9 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio * @param query The [SimpleFulltextQuery] to execute. * @return [Sequence] of [StructDescriptor]s. */ - private fun queryFulltext(query: SimpleFulltextQuery): Sequence { + private fun queryFulltext(query: SimpleFulltextQuery): Sequence> { require(query.attributeName != null) { "Query attribute must not be null for a fulltext query on a struct descriptor." } - val statement = "SELECT * FROM \"$tableName\" WHERE ${query.attributeName} @@ plainto_tsquery(?)" + val statement = "SELECT * FROM \"${tableName.lowercase()}\" WHERE ${query.attributeName} @@ plainto_tsquery(?)" return sequence { this@StructDescriptorReader.connection.jdbc.prepareStatement(statement).use { stmt -> stmt.setString(1, query.value.value) @@ -105,9 +105,9 @@ class StructDescriptorReader(field: Schema.Field<*, StructDescriptor>, connectio * @param query The [SimpleBooleanQuery] to execute. * @return [Sequence] of [StructDescriptor]s. */ - private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence { + private fun queryBoolean(query: SimpleBooleanQuery<*>): Sequence> { require(query.attributeName != null) { "Query attribute must not be null for a fulltext query on a struct descriptor." } - val statement = "SELECT * FROM \"$tableName\" WHERE ${query.attributeName} ${query.comparison.toSql()} ?" + val statement = "SELECT * FROM \"${tableName.lowercase()}\" WHERE ${query.attributeName} ${query.comparison.toSql()} ?" return sequence { this@StructDescriptorReader.connection.jdbc.prepareStatement(statement).use { stmt -> stmt.setValue(1, query.value) diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorProvider.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorProvider.kt index 57b7a00a1..50e8f064f 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorProvider.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorProvider.kt @@ -14,8 +14,8 @@ import org.vitrivr.engine.database.pgvector.descriptor.PgDescriptorWriter * @author Ralph Gasser * @version 1.0.0 */ -object VectorDescriptorProvider: DescriptorProvider> { - override fun newInitializer(connection: Connection, field: Schema.Field<*, VectorDescriptor<*>>) = PgDescriptorInitializer(field, connection as PgVectorConnection) - override fun newReader(connection: Connection, field: Schema.Field<*, VectorDescriptor<*>>) = VectorDescriptorReader(field, connection as PgVectorConnection) - override fun newWriter(connection: Connection, field: Schema.Field<*, VectorDescriptor<*>>) = PgDescriptorWriter(field, connection as PgVectorConnection) +object VectorDescriptorProvider : DescriptorProvider> { + override fun newInitializer(connection: Connection, field: Schema.Field<*, VectorDescriptor<*, *>>) = PgDescriptorInitializer(field, connection as PgVectorConnection) + override fun newReader(connection: Connection, field: Schema.Field<*, VectorDescriptor<*, *>>) = VectorDescriptorReader(field, connection as PgVectorConnection) + override fun newWriter(connection: Connection, field: Schema.Field<*, VectorDescriptor<*, *>>) = PgDescriptorWriter(field, connection as PgVectorConnection) } \ No newline at end of file diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorReader.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorReader.kt index 6d69d35be..3efbaf1fd 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorReader.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/descriptor/vector/VectorDescriptorReader.kt @@ -21,13 +21,13 @@ import java.util.* * @author Ralph Gasser * @version 1.0.0 */ -class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*>>, connection: PgVectorConnection) : AbstractDescriptorReader>(field, connection) { +class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*, *>>, connection: PgVectorConnection) : AbstractDescriptorReader>(field, connection) { /** * Executes the provided [Query] and returns a [Sequence] of [Retrieved]s that match it. * * @param query The [Query] to execute. */ - override fun query(query: Query): Sequence> = when (query) { + override fun query(query: Query): Sequence> = when (query) { is ProximityQuery<*> -> queryProximity(query) else -> throw UnsupportedOperationException("Query of typ ${query::class} is not supported by VectorDescriptorReader.") } @@ -51,7 +51,7 @@ class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*>>, connec * @param result [ResultSet] to convert. * @return [VectorDescriptor] */ - override fun rowToDescriptor(result: ResultSet): VectorDescriptor<*> { + override fun rowToDescriptor(result: ResultSet): VectorDescriptor<*, *> { val descriptorId = result.getObject(DESCRIPTOR_ID_COLUMN_NAME, UUID::class.java) val retrievableId = result.getObject(RETRIEVABLE_ID_COLUMN_NAME, UUID::class.java) return when (this.prototype) { @@ -95,9 +95,9 @@ class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*>>, connec * @param query The [ProximityQuery] to execute. * @return [Sequence] of [VectorDescriptor]s. */ - private fun queryProximity(query: ProximityQuery<*>): Sequence> = sequence { + private fun queryProximity(query: ProximityQuery<*>): Sequence> = sequence { val statement = - "SELECT $DESCRIPTOR_ID_COLUMN_NAME, $RETRIEVABLE_ID_COLUMN_NAME, $VECTOR_ATTRIBUTE_NAME, $VECTOR_ATTRIBUTE_NAME ${query.distance.toSql()} ? AS $DISTANCE_COLUMN_NAME FROM \"${tableName}\" ORDER BY $DISTANCE_COLUMN_NAME ${query.order} LIMIT ${query.k}" + "SELECT $DESCRIPTOR_ID_COLUMN_NAME, $RETRIEVABLE_ID_COLUMN_NAME, $VECTOR_ATTRIBUTE_NAME, $VECTOR_ATTRIBUTE_NAME ${query.distance.toSql()} ? AS $DISTANCE_COLUMN_NAME FROM \"${tableName.lowercase()}\" ORDER BY $DISTANCE_COLUMN_NAME ${query.order} LIMIT ${query.k}" this@VectorDescriptorReader.connection.jdbc.prepareStatement(statement).use { stmt -> stmt.setValue(1, query.value) stmt.executeQuery().use { result -> @@ -115,9 +115,9 @@ class VectorDescriptorReader(field: Schema.Field<*, VectorDescriptor<*>>, connec * @return [Sequence] of [VectorDescriptor]s. */ private fun queryAndJoinProximity(query: ProximityQuery<*>): Sequence { - val descriptors = mutableListOf, Float>>() + val descriptors = mutableListOf, Float>>() val statement = - "SELECT $DESCRIPTOR_ID_COLUMN_NAME, $RETRIEVABLE_ID_COLUMN_NAME, $VECTOR_ATTRIBUTE_NAME, $VECTOR_ATTRIBUTE_NAME ${query.distance.toSql()} ? AS $DISTANCE_COLUMN_NAME FROM \"${tableName}\" ORDER BY $DISTANCE_COLUMN_NAME ${query.order} LIMIT ${query.k}" + "SELECT $DESCRIPTOR_ID_COLUMN_NAME, $RETRIEVABLE_ID_COLUMN_NAME, $VECTOR_ATTRIBUTE_NAME, $VECTOR_ATTRIBUTE_NAME ${query.distance.toSql()} ? AS $DISTANCE_COLUMN_NAME FROM \"${tableName.lowercase()}\" ORDER BY $DISTANCE_COLUMN_NAME ${query.order} LIMIT ${query.k}" this@VectorDescriptorReader.connection.jdbc.prepareStatement(statement).use { stmt -> stmt.setValue(1, query.value) stmt.executeQuery().use { result -> diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableInitializer.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableInitializer.kt index afd8408f6..1e53c6e1c 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableInitializer.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableInitializer.kt @@ -18,12 +18,12 @@ internal class RetrievableInitializer(private val connection: PgVectorConnection override fun initialize() { try { /* Create 'retrievable' entity and index. */ - this.connection.jdbc.prepareStatement(/* sql = postgres */ "CREATE TABLE IF NOT EXISTS \"${RETRIEVABLE_ENTITY_NAME}\" ($RETRIEVABLE_ID_COLUMN_NAME uuid NOT NULL, type VARCHAR(100), PRIMARY KEY ($RETRIEVABLE_ID_COLUMN_NAME));").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "CREATE TABLE IF NOT EXISTS ${RETRIEVABLE_ENTITY_NAME} ($RETRIEVABLE_ID_COLUMN_NAME uuid NOT NULL, type VARCHAR(100), PRIMARY KEY ($RETRIEVABLE_ID_COLUMN_NAME));").use { it.execute() } /* Create 'relationship' entity. */ - this.connection.jdbc.prepareStatement(/* sql = postgres */ "CREATE TABLE IF NOT EXISTS \"${RELATIONSHIP_ENTITY_NAME}\" ($OBJECT_ID_COLUMN_NAME uuid NOT NULL, $PREDICATE_COLUMN_NAME VARCHAR(100) NOT NULL, $SUBJECT_ID_COLUMN_NAME uuid NOT NULL, PRIMARY KEY ($OBJECT_ID_COLUMN_NAME, $PREDICATE_COLUMN_NAME, $SUBJECT_ID_COLUMN_NAME), FOREIGN KEY($OBJECT_ID_COLUMN_NAME) REFERENCES $RETRIEVABLE_ENTITY_NAME($RETRIEVABLE_ID_COLUMN_NAME) ON DELETE CASCADE, FOREIGN KEY($SUBJECT_ID_COLUMN_NAME) REFERENCES $RETRIEVABLE_ENTITY_NAME($RETRIEVABLE_ID_COLUMN_NAME) ON DELETE CASCADE);") + this.connection.jdbc.prepareStatement(/* sql = postgres */ "CREATE TABLE IF NOT EXISTS ${RELATIONSHIP_ENTITY_NAME} ($OBJECT_ID_COLUMN_NAME uuid NOT NULL, $PREDICATE_COLUMN_NAME VARCHAR(100) NOT NULL, $SUBJECT_ID_COLUMN_NAME uuid NOT NULL, PRIMARY KEY ($OBJECT_ID_COLUMN_NAME, $PREDICATE_COLUMN_NAME, $SUBJECT_ID_COLUMN_NAME), FOREIGN KEY($OBJECT_ID_COLUMN_NAME) REFERENCES $RETRIEVABLE_ENTITY_NAME($RETRIEVABLE_ID_COLUMN_NAME) ON DELETE CASCADE, FOREIGN KEY($SUBJECT_ID_COLUMN_NAME) REFERENCES $RETRIEVABLE_ENTITY_NAME($RETRIEVABLE_ID_COLUMN_NAME) ON DELETE CASCADE);") .use { it.execute() } @@ -38,12 +38,12 @@ internal class RetrievableInitializer(private val connection: PgVectorConnection override fun deinitialize() { try { /* Create 'retrievable' entity and index. */ - this.connection.jdbc.prepareStatement(/* sql = postgres */ "DROP TABLE IF EXISTS \"${RETRIEVABLE_ENTITY_NAME}\" CASCADE;").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "DROP TABLE IF EXISTS ${RETRIEVABLE_ENTITY_NAME} CASCADE;").use { it.execute() } /* Create 'relationship' entity. */ - this.connection.jdbc.prepareStatement(/* sql = postgres */ "DROP TABLE IF EXISTS \"${RELATIONSHIP_ENTITY_NAME}\" CASCADE;").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "DROP TABLE IF EXISTS ${RELATIONSHIP_ENTITY_NAME} CASCADE;").use { it.execute() } } catch (e: SQLException) { @@ -58,14 +58,14 @@ internal class RetrievableInitializer(private val connection: PgVectorConnection */ override fun isInitialized(): Boolean { try { - this.connection.jdbc.prepareStatement(/* sql = postgres */ "SELECT count(*) FROM \"${RETRIEVABLE_ENTITY_NAME}\";").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "SELECT count(*) FROM ${RETRIEVABLE_ENTITY_NAME};").use { it.execute() } } catch (e: SQLException) { return false } try { - this.connection.jdbc.prepareStatement(/* sql = postgres */ "SELECT count(*) FROM \"$RELATIONSHIP_ENTITY_NAME\";").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "SELECT count(*) FROM $RELATIONSHIP_ENTITY_NAME;").use { it.execute() } } catch (e: SQLException) { @@ -79,7 +79,7 @@ internal class RetrievableInitializer(private val connection: PgVectorConnection */ override fun truncate() { try { - this.connection.jdbc.prepareStatement(/* sql = postgres */ "TRUNCATE \"${RETRIEVABLE_ENTITY_NAME}\", \"${RELATIONSHIP_ENTITY_NAME}\"").use { + this.connection.jdbc.prepareStatement(/* sql = postgres */ "TRUNCATE ${RETRIEVABLE_ENTITY_NAME}, ${RELATIONSHIP_ENTITY_NAME}").use { it.execute() } } catch (e: SQLException) { diff --git a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableReader.kt b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableReader.kt index 758cf378e..030a4d99a 100644 --- a/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableReader.kt +++ b/vitrivr-engine-module-pgvector/src/main/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableReader.kt @@ -5,13 +5,14 @@ import org.vitrivr.engine.core.model.retrievable.Retrievable import org.vitrivr.engine.core.model.retrievable.RetrievableId import org.vitrivr.engine.core.model.retrievable.Retrieved import org.vitrivr.engine.database.pgvector.* +import java.sql.SQLException import java.util.* /** * A [RetrievableReader] implementation for PostgreSQL with pgVector. * * @author Ralph Gasser - * @version 1.0.0 + * @version 1.0.1 */ class RetrievableReader(override val connection: PgVectorConnection): RetrievableReader { /** @@ -97,12 +98,53 @@ class RetrievableReader(override val connection: PgVectorConnection): Retrievabl } } - override fun getConnections( - subjectIds: Collection, - predicates: Collection, - objectIds: Collection - ): Sequence> { - TODO("Not yet implemented") + /** + * Returns all relationships thar are stored by the database and that match the given query. + * + * @return A [Sequence] of all [Retrievable]s in the database. + */ + override fun getConnections(subjectIds: Collection, predicates: Collection, objectIds: Collection): Sequence> { + val query = StringBuilder("SELECT * FROM \"$RELATIONSHIP_ENTITY_NAME\" WHERE ") + if (subjectIds.isNotEmpty()) { + query.append("$SUBJECT_ID_COLUMN_NAME = ANY (?)") + } + if (predicates.isNotEmpty()) { + if (subjectIds.isNotEmpty()) { + query.append(" AND ") + } + query.append("$PREDICATE_COLUMN_NAME = ANY (?)") + } + if (objectIds.isNotEmpty()) { + if (subjectIds.isNotEmpty() || predicates.isNotEmpty()) { + query.append(" AND ") + } + query.append("$OBJECT_ID_COLUMN_NAME = ANY (?)") + } + + return sequence { + try { + this@RetrievableReader.connection.jdbc.prepareStatement(query.toString()).use { stmt -> + var index = 1 + if (subjectIds.isNotEmpty()) { + stmt.setArray(index++, this@RetrievableReader.connection.jdbc.createArrayOf("uuid", subjectIds.toTypedArray())) + } + if (predicates.isNotEmpty()) { + stmt.setArray(index++, this@RetrievableReader.connection.jdbc.createArrayOf("varchar", predicates.toTypedArray())) + } + if (objectIds.isNotEmpty()) { + stmt.setArray(index, this@RetrievableReader.connection.jdbc.createArrayOf("uuid", objectIds.toTypedArray())) + } + stmt.executeQuery().use { result -> + while (result.next()) { + yield(Triple(result.getObject(OBJECT_ID_COLUMN_NAME, UUID::class.java), result.getString(PREDICATE_COLUMN_NAME), result.getObject(SUBJECT_ID_COLUMN_NAME, UUID::class.java))) + } + } + } + } catch (e: SQLException) { + LOGGER.error(e) { "Failed to fetch relationships due to SQL error." } + } + } + } /** @@ -118,7 +160,7 @@ class RetrievableReader(override val connection: PgVectorConnection): Retrievabl return result.getLong(1) } } - } catch (e: Exception) { + } catch (e: SQLException) { LOGGER.error(e) { "Failed to count retrievable due to SQL error." } return 0L } diff --git a/vitrivr-engine-module-pgvector/src/test/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableWriterTest.kt b/vitrivr-engine-module-pgvector/src/test/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableWriterTest.kt index c6326f32a..7572f718a 100644 --- a/vitrivr-engine-module-pgvector/src/test/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableWriterTest.kt +++ b/vitrivr-engine-module-pgvector/src/test/kotlin/org/vitrivr/engine/database/pgvector/retrievable/RetrievableWriterTest.kt @@ -1,6 +1,7 @@ package org.vitrivr.engine.database.pgvector.retrievable import org.vitrivr.engine.core.database.retrievable.AbstractRetrievableWriterTest +import org.vitrivr.engine.database.pgvector.PgVectorConnection /** * An [AbstractRetrievableWriterTest] for the [PgVectorConnection]. @@ -8,6 +9,4 @@ import org.vitrivr.engine.core.database.retrievable.AbstractRetrievableWriterTes * @author Ralph Gasser * @version 1.0.0 */ -class RetrievableWriterTest : AbstractRetrievableWriterTest("test-schema-postgres.json") { - -} \ No newline at end of file +class RetrievableWriterTest : AbstractRetrievableWriterTest("test-schema-postgres.json") \ No newline at end of file diff --git a/vitrivr-engine-module-statistics/averagecolor/AverageColor.kt b/vitrivr-engine-module-statistics/averagecolor/AverageColor.kt deleted file mode 100644 index 4e8dfa8ae..000000000 --- a/vitrivr-engine-module-statistics/averagecolor/AverageColor.kt +++ /dev/null @@ -1,135 +0,0 @@ -package org.vitrivr.engine.base.features.averagecolor - -import io.github.oshai.kotlinlogging.KLogger -import io.github.oshai.kotlinlogging.KotlinLogging -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.context.QueryContext -import org.vitrivr.engine.core.model.color.MutableRGBFloatColorContainer -import org.vitrivr.engine.core.model.color.RGBByteColorContainer -import org.vitrivr.engine.core.model.color.RGBFloatColorContainer -import org.vitrivr.engine.core.model.content.Content -import org.vitrivr.engine.core.model.content.element.ImageContent -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Analyser -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.Query -import org.vitrivr.engine.core.model.query.proximity.ProximityQuery -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.operators.retrieve.Retriever -import org.vitrivr.engine.core.util.extension.getRGBArray -import java.util.* - -/** - * Implementation of the [AverageColor] [Analyser], which derives the average color from an [ImageContent] as [FloatVectorDescriptor]. - * - * @author Ralph Gasser - * @version 1.0.0 - */ -class AverageColor : Analyser { - - private val logger: KLogger = KotlinLogging.logger {} - - override val contentClasses = setOf(ImageContent::class) - override val descriptorClass = FloatVectorDescriptor::class - - /** - * Generates a prototypical [FloatVectorDescriptor] for this [AverageColor]. - * - * @param field [Schema.Field] to create the prototype for. - * @return [FloatVectorDescriptor] - */ - override fun prototype(field: Schema.Field<*, *>) = FloatVectorDescriptor(UUID.randomUUID(), UUID.randomUUID(), listOf(Value.Float(0.0f), Value.Float(0.0f), Value.Float(0.0f))) - - /** - * Generates and returns a new [AverageColorExtractor] instance for this [AverageColor]. - * - * @param field The [Schema.Field] to create an [Extractor] for. - * @param input The [Operator] that acts as input to the new [Extractor]. - * @param context The [IndexContext] to use with the [Extractor]. - * - * @return A new [Extractor] instance for this [Analyser] - * @throws [UnsupportedOperationException], if this [Analyser] does not support the creation of an [Extractor] instance. - */ - override fun newExtractor(field: Schema.Field, input: Operator, context: IndexContext) = AverageColorExtractor(input, field) - - /** - * Generates and returns a new [AverageColorExtractor] instance for this [AverageColor]. - * - * @param name The name of the [AverageColorExtractor]. - * @param input The [Operator] that acts as input to the new [Extractor]. - * @param context The [IndexContext] to use with the [Extractor]. - * - * @return A new [Extractor] instance for this [Analyser] - * @throws [UnsupportedOperationException], if this [Analyser] does not support the creation of an [Extractor] instance. - */ - override fun newExtractor(name: String, input: Operator, context: IndexContext): Extractor = AverageColorExtractor(input, null) - - /** - * Generates and returns a new [AverageColorRetriever] instance for this [AverageColor]. - * - * @param field The [Schema.Field] to create an [Retriever] for. - * @param query The [Query] to use with the [Retriever]. - * @param context The [QueryContext] to use with the [Retriever]. - * - * @return A new [Retriever] instance for this [Analyser] - */ - override fun newRetrieverForQuery(field: Schema.Field, query: Query, context: QueryContext): AverageColorRetriever { - require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" } - require(query is ProximityQuery<*> && query.value.first() is Value.Float) { "The query is not a ProximityQuery." } - @Suppress("UNCHECKED_CAST") - return AverageColorRetriever(field, query as ProximityQuery) - } - - /** - * Generates and returns a new [AverageColorRetriever] instance for this [AverageColor]. - * - * Invoking this method involves converting the provided [FloatVectorDescriptor] into a [ProximityQuery] that can be used to retrieve similar [ImageContent] elements. - * - * @param field The [Schema.Field] to create an [Retriever] for. - * @param descriptors An array of [FloatVectorDescriptor] elements to use with the [Retriever] - * @param context The [QueryContext] to use with the [Retriever] - */ - override fun newRetrieverForDescriptors(field: Schema.Field, descriptors: Collection, context: QueryContext): AverageColorRetriever { - require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" } - - /* Prepare query parameters. */ - val k = context.getProperty(field.fieldName, "limit")?.toLongOrNull() ?: 1000L - val fetchVector = context.getProperty(field.fieldName, "returnDescriptor")?.toBooleanStrictOrNull() ?: false - - /* Return retriever. */ - return this.newRetrieverForQuery(field, ProximityQuery(value = descriptors.first().vector, k = k, fetchVector = fetchVector), context) - } - - /** - * Generates and returns a new [AverageColorRetriever] instance for this [AverageColor]. - * - * Invoking this method involves converting the provided [ImageContent] and the [QueryContext] into a [FloatVectorDescriptor] - * that can be used to retrieve similar [ImageContent] elements. - * - * @param field The [Schema.Field] to create an [Retriever] for. - * @param content An array of [Content] elements to use with the [Retriever] - * @param context The [QueryContext] to use with the [Retriever] - */ - override fun newRetrieverForContent(field: Schema.Field, content: Collection, context: QueryContext): AverageColorRetriever = - this.newRetrieverForDescriptors(field, this.analyse(content), context) - - /** - * Performs the [AverageColor] analysis on the provided [List] of [ImageContent] elements. - * - * @param content The [List] of [ImageContent] elements. - * @return [List] of [FloatVectorDescriptor]s. - */ - fun analyse(content: Collection): List = content.map { - logger.trace{"Analysing"} - val color = MutableRGBFloatColorContainer() - val rgb = it.content.getRGBArray() - rgb.forEach { c -> color += RGBByteColorContainer.fromRGB(c) } - - /* Generate descriptor. */ - val averageColor = RGBFloatColorContainer(color.red / rgb.size, color.green / rgb.size, color.blue / rgb.size) - FloatVectorDescriptor(UUID.randomUUID(), null, averageColor.toValueList()) - } -} diff --git a/vitrivr-engine-module-statistics/averagecolor/AverageColorExtractor.kt b/vitrivr-engine-module-statistics/averagecolor/AverageColorExtractor.kt deleted file mode 100644 index fa0b07316..000000000 --- a/vitrivr-engine-module-statistics/averagecolor/AverageColorExtractor.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.vitrivr.engine.base.features.averagecolor - -import org.vitrivr.engine.core.features.AbstractExtractor -import org.vitrivr.engine.core.features.metadata.source.file.FileSourceMetadataExtractor -import org.vitrivr.engine.core.model.content.ContentType -import org.vitrivr.engine.core.model.content.element.ImageContent -import org.vitrivr.engine.core.model.descriptor.Descriptor -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.ingest.Extractor -import org.vitrivr.engine.core.source.file.FileSource - -/** - * [Extractor] implementation for the [AverageColor] analyser. - * - * @see [AverageColor] - * - * @author Luca Rossetto - * @version 1.1.0 - */ -class AverageColorExtractor(input: Operator, field: Schema.Field?) : AbstractExtractor(input, field) { - /** - * Internal method to check, if [Retrievable] matches this [Extractor] and should thus be processed. - * - * [FileSourceMetadataExtractor] implementation only works with [Retrievable] that contain a [FileSource]. - * - * @param retrievable The [Retrievable] to check. - * @return True on match, false otherwise, - */ - override fun matches(retrievable: Retrievable): Boolean = retrievable.content.any { it.type == ContentType.BITMAP_IMAGE } - - /** - * Internal method to perform extraction on [Retrievable]. - ** - * @param retrievable The [Retrievable] to process. - * @return List of resulting [Descriptor]s. - */ - override fun extract(retrievable: Retrievable): List { - val content = retrievable.content.filterIsInstance() - return AverageColor().analyse(content).map { it.copy(retrievableId = retrievable.id, field = this@AverageColorExtractor.field) } - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-statistics/averagecolor/AverageColorRetriever.kt b/vitrivr-engine-module-statistics/averagecolor/AverageColorRetriever.kt deleted file mode 100644 index 6e32d8f39..000000000 --- a/vitrivr-engine-module-statistics/averagecolor/AverageColorRetriever.kt +++ /dev/null @@ -1,48 +0,0 @@ -package org.vitrivr.engine.base.features.averagecolor - -import io.github.oshai.kotlinlogging.KLogger -import io.github.oshai.kotlinlogging.KotlinLogging -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.flow -import org.vitrivr.engine.core.model.content.element.ImageContent -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.query.proximity.ProximityQuery -import org.vitrivr.engine.core.model.retrievable.Retrieved -import org.vitrivr.engine.core.model.retrievable.attributes.DistanceAttribute -import org.vitrivr.engine.core.model.retrievable.attributes.ScoreAttribute -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.core.operators.retrieve.Retriever - -/** - * [Retriever] implementation for the [AverageColor] analyser. - * - * @see [AverageColor] - * - * @author Luca Rossetto - * @version 1.0.0 - */ -class AverageColorRetriever( - override val field: Schema.Field, - private val query: ProximityQuery -) : Retriever { - - private val logger: KLogger = KotlinLogging.logger {} - - companion object { - private const val MAXIMUM_DISTANCE = 3f - fun scoringFunction(retrieved: Retrieved): Float { - val distance = retrieved.filteredAttribute()?.distance ?: return 0f - return 1f - (distance / MAXIMUM_DISTANCE) - } - } - - override fun toFlow(scope: CoroutineScope) = flow { - val reader = this@AverageColorRetriever.field.getReader() - logger.debug { "Flow init with query $query" } - reader.getAll(this@AverageColorRetriever.query).forEach { - it.addAttribute(ScoreAttribute.Similarity(scoringFunction(it))) - emit(it) - } - } -} diff --git a/vitrivr-engine-module-statistics/build.gradle b/vitrivr-engine-module-statistics/build.gradle deleted file mode 100644 index 8f65ebe63..000000000 --- a/vitrivr-engine-module-statistics/build.gradle +++ /dev/null @@ -1,75 +0,0 @@ -plugins { - id 'maven-publish' - id 'signing' -} - -dependencies { - api project(':vitrivr-engine-core') -} - -/* Publication of vitrivr engine query to Maven Central. */ -publishing { - publications { - mavenJava(MavenPublication) { - groupId = 'org.vitrivr' - artifactId = 'vitrivr-engine-plugin-statistics' - version = System.getenv().getOrDefault("MAVEN_PUBLICATION_VERSION", version.toString()) - from components.java - pom { - name = 'vitrivr Engine Statistics' - description = 'Shared based components of the vitrivr multimedia retrieval engine (e.g., database connection, features).' - url = 'https://github.com/vitrivr/vitrivr-engine/' - licenses { - license { - name = 'MIT License' - } - } - developers { - developer { - id = 'ppanopticon' - name = 'Ralph Gasser' - email = 'ralph.gasser@unibas.ch' - } - developer { - id = 'lucaro' - name = 'Luca Rossetto' - email = 'rossetto@ifi.uzh.ch' - } - developer { - id = 'net-cscience-raphael' - name = 'Raphael Waltensül' - email = 'raphael.waltenspuel@unibas.ch' - } - developer { - id = 'rahelarnold98' - name = 'Rahel Arnold' - email = 'rahel.arnold@unibas.ch' - } - developer { - id = 'rahelarnold98' - name = 'faberf' - email = 'fynnfirouz.faber@unibas.ch' - } - } - scm { - connection = 'scm:git:https://github.com/vitrivr/vitrivr-engine.git' - url = 'https://github.com/vitrivr/vitrivr-engine/' - } - } - } - } - repositories { - repositories { - maven { - def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' - def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' - name = "OSSRH" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - credentials { - username = System.getenv("MAVEN_USERNAME") - password = System.getenv("MAVEN_PASSWORD") - } - } - } - } -} \ No newline at end of file diff --git a/vitrivr-engine-module-statistics/src/main/kotlin/StatisticsConsumer.kt b/vitrivr-engine-module-statistics/src/main/kotlin/StatisticsConsumer.kt deleted file mode 100644 index 42d2129e6..000000000 --- a/vitrivr-engine-module-statistics/src/main/kotlin/StatisticsConsumer.kt +++ /dev/null @@ -1,52 +0,0 @@ -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors - - -class StatisticsConsumer { - /** The [ExecutorService] used to execution [] */ - private val executor: ExecutorService = Executors.newCachedThreadPool() - - - @OptIn(ExperimentalCoroutinesApi::class) - suspend fun produceNumbers(channel: Channel) { - while (!channel.isClosedForSend) { - (500..2000).random().let { - println("Sending $it") - channel.send(it) - suspend { delay(it.toLong()) } - } - - } - channel.close() - } - - @OptIn(ExperimentalCoroutinesApi::class) - suspend fun consumeNumbers(channel: Channel) { - var millis = System.currentTimeMillis() - while (!channel.isClosedForReceive) { - - channel.receive().let { num -> - System.currentTimeMillis().let { - println("Received $num current time: ${it - millis}") - millis = it - } - - } - } - } - - fun main() = runBlocking { - val channel = Channel() - launch { produceNumbers(channel) } - consumeNumbers(channel) - } - - - - -} \ No newline at end of file diff --git a/vitrivr-engine-module-statistics/src/main/kotlin/StatisticsExporter.kt b/vitrivr-engine-module-statistics/src/main/kotlin/StatisticsExporter.kt deleted file mode 100644 index 49f132717..000000000 --- a/vitrivr-engine-module-statistics/src/main/kotlin/StatisticsExporter.kt +++ /dev/null @@ -1,27 +0,0 @@ -import io.github.oshai.kotlinlogging.KLogger -import io.github.oshai.kotlinlogging.KotlinLogging -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import org.vitrivr.engine.core.context.IndexContext -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.operators.Operator -import org.vitrivr.engine.core.operators.general.Exporter -import org.vitrivr.engine.core.operators.general.ExporterFactory -import org.vitrivr.engine.core.source.file.MimeType - - -private val logger: KLogger = KotlinLogging.logger {} - -class StatisticsExporter : ExporterFactory { - - - override fun newExporter(name: String, input: Operator, context: IndexContext): Exporter { - logger.debug { "Creating new StatisticsExporter." } - return Instance(input, context) - } - private class Instance(override val input: Operator, private val context: IndexContext) : Exporter { - override fun toFlow(scope: CoroutineScope): Flow { - return this.input.toFlow(scope) - } - } -} \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregator.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregator.kt index 459955707..c87d192bd 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregator.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregator.kt @@ -15,7 +15,7 @@ import org.vitrivr.engine.core.operators.general.Aggregator import java.util.* class TemporalSequenceAggregator( - override val inputs: List> + override val inputs: List>, override val name: String ) : Aggregator { companion object { diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregatorFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregatorFactory.kt index 2f1174c1d..a958221a1 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregatorFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/TemporalSequenceAggregatorFactory.kt @@ -13,7 +13,7 @@ class TemporalSequenceAggregatorFactory : AggregatorFactory { context: Context ): Aggregator { return TemporalSequenceAggregator( - inputs + inputs, name ) } } \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt index 0142ef43b..5989a6387 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt @@ -10,12 +10,15 @@ import org.vitrivr.engine.core.model.retrievable.RetrievableId import org.vitrivr.engine.core.model.retrievable.attributes.ScoreAttribute import org.vitrivr.engine.core.operators.Operator import org.vitrivr.engine.core.operators.general.Aggregator +import java.util.* import kotlin.math.pow class WeightedScoreFusion( override val inputs: List>, weights: List, - val p: Float + private val p: Float, + private val normalize: Boolean, + override val name: String ) : Aggregator { private val weights: List = when { @@ -81,7 +84,8 @@ class WeightedScoreFusion( else { score = retrieveds.map { ((it.second.filteredAttribute(ScoreAttribute::class.java))?.score ?: 0f).pow(p) * weights[it.first] - }.sum().pow(1 / p) / normalization + }.sum().pow(1 / p) + if (normalize) score /= normalization } first = retrieveds.first().second } diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt index a315d6bd1..2b4e12902 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt @@ -17,9 +17,10 @@ class WeightedScoreFusionFactory : AggregatorFactory { ): Aggregator { val weights = context[name, "weights"]?.split(",")?.mapNotNull { s -> s.trim().toFloatOrNull() } ?: emptyList() val p = context[name, "p"]?.toFloatOrNull() ?: 1f + val normalize = context[name, "normalize"]?.toBoolean() ?: true if (p == Float.POSITIVE_INFINITY && weights.isNotEmpty()) { logger.warn { "Weights are ignored when p is set to infinity" } } - return WeightedScoreFusion(inputs, weights, p) + return WeightedScoreFusion(inputs, weights, p, normalize, name) } } \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/retrieval/RetrievedLookup.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/retrieval/RetrievedLookup.kt index e5e0e91bd..cb7c5b4a2 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/retrieval/RetrievedLookup.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/retrieval/RetrievedLookup.kt @@ -14,7 +14,10 @@ import org.vitrivr.engine.core.operators.Operator * @author Luca Rossetto * @version 1.1.0 */ -class RetrievedLookup(private val reader: RetrievableReader, private val ids: Collection) : Operator.Nullary { +class RetrievedLookup(private val reader: RetrievableReader, + private val ids: Collection, + override val name: String +) : Operator.Nullary { override fun toFlow(scope: CoroutineScope): Flow = flow { this@RetrievedLookup.reader.getAll(ids).forEach { emit(Retrieved(it.id, it.type, false)) diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookup.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookup.kt index 9b14d214b..6239d7084 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookup.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookup.kt @@ -24,7 +24,8 @@ import javax.management.Descriptor class FieldLookup( override val input: Operator, private val reader: DescriptorReader<*>, - val keys: List + val keys: List, + override val name: String ) : Transformer { override fun toFlow(scope: CoroutineScope): Flow = flow { /* Parse input IDs.*/ diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookupFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookupFactory.kt index 0e1cd0c03..ae9630b88 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookupFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/FieldLookupFactory.kt @@ -22,6 +22,6 @@ class FieldLookupFactory() : TransformerFactory { }else{ emptyList() } - return FieldLookup(input, reader, keys) + return FieldLookup(input, reader, keys, name) } } diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookup.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookup.kt index cda016333..fc639db61 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookup.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookup.kt @@ -19,7 +19,11 @@ import org.vitrivr.engine.core.operators.general.Transformer * @author Luca Rossetto * @author Ralph Gasser */ -class ObjectFieldLookup(override val input: Operator, private val reader: DescriptorReader<*>, private val predicates: Set) : +class ObjectFieldLookup(override val input: Operator, + private val reader: DescriptorReader<*>, + private val predicates: Set, + override val name: String +) : Transformer { override fun toFlow(scope: CoroutineScope): Flow = flow { /* Parse input IDs.*/ diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookupFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookupFactory.kt index c53a25d55..b8cf32a4a 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookupFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/lookup/ObjectFieldLookupFactory.kt @@ -19,6 +19,6 @@ class ObjectFieldLookupFactory() : TransformerFactory { val field = context[name, "field"] ?: throw IllegalArgumentException("Expected 'field' to be defined in properties") val predicates = context[name, "predicates"]?.split(",")?.toSet() ?: emptySet() val reader = (context.schema[field] ?: throw IllegalArgumentException("Field '$field' not defined in schema")).getReader() - return ObjectFieldLookup(input, reader, predicates) + return ObjectFieldLookup(input, reader, predicates, name) } } \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpander.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpander.kt index 8fd7f22e6..793173d6c 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpander.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpander.kt @@ -23,7 +23,8 @@ class RelationExpander( override val input: Operator, private val incomingRelations: List, private val outgoingRelations: List, - private val retrievableReader: RetrievableReader + private val retrievableReader: RetrievableReader, + override val name: String ) : Transformer { override fun toFlow(scope: CoroutineScope): Flow = flow { /* Collect input into list. */ diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpanderFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpanderFactory.kt index 2b3ebdf81..e0fbaa763 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpanderFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationExpanderFactory.kt @@ -20,6 +20,6 @@ class RelationExpanderFactory : TransformerFactory { val retrievableReader = context.schema.connection.getRetrievableReader() val incomingRelations = context[name, "incoming"]?.split(",")?.map { s -> s.trim() } ?: emptyList() val outgoingRelations = context[name, "outgoing"]?.split(",")?.map { s -> s.trim() } ?: emptyList() - return RelationExpander(input, incomingRelations, outgoingRelations, retrievableReader) + return RelationExpander(input, incomingRelations, outgoingRelations, retrievableReader, name) } } \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolver.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolver.kt index 5a22d67ba..242194d12 100755 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolver.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolver.kt @@ -19,7 +19,8 @@ import org.vitrivr.engine.core.operators.general.Transformer class RelationResolver( override val input: Operator, private val relationPredicate: String, - private val retrievableReader: RetrievableReader + private val retrievableReader: RetrievableReader, + override val name: String ): Transformer { /** * Converts this [Operator] to a [Flow] of type [O]. diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolverFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolverFactory.kt index bc797d6ff..8d40d2078 100755 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolverFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/relation/RelationResolverFactory.kt @@ -25,6 +25,6 @@ class RelationResolverFactory: TransformerFactory { val retrievableReader = context.schema.connection.getRetrievableReader() val predicate = context[name, "predicate"] require(predicate?.isNotBlank() == true){"Requires a non-blank predicate!"} - return RelationResolver(input, predicate!! , retrievableReader) + return RelationResolver(input, predicate!! , retrievableReader, name) } } diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregator.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregator.kt index 81263d07e..df469e978 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregator.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregator.kt @@ -12,7 +12,8 @@ import org.vitrivr.engine.core.operators.general.Transformer class ScoreAggregator( override val input: Operator, private val aggregationMode: AggregationMode = AggregationMode.MAX, - private val relations: Set = setOf("partOf") + private val relations: Set = setOf("partOf"), + override val name: String ) : Transformer { enum class AggregationMode { MAX, diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregatorFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregatorFactory.kt index a0a483442..a82c4fe7f 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregatorFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreAggregatorFactory.kt @@ -24,6 +24,6 @@ class ScoreAggregatorFactory : TransformerFactory { val relationships = context[name, "relationships"]?.split(",")?.map { s -> s.trim() }?.toSet() ?: setOf("partOf") - return ScoreAggregator(input, aggregation, relationships) + return ScoreAggregator(input, aggregation, relationships, name) } } \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggerator.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggerator.kt index 5254f517b..62f315b56 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggerator.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggerator.kt @@ -9,7 +9,7 @@ import org.vitrivr.engine.core.operators.Operator import org.vitrivr.engine.core.operators.general.Transformer import kotlin.math.pow -class ScoreExaggerator(override val input: Operator, val factor: Float) : Transformer { +class ScoreExaggerator(override val input: Operator, val factor: Float, override val name: String) : Transformer { override fun toFlow(scope: CoroutineScope): Flow { return flow { input.toFlow(scope).collect { retrieved : Retrievable -> diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggeratorFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggeratorFactory.kt index 0fb27e88e..669c44cc2 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggeratorFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/operators/transform/scoring/ScoreExaggeratorFactory.kt @@ -9,6 +9,6 @@ import org.vitrivr.engine.core.operators.general.TransformerFactory class ScoreExaggeratorFactory : TransformerFactory{ override fun newTransformer(name: String, input: Operator, context: Context): Transformer { val factor = context[name, "factor"]?.toFloat() ?: throw IllegalArgumentException("Property 'factor' must be specified") - return ScoreExaggerator(input, factor) + return ScoreExaggerator(input, factor, name) } } \ No newline at end of file diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/parsing/QueryParser.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/parsing/QueryParser.kt index ea3f43194..afbcf80b0 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/parsing/QueryParser.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/parsing/QueryParser.kt @@ -72,7 +72,7 @@ class QueryParser(val schema: Schema) { /* Special case: handle pass-through. */ if (operation.field == null) { //special case, handle pass-through require(input.type == InputType.ID) { "Only inputs of type ID are supported for direct retrievable lookup." } - return RetrievedLookup(this.schema.connection.getRetrievableReader(), listOf(UUID.fromString((input as RetrievableIdInputData).id))) + return RetrievedLookup(this.schema.connection.getRetrievableReader(), listOf(UUID.fromString((input as RetrievableIdInputData).id)), "${operatorName}-lookup") } val fieldAndAttributeName: Pair = if (operation.field.contains(".")) { val f = operation.field.substringBefore(".") diff --git a/vitrivr-engine-server/build.gradle b/vitrivr-engine-server/build.gradle index f11d772e8..007186c30 100644 --- a/vitrivr-engine-server/build.gradle +++ b/vitrivr-engine-server/build.gradle @@ -8,10 +8,10 @@ dependencies { /** vitrivr engine dependencies. */ api project(':vitrivr-engine-index') api project(':vitrivr-engine-query') - api project(':vitrivr-engine-module-features') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ - api project(':vitrivr-engine-module-cottontaildb') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ - api project(':vitrivr-engine-module-pgvector') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ - api project(':vitrivr-engine-module-fes') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ + api project(':vitrivr-engine-module-features') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ + api project(':vitrivr-engine-module-cottontaildb') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ + api project(':vitrivr-engine-module-pgvector') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ + api project(':vitrivr-engine-module-fes') /* TODO: This dependency is not necessary and only here to facilitate easy testing. */ /** Clikt & JLine */ implementation group: 'com.github.ajalt.clikt', name: 'clikt', version: version_clikt diff --git a/vitrivr-engine-server/src/main/kotlin/org/vitrivr/engine/tools/CineastMigrationTool.kt b/vitrivr-engine-server/src/main/kotlin/org/vitrivr/engine/tools/CineastMigrationTool.kt deleted file mode 100644 index 0c1d57d6a..000000000 --- a/vitrivr-engine-server/src/main/kotlin/org/vitrivr/engine/tools/CineastMigrationTool.kt +++ /dev/null @@ -1,545 +0,0 @@ -package org.vitrivr.engine.tools - -import kotlinx.coroutines.* -import kotlinx.serialization.* -import kotlinx.serialization.builtins.ListSerializer -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonDecoder -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.decodeFromStream -import kotlinx.serialization.modules.SerializersModule -import kotlinx.serialization.modules.contextual -import org.vitrivr.engine.core.config.schema.SchemaConfig -import org.vitrivr.engine.core.database.Initializer -import org.vitrivr.engine.core.model.descriptor.Descriptor -import org.vitrivr.engine.core.model.descriptor.DescriptorId -import org.vitrivr.engine.core.model.descriptor.scalar.FloatDescriptor -import org.vitrivr.engine.core.model.descriptor.scalar.StringDescriptor -import org.vitrivr.engine.core.model.descriptor.struct.metadata.MediaDimensionsDescriptor -import org.vitrivr.engine.core.model.descriptor.struct.metadata.TemporalMetadataDescriptor -import org.vitrivr.engine.core.model.descriptor.struct.metadata.source.FileSourceMetadataDescriptor -import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor -import org.vitrivr.engine.core.model.metamodel.Schema -import org.vitrivr.engine.core.model.metamodel.SchemaManager -import org.vitrivr.engine.core.model.relationship.Relationship -import org.vitrivr.engine.core.model.retrievable.Ingested -import org.vitrivr.engine.core.model.retrievable.Retrievable -import org.vitrivr.engine.core.model.retrievable.RetrievableId -import org.vitrivr.engine.core.model.types.Value -import org.vitrivr.engine.module.features.feature.averagecolorraster.RasterDescriptor -import org.vitrivr.engine.module.features.feature.skeleton.SkeletonDescriptor -import java.io.File -import java.io.FileReader -import java.nio.file.Files -import java.nio.file.Paths -import kotlin.reflect.KClass - -@Serializable -data class CineastMultimediaObject( - val objectid: String, - val mediatype: Int, - val name: String, - val path: String -) - -@Serializable -data class CineastSegment( - val segmentid: String, - val objectid: String, - val segmentnumber: Int, - val segmentstart: Int, - val segmentend: Int, - val segmentstartabs: Float, - val segmentendabs: Float -) - -@Serializable -data class CineastObjectMetadata( - val objectid: String, - val domain: String, - val key: String, - val value: String -) - -@Serializable -data class CineastSegmentMetadata( - val segmentid: String, - val domain: String, - val key: String, - val value: String -) - -interface CineastFeature { - val id: String - fun toDescriptor(idmap: Map): Descriptor? -} - -@Serializable -data class CineastVectorFeature(override val id: String, val feature: List) : CineastFeature { - override fun toDescriptor(idmap: Map): FloatVectorDescriptor? { - val id = this.id - if (idmap[id] == null) { - return null - } - return FloatVectorDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = RetrievableId.fromString(idmap[id]), - vector = Value.FloatVector(feature.toFloatArray()) - ) - } -} - -@Serializable -data class CineastStringFeature(override val id: String, val feature: String) : CineastFeature { - override fun toDescriptor(idmap: Map): StringDescriptor? { - val id = this.id - if (idmap[id] == null) { - return null - } - return StringDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = RetrievableId.fromString(idmap[id]), - value = Value.String(feature) - ) - } -} - -@Serializable -data class CineastSkeletonPoseFeature( - override val id: String, - val person: Int, - val skeleton: List, - val weights: List -) : CineastFeature { - override fun toDescriptor(idmap: Map): SkeletonDescriptor? { - val id = this.id - if (idmap[id] == null) { - return null - } - return SkeletonDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = RetrievableId.fromString(idmap[id]), - mapOf( - "person" to Value.Int(person), - "skeleton" to Value.FloatVector(skeleton.toFloatArray()), - "weights" to Value.FloatVector(weights.toFloatArray()) - ) - ) - } -} - -@Serializable -data class CineastRasterFeature(override val id: String, val hist: List, val raster: List) : - CineastFeature { - override fun toDescriptor(idmap: Map): RasterDescriptor? { - val id = this.id - if (idmap[id] == null) { - return null - } - return RasterDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = RetrievableId.fromString(idmap[id]), - mapOf( - "hist" to Value.FloatVector(hist.toFloatArray()), - "raster" to Value.FloatVector(raster.toFloatArray()) - ) - ) - } -} - -@Serializable -data class MigrationConfig( - val segmentspath: String, - val objectspath: String, - val segmentmetadatapath: String, - val objectmetadatapath: String, - val features: List -) - -@Serializable -data class FeatureConfig(val path: String, val fieldname: String) - -@OptIn(InternalSerializationApi::class) -fun parseJsonList(filePath: String, clazz: KClass): List { - val json = Json { ignoreUnknownKeys = true } - return Files.newInputStream(Paths.get(filePath)).use { inputStream -> - json.decodeFromStream(ListSerializer(clazz.serializer()), inputStream) - } -} - -@OptIn(InternalSerializationApi::class) -fun streamJsonItems(filePath: String, clazz: KClass): Sequence = sequence { - val json = Json { ignoreUnknownKeys = true } - Files.newInputStream(Paths.get(filePath)).use { inputStream -> - val element = json.decodeFromStream(inputStream) - if (element is JsonArray) { - element.forEach { jsonElement -> - val item = Json.decodeFromJsonElement(clazz.serializer(), jsonElement) - yield(item) - } - } else { - throw IllegalArgumentException("Expected a JSON array at the root") - } - } -} - -// Function to obtain a serializer for a given KClass instance at runtime. -@OptIn(InternalSerializationApi::class) -fun serializerForType(type: KClass): KSerializer { - return type.serializer() -} - -// Function to deserialize a JSON string into a list of objects of a dynamic type. -fun decodeJsonListFromString(jsonString: String, type: KClass): List { - val json = Json { serializersModule = SerializersModule { contextual(type, serializerForType(type)) } } - val listSerializer = ListSerializer(serializerForType(type)) - return json.decodeFromString(listSerializer, jsonString) -} - -class CineastMigrationTool(val migrationconfigpath: String, val schemaconfigpath: String) { - - private val migrationConfig: MigrationConfig - private val schemaConfig: SchemaConfig - private val schemaManager: SchemaManager - val schema: Schema - val descriptorToFeatureMap: Map, KClass> = mapOf( - FloatVectorDescriptor::class to CineastVectorFeature::class, - StringDescriptor::class to CineastStringFeature::class, - SkeletonDescriptor::class to CineastSkeletonPoseFeature::class, - RasterDescriptor::class to CineastRasterFeature::class, - ) - - private var idmap: MutableMap = mutableMapOf() - - init { - // Read the configuration strings - val configstring = Files.readString(Paths.get(migrationconfigpath)) - val schemaconfigstring = Files.readString(Paths.get(schemaconfigpath)) - - // Decode the configuration strings into objects - migrationConfig = Json.decodeFromString(configstring) - schemaConfig = Json.decodeFromString(schemaconfigstring) - - // Initialize the SchemaManager and load the schema - schemaManager = SchemaManager() - schemaManager.load(schemaConfig) - schema = schemaManager.getSchema(schemaConfig.name) - ?: throw IllegalArgumentException("Schema ${schemaConfig.name} not found") - } - - fun getFeatureClassFromDescriptor(descriptorClass: KClass<*>): KClass? { - return descriptorToFeatureMap[descriptorClass] - } - - fun initialize() { - var initialized = 0 - var initializer: Initializer<*> = schema.connection.getRetrievableInitializer() - if (!initializer.isInitialized()) { - initializer.initialize() - initialized += 1 - } - for (field in schema.fields()) { - initializer = field.getInitializer() - if (!initializer.isInitialized()) { - initializer.initialize() - initialized += 1 - } - } - println("Successfully initialized schema '${schema.name}'; created $initialized entities.") - - } - - fun migrate_objects() { - - val objects: List = - parseJsonList(migrationConfig.objectspath, CineastMultimediaObject::class) - val retrievableWriter = schema.connection.getRetrievableWriter() - val filemetadatawriter = schema.get("file")?.getWriter() - ?: throw IllegalArgumentException("Could not find file metadata writer in schema ${schema.name}") - - //val retr_list = mutableListOf() - //val desc_list = mutableListOf() - - //var i = 0 - for (mobject in objects) { - val uuid = RetrievableId.randomUUID() - idmap[mobject.objectid] = uuid.toString() - val objectRetrievable = Ingested( - uuid, - "source", - false - ) - val size = 0L - try { - val size = Files.size(Paths.get(mobject.path)) - } catch (e: Exception) { - println("Could not find file ${mobject.path}, setting size to 0") - } - val fileMetadataDescriptor = FileSourceMetadataDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = objectRetrievable.id, - mapOf( - "path" to Value.String(mobject.path), - "size" to Value.Long(size), - ) - ) - filemetadatawriter.add(fileMetadataDescriptor) - retrievableWriter.add(objectRetrievable) - } - - } - - fun save_idmap() { - val idmapjson = Json.encodeToString(idmap as Map) - Files.writeString(Paths.get("idmap.json"), idmapjson) - } - - fun load_idmap() { - val idmapjson = Files.readString(Paths.get("idmap.json")) - idmap = Json.decodeFromString(idmapjson) - } - - fun migrate_objectmetadata() { - val widths = mutableMapOf() - val heights = mutableMapOf() - - val objectmetadata: List = - parseJsonList(migrationConfig.objectmetadatapath, CineastObjectMetadata::class) - val mediadimensionswriter = schema.get("dimensions")?.getWriter() - ?: throw IllegalArgumentException("Could not find media dimensions writer in schema ${schema.name}") - val videofpswriter = schema.get("fps")?.getWriter() - ?: throw IllegalArgumentException("Could not find video fps writer in schema ${schema.name}") - val videodurationwriter = schema.get("duration")?.getWriter() - ?: throw IllegalArgumentException("Could not find video duration writer in schema ${schema.name}") - - for (mobjectmetadata in objectmetadata) { - val retrievableId = idmap[mobjectmetadata.objectid] - ?: throw IllegalArgumentException("Could not find retrievable id for object ${mobjectmetadata.objectid}") - - if (mobjectmetadata.domain == "technical" && mobjectmetadata.key == "width") { - widths[retrievableId] = mobjectmetadata.value.toInt() - } - if (mobjectmetadata.domain == "technical" && mobjectmetadata.key == "height") { - val height = mobjectmetadata.value.toInt() - heights[retrievableId] = height - - if (widths.containsKey(retrievableId)) { - val width = widths[retrievableId] - ?: throw IllegalArgumentException("Could not find width for object ${mobjectmetadata.objectid}") - val dimensionsDescriptor = MediaDimensionsDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = RetrievableId.fromString(retrievableId), - mapOf( - "width" to Value.Int(width), - "height" to Value.Int(height) - ) - ) - mediadimensionswriter.add(dimensionsDescriptor) - } - } - if (mobjectmetadata.domain == "technical" && mobjectmetadata.key == "fps") { - val fps = mobjectmetadata.value.toFloat() - val retrievableId = idmap[mobjectmetadata.objectid] - ?: throw IllegalArgumentException("Could not find retrievable id for object ${mobjectmetadata.objectid}") - val fpsDescriptor = FloatDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = RetrievableId.fromString(retrievableId), - value = Value.Float(fps) - ) - videofpswriter.add(fpsDescriptor) - } - - if (mobjectmetadata.domain == "technical" && mobjectmetadata.key == "duration") { - val retrievableId = idmap[mobjectmetadata.objectid] - ?: throw IllegalArgumentException("Could not find retrievable id for object ${mobjectmetadata.objectid}") - val duration = mobjectmetadata.value.toFloat() - val durationDescriptor = FloatDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = RetrievableId.fromString(retrievableId), - value = Value.Float(duration) - ) - videodurationwriter.add(durationDescriptor) - } - } - } - - fun migrate_segments() { - val segments: List = parseJsonList(migrationConfig.segmentspath, CineastSegment::class) - val temporalmetadatawriter = schema.get("time")?.getWriter() - ?: throw IllegalArgumentException("Could not find temporal metadata writer in schema ${schema.name}") - val retrievableWriter = schema.connection.getRetrievableWriter() - - val batchSize = 5000 - val ingestedList = mutableListOf() - val temporalMetadataList = mutableListOf() - val parentIdList = mutableListOf() - - for ((index, segment) in segments.withIndex()) { - val uuid = RetrievableId.randomUUID() - idmap[segment.segmentid] = uuid.toString() - - val ingested = Ingested( - uuid, - "segment", - false - ) - - val temporalMetadataDescriptor = TemporalMetadataDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = ingested.id, - mapOf( - "start" to Value.Long(segment.segmentstartabs.toLong() * 1000 * 1000 * 1000), - "end" to Value.Long(segment.segmentendabs.toLong() * 1000 * 1000 * 1000), - ) - - ) - - ingestedList.add(ingested) - temporalMetadataList.add(temporalMetadataDescriptor) - parentIdList.add( - idmap[segment.objectid] - ?: throw IllegalArgumentException("Could not find retrievable id for segment ${segment.objectid}") - ) - - // Check if the batch size is reached - if ((index + 1) % batchSize == 0 || index == segments.size - 1) { - retrievableWriter.addAll(ingestedList) - retrievableWriter.connectAll( - ingestedList.zip(parentIdList).map { - Relationship.ById( - it.first.id, - "isPartOf", - RetrievableId.fromString(it.second) - ?: throw IllegalArgumentException("Could not find retrievable id for segment $it"), - false - ) - } - ) - temporalmetadatawriter.addAll(temporalMetadataList) - - // Clear the lists for the next batch - ingestedList.clear() - temporalMetadataList.clear() - parentIdList.clear() - } - } - } - - fun migrate_segmentmetadata() { - val segmentmetadata: List = - parseJsonList(migrationConfig.segmentmetadatapath, CineastSegmentMetadata::class) - val dominantcolorwriter = schema.get("dominantcolor")?.getWriter() - ?: throw IllegalArgumentException("Could not find dominant color writer in schema ${schema.name}") - - val dominantcolordescriptors = mutableListOf() - for (msegmentmetadata in segmentmetadata) { - if (msegmentmetadata.domain == "dominantcolor" && msegmentmetadata.key == "color") { - val color = msegmentmetadata.value - try { - val retrievableId = RetrievableId.fromString(idmap[msegmentmetadata.segmentid]) - ?: throw IllegalArgumentException("Could not find retrievable id for segment ${msegmentmetadata.segmentid}") - val dominantColorDescriptor = StringDescriptor( - id = DescriptorId.randomUUID(), - retrievableId = retrievableId, - value = Value.String(color) - ) - dominantcolordescriptors.add(dominantColorDescriptor) - } catch (e: Exception) { - println("Could not find retrievable id for segment ${msegmentmetadata.segmentid}") - } - } - } - dominantcolorwriter.addAll(dominantcolordescriptors) - } - - fun migrateAllFeatures() = runBlocking { - migrationConfig.features.map { featureConfig -> - launch(Dispatchers.Default) { // Use the appropriate dispatcher - migrateFeature(featureConfig.fieldname) - } - }.joinAll() // Wait for all tasks to complete - } - - suspend fun migrateFeature(fieldName: String) = withContext(Dispatchers.Default) { - - println("Migrating feature $fieldName") - val featureConfig = migrationConfig.features.find { it.fieldname == fieldName } - ?: throw IllegalArgumentException("Feature config for field $fieldName not found.") - val path = featureConfig.path - - val field = schema.get(name = fieldName) - ?: throw IllegalArgumentException("Field $fieldName does not exist in schema ${schema.name}.") - - val descriptorClass = field.analyser.descriptorClass - - val featureClass = getFeatureClassFromDescriptor(descriptorClass) - ?: throw IllegalArgumentException("Feature class not found for descriptor class $descriptorClass") - - val featureStream = streamJsonItems(path, featureClass) - - val fieldwriter = field.getWriter() - - val fieldreader = field.getReader() - - if (fieldreader.count() > 0) { - println("Field $fieldName already contains ${fieldreader.count()} entries, skipping migration.") - return@withContext - } - - File("$fieldName-skipped_ids.json").bufferedWriter().use { writer -> - writer.write("[") // Start of JSON array - var firstEntry = true - - featureStream.chunked(1000).forEach { batch -> - val descriptors: Iterable = batch.mapNotNull { feature -> - if (!featureClass.isInstance(feature)) { - throw IllegalArgumentException("Feature is not an instance of expected feature class $featureClass") - } - val descriptor = feature.toDescriptor(idmap) - if (descriptor == null) { - if (firstEntry) { - firstEntry = false - } else { - writer.write(",") // Add comma before next entry, except for the first - } - writer.write(Json.encodeToString(feature.id)) - } - descriptor - } - fieldwriter.addAll(descriptors) - } - - writer.write("]") // End of JSON array - } - - println("Finished migrating feature $fieldName") - } -} - -fun main(args: Array) { - // Check for the required arguments - if (args.size < 2) { - println("Usage: ") - return - } - - // Obtain the paths from the command-line arguments - val migrationConfigPath = args[0] - val schemaConfigPath = args[1] - - // Create an instance of the migration tool with the paths - val migrationTool = CineastMigrationTool(migrationConfigPath, schemaConfigPath) - - // Perform the migration - migrationTool.initialize() - migrationTool.load_idmap() - - runBlocking { - migrationTool.migrateFeature("skeletonpose") - } - - println("Migration completed successfully.") -}