/** * Copyright (c) 2012-2016 Marsha Chechik, Alessio Di Sandro, Michalis Famelis, * Rick Salay. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Alessio Di Sandro - Implementation. */ package edu.toronto.cs.se.modelepedia.icse14.operator; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashSet; import java.util.Properties; import java.util.Set; import edu.toronto.cs.se.mmint.mid.utils.FileUtils; import edu.toronto.cs.se.mmint.mid.utils.MIDOperatorIOUtils; import edu.toronto.cs.se.modelepedia.z3.Z3Utils; import edu.toronto.cs.se.modelepedia.z3.operator.henshin.LiftingHenshinTransformation; import splar.core.constraints.CNFClause; import splar.core.constraints.CNFFormula; import splar.core.constraints.CNFLiteral; import splar.core.fm.FeatureModel; import splar.core.fm.XMLFeatureModel; public class FeatureModelToSMTLIB { private static final Set<String> Z3_KEYWORDS = new HashSet<String>(); static { Z3_KEYWORDS.add("select"); Z3_KEYWORDS.add("min"); } private static final String Z3_KEYWORD_SUFFIX = "_KEYWORD"; private static void getConstraint(String featureModelPath) throws Exception { FeatureModel featureModel = new XMLFeatureModel(featureModelPath, XMLFeatureModel.USE_VARIABLE_NAME_AS_ID); featureModel.loadModel(); CNFFormula cnf = featureModel.FM2CNF(); StringBuilder cnfFormula = new StringBuilder(Z3Utils.SMTLIB_AND); Set<String> cnfVars = new HashSet<String>(); boolean needSpace = false; String variable; for (CNFClause cnfClause : cnf.getClauses()) { if (cnfClause.countLiterals() > 1) { cnfFormula.append(Z3Utils.SMTLIB_OR); needSpace = false; } for (CNFLiteral cnfLiteral : cnfClause.getLiterals()) { if (!cnfLiteral.isPositive()) { cnfFormula.append(Z3Utils.SMTLIB_NOT); needSpace = false; } if (needSpace) { cnfFormula.append(" "); } variable = cnfLiteral.getVariable().getID(); if (Z3_KEYWORDS.contains(variable)) { variable += Z3_KEYWORD_SUFFIX; } cnfFormula.append(variable); cnfVars.add(variable); if (cnfLiteral.isPositive()) { needSpace = true; } else { cnfFormula.append(Z3Utils.SMTLIB_PREDICATE_END); } } if (cnfClause.countLiterals() > 1) { cnfFormula.append(Z3Utils.SMTLIB_PREDICATE_END); } } cnfFormula.append(Z3Utils.SMTLIB_PREDICATE_END); StringBuilder cnfVariables = new StringBuilder(); for (String cnfVariable : cnfVars) { cnfVariables.append(cnfVariable); cnfVariables.append(","); } cnfVariables.deleteCharAt(cnfVariables.length()-1); Properties outputProperties = new Properties(); outputProperties.setProperty(LiftingHenshinTransformation.PROPERTY_IN_CONSTRAINT, cnfFormula.toString()); outputProperties.setProperty(LiftingHenshinTransformation.PROPERTY_IN_CONSTRAINTVARIABLES, cnfVariables.toString()); outputProperties.store( new FileOutputStream( FileUtils.replaceFileExtensionInUri(featureModelPath, MIDOperatorIOUtils.PROPERTIES_SUFFIX.substring(1)) ), null ); } public static void main(String[] args) { String inputPath = args[0]; Path path = Paths.get(inputPath); if (Files.isDirectory(path)) { FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { try { getConstraint(file.toString()); } catch (Exception e) { e.printStackTrace(); } return FileVisitResult.CONTINUE; } }; try { Files.walkFileTree(path, visitor); } catch (IOException e) { e.printStackTrace(); } } else { try { getConstraint(inputPath); } catch (Exception e) { e.printStackTrace(); } } } }