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]int 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 = "green" 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) if ref, e := gb.refs[name]; e { for _, item := range ref { gb.addNode(item.Name) } } for key, references := range gb.refs { for _, item := range references { if name == item.Name { gb.addNode(key) } } } return nil } func prepareEdges(refs Refs, nodeMap NodeMap) []Edge { var edges []Edge edgeSet := make(map[Edge]bool) for key, references := range refs { if toID, e := nodeMap[key]; e { for _, item := range references { if fromID, e := nodeMap[item.Name]; e { edge := Edge{ From: fromID, To: toID, } 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 name, id := range nodeMap { nodes = append(nodes, apply(Node{ Id: id, Label: name, Color: nil, })) } return nodes } func (gb *graphBuilder) prepareNodeMap() { for key, references := range gb.refs { gb.addNode(key) for _, item := range references { gb.addNode(item.Name) } } } func (gb *graphBuilder) addNode(key string) int { if _, e := gb.nodeMap[key]; !e { gb.nodeMap[key] = gb.nodeCount gb.nodeCount += 1 } return gb.nodeMap[key] }