Class: Archruby::Presenters::Graph

Inherits:
Object
  • Object
show all
Defined in:
lib/archruby/presenters/graph.rb

Instance Method Summary collapse

Instance Method Details

#render(architecture) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/archruby/presenters/graph.rb', line 8

def render architecture
  modules = architecture.modules

  g = GraphViz.new(:G)

  g.edge[:color] = "black"
  g.edge[:style] = "filled"
  g.edge[:label] = ""

  internal = g.subgraph("internal", "label" => "Internal", "color" => "black")

  external = g.subgraph("external", "label" => "External", "color" => "black", "rank" => "same")

  nodes = {}

  internal_nodes = []
  external_nodes = []
  modules.each do |module_definiton|
    next if module_definiton.name == 'unknown'
    next if module_definiton.name == Archruby::Ruby::STD_LIB_NAME || module_definiton.name == Archruby::Ruby::CORE_LIB_NAME
    if module_definiton.is_external?
      nodes[module_definiton.name] = external.add_nodes(module_definiton.name, "shape" => "parallelogram", "color" => "gray60", "style" => "filled")
      external_nodes << nodes[module_definiton.name]
    else
      if module_definiton.is_empty?
        nodes[module_definiton.name] = internal.add_nodes("#{module_definiton.name}\n [empty]", "color" => "gray74", "shape" => "rectangle")
      else
        nodes[module_definiton.name] = internal.add_nodes(module_definiton.name, "color" => "gray92", "style" => "filled", "shape" => "rectangle")
      end
      internal_nodes << nodes[module_definiton.name]
    end
  end

  edges = {}
  edges_objs = []

  modules.each do |module_definiton|
    module_name = module_definiton.name
    node_origin = nodes[module_name]
    edges[module_name] ||= {}
    edges[module_name][:edges] ||= []

    module_definiton.dependencies.each do |class_name|
      module_dest = architecture.module_name class_name
      next if module_dest == Archruby::Ruby::STD_LIB_NAME || module_dest == Archruby::Ruby::CORE_LIB_NAME
      next if module_dest == 'unknown'
      how_many_access = architecture.how_many_access_to module_name, module_dest
      if !edges[module_name][:edges].include?(module_dest) && module_dest != module_name
        edges[module_name][:edges] << module_dest
        node_dest = nodes[module_dest]
        edges_objs << internal.add_edges(node_origin, node_dest, :headlabel => how_many_access, :minlen => 2)
      end
    end
  end

  constraints_breaks = architecture.constraints_breaks
  constraints_breaks.each_with_index do |constraint_break, index|
    module_origin = constraint_break.module_origin
    module_target = constraint_break.module_target
    next if module_target == 'unknown'
    contraint_type = constraint_break.type
    node_origin = nodes[module_origin]
    node_dest = nodes[module_target]
    node_found = false
    edges_objs.each do |edge|
      if edge.node_one == module_origin && edge.node_two == module_target
        if contraint_type == Archruby::Architecture::ConstraintBreak::ABSENSE
          edge.set do |e|
            e.headlabel = "X (##{architecture.how_many_break(module_origin, module_target,  Archruby::Architecture::ConstraintBreak::ABSENSE)})"
            e.color = "red"
            e.style = "dotted"
            e.minlen = 2
          end
        else
          edge.set do |e|
            e.headlabel = "! (##{architecture.how_many_break(module_origin, module_target, Archruby::Architecture::ConstraintBreak::DIVERGENCE)})"
            e.color = "orange"
            e.style = "dashed"
            e.minlen = 2
          end
        end
        node_found = true
        break
      end
    end

    if !node_found
      if contraint_type == Archruby::Architecture::ConstraintBreak::ABSENSE
        break_count = architecture.how_many_break(module_origin, module_target, Archruby::Architecture::ConstraintBreak::ABSENSE)
        edges_objs << g.add_edges(node_origin, node_dest, :color => 'red', :headlabel => "X (##{break_count})", 'style' => 'dotted', :minlen => 2)
      else
        break_count = architecture.how_many_break(module_origin, module_target, Archruby::Architecture::ConstraintBreak::DIVERGENCE)
        edges_objs << g.add_edges(node_origin, node_dest, :color => 'orange', :headlabel => "! (##{break_count})", 'style' => 'dashed', :minlen => 2)
      end
    end
  end

  modules.each do |module_definiton|
    next if module_definiton.name == Archruby::Ruby::STD_LIB_NAME || module_definiton.name == Archruby::Ruby::CORE_LIB_NAME
    module_origin = module_definiton.is_empty? ? "#{module_definiton.name}\n [empty]" : module_definiton.name
    node_origin = nodes[module_origin]
    #  puts module_definiton.name.inspect
    #  puts module_definiton.classes.inspect
    #  puts module_definiton.dependencies.inspect
    #  puts module_definiton.classes_and_dependencies.inspect
    #  puts
    module_definiton.allowed_modules.each do |allowed_module_name|
      module_target = allowed_module_name
      node_dest = nodes[allowed_module_name]
      edge_found = false
      edges_objs.each do |edge|
        if edge.node_one == module_origin && edge.node_two == module_target
          edge_found = true
          break
        end
      end
      if !edge_found
        internal.add_edges(node_origin, node_dest, :color => 'gray74', :label => "[none]", :minlen => 2)
      end
    end
  end

  g.output( :png => "architecture.png" )
end