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

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

The newest version!
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.NodeProperty
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 java.lang.reflect.Parameter
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: Aggregate.(CollektiveDevice

) -> 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) } } /** * Create a [RunCollektiveProgram] with a specific [entrypoint] and a [node]. */ constructor( node: Node, entrypoint: String, ) : this(node, entrypoint, findEntrypoint(entrypoint)) /** * 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)) override fun cloneAction( node: Node, reaction: Reaction, ): Action = RunCollektiveProgram(node, name) override fun execute() { collektiveProgram.cycle().also { node.setConcentration(programIdentifier, it) } } override fun getContext(): Context = Context.NEIGHBORHOOD private companion object { private fun

> findEntrypoint( entrypoint: String, ): Aggregate.(CollektiveDevice

) -> 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) } private fun

> buildEntryPoint(method: Method): Aggregate.(CollektiveDevice

) -> Any? { val ktFunction = checkNotNull(method.kotlinFunction) { "Method ${method.name} in class ${method.declaringClass.name}" + " cannot be converted to a Kotlin function" } // Build the lambda function to be executed return { device: CollektiveDevice

-> val parameters = method.parameters .map { when { it.type.isAssignableFrom(Aggregate::class.java) -> this it.type.isAssignableFrom(CollektiveDevice::class.java) -> device it.type.isAssignableFrom(Node::class.java) -> device.node device.node.hasPropertyCompatibleWith(it) -> device.node.getPropertyCompatibleWith(it) else -> error("Unsupported type ${it.type} in entrypoint ${ktFunction.name}") } }.toTypedArray() ktFunction.call(*parameters) } } private fun Node<*>.hasPropertyCompatibleWith(parameter: Parameter): Boolean = properties.any { parameter.type.isAssignableFrom(it::class.java) } private fun Node<*>.getPropertyCompatibleWith(property: Parameter): NodeProperty<*> = properties.first { property.type.isAssignableFrom(it::class.java) } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy