package org.togglz.junit.vary;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.togglz.core.Feature;
import org.togglz.core.util.Validate;
/**
* Default implementation of {@link VariationSet} that allows to build the set dynamically.
*
* @author Christian Kaltepoth
*
* @param <F> The feature class
*/
public class VariationSetBuilder<F extends Feature> implements VariationSet<F>
{
public static <F extends Feature> VariationSetBuilder<F> create(Class<F> featureClass)
{
return new VariationSetBuilder<F>(featureClass);
}
private final Class<F> featureClass;
private final Set<F> featuresToVary = new HashSet<F>();
private final Set<F> featuresToEnable = new HashSet<F>();
private final Set<F> featuresToDisable = new HashSet<F>();
private VariationSetBuilder(Class<F> featureEnum)
{
Validate.notNull(featureEnum, "The featureEnum argument is required");
Validate.isTrue(featureEnum.isEnum(), "This class only works with feature enums");
this.featureClass = featureEnum;
}
/**
* Vary this feature in the variation set.
*/
public VariationSetBuilder<F> vary(F f)
{
featuresToVary.add(f);
featuresToEnable.remove(f);
featuresToDisable.remove(f);
return this;
}
/**
* Enable this feature in the variation set.
*/
public VariationSetBuilder<F> enable(F f)
{
featuresToVary.remove(f);
featuresToEnable.add(f);
featuresToDisable.remove(f);
return this;
}
/**
* Disable this feature in the variation set.
*/
public VariationSetBuilder<F> disable(F f)
{
featuresToVary.remove(f);
featuresToEnable.remove(f);
featuresToDisable.add(f);
return this;
}
/**
* Enable all features in the variation set.
*/
public VariationSetBuilder<F> enableAll() {
for (F f : featureClass.getEnumConstants()) {
enable(f);
}
return this;
}
/**
* Disable all features in the variation set.
*/
public VariationSetBuilder<F> disableAll() {
for (F f : featureClass.getEnumConstants()) {
disable(f);
}
return this;
}
/*
* (non-Javadoc)
*
* @see org.togglz.junit.vary.VariationSet#getVariants()
*/
@Override
public Set<Set<F>> getVariants()
{
// start with a single variant with all feature disabled
Set<Set<F>> variantSet = new LinkedHashSet<Set<F>>();
variantSet.add(new HashSet<F>());
for (F feature : featureClass.getEnumConstants()) {
// enable the feature in all variants
if (featuresToEnable.contains(feature)) {
for (Set<F> variant : variantSet) {
variant.add(feature);
}
}
// disable the feature in all variants
else if (featuresToDisable.contains(feature)) {
for (Set<F> variant : variantSet) {
variant.remove(feature);
}
}
// copy the existing variants, enable the feature in the copy, and merge them
else if (featuresToVary.contains(feature)) {
Set<Set<F>> copy = deepCopy(variantSet);
for (Set<F> variant : copy) {
variant.add(feature);
}
variantSet.addAll(copy);
}
}
return variantSet;
}
private Set<Set<F>> deepCopy(Set<Set<F>> src) {
Set<Set<F>> copy = new HashSet<Set<F>>();
for (Set<F> variant : src) {
copy.add(new HashSet<F>(variant));
}
return copy;
}
public Class<? extends Feature> getFeatureClass()
{
return featureClass;
}
}