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
# 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 == 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
      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
    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 = "bold"
            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 = "bold"
            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' => 'bold', :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 => 'red', :headlabel => "! (##{break_count})", 'style' => 'bold', :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