SemanticAdaptationCanonicalGenerator.xtend 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. /*
  2. * generated by Xtext 2.10.0
  3. */
  4. package be.uantwerpen.ansymo.semanticadaptation.generator
  5. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Adaptation
  6. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BoolLiteral
  7. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BuiltinFunction
  8. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Close
  9. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Connection
  10. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DeclaredParameter
  11. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Expression
  12. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.FMU
  13. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMU
  14. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMUDeclaration
  15. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMUDeclarationFull
  16. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IntLiteral
  17. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IsSet
  18. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Port
  19. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.RealLiteral
  20. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
  21. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptationFactory
  22. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleParamDeclaration
  23. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleVarDeclaration
  24. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StringLiteral
  25. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Unity
  26. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Variable
  27. import java.io.ByteArrayOutputStream
  28. import java.util.HashMap
  29. import java.util.LinkedList
  30. import org.eclipse.emf.ecore.EObject
  31. import org.eclipse.emf.ecore.resource.Resource
  32. import org.eclipse.xtext.EcoreUtil2
  33. import org.eclipse.xtext.generator.AbstractGenerator
  34. import org.eclipse.xtext.generator.IFileSystemAccess2
  35. import org.eclipse.xtext.generator.IGeneratorContext
  36. /**
  37. * Generates code from your model files on save.
  38. *
  39. * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
  40. */
  41. class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
  42. String CANONICAL_EXT = ".BASE.sa"
  43. String NAME_SUFFIX = "_BASE"
  44. override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
  45. Log.push("Generating canonical semantic adaptation for file " + resource.URI.toFileString() + "...")
  46. Log.println("Resource URI information:")
  47. Log.println("\t resource.URI.lastSegment = " + resource.URI.lastSegment())
  48. Log.println("\t resource.URI.trimFileExtension = " + resource.URI.trimFileExtension())
  49. // Create in memory representation of canonical SA file
  50. var adaptations = resource.allContents.toIterable.filter(SemanticAdaptation).last.elements.filter(Adaptation);
  51. if (adaptations.size > 1){
  52. throw new Exception("Only one semantic adaptation is supported per .sa file")
  53. }
  54. var adaptation = adaptations.head
  55. Log.println(prettyprint_model(adaptation, "File Read"))
  56. // Create file name for the canonical sa file
  57. var fileNameWithoutExt = resource.URI.trimFileExtension().lastSegment()
  58. var canonicalFileName = fileNameWithoutExt + CANONICAL_EXT
  59. Log.println("canonicalFileName = " + canonicalFileName)
  60. Log.println("Checking if file is already a canonical version...")
  61. if (adaptation.name.indexOf(NAME_SUFFIX) == -1){
  62. Log.println("It is not.")
  63. adaptation.name = adaptation.name + NAME_SUFFIX
  64. canonicalize(adaptation)
  65. Log.println(prettyprint_model(adaptation, "Generated File"))
  66. fsa.generateFile(canonicalFileName, adaptation.serialize_model)
  67. Log.println("File " + canonicalFileName + " written.")
  68. } else {
  69. Log.println("It is already a canonical version.")
  70. Log.println("Nothing to do.")
  71. }
  72. Log.pop("Generating canonical semantic adaptation for file " + resource.URI.toFileString() + "... DONE.")
  73. }
  74. def prettyprint_model(Adaptation sa, String title){
  75. var outputByteArray = new ByteArrayOutputStream()
  76. sa.eResource.save(outputByteArray,null)
  77. return "______________________________" + title + "______________________________\n" +
  78. sa.serialize_model +
  79. "\n__________________________________________________________________________"
  80. }
  81. def serialize_model(Adaptation sa){
  82. var outputByteArray = new ByteArrayOutputStream()
  83. sa.eResource.save(outputByteArray,null)
  84. return outputByteArray.toString()
  85. }
  86. def canonicalize(Adaptation sa){
  87. Log.push("Canonicalize")
  88. // Unit inference
  89. var unitlessElements = genericDeclarationInferenceAlgorithm(sa ,
  90. [// getField
  91. element | {
  92. var DUMMY_UNIT = "Dips"
  93. if (element instanceof SingleParamDeclaration) {
  94. return DUMMY_UNIT
  95. } else if (element instanceof Port){
  96. return element.unity
  97. } else if (element instanceof SingleVarDeclaration){
  98. return DUMMY_UNIT
  99. } else {
  100. throw new Exception("Unexpected element type: " + element)
  101. }
  102. }
  103. ],
  104. [// setField
  105. element, value | {
  106. if (element instanceof SingleParamDeclaration) {
  107. } else if (element instanceof Port){
  108. element.unity = EcoreUtil2.copy(value as Unity)
  109. } else if (element instanceof SingleVarDeclaration){
  110. } else {
  111. throw new Exception("Unexpected element type: " + element)
  112. }
  113. }
  114. ],
  115. [// inferField
  116. element | {
  117. var DUMMY_UNIT = "Dips"
  118. if (element instanceof SingleParamDeclaration) {
  119. return DUMMY_UNIT
  120. } else if (element instanceof Port){
  121. return getPortUnit(element)
  122. } else if (element instanceof SingleVarDeclaration){
  123. return DUMMY_UNIT
  124. } else {
  125. throw new Exception("Unexpected element type: " + element)
  126. }
  127. }
  128. ]
  129. )
  130. if (unitlessElements > 0){
  131. Log.println("Could not infer all element units. There are " + unitlessElements + " unitless elements.")
  132. }
  133. // Type inference
  134. var untypedElements = genericDeclarationInferenceAlgorithm(sa ,
  135. [// getField
  136. element | {
  137. if (element instanceof SingleParamDeclaration) {
  138. return element.type
  139. } else if (element instanceof Port){
  140. return element.type
  141. } else if (element instanceof SingleVarDeclaration){
  142. return element.type
  143. } else {
  144. throw new Exception("Unexpected element type: " + element)
  145. }
  146. }
  147. ],
  148. [// setField
  149. element, value | {
  150. if (element instanceof SingleParamDeclaration) {
  151. element.type = value as String
  152. } else if (element instanceof Port){
  153. element.type = value as String
  154. } else if (element instanceof SingleVarDeclaration){
  155. element.type = value as String
  156. } else {
  157. throw new Exception("Unexpected element type: " + element)
  158. }
  159. }
  160. ],
  161. [// inferField
  162. element | {
  163. if (element instanceof SingleParamDeclaration) {
  164. return extractTypeFromExpression(element.expr, element.name)
  165. } else if (element instanceof Port){
  166. return getPortType(element)
  167. } else if (element instanceof SingleVarDeclaration){
  168. return extractTypeFromExpression(element.expr, element.name)
  169. } else {
  170. throw new Exception("Unexpected element type: " + element)
  171. }
  172. }
  173. ]
  174. )
  175. if (untypedElements > 0){
  176. Log.println("Error: Could not infer all types. There are " + untypedElements + " untyped elements.")
  177. Log.println(prettyprint_model(sa, "Current File"))
  178. throw new Exception("Could not infer all types. There are " + untypedElements + " untyped elements.")
  179. }
  180. // Add input ports
  181. addInPorts(sa)
  182. // Add in params
  183. //addInParams(sa)
  184. Log.pop("Canonicalize")
  185. }
  186. def genericDeclarationInferenceAlgorithm(Adaptation sa,
  187. (EObject)=>Object getField,
  188. (EObject, Object)=>void setField,
  189. (EObject)=>Object inferField
  190. ){
  191. Log.push("Running generic inference algorithm...")
  192. /*
  193. * Dumbest (and simplest) algorithm for this is a fixed point computation:
  194. * 1. Look for every var/port declaration
  195. * 2. If that var has a XXX already, nothing else to be done.
  196. * 3. If that var has no XXX declared, then
  197. * 3.1 If var/port has an initial value or connection, then
  198. * 3.1.1 If the initial_value/connection has a XXX declared, then var gets that XXX.
  199. * 3.1.2 Otherwise, nothing else to be done.
  200. * 3.2 If var/port has no initial value or connection then this either is a missing feature, or an error.
  201. * 3.3 If something has changed, go to 1. Otherwise, end.
  202. *
  203. * An extra set of instructions is there to push the element field information using connections and bindings.
  204. */
  205. var fixedPoint = false
  206. var unfieldedElementsCounter = 0
  207. while (! fixedPoint){
  208. fixedPoint = true
  209. unfieldedElementsCounter = 0
  210. Log.println("Inferring parameter fields...")
  211. for (paramDeclarations : sa.params) {
  212. for (paramDeclaration : paramDeclarations.declarations) {
  213. Log.println("Computing field for param " + paramDeclaration.name)
  214. if(getField.apply(paramDeclaration) !== null){
  215. Log.println("Already has been inferred: " + getField.apply(paramDeclaration))
  216. } else {
  217. Log.println("Has not been inferred yet.")
  218. if (tryInferAndAssignField(paramDeclaration, getField, setField, inferField)){
  219. fixedPoint = false
  220. } else {
  221. unfieldedElementsCounter++
  222. }
  223. }
  224. }
  225. }
  226. if(sa.inner !== null){
  227. if(sa.inner instanceof InnerFMUDeclarationFull){
  228. var innerFMUFull = sa.inner as InnerFMUDeclarationFull
  229. for(fmu : innerFMUFull.fmus){
  230. Log.println("Inferring port fields of FMU " + fmu.name)
  231. for (port : EcoreUtil2.getAllContentsOfType(fmu, Port)) {
  232. if(getField.apply(port) !== null){
  233. Log.println("Already has a field: " + getField.apply(port))
  234. } else {
  235. if (tryInferAndAssignField(port, getField, setField, inferField)){
  236. fixedPoint = false
  237. } else {
  238. unfieldedElementsCounter++
  239. }
  240. }
  241. }
  242. }
  243. if (innerFMUFull.connection.size > 0){
  244. Log.println("Inferring port fields using internal scenario bindings.")
  245. for (binding : innerFMUFull.connection){
  246. if (getField.apply(binding.src.port) !== null && getField.apply(binding.tgt.port) !== null){
  247. Log.println("Both ports have fields already.")
  248. } else {
  249. var inferredFieldAttempt = inferPortFieldViaConnection(binding, getField, setField, inferField)
  250. if (inferredFieldAttempt !== null){
  251. if (getField.apply(binding.src.port) === null){
  252. setField.apply(binding.src.port, inferredFieldAttempt)
  253. } else if (getField.apply(binding.tgt.port) === null){
  254. setField.apply(binding.tgt.port, inferredFieldAttempt)
  255. }
  256. fixedPoint = false
  257. unfieldedElementsCounter--
  258. Log.println("Got new field: " + inferredFieldAttempt)
  259. } else {
  260. Log.println("Cannot infer field from binding now.")
  261. }
  262. }
  263. }
  264. }
  265. } else {
  266. throw new Exception("Field inference only supported for InnerFMUDeclarationFull.")
  267. }
  268. }
  269. Log.println("Inferring external port fields...")
  270. var externalPorts = new LinkedList(sa.inports)
  271. externalPorts.addAll(sa.outports)
  272. for (port : externalPorts) {
  273. if (getField.apply(port) !== null){
  274. Log.println("Already has a field: " + getField.apply(port))
  275. if (pushPortField(port, getField, setField, inferField)){
  276. fixedPoint = false
  277. unfieldedElementsCounter--
  278. }
  279. } else {
  280. if (tryInferAndAssignField(port, getField, setField, inferField)){
  281. fixedPoint = false
  282. } else {
  283. unfieldedElementsCounter++
  284. }
  285. }
  286. }
  287. Log.println("Inferring all other declaration fields...")
  288. for (varDeclaration : EcoreUtil2.getAllContentsOfType(sa, SingleVarDeclaration)) {
  289. Log.println("Computing field for declaration " + varDeclaration.name)
  290. if(getField.apply(varDeclaration) !== null){
  291. Log.println("Already has a field: " + getField.apply(varDeclaration))
  292. } else {
  293. if (tryInferAndAssignField(varDeclaration, getField, setField, inferField)){
  294. fixedPoint = false
  295. } else {
  296. unfieldedElementsCounter++
  297. }
  298. }
  299. }
  300. Log.println("Ended iteration with unfielded elements remaining: " + unfieldedElementsCounter)
  301. } // while (! fixedPoint)
  302. Log.pop("Running generic inference algorithm... DONE")
  303. return unfieldedElementsCounter
  304. }
  305. def tryInferAndAssignField(EObject element,
  306. (EObject)=>Object getField,
  307. (EObject, Object)=>void setField,
  308. (EObject)=>Object inferField) {
  309. var inferredFieldAttempt = inferField.apply(element)
  310. if (inferredFieldAttempt !== null){
  311. setField.apply(element, inferredFieldAttempt)
  312. Log.println("Got new field: " + inferredFieldAttempt)
  313. return true
  314. } else {
  315. Log.println("Cannot infer field now.")
  316. return false
  317. }
  318. }
  319. def extractTypeFromExpression(Expression expression, String declarationName){
  320. if (expression instanceof IntLiteral){
  321. return "Integer"
  322. } else if (expression instanceof RealLiteral){
  323. return "Real"
  324. } else if (expression instanceof BoolLiteral){
  325. return "Bool"
  326. } else if (expression instanceof StringLiteral){
  327. return "String"
  328. } else if (expression instanceof Variable){
  329. var varRef = expression as Variable
  330. if (varRef.ref instanceof Port){
  331. var decl = varRef.ref as Port
  332. if (decl.type !== null){
  333. return decl.type
  334. }
  335. } else if(varRef.ref instanceof SingleParamDeclaration){
  336. var decl = varRef.ref as SingleParamDeclaration
  337. if (decl.type !== null){
  338. return decl.type
  339. }
  340. } else if(varRef.ref instanceof SingleVarDeclaration){
  341. var decl = varRef.ref as SingleVarDeclaration
  342. if (decl.type !== null){
  343. return decl.type
  344. }
  345. } else if(varRef.ref instanceof DeclaredParameter){
  346. throw new Exception("Type cannot be inferred for references to DeclaredParameter (for now). Please specify the explicit type of declaration " + declarationName)
  347. } else {
  348. throw new Exception("Unexpected kind of Variable expression found.")
  349. }
  350. } else if(expression instanceof BuiltinFunction){
  351. if (expression instanceof IsSet || expression instanceof Close){
  352. return "Bool"
  353. } else {
  354. return "Real"
  355. }
  356. } else {
  357. throw new Exception("Initial value for declaration " + declarationName + " must be literal or var ref for now. Got instead " + expression + ". If you want complex expressions, give it an explicit type.")
  358. }
  359. return null
  360. }
  361. def inferPortFieldViaConnection(Connection binding,
  362. (EObject)=>Object getField,
  363. (EObject, Object)=>void setField,
  364. (EObject)=>Object inferField
  365. ){
  366. var Object resultField = null
  367. if (getField.apply(binding.src.port) !== null && getField.apply(binding.tgt.port) !== null){
  368. throw new Exception("Wrong way of using this function. It assumes type is not inferred yet.")
  369. } else if (getField.apply(binding.src.port) !== null){
  370. resultField = getField.apply(binding.src.port)
  371. Log.println("Target port "+ binding.tgt.port.name +" got new type: " + resultField)
  372. } else if (getField.apply(binding.tgt.port) !== null){
  373. resultField = getField.apply(binding.tgt.port)
  374. Log.println("Target port "+ binding.src.port.name +" got new type: " + resultField)
  375. }
  376. return resultField
  377. }
  378. def pushPortField(Port port,
  379. (EObject)=>Object getField,
  380. (EObject, Object)=>void setField,
  381. (EObject)=>Object inferField){
  382. var fieldInferred = false
  383. Log.println("Pushing field of port " + port.name + " to its bindings.")
  384. if(getField.apply(port) === null){
  385. Log.println("Has no field to be pushed.")
  386. throw new Exception("Wrong way of using this function. It assumes field is already inferred.")
  387. } else {
  388. Log.println("Pushing field: " + getField.apply(port))
  389. if(port.sourcedependency !== null){
  390. Log.println("Has a source dependency: " + port.sourcedependency.port.name)
  391. if(getField.apply(port.sourcedependency.port) === null){
  392. setField.apply(port.sourcedependency.port, getField.apply(port))
  393. Log.println("Port " + port.sourcedependency.port.name + " got new type: " + getField.apply(port.sourcedependency.port))
  394. fieldInferred = true
  395. } else {
  396. Log.println("Source port already has field.")
  397. }
  398. } else {
  399. Log.println("Has no source dependency.")
  400. }
  401. if (port.targetdependency !== null) {
  402. Log.println("Has a target dependency: " + port.targetdependency.port.name)
  403. if(getField.apply(port.targetdependency.port) === null){
  404. Log.println("Dependency has no field yet.")
  405. setField.apply(port.targetdependency.port, getField.apply(port))
  406. Log.println("Port " + port.targetdependency.port.name + " got new type: " + getField.apply(port.targetdependency.port))
  407. fieldInferred = true
  408. } else {
  409. Log.println("Target port already has field.")
  410. }
  411. } else {
  412. Log.println("Has no target dependency.")
  413. }
  414. }
  415. return fieldInferred
  416. }
  417. def getPortUnit(Port port){
  418. var unitInferred = false
  419. Log.println("Computing unit for port " + port.name)
  420. var Unity returnUnit = null
  421. if(port.unity !== null){
  422. throw new Exception("Wrong way of using this function. It assumes unit is not inferred yet.")
  423. } else {
  424. Log.println("Has no unit.")
  425. Log.println("Attempting to infer unit from bindings.")
  426. if(port.sourcedependency !== null){
  427. Log.println("Has a source dependency: " + port.sourcedependency.port.name)
  428. if(port.sourcedependency.port.unity === null){
  429. Log.println("Dependency has no unit yet.")
  430. } else {
  431. returnUnit = port.sourcedependency.port.unity
  432. Log.println("Got new unit: " + returnUnit)
  433. unitInferred = true
  434. }
  435. } else {
  436. Log.println("Has no source dependency.")
  437. }
  438. if (port.targetdependency !== null && !unitInferred) {
  439. Log.println("Has a target dependency: " + port.targetdependency.owner.name + "." + port.targetdependency.port.name)
  440. if(port.targetdependency.port.unity === null){
  441. Log.println("Dependency has no unit yet.")
  442. } else {
  443. returnUnit = port.targetdependency.port.unity
  444. Log.println("Got new unit: " + returnUnit)
  445. unitInferred = true
  446. }
  447. } else {
  448. Log.println("Has no target dependency, or unit has already been inferred from source dependency.")
  449. }
  450. }
  451. return returnUnit
  452. }
  453. def getPortType(Port port){
  454. var typeInferred = false
  455. Log.println("Computing type for port " + port.name)
  456. var String returnType = null
  457. if(port.type !== null){
  458. throw new Exception("Wrong way of using this function. It assumes type is not inferred yet.")
  459. } else {
  460. Log.println("Has no type.")
  461. Log.println("Attempting to infer type from units.")
  462. if (port.unity !== null){
  463. returnType = "Real"
  464. Log.println("Got new type: " + returnType)
  465. typeInferred = true
  466. } else {
  467. Log.println("Attempting to infer type from bindings.")
  468. if(port.sourcedependency !== null){
  469. Log.println("Has a source dependency: " + port.sourcedependency.port.name)
  470. if(port.sourcedependency.port.type === null){
  471. Log.println("Dependency has no type yet.")
  472. } else {
  473. returnType = port.sourcedependency.port.type
  474. Log.println("Got new type: " + returnType)
  475. typeInferred = true
  476. }
  477. } else {
  478. Log.println("Has no source dependency.")
  479. }
  480. if (port.targetdependency !== null && !typeInferred) {
  481. Log.println("Has a target dependency: " + port.targetdependency.owner.name + "." + port.targetdependency.port.name)
  482. if(port.targetdependency.port.type === null){
  483. //println("Port object: " + port.targetdependency.port)
  484. Log.println("Dependency has no type yet.")
  485. } else {
  486. returnType = port.targetdependency.port.type
  487. Log.println("Got new type: " + returnType)
  488. typeInferred = true
  489. }
  490. } else {
  491. Log.println("Has no target dependency, or type has already been inferred from source dependency.")
  492. }
  493. }
  494. }
  495. return returnType
  496. }
  497. def addInPorts(Adaptation sa) {
  498. Log.push("Adding input ports...")
  499. for (port : getAllInnerFMUInputPortDeclarations(sa)){
  500. var parentFMU = port.eContainer as InnerFMU
  501. Log.println("Checking if port " + parentFMU.name + "." + port.name + " has incoming connections")
  502. if (! hasIncomingConnection(port, sa)){
  503. Log.println("Port " + parentFMU.name + "." + port.name + " has no incoming connections.")
  504. if (findExternalPortByName(sa, port.name) === null){
  505. var newExternalPort = createExternalInputPortDeclarationFromInnerPort(port, parentFMU, sa)
  506. Log.println("External port " + newExternalPort.name + " created.")
  507. newExternalPort.bindExternalInputPortTo(parentFMU, port)
  508. Log.println("External port " + newExternalPort.name + " bound to port " + parentFMU.name + "." + port.name)
  509. } else {
  510. Log.println("External port " + port.name + " already declared.")
  511. }
  512. } else {
  513. Log.println("Port " + parentFMU.name + "." + port.name + " has an incoming connection.")
  514. }
  515. }
  516. Log.pop("Adding input ports... DONE")
  517. }
  518. def bindExternalInputPortTo(Port externalInputPort, InnerFMU internalPortParent, Port internalPort) {
  519. externalInputPort.targetdependency = SemanticAdaptationFactory.eINSTANCE.createSpecifiedPort()
  520. externalInputPort.targetdependency.owner = internalPortParent
  521. externalInputPort.targetdependency.port = internalPort
  522. }
  523. def createExternalInputPortDeclarationFromInnerPort(Port port, FMU parent, Adaptation sa) {
  524. var externalInputPort = SemanticAdaptationFactory.eINSTANCE.createPort()
  525. externalInputPort.name = parent.name + "__" + port.name
  526. externalInputPort.type = port.type
  527. externalInputPort.unity = EcoreUtil2.copy(port.unity)
  528. sa.inports.add(externalInputPort)
  529. return externalInputPort
  530. }
  531. def findExternalPortByName(Adaptation adaptation, String name) {
  532. for (externalInputPort : adaptation.inports){
  533. if (externalInputPort.name == name){
  534. return externalInputPort
  535. }
  536. }
  537. return null
  538. }
  539. def hasIncomingConnection(Port port, Adaptation adaptation) {
  540. var result = false
  541. if (port.sourcedependency !== null){
  542. result = true
  543. } else {
  544. if (port.eContainer instanceof InnerFMU){
  545. var innerScenarioDeclaration = EcoreUtil2.getContainerOfType(port, InnerFMUDeclaration)
  546. if (innerScenarioDeclaration instanceof InnerFMUDeclarationFull){
  547. var innerScenarioWithCoupling = innerScenarioDeclaration as InnerFMUDeclarationFull
  548. if (innerScenarioWithCoupling.connection.size > 0){
  549. for (connection : innerScenarioWithCoupling.connection ){
  550. if (connection.tgt.port == port){
  551. var parentFMU = port.eContainer as InnerFMU
  552. var sourceFMU = connection.src.port.eContainer as InnerFMU
  553. Log.println("Port " + parentFMU.name + "." + port.name + " has an incoming connection from internal port " + sourceFMU.name + "." + connection.src.port.name)
  554. result = true
  555. }
  556. }
  557. }
  558. }
  559. for (externalInputPort : adaptation.inports.filter[p | p.targetdependency !== null]){
  560. if (externalInputPort.targetdependency.port == port){
  561. var parentFMU = port.eContainer as InnerFMU
  562. Log.println("Port " + parentFMU.name + "." + port.name + " has an incoming connection from external port " + externalInputPort.name)
  563. result = true
  564. }
  565. }
  566. }
  567. }
  568. return result
  569. }
  570. def getAllInnerFMUInputPortDeclarations(Adaptation sa){
  571. var result = new LinkedList()
  572. if(sa.inner !== null){
  573. if(sa.inner instanceof InnerFMUDeclarationFull){
  574. var innerFMUFull = sa.inner as InnerFMUDeclarationFull
  575. for(fmu : innerFMUFull.fmus){
  576. result.addAll(fmu.inports)
  577. }
  578. } else {
  579. throw new Exception("Only support for InnerFMUDeclarationFull.")
  580. }
  581. }
  582. return result;
  583. }
  584. def addInParams(Adaptation sa) {
  585. Log.push("Adding input parameters...")
  586. val PARAM_PREFIX = "INIT_"
  587. var inputPort_to_parameterDeclaration_Map = new HashMap<Port, SingleParamDeclaration>(sa.inports.size)
  588. for (inputPortDeclaration : sa.inports) {
  589. Log.println("Generating parameter for port " + inputPortDeclaration.name)
  590. var paramname = PARAM_PREFIX + inputPortDeclaration.name.toUpperCase()
  591. var paramAlreadyDeclared = false
  592. for(paramDeclarations : sa.params){
  593. for(paramDeclaration : paramDeclarations.declarations){
  594. if(paramDeclaration.name == paramname){
  595. paramAlreadyDeclared = true
  596. }
  597. }
  598. }
  599. if (paramAlreadyDeclared){
  600. Log.println("Parameter " + paramname + " already declared for port " + inputPortDeclaration.name)
  601. } else {
  602. Log.println("Declaring new parameter " + paramname + " for port " + inputPortDeclaration.name)
  603. var factory = SemanticAdaptationFactory.eINSTANCE
  604. if (sa.params.size == 0){
  605. sa.params.add(factory.createParamDeclarations())
  606. }
  607. var paramDeclaration = factory.createSingleParamDeclaration()
  608. // TODO Continue here after solving problem with ports.
  609. //adaptation.params.head.declarations.add()
  610. }
  611. }
  612. Log.pop("Adding input parameters... DONE")
  613. }
  614. }