Class: Asciidoctor::Datamodel::PlantumlRenderer

Inherits:
Object
  • Object
show all
Defined in:
lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb

Constant Summary collapse

TEMPLATES_PATH =
File.expand_path('../views/datamodel', __dir__).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(yml, plantuml_path) ⇒ PlantumlRenderer

Returns a new instance of PlantumlRenderer.



12
13
14
15
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 12

def initialize(yml, plantuml_path)
  @yml = yml
  @plantuml_path = plantuml_path
end

Instance Attribute Details

#plantuml_pathObject (readonly)

Returns the value of attribute plantuml_path.



10
11
12
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 10

def plantuml_path
  @plantuml_path
end

#ymlObject (readonly)

Returns the value of attribute yml.



10
11
12
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 10

def yml
  @yml
end

Instance Method Details

#attribute_cardinality(attribute_cardinality) ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 280

def attribute_cardinality(attribute_cardinality)
  cardinality = ''
  if attribute_cardinality
    cardinality = attribute_cardinality_plantuml(
      attribute_cardinality,
      false
    )
    cardinality = " #{cardinality}"
  end
  cardinality
end

#attribute_cardinality_plantuml(cardinality, with_bracket = true) ⇒ Object



145
146
147
148
149
150
151
152
153
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 145

def attribute_cardinality_plantuml(cardinality, with_bracket = true)
  return '' if cardinality.nil? ||
               (cardinality['min'] == cardinality['max'] &&
                 cardinality['min'] == 1)
  card = "#{cardinality['min']}..#{cardinality['max']}"
  return card unless with_bracket

  "[#{card}]"
end

#attribute_to_plantuml(attr_name, attr_hash) ⇒ Object



139
140
141
142
143
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 139

def attribute_to_plantuml(attr_name, attr_hash)
  <<~TEMPLATE
    +#{attr_name}: #{attr_hash['type']}#{attribute_cardinality_plantuml(attr_hash['cardinality'])}
  TEMPLATE
end

#attributes_to_plantuml(attributes) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 131

def attributes_to_plantuml(attributes)
  return unless attributes

  attributes.map do |(attr_name, attr_hash)|
    attribute_to_plantuml(attr_name, attr_hash)
  end.join('').sub(/\n\Z/, '')
end

#bottom_to_plantuml(bottom) ⇒ Object



345
346
347
348
349
350
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 345

def bottom_to_plantuml(bottom)
  bottom ||= []
  return if bottom.empty?

  "#{bottom.join("\n")}\n"
end

#bottom_yml_to_plantumlObject



88
89
90
91
92
93
94
95
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 88

def bottom_yml_to_plantuml
  return if empty?(yml, 'bottom')

  <<~TEMPLATE
    '******* BOTTOM OVERRIDE CONFIG **************************************
    #{join_as_plantuml(bottom_to_plantuml(yml['bottom']))}
  TEMPLATE
end

#class_defs_yml_to_plantumlObject



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 42

def class_defs_yml_to_plantuml
  return if empty?(yml, 'classes') && empty?(yml, 'enums')

  <<~TEMPLATE
    '******* CLASS DEFINITIONS ********************************************
    #{join_as_plantuml(
      classes_to_classes_plantuml(yml['classes']),
      enums_to_enums_plantuml(yml['enums'])
    )}
  TEMPLATE
end

#class_groups_yml_to_plantumlObject



54
55
56
57
58
59
60
61
62
63
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 54

def class_groups_yml_to_plantuml
  return if empty?(yml, 'groups')

  <<~TEMPLATE
    '******* CLASS GROUPS *************************************************
    #{join_as_plantuml(
      groups_to_plantuml(yml['groups'])
    )}
  TEMPLATE
end

#class_relations_yml_to_plantumlObject



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 65

def class_relations_yml_to_plantuml
  return if empty?(yml, 'classes') && empty?(yml, 'relations')

  <<~TEMPLATE
    '******* CLASS RELATIONS **********************************************
    #{join_as_plantuml(
      classes_to_relations_plantuml(yml['classes']),
      relations_to_plantuml(nil, yml['relations'])
    )}
  TEMPLATE
end

#class_to_plantuml(class_name, class_hash) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 116

def class_to_plantuml(class_name, class_hash)
  return unless class_name

  class_hash ||= {}

  <<~TEMPLATE
    class #{class_name}#{model_stereotype_to_plantuml(class_hash['type'])} {
    #{join_as_plantuml(
      attributes_to_plantuml(class_hash['attributes']),
      constraints_to_plantuml(class_hash['constraints'])
    )}
    }
  TEMPLATE
end

#classes_to_classes_plantuml(classes) ⇒ Object



106
107
108
109
110
111
112
113
114
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 106

def classes_to_classes_plantuml(classes)
  classes ||= {}

  return if classes.empty?

  classes.map do |(class_name, class_hash)|
    class_to_plantuml(class_name, class_hash)
  end.join("\n")
end

#classes_to_relations_plantuml(classes) ⇒ Object



172
173
174
175
176
177
178
179
180
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 172

def classes_to_relations_plantuml(classes)
  output_ary = classes.map do |(class_name, class_hash)|
    class_hash ||= {}
    relations = class_hash['relations']
    relations_to_plantuml(class_name, relations)
  end

  join_as_plantuml(*output_ary)
end

#constraints_to_plantuml(constraints) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 155

def constraints_to_plantuml(constraints)
  constraints ||= []

  return if constraints.empty?

  constraints_output = constraints.map do |constraint|
    "  {#{constraint}}"
  end

  <<~TEMPLATE
      __ constraints __
    #{join_as_plantuml(
      *constraints_output
    )}
  TEMPLATE
end

#diagram_captionObject



29
30
31
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 29

def diagram_caption
  yml['caption']
end

#diagram_options_to_plantuml(diagram_options) ⇒ Object



338
339
340
341
342
343
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 338

def diagram_options_to_plantuml(diagram_options)
  diagram_options ||= []
  return if diagram_options.empty?

  "#{diagram_options.join("\n")}\n"
end

#diagram_options_yml_to_plantumlObject



77
78
79
80
81
82
83
84
85
86
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 77

def diagram_options_yml_to_plantuml
  return if empty?(yml, 'diagram_options')

  <<~TEMPLATE
    '******* DIAGRAM SPECIFIC CONFIG **************************************
    #{join_as_plantuml(
      diagram_options_to_plantuml(yml['diagram_options'])
    )}
  TEMPLATE
end

#empty?(yml, prop) ⇒ Boolean

Returns:

  • (Boolean)


403
404
405
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 403

def empty?(yml, prop)
  yml[prop].nil? || yml[prop].length.zero?
end

#enum_to_plantuml(enum_name, enum_hash) ⇒ Object



300
301
302
303
304
305
306
307
308
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 300

def enum_to_plantuml(enum_name, enum_hash)
  enum_hash ||= {}

  <<~TEMPLATE
    enum #{enum_name}#{model_stereotype_to_plantuml(enum_hash['type'])} {
    #{join_as_plantuml(enum_values_to_plantuml(enum_hash['values']))}
    }
  TEMPLATE
end

#enum_values_to_plantuml(enum_values) ⇒ Object



316
317
318
319
320
321
322
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 316

def enum_values_to_plantuml(enum_values)
  output_ary = enum_values.map do |(enum_value, _enum_value_hash)|
    "  #{enum_value}"
  end

  join_as_plantuml(*output_ary)
end

#enums_to_enums_plantuml(enums) ⇒ Object



292
293
294
295
296
297
298
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 292

def enums_to_enums_plantuml(enums)
  enums ||= {}

  enums.map do |(enum_name, enum_hash)|
    enum_to_plantuml(enum_name, enum_hash)
  end.join("\n\n")
end

#fidelity_to_plantuml(fidelity) ⇒ Object



394
395
396
397
398
399
400
401
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 394

def fidelity_to_plantuml(fidelity)
  return '' if fidelity.nil?

  output = ''
  output += hide_other_classes(fidelity) if fidelity['hideOtherClasses']
  output += "\nhide members\n" if fidelity['hideMembers']
  output
end

#fidelity_yml_to_plantumlObject



97
98
99
100
101
102
103
104
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 97

def fidelity_yml_to_plantuml
  return if empty?(yml, 'fidelity')

  <<~TEMPLATE
    '******* FIDELITY *****************************************************
    #{join_as_plantuml(fidelity_to_plantuml(yml['fidelity']))}
  TEMPLATE
end

#format_association_relation(relation, fidelity_classes, acc) ⇒ Object



369
370
371
372
373
374
375
376
377
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 369

def format_association_relation(relation, fidelity_classes, acc)
  return unless relation['relationship'] &&
                relation['relationship']['association']

  association = relation['relationship']['association']
  return unless association && !fidelity_classes.key?(association)

  acc.merge!(association => true)
end

#format_hidden_class(accum, fidelity_classes, class_hash) ⇒ Object



352
353
354
355
356
357
358
359
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 352

def format_hidden_class(accum, fidelity_classes, class_hash)
  return accum if class_hash['relations'].nil?

  class_hash['relations'].each_with_object(accum) do |relation, acc|
    format_source_target_relation(relation, fidelity_classes, acc)
    format_association_relation(relation, fidelity_classes, acc)
  end
end

#format_source_target_relation(relation, fidelity_classes, acc) ⇒ Object



361
362
363
364
365
366
367
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 361

def format_source_target_relation(relation, fidelity_classes, acc)
  %w[source target].each do |type|
    next unless relation[type] && !fidelity_classes.key?(relation[type])

    acc.merge!(relation[type] => true)
  end
end

#groups_to_plantuml(groups) ⇒ Object



324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 324

def groups_to_plantuml(groups)
  groups ||= []
  return if groups.empty?

  groups.reduce('') do |output, group|
    output += "\ntogether {\n"
    group.each do |class_name|
      output += "\nclass #{class_name}\n"
    end
    output += "\n}\n"
    output
  end
end

#hide_other_classes(fidelity) ⇒ Object



379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 379

def hide_other_classes(fidelity)
  return '' if fidelity.nil? || fidelity['classes'].nil?

  output = ''
  hidden_classes = fidelity['classes']
                   .reduce({}) do |acc, (_class_name, class_hash)|
    format_hidden_class(acc, fidelity['classes'], class_hash)
  end

  hidden_classes.keys.each do |hidden_class_name|
    output += "\nhide #{hidden_class_name}\n"
  end
  output
end

#imports_yml_to_plantumlObject



33
34
35
36
37
38
39
40
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 33

def imports_yml_to_plantuml
  return if empty?(yml, 'imports')

  <<~TEMPLATE
    '******* IMPORTS ******************************************************
    !include #{plantuml_path}/style.uml.inc
  TEMPLATE
end

#join_as_plantuml(*ary) ⇒ Object



17
18
19
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 17

def join_as_plantuml(*ary)
  ary.compact.join("\n").sub(/\s+\Z/, '')
end

#model_stereotype_to_plantuml(model_stereotype) ⇒ Object



310
311
312
313
314
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 310

def model_stereotype_to_plantuml(model_stereotype)
  return '' unless model_stereotype

  " <<#{model_stereotype}>>"
end

#relation_arrow(relationship, relation) ⇒ Object



195
196
197
198
199
200
201
202
203
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 195

def relation_arrow(relationship, relation)
  [
    relationship_type_to_plantuml('source',
                                  relationship['source']['type']),
    (relation['direction']).to_s,
    relationship_type_to_plantuml('target',
                                  relationship['target']['type'])
  ].compact.join('-')
end

#relation_association(source, target, association) ⇒ Object



235
236
237
238
239
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 235

def relation_association(source, target, association)
  return unless association

  "\n(#{source}, #{target}) . #{association}"
end

#relation_label(action) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 205

def relation_label(action)
  return '' unless action

  case action['direction']
  when 'source'
    " : < #{action['verb']}"
  when 'target'
    " : #{action['verb']} >"
  else
    ''
  end
end

#relation_output_lines(source, target, relation, relationship) ⇒ Object



248
249
250
251
252
253
254
255
256
257
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 248

def relation_output_lines(source, target, relation, relationship)
  output_lines = [
    source_arrow_end(source, relationship),
    relation_arrow(relationship, relation),
    target_arrow_end(target, relationship, relation['action']),
    relation_association(source, target, relationship['association'])
  ].join(' ')

  join_as_plantuml(*output_lines)
end

#relation_to_plantuml(source, target, relation) ⇒ Object



241
242
243
244
245
246
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 241

def relation_to_plantuml(source, target, relation)
  relationship = relation['relationship'] || {}
  relationship['source'] ||= {}
  relationship['target'] ||= {}
  relation_output_lines(source, target, relation, relationship)
end

#relations_to_plantuml(class_name, relations) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 182

def relations_to_plantuml(class_name, relations)
  return unless relations

  output_ary = relations.map do |relation|
    source = class_name || relation['source']
    relation_to_plantuml(source,
                         relation['target'],
                         relation)
  end

  join_as_plantuml(*output_ary)
end

#relationship_cardinality_to_plantuml(attribute) ⇒ Object



270
271
272
273
274
275
276
277
278
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 270

def relationship_cardinality_to_plantuml(attribute)
  attribute_name = (attribute || {}).keys.first

  return unless attribute_name

  attribute_hash = attribute[attribute_name] || {}
  card = attribute_cardinality(attribute_hash['cardinality'])
  "\"+#{attribute_name}#{card}\""
end

#relationship_type_to_plantuml(relation_end, relationship_type) ⇒ Object



259
260
261
262
263
264
265
266
267
268
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 259

def relationship_type_to_plantuml(relation_end, relationship_type)
  is_source = (relation_end == 'source')
  mappings = {
    'direct' => is_source ? '<' : '>',
    'inheritance' => is_source ? '<|' : '|>',
    'composition' => '*',
    'aggregation' => 'o'
  }
  mappings.fetch(relationship_type, '')
end

#renderObject



21
22
23
24
25
26
27
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 21

def render
  ERB.new(
    File.read(
      File.join(TEMPLATES_PATH, 'plantuml_representation.adoc.erb')
    )
  ).result(binding)
end

#source_arrow_end(source, relationship) ⇒ Object



218
219
220
221
222
223
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 218

def source_arrow_end(source, relationship)
  source_attribute = relationship_cardinality_to_plantuml(
    relationship['source']['attribute']
  )
  [source, source_attribute].join(' ')
end

#target_arrow_end(target, relationship, action) ⇒ Object



225
226
227
228
229
230
231
232
233
# File 'lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb', line 225

def target_arrow_end(target, relationship, action)
  target_attribute = relationship_cardinality_to_plantuml(
    relationship['target']['attribute']
  )
  [
    [target_attribute, target].join(' '),
    relation_label(action)
  ].join
end