package de.FeatureModellingTool.PLModelChecker.RelationAnalysis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import de.FeatureModellingTool.FeatureModel.CompositeConstraint;
import de.FeatureModellingTool.FeatureModel.ConstraintModel;
import de.FeatureModellingTool.FeatureModel.Feature;
import de.FeatureModellingTool.FeatureModel.FeatureModel;
import de.FeatureModellingTool.FeatureModel.FeatureRelation;
import de.FeatureModellingTool.FeatureModel.GroupConstraint;
public class ConstraintRelationDiagram {
public ConstraintRelationDiagram(FeatureModel featureModel
, ConstraintModel constraintModel
, Collection<Collection<Feature>> atomFeature) {
this.featureModel = featureModel;
this.constraintModel = constraintModel;
if (atomFeature==null) {
for (Iterator<Feature> itFeature=this.featureModel.getAllFeature().values().iterator() ; itFeature.hasNext() ; ) {
Feature feature = itFeature.next();
atomMap.put(feature , feature);
}
} else {
for (Iterator<Collection<Feature>> itAtom=atomFeature.iterator() ; itAtom.hasNext() ; ) {
List<Feature> atomList = new ArrayList<Feature>(itAtom.next());
for (int i=0 ; i<atomList.size() ; i++) {
atomMap.put(atomList.get(i) , atomList.get(0));
}
}
}
this.buildGraph();
}
protected FeatureModel featureModel = null;
protected ConstraintModel constraintModel = null;
protected HashMap<Feature,Feature> atomMap = new HashMap<Feature,Feature>();
private NGraph graph = new NGraph();
public void setGraph(NGraph graph) {
this.graph = graph;
}
public NGraph getGraph() {
return graph;
}
protected void buildGraph() {
HashMap<Feature,NNode> builtFeatures = new HashMap<Feature,NNode>();
for (Iterator<Feature> itFeature=this.featureModel.getAllFeature().values().iterator()
; itFeature.hasNext() ; ) {
Feature feature = itFeature.next();
if (!builtFeatures.containsKey(atomMap.get(feature))) {
NNode node = new NNode(atomMap.get(feature));
this.graph.nodes.put(node.feature , node);
builtFeatures.put(atomMap.get(feature) , node);
}
builtFeatures.put(feature , builtFeatures.get(feature));
}
if (this.featureModel.getAllFeatureRelation() != null) {
for (Iterator<FeatureRelation> itFeatureRelation = this.featureModel
.getAllFeatureRelation().values().iterator(); itFeatureRelation
.hasNext();) {
FeatureRelation fr = itFeatureRelation.next();
NNode startNode = builtFeatures.get(fr.getStartFeature());
NNode endNode = builtFeatures.get(fr.getEndFeature());
startNode.addEdge(endNode);
endNode.addEdge(startNode);
}
}
if (this.constraintModel.getAllGroupConstraint()!=null) {
for (Iterator<GroupConstraint> itGC=this.constraintModel.getAllGroupConstraint().values().iterator()
; itGC.hasNext() ; ) {
GroupConstraint gc = itGC.next();
List<Feature> featureList = new ArrayList<Feature>(gc.getFeatureSet());
for (int i=0 ; i<featureList.size() ; i++) {
for (int j=i+1 ; j<featureList.size() ; j++) {
NNode startNode = builtFeatures.get(featureList.get(i));
NNode endNode = builtFeatures.get(featureList.get(j));
startNode.addEdge(endNode);
endNode.addEdge(startNode);
}
}
}
}
if (this.constraintModel.getAllCompositeConstraint()!=null) {
for (Iterator<CompositeConstraint> itCC=this.constraintModel.getAllCompositeConstraint().values().iterator()
; itCC.hasNext() ; ) {
CompositeConstraint cc = itCC.next();
List<Feature> featureList = new ArrayList<Feature>(cc.getSourceFeatureSet());
featureList.addAll(cc.getSinkFeatureSet());
for (int i=0 ; i<featureList.size() ; i++) {
for (int j=i+1 ; j<featureList.size() ; j++) {
NNode startNode = builtFeatures.get(featureList.get(i));
NNode endNode = builtFeatures.get(featureList.get(j));
startNode.addEdge(endNode);
endNode.addEdge(startNode);
}
}
}
}
}
public static int getConnectedGraphMaxSize(Collection<NGraph> graphs) {
int result = 0;
for (Iterator<NGraph> itGraph=graphs.iterator() ; itGraph.hasNext() ; ) {
result = Math.max(result , itGraph.next().nodes.size());
}
return result;
}
public class NGraph {
public HashMap<Feature,NNode> nodes = new HashMap<Feature,NNode>();
public Set<NGraph> getConnectedGraph() {
HashMap<Feature,NGraph> map = new HashMap<Feature,NGraph>();
for (Iterator<NNode> itNode=this.nodes.values().iterator() ; itNode.hasNext() ; ) {
NNode node = itNode.next();
if (!node.isEnabled()) {
continue;
}
map.put(node.feature , new NGraph());
map.get(node.feature).nodes.put(node.feature , node);
}
for (Iterator<NNode> itNode=this.nodes.values().iterator() ; itNode.hasNext() ; ) {
NNode node = itNode.next();
if (!node.isEnabled()) {
continue;
}
NGraph graph = map.get(node.feature);
for (Iterator<NNode> itChildNode=node.nodes.iterator() ; itChildNode.hasNext() ; ) {
NNode childNode = itChildNode.next();
if (!childNode.isEnabled()) {
continue;
}
NGraph childGraph = map.get(childNode.feature);
if (graph!=childGraph) {
graph.nodes.putAll(childGraph.nodes);
for (Iterator<NNode> itChangeNode=childGraph.nodes.values().iterator() ; itChangeNode.hasNext() ; ) {
NNode changeNode = itChangeNode.next();
map.remove(changeNode.feature);
map.put(changeNode.feature , graph);
}
}
}
}
HashSet<NGraph> result = new HashSet<NGraph>(map.values());
return result;
}
public Bridge getBestBridge(int maxDecreaseFeature , double maxDecreaseRatio) {
Bridge result = null;
int orignalSize = this.nodes.size();
int maxSize = Integer.MAX_VALUE;
for (Iterator<NNode> itNode=this.nodes.values().iterator() ; itNode.hasNext() ; ) {
NNode node = itNode.next();
node.enabled = false;
Set<NGraph> connectedGraphs = this.getConnectedGraph();
if (result==null) {
result = new Bridge();
result.node = node;
result.connectedGraph = connectedGraphs;
maxSize = getConnectedGraphMaxSize(result.connectedGraph);
} else {
if (maxSize>getConnectedGraphMaxSize(connectedGraphs)) {
result.node = node;
result.connectedGraph = connectedGraphs;
maxSize = getConnectedGraphMaxSize(result.connectedGraph);
}
}
node.enabled = true;
if (maxSize<orignalSize-maxDecreaseFeature || maxSize<orignalSize*maxDecreaseRatio) {
break;
}
}
return result;
}
}
public class NNode {
public NNode(Feature feature) {
this.feature = feature;
this.setEnabled(true);
}
public Feature feature = null;
public Set<NNode> nodes = new HashSet<NNode>();
public void addEdge(NNode node) {
this.nodes.add(node);
}
private boolean enabled = true;
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEnabled() {
return enabled;
}
}
public class Bridge {
public NNode node;
public Set<NGraph> connectedGraph;
}
}