gaulthiergain-tools/srcs/common/graph_process.go

139 lines
3.2 KiB
Go
Raw Normal View History

2020-09-16 09:14:26 +02:00
// Copyright 2019 The UNICORE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
//
// Author: Gaulthier Gain <gaulthier.gain@uliege.be>
package common
import (
"math/rand"
"os"
"github.com/awalterschulze/gographviz"
)
const letters = "0123456789ABCDEF"
// RandStringBytes generates random string of size n.
//
// It returns a random string of a particular length.
func RandStringBytes(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
// ColorGenerator generates a color in RGB format.
//
// It returns a string which represents a random string formatted as RGB color.
func ColorGenerator() string {
return "#" + RandStringBytes(6)
}
// CreateGraphLabel creates a graph from a map.
//
// It returns a graph which represents all the direct and no-direct dependencies
// of a given application and an error if any, otherwise it returns nil.
func CreateGraphLabel(name string, data map[string][]string,
mapLabel map[string]string) (*gographviz.Escape, error) {
graph := gographviz.NewEscape()
if err := graph.SetName(name); err != nil {
return nil, err
}
// Directed graph
if err := graph.SetDir(true); err != nil {
return nil, err
}
// Create graph from map
for key, values := range data {
colorsMap := map[string]string{}
// Generate a random color
if _, in := colorsMap[key]; !in {
colorsMap[key] = ColorGenerator()
}
attributes := map[string]string{"color": colorsMap[key]}
// Create nodes
if err := graph.AddNode("\""+key+"\"", "\""+key+"\"",
attributes); err != nil {
return nil, err
}
if values != nil {
// Add edges
for _, v := range values {
if label, ok := mapLabel[v]; ok {
attributes["label"] = label
}
if err := graph.AddEdge("\""+key+"\"", "\""+v+"\"", true,
attributes); err != nil {
return nil, err
}
// Delete label attributes if necessary
if _, ok := mapLabel[v]; ok {
delete(attributes, "label")
}
}
}
}
return graph, nil
}
// SaveGraphToFile saves a given graph to a file.
//
// It returns an error if any, otherwise it returns nil.
func SaveGraphToFile(filename string, graph *gographviz.Escape) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err = file.WriteString(graph.String())
if err != nil {
return err
}
return nil
}
// GenerateGraph generates a given graph to a '.dot' and '.png' files.
//
// It returns an error if any, otherwise it returns nil.
func GenerateGraph(programName, fullPathName string, data map[string][]string,
mapLabel map[string]string) {
// Create graph
graph, err := CreateGraphLabel(programName, data, mapLabel)
// Save graph as '.dot' file
if err = SaveGraphToFile(fullPathName+".dot", graph); err != nil {
PrintWarning(err)
}
// Save graph as '.png' file
if _, err := ExecuteCommand("dot", []string{"-Tpng",
fullPathName + ".dot", "-o", fullPathName + ".png"}); err != nil {
PrintWarning(err)
PrintWarning("Open the following website to display the graph:" +
" https://dreampuf.github.io/GraphvizOnline/")
} else {
PrintOk("Graph saved into " + fullPathName + ".png")
}
}