package domain import "sync" type Graph struct { adjacencyList map[string]map[string]bool mutex sync.RWMutex } func NewGraph() *Graph { return &Graph{ adjacencyList: make(map[string]map[string]bool), } } func (g *Graph) AddEdge(from, to string) { g.mutex.Lock() defer g.mutex.Unlock() if g.adjacencyList[from] == nil { g.adjacencyList[from] = make(map[string]bool) } g.adjacencyList[from][to] = true } func (g *Graph) RemoveEdge(from, to string) { g.mutex.Lock() defer g.mutex.Unlock() if g.adjacencyList[from] != nil { delete(g.adjacencyList[from], to) if len(g.adjacencyList[from]) == 0 { delete(g.adjacencyList, from) } } } func (g *Graph) GetOutlinks(path string) []string { g.mutex.RLock() defer g.mutex.RUnlock() var outlinks []string if targets, exists := g.adjacencyList[path]; exists { for target := range targets { outlinks = append(outlinks, target) } } return outlinks } func (g *Graph) GetBacklinks(path string) []string { g.mutex.RLock() defer g.mutex.RUnlock() var backlinks []string for source, targets := range g.adjacencyList { if targets[path] { backlinks = append(backlinks, source) } } return backlinks } func (g *Graph) HasEdge(from, to string) bool { g.mutex.RLock() defer g.mutex.RUnlock() if targets, exists := g.adjacencyList[from]; exists { return targets[to] } return false } func (g *Graph) RemoveNode(path string) { g.mutex.Lock() defer g.mutex.Unlock() delete(g.adjacencyList, path) for source, targets := range g.adjacencyList { delete(targets, path) if len(targets) == 0 { delete(g.adjacencyList, source) } } } func (g *Graph) GetAllNodes() []string { g.mutex.RLock() defer g.mutex.RUnlock() nodeSet := make(map[string]bool) for source := range g.adjacencyList { nodeSet[source] = true } for _, targets := range g.adjacencyList { for target := range targets { nodeSet[target] = true } } var nodes []string for node := range nodeSet { nodes = append(nodes, node) } return nodes } func (g *Graph) Clear() { g.mutex.Lock() defer g.mutex.Unlock() g.adjacencyList = make(map[string]map[string]bool) }