/* FeatureIDE - An IDE to support feature-oriented software development * Copyright (C) 2005-2009 FeatureIDE Team, University of Magdeburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * See http://www.fosd.de/featureide/ for further information. */ package featureide.fm.core.editing; import java.util.HashMap; import java.util.LinkedList; import org.prop4j.And; import org.prop4j.AtMost; import org.prop4j.Equals; import org.prop4j.Implies; import org.prop4j.Literal; import org.prop4j.Node; import org.prop4j.Not; import org.prop4j.Or; import featureide.fm.core.Feature; import featureide.fm.core.FeatureModel; public class NodeCreator { private static final HashMap<Object, Node> EMPTY_MAP = new HashMap<Object, Node>(); public static Node createNodes(FeatureModel featureModel) { return createNodes(featureModel, EMPTY_MAP); } public static Node createNodes(FeatureModel featureModel, HashMap<Object, Node> replacingMap) { Feature root = featureModel.getRoot(); LinkedList<Node> nodes = new LinkedList<Node>(); if (root != null) { nodes.add(new Literal(getVariable(root, featureModel))); //convert grammar rules into propositional formulas createNodes(nodes, root, featureModel, true, replacingMap); //add extra constraints for (Node node : featureModel.getPropositionalNodes()) nodes.add(node.clone()); } return eliminateAbstractVariables(new And(nodes), replacingMap); } public static Node eliminateAbstractVariables(Node node, HashMap<Object, Node> map) { if (node instanceof Literal) { Literal literal = (Literal) node; if (map.containsKey(literal.var)) { Node replacing = map.get(literal.var); node = literal.positive ? replacing : new Not(replacing); } } else { Node[] children = node.getChildren(); for (int i = 0; i < children.length; i++) children[i] = eliminateAbstractVariables(children[i], map); } return node; } private static void createNodes(LinkedList<Node> nodes, Feature rootFeature, FeatureModel featureModel, boolean recursive, HashMap<Object, Node> replacings) { if (rootFeature == null || !rootFeature.hasChildren()) return; String s = getVariable(rootFeature, featureModel); Node[] children = new Node[rootFeature.getChildrenCount()]; for (int i = 0; i < children.length; i++) { String var = getVariable(rootFeature.getChildren().get(i), featureModel); children[i] = new Literal(var); } Node definition = children.length == 1 ? children[0] : new Or(children); if (rootFeature.isAnd()) {// && (!replacings.containsKey(featureModel.getOldName(rootFeature.getName())) || !rootFeature.isPossibleEmpty())) { LinkedList<Node> manChildren = new LinkedList<Node>(); for (Feature feature : rootFeature.getChildren()) if (feature.isMandatory()) { String var = getVariable(feature, featureModel); manChildren.add(new Literal(var)); } //add constraints for all mandatory children S => (A & B) if (manChildren.size() == 1) nodes.add(new Implies(new Literal(s), manChildren.getFirst())); else if (manChildren.size() > 1) nodes.add(new Implies(new Literal(s), new And(manChildren))); //add contraint (A | B | C) => S if (!replacings.containsKey(featureModel.getOldName(rootFeature.getName()))) { if (rootFeature.isAbstract()) nodes.add(new Equals(definition, new Literal(s))); else nodes.add(new Implies(definition, new Literal(s))); } } else { //add constraint S <=> (A | B | C) if (!replacings.containsKey(featureModel.getOldName(rootFeature.getName()))) { nodes.add(new Equals(new Literal(s), definition)); } if (rootFeature.isAlternative()) { //add constraint atmost1(A, B, C) if (children.length > 1) nodes.add(new AtMost(1, Node.clone(children))); } } if (recursive) for (Feature feature : rootFeature.getChildren()) createNodes(nodes, feature, featureModel, true, replacings); } public static String getVariable(Feature feature, FeatureModel featureModel) { return featureModel.getOldName(feature.getName()); } }