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

org.enodeframework.commanding.impl.DefaultCommandExecuteContext.kt Maven / Gradle / Ivy

package org.enodeframework.commanding.impl

import com.google.common.base.Strings
import kotlinx.coroutines.future.await
import org.enodeframework.commanding.CommandExecuteContext
import org.enodeframework.commanding.CommandResult
import org.enodeframework.common.exception.AggregateRootAlreadyExistException
import org.enodeframework.common.exception.AggregateRootNotFoundException
import org.enodeframework.common.io.Task
import org.enodeframework.common.utils.Assert
import org.enodeframework.domain.AggregateRoot
import org.enodeframework.domain.AggregateStorage
import org.enodeframework.domain.Repository
import org.enodeframework.messaging.ApplicationMessage
import org.enodeframework.queue.MessageContext
import org.enodeframework.queue.QueueMessage
import org.enodeframework.queue.SendReplyService
import org.enodeframework.queue.command.GenericCommandMessage
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap

/**
 * @author [email protected]
 */
class DefaultCommandExecuteContext(
    repository: Repository,
    aggregateRootStorage: AggregateStorage,
    queueMessage: QueueMessage,
    messageContext: MessageContext,
    genericCommandMessage: GenericCommandMessage,
    sendReplyService: SendReplyService
) : CommandExecuteContext {
    private val trackingAggregateRootDict: ConcurrentMap
    private val repository: Repository
    private val aggregateRootStorage: AggregateStorage
    private val sendReplyService: SendReplyService
    private val queueMessage: QueueMessage
    private val messageContext: MessageContext
    private val genericCommandMessage: GenericCommandMessage
    override var result: String = ""
    override var applicationMessage: ApplicationMessage? = null
    override fun onCommandExecutedAsync(commandResult: CommandResult): CompletableFuture {
        messageContext.onMessageHandled(queueMessage)
        return if (Strings.isNullOrEmpty(genericCommandMessage.replyAddress)) {
            Task.completedTask
        } else sendReplyService.sendCommandReply(commandResult, genericCommandMessage.replyAddress)
    }

    override suspend fun add(aggregateRoot: AggregateRoot) {
        addAsync(aggregateRoot).await()
    }

    private fun addInternal(aggregateRoot: AggregateRoot) {
        Assert.nonNull(aggregateRoot, "aggregateRoot")
        if (trackingAggregateRootDict.containsKey(aggregateRoot.uniqueId)) {
            throw AggregateRootAlreadyExistException(aggregateRoot.uniqueId, aggregateRoot.javaClass)
        }
        trackingAggregateRootDict[aggregateRoot.uniqueId] = aggregateRoot
    }

    override fun addAsync(aggregateRoot: AggregateRoot): CompletableFuture {
        addInternal(aggregateRoot)
        return Task.completedTask
    }

    /**
     * Get an aggregate from the current command context.
     */
    override fun  getAsync(
        id: String,
        firstFromCache: Boolean,
        aggregateRootType: Class
    ): CompletableFuture {
        Assert.nonNull(id, "id")
        val trackingAggregateRoot = trackingAggregateRootDict[id] as T
        var future = CompletableFuture()
        if (trackingAggregateRoot != null) {
            future.complete(trackingAggregateRoot)
            return future
        }
        if (firstFromCache) {
            future = repository.getAsync(aggregateRootType, id)
        } else {
            future = aggregateRootStorage.getAsync(aggregateRootType, id)
        }
        return future.thenApply { aggregateRoot: T ->
            if (aggregateRoot == null) {
                throw AggregateRootNotFoundException(id, aggregateRootType)
            }
            trackingAggregateRootDict[aggregateRoot.uniqueId] = aggregateRoot
            repository.refreshAggregate(aggregateRoot)
            aggregateRoot
        }
    }

    override fun  getAsync(id: String, aggregateRootType: Class): CompletableFuture {
        return getAsync(id, true, aggregateRootType)
    }

    override suspend fun  get(id: String, firstFromCache: Boolean, aggregateRootType: Class): T {
        return getAsync(id, firstFromCache, aggregateRootType).await()
    }

    override suspend fun  get(id: String, aggregateRootType: Class): T {
        return getAsync(id, aggregateRootType).await()
    }

    override val trackedAggregateRoots: List
        get() = ArrayList(trackingAggregateRootDict.values)

    override fun clear() {
        trackingAggregateRootDict.clear()
        result = ""
    }

    init {
        trackingAggregateRootDict = ConcurrentHashMap()
        this.repository = repository
        this.aggregateRootStorage = aggregateRootStorage
        this.sendReplyService = sendReplyService
        this.queueMessage = queueMessage
        this.genericCommandMessage = genericCommandMessage
        this.messageContext = messageContext
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy