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

it.unibo.alchemist.actions.RunCollektiveProgram.kt Maven / Gradle / Ivy

package it.unibo.alchemist.actions

import it.unibo.alchemist.collektive.device.CollektiveDevice
import it.unibo.alchemist.model.Action
import it.unibo.alchemist.model.Context
import it.unibo.alchemist.model.Node
import it.unibo.alchemist.model.Node.Companion.asProperty
import it.unibo.alchemist.model.Position
import it.unibo.alchemist.model.Reaction
import it.unibo.alchemist.model.actions.AbstractAction
import it.unibo.alchemist.model.molecules.SimpleMolecule
import it.unibo.collektive.Collektive
import it.unibo.collektive.aggregate.api.Aggregate
import java.lang.reflect.Method
import kotlin.reflect.jvm.kotlinFunction

/**
 * An Alchemist [Action] that runs a [Collektive] program.
 * Requires a [node], a program [name], and the actual [program] to execute.
 */
class RunCollektiveProgram

>( node: Node, val name: String, val program: context(CollektiveDevice

) Aggregate.() -> Any?, ) : AbstractAction(node) { private val programIdentifier = SimpleMolecule(name) /** * The [CollektiveDevice] associated with the [node]. */ val localDevice: CollektiveDevice

= node.asProperty() /** * The [Collektive] program on which cycles will be executed. */ val collektiveProgram: Collektive init { declareDependencyTo(programIdentifier) collektiveProgram = Collektive(localDevice.id, network = localDevice) { program(localDevice, this) } } /** * Create a [RunCollektiveProgram] with a specific [entrypoint] and a [node]. */ constructor( node: Node, entrypoint: String, ) : this(node, entrypoint, findEntrypoint(entrypoint, node.asProperty())) /** * Create a [RunCollektiveProgram] with a specific [entrypoint] and a [node]. */ @JvmOverloads constructor( node: Node, entrypoint: Method, name: String = entrypoint.name, ) : this(node, name, buildEntryPoint(entrypoint, node.asProperty())) override fun cloneAction(node: Node, reaction: Reaction): Action = RunCollektiveProgram(node, name, program) override fun execute() { collektiveProgram.cycle().also { node.setConcentration(programIdentifier, it) } } override fun getContext(): Context = Context.NEIGHBORHOOD companion object { private fun

> findEntrypoint( entrypoint: String, localDevice: CollektiveDevice

, ): context(CollektiveDevice

) Aggregate.() -> Any? { val className = entrypoint.substringBeforeLast(".") val methodName = entrypoint.substringAfterLast(".") val clazz = Class.forName(className) val method = clazz.methods.find { it.name == methodName } ?: error("Entrypoint $entrypoint not found, no method $methodName found in class $className") return buildEntryPoint(method, localDevice) } private fun

> buildEntryPoint( method: Method, localDevice: CollektiveDevice

, ): context(CollektiveDevice

) Aggregate.() -> Any? { val ktfunction = checkNotNull(method.kotlinFunction) { "Method ${method.name} in class ${method.declaringClass.name} cannot be converted to a Kotlin function" } return { val parameters = method.parameters.map { when { it.type.isAssignableFrom(Aggregate::class.java) -> this it.type.isAssignableFrom(CollektiveDevice::class.java) -> localDevice it.type.isAssignableFrom(Node::class.java) -> localDevice.node else -> error("Unsupported type ${it.type} in entrypoint ${ktfunction.name}") } }.toTypedArray() ktfunction.call(*parameters) } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy