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

commonMain.internal.ExternalIssuesDependencies.kt Maven / Gradle / Ivy

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

import io.kform.AbsolutePath
import io.kform.LocatedValidationIssue
import io.kform.Path
import io.kform.collections.mutablePathMultimapOf
import io.kform.collections.set
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

/**
 * Class tracking dependencies of a form manager's external issues, providing coroutine-safe methods
 * to get, add, and remove them.
 */
internal class ExternalIssuesDependencies {
    /** Maps paths to the external issues depending on them. */
    private val pathDependencies = mutablePathMultimapOf()
    /** Maps external contexts to the external issues depending on them. */
    private val externalContextDependencies =
        mutableMapOf>()

    private val mutex = Mutex()

    /** Gets and removes all external issues dependent on [path]. */
    suspend fun getAndRemoveExternalIssuesDependentOnPath(
        path: AbsolutePath
    ): Set {
        mutex.withLock {
            val entriesToRemove = pathDependencies.entries(path).toList()
            for (entry in entriesToRemove) {
                pathDependencies.removeEntry(entry.id)
            }
            val removedIssues = entriesToRemove.mapTo(HashSet(entriesToRemove.size)) { it.value }
            for (issue in removedIssues) {
                removeExternalContextDependencies(issue)
            }
            return removedIssues
        }
    }

    /** Gets and removes all external issues dependent on the external context [externalContext]. */
    suspend fun getAndRemoveExternalIssuesDependentOnExternalContext(
        externalContext: String
    ): Set {
        mutex.withLock {
            val removedIssues = externalContextDependencies.remove(externalContext) ?: emptySet()
            for (issue in removedIssues) {
                removePathDependencies(issue)
            }
            return removedIssues
        }
    }

    /** Adds dependencies from all provided [externalIssues]. */
    suspend fun addDependenciesOfExternalIssues(externalIssues: Iterable) {
        mutex.withLock {
            for (issue in externalIssues) {
                val dependencies = pathDependencies(issue)
                for (dependency in dependencies) {
                    pathDependencies[dependency] = issue
                }
                for (contextDependency in issue.externalContextDependencies) {
                    externalContextDependencies.getOrPut(contextDependency) { mutableSetOf() } +=
                        issue
                }
            }
        }
    }

    /** Removes all dependencies of all provided [externalIssues]. */
    suspend fun removeDependenciesOfExternalIssues(
        externalIssues: Iterable
    ) {
        mutex.withLock {
            for (issue in externalIssues) {
                removePathDependencies(issue)
                removeExternalContextDependencies(issue)
            }
        }
    }

    /**
     * Returns the path dependencies of [externalIssue] taking into consideration whether it
     * [depends on descendants][LocatedValidationIssue.dependsOnDescendants].
     */
    private fun pathDependencies(externalIssue: LocatedValidationIssue): Set {
        val dependencies = externalIssue.dependencies.toMutableSet()
        if (externalIssue.dependsOnDescendants) {
            dependencies += externalIssue.path + Path.DESCENDANTS
        }
        return dependencies
    }

    /** Removes all path dependencies of [externalIssue] from [pathDependencies]. */
    private fun removePathDependencies(externalIssue: LocatedValidationIssue) {
        val dependencies = pathDependencies(externalIssue)
        for (dependency in dependencies) {
            val entriesToRemove =
                pathDependencies.entries(dependency).filter { it.value == externalIssue }.toList()
            for (entry in entriesToRemove) {
                pathDependencies.removeEntry(entry.id)
            }
        }
    }

    /**
     * Removes all external context dependencies of [externalIssue] from
     * [externalContextDependencies].
     */
    private fun removeExternalContextDependencies(externalIssue: LocatedValidationIssue) {
        for (externalContext in externalIssue.externalContextDependencies) {
            externalContextDependencies[externalContext]?.remove(externalIssue)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy