All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.internal.actions.SetAction.kt Maven / Gradle / Ivy

There is a newer version: 0.23.0
Show newest version
package io.kform.internal.actions

import io.kform.*
import io.kform.internal.INITIAL_VALUE
import io.kform.internal.UNINITIALIZED

/**
 * Action that sets [toSet] as children of parent values matching [parentPath]. The children to set
 * are represented by [fragment]. [fragment] **cannot** be a recursive wildcard.
 *
 * To reset a value to its initial value, set [toSet] as [INITIAL_VALUE].
 */
internal class SetAction(
    formManager: FormManager,
    override val parentPath: AbsolutePath?,
    parentSchema: ParentSchema?,
    override val fragment: AbsolutePathFragment?,
    private val toSet: Any?
) : WriteValueStateAction(formManager) {
    override fun toString() = if (toSet === INITIAL_VALUE) "Reset($path)" else "Set($path, $toSet)"

    // When the parent schema supports concurrent sets, then we can simply lock the exact child
    // being set instead of the whole parent value
    override val accessedPath =
        (if (parentSchema?.supportsConcurrentSets == true) path
        else parentPath ?: AbsolutePath.ROOT) + AbsolutePathFragment.RecursiveWildcard

    override suspend fun run() {
        // Set root value
        if (parentPath == null) {
            @Suppress("UNCHECKED_CAST")
            withSchemaEventsBus { eventsBus ->
                val formSchema = formManager.formSchema as Schema
                val valueToSet = if (toSet === INITIAL_VALUE) formSchema.initialValue else toSet
                formManager.formValue =
                    if (formManager.formValue === UNINITIALIZED)
                        formSchema.init(AbsolutePath.ROOT, valueToSet, eventsBus)
                    else
                        formSchema.change(
                            AbsolutePath.ROOT,
                            formManager.formValue,
                            valueToSet,
                            eventsBus
                        )
            }
            return
        }

        fragment ?: error("Fragment cannot be null when [parentPath] is not null.")
        valueInfo(parentPath).collect { (parentValue, parentSchema, parentPath, parentSchemaPath) ->
            @Suppress("UNCHECKED_CAST") (parentSchema as ParentSchema)
            // Always support setting all children via a wildcard
            if (
                fragment !is AbsolutePathFragment.Wildcard &&
                    !parentSchema.isValidSetFragment(parentValue, fragment)
            ) {
                throw ExceptionAtPath(parentPath, "Cannot set child fragment: '$fragment'.")
            }
            // Disallow resetting a value that doesn't exist
            if (fragment is AbsolutePathFragment.CollectionEnd && toSet === INITIAL_VALUE) {
                throw ExceptionAtPath(parentPath, "Cannot reset child fragment: '$fragment'.")
            }
            withSchemaEventsBus { eventsBus ->
                // Set all children
                if (fragment is AbsolutePathFragment.Wildcard) {
                    parentSchema
                        .children(parentPath, parentSchemaPath, parentValue, fragment)
                        .collect { (_, childSchema, childPath) ->
                            val valueToSet =
                                if (toSet === INITIAL_VALUE) childSchema.initialValue else toSet
                            parentSchema.set(
                                parentPath,
                                parentValue,
                                childPath.lastFragment!!,
                                valueToSet,
                                eventsBus
                            )
                        }
                }
                // Set single child
                else {
                    val valueToSet =
                        if (toSet === INITIAL_VALUE)
                            parentSchema
                                .childrenSchemas(parentSchemaPath, parentPath, fragment)
                                .single()
                                .schema
                                .initialValue
                        else toSet
                    parentSchema.set(parentPath, parentValue, fragment, valueToSet, eventsBus)
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy