package splar.core.util; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Image; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.InputStream; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Vector; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import net.sf.javabdd.BDD; import org.jgrapht.DirectedGraph; import org.jgrapht.graph.DefaultEdge; import splar.core.constraints.BooleanVariableInterface; import splar.core.fm.FeatureGroup; import splar.core.fm.FeatureModel; import splar.core.fm.FeatureTreeNode; import splar.core.fm.clustering.FTCluster; import splar.core.heuristics.VariableOrderingHeuristic; public class Utils { public static String generateBDDFile(String path, String variables[], BDD bdd, String fileName, FeatureModel fm, Map<String,String> parameters) { PrintStream savedOut = System.out; try { // convert nodes labels from numbers to names in the BDD dot file ByteArrayOutputStream outByte = new ByteArrayOutputStream(); PrintStream out1 = new PrintStream(outByte); System.setOut(out1); bdd.printDot(); BufferedReader reader = new BufferedReader(new StringReader(outByte.toString())); // create output file FileWriter writer = new FileWriter(path+fileName+".dot"); // skip header and unuseful data String line = reader.readLine(); for( int i = 0 ; i < 3 ; i++ ) { writer.write(line); line = reader.readLine(); } writer.write("\tlabelloc=\"t\";"); writer.write("\tlabel=\"Feature Model: " + fm.getName() + " (" + parameters.get("heuristic_name") + ")" + "\\n" + " (BDD size: " + parameters.get("bdd_size") + ", BDD paths: " + parameters.get("bdd_paths") + ", Span: " + parameters.get("clause_span") + ")\";"); String newLine = ""; while( line != null ) { newLine = adjustDotFileLines(variables, line); writer.write(newLine); line = reader.readLine(); } writer.close(); out1.close(); System.setOut(savedOut); try { // generates BDD JPG file from dot file Process p = Runtime.getRuntime().exec("dot -Tjpg " + path+fileName+".dot -o "+path+fileName+".jpg"); p.waitFor(); return path+fileName+".jpg"; } catch(InterruptedException ie) { } } catch( Exception e ) { e.printStackTrace(); } return null; } private static String adjustDotFileLines(String variables[], String line){ String newLine = null; try { if ( line.indexOf("label=") != -1 ) { int index1 = line.indexOf("\""); int index2 = line.indexOf("]"); if( index1 != -1 && index2 != -1 ) { String label = line.substring(index1+1, index2-1); int varID = Integer.valueOf(label).intValue(); String strVarID = variables[varID]; if ( strVarID != null ) { newLine = line.substring(0,index1) + "\"" + strVarID + "\"];"; } } } } catch( Exception e ) { } return (newLine == null ? line : newLine); } public static JPanel generateImageVisualizationPanel(String path, int width, int height, int scaling) { JPanel panel = new JPanel(new BorderLayout()); try { Image image = ImageIO.read(new File(path)); // Read from an input stream InputStream is = new BufferedInputStream(new FileInputStream(path)); image = ImageIO.read(is); ImageIcon icon = new ImageIcon(path); // icon.setImage(icon.getImage().getScaledInstance(width, height, scaling)); icon.setImage(image); JLabel label = new JLabel(icon); panel.setBackground(Color.white); panel.add(label, BorderLayout.CENTER ); } catch( Exception e ) { e.printStackTrace(); } return panel; } public static String generateFTDependencyViewDotFile(String path, String fileName, FeatureModel fm, Map<String,FTCluster> view, String heuristicName, String variableOrder[]) { try { System.out.println("Generating file: " + path+fileName+".dot"); Map<String,Integer> mapVarOrder = null; if ( variableOrder != null ) { mapVarOrder = VariableOrderingHeuristic.variableOrderingAsHashMap(variableOrder);; } // create output file PrintWriter writer = new PrintWriter(new FileWriter(path+fileName+".dot")); // skip header and unuseful data writer.println("graph G {\n"); writer.println("\t compound=true;"); if ( variableOrder != null ) { writer.println("\tlabelloc=\"t\";"); int span = fm.FM2CNF().calculateClauseSpan(mapVarOrder); writer.println("\tlabel=\"Feature Model: " + fm.getName() + "\\n" + heuristicName + "\\n" + "Total Clause Span: " + span +"\";"); } else { writer.println("\tlabelloc=\"t\";"); writer.println("\tlabel=\"Feature Model: " + fm.getName() + "\";"); } List<String> clusterDep = new Vector<String>(); for( String clusterRoot: view.keySet() ) { // root writer.println("\tsubgraph cluster_" + clusterRoot + " {"); writer.println("\t\tlabel=\"" + clusterRoot +":["+(fm.getNodeLevel(clusterRoot)+1)+"]\";"); writer.println("\t\tnode [style=\"setlinewidth(1)\",filled];"); writer.println("\t\tcolor=black;"); FTCluster cluster = view.get(clusterRoot); // FeatureTreeNode ancestor = cluster.getAncestor(); // if ( ancestor != null ) { //// clusterDep.add("\tcluster_" + clusterRoot + " -- " + cluster.getAncestor().getID()); // } if ( variableOrder != null ) { String relativeVariableOrder[] = calculateRelativeVariableOrder(cluster, variableOrder); int i = 1; for( String childID : relativeVariableOrder ) { String varRelOrderStr = String.valueOf(i++) + ":"; writer.println("\t\t"+childID + " [label=\"" + varRelOrderStr + childID + "(" + (fm.countNodes(fm.getNodeByID(childID))-1) + ")\"]" ); } } else { for( FeatureTreeNode child : cluster.getChildren() ) { String childID = child.getID(); writer.println("\t\t"+childID + " [label=\"" + childID + "(" + (fm.countNodes(fm.getNodeByID(childID))-1) + ")\"]" ); } } // children relations for( int i = 0 ; i < cluster.getClusterNodesRelations().size() ; i++ ) { List<FeatureTreeNode> dependency = cluster.getClusterNodesRelations().get(i); List<BooleanVariableInterface> clauseDependency = cluster.getClauseNodesRelations().get(i); String depStr = "\t\t"; int varsDistance = 0; for( int j = 0 ; j < dependency.size() ; j++ ) { FeatureTreeNode node = dependency.get(j); BooleanVariableInterface clauseVar = clauseDependency.get(j); depStr += node.getID(); if ( j < (dependency.size()-1) ) { depStr += " -- "; } if ( variableOrder != null ) { varsDistance = Math.abs( varsDistance - mapVarOrder.get(clauseVar.getID()).intValue()); } } String absOrderStr = ""; if ( variableOrder != null ) { absOrderStr = ""+varsDistance; } writer.println(depStr + " [label=\""+ absOrderStr + "\",color=\"blue\"]"); } // for( List<FeatureTreeNode> dependency : cluster.getClusterNodesRelations() ) { // String depStr = "\t\t"; // for( Iterator<FeatureTreeNode> it = dependency.iterator() ; it.hasNext() ; ) { // FeatureTreeNode node = it.next(); // depStr += node.getID(); // if ( it.hasNext() ) { // depStr += " -- "; // } // } // String absOrderStr = ""; // if ( variableOrder != null ) { // // } // writer.println(depStr + " ["+ absOrderStr + "color=\"blue\"]"); // } writer.println("\t}"); } for( String line : clusterDep ) { writer.println(line); } writer.println("}"); writer.close(); try { // generates BDD JPG file from dot file System.out.println("running: dot -Tjpg " + path+fileName+".dot -o "+path+fileName+".jpg"); Process p = Runtime.getRuntime().exec("dot -Tjpg " + path+fileName+".dot -o "+path+fileName+".jpg"); p.waitFor(); return path+fileName+".jpg"; } catch(InterruptedException ie) { ie.printStackTrace(); } } catch( Exception e ) { e.printStackTrace(); } return null; } private static String[] calculateRelativeVariableOrder(FTCluster cluster, String variableOrder[]) { String relativeVariableOrder[] = new String[cluster.getChildren().size()]; try { List<FeatureTreeNode> children = new ArrayList<FeatureTreeNode>(); children.addAll(cluster.getChildren()); int index = 0; for( String varName : variableOrder ) { for( int i = 0 ; i < children.size() ; i++ ) { FeatureTreeNode childNode = children.get(i); if ( childNode instanceof FeatureGroup ) { for( int j = 0 ; j < childNode.getChildCount() ; j++ ) { FeatureTreeNode groupedNode = (FeatureTreeNode)childNode.getChildAt(j); if ( varName.compareTo(groupedNode.getID()) == 0) { relativeVariableOrder[index++] = childNode.getID(); children.remove(i); break; } } } else { if ( varName.compareTo(childNode.getID()) == 0) { relativeVariableOrder[index++] = varName; children.remove(i); break; } } } } } catch( Exception e ) { e.printStackTrace(); } return relativeVariableOrder; } }