From be49c4b943aa8fc9e2ebd6302287a4f81edfa4dc Mon Sep 17 00:00:00 2001
From: Alexander Diewald <diewald@fortiss.org>
Date: Thu, 22 Mar 2018 20:29:00 +0000
Subject: [PATCH] Exploration.alg: Add Channels Export for Partitions.

* Adds a sub-method to the Partition Transformation Strategy that adds Ports and Channels to a PartitionAchitecture.
* The required Ports and Channels are derived from the Signals exchanged between Tasks.
* Ports and Channels are only added for InterPartitionCommunication (logically).
* The Sampling and Queuing characteristics of PartitionPorts is derived from their corresponding TaskPorts.
refs 3257
---
 .../modeltransformation/partition/.ratings    |   2 +-
 .../partition/PartitionTransformer.java       | 115 +++++++++++++++++-
 .../fortiss/af3/exploration/alg/plot/.ratings |   2 +-
 .../af3/exploration/alg/plot/XYPlotter.java   |  67 ++++++----
 4 files changed, 154 insertions(+), 32 deletions(-)

diff --git a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/.ratings b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/.ratings
index 08a954b4..35170dce 100644
--- a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/.ratings
+++ b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/.ratings
@@ -1,2 +1,2 @@
 PartitionTransformationStrategy.java 220d5175ac8ff958f82c053a934095880540fcd3 YELLOW
-PartitionTransformer.java b2f9f2dc793c73b35bef529646e449012f747750 RED
+PartitionTransformer.java 3226c719980e12590e02eea5b01652b19b290577 RED
diff --git a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/PartitionTransformer.java b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/PartitionTransformer.java
index b3141909..d61f8d06 100644
--- a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/PartitionTransformer.java
+++ b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/dse/modeltransformation/partition/PartitionTransformer.java
@@ -19,6 +19,11 @@ import static org.fortiss.af3.allocation.utils.AllocationModelElementFactory.cre
 import static org.fortiss.af3.allocation.utils.AllocationUtils.addAllocationEntry;
 import static org.fortiss.af3.exploration.alg.dse.modeltransformation.ITransformationModule.TransformationState.INITIALIZING;
 import static org.fortiss.af3.exploration.alg.util.TransformationUtils.getArchitectureOfAllocSuperSet;
+import static org.fortiss.af3.partition.util.PartitionModelElementFactory.createPartitionChannel;
+import static org.fortiss.af3.partition.util.PartitionModelElementFactory.createPartitionQueuingInputPort;
+import static org.fortiss.af3.partition.util.PartitionModelElementFactory.createPartitionQueuingOutputPort;
+import static org.fortiss.af3.partition.util.PartitionModelElementFactory.createPartitionSamplingInputPort;
+import static org.fortiss.af3.partition.util.PartitionModelElementFactory.createPartitionSamplingOutputPort;
 import static org.fortiss.tooling.common.util.LambdaUtils.getFirst;
 
 import java.util.Collection;
@@ -38,6 +43,9 @@ import org.fortiss.af3.exploration.alg.service.IExplorationTransformationService
 import org.fortiss.af3.exploration.dsl_v2.model.expression.SuperSet;
 import org.fortiss.af3.partition.model.Partition;
 import org.fortiss.af3.partition.model.PartitionArchitecture;
+import org.fortiss.af3.partition.model.PartitionChannel;
+import org.fortiss.af3.partition.model.PartitionInputPort;
+import org.fortiss.af3.partition.model.PartitionOutputPort;
 import org.fortiss.af3.partition.model.allocation.PartitionToExecutionUnitAllocationEntry;
 import org.fortiss.af3.partition.model.allocation.PartitionToExecutionUnitAllocationTable;
 import org.fortiss.af3.partition.model.allocation.TaskToPartitionAllocationEntry;
@@ -46,12 +54,23 @@ import org.fortiss.af3.partition.util.PartitionModelElementFactory;
 import org.fortiss.af3.platform.model.PlatformArchitecture;
 import org.fortiss.af3.project.model.FileProject;
 import org.fortiss.af3.project.utils.ProjectUtils;
+import org.fortiss.af3.task.model.Signal;
+import org.fortiss.af3.task.model.Task;
 import org.fortiss.af3.task.model.TaskArchitecture;
+import org.fortiss.af3.task.model.TaskInputPort;
+import org.fortiss.af3.task.model.TaskOutputPort;
+import org.fortiss.af3.task.model.TaskQueuingInputPort;
+import org.fortiss.af3.task.model.TaskQueuingOutputPort;
+import org.fortiss.af3.task.model.TaskSamplingInputPort;
+import org.fortiss.af3.task.model.TaskSamplingOutputPort;
 import org.fortiss.tooling.base.model.element.IHierarchicElement;
 import org.fortiss.tooling.common.util.LambdaUtils;
 import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
 import org.fortiss.tooling.kernel.service.IPersistencyService;
 
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
 /**
  * Initializes a {@link Deployment} by creating a new model and setting its references to the given
  * {@link ComponentArchitecture} and {@link PlatformArchitecture}.
@@ -59,6 +78,8 @@ import org.fortiss.tooling.kernel.service.IPersistencyService;
  * @author diewald
  */
 public class PartitionTransformer extends TransformationModuleBase<AllocationTableCollection> {
+	/** Model context to attach model elements to others. */
+	ITopLevelElement modelContext;
 	/** Input {@link TaskArchitecture} passed to the DSE. */
 	private TaskArchitecture taskArchitecture;
 	/** Input {@link PlatformArchitecture} passed to the DSE. */
@@ -93,7 +114,7 @@ public class PartitionTransformer extends TransformationModuleBase<AllocationTab
 				LambdaUtils.getFirst(partToExU.getEntries()).get();
 		FileProject fp =
 				ProjectUtils.getFileProject(LambdaUtils.getFirst(entry.getTargetElements()).get());
-		ITopLevelElement modelContext = IPersistencyService.getInstance().getTopLevelElementFor(fp);
+		modelContext = IPersistencyService.getInstance().getTopLevelElementFor(fp);
 
 		// TODO: The following step should be performed in a separate module.
 		createPartitionArchitecture(inputs.getSuperSet(Partition.class), modelContext);
@@ -101,17 +122,20 @@ public class PartitionTransformer extends TransformationModuleBase<AllocationTab
 
 		// Create the allocations.
 		allocTableCollection = createAllocationTableCollection("Generated Allocations");
-		TaskToPartitionAllocationTable taskExUTable =
+		TaskToPartitionAllocationTable taskPartTable =
 				createTaskToPartitionAllocationTable(inputs
 						.getSuperSet(TaskToPartitionAllocationEntry.class));
 		modelContext.runAsNonDirtyingCommand(() -> allocTableCollection.getContainedElements().add(
-				taskExUTable));
+				taskPartTable));
 		PartitionToExecutionUnitAllocationTable partExUTable =
 				createPartitionToExecutionUnitAllocationTable(inputs
 						.getSuperSet(PartitionToExecutionUnitAllocationEntry.class));
 		modelContext.runAsNonDirtyingCommand(() -> allocTableCollection.getContainedElements().add(
 				partExUTable));
 
+		// Create the Interpartition comm channels
+		createInterPartitionComm(taskPartTable, inputs.getSuperSet(Signal.class));
+
 		return allocTableCollection;
 	}
 
@@ -130,14 +154,14 @@ public class PartitionTransformer extends TransformationModuleBase<AllocationTab
 	 * the given {@link SuperSet}.
 	 */
 	private TaskToPartitionAllocationTable createTaskToPartitionAllocationTable(
-			SuperSet<TaskToPartitionAllocationEntry> taskExecUnitAllocs) {
+			SuperSet<TaskToPartitionAllocationEntry> taskPartAllocs) {
 		TaskToPartitionAllocationTable table =
 				org.fortiss.af3.partition.util.PartitionModelElementFactory
 						.createTaskToPartitionAllocationTable("Generated Task->Part Table");
 		table.setSourceView(taskArchitecture);
 		table.setTargetView(partitionArchitecture);
 
-		for(TaskToPartitionAllocationEntry entry : taskExecUnitAllocs.getEntries()) {
+		for(TaskToPartitionAllocationEntry entry : taskPartAllocs.getEntries()) {
 			Partition af3Partition = (Partition)entry.getTargetElement();
 			// TODO: We assume single Tasks in this place.
 			addAllocationEntry(table, TaskToPartitionAllocationEntry.class,
@@ -167,6 +191,87 @@ public class PartitionTransformer extends TransformationModuleBase<AllocationTab
 		return table;
 	}
 
+	private void createInterPartitionComm(TaskToPartitionAllocationTable taskPartAllocTable,
+			SuperSet<Signal> signals) {
+		// Extract sender / receiver information from the signals
+		Multimap<Task, Signal> senderTaskToSignal = HashMultimap.create();
+		Multimap<Task, Partition> senderTaskToRecvPartition = HashMultimap.create();
+		for(Signal signal : signals.getEntries()) {
+			Task senderTask = (Task)signal.getSource().getOwner();
+			senderTaskToSignal.put(senderTask, signal);
+		}
+
+		for(TaskToPartitionAllocationEntry alloc : taskPartAllocTable
+				.getAllocationEntries(TaskToPartitionAllocationEntry.class)) {
+			// TODO: currently, the supersets contain only 1:1 allocations.
+			Collection<Task> allocatedTasks =
+					(Collection<Task>)(Collection<?>)alloc.getSourceElements();
+			Partition senderPartition = (Partition)alloc.getTargetElement();
+			for(Task senderTask : allocatedTasks) {
+				// Get the target task.
+				for(Signal signal : senderTaskToSignal.get(senderTask)) {
+					TaskInputPort targetInputPort = signal.getTargetTaskPort();
+					Task targetTask = (Task)targetInputPort.getOwner();
+					Partition targetPartition = taskPartAllocTable.getPartition(targetTask);
+					// Only create channels for interpartition communication.
+					if(senderPartition != targetPartition) {
+						PartitionOutputPort senderPartitionPort = null;
+						// TODO: combine the following ifs using an enum to denote the port type.
+						TaskOutputPort senderPort = signal.getSourceTaskPort();
+						if(senderPort instanceof TaskSamplingOutputPort) {
+							senderPartitionPort =
+									createPartitionSamplingOutputPort("Part_" +
+											senderPort.getName());
+						} else if(senderPort instanceof TaskQueuingOutputPort) {
+							senderPartitionPort =
+									createPartitionQueuingOutputPort("Part_senderPort.getName()");
+						}
+						addSenderPartitionPort(senderPartition, senderPartitionPort);
+
+						PartitionInputPort targetPartitionPort = null;
+						if(targetInputPort instanceof TaskSamplingInputPort) {
+							targetPartitionPort =
+									createPartitionSamplingInputPort("Part_" +
+											targetInputPort.getName());
+						} else if(targetInputPort instanceof TaskQueuingInputPort) {
+							targetPartitionPort =
+									createPartitionQueuingInputPort("Part_" +
+											targetInputPort.getName());
+						}
+						addTargetPartitionPort(targetPartition, targetPartitionPort);
+						createAndAddPartitionChannel(senderPartitionPort, targetPartitionPort);
+					}
+				}
+			}
+		}
+	}
+
+	private void addSenderPartitionPort(Partition senderPartition,
+			final PartitionOutputPort senderPartitionPort) {
+		modelContext.runAsNonDirtyingCommand(() -> senderPartition.getConnectors().add(
+				senderPartitionPort));
+	}
+
+	private void addTargetPartitionPort(Partition targetPartition,
+			final PartitionInputPort targetPartitionPort) {
+		modelContext.runAsNonDirtyingCommand(() -> targetPartition.getConnectors().add(
+				targetPartitionPort));
+	}
+
+	private void createAndAddPartitionChannel(final PartitionOutputPort senderPartitionPort,
+			final PartitionInputPort targetPartitionPort) {
+		modelContext
+				.runAsNonDirtyingCommand(() -> {
+					PartitionChannel partitionChannel =
+							createPartitionChannel(
+									senderPartitionPort,
+									targetPartitionPort,
+									senderPartitionPort.getName() + " --> " +
+											targetPartitionPort.getName());
+					partitionArchitecture.getConnections().add(partitionChannel);
+				});
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public Class<AllocationTableCollection> getOutputType() {
diff --git a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/.ratings b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/.ratings
index 98ccaf4e..3d0c634c 100644
--- a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/.ratings
+++ b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/.ratings
@@ -4,4 +4,4 @@ ScheduleLabelGenerator.java 0ceecedfec9802bbcaa33525d61e1a60a70d3841 RED
 SchedulePlotter.java 29b1156c9419d4ff3314c4b2c932aeb46f4749f8 RED
 ScheduleToolTipGenerator.java cedfa0dd7ebc7b48d7cc70e966eebaeee9636caf RED
 TaskSeriesCollectionFromSchedule.java b53b7af649c48980520ad572da8c7bbdbae0aed5 RED
-XYPlotter.java bdea08cbfbaea8755a225c149a5aba8830a68549 RED
+XYPlotter.java b8abd061e80509c7c8af83baf584e9549c98a4d9 RED
diff --git a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/XYPlotter.java b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/XYPlotter.java
index e6d38d79..8374540a 100644
--- a/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/XYPlotter.java
+++ b/org.fortiss.af3.exploration.alg/trunk/src/org/fortiss/af3/exploration/alg/plot/XYPlotter.java
@@ -19,6 +19,7 @@ import static javax.swing.JOptionPane.YES_OPTION;
 import static org.fortiss.af3.exploration.alg.ExplorationAlgActivator.PLUGIN_ID;
 import static org.fortiss.af3.exploration.alg.service.ExplorationService.getService;
 import static org.fortiss.af3.exploration.alg.service.IExplorationTransformationService.TransformationContext.EXPORT;
+import static org.fortiss.af3.exploration.util.DesignSpaceExplorationModelElementFactory.createSuperSetMap;
 import static org.fortiss.af3.exploration.util.ExplorationUtils.createExceptionStatus;
 import static org.fortiss.af3.project.utils.ProjectUtils.getFileProject;
 import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.getRootElements;
@@ -59,6 +60,7 @@ import org.fortiss.af3.exploration.dsl_v2.model.expression.SuperSet;
 import org.fortiss.af3.exploration.model.ExplorationConstraint;
 import org.fortiss.af3.exploration.model.ExplorationSpecification;
 import org.fortiss.af3.exploration.model.ExplorationTarget;
+import org.fortiss.af3.exploration.model.SuperSetMap;
 import org.fortiss.af3.exploration.model.solutions.ExplorationResult;
 import org.fortiss.af3.exploration.model.solutions.ExplorationSolution;
 import org.fortiss.af3.exploration.model.solutions.SingleExplorationSolution;
@@ -216,11 +218,11 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 	public void createPlot() {
 		// TODO: Do we want to add constraints here?
 		goalList = new ArrayList<ExplorationTarget<?>>();
-		goalList.addAll(
-				expSpec.getTargets().stream()
-						.filter(t -> !(t instanceof ExplorationConstraint &&
-								((ExplorationConstraint<?>)t).isImplicit()))
-						.collect(Collectors.toList()));
+		goalList.addAll(expSpec
+				.getTargets()
+				.stream()
+				.filter(t -> !(t instanceof ExplorationConstraint && ((ExplorationConstraint<?>)t)
+						.isImplicit())).collect(Collectors.toList()));
 
 		goalList.stream().forEach(t -> targetUIMap.put(t, new ExplorationTargetItem(t)));
 
@@ -406,7 +408,7 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 				PlotOrientation.VERTICAL, true, // include legend
 				true, // tooltips
 				false // urls
-		);
+				);
 
 		chart.setBackgroundPaint(Color.white);
 		chart.getLegend().setPosition(RectangleEdge.TOP);
@@ -491,8 +493,9 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 			XYDataItem item = new XYDataItem(x, y);
 			currentSolution = coordinateToSolution.get(item);
 
-			Optional<SingleExplorationSolution> singleExpSol = explorationResult.getSolutions()
-					.stream().filter(r -> r == currentSolution).findAny();
+			Optional<SingleExplorationSolution> singleExpSol =
+					explorationResult.getSolutions().stream().filter(r -> r == currentSolution)
+							.findAny();
 			if(singleExpSol.isPresent()) {
 				SingleExplorationSolution currentSolMap = singleExpSol.get();
 				// TODO: identifying the elements by their names is not good style, the map is not
@@ -505,8 +508,8 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 						ExplorationResult<?> expResult = currentSolMap.get(target);
 						if(objectiveToGuiItems.get(target) != null &&
 								(expResult != null && expResult.getResult() instanceof Double)) {
-							objectiveToGuiItems.get(target).objTextField
-									.setText(Double.toString((Double)expResult.getResult()));
+							objectiveToGuiItems.get(target).objTextField.setText(Double
+									.toString((Double)expResult.getResult()));
 						}
 					}
 				}
@@ -535,9 +538,10 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 		} else if("generateDeployment".equals(e.getActionCommand())) {
 			if(currentSolution != null) {
 
-				String deploymentName = (String)JOptionPane.showInputDialog(this,
-						"Generate Deployment", "Enter a name for the Deployment",
-						JOptionPane.QUESTION_MESSAGE, null, null, "_Deployment");
+				String deploymentName =
+						(String)JOptionPane.showInputDialog(this, "Generate Deployment",
+								"Enter a name for the Deployment", JOptionPane.QUESTION_MESSAGE,
+								null, null, "_Deployment");
 				int generateSCSpcec = 0;
 				if(deploymentName != null) {
 					// if(pickFirstInstanceOf(SafetyComplianceConstraint.class, dse
@@ -559,9 +563,10 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 						"Cannot perform model transformation : No Exploration Solution Selected!");
 			}
 		} else if("generateAllDeployments".equals(e.getActionCommand())) {
-			String deploymentName = (String)JOptionPane.showInputDialog(this,
-					"Generate All Deployments", "Enter a name prefix for the resulting deployments",
-					JOptionPane.QUESTION_MESSAGE, null, null, "GenDeployment_");
+			String deploymentName =
+					(String)JOptionPane.showInputDialog(this, "Generate All Deployments",
+							"Enter a name prefix for the resulting deployments",
+							JOptionPane.QUESTION_MESSAGE, null, null, "GenDeployment_");
 			if(deploymentName != null) {
 				int generateSCSpcec = 0;
 				// if(pickFirstInstanceOf(SafetyComplianceConstraint.class, dse
@@ -582,8 +587,8 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 			}
 		} else if("showschedule".equals(e.getActionCommand())) {
 			JOptionPane.showMessageDialog(this,
-					"The schedule view is currently disabled due to a rework of the solution" +
-							" transformation framework.");
+					"The schedule view is currently disabled due to a rework of the solution"
+							+ " transformation framework.");
 			// IScheduleSolution<?> scheduleSolution =
 			// currentSolution.getSolutionModel(IScheduleSolution.class);
 			// if(scheduleSolution instanceof StrictTTSchedule<?, ?>) {
@@ -639,8 +644,9 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 				solutionMap.getSolutionSets().get(PartitionToExecutionUnitAllocationEntry.class);
 		PartitionToExecutionUnitAllocationEntry entry =
 				LambdaUtils.getFirst(partToExU.getEntries()).get();
-		ITopLevelElement modelContext = IPersistencyService.getInstance()
-				.getTopLevelElementFor(LambdaUtils.getFirst(entry.getTargetElements()).get());
+		ITopLevelElement modelContext =
+				IPersistencyService.getInstance().getTopLevelElementFor(
+						LambdaUtils.getFirst(entry.getTargetElements()).get());
 
 		Collection<Class<?>> solutionModelTypes = new HashSet<>();
 		// solutionModelTypes.add(Deployment.class);
@@ -649,8 +655,18 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 			// solutionModelTypes.add(SafetyComplianceSpecification.class);
 		}
 
+		// TODO: clearer separation between In- and output models.
+		// Create a new SuperSet Map that combines in and outputs.
+		SuperSetMap solutionSuperSets = solutionMap.getSolutionSets();
+		SuperSetMap superSetMap = createSuperSetMap();
+		for(Class<?> setType : solutionSuperSets.keySet()) {
+			superSetMap.put((Class)setType, solutionSuperSets.get((Class)setType));
+		}
+		for(Class<?> setType : expSpec.getSearchSpace().keySet()) {
+			superSetMap.put((Class)setType, expSpec.getSearchSpace().get((Class)setType));
+		}
 		ExplorationTransformationInputs inputs =
-				new ExplorationTransformationInputs(solutionMap.getSolutionSets(), null);
+				new ExplorationTransformationInputs(superSetMap, null);
 		AllocationTableCollection deployment = null;
 		Map<Class<EObject>, ?> solutionModels =
 				getService(IExplorationTransformationService.class).getTransformedModels(EXPORT,
@@ -706,8 +722,8 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 
 		Integer deploymentNumber = 1;
 		for(SingleExplorationSolution solution : explorationResult.getSolutions()) {
-			transformedDeployments.add(transformSingleDeployment(solution,
-					deploymentName + "_" + deploymentNumber, generateSCSpec));
+			transformedDeployments.add(transformSingleDeployment(solution, deploymentName + "_" +
+					deploymentNumber, generateSCSpec));
 			deploymentNumber++;
 		}
 
@@ -739,8 +755,9 @@ public class XYPlotter extends JFrame implements ChartMouseListener, ActionListe
 	 */
 	private <S extends InstantiatedTaskMappingEntry, T extends InstantiatedTaskMappingEncoding<S>>
 			void addDeploymentToProject(Deployment deployment) {
-		ComponentArchitecture deployedArchitecture = (ComponentArchitecture)deployment
-				.getComponentArchitectureReference().getReference();
+		ComponentArchitecture deployedArchitecture =
+				(ComponentArchitecture)deployment.getComponentArchitectureReference()
+						.getReference();
 		FileProject fp = getFileProject(expSpec);
 		if(!getRootElements(expSpec, ComponentArchitecture.class).contains(deployedArchitecture)) {
 			fp.getRootElements().add(deployedArchitecture);
-- 
GitLab