
no.ntnu.ihb.sspgen.dsl.osp.OspConnectionsContext.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dsl Show documentation
Show all versions of dsl Show documentation
A Kotlin DSL for generating SSP archives
package no.ntnu.ihb.sspgen.dsl
import no.ntnu.ihb.fmi4j.modeldescription.ModelDescription
import no.ntnu.ihb.fmi4j.modeldescription.variables.Causality
import no.ntnu.ihb.sspgen.dsl.annotations.Scoped
import no.ntnu.ihb.sspgen.dsl.extensions.getSourceFileName
import no.ntnu.ihb.sspgen.osp.OspModelDescriptionType
import no.ntnu.ihb.sspgen.osp.VariableType
import no.ntnu.ihb.sspgen.ssp.TComponent
import no.ntnu.ihb.sspgen.ssp.TSystem
import javax.xml.bind.annotation.XmlElement
@Scoped
class OspConnectionsContext(
private val system: TSystem,
private val modelDescriptions: Map,
private val ospModelDescriptions: Map
) {
private fun VariableGroupIdentifier.getOspVariableGroup(osp: OspModelDescriptionType): Any {
val vgs = osp.variableGroups
vgs.javaClass.declaredFields.forEach { f1 ->
f1.getAnnotation(XmlElement::class.java)?.also { annotation ->
if (annotation.name.toLowerCase().contains("port")) {
f1.isAccessible = true
(f1.get(vgs) as? List<*>)?.onEach { e ->
val name = e!!.javaClass.getDeclaredField("name").let {
it.isAccessible = true
it.get(e)
}
if (name == this.groupName) {
return e
}
}
}
}
}
throw IllegalStateException("No variable group named '${this.groupName}' found in component '${this.componentName}'")
}
private fun Any.getTypes(): List {
val types = mutableListOf()
this.javaClass.declaredFields.forEach { f1 ->
f1.getAnnotation(XmlElement::class.java)?.also {
if (f1.type.name.toLowerCase().contains("type")) {
f1.isAccessible = true
types.add(f1.get(this))
}
}
}
return types
}
private fun Any.getVariables(): List {
val refs = mutableListOf()
val variables = this.javaClass.getDeclaredField("variable").let {
it.isAccessible = true
it.get(this) as List<*>
}
variables.forEach { variable ->
refs.add(variable as VariableType)
}
return refs
}
private fun VariableGroupIdentifier.getComponent(): TComponent {
return system.elements.component.firstOrNull { it.name == this.componentName }
?: throw IllegalStateException("No component named '${this.componentName}'")
}
private fun VariableGroupIdentifier.getModelDescription(): ModelDescription {
val component = getComponent()
return modelDescriptions[component.getSourceFileName()]
?: throw IllegalStateException("No modelDescription.xml available for component '${this.componentName}'")
}
private fun VariableGroupIdentifier.getOspModelDescription(): OspModelDescriptionType {
val component = getComponent()
return ospModelDescriptions[component.getSourceFileName()]
?: throw IllegalStateException("No OspModelDescription.xml available for component '${this.componentName}'")
}
infix fun String.to(other: String) {
val vgi1 = VariableGroupIdentifier(this)
val vgi2 = VariableGroupIdentifier(other)
val md1 = vgi1.getModelDescription()
val md2 = vgi2.getModelDescription()
val osp1 = vgi1.getOspModelDescription()
val osp2 = vgi2.getOspModelDescription()
val vg1 = vgi1.getOspVariableGroup(osp1)
val vg2 = vgi2.getOspVariableGroup(osp2)
require(vg1.javaClass == vg2.javaClass) { "${vg1.javaClass} !=${vg2.javaClass}" }
val types1 = vg1.getTypes()
val types2 = vg2.getTypes()
require(types1.isNotEmpty())
require(types2.isNotEmpty())
require(types1.size == types2.size) { "Dimension mismatch" }
for (i in types1.indices) {
val t1 = types1[i]
val t2 = types2[i]
val v1 = t1.getVariables()
val v2 = t2.getVariables()
require(v1.size == v2.size) { "Dimension mismatch" }
for (j in v1.indices) {
val ref1 = v1[j].ref
val ref2 = v2[j].ref
TSystem.Connections.Connection().also { connection ->
when (md1.modelVariables.getByName(ref1).causality) {
Causality.CALCULATED_PARAMETER, Causality.OUTPUT -> {
connection.startElement = vgi1.componentName
connection.startConnector = ref1
connection.endElement = vgi2.componentName
connection.endConnector = ref2
}
else -> {
connection.startElement = vgi2.componentName
connection.startConnector = ref2
connection.endElement = vgi1.componentName
connection.endConnector = ref1
}
}
system.connections.connection.add(connection)
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy