github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/dag/graph.go (about)

     1  package dag
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sort"
     7  )
     8  
     9  // Graph is used to represent a dependency graph.
    10  type Graph struct {
    11  	vertices  Set
    12  	edges     Set
    13  	downEdges map[interface{}]Set
    14  	upEdges   map[interface{}]Set
    15  }
    16  
    17  // Subgrapher allows a Vertex to be a Graph itself, by returning a Grapher.
    18  type Subgrapher interface {
    19  	Subgraph() Grapher
    20  }
    21  
    22  // A Grapher is any type that returns a Grapher, mainly used to identify
    23  // dag.Graph and dag.AcyclicGraph.  In the case of Graph and AcyclicGraph, they
    24  // return themselves.
    25  type Grapher interface {
    26  	DirectedGraph() Grapher
    27  }
    28  
    29  // Vertex of the graph.
    30  type Vertex interface{}
    31  
    32  // NamedVertex is an optional interface that can be implemented by Vertex
    33  // to give it a human-friendly name that is used for outputting the graph.
    34  type NamedVertex interface {
    35  	Vertex
    36  	Name() string
    37  }
    38  
    39  func (g *Graph) DirectedGraph() Grapher {
    40  	return g
    41  }
    42  
    43  // Vertices returns the list of all the vertices in the graph.
    44  func (g *Graph) Vertices() []Vertex {
    45  	result := make([]Vertex, 0, len(g.vertices))
    46  	for _, v := range g.vertices {
    47  		result = append(result, v.(Vertex))
    48  	}
    49  
    50  	return result
    51  }
    52  
    53  // Edges returns the list of all the edges in the graph.
    54  func (g *Graph) Edges() []Edge {
    55  	result := make([]Edge, 0, len(g.edges))
    56  	for _, v := range g.edges {
    57  		result = append(result, v.(Edge))
    58  	}
    59  
    60  	return result
    61  }
    62  
    63  // EdgesFrom returns the list of edges from the given source.
    64  func (g *Graph) EdgesFrom(v Vertex) []Edge {
    65  	var result []Edge
    66  	from := hashcode(v)
    67  	for _, e := range g.Edges() {
    68  		if hashcode(e.Source()) == from {
    69  			result = append(result, e)
    70  		}
    71  	}
    72  
    73  	return result
    74  }
    75  
    76  // EdgesTo returns the list of edges to the given target.
    77  func (g *Graph) EdgesTo(v Vertex) []Edge {
    78  	var result []Edge
    79  	search := hashcode(v)
    80  	for _, e := range g.Edges() {
    81  		if hashcode(e.Target()) == search {
    82  			result = append(result, e)
    83  		}
    84  	}
    85  
    86  	return result
    87  }
    88  
    89  // HasVertex checks if the given Vertex is present in the graph.
    90  func (g *Graph) HasVertex(v Vertex) bool {
    91  	return g.vertices.Include(v)
    92  }
    93  
    94  // HasEdge checks if the given Edge is present in the graph.
    95  func (g *Graph) HasEdge(e Edge) bool {
    96  	return g.edges.Include(e)
    97  }
    98  
    99  // Add adds a vertex to the graph. This is safe to call multiple time with
   100  // the same Vertex.
   101  func (g *Graph) Add(v Vertex) Vertex {
   102  	g.init()
   103  	g.vertices.Add(v)
   104  	return v
   105  }
   106  
   107  // Remove removes a vertex from the graph. This will also remove any
   108  // edges with this vertex as a source or target.
   109  func (g *Graph) Remove(v Vertex) Vertex {
   110  	// Delete the vertex itself
   111  	g.vertices.Delete(v)
   112  
   113  	// Delete the edges to non-existent things
   114  	for _, target := range g.downEdgesNoCopy(v) {
   115  		g.RemoveEdge(BasicEdge(v, target))
   116  	}
   117  	for _, source := range g.upEdgesNoCopy(v) {
   118  		g.RemoveEdge(BasicEdge(source, v))
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  // Replace replaces the original Vertex with replacement. If the original
   125  // does not exist within the graph, then false is returned. Otherwise, true
   126  // is returned.
   127  func (g *Graph) Replace(original, replacement Vertex) bool {
   128  	// If we don't have the original, we can't do anything
   129  	if !g.vertices.Include(original) {
   130  		return false
   131  	}
   132  
   133  	// If they're the same, then don't do anything
   134  	if original == replacement {
   135  		return true
   136  	}
   137  
   138  	// Add our new vertex, then copy all the edges
   139  	g.Add(replacement)
   140  	for _, target := range g.downEdgesNoCopy(original) {
   141  		g.Connect(BasicEdge(replacement, target))
   142  	}
   143  	for _, source := range g.upEdgesNoCopy(original) {
   144  		g.Connect(BasicEdge(source, replacement))
   145  	}
   146  
   147  	// Remove our old vertex, which will also remove all the edges
   148  	g.Remove(original)
   149  
   150  	return true
   151  }
   152  
   153  // RemoveEdge removes an edge from the graph.
   154  func (g *Graph) RemoveEdge(edge Edge) {
   155  	g.init()
   156  
   157  	// Delete the edge from the set
   158  	g.edges.Delete(edge)
   159  
   160  	// Delete the up/down edges
   161  	if s, ok := g.downEdges[hashcode(edge.Source())]; ok {
   162  		s.Delete(edge.Target())
   163  	}
   164  	if s, ok := g.upEdges[hashcode(edge.Target())]; ok {
   165  		s.Delete(edge.Source())
   166  	}
   167  }
   168  
   169  // UpEdges returns the vertices that are *sources* of edges that target the
   170  // destination Vertex v.
   171  func (g *Graph) UpEdges(v Vertex) Set {
   172  	return g.upEdgesNoCopy(v).Copy()
   173  }
   174  
   175  // DownEdges returns the vertices that are *targets* of edges that originate
   176  // from the source Vertex v.
   177  func (g *Graph) DownEdges(v Vertex) Set {
   178  	return g.downEdgesNoCopy(v).Copy()
   179  }
   180  
   181  // downEdgesNoCopy returns the vertices targeted by edges from the source Vertex
   182  // v as a Set. This Set is the same as used internally by the Graph to prevent a
   183  // copy, and must not be modified by the caller.
   184  func (g *Graph) downEdgesNoCopy(v Vertex) Set {
   185  	g.init()
   186  	return g.downEdges[hashcode(v)]
   187  }
   188  
   189  // upEdgesNoCopy returns the vertices that are sources of edges targeting the
   190  // destination Vertex v as a Set. This Set is the same as used internally by the
   191  // Graph to prevent a copy, and must not be modified by the caller.
   192  func (g *Graph) upEdgesNoCopy(v Vertex) Set {
   193  	g.init()
   194  	return g.upEdges[hashcode(v)]
   195  }
   196  
   197  // Connect adds an edge with the given source and target. This is safe to
   198  // call multiple times with the same value. Note that the same value is
   199  // verified through pointer equality of the vertices, not through the
   200  // value of the edge itself.
   201  func (g *Graph) Connect(edge Edge) {
   202  	g.init()
   203  
   204  	source := edge.Source()
   205  	target := edge.Target()
   206  	sourceCode := hashcode(source)
   207  	targetCode := hashcode(target)
   208  
   209  	// Do we have this already? If so, don't add it again.
   210  	if s, ok := g.downEdges[sourceCode]; ok && s.Include(target) {
   211  		return
   212  	}
   213  
   214  	// Add the edge to the set
   215  	g.edges.Add(edge)
   216  
   217  	// Add the down edge
   218  	s, ok := g.downEdges[sourceCode]
   219  	if !ok {
   220  		s = make(Set)
   221  		g.downEdges[sourceCode] = s
   222  	}
   223  	s.Add(target)
   224  
   225  	// Add the up edge
   226  	s, ok = g.upEdges[targetCode]
   227  	if !ok {
   228  		s = make(Set)
   229  		g.upEdges[targetCode] = s
   230  	}
   231  	s.Add(source)
   232  }
   233  
   234  // Subsume imports all of the nodes and edges from the given graph into the
   235  // reciever, leaving the given graph unchanged.
   236  //
   237  // If any of the nodes in the given graph are already present in the reciever
   238  // then the existing node will be retained and any new edges from the given
   239  // graph will be connected with it.
   240  //
   241  // If the given graph has edges in common with the reciever then they will be
   242  // ignored, because each pair of nodes can only be connected once.
   243  func (g *Graph) Subsume(other *Graph) {
   244  	// We're using Set.Filter just as a "visit each element" here, so we're
   245  	// not doing anything with the result (which will always be empty).
   246  	other.vertices.Filter(func(i interface{}) bool {
   247  		g.Add(i)
   248  		return false
   249  	})
   250  	other.edges.Filter(func(i interface{}) bool {
   251  		g.Connect(i.(Edge))
   252  		return false
   253  	})
   254  }
   255  
   256  // String outputs some human-friendly output for the graph structure.
   257  func (g *Graph) StringWithNodeTypes() string {
   258  	var buf bytes.Buffer
   259  
   260  	// Build the list of node names and a mapping so that we can more
   261  	// easily alphabetize the output to remain deterministic.
   262  	vertices := g.Vertices()
   263  	names := make([]string, 0, len(vertices))
   264  	mapping := make(map[string]Vertex, len(vertices))
   265  	for _, v := range vertices {
   266  		name := VertexName(v)
   267  		names = append(names, name)
   268  		mapping[name] = v
   269  	}
   270  	sort.Strings(names)
   271  
   272  	// Write each node in order...
   273  	for _, name := range names {
   274  		v := mapping[name]
   275  		targets := g.downEdges[hashcode(v)]
   276  
   277  		buf.WriteString(fmt.Sprintf("%s - %T\n", name, v))
   278  
   279  		// Alphabetize dependencies
   280  		deps := make([]string, 0, targets.Len())
   281  		targetNodes := make(map[string]Vertex)
   282  		for _, target := range targets {
   283  			dep := VertexName(target)
   284  			deps = append(deps, dep)
   285  			targetNodes[dep] = target
   286  		}
   287  		sort.Strings(deps)
   288  
   289  		// Write dependencies
   290  		for _, d := range deps {
   291  			buf.WriteString(fmt.Sprintf("  %s - %T\n", d, targetNodes[d]))
   292  		}
   293  	}
   294  
   295  	return buf.String()
   296  }
   297  
   298  // String outputs some human-friendly output for the graph structure.
   299  func (g *Graph) String() string {
   300  	var buf bytes.Buffer
   301  
   302  	// Build the list of node names and a mapping so that we can more
   303  	// easily alphabetize the output to remain deterministic.
   304  	vertices := g.Vertices()
   305  	names := make([]string, 0, len(vertices))
   306  	mapping := make(map[string]Vertex, len(vertices))
   307  	for _, v := range vertices {
   308  		name := VertexName(v)
   309  		names = append(names, name)
   310  		mapping[name] = v
   311  	}
   312  	sort.Strings(names)
   313  
   314  	// Write each node in order...
   315  	for _, name := range names {
   316  		v := mapping[name]
   317  		targets := g.downEdges[hashcode(v)]
   318  
   319  		buf.WriteString(fmt.Sprintf("%s\n", name))
   320  
   321  		// Alphabetize dependencies
   322  		deps := make([]string, 0, targets.Len())
   323  		for _, target := range targets {
   324  			deps = append(deps, VertexName(target))
   325  		}
   326  		sort.Strings(deps)
   327  
   328  		// Write dependencies
   329  		for _, d := range deps {
   330  			buf.WriteString(fmt.Sprintf("  %s\n", d))
   331  		}
   332  	}
   333  
   334  	return buf.String()
   335  }
   336  
   337  func (g *Graph) init() {
   338  	if g.vertices == nil {
   339  		g.vertices = make(Set)
   340  	}
   341  	if g.edges == nil {
   342  		g.edges = make(Set)
   343  	}
   344  	if g.downEdges == nil {
   345  		g.downEdges = make(map[interface{}]Set)
   346  	}
   347  	if g.upEdges == nil {
   348  		g.upEdges = make(map[interface{}]Set)
   349  	}
   350  }
   351  
   352  // Dot returns a dot-formatted representation of the Graph.
   353  func (g *Graph) Dot(opts *DotOpts) []byte {
   354  	return newMarshalGraph("", g).Dot(opts)
   355  }
   356  
   357  // VertexName returns the name of a vertex.
   358  func VertexName(raw Vertex) string {
   359  	switch v := raw.(type) {
   360  	case NamedVertex:
   361  		return v.Name()
   362  	case fmt.Stringer:
   363  		return v.String()
   364  	default:
   365  		return fmt.Sprintf("%v", v)
   366  	}
   367  }