package main import ( "encoding/json" "os" "path/filepath" "strings" ) type graphBuilder struct { refs Refs nodeMap NodeMap nodeCount int nodes []Node edges []Edge } type NodeMap map[string]Node func NewGraphBuilder(mp PagesRepository) (*graphBuilder, error) { refs := make(Refs) f, err := os.Open(filepath.Join(mp.(*FilePages).dirname, "backrefs.json")) if err != nil { return nil, err } defer f.Close() err = json.NewDecoder(f).Decode(&refs) if err != nil { return nil, err } return &graphBuilder{ refs: refs, nodeMap: make(NodeMap), nodes: nil, edges: nil, }, nil } func (gb *graphBuilder) prepareGraph() error { gb.nodes = prepareNodes(gb.nodeMap, func(node Node) Node { if node.Id == 0 { var green string green = "#f57900" node.Color = &green } return node }) gb.edges = prepareEdges(gb.refs, gb.nodeMap) return nil } func (gb *graphBuilder) RemoveNode(name string) { delete(gb.nodeMap, name) } func (gb *graphBuilder) RemoveNodeWithSuffix(suffix string) { for k, _ := range gb.nodeMap { if strings.HasSuffix(k, suffix) { delete(gb.nodeMap, k) } } } func (gb *graphBuilder) buildFromCenter(name string) error { _ = gb.addNode(name, "#ef2929") if ref, e := gb.refs[name]; e { for _, item := range ref { gb.addNode(item.Name, "#fce94f") } } for key, references := range gb.refs { for _, item := range references { if name == item.Name { gb.addNode(key, "#ad7fa8") } } } return nil } func prepareEdges(refs Refs, nodeMap NodeMap) []Edge { var edges []Edge edgeSet := make(map[Edge]bool) for key, references := range refs { if to, e := nodeMap[key]; e { for _, item := range references { if from, e := nodeMap[item.Name]; e { edge := Edge{ From: from.Id, To: to.Id, } if _, e := edgeSet[edge]; !e { edgeSet[edge] = true edges = append(edges, edge) } } } } } return edges } func prepareNodes(nodeMap NodeMap, apply func(node Node) Node) []Node { var nodes []Node for _, node := range nodeMap { nodes = append(nodes, apply(Node{ Id: node.Id, Label: node.Label, Color: node.Color, Opacity: node.Opacity, })) } return nodes } func (gb *graphBuilder) prepareNodeMap() { for key, references := range gb.refs { gb.addNode(key, "#5e8") for _, item := range references { gb.addNode(item.Name, "#403") } } } func (gb *graphBuilder) addNode(key string, color string) int { if _, e := gb.nodeMap[key]; !e { color := color gb.nodeMap[key] = Node{gb.nodeCount, key, &color, 1} gb.nodeCount += 1 } return gb.nodeMap[key].Id }