From 6653199a4cc14b4a25274d186ec4914dbaa3e5ef Mon Sep 17 00:00:00 2001
From: Andreas Bayha <bayha@fortiss.org>
Date: Wed, 2 Aug 2023 11:04:43 +0200
Subject: [PATCH] Variability: Added island optimization to EMF translation

Added "island optimization" option to EMT translation which translates
only optional islands of a configurable size within the model.

Issue-ref: 4240
Issue-URL: https://git.fortiss.org/af3/af3/-/issues/4240

Signed-off-by: Andreas Bayha <bayha@fortiss.org>
---
 .../OptimizedProductLineTranslation.java      |  1 -
 .../analysis/EMFProductLineTranslation.java   | 66 ++++++++++++++++---
 2 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/org.fortiss.tooling.ext.variability/src/org/fortiss/tooling/ext/variability/analysis/OptimizedProductLineTranslation.java b/org.fortiss.tooling.ext.variability/src/org/fortiss/tooling/ext/variability/analysis/OptimizedProductLineTranslation.java
index 85a18dc56..a83f1d1ab 100644
--- a/org.fortiss.tooling.ext.variability/src/org/fortiss/tooling/ext/variability/analysis/OptimizedProductLineTranslation.java
+++ b/org.fortiss.tooling.ext.variability/src/org/fortiss/tooling/ext/variability/analysis/OptimizedProductLineTranslation.java
@@ -32,7 +32,6 @@ import org.fortiss.variability.model.presence.PresenceConditionTerm;
  * @author bayha
  */
 public class OptimizedProductLineTranslation extends EMFProductLineTranslation {
-
 	/** {@inheritDoc} */
 	@Override
 	protected PresenceConditionTerm getLocalPresenceCondition(EObject model) {
diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/EMFProductLineTranslation.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/EMFProductLineTranslation.java
index bf2fd8475..eceb5c61e 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/analysis/EMFProductLineTranslation.java
+++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/EMFProductLineTranslation.java
@@ -3,6 +3,7 @@ package org.fortiss.variability.analysis;
 import static java.util.stream.Collectors.toList;
 import static org.eclipse.emf.ecore.util.EcoreUtil.copy;
 import static org.fortiss.variability.model.VariabilityModelElementFactory.createAndPC;
+import static org.fortiss.variability.util.VariabilityUtilsInternal.getAllReferences;
 import static org.fortiss.variability.util.VariabilityUtilsInternal.getChildrenWithType;
 
 import java.util.ArrayList;
@@ -21,8 +22,9 @@ import org.eclipse.emf.ecore.EEnum;
 import org.eclipse.emf.ecore.EEnumLiteral;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EStructuralFeature.Setting;
 import org.eclipse.emf.ecore.EcorePackage;
-import org.fortiss.tooling.kernel.model.IIdLabeled;
 import org.fortiss.variability.model.IAlternative;
 import org.fortiss.variability.model.IOptionalVariationPoint;
 import org.fortiss.variability.model.features.AbstractAlternativeFeature;
@@ -154,6 +156,10 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 
 	protected Map<EReference, EClass> reference2TranslatedEClass;
 
+	private boolean isIslandOptimizationEnabled = false;
+
+	private int islandOptimizationStepNum = 0;
+
 	/**
 	 * Constructor.
 	 */
@@ -219,10 +225,10 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 
 		for(EClass cls : translatedClasses) {
 			if(cls.isSuperTypeOf(modelClass)) {
-				// // Only optional objects are translated.
-				// if(pc != null) {
-				collectEObject(model, cls, pc);
-				// }
+				// For the island optimization, only optional objects are translated.
+				if(isIslandOptimizationEnabled && pc != null) {
+					collectEObject(model, cls, pc);
+				}
 			}
 		}
 
@@ -231,7 +237,11 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		}
 	}
 
-	private void collectTranslatedReferences(EObject model) {
+	private void collectTranslatedReferences(EObject model, int remainingSteps) {
+		if(remainingSteps <= 0) {
+			return;
+		}
+
 		// Collect outgoing references
 		for(EReference ref : model.eClass().getEAllReferences()) {
 			if(translatedReferences.contains(ref)) {
@@ -246,8 +256,36 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 							" which is not translated.");
 				}
 
-				collectTranslatedReferences(refObj);
+				collectTranslatedReferences(refObj, remainingSteps - 1);
+			}
+		}
+
+		// Collect incoming references
+		for(Setting s : getAllReferences(model)) {
+			EStructuralFeature ref = s.getEStructuralFeature();
+			if(ref instanceof EReference) {
+				if(translatedReferences.contains(ref)) {
+					EObject referencingEObject = s.getEObject();
+					EClass referencingEClass = referencingEObject.eClass();
+
+					if(translatedClasses.contains(referencingEClass)) {
+						class2TranslatedEObjects.add(referencingEClass, referencingEObject);
+
+						collectTranslatedReferences(referencingEObject, remainingSteps - 1);
+
+						continue;
+					}
+
+					for(EClass cls : translatedClasses) {
+						if(cls.isSuperTypeOf(referencingEClass)) {
+							class2TranslatedEObjects.add(cls, referencingEObject);
 
+							collectTranslatedReferences(referencingEObject, remainingSteps - 1);
+
+							// break;
+						}
+					}
+				}
 			}
 		}
 	}
@@ -280,7 +318,9 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 	private void collectEObject(EObject eo, EClass cls, PresenceConditionTerm pc) {
 		class2TranslatedEObjects.add(cls, eo);
 
-		// collectTranslatedReferences(eo);
+		if(isIslandOptimizationEnabled) {
+			collectTranslatedReferences(eo, islandOptimizationStepNum);
+		}
 
 		object2presenceCondition.put(eo, pc);
 	}
@@ -1014,4 +1054,14 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		BoolExpr liftedBody = ctx.mkAnd(ctx.mkAnd(selExprs), body);
 		return ctx.mkExists(quantifierValiables, liftedBody, 0, null, null, null, null);
 	}
+
+	/** Sets isIslandOptimizationEnabled. */
+	public void setIslandOptimizationEnabled(boolean isIslandOptimizationEnabled) {
+		this.isIslandOptimizationEnabled = isIslandOptimizationEnabled;
+	}
+
+	/** Sets islandOptimizationStepNum. */
+	public void setIslandOptimizationStepNum(int islandOptimizationStepNum) {
+		this.islandOptimizationStepNum = islandOptimizationStepNum;
+	}
 }
-- 
GitLab