From ea95f7925ac450e2a6b7148dcf5f98b991200a75 Mon Sep 17 00:00:00 2001 From: Andreas Bayha <bayha@fortiss.org> Date: Tue, 25 Apr 2023 17:22:07 +0200 Subject: [PATCH] YELLOW Issue-ref: 4240 Issue-URL: af3#4240 Signed-off-by: Andreas Bayha <bayha@fortiss.org> --- .../org/fortiss/variability/analysis/.ratings | 6 +- .../variability/analysis/BucketMap.java | 54 ------ .../variability/analysis/BucketSetMap.java | 14 +- .../analysis/IProductLineConstraint.java | 54 +++++- .../analysis/ProductLineConstraintBase.java | 158 ++++++++++++++++++ .../ProductLineConstraintViolation.java | 12 +- 6 files changed, 223 insertions(+), 75 deletions(-) delete mode 100644 org.fortiss.variability/src/org/fortiss/variability/analysis/BucketMap.java create mode 100644 org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings b/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings index a69031f1f..87e0861f6 100644 --- a/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings +++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/.ratings @@ -1,3 +1,5 @@ -BucketMap.java c9572ca6503b41462240c1931cb1390af7b46c73 YELLOW -BucketSetMap.java 2c87b2f7f9ac68ed0aa669d665a1f6cb91d27207 YELLOW +BucketSetMap.java 407a35a6377ace1627c4c31890cfdc907f85945b YELLOW DualKeyMap.java 75fbe85a54e5a655aaf67108ae004f98ed2879d8 YELLOW +IProductLineConstraint.java e9dfd0f5271420e9801b7728c718808e7316522e YELLOW +ProductLineConstraintBase.java b112ea23bb618e8b5838943d3dede279f75b54b3 YELLOW +ProductLineConstraintViolation.java a822cc970dc7bd08d6e702c123d86b4a6e05b9f0 YELLOW diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/BucketMap.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/BucketMap.java deleted file mode 100644 index c9572ca65..000000000 --- a/org.fortiss.variability/src/org/fortiss/variability/analysis/BucketMap.java +++ /dev/null @@ -1,54 +0,0 @@ -/*-------------------------------------------------------------------------+ -| Copyright 2022 fortiss GmbH | -| | -| Licensed under the Apache License, Version 2.0 (the "License"); | -| you may not use this file except in compliance with the License. | -| You may obtain a copy of the License at | -| | -| http://www.apache.org/licenses/LICENSE-2.0 | -| | -| Unless required by applicable law or agreed to in writing, software | -| distributed under the License is distributed on an "AS IS" BASIS, | -| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | -| See the License for the specific language governing permissions and | -| limitations under the License. | -+--------------------------------------------------------------------------*/ -package org.fortiss.variability.analysis; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * {@link Map} implementation which maps a key to a {@link List} of values. - * - * @author bayha - */ -public class BucketMap<K, V> extends HashMap<K, List<V>> { - /** ISerializable */ - private static final long serialVersionUID = 312480465506162554L; - - /** - * Adds a given value to the list for the given key. - * - * @param key - * The key for which an additional value shall be added. - * @param value - * The additional value that shall be added. - * - * @return The new list of values for the given key. - */ - public List<V> append(K key, V value) { - List<V> lst = this.get(key); - - if(lst == null) { - lst = new ArrayList<V>(); - this.put(key, lst); - } - - lst.add(value); - - return lst; - } -} diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/BucketSetMap.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/BucketSetMap.java index 2c87b2f7f..407a35a63 100644 --- a/org.fortiss.variability/src/org/fortiss/variability/analysis/BucketSetMap.java +++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/BucketSetMap.java @@ -39,16 +39,16 @@ public class BucketSetMap<K, V> extends HashMap<K, Set<V>> { * * @return The new set of values for the given key. */ - public Set<V> append(K key, V value) { - Set<V> lst = this.get(key); + public Set<V> add(K key, V value) { + Set<V> set = this.get(key); - if(lst == null) { - lst = new HashSet<V>(); - this.put(key, lst); + if(set == null) { + set = new HashSet<V>(); + this.put(key, set); } - lst.add(value); + set.add(value); - return lst; + return set; } } 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 47d009b35..e9dfd0f52 100644 --- a/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineConstraint.java +++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/IProductLineConstraint.java @@ -25,26 +25,68 @@ import com.microsoft.z3.BoolExpr; import com.microsoft.z3.Expr; /** + * Interface for product line constraints to be checked by the {@link ProductLineBaseAnalysis}. + * + * Note that usually this interface should not be implemented immediately. Instead use the base + * class {@link ProductLineConstraintBase} to define new constraints. * * @author bayha */ public interface IProductLineConstraint { + /** + * The name of the constraint. + * + * @return The name as {@link String}. + */ public String getConstraintName(); - public String getConstraintMessage(List<EObject> violatingObjects, + /** + * Creates a meaningful error message for violations of this constraint. + * + * @param violatingObjects + * The {@link EObject}s which violate the constraint in combination. + * @param violatingConfiguration + * A {@link VariantConfiguration} which will result in a model variant in which the + * 'violatingObjects' will violate this constraint. + * @return The error message as a {@link String}. + */ + public String createErrorMessage(List<EObject> violatingObjects, VariantConfiguration violatingConfiguration); + /** + * Retrieves the quantified variables for this constraint. + * + * @return An array of variables as {@link Expr}s. + */ public Expr[] getQuantifierVariables(); - public EClass[] getVariablesClasses(); - - public BoolExpr[] getContainmentExpr(); - + /** + * Retrieves the constrain body for this constraint. + * + * @return The constraint body as a {@link BoolExpr}. + */ public BoolExpr getBody(); + /** + * Specifies whether this constraint is quantified as "for all". + * + * @return 'true' if this constraint is quantified as "for all". 'false' if "exists". + */ public boolean isForAll(); - public List<Expr> getVariableTracker(); + /** + * Retrieves the generated tracker variables to identify violating interpretations for the + * quantifier variables. + * + * @return An array of {@link Expr}s with the quantifier variables. + */ + public Expr[] getVariableTracker(); + /** + * Retrieves the {@link EClass} types for the quantified variables. + * + * @return An array of {@link EClass}s for all quantified variables. + */ + public EClass[] getVariablesClasses(); } diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java new file mode 100644 index 000000000..b112ea23b --- /dev/null +++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintBase.java @@ -0,0 +1,158 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2023 fortiss GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +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; +import com.microsoft.z3.Expr; + +/** + * Base class for product line constraints to be checked by the product-line analysis. + * + * All constraints are quantified expressions of the form: + * [ForAll|Exists] <list of quantifed variables>: <body using quantified variables> + * + * @author bayha + */ +public abstract class ProductLineConstraintBase implements IProductLineConstraint { + /** Prefix to label tracking variables. */ + private static final String TRACK_PREFIX = "TRACK_"; + + /** The body of this constraint. I.e. the quantified expression. */ + protected BoolExpr body; + + /** The {@link EClass} types of the quantified variables. */ + protected EClass[] variableTypes; + + /** The names of the quantified variables. */ + protected String[] variableNames; + + /** The quantified variables */ + protected Expr[] variables; + + /** + * The tracking constants which are used to extract violating interpretations for the quantifier + * variables. + */ + 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>(); + + /** The {@link ProductLineBaseTranslation} to be used for creation of variables. */ + protected ProductLineBaseTranslation translation; + + /** Constructor. */ + public ProductLineConstraintBase(ProductLineBaseTranslation translation) { + this.translation = translation; + + variableTypes = createVariablesClasses(); + variableNames = createVariableNames(); + trackerVars = new Expr[variableNames.length]; + + createVariables(); + + body = createBody(); + + createTracking(); + } + + /** 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.geteClass2Datatype().get(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); + } + } + + /** {@inheritDoc} */ + @Override + public final Expr[] getQuantifierVariables() { + return variables; + } + + /** Returns tracker. */ + @Override + public final Expr[] getVariableTracker() { + return trackerVars; + } + + /** Returns body. */ + @Override + public final BoolExpr getBody() { + return body; + } + + /** Returns variableTypes. */ + @Override + public final EClass[] getVariablesClasses() { + return variableTypes; + } + + /** Creates the actual body for this constraint using the quantified variables. */ + protected abstract BoolExpr createBody(); + + /** Specifies the names for the quantified variables. */ + protected abstract String[] createVariableNames(); + + /** Specifies the EClass types for the quantified variables. */ + protected abstract EClass[] createVariablesClasses(); + + /** {@inheritDoc} */ + @Override + public abstract boolean isForAll(); + + /** {@inheritDoc} */ + @Override + public abstract String getConstraintName(); + + /** {@inheritDoc} */ + @Override + public abstract String createErrorMessage(List<EObject> violatingObjects, + VariantConfiguration violatingConfiguration); +} diff --git a/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintViolation.java b/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintViolation.java index 7d4de79b3..a822cc970 100644 --- a/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintViolation.java +++ b/org.fortiss.variability/src/org/fortiss/variability/analysis/ProductLineConstraintViolation.java @@ -21,22 +21,22 @@ import org.eclipse.emf.ecore.EObject; import org.fortiss.variability.model.features.configuration.VariantConfiguration; /** + * Class representing one error identified by a product line analysis run. * * @author bayha */ public class ProductLineConstraintViolation { + /** The model elements which cause a constraint violation. */ protected List<EObject> violatingElements; + /** The violated constraint. */ protected IProductLineConstraint constraint; + /** The configuration which will reuslt in a model variant which violates the constraint. */ private VariantConfiguration violatingConfiguration; - /** - * @param constraint - * @param violatingElements - * @param violatingConfiguration - */ + /** Constructor. */ public ProductLineConstraintViolation(IProductLineConstraint constraint, List<EObject> violatingElements, VariantConfiguration violatingConfiguration) { this.constraint = constraint; @@ -51,7 +51,7 @@ public class ProductLineConstraintViolation { /** Returns errorMessage. */ public String getErrorMessage() { - return constraint.getConstraintMessage(violatingElements, violatingConfiguration); + return constraint.createErrorMessage(violatingElements, violatingConfiguration); } /** Returns constraint. */ -- GitLab