Browse Source

some refactoring, and external ports are created with the same name as the internal ports, to not violate transparency

Cláudio Gomes 4 years ago
parent
commit
04e46bb3c1

+ 7 - 7
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/canonical_generation/sample1.sa

@@ -3,15 +3,15 @@ at "./path/to/FMU.fmu"
 
 	for inner fmu InnerFMU innerFMU1
 		at "./path/to/InnerFMU.fmu"
-		with input ports input_port1(rad), Bool input_port2, input_port3 (N.m)
-		with output ports Real outout_port1, Integer output_port2
+		with input ports innerFMU1__input_port1(rad), Bool innerFMU1__input_port2, innerFMU1__input_port3 (N.m)
+		with output ports Real innerFMU1__outout_port1, Integer innerFMU1__output_port2
 
 	for inner fmu InnerFMU innerFMU2
 		at "./path/to/InnerFMU.fmu"
-		with input ports input_port1(rad), Bool input_port2, input_port3 (N.m)
-		with output ports outout_port1, String output_port2
+		with input ports innerFMU2__input_port1(rad), Bool innerFMU2__input_port2, innerFMU2__input_port3 (N.m)
+		with output ports innerFMU2__outout_port1, String innerFMU2__output_port2
 	
-	coupled as innerFMU2.outout_port1 -> innerFMU1.input_port1
+	coupled as innerFMU2.innerFMU2__outout_port1 -> innerFMU1.innerFMU1__input_port1
 	
-	input ports Real ext_input_port3 -> innerFMU1.input_port3
-	output ports ext_output_port2 <- innerFMU1.output_port2
+	input ports Real ext_input_port3 -> innerFMU1.innerFMU1__input_port3
+	output ports ext_output_port2 <- innerFMU1.innerFMU1__output_port2

+ 6 - 4
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/src/be/uantwerpen/ansymo/semanticadaptation/tests/SemanticAdaptationGeneratorTest.xtend

@@ -34,11 +34,11 @@ class SemanticAdaptationGeneratorTest extends AbstractSemanticAdaptationTest{
 				sa.name == "outerFMU"
 				sa.eAllContents.filter(Port).filter[p | p.name=="ext_input_port3"].head.unity instanceof MultiplyUnity
 				sa.eAllContents.filter(InnerFMU).filter[f | f.name=="innerFMU2"].head
-							.eAllContents.filter(Port).filter[p | p.name=="input_port1"].head.type == "Real"
+							.eAllContents.filter(Port).filter[p | p.name=="innerFMU2__input_port1"].head.type == "Real"
 				sa.eAllContents.filter(InnerFMU).filter[f | f.name=="innerFMU2"].head
-							.eAllContents.filter(Port).filter[p | p.name=="outout_port1"].head.type == "Real"
+							.eAllContents.filter(Port).filter[p | p.name=="innerFMU2__outout_port1"].head.type == "Real"
 				sa.eAllContents.filter(InnerFMU).filter[f | f.name=="innerFMU2"].head
-							.eAllContents.filter(Port).filter[p | p.name=="outout_port1"].head.unity instanceof AtomicUnity
+							.eAllContents.filter(Port).filter[p | p.name=="innerFMU2__outout_port1"].head.unity instanceof AtomicUnity
 				
 			}
 		}) }
@@ -47,6 +47,9 @@ class SemanticAdaptationGeneratorTest extends AbstractSemanticAdaptationTest{
 			override accept(Result t) {
 				var Adaptation sa = t.resourceSet.resources.head.allContents.toIterable.filter(SemanticAdaptation).last.elements.filter(Adaptation).head
 				sa.inports.filter[p | p.name=="innerFMU1__input_port2"].head.type == "Bool"
+				
+				sa.inports.filter[p | p.name=="innerFMU1__input_port1"].size == 0
+				
 				//sa.inports.filter[p | p.name=="innerFMU2__input_port3"].head.targetdependency.owner.name == "innerFMU2"
 				//sa.inports.filter[p | p.name=="innerFMU2__input_port3"].head.targetdependency.port.name == "input_port3"
 			}
@@ -87,7 +90,6 @@ class SemanticAdaptationGeneratorTest extends AbstractSemanticAdaptationTest{
 			}
 		}) }
 	
-	
 	@Test def test_removeInBindings_sample1() { __generate('input/canonical_generation/sample1.sa', new IAcceptor<CompilationTestHelper.Result>(){
 			override accept(Result t) {
 				var Adaptation sa = t.resourceSet.resources.head.allContents.toIterable.filter(SemanticAdaptation).last.elements.filter(Adaptation).head

+ 66 - 10
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation/src/be/uantwerpen/ansymo/semanticadaptation/generator/SemanticAdaptationCanonicalGenerator.xtend

@@ -39,6 +39,7 @@ import org.eclipse.xtext.EcoreUtil2
 import org.eclipse.xtext.generator.AbstractGenerator
 import org.eclipse.xtext.generator.IFileSystemAccess2
 import org.eclipse.xtext.generator.IGeneratorContext
+import java.util.List
 
 /**
  * Generates code from your model files on save.
@@ -233,6 +234,8 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 		
 		removeInBindings(internalPort2ExternalPortBindings, sa)
 		
+		//addOutPorts(sa)
+		
 		Log.pop("Canonicalize")
 	}
 	
@@ -271,7 +274,8 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 	}
 	
 	def createExternalPortNameFromInternalPort(String parentFMUName, String internalPortName) {
-		return parentFMUName + "__" + internalPortName
+		//return parentFMUName + "__" + internalPortName // Violates transparency
+		return internalPortName
 	}
 	
 	def addInRules_External2Internal_Assignments(Adaptation sa, HashMap<Port, Port> internalPort2ExternalPort) {
@@ -801,15 +805,17 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 		for (port : getAllInnerFMUInputPortDeclarations(sa)){
 			var parentFMU = port.eContainer as InnerFMU
 			Log.println("Checking if port " + parentFMU.name + "." + port.name + " has incoming connections")
-			if (! hasIncomingConnection(port, sa)){
+			if (! hasConnection(port, sa, true)){
 				Log.println("Port " + parentFMU.name + "." + port.name + " has no incoming connections.")
-				if (findExternalPortByName(sa, port.name) === null){
+				val externalPortName = createExternalPortNameFromInternalPort(parentFMU.name, port.name)
+				if (findExternalPortByName(sa, externalPortName) === null){
 					var newExternalPort = createExternalInputPortDeclarationFromInnerPort(port, parentFMU, sa)
 					Log.println("External port " + newExternalPort.name + " created.")
 					newExternalPort.bindExternalInputPortTo(parentFMU, port)
 					Log.println("External port " + newExternalPort.name + " bound to port " + parentFMU.name + "." + port.name)
 				} else {
-					Log.println("External port " + port.name + " already declared.")
+					Log.println("Error: External port " + externalPortName + " already declared.")
+					throw new Exception("Error: External port " + externalPortName + " already declared. Please rename it to avoid clashes.")
 				}
 			} else {
 				Log.println("Port " + parentFMU.name + "." + port.name + " has an incoming connection.")
@@ -854,11 +860,13 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 	}
 	
 	
-	def hasIncomingConnection(Port port, Adaptation adaptation) {
+	def hasConnection(Port port, Adaptation adaptation, Boolean checkForIncomming) {
 		
 		var result = false
 		
-		if (port.sourcedependency !== null){
+		if ( (checkForIncomming && port.sourcedependency !== null) ||
+			 (! checkForIncomming && port.targetdependency !== null)
+		){
 			result = true
 		} else {
 			if (port.eContainer instanceof InnerFMU){
@@ -869,21 +877,30 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 					var innerScenarioWithCoupling = innerScenarioDeclaration as InnerFMUDeclarationFull
 					if (innerScenarioWithCoupling.connection.size > 0){
 						for (connection : innerScenarioWithCoupling.connection ){
-							if (connection.tgt.port == port){
+							if ( (checkForIncomming && connection.tgt.port == port)){
 								var parentFMU = port.eContainer as InnerFMU
 								var sourceFMU = connection.src.port.eContainer as InnerFMU
 								Log.println("Port " + parentFMU.name + "." + port.name + " has an incoming connection from internal port " + sourceFMU.name + "." + connection.src.port.name)
 								result = true
+							} else if (!checkForIncomming && connection.src.port == port) {
+								var parentFMU = port.eContainer as InnerFMU
+								var targetFMU = connection.tgt.port.eContainer as InnerFMU
+								Log.println("Port " + parentFMU.name + "." + port.name + " has an outgoing connection to internal port " + targetFMU.name + "." + connection.tgt.port.name)
+								result = true
 							}
 						}
 					}
 				}
 				
-				for (externalInputPort : adaptation.inports.filter[p | p.targetdependency !== null]){
-					if (externalInputPort.targetdependency.port == port){
+				for (externalInputPort : adaptation.inports.filter[p | (checkForIncomming && p.targetdependency !== null) || (!checkForIncomming && p.sourcedependency !== null) ]){
+					if (checkForIncomming && externalInputPort.targetdependency.port == port){
 						var parentFMU = port.eContainer as InnerFMU
 						Log.println("Port " + parentFMU.name + "." + port.name + " has an incoming connection from external port " + externalInputPort.name)
 						result = true
+					} else if ( !checkForIncomming &&  externalInputPort.sourcedependency.port == port){
+						var parentFMU = port.eContainer as InnerFMU
+						Log.println("Port " + parentFMU.name + "." + port.name + " has an outgoing connection to external port " + externalInputPort.name)
+						result = true
 					}
 				}
 			}
@@ -893,13 +910,21 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 	}
 	
 	def getAllInnerFMUInputPortDeclarations(Adaptation sa){
+		return mapAllInnerFMUs(sa, [fmu | fmu.inports]);
+	}
+	
+	def getAllInnerFMUOutputPortDeclarations(Adaptation sa){
+		return mapAllInnerFMUs(sa, [fmu | fmu.outports]);
+	}
+	
+	def <T> List<T> mapAllInnerFMUs(Adaptation sa, (InnerFMU)=>List<T> map){
 		var result = new LinkedList()
 		
 		if(sa.inner !== null){
 			if(sa.inner instanceof InnerFMUDeclarationFull){
 				var innerFMUFull = sa.inner as InnerFMUDeclarationFull
 				for(fmu : innerFMUFull.fmus){
-					result.addAll(fmu.inports)
+					result.addAll(map.apply(fmu))
 				}
 			} else {
 				throw new Exception("Only support for InnerFMUDeclarationFull.")
@@ -909,6 +934,7 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 		return result;
 	}
 	
+	
 	def addInParams(Adaptation sa) {
 		Log.push("Adding input parameters...")
 		
@@ -988,4 +1014,34 @@ class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
 		return false
 	}
 	
+	
+	def addOutPorts(Adaptation sa) {
+		Log.push("Adding output ports...")
+
+		for (port : getAllInnerFMUOutputPortDeclarations(sa)){
+			var parentFMU = port.eContainer as InnerFMU
+			Log.println("Checking if port " + parentFMU.name + "." + port.name + " has outgoing connections")
+			if (! hasConnection(port, sa, false)){
+				Log.println("Port " + parentFMU.name + "." + port.name + " has no outgoing connections.")
+				
+				// TODO Continue here.
+				
+				val externalPortName = createExternalPortNameFromInternalPort(parentFMU.name, port.name)
+				if (findExternalPortByName(sa, externalPortName) === null){
+					var newExternalPort = createExternalInputPortDeclarationFromInnerPort(port, parentFMU, sa)
+					Log.println("External port " + newExternalPort.name + " created.")
+					newExternalPort.bindExternalInputPortTo(parentFMU, port)
+					Log.println("External port " + newExternalPort.name + " bound to port " + parentFMU.name + "." + port.name)
+				} else {
+					Log.println("Error: External port " + externalPortName + " already declared.")
+					throw new Exception("Error: External port " + externalPortName + " already declared. Please rename it to avoid clashes.")
+				}
+			} else {
+				Log.println("Port " + parentFMU.name + "." + port.name + " has an incoming connection.")
+			}
+		}
+		
+		Log.pop("Adding output ports... DONE")
+	}
+	
 }