package de.FeatureModellingTool.PLModelChecker.RelationAnalysis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import de.FeatureModellingTool.FeatureModel.CFRModifier;
import de.FeatureModellingTool.FeatureModel.CompositeConstraint;
import de.FeatureModellingTool.FeatureModel.CompositeConstraintEditor;
import de.FeatureModellingTool.FeatureModel.CompositeConstraintPortType;
import de.FeatureModellingTool.FeatureModel.CompositeConstraintType;
import de.FeatureModellingTool.FeatureModel.Constraint;
import de.FeatureModellingTool.FeatureModel.ConstraintModel;
import de.FeatureModellingTool.FeatureModel.ConstraintModelEditor;
import de.FeatureModellingTool.FeatureModel.Feature;
import de.FeatureModellingTool.FeatureModel.FeatureEditor;
import de.FeatureModellingTool.FeatureModel.FeatureModel;
import de.FeatureModellingTool.FeatureModel.FeatureModelEditor;
import de.FeatureModellingTool.FeatureModel.FeatureRelation;
import de.FeatureModellingTool.FeatureModel.GroupConstraint;
import de.FeatureModellingTool.FeatureModel.GroupConstraintEditor;
import de.FeatureModellingTool.FeatureModel.GroupConstraintType;
import de.FeatureModellingTool.FeatureModel.Variability;
public class ModelGenerator {
public ModelGenerator(FeatureModel featureModel , FeatureModelEditor featureModelEditor
, FeatureEditor featureEditor , ConstraintModel constraintModel , ConstraintModelEditor constraintModelEditor
, GroupConstraintEditor groupConstraintEditor , CompositeConstraintEditor compositeConstraintEditor) {
this.featureModel = featureModel;
this.featureModelEditor = featureModelEditor;
this.featureEditor = featureEditor;
this.constraintModel = constraintModel;
this.constraintModelEditor = constraintModelEditor;
this.groupConstraintEditor = groupConstraintEditor;
this.compositeConstraintEditor = compositeConstraintEditor;
}
protected FeatureModel featureModel = null;
protected FeatureModelEditor featureModelEditor = null;
protected FeatureEditor featureEditor = null;
protected ConstraintModel constraintModel = null;
protected ConstraintModelEditor constraintModelEditor = null;
protected GroupConstraintEditor groupConstraintEditor = null;
protected CompositeConstraintEditor compositeConstraintEditor = null;
public void generate(int treeCount , int treeWidth , int treeHeight
, int requireCount , int mutexCount
, int singleGroupCount , int allGroupCount , int featurePerGroup
, int requireCompositeCount , int mutexCompositeCount , int featurePerPredict) {
this.generateForest(treeCount , treeWidth , treeHeight);
this.reorder();
this.addRelation(requireCount , FeatureRelation.REQUIRE);
this.addRelation(mutexCount , FeatureRelation.EXCLUDE);
this.addGroupConstraint(singleGroupCount , featurePerGroup , GroupConstraintType.SingleGroup);
this.addGroupConstraint(allGroupCount , featurePerGroup , GroupConstraintType.AllGroup);
this.addCompositeConstraint(requireCompositeCount , featurePerPredict , CompositeConstraintType.L2R_Implication);
this.addCompositeConstraint(mutexCompositeCount , featurePerPredict , CompositeConstraintType.Mutex);
}
protected List<List<Feature>> featureForest = new ArrayList<List<Feature>>();
protected void generateForest(int treeCount , int treeWidth , int treeHeight) {
for (int i=0 ; i<treeCount ; i++) {
List<Feature> features = new ArrayList<Feature>();
this.featureForest.add(features);
addChild(null , Integer.toString(i) , treeWidth , treeHeight , features);
}
}
private void addChild(Feature root , String featureName , int treeWidth , int treeHeight , List<Feature> features) {
Feature feature = this.featureModelEditor.addFeature(featureName);
this.featureEditor.setVariability(feature , Variability.Optional);
if (root!=null) {
featureModelEditor.addRelation(FeatureRelation.DECOMPOSE , root, feature);
}
features.add(feature);
treeHeight --;
if (treeHeight>0) {
for (int i=0 ; i<treeWidth ; i++) {
addChild(feature , featureName + "." + Integer.toString(i) , treeWidth , treeHeight , features);
}
}
}
protected void reorder() {
// List<List<Feature>> tmp = new ArrayList<List<Feature>>(this.featureForest);
// this.featureForest.clear();
// while (tmp.size()>0) {
// int l = this.random() % tmp.size();
// this.featureForest.add(tmp.get(l));
// tmp.remove(l);
// }
// if (this.featureForest.size()%2!=0) {
// this.featureForest.add(this.featureForest.get(this.featureForest.size()-1));
// }
}
protected void addRelation(int relationCount , String relationName) {
for (int i=0 ; i<relationCount ; i++) {
List<Feature> features = this.getRandomFeatures(2);
this.featureModelEditor.addRelation(relationName , features.get(0) , features.get(1));
}
}
protected void addCFRelation(Feature feature , Constraint constraint , boolean isSource) {
if (this.random() % 100==0) {
this.constraintModelEditor.addCFRelation(feature , constraint , isSource , CFRModifier.Negation);
} else {
this.constraintModelEditor.addCFRelation(feature , constraint , isSource , CFRModifier.Affirmation);
}
}
protected void addGroupConstraint(int groupCount , int featurePerGroup , GroupConstraintType gct) {
for (int i=0 ; i<groupCount ; i++) {
GroupConstraint gc = this.constraintModelEditor.addGroupConstraint();
this.groupConstraintEditor.setType(gc , gct);
List<Feature> features = this.getRandomFeatures(featurePerGroup);
for (int j=0 ; j<features.size() ; j++) {
this.groupConstraintEditor.addFeature(gc , features.get(j));
this.addCFRelation(features.get(j) , gc , false);
}
}
}
protected void addCompositeConstraint(int compositeCount , int featurePerPredict , CompositeConstraintType cct) {
for (int i=0 ; i<compositeCount ; i++) {
CompositeConstraint cc = this.constraintModelEditor.addCompositeConstraint();
this.compositeConstraintEditor.setPLType(cc , cct);
this.compositeConstraintEditor.setSourceType(cc , CompositeConstraintPortType.Multi);
this.compositeConstraintEditor.setSinkType(cc , CompositeConstraintPortType.Multi);
List<Feature> features = this.getRandomFeatures(featurePerPredict*2);
for (int j=0 ; j<featurePerPredict ; j++) {
this.compositeConstraintEditor.addSourceFeature(cc , features.get(j));
this.addCFRelation(features.get(j) , cc , true);
}
for (int j=featurePerPredict ; j<features.size() ; j++) {
this.compositeConstraintEditor.addSinkFeature(cc , features.get(j));
this.addCFRelation(features.get(j) , cc , false);
}
}
}
private List<Feature> getRandomFeatures(List<Feature> features , int featureCount) {
return getRandomFeaturesExclude(features , featureCount , null);
}
private List<Feature> getRandomFeaturesExclude(List<Feature> features , int featureCount , Collection<Feature> exclude) {
List<Feature> result = new ArrayList<Feature>();
while (result.size()<featureCount) {
int i = this.random() % features.size();
if (exclude!=null && exclude.contains(features.get(i))) {
continue;
}
if (!result.contains(features.get(i))) {
result.add(features.get(i));
}
}
return result;
}
private Feature getRandomFeature(List<Feature> features) {
return getRandomFeatureExclude(features , null);
}
private Feature getRandomFeatureExclude(List<Feature> features , Feature exclude) {
if (features.size()==0) {
return null;
} if (features.size()==1) {
return features.get(0);
} else {
while (true) {
int l = (int)(Math.round(Math.random()) % features.size());
if (exclude!=null && features.get(l).equals(exclude)) {
continue;
}
return features.get(l);
}
}
}
private List<List<Feature>> apartFeatures = null;
private List<Feature> getRandomFeatures(int featureCount) {
if (this.apartFeatures==null) {
this.apartFeatures = new ArrayList<List<Feature>>();
this.apartFeatures.add(new ArrayList<Feature>());
this.apartFeatures.add(new ArrayList<Feature>());
int size = this.featureForest.size()/2;
for (int i=0 ; i<size ; i++) {
this.apartFeatures.get(0).addAll(this.featureForest.get(i*2));
this.apartFeatures.get(1).addAll(this.featureForest.get(i*2+1));
}
if (this.featureForest.size()%2>0) {
this.apartFeatures.get(0).addAll(this.featureForest.get(this.featureForest.size()-1));
}
}
return this.getRandomFeatures(this.apartFeatures.get(this.random()%this.apartFeatures.size()) , featureCount);
}
private int random() {
return (int)Math.round(Math.random() * Integer.MAX_VALUE);
}
}