/* * This is a prototype implementation of the concept of Feature-Sen * sitive Dataflow Analysis. More details in the AOSD'12 paper: * Dataflow Analysis for Software Product Lines * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package br.ufal.cideei.util; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import de.ovgu.cide.features.IFeature; // TODO: Auto-generated Javadoc /** * The Class SetUtil is a utility class to generate relevant sets to the * application. */ public class SetUtil { /** * Instantiates a new sets the util. */ private SetUtil() { } /** * Recursively generates a power set for a given set. * * @param <T> * the generic type * @param originalSet * the original set * @return the sets the */ // TODO: look for a more efficient implementation. public static <T> Set<Set<T>> powerSet(Set<T> originalSet) { Set<Set<T>> sets = new HashSet<Set<T>>(); if (originalSet.isEmpty()) { sets.add(new HashSet<T>()); return sets; } List<T> list = new ArrayList<T>(originalSet); T head = list.get(0); Set<T> rest = new HashSet<T>(list.subList(1, list.size())); for (Set<T> set : powerSet(rest)) { Set<T> newSet = new HashSet<T>(); newSet.add(head); newSet.addAll(set); sets.add(newSet); sets.add(set); } return sets; } /** * Generates a valid configuration sets for given set of features and a * power set. * * @param <T> * the generic type * @param featurePowerSet * the feature power set * @param featuresInUaf * the features in uaf * @return the sets the */ public static <T> Set<Set<T>> configurationSet(Set<Set<T>> featurePowerSet, Set<IFeature> featuresInUaf) { Iterator<Set<T>> powerSetIterator = featurePowerSet.iterator(); Set<Set<T>> resultingSet = new HashSet<Set<T>>(); while (powerSetIterator.hasNext()) { Set<T> nextSubSet = (Set<T>) powerSetIterator.next(); boolean foundFeature = false; if (featuresInUaf.size() >= 1) { Iterator<IFeature> iterator = featuresInUaf.iterator(); while (iterator.hasNext()) { IFeature feature = iterator.next(); if (nextSubSet.contains(feature.getName())) { foundFeature = true; } else { foundFeature = false; break; } } } if (foundFeature) { resultingSet.add(nextSubSet); } } return resultingSet; } /** * Returns the power set from the given set by using a binary counter * Example: S = {a,b,c} * * P(S) = {[], [c], [b], [b, c], [a], [a, c], [a, b], [a, b, c]} * * @param set * String[] * @return LinkedHashSet */ // TODO: retained as legacy. Search for a more efficient implementation. private static Set<Set<String>> powerset(String[] set) { // create the empty power set LinkedHashSet<Set<String>> power = new LinkedHashSet<Set<String>>(); // get the number of elements in the set int elements = set.length; // the number of members of a power set is 2^n int powerElements = (int) Math.pow(2, elements); // run a binary counter for the number of power elements for (int i = 0; i < powerElements; i++) { // convert the binary number to a string containing n digits String binary = intToBinary(i, elements); // create a new set LinkedHashSet<String> innerSet = new LinkedHashSet<String>(); // convert each digit in the current binary number to the // corresponding element // in the given set for (int j = 0; j < binary.length(); j++) { if (binary.charAt(j) == '1') innerSet.add(set[j]); } // add the new set to the power set power.add(innerSet); } return power; } /** * Converts the given integer to a String representing a binary number with * the specified number of digits For example when using 4 digits the binary * 1 is 0001 * * @param binary * int * @param digits * int * @return String */ private static String intToBinary(int binary, int digits) { String temp = Integer.toBinaryString(binary); int foundDigits = temp.length(); String returner = temp; for (int i = foundDigits; i < digits; i++) { returner = "0" + returner; } return returner; } }