class Metanorma::Datamodel::PlantumlRenderer

Constants

TEMPLATES_PATH

Attributes

plantuml_path[R]
yml[R]

Public Class Methods

new(yml, plantuml_path) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 12
def initialize(yml, plantuml_path)
  @yml = yml
  @plantuml_path = plantuml_path
end

Public Instance Methods

attribute_cardinality(attribute_cardinality) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 281
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) click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 346
def bottom_to_plantuml(bottom)
  bottom ||= []
  return if bottom.empty?

  "#{bottom.join("\n")}\n"
end
bottom_yml_to_plantuml() click to toggle source
# File lib/metanorma/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_plantuml() click to toggle source
# File lib/metanorma/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_plantuml() click to toggle source
# File lib/metanorma/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_plantuml() click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 173
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 156
      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_caption() click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 29
def diagram_caption
  yml["caption"]
end
diagram_options_to_plantuml(diagram_options) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 339
def diagram_options_to_plantuml(diagram_options)
  diagram_options ||= []
  return if diagram_options.empty?

  "#{diagram_options.join("\n")}\n"
end
diagram_options_yml_to_plantuml() click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 404
def empty?(yml, prop)
  yml[prop].nil? || yml[prop].length.zero?
end
enum_to_plantuml(enum_name, enum_hash) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 301
      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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 317
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 293
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 395
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_plantuml() click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 370
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 353
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 362
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 325
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 380
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.each_key do |hidden_class_name|
    output += "\nhide #{hidden_class_name}\n"
  end
  output
end
imports_yml_to_plantuml() click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 311
def model_stereotype_to_plantuml(model_stereotype)
  return "" unless model_stereotype

  " <<#{model_stereotype}>>"
end
relation_arrow(relationship, relation) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 196
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 236
def relation_association(source, target, association)
  return unless association

  "\n(#{source}, #{target}) . #{association}"
end
relation_label(action) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 206
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 249
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 242
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 183
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 271
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 260
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
render() click to toggle source
# File lib/metanorma/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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 219
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) click to toggle source
# File lib/metanorma/standoc/datamodel/plantuml_renderer.rb, line 226
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