From e80c550942b902c12dd629c90780ffa16c3a7bca Mon Sep 17 00:00:00 2001
From: Andreas Bayha <bayha@fortiss.org>
Date: Thu, 3 Aug 2023 11:33:40 +0200
Subject: [PATCH] YELLOW

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

Signed-off-by: Andreas Bayha <bayha@fortiss.org>
---
 .../org/fortiss/variability/analysis/.ratings |   8 +-
 .../analysis/EMFProductLineTranslation.java   | 320 +++++++++---------
 .../analysis/IProductLineConstraint.java      |  21 +-
 .../analysis/IProductLineTranslation.java     | 103 ++++--
 .../analysis/ProductLineConstraintBase.java   |  96 +++---
 .../src/org/fortiss/variability/util/.ratings |   2 +-
 .../util/VariabilityUtilsInternal.java        |  69 +++-
 7 files changed, 360 insertions(+), 259 deletions(-)

diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings b/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings
index 87e0861f6..cab9866ef 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings
+++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings
@@ -1,5 +1,7 @@
-BucketSetMap.java 407a35a6377ace1627c4c31890cfdc907f85945b YELLOW
+BucketSetMap.java 665a28c80a9693b9b9e31b7ebe59f2de4195d56c YELLOW
 DualKeyMap.java 75fbe85a54e5a655aaf67108ae004f98ed2879d8 YELLOW
-IProductLineConstraint.java e9dfd0f5271420e9801b7728c718808e7316522e YELLOW
-ProductLineConstraintBase.java b112ea23bb618e8b5838943d3dede279f75b54b3 YELLOW
+EMFProductLineTranslation.java a9f4daf255db599cef1a0fe894f702d88b008cc0 YELLOW
+IProductLineConstraint.java 1b0e1231cc578a6e7e544441ac33533b4feafeb1 YELLOW
+IProductLineTranslation.java 733dae03e2baae237b6f0b33f0dd618a4f47cf73 YELLOW
+ProductLineConstraintBase.java 04097c7c31367fdd11a054ba2b259a0535a313f4 YELLOW
 ProductLineConstraintViolation.java a822cc970dc7bd08d6e702c123d86b4a6e05b9f0 YELLOW
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 86aa2e7d2..a9f4daf25 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/analysis/EMFProductLineTranslation.java
+++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/EMFProductLineTranslation.java
@@ -5,6 +5,8 @@ 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 static org.fortiss.variability.util.VariabilityUtilsInternal.logError;
+import static org.fortiss.variability.util.VariabilityUtilsInternal.logInfo;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -63,94 +65,87 @@ import com.microsoft.z3.Symbol;
  */
 public class EMFProductLineTranslation implements IProductLineTranslation {
 
-	/*
-	 * FIXME: These should be
-	 * easier now, since we do not translate objects for all inheritance levels. Multiple
-	 * properties??.
-	 */
-
-	/**
-	 * Mapping of attributes to their translated Z3 function.
-	 */
-	protected DualKeyMap<EAttribute, EClass, FuncDecl<?>> eAttribute2FunDecl =
-			new DualKeyMap<EAttribute, EClass, FuncDecl<?>>();
-	/** Mapping of references to their translated Z3 function. */
-	protected DualKeyMap<EReference, EClass, FuncDecl<?>> eReference2FunDecl =
-			new DualKeyMap<EReference, EClass, FuncDecl<?>>();
-
-	/**
-	 * Mapping of objects with types to their translated Z3 expressions. (EClass is necessary as an
-	 * object is translated for all classes in the inheritance hierarchy).
-	 */
-	protected DualKeyMap<EObject, EClass, Expr<?>> eObject2z3Expr =
-			new DualKeyMap<EObject, EClass, Expr<?>>();
-
-	/* Refactoring */
+	/** Prefix to be displayed as prefix to all logging messages from the translation. */
+	private static final String LOG_PREFIX = "[EMF product-line translation]: ";
 
 	/** {@link Context} to capture the translated model. */
-	protected Context ctx;
+	private Context ctx;
 
 	/** Z3 sort for base type integer. */
-	protected IntSort intSort;
+	private IntSort intSort;
 	/** Z3 sort for base type string. */
-	protected SeqSort<?> stringSort;
+	private SeqSort<?> stringSort;
 	/** Z3 sort for base type boolean. */
-	protected BoolSort boolSort;
+	private BoolSort boolSort;
 
 	/** List of all translated assertions for the model. */
-	protected List<BoolExpr> modelAssertions;
+	private List<BoolExpr> modelAssertions;
 	/** List of all assertions for the feature model. */
-	protected List<BoolExpr> featureModelAssertions;
+	private List<BoolExpr> featureModelAssertions;
 	/** List of all assertions which encode the presence conditions. */
-	protected List<BoolExpr> presenceConditionAssertions;
+	private List<BoolExpr> presenceConditionAssertions;
 	/** List of all assertions which encode the constraints. */
-	protected List<BoolExpr> constraintAssertions;
+	private List<BoolExpr> constraintAssertions;
 
 	/** Mapping of EDataTypes (e.g. EInt) to their translated Z3 type. */
-	protected Map<EDataType, Sort> eDataType2Sort;
+	private Map<EDataType, Sort> eDataType2Sort;
 	/** Mapping for classes to their respective Z3 type. */
-	protected Map<EClass, EnumSort<?>> eClass2z3Sort;
+	private Map<EClass, EnumSort<?>> eClass2z3Sort;
 
 	/** Mapping of enumeration literals to the translated Z3 expression. */
-	protected Map<Enum<?>, Expr<?>> eLiteral2Expr;
+	private Map<Enum<?>, Expr<?>> eLiteral2Expr;
 	/** Mapping of classes to their respective z3 expression for 'null' */
-	protected Map<EClass, Expr<?>> eClass2NullElement;
+	private Map<EClass, Expr<?>> eClass2NullElement;
 	/** Mapping of enumerations to their respective z3 expression for 'null' */
-	protected Map<EEnum, Expr<?>> eEnum2NullElement;
+	private Map<EEnum, Expr<?>> eEnum2NullElement;
+
+	/** Mapping of attributes to their translated Z3 function. */
+	private DualKeyMap<EAttribute, EClass, FuncDecl<?>> eAttribute2FunDecl =
+			new DualKeyMap<EAttribute, EClass, FuncDecl<?>>();
+	/** Mapping of references to their translated Z3 function. */
+	private DualKeyMap<EReference, EClass, FuncDecl<?>> eReference2FunDecl =
+			new DualKeyMap<EReference, EClass, FuncDecl<?>>();
+
+	/**
+	 * Mapping of objects with types to their translated Z3 expressions. The second key EClass is
+	 * necessary as an object is translated for all classes specified in 'translatedClasses').
+	 */
+	private DualKeyMap<EObject, EClass, Expr<?>> eObject2z3Expr =
+			new DualKeyMap<EObject, EClass, Expr<?>>();
 
 	/** Mapping of classes to the selection function for this type. */
-	protected Map<EClass, FuncDecl<?>> eClass2SelectionFunction;
+	private Map<EClass, FuncDecl<?>> eClass2SelectionFunction;
 
 	/** The set to specify all {@link EClass} to be translated by this translation. */
-	protected Set<EClass> translatedClasses;
+	private Set<EClass> translatedClasses;
 	/** The set to specify all {@link EReference} to be translated by this translation. */
-	protected Set<EReference> translatedReferences;
+	private Set<EReference> translatedReferences;
 	/** The set to specify all {@link EAttribute} to be translated by this translation. */
-	protected Set<EAttribute> translatedAttributes;
+	private Set<EAttribute> translatedAttributes;
 
 	/** The mapping of translated {@link EClass} to the objects that have been collected. */
-	protected BucketSetMap<EClass, EObject> class2TranslatedEObjects;
+	private BucketSetMap<EClass, EObject> class2TranslatedEObjects;
 
 	/** The {@link AbstractFeatureModel} collected by this translation */
-	protected AbstractFeatureModel featureModel;
+	private AbstractFeatureModel featureModel;
 	/** Mapping of features to corresponding Z3 {@link BoolExpr}. */
-	protected Map<AbstractFeature, BoolExpr> feature2BoolExpr;
+	private Map<AbstractFeature, BoolExpr> feature2BoolExpr;
 
 	/** The mapping of translated {@link EObject}s to global {@link PresenceCondition}s. */
-	protected Map<EObject, PresenceConditionTerm> object2presenceCondition;
+	private Map<EObject, PresenceConditionTerm> object2presenceCondition;
 
 	/**
 	 * The mapping from Z3 {@link Expr} back to the respective {@link EObject} to be used for
 	 * interpreting solver results.
 	 */
-	protected Map<Expr<?>, EObject> expr2EObject = new HashMap<Expr<?>, EObject>();
+	private Map<Expr<?>, EObject> expr2EObject = new HashMap<Expr<?>, EObject>();
 
 	/**
 	 * The mapping of translated {@link EReference}s to the type that will be used for translation.
 	 * This type might be different from the references original type in case only a subtype is
 	 * specified for translation.
 	 */
-	protected Map<EReference, EClass> reference2TranslatedEClass;
+	private Map<EReference, EClass> reference2TranslatedEClass;
 
 	/** Flag that specifies whether the optimization to only translate optional parts is enabled. */
 	private boolean isIslandOptimizationEnabled = false;
@@ -246,16 +241,24 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 					if(ecls.isSuperTypeOf(refType)) {
 						reference2TranslatedEClass.put(ref, ecls);
 					} else if(refType.isSuperTypeOf(ecls)) {
-						// FIXME: Is this a good idea?
 						// Attempt to use nearest found class
 						reference2TranslatedEClass.put(ref, ecls);
+
+						logInfo(LOG_PREFIX + "The reference \"" + ref.getName() + "\" of type " +
+								refType.getName() +
+								" is supposed to be transletd for a prodct-line analysis. Since this type is not specified to be translated, the translated sub-class " +
+								ecls.getName() + " will be used.");
 					}
 				}
 
 				// Check if any super type was found
 				if(reference2TranslatedEClass.get(ref) == null) {
-					throw new RuntimeException("ERefernce \"" + ref.getName() + "\" is of type " +
-							ref.getEReferenceType().getName() + " which is not translated.");
+					String errMsg = LOG_PREFIX + "ERefernce \"" + ref.getName() + "\" is of type " +
+							ref.getEReferenceType().getName() + " which is not translated.";
+
+					logError(errMsg);
+
+					throw new RuntimeException(errMsg);
 				}
 			}
 		}
@@ -324,15 +327,8 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		for(EReference ref : model.eClass().getEAllReferences()) {
 			if(translatedReferences.contains(ref)) {
 				EObject refObj = (EObject)model.eGet(ref);
-
 				EClass refClass = reference2TranslatedEClass.get(ref);
-				if(refClass != null) {
-					class2TranslatedEObjects.add(refClass, refObj);
-				} else {
-					throw new RuntimeException("Invalid reference found. Reference " +
-							ref.getName() + " is of type " + ref.getEReferenceType().getName() +
-							" which is not translated.");
-				}
+				class2TranslatedEObjects.add(refClass, refObj);
 
 				collectTranslatedReferences(refObj, remainingSteps - 1);
 			}
@@ -359,8 +355,6 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 							class2TranslatedEObjects.add(cls, referencingEObject);
 
 							collectTranslatedReferences(referencingEObject, remainingSteps - 1);
-
-							// break;
 						}
 					}
 				}
@@ -368,55 +362,8 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		}
 	}
 
-	/**
-	 * Retrieves the {@link PresenceCondition} that was assigned to 'modelElement' in the model.
-	 * This function might be overwritten in case an alternative location for presence conditions
-	 * was defined.
-	 */
-	protected PresenceConditionTerm getLocalPresenceCondition(EObject model) {
-		if(model instanceof IOptionalVariationPoint<?>) {
-			PresenceCondition presenceCondition =
-					((IOptionalVariationPoint<?>)model).getPresenceCondition();
-
-			if(presenceCondition == null) {
-				return null;
-			}
-
-			return presenceCondition.resolveToFeatureLiterals();
-		}
-		if(model instanceof IAlternative) {
-			return ((IAlternative)model).getPresenceCondition().resolveToFeatureLiterals();
-		}
-
-		return null;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public void setTranslatedEClasses(Collection<EClass> clss) {
-		translatedClasses.clear();
-
-		translatedClasses.addAll(clss);
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public void setTranslatedEReferences(Collection<EReference> refs) {
-		translatedReferences.clear();
-
-		translatedReferences.addAll(refs);
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public void setTranslatedEAttributes(Collection<EAttribute> atts) {
-		translatedAttributes.clear();
-
-		translatedAttributes.addAll(atts);
-	}
-
 	/** Translates all presence conditions to Z3. */
-	protected void translatePresenceConditions() {
+	private void translatePresenceConditions() {
 		for(EClass ec : translatedClasses) {
 			EnumSort<?> ecSort = eClass2z3Sort.get(ec);
 			FuncDecl<?> selFun = ctx.mkFuncDecl("SELECTED_" + ec.getName(), ecSort, boolSort);
@@ -473,7 +420,7 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 			return ctx.mkNot(translatePresenceCondition(((NotPC)pc).getOperand()));
 		}
 
-		logError("Unknown PresenceCondition: " + pc);
+		logError(LOG_PREFIX + "Unknown PresenceCondition: " + pc);
 		return null;
 	}
 
@@ -552,25 +499,10 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		}
 	}
 
-	/** Creates and initializes the Z3 solver to be used for analyis. */
-	@Override
-	public Solver createSolver() {
-		Solver solver = ctx.mkSolver();
-
-		solver.add(featureModelAssertions.toArray(new BoolExpr[featureModelAssertions.size()]));
-		solver.add(presenceConditionAssertions
-				.toArray(new BoolExpr[presenceConditionAssertions.size()]));
-		solver.add(modelAssertions.toArray(new BoolExpr[modelAssertions.size()]));
-
-		solver.add(constraintAssertions.toArray(new BoolExpr[constraintAssertions.size()]));
-
-		return solver;
-	}
-
 	/** Translates all objects in the model. */
 	private void translateObjects() {
 		// Translate objects by class.
-		for(EClass ec : class2TranslatedEObjects.keySet()) {
+		for(EClass ec : translatedClasses) {
 			Set<EObject> objs = class2TranslatedEObjects.get(ec);
 
 			EList<EAttribute> attributes = ec.getEAllAttributes();
@@ -628,7 +560,7 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 			List<?> values = (List<?>)value;
 
 			if(values.size() == 0) {
-				return ctx.mkEmptySeq(eReferenceToz3Sort(er));
+				return ctx.mkEmptySeq(getSortForReference(er));
 			}
 
 			SeqExpr[] seqElems = new SeqExpr[values.size()];
@@ -639,7 +571,7 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 
 				SeqExpr<?> selectedExpr = ctx.mkUnit(elemExpr);
 				if(refSelFun != null) {
-					SeqExpr notSelectedExpr = ctx.mkEmptySeq(eReferenceToz3Sort(er));
+					SeqExpr notSelectedExpr = ctx.mkEmptySeq(getSortForReference(er));
 					seqElems[i] = (SeqExpr<?>)ctx.mkITE((BoolExpr)ctx.mkApp(refSelFun, elemExpr),
 							selectedExpr, notSelectedExpr);
 				} else {
@@ -648,7 +580,7 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 			}
 
 			if(seqElems.length == 0) {
-				return ctx.mkEmptySeq(eReferenceToz3Sort(er));
+				return ctx.mkEmptySeq(getSortForReference(er));
 			}
 			if(seqElems.length == 1) {
 				return seqElems[0];
@@ -702,7 +634,7 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		// Single value
 		if(attType.equals(EcorePackage.Literals.EINT)) {
 			if(value == null) {
-				logError("null int found");
+				logError(LOG_PREFIX + "null int found");
 				return ctx.mkInt(0);
 			}
 			return ctx.mkInt((int)value);
@@ -715,7 +647,7 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		}
 		if(attType.equals(EcorePackage.Literals.EBOOLEAN)) {
 			if(value == null) {
-				logError("null bool found");
+				logError(LOG_PREFIX + "null bool found");
 				return ctx.mkBool(false);
 			}
 			return ctx.mkBool((boolean)value);
@@ -768,18 +700,25 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 
 					if(refSort == null) {
 						// Find translated subclass of reference target and attempt to use this.
-						// TODO: Log message
 						for(EClass ecls : translatedClasses) {
 							if(refType.isSuperTypeOf(ecls)) {
 								refSort = eClass2z3Sort.get(ecls);
+
+								logInfo(LOG_PREFIX + "The reference \"" + er.getName() +
+										"\" of type " + refType.getName() +
+										" is supposed to be transletd for a prodct-line analysis. Since this type is not specified to be translated, the translated sub-class " +
+										ecls.getName() + " will be used.");
 							}
 						}
 					}
 
 					if(refSort == null) {
-						throw new RuntimeException("Reference " + er.getName() +
+						String msg = "Reference " + er.getName() +
 								" shall be translated, but is of type " + refType.getName() +
-								" which is not translated. Add the type to the translated classes to translate this reference.");
+								" which is not translated. Add the type to the translated classes to translate this reference.";
+
+						logError(LOG_PREFIX + msg, null);
+						throw new RuntimeException(msg);
 					}
 
 					if(er.getUpperBound() < 0) {
@@ -850,9 +789,19 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		}
 	}
 
-	/** Logs an error in the translation. */
-	private void logError(String message) {
-		// FIXME //error(getDefault(), "Error in product-line translation: " + message);
+	/** {@inheritDoc} */
+	@Override
+	public Solver createSolver() {
+		Solver solver = ctx.mkSolver();
+
+		solver.add(featureModelAssertions.toArray(new BoolExpr[featureModelAssertions.size()]));
+		solver.add(presenceConditionAssertions
+				.toArray(new BoolExpr[presenceConditionAssertions.size()]));
+		solver.add(modelAssertions.toArray(new BoolExpr[modelAssertions.size()]));
+
+		solver.add(constraintAssertions.toArray(new BoolExpr[constraintAssertions.size()]));
+
+		return solver;
 	}
 
 	/** {@inheritDoc} */
@@ -867,25 +816,12 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		return expr2EObject.get(expr);
 	}
 
-	/** {@inheritDoc} FIXME: required?? */
-	@Override
-	public FuncDecl<?> getSelectionFunction(EClass cls) {
-		return eClass2SelectionFunction.get(cls);
-	}
-
 	/** {@inheritDoc} */
 	@Override
 	public Expr<?> getNullElement(EClass cls) {
 		return eClass2NullElement.get(cls);
 	}
 
-	/** {@inheritDoc} */
-	@Override
-	@Deprecated
-	public final void addExcludedClasses(Collection<EClass> excludedClasses) {
-		// EMPTY
-	}
-
 	/** {@inheritDoc} */
 	@Override
 	public EnumSort<?> getDatatype(EClass ec) {
@@ -951,7 +887,7 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 			EClass cls = variableClasses[i];
 			Expr<?> var = quantifierValiables[i];
 
-			FuncDecl<?> selFun = getSelectionFunction(cls);
+			FuncDecl<?> selFun = eClass2SelectionFunction.get(cls);
 			BoolExpr selected = (BoolExpr)ctx.mkApp(selFun, var);
 			BoolExpr notNull = ctx.mkNot(ctx.mkEq(var, getNullElement(cls)));
 
@@ -975,21 +911,87 @@ public class EMFProductLineTranslation implements IProductLineTranslation {
 		return ctx.mkExists(quantifierValiables, liftedBody, 0, null, null, null, null);
 	}
 
-	/** Sets isIslandOptimizationEnabled. TODO */
-	public void setIslandOptimizationEnabled(boolean isIslandOptimizationEnabled) {
-		this.isIslandOptimizationEnabled = isIslandOptimizationEnabled;
+	/** Utility method to get the z3 sort for a given reference. */
+	private EnumSort<?> getSortForReference(EReference er) {
+		return eClass2z3Sort.get(reference2TranslatedEClass.get(er));
 	}
 
-	/** Sets islandOptimizationStepNum. TODO */
-	public void setIslandOptimizationStepNum(int islandOptimizationStepNum) {
-		this.islandOptimizationStepNum = islandOptimizationStepNum;
+	/**
+	 * Retrieves the {@link PresenceCondition} that was assigned to 'modelElement' in the model.
+	 * This function might be overwritten in case an alternative location for presence conditions
+	 * was defined.
+	 */
+	protected PresenceConditionTerm getLocalPresenceCondition(EObject model) {
+		if(model instanceof IOptionalVariationPoint<?>) {
+			PresenceCondition presenceCondition =
+					((IOptionalVariationPoint<?>)model).getPresenceCondition();
+
+			if(presenceCondition == null) {
+				return null;
+			}
+
+			return presenceCondition.resolveToFeatureLiterals();
+		}
+		if(model instanceof IAlternative) {
+			return ((IAlternative)model).getPresenceCondition().resolveToFeatureLiterals();
+		}
+
+		return null;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void setTranslatedEClasses(Collection<EClass> clss) {
+		translatedClasses.clear();
+
+		translatedClasses.addAll(clss);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void setTranslatedEReferences(Collection<EReference> refs) {
+		translatedReferences.clear();
+
+		translatedReferences.addAll(refs);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void setTranslatedEAttributes(Collection<EAttribute> atts) {
+		translatedAttributes.clear();
+
+		translatedAttributes.addAll(atts);
 	}
 
 	/**
-	 * @param er
-	 * @return
+	 * Enables or disables the "island optimization" for which only optional parts of the model are
+	 * translated.
+	 * This optimization is disbaled by default.
+	 * 
+	 * Via the method {@code setIslandOptimizationStepNum()} it is possible to specify a range of
+	 * transitive references to be guaranteed to be translated for all optional elements.
+	 * Note, that this step size might be crucial for a constraint to checked correctly for
+	 * interactions between optional and non-optional elements.
+	 * 
+	 * @param setEnabled
+	 *            'true' will enable the island optimization; 'false' will disbale.
 	 */
-	private EnumSort<?> eReferenceToz3Sort(EReference er) {
-		return eClass2z3Sort.get(reference2TranslatedEClass.get(er));
+	public void setIslandOptimizationEnabled(boolean setEnabled) {
+		this.isIslandOptimizationEnabled = setEnabled;
+	}
+
+	/**
+	 * Specifies a number of transitive references starting from every optional element that will be
+	 * guaranteed to be translated - even if they are non-optional.
+	 * 
+	 * Note, that this step size might be crucial for a constraint to checked correctly for
+	 * interactions between optional and non-optional elements.
+	 * 
+	 * @param stepNum
+	 *            The number of trabnsitive references to be guaranteed to be translated for all
+	 *            optional elements.
+	 */
+	public void setIslandOptimizationStepNum(int stepNum) {
+		this.islandOptimizationStepNum = stepNum;
 	}
 }
diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineConstraint.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineConstraint.java
index 7ddf34012..1b0e1231c 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineConstraint.java
+++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineConstraint.java
@@ -62,7 +62,7 @@ public interface IProductLineConstraint {
 	 * 
 	 * @return An array of variables as {@link Expr}s.
 	 */
-	public Expr[] getQuantifierVariables();
+	public Expr<?>[] getQuantifierVariables();
 
 	/**
 	 * Retrieves the constrain body for this constraint.
@@ -84,7 +84,7 @@ public interface IProductLineConstraint {
 	 * 
 	 * @return An array of {@link Expr}s with the quantifier variables.
 	 */
-	public Expr[] getVariableTracker();
+	public Expr<?>[] getVariableTracker();
 
 	/**
 	 * Retrieves the {@link EClass} types for the quantified variables.
@@ -93,9 +93,26 @@ public interface IProductLineConstraint {
 	 */
 	public EClass[] getVariablesClasses();
 
+	/**
+	 * Specifies the classes which need to be translated in order to evaluate this constraint.
+	 * 
+	 * @return A {@link Collection} with all {@link EClass} which will be required to be translated.
+	 */
 	public Collection<EClass> getTranslatedClasses();
 
+	/**
+	 * Specifies the references which are used in this constraint and need to translated.
+	 * 
+	 * @return A {@link Collection} with all {@link EReference} which will be required to be
+	 *         translated.
+	 */
 	public Collection<EReference> getTranslatedReferences();
 
+	/**
+	 * Specifies the attributes which are used in this constraint and need to translated.
+	 * 
+	 * @return A {@link Collection} with all {@link EAttribute} which will be required to be
+	 *         translated.
+	 */
 	public Collection<EAttribute> getTranslatedAttributes();
 }
diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineTranslation.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineTranslation.java
index 410a2dba4..733dae03e 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineTranslation.java
+++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineTranslation.java
@@ -31,74 +31,119 @@ import com.microsoft.z3.FuncDecl;
 import com.microsoft.z3.Solver;
 
 /**
+ * Interface for generic translation of model product-lines to SMT.
  * 
  * @author bayha
  */
 public interface IProductLineTranslation {
 
 	/**
-	 * @return
+	 * Retrieves the context used for this translation.
+	 * 
+	 * @return The Z3 {@link Context}.
 	 */
-	Context getContext();
+	public Context getContext();
 
 	/**
+	 * Translates the given model to Z3 SMT.
+	 * 
 	 * @param model
+	 *            {@link EObject} with model to be translated.
 	 */
-	void translateModel(EObject model);
+	public void translateModel(EObject model);
 
 	/**
+	 * Translates the given product-line constraints to Z3 SMT.
+	 * 
 	 * @param constraints
-	 * @return
+	 *            A {@link Collection} of {@link IProductLineConstraint} to be translated.
+	 * 
+	 * @return A {@link Map} with Z3 {@link BoolExpr} to track the constraints in Z3
+	 *         models.
 	 */
-	Map<BoolExpr, IProductLineConstraint>
+	public Map<BoolExpr, IProductLineConstraint>
 			translateConstraints(Collection<IProductLineConstraint> constraints);
 
 	/**
-	 * @return
+	 * Retrieves the model element which was the source for the given Z3 expression.
+	 * 
+	 * @param expr
+	 *            The Z3 {@link Expr} for which to retrieve the originating {@link EObject}.
+	 * 
+	 * @return The {@link EObject} which was the source for the given Z3 expression.
 	 */
-	EObject getEObjectForExpression(Expr<?> expr);
+	public EObject getEObjectForExpression(Expr<?> expr);
 
 	/**
-	 * @param tracToExpr
-	 * @return
+	 * Creates and initializes the Z3 solver to be used for analyzes.
+	 * 
+	 * Note, that {@code translateModel()} and {@code translateConstraints} should be called prior
+	 * to this method.
+	 * 
+	 * @return The Z3 {@link Solver} containing the model translation.
 	 */
-	Solver createSolver();
+	public Solver createSolver();
 
 	/**
+	 * Retrieves the Z3 expression representing null for the given {@link EClass}.
+	 * 
 	 * @param cls
-	 * @return
+	 *            The {@link EClass} to retrieve the Z3 null element for.
+	 * @return The Z3 {@link Expr} encoding null.
 	 */
-	FuncDecl getSelectionFunction(EClass cls);
+	public Expr<?> getNullElement(EClass cls);
 
 	/**
-	 * @param cls
-	 * @return
+	 * Retrieves the Z3 sort which represents the given EClass and its objects.
+	 * 
+	 * @param eClass
+	 *            The {@link EClass} to get the Z3 sort for.
+	 * @return The Z3 {@link EnumSort} for the given eClass.
 	 */
-	Expr<?> getNullElement(EClass cls);
+	public EnumSort<?> getDatatype(EClass eClass);
 
 	/**
-	 * @param excludedClasses
+	 * Retrieve the Z3 function declaration which represents the given attribute or reference for
+	 * the given EClass.
+	 * 
+	 * @param eClass
+	 *            The {@link EClass} for which to get a attribute or reference function.
+	 * @param attRefName
+	 *            {@link String} with the name for the attribute or reference.
+	 * @return A Z3 {@link FuncDecl} representing the attribute or reference.
 	 */
-	@Deprecated
-	void addExcludedClasses(Collection<EClass> excludedClasses);
+	FuncDecl<?> getAttributeReferenceFunctionDeclaration(EClass eClass, String attRefName);
 
 	/**
-	 * @param ec
-	 * @return
+	 * Specifies the classes for which model elements shall be translated.
+	 * 
+	 * Note, that all classes which are relevant for evaluating the constraints need to specified
+	 * here, before staring a translation.
+	 * 
+	 * @param clss
+	 *            A {@link Collection} of all {@link EClass} to be translated.
 	 */
-	EnumSort getDatatype(EClass ec);
+	public void setTranslatedEClasses(Collection<EClass> clss);
 
 	/**
-	 * @param cVarType
-	 * @param string
-	 * @return
+	 * Specifies the references which shall be translated.
+	 * 
+	 * Note, that all references which are used in the constraints need to specified
+	 * here, before staring a translation.
+	 * 
+	 * @param refs
+	 *            A {@link Collection} of all {@link EReference} to be translated.
 	 */
-	FuncDecl getAttributeReferenceFunctionDeclaration(EClass cVarType, String string);
-
-	public void setTranslatedEClasses(Collection<EClass> clss);
-
 	public void setTranslatedEReferences(Collection<EReference> refs);
 
+	/**
+	 * Specifies the attributes which shall be translated.
+	 * 
+	 * Note, that all attributes which are used in the constraints need to specified
+	 * here, before staring a translation.
+	 * 
+	 * @param atts
+	 *            A {@link Collection} of all {@link EAttribute} to be translated.
+	 */
 	public void setTranslatedEAttributes(Collection<EAttribute> atts);
-
 }
diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java
index 58afed3e0..04097c7c3 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java
+++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java
@@ -16,12 +16,9 @@
 package org.fortiss.variability.analysis;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.fortiss.variability.model.features.configuration.VariantConfiguration;
 
 import com.microsoft.z3.BoolExpr;
 import com.microsoft.z3.EnumSort;
@@ -49,16 +46,16 @@ public abstract class ProductLineConstraintBase implements IProductLineConstrain
 	protected String[] variableNames;
 
 	/** The quantified variables */
-	protected Expr[] variables;
+	protected Expr<?>[] variables;
 
 	/**
 	 * The tracking constants which are used to extract violating interpretations for the quantifier
 	 * variables.
 	 */
-	protected Expr[] trackerVars;
+	protected Expr<?>[] trackerVars;
 
 	/** A map from variable names to expressions which can be used in the body. */
-	protected Map<String, Expr> name2Variables = new HashMap<String, Expr>();
+	protected Map<String, Expr<?>> name2Variables = new HashMap<String, Expr<?>>();
 
 	/** The {@link IProductLineTranslation} to be used for creation of variables. */
 	protected IProductLineTranslation translation;
@@ -72,54 +69,31 @@ public abstract class ProductLineConstraintBase implements IProductLineConstrain
 		trackerVars = new Expr[variableNames.length];
 	}
 
-	/** Creates tracking variables and adds them to the body. */
-	private final void createTracking() {
-		int numVariables = variableNames.length;
-		BoolExpr[] trackExprs = new BoolExpr[numVariables + 1];
-
-		for(int i = 0; i < variables.length; i++) {
-			trackExprs[i] = translation.getContext().mkEq(trackerVars[i], variables[i]);
-		}
-
-		trackExprs[numVariables] = body;
-
-		body = translation.getContext().mkAnd(trackExprs);
-	}
-
-	/** Creates the Z3 variables for this constraint, using the translation. */
-	private final void createVariables() {
-		int numVariables = variableTypes.length;
-		variables = new Expr[numVariables];
-
-		for(int i = 0; i < numVariables; i++) {
-			EClass ec = variableTypes[i];
-			EnumSort ecSort = translation.getDatatype(ec);
+	/** Creates the actual body for this constraint using the quantified variables. */
+	protected abstract BoolExpr createBody();
 
-			String varName = variableNames[i];
-			trackerVars[i] = translation.getContext().mkConst(TRACK_PREFIX + varName, ecSort);
+	/** Specifies the names for the quantified variables. */
+	protected abstract String[] createVariableNames();
 
-			Expr var = translation.getContext().mkConst(varName, ecSort);
-			variables[i] = var;
-			name2Variables.put(varName, var);
-		}
-	}
+	/** Specifies the EClass types for the quantified variables. */
+	protected abstract EClass[] createVariablesClasses();
 
 	/** {@inheritDoc} */
 	@Override
-	public final Expr[] getQuantifierVariables() {
+	public final Expr<?>[] getQuantifierVariables() {
 		if(variables == null) {
 			createVariables();
 		}
 		return variables;
 	}
 
-	/** Returns tracker. */
+	/** {@inheritDoc} */
 	@Override
-	public final Expr[] getVariableTracker() {
+	public final Expr<?>[] getVariableTracker() {
 		return trackerVars;
 	}
 
-	/** Returns body. */
+	/** {@inheritDoc} */
 	@Override
 	public final BoolExpr getBody() {
 		if(variables == null) {
@@ -134,31 +108,41 @@ public abstract class ProductLineConstraintBase implements IProductLineConstrain
 		return body;
 	}
 
-	/** Returns variableTypes. */
+	/** {@inheritDoc} */
 	@Override
 	public final EClass[] getVariablesClasses() {
 		return variableTypes;
 	}
 
-	/** Creates the actual body for this constraint using the quantified variables. */
-	protected abstract BoolExpr createBody();
+	/** Creates tracking variables and adds them to the body. */
+	private final void createTracking() {
+		int numVariables = variableNames.length;
+		BoolExpr[] trackExprs = new BoolExpr[numVariables + 1];
 
-	/** Specifies the names for the quantified variables. */
-	protected abstract String[] createVariableNames();
+		for(int i = 0; i < variables.length; i++) {
+			trackExprs[i] = translation.getContext().mkEq(trackerVars[i], variables[i]);
+		}
 
-	/** Specifies the EClass types for the quantified variables. */
-	protected abstract EClass[] createVariablesClasses();
+		trackExprs[numVariables] = body;
 
-	/** {@inheritDoc} */
-	@Override
-	public abstract boolean isForAll();
+		body = translation.getContext().mkAnd(trackExprs);
+	}
 
-	/** {@inheritDoc} */
-	@Override
-	public abstract String getConstraintName();
+	/** Creates the Z3 variables for this constraint, using the translation. */
+	private final void createVariables() {
+		int numVariables = variableTypes.length;
+		variables = new Expr[numVariables];
 
-	/** {@inheritDoc} */
-	@Override
-	public abstract String createErrorMessage(List<EObject> violatingObjects,
-			VariantConfiguration violatingConfiguration);
+		for(int i = 0; i < numVariables; i++) {
+			EClass ec = variableTypes[i];
+			EnumSort<?> ecSort = translation.getDatatype(ec);
+
+			String varName = variableNames[i];
+			trackerVars[i] = translation.getContext().mkConst(TRACK_PREFIX + varName, ecSort);
+
+			Expr<?> var = translation.getContext().mkConst(varName, ecSort);
+			variables[i] = var;
+			name2Variables.put(varName, var);
+		}
+	}
 }
diff --git a/org.fortiss.variability/src/org/fortiss/variability/util/.ratings b/org.fortiss.variability/src/org/fortiss/variability/util/.ratings
index 8f6b1c25d..253136c40 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/util/.ratings
+++ b/org.fortiss.variability/src/org/fortiss/variability/util/.ratings
@@ -1,4 +1,4 @@
 FeatureModelTransformationUtils.java b38702296dcb48ff311b382bb9c05d2590e2dfac GREEN
 Pair.java 2dfd7dc65f7b9ba09a120f1a6058d1e8e9556a37 GREEN
 VariabilityUtils.java 3e57a37ced6396076c71227aea8de534381b6ace GREEN
-VariabilityUtilsInternal.java 3db6af80e349e41ef3e236e783feaf34ce773fd0 YELLOW
+VariabilityUtilsInternal.java c5a4c445e73a15826882361a75b5dca201c3ca91 YELLOW
diff --git a/org.fortiss.variability/src/org/fortiss/variability/util/VariabilityUtilsInternal.java b/org.fortiss.variability/src/org/fortiss/variability/util/VariabilityUtilsInternal.java
index 3db6af80e..c5a4c445e 100644
--- a/org.fortiss.variability/src/org/fortiss/variability/util/VariabilityUtilsInternal.java
+++ b/org.fortiss.variability/src/org/fortiss/variability/util/VariabilityUtilsInternal.java
@@ -16,9 +16,13 @@
  +--------------------------------------------------------------------------*/
 package org.fortiss.variability.util;
 
+import static org.eclipse.core.runtime.IStatus.ERROR;
+import static org.eclipse.core.runtime.IStatus.INFO;
+import static org.eclipse.core.runtime.IStatus.WARNING;
 import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
 import static org.eclipse.emf.ecore.util.EcoreUtil.getRootContainer;
 import static org.eclipse.emf.ecore.util.EcoreUtil.UsageCrossReferencer.find;
+import static org.fortiss.variability.VariabilityActivator.getDefault;
 import static org.fortiss.variability.model.VariabilityModelElementFactory.createAndPC;
 
 import java.util.Collection;
@@ -26,9 +30,11 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
-import java.util.Set;
 import java.util.function.Predicate;
 
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.emf.common.util.BasicEList;
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.TreeIterator;
@@ -43,6 +49,9 @@ import org.fortiss.variability.model.presence.PresenceConditionTerm;
 /**
  * Utility functions that are used within the variability layers.
  * 
+ * This class contains duplicates of EcoreUtils of the fortiss Tooling Kernel to enable a usage of
+ * this variability plugin independent of the tooling kernel.
+ * 
  * @author bayha
  */
 public class VariabilityUtilsInternal {
@@ -263,14 +272,56 @@ public class VariabilityUtilsInternal {
 		return rest;
 	}
 
-	public static Class<? extends EObject> getContainedSuperClass(Class<?> subCls,
-			Set<Class<? extends EObject>> clss) {
-		for(Class<? extends EObject> t : clss) {
-			if(t.isAssignableFrom(subCls)) {
-				return t;
-			}
-		}
+	/**
+	 * Logs a message that occurred in the context of the given plug-in with the
+	 * given severity and a given {@link Throwable} that originally caused this
+	 * log message.
+	 */
+	private static void log(Plugin plugin, String message, int severity, Throwable cause) {
+		String pluginId = plugin.getBundle().getSymbolicName();
+		IStatus status = new Status(severity, pluginId, message, cause);
+		plugin.getLog().log(status);
+	}
+
+	/**
+	 * Logs an info message that occurred in the context of the variability plug-in.
+	 * 
+	 * @param message
+	 *            The {@link String} with the info message to be logged.
+	 */
+	public static void logInfo(String message) {
+		log(getDefault(), message, INFO, null);
+	}
+
+	/**
+	 * Logs a warning that occurred in the context of the variability plug-in.
+	 * 
+	 * @param message
+	 *            The {@link String} with the warning message to be logged.
+	 */
+	public static void logWarning(String message) {
+		log(getDefault(), message, WARNING, null);
+	}
+
+	/**
+	 * Logs an error that occurred in the context of the variability plug-in.
+	 * 
+	 * @param message
+	 *            The {@link String} with the error message to be logged.
+	 * @param exception
+	 *            The {@link Exception} that originally caused this log message.
+	 */
+	public static void logError(String message, Exception exception) {
+		log(getDefault(), message, ERROR, exception);
+	}
 
-		return null;
+	/**
+	 * Logs an error that occurred in the context of the variability plug-in.
+	 * 
+	 * @param message
+	 *            The {@link String} with the error message to be logged.
+	 */
+	public static void logError(String message) {
+		log(getDefault(), message, ERROR, null);
 	}
 }
-- 
GitLab