lutaml-uml 0.2.7 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ubuntu.yml +1 -1
- data/LUTAML.adoc +8 -3
- data/README.adoc +9 -10
- data/bin/plantuml2lutaml +1 -0
- data/bin/yaml2lutaml +2 -2
- data/exe/lutaml-wsd2uml +59 -0
- data/exe/lutaml-yaml2uml +144 -0
- data/lib/lutaml/uml.rb +4 -2
- data/lib/lutaml/uml/class.rb +0 -5
- data/lib/lutaml/uml/document.rb +13 -4
- data/lib/lutaml/uml/enum.rb +0 -4
- data/lib/lutaml/uml/package.rb +29 -8
- data/lib/lutaml/uml/parsers/dsl.rb +13 -8
- data/lib/lutaml/uml/top_element.rb +11 -0
- data/lib/lutaml/uml/top_element_attribute.rb +10 -0
- data/lib/lutaml/uml/version.rb +1 -1
- data/lutaml-uml.gemspec +1 -1
- data/spec/fixtures/dsl/diagram_class_fields.lutaml +6 -0
- data/spec/fixtures/dsl/diagram_data_types.lutaml +22 -2
- data/spec/fixtures/dsl/diagram_definitions.lutaml +2 -0
- data/spec/lutaml/uml/parsers/dsl_spec.rb +19 -4
- metadata +7 -7
- data/exe/lutaml-uml +0 -21
- data/lib/lutaml/uml/interface/base.rb +0 -28
- data/lib/lutaml/uml/interface/command_line.rb +0 -265
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3436e32ef66aba3d38cf8418de2ecef7bd475a1379e62e787aaddb0701397b55
         | 
| 4 | 
            +
              data.tar.gz: da160c6b5ffaa013cb0d4bc4df8a23175acdff14da402c15b883c96a424cbd83
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f76a00663fa9a4a8167930d4114ef4995ce7b488034336dd1134953ca9ed09ab4fd2da6e32a425082b6cf212b97bf47493e0b3f45c4b181fa93966f581ad7265
         | 
| 7 | 
            +
              data.tar.gz: 85f1fd71d5df7d0e673a5c4994f7d524dbaa915afca26bdacd483e384889003114e3f91ac1d7c0a28bc9a649b675036458c4fcc685b9e8534b6a49c346bb269d
         | 
    
        data/LUTAML.adoc
    CHANGED
    
    | @@ -7,13 +7,18 @@ | |
| 7 7 | 
             
            [source,java]
         | 
| 8 8 | 
             
            ----
         | 
| 9 9 | 
             
            diagram MyView {
         | 
| 10 | 
            -
               | 
| 11 | 
            -
               | 
| 12 | 
            -
              file "my_view.png"
         | 
| 10 | 
            +
              title "My diagram"
         | 
| 11 | 
            +
              caption "My custom caption"
         | 
| 13 12 | 
             
              fontname "Helvetica"
         | 
| 14 13 | 
             
            }
         | 
| 15 14 | 
             
            ----
         | 
| 16 15 |  | 
| 16 | 
            +
            where:
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            * `fontname` - optional, configuration option to use supplied font name
         | 
| 19 | 
            +
            * `title` - optional, set custom title for diagram
         | 
| 20 | 
            +
            * `caption` - optional, set custom caption for diagram
         | 
| 21 | 
            +
             | 
| 17 22 | 
             
            == DataTypes
         | 
| 18 23 |  | 
| 19 24 | 
             
            Lutaml supports 3 types of data_types: `data_type`, `primitive` and `enum`. Example of data types declaration:
         | 
    
        data/README.adoc
    CHANGED
    
    | @@ -8,20 +8,19 @@ Lutaml is a language for specifying UML class diagrams and a tool for converting | |
| 8 8 |  | 
| 9 9 | 
             
            ### RubyGems: `gem install lutaml-uml`
         | 
| 10 10 |  | 
| 11 | 
            -
            ##  | 
| 11 | 
            +
            ## Language
         | 
| 12 12 |  | 
| 13 | 
            -
            [ | 
| 14 | 
            -
            --
         | 
| 15 | 
            -
            # Convert example.lutaml to example.png
         | 
| 16 | 
            -
            $ lutaml-uml --type png --output . example.lutaml
         | 
| 13 | 
            +
            See link:LUTAML.adoc[LUTAML.adoc]
         | 
| 17 14 |  | 
| 18 | 
            -
             | 
| 19 | 
            -
            $ lutaml-uml --help
         | 
| 20 | 
            -
            --
         | 
| 15 | 
            +
            ## Usage
         | 
| 21 16 |  | 
| 22 | 
            -
             | 
| 17 | 
            +
            Converter executables are available:
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * PlantUML WSD to LutaML UML: `lutaml-wsd2uml`
         | 
| 20 | 
            +
            * LutaML YAML to LutaML UML: `lutaml-yaml2uml`
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            EXAMPLE: `lutaml-wsd2uml mn/metanorma-model-standoc/models/StandardDoc_Blocks_New.wsd`
         | 
| 23 23 |  | 
| 24 | 
            -
            See link:LUTAML.adoc[LUTAML.adoc]
         | 
| 25 24 |  | 
| 26 25 | 
             
            ## Development
         | 
| 27 26 |  | 
    
        data/bin/plantuml2lutaml
    CHANGED
    
    | @@ -27,6 +27,7 @@ ASSOCIATION_MAPPINGS = { | |
| 27 27 | 
             
            in_comment_block = false
         | 
| 28 28 |  | 
| 29 29 | 
             
            def transform_line(line)
         | 
| 30 | 
            +
              line = line.gsub(/^\s*'/, '** ').gsub(/\|[\sa-zA-Z]+$/, '')
         | 
| 30 31 | 
             
              return sync_puts(line, 2) if ASSOCIATION_MAPPINGS.keys.none? { |key| line =~ key }
         | 
| 31 32 |  | 
| 32 33 | 
             
              owner_type, member_type = ASSOCIATION_MAPPINGS.detect { |(key, _value)| line =~ key }.last.split(",")
         | 
    
        data/bin/yaml2lutaml
    CHANGED
    
    
    
        data/exe/lutaml-wsd2uml
    ADDED
    
    | @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # Script to convert plantuml files into LutaML syntax
         | 
| 6 | 
            +
            # Usage: bin/plantuml2lutaml /path/to/plantuml.wsd
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            file_path = ARGV[0]
         | 
| 9 | 
            +
            FILE_NAME = File.basename(file_path, ".wsd")
         | 
| 10 | 
            +
            wsd_file = File.new(ARGV[0])
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            def sync_puts(line, level = 0)
         | 
| 13 | 
            +
              $stdout.puts("#{''.rjust(level)}#{line}")
         | 
| 14 | 
            +
              $stdout.flush
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            SKIPPED_LINES_REGEXP = /^(@startuml|'\*{7}|note|@enduml|\!|'\/)/
         | 
| 18 | 
            +
            COMMENT_START = /\/'/
         | 
| 19 | 
            +
            COMMENT_END = /'\//
         | 
| 20 | 
            +
            ASSOCIATION_MAPPINGS = {
         | 
| 21 | 
            +
              /-\|>/ => ",inheritance",
         | 
| 22 | 
            +
              /<\|-/ => "inheritance,",
         | 
| 23 | 
            +
              /->/ => ",direct",
         | 
| 24 | 
            +
              /<-/ => "direct,",
         | 
| 25 | 
            +
            }.freeze
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            in_comment_block = false
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            def transform_line(line)
         | 
| 30 | 
            +
              line = line.gsub(/^\s*'/, '** ').gsub(/\|[\sa-zA-Z]+$/, '')
         | 
| 31 | 
            +
              return sync_puts(line, 2) if ASSOCIATION_MAPPINGS.keys.none? { |key| line =~ key }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              owner_type, member_type = ASSOCIATION_MAPPINGS.detect { |(key, _value)| line =~ key }.last.split(",")
         | 
| 34 | 
            +
              blocks = line.split(" ")
         | 
| 35 | 
            +
              owner = blocks.first
         | 
| 36 | 
            +
              member = blocks.last
         | 
| 37 | 
            +
              sync_puts("association {", 2)
         | 
| 38 | 
            +
              sync_puts("owner #{owner}", 4)
         | 
| 39 | 
            +
              sync_puts("member #{member}", 4)
         | 
| 40 | 
            +
              sync_puts("owner_type #{owner_type}", 4) if !owner_type.to_s.empty?
         | 
| 41 | 
            +
              sync_puts("member_type #{member_type}", 4) if !member_type.to_s.empty?
         | 
| 42 | 
            +
              sync_puts("}", 2)
         | 
| 43 | 
            +
            end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            sync_puts("diagram #{FILE_NAME} {")
         | 
| 46 | 
            +
            wsd_file.readlines.each do |line|
         | 
| 47 | 
            +
              if line.match?(COMMENT_START)
         | 
| 48 | 
            +
                in_comment_block = true
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              if line.match?(COMMENT_END)
         | 
| 52 | 
            +
                in_comment_block = false
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              next if in_comment_block || line =~ SKIPPED_LINES_REGEXP
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              transform_line(line)
         | 
| 58 | 
            +
            end
         | 
| 59 | 
            +
            sync_puts("}")
         | 
    
        data/exe/lutaml-yaml2uml
    ADDED
    
    | @@ -0,0 +1,144 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # Script to convert datamodel yaml files into LutaML syntax
         | 
| 6 | 
            +
            # Usage: bin/yaml2lutaml /path/to/datamodel/view/file.yml
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            require "yaml"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            view_yaml = YAML.safe_load(File.read(ARGV[0]))
         | 
| 11 | 
            +
            models_path = File.expand_path("../../models", ARGV[0])
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            def sync_puts(line, level = 0)
         | 
| 14 | 
            +
              $stdout.puts("#{''.rjust(level)}#{line}")
         | 
| 15 | 
            +
              $stdout.flush
         | 
| 16 | 
            +
            end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            encountered_relations = Hash.new { |h, key| h[key] = [] }
         | 
| 19 | 
            +
            # relations:
         | 
| 20 | 
            +
            # - target: AttributeProfile
         | 
| 21 | 
            +
            #   relationship:
         | 
| 22 | 
            +
            #     source:
         | 
| 23 | 
            +
            #       type: aggregation
         | 
| 24 | 
            +
            #       attribute:
         | 
| 25 | 
            +
            #         addressClassProfile:
         | 
| 26 | 
            +
            #     target:
         | 
| 27 | 
            +
            #       type: direct
         | 
| 28 | 
            +
            #       attribute:
         | 
| 29 | 
            +
            #         attributeProfile:
         | 
| 30 | 
            +
            #           cardinality:
         | 
| 31 | 
            +
            #             min: 0
         | 
| 32 | 
            +
            #             max: '*'
         | 
| 33 | 
            +
            def process_association(owner, values, encountered_relations)
         | 
| 34 | 
            +
              target_name = values["target"]
         | 
| 35 | 
            +
              return if encountered_relations[owner].include?(target_name)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              encountered_relations[owner].push(target_name)
         | 
| 38 | 
            +
              sync_puts("association {", 2)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              relationship_block = values["relationship"] || {}
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              if relationship_block["source"] && relationship_block["source"]["type"]
         | 
| 43 | 
            +
                source = relationship_block["source"]
         | 
| 44 | 
            +
                sync_puts("owner_type #{source['type']}", 4)
         | 
| 45 | 
            +
                if source["attribute"]
         | 
| 46 | 
            +
                  source_attribute_name = source["attribute"].keys.first
         | 
| 47 | 
            +
                  owner += "##{source_attribute_name}"
         | 
| 48 | 
            +
                  if source["attribute"][source_attribute_name] && source["attribute"][source_attribute_name]["cardinality"]
         | 
| 49 | 
            +
                    cardinality = source["attribute"][source_attribute_name]["cardinality"]
         | 
| 50 | 
            +
                    owner += " [#{cardinality['min']}..#{cardinality['max']}]"
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
              sync_puts("owner #{owner}", 4)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              member = target_name
         | 
| 57 | 
            +
              if relationship_block["target"]
         | 
| 58 | 
            +
                target = relationship_block["target"]
         | 
| 59 | 
            +
                type = target["type"] || "direct"
         | 
| 60 | 
            +
                sync_puts("member_type #{type}", 4)
         | 
| 61 | 
            +
                if target["attribute"]
         | 
| 62 | 
            +
                  target_attribute_name = target["attribute"].keys.first
         | 
| 63 | 
            +
                  member += "##{target_attribute_name}"
         | 
| 64 | 
            +
                  if target["attribute"][target_attribute_name] && target["attribute"][target_attribute_name]["cardinality"]
         | 
| 65 | 
            +
                    cardinality = target["attribute"][target_attribute_name]["cardinality"]
         | 
| 66 | 
            +
                    member += " [#{cardinality['min']}..#{cardinality['max']}]"
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              else
         | 
| 70 | 
            +
                sync_puts("member_type direct", 4)
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
              sync_puts("member #{member}", 4)
         | 
| 73 | 
            +
             | 
| 74 | 
            +
              sync_puts("}", 2)
         | 
| 75 | 
            +
            end
         | 
| 76 | 
            +
            sync_puts("diagram #{File.basename(ARGV[0], 'yml')[0..-2]} {")
         | 
| 77 | 
            +
            sync_puts("title '#{view_yaml['title']}'", 2)
         | 
| 78 | 
            +
            sync_puts("caption '#{view_yaml['caption']}'", 2)
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            # Class associations notations
         | 
| 81 | 
            +
            view_yaml["relations"]&.each do |values|
         | 
| 82 | 
            +
              process_association(values["source"], values, encountered_relations)
         | 
| 83 | 
            +
            end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            view_yaml["imports"].keys.each do |entry|
         | 
| 86 | 
            +
              import = YAML.safe_load(File.read(File.join(models_path, "#{entry}.yml")))
         | 
| 87 | 
            +
              import_name = import["name"] || File.basename(entry)
         | 
| 88 | 
            +
              # Class notation
         | 
| 89 | 
            +
              sync_puts("#{import['modelType']} #{import_name} {", 2)
         | 
| 90 | 
            +
              if import["definition"]
         | 
| 91 | 
            +
                definition = <<~TEXT
         | 
| 92 | 
            +
                  definition {
         | 
| 93 | 
            +
                    #{import['definition']}
         | 
| 94 | 
            +
                  }
         | 
| 95 | 
            +
                TEXT
         | 
| 96 | 
            +
                sync_puts(definition, 4)
         | 
| 97 | 
            +
              end
         | 
| 98 | 
            +
              import["values"]&.each_pair do |key, values|
         | 
| 99 | 
            +
                result_string = key
         | 
| 100 | 
            +
                if values["definition"]
         | 
| 101 | 
            +
                  result_string += <<~TEXT
         | 
| 102 | 
            +
                    {
         | 
| 103 | 
            +
                      definition {
         | 
| 104 | 
            +
                      #{values['definition']}
         | 
| 105 | 
            +
                      }
         | 
| 106 | 
            +
                    }
         | 
| 107 | 
            +
                  TEXT
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
                sync_puts(result_string, 4)
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
              import["attributes"]&.each_pair do |key, values|
         | 
| 112 | 
            +
                definition = values["definition"]
         | 
| 113 | 
            +
                cardinality = if values["cardinality"]
         | 
| 114 | 
            +
                                cardinality_val = values["cardinality"]
         | 
| 115 | 
            +
                                "[#{cardinality_val['min']}..#{cardinality_val['max']}]"
         | 
| 116 | 
            +
                              else
         | 
| 117 | 
            +
                                ""
         | 
| 118 | 
            +
                              end
         | 
| 119 | 
            +
                result_string = "+#{key}"
         | 
| 120 | 
            +
                if values["type"]
         | 
| 121 | 
            +
                  result_string += ": #{values['type']}"
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
                if cardinality
         | 
| 124 | 
            +
                  result_string += " #{cardinality}"
         | 
| 125 | 
            +
                end
         | 
| 126 | 
            +
                if definition
         | 
| 127 | 
            +
                  result_string += <<~TEXT
         | 
| 128 | 
            +
                    {
         | 
| 129 | 
            +
                      definition
         | 
| 130 | 
            +
                      #{definition}
         | 
| 131 | 
            +
                      end definition
         | 
| 132 | 
            +
                    }
         | 
| 133 | 
            +
                  TEXT
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
                sync_puts(result_string, 4)
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
              sync_puts("}", 2)
         | 
| 138 | 
            +
             | 
| 139 | 
            +
              # Associations notations
         | 
| 140 | 
            +
              import["relations"]&.each do |values|
         | 
| 141 | 
            +
                process_association(import_name, values, encountered_relations)
         | 
| 142 | 
            +
              end
         | 
| 143 | 
            +
            end
         | 
| 144 | 
            +
            sync_puts("}")
         | 
    
        data/lib/lutaml/uml.rb
    CHANGED
    
    | @@ -1,11 +1,13 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require "lutaml/uml/version"
         | 
| 4 | 
            -
            require "lutaml/uml/ | 
| 4 | 
            +
            require "lutaml/uml/parsers/dsl"
         | 
| 5 | 
            +
            require "lutaml/uml/parsers/yaml"
         | 
| 6 | 
            +
            require "lutaml/uml/parsers/attribute"
         | 
| 7 | 
            +
            require "lutaml/uml/formatter"
         | 
| 5 8 |  | 
| 6 9 | 
             
            module Lutaml
         | 
| 7 10 | 
             
              module Uml
         | 
| 8 11 | 
             
                class Error < StandardError; end
         | 
| 9 | 
            -
                # Your code goes here...
         | 
| 10 12 | 
             
              end
         | 
| 11 13 | 
             
            end
         | 
    
        data/lib/lutaml/uml/class.rb
    CHANGED
    
    | @@ -16,7 +16,6 @@ module Lutaml | |
| 16 16 |  | 
| 17 17 | 
             
                  attr_reader :associations,
         | 
| 18 18 | 
             
                              :attributes,
         | 
| 19 | 
            -
                              :definition,
         | 
| 20 19 | 
             
                              :members,
         | 
| 21 20 | 
             
                              :modifier
         | 
| 22 21 |  | 
| @@ -32,10 +31,6 @@ module Lutaml | |
| 32 31 | 
             
                    @modifier = value.to_s # TODO: Validate?
         | 
| 33 32 | 
             
                  end
         | 
| 34 33 |  | 
| 35 | 
            -
                  def definition=(value)
         | 
| 36 | 
            -
                    @definition = value.to_s
         | 
| 37 | 
            -
                  end
         | 
| 38 | 
            -
             | 
| 39 34 | 
             
                  def attributes=(value)
         | 
| 40 35 | 
             
                    @attributes = value.to_a.map do |attr|
         | 
| 41 36 | 
             
                      TopElementAttribute.new(attr)
         | 
    
        data/lib/lutaml/uml/document.rb
    CHANGED
    
    | @@ -1,8 +1,9 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require "lutaml/uml/class"
         | 
| 4 | 
            -
            require "lutaml/uml/enum"
         | 
| 5 4 | 
             
            require "lutaml/uml/data_type"
         | 
| 5 | 
            +
            require "lutaml/uml/enum"
         | 
| 6 | 
            +
            require "lutaml/uml/package"
         | 
| 6 7 | 
             
            require "lutaml/uml/primitive_type"
         | 
| 7 8 |  | 
| 8 9 | 
             
            module Lutaml
         | 
| @@ -18,23 +19,27 @@ module Lutaml | |
| 18 19 | 
             
                                :fidelity,
         | 
| 19 20 | 
             
                                :fontname,
         | 
| 20 21 | 
             
                                :comments
         | 
| 22 | 
            +
                  attr_reader :packages
         | 
| 21 23 |  | 
| 22 24 | 
             
                  # rubocop:disable Rails/ActiveRecordAliases
         | 
| 23 25 | 
             
                  def initialize(attributes = {})
         | 
| 24 26 | 
             
                    update_attributes(attributes)
         | 
| 25 27 | 
             
                  end
         | 
| 26 28 | 
             
                  # rubocop:enable Rails/ActiveRecordAliases
         | 
| 27 | 
            -
             | 
| 28 29 | 
             
                  def classes=(value)
         | 
| 29 30 | 
             
                    @classes = value.to_a.map { |attributes| Class.new(attributes) }
         | 
| 30 31 | 
             
                  end
         | 
| 31 32 |  | 
| 33 | 
            +
                  def data_types=(value)
         | 
| 34 | 
            +
                    @data_types = value.to_a.map { |attributes| DataType.new(attributes) }
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 32 37 | 
             
                  def enums=(value)
         | 
| 33 38 | 
             
                    @enums = value.to_a.map { |attributes| Enum.new(attributes) }
         | 
| 34 39 | 
             
                  end
         | 
| 35 40 |  | 
| 36 | 
            -
                  def  | 
| 37 | 
            -
                    @ | 
| 41 | 
            +
                  def packages=(value)
         | 
| 42 | 
            +
                    @packages = value.to_a.map { |attributes| Package.new(attributes) }
         | 
| 38 43 | 
             
                  end
         | 
| 39 44 |  | 
| 40 45 | 
             
                  def primitives=(value)
         | 
| @@ -59,6 +64,10 @@ module Lutaml | |
| 59 64 | 
             
                    @data_types || []
         | 
| 60 65 | 
             
                  end
         | 
| 61 66 |  | 
| 67 | 
            +
                  def packages
         | 
| 68 | 
            +
                    @packages || []
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 62 71 | 
             
                  def primitives
         | 
| 63 72 | 
             
                    @primitives || []
         | 
| 64 73 | 
             
                  end
         | 
    
        data/lib/lutaml/uml/enum.rb
    CHANGED
    
    
    
        data/lib/lutaml/uml/package.rb
    CHANGED
    
    | @@ -3,16 +3,37 @@ | |
| 3 3 | 
             
            module Lutaml
         | 
| 4 4 | 
             
              module Uml
         | 
| 5 5 | 
             
                class Package < TopElement
         | 
| 6 | 
            +
                  include HasAttributes
         | 
| 7 | 
            +
             | 
| 6 8 | 
             
                  attr_accessor :imports, :contents
         | 
| 9 | 
            +
                  attr_reader :classes, :enums
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def initialize(attributes)
         | 
| 12 | 
            +
                    update_attributes(attributes)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def classes=(value)
         | 
| 16 | 
            +
                    @classes = value.to_a.map { |attributes| Class.new(attributes) }
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def enums=(value)
         | 
| 20 | 
            +
                    @enums = value.to_a.map { |attributes| Enum.new(attributes) }
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def packages=(value)
         | 
| 24 | 
            +
                    @packages = value.to_a.map { |attributes| Package.new(attributes) }
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def classes
         | 
| 28 | 
            +
                    @classes || []
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def enums
         | 
| 32 | 
            +
                    @enums || []
         | 
| 33 | 
            +
                  end
         | 
| 7 34 |  | 
| 8 | 
            -
                  def  | 
| 9 | 
            -
                    @ | 
| 10 | 
            -
                    @contents = []
         | 
| 11 | 
            -
                    @name = nil
         | 
| 12 | 
            -
                    @xmi_id = nil
         | 
| 13 | 
            -
                    @xmi_uuid = nil
         | 
| 14 | 
            -
                    @namespace = nil
         | 
| 15 | 
            -
                    @href = nil
         | 
| 35 | 
            +
                  def packages
         | 
| 36 | 
            +
                    @packages || []
         | 
| 16 37 | 
             
                  end
         | 
| 17 38 | 
             
                end
         | 
| 18 39 | 
             
              end
         | 
| @@ -63,7 +63,7 @@ module Lutaml | |
| 63 63 | 
             
                    rule(:spaces) { match("\s").repeat(1) }
         | 
| 64 64 | 
             
                    rule(:spaces?) { spaces.maybe }
         | 
| 65 65 | 
             
                    rule(:whitespace) do
         | 
| 66 | 
            -
                      (match("\s") | match("\r?\n") | match("\r") | str(";")).repeat(1)
         | 
| 66 | 
            +
                      (match("\s") | match("	") | match("\r?\n") | match("\r") | str(";")).repeat(1)
         | 
| 67 67 | 
             
                    end
         | 
| 68 68 | 
             
                    rule(:whitespace?) { whitespace.maybe }
         | 
| 69 69 | 
             
                    rule(:name) { match["a-zA-Z0-9 _-"].repeat(1) }
         | 
| @@ -82,9 +82,9 @@ module Lutaml | |
| 82 82 | 
             
                          str(")")).maybe
         | 
| 83 83 | 
             
                    end
         | 
| 84 84 | 
             
                    rule(:cardinality_body_definition) do
         | 
| 85 | 
            -
                      match['0-9\*'].as( | 
| 85 | 
            +
                      match['0-9\*'].as('min') >>
         | 
| 86 86 | 
             
                        str("..").maybe >>
         | 
| 87 | 
            -
                        match['0-9\*'].as( | 
| 87 | 
            +
                        match['0-9\*'].as('max').maybe
         | 
| 88 88 | 
             
                    end
         | 
| 89 89 | 
             
                    rule(:cardinality) do
         | 
| 90 90 | 
             
                      str("[") >>
         | 
| @@ -117,7 +117,7 @@ module Lutaml | |
| 117 117 | 
             
                        attribute_keyword? >>
         | 
| 118 118 | 
             
                        spaces? >>
         | 
| 119 119 | 
             
                        match['"\''].maybe >>
         | 
| 120 | 
            -
                        match['a-zA-Z0-9_\- '].repeat(1).as(:type) >>
         | 
| 120 | 
            +
                        match['a-zA-Z0-9_\- \/\+'].repeat(1).as(:type) >>
         | 
| 121 121 | 
             
                        match['"\''].maybe >>
         | 
| 122 122 | 
             
                        spaces?
         | 
| 123 123 | 
             
                      )
         | 
| @@ -126,7 +126,7 @@ module Lutaml | |
| 126 126 | 
             
                      attribute_type.maybe
         | 
| 127 127 | 
             
                    end
         | 
| 128 128 |  | 
| 129 | 
            -
                    rule(:attribute_name) {  | 
| 129 | 
            +
                    rule(:attribute_name) { match['a-zA-Z0-9_\- \/\+'].repeat(1).as(:name) }
         | 
| 130 130 | 
             
                    rule(:attribute_definition) do
         | 
| 131 131 | 
             
                      (visibility?.as(:visibility) >>
         | 
| 132 132 | 
             
                        match['"\''].maybe >>
         | 
| @@ -293,9 +293,9 @@ module Lutaml | |
| 293 293 | 
             
                        whitespace? >>
         | 
| 294 294 | 
             
                        str("{") >>
         | 
| 295 295 | 
             
                        whitespace? >>
         | 
| 296 | 
            -
                        ( | 
| 296 | 
            +
                        (match("[\n\s]}").absent? >> any).repeat.as(:definition) >>
         | 
| 297 297 | 
             
                        whitespace? >>
         | 
| 298 | 
            -
                        str( | 
| 298 | 
            +
                        str('}')
         | 
| 299 299 | 
             
                    end
         | 
| 300 300 |  | 
| 301 301 | 
             
                    # -- Enum
         | 
| @@ -322,13 +322,17 @@ module Lutaml | |
| 322 322 | 
             
                        match['"\''].maybe >>
         | 
| 323 323 | 
             
                        class_name.as(:name) >>
         | 
| 324 324 | 
             
                        match['"\''].maybe >>
         | 
| 325 | 
            +
                        attribute_keyword? >>
         | 
| 325 326 | 
             
                        enum_body?
         | 
| 326 327 | 
             
                    end
         | 
| 327 328 |  | 
| 328 329 | 
             
                    # -- data_type
         | 
| 329 330 | 
             
                    rule(:data_type_keyword) { kw_data_type >> spaces }
         | 
| 330 331 | 
             
                    rule(:data_type_inner_definitions) do
         | 
| 331 | 
            -
                       | 
| 332 | 
            +
                      definition_body |
         | 
| 333 | 
            +
                        attribute_definition |
         | 
| 334 | 
            +
                        comment_definition |
         | 
| 335 | 
            +
                        comment_multiline_definition
         | 
| 332 336 | 
             
                    end
         | 
| 333 337 | 
             
                    rule(:data_type_inner_definition) do
         | 
| 334 338 | 
             
                      data_type_inner_definitions >> whitespace?
         | 
| @@ -346,6 +350,7 @@ module Lutaml | |
| 346 350 | 
             
                        match['"\''].maybe >>
         | 
| 347 351 | 
             
                        class_name.as(:name) >>
         | 
| 348 352 | 
             
                        match['"\''].maybe >>
         | 
| 353 | 
            +
                        attribute_keyword? >>
         | 
| 349 354 | 
             
                        data_type_body?
         | 
| 350 355 | 
             
                    end
         | 
| 351 356 |  | 
| @@ -6,6 +6,7 @@ module Lutaml | |
| 6 6 | 
             
                  include HasAttributes
         | 
| 7 7 |  | 
| 8 8 | 
             
                  attr_accessor :name,
         | 
| 9 | 
            +
                                :definition,
         | 
| 9 10 | 
             
                                :xmi_id,
         | 
| 10 11 | 
             
                                :xmi_uuid,
         | 
| 11 12 | 
             
                                :namespace,
         | 
| @@ -42,6 +43,16 @@ module Lutaml | |
| 42 43 |  | 
| 43 44 | 
             
                    the_name
         | 
| 44 45 | 
             
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def definition=(value)
         | 
| 48 | 
            +
                    @definition = value
         | 
| 49 | 
            +
                                    .to_s
         | 
| 50 | 
            +
                                    .gsub(/\\}/, '}')
         | 
| 51 | 
            +
                                    .gsub(/\\{/, '{')
         | 
| 52 | 
            +
                                    .split("\n")
         | 
| 53 | 
            +
                                    .map(&:strip)
         | 
| 54 | 
            +
                                    .join("\n")
         | 
| 55 | 
            +
                  end
         | 
| 45 56 | 
             
                end
         | 
| 46 57 | 
             
              end
         | 
| 47 58 | 
             
            end
         | 
| @@ -21,6 +21,16 @@ module Lutaml | |
| 21 21 | 
             
                    update_attributes(attributes)
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 | 
             
                  # rubocop:enable Rails/ActiveRecordAliases
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def definition=(value)
         | 
| 26 | 
            +
                    @definition = value
         | 
| 27 | 
            +
                                    .to_s
         | 
| 28 | 
            +
                                    .gsub(/\\}/, '}')
         | 
| 29 | 
            +
                                    .gsub(/\\{/, '{')
         | 
| 30 | 
            +
                                    .split("\n")
         | 
| 31 | 
            +
                                    .map(&:strip)
         | 
| 32 | 
            +
                                    .join("\n")
         | 
| 33 | 
            +
                  end
         | 
| 24 34 | 
             
                end
         | 
| 25 35 | 
             
              end
         | 
| 26 36 | 
             
            end
         | 
    
        data/lib/lutaml/uml/version.rb
    CHANGED
    
    
    
        data/lutaml-uml.gemspec
    CHANGED
    
    | @@ -22,7 +22,7 @@ Gem::Specification.new do |spec| | |
| 22 22 |  | 
| 23 23 | 
             
              spec.bindir        = "exe"
         | 
| 24 24 | 
             
              spec.require_paths = ["lib"]
         | 
| 25 | 
            -
              spec.executables   = %w[lutaml- | 
| 25 | 
            +
              spec.executables   = %w[lutaml-wsd2uml lutaml-yaml2uml]
         | 
| 26 26 |  | 
| 27 27 | 
             
              spec.add_runtime_dependency "hashie", "~> 4.1.0"
         | 
| 28 28 | 
             
              spec.add_runtime_dependency "parslet", "~> 1.7.1"
         | 
| @@ -15,5 +15,11 @@ diagram MyView { | |
| 15 15 | 
             
                ~friendlyAttributeProfile: <<Type>> "CharacterString" [1..*]
         | 
| 16 16 | 
             
                ~friendlyAttributeProfile1: <<Type>> "CharacterString"
         | 
| 17 17 | 
             
                #protectedAttributeProfile: CharacterString
         | 
| 18 | 
            +
                type/text: String
         | 
| 19 | 
            +
                slashType: slash/type
         | 
| 20 | 
            +
                application/docbook+xml
         | 
| 21 | 
            +
                application/tei+xml
         | 
| 22 | 
            +
                text/x-asciidoc
         | 
| 23 | 
            +
                application/x-isodoc+xml
         | 
| 18 24 | 
             
              }
         | 
| 19 25 | 
             
            }
         | 
| @@ -3,15 +3,35 @@ diagram MyView { | |
| 3 3 |  | 
| 4 4 | 
             
              enum MyEnum {}
         | 
| 5 5 |  | 
| 6 | 
            -
              enum AddressClassProfile {
         | 
| 6 | 
            +
              enum AddressClassProfile <<my_keyword>> {
         | 
| 7 7 | 
             
                +addressClassProfile: CharacterString
         | 
| 8 8 | 
             
              }
         | 
| 9 9 |  | 
| 10 10 | 
             
              data_type "Banking Information" {
         | 
| 11 | 
            -
                 | 
| 11 | 
            +
                definition {
         | 
| 12 | 
            +
                  Common code types used in banking.
         | 
| 13 | 
            +
                }
         | 
| 14 | 
            +
                "art code" {
         | 
| 15 | 
            +
                  definition {
         | 
| 16 | 
            +
                    The bank ART code.
         | 
| 17 | 
            +
                  }
         | 
| 18 | 
            +
                }
         | 
| 12 19 | 
             
                "CCT Number"
         | 
| 13 20 | 
             
              }
         | 
| 14 21 |  | 
| 22 | 
            +
              data_type DateTimeType {
         | 
| 23 | 
            +
                definition {
         | 
| 24 | 
            +
                  Type of date time value.
         | 
| 25 | 
            +
                }
         | 
| 26 | 
            +
                year {
         | 
| 27 | 
            +
                  definition {
         | 
| 28 | 
            +
                    The value only provides year.
         | 
| 29 | 
            +
                  }
         | 
| 30 | 
            +
                }
         | 
| 31 | 
            +
                monthYear
         | 
| 32 | 
            +
                dayMonthYear
         | 
| 33 | 
            +
              }
         | 
| 34 | 
            +
             | 
| 15 35 | 
             
              primitive Integer
         | 
| 16 36 |  | 
| 17 37 | 
             
              enum Profile {
         | 
| @@ -6,6 +6,7 @@ diagram MyView { | |
| 6 6 | 
             
                  this is multiline with `ascidoc`
         | 
| 7 7 | 
             
                  comments
         | 
| 8 8 | 
             
                  and list
         | 
| 9 | 
            +
                  \{foo\} \{name\}
         | 
| 9 10 | 
             
                }
         | 
| 10 11 | 
             
                +addressClassProfile: CharacterString [0..1]
         | 
| 11 12 | 
             
              }
         | 
| @@ -16,6 +17,7 @@ diagram MyView { | |
| 16 17 | 
             
                  {
         | 
| 17 18 | 
             
                    this is attribute definition
         | 
| 18 19 | 
             
                    with multiply lines
         | 
| 20 | 
            +
                    \{foo\} \{name\}
         | 
| 19 21 | 
             
                    end definition
         | 
| 20 22 | 
             
                  }
         | 
| 21 23 | 
             
                }
         | 
| @@ -68,7 +68,22 @@ RSpec.describe Lutaml::Uml::Parsers::Dsl do | |
| 68 68 | 
             
                    expect(by_name(classes, "AddressClassProfile")
         | 
| 69 69 | 
             
                            .attributes.length).to eq(1)
         | 
| 70 70 | 
             
                    expect(by_name(classes, "AttributeProfile")
         | 
| 71 | 
            -
                            .attributes.length).to eq( | 
| 71 | 
            +
                            .attributes.length).to eq(13)
         | 
| 72 | 
            +
                    expect(by_name(classes, "AttributeProfile")
         | 
| 73 | 
            +
                            .attributes.map(&:name))
         | 
| 74 | 
            +
                          .to(eq(["imlicistAttributeProfile",
         | 
| 75 | 
            +
                            "attributeProfile",
         | 
| 76 | 
            +
                            "attributeProfile1",
         | 
| 77 | 
            +
                            "privateAttributeProfile",
         | 
| 78 | 
            +
                            "friendlyAttributeProfile",
         | 
| 79 | 
            +
                            "friendlyAttributeProfile1",
         | 
| 80 | 
            +
                            "protectedAttributeProfile",
         | 
| 81 | 
            +
                            "type/text",
         | 
| 82 | 
            +
                            "slashType",
         | 
| 83 | 
            +
                            "application/docbook+xml",
         | 
| 84 | 
            +
                            "application/tei+xml",
         | 
| 85 | 
            +
                            "text/x-asciidoc",
         | 
| 86 | 
            +
                            "application/x-isodoc+xml"]))
         | 
| 72 87 | 
             
                  end
         | 
| 73 88 |  | 
| 74 89 | 
             
                  it "creates the correct attributes with the correct visibility" do
         | 
| @@ -121,7 +136,7 @@ RSpec.describe Lutaml::Uml::Parsers::Dsl do | |
| 121 136 | 
             
                      expect(association.member_end).to(eq("AttributeProfile"))
         | 
| 122 137 | 
             
                      expect(association.member_end_attribute_name)
         | 
| 123 138 | 
             
                        .to(eq("attributeProfile"))
         | 
| 124 | 
            -
                      expect(association.member_end_cardinality).to(eq(min | 
| 139 | 
            +
                      expect(association.member_end_cardinality).to(eq("min" => "0", "max" => "*"))
         | 
| 125 140 | 
             
                    end
         | 
| 126 141 | 
             
                  end
         | 
| 127 142 |  | 
| @@ -254,10 +269,10 @@ RSpec.describe Lutaml::Uml::Parsers::Dsl do | |
| 254 269 | 
             
                    File.new(fixtures_path("dsl/diagram_definitions.lutaml"))
         | 
| 255 270 | 
             
                  end
         | 
| 256 271 | 
             
                  let(:class_definition) do
         | 
| 257 | 
            -
                    "this is multiline with `ascidoc`\ | 
| 272 | 
            +
                    "this is multiline with `ascidoc`\ncomments\nand list\n{foo} {name}"
         | 
| 258 273 | 
             
                  end
         | 
| 259 274 | 
             
                  let(:attribute_definition) do
         | 
| 260 | 
            -
                    "this is attribute definition\ | 
| 275 | 
            +
                    "this is attribute definition\nwith multiply lines\n{foo} {name}\nend definition"
         | 
| 261 276 | 
             
                  end
         | 
| 262 277 |  | 
| 263 278 | 
             
                  it "create comments for document and classes" do
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: lutaml-uml
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ribose Inc.
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2021-03-28 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: hashie
         | 
| @@ -168,7 +168,8 @@ description: UML model module for LutaML. | |
| 168 168 | 
             
            email:
         | 
| 169 169 | 
             
            - open.source@ribose.com'
         | 
| 170 170 | 
             
            executables:
         | 
| 171 | 
            -
            - lutaml- | 
| 171 | 
            +
            - lutaml-wsd2uml
         | 
| 172 | 
            +
            - lutaml-yaml2uml
         | 
| 172 173 | 
             
            extensions: []
         | 
| 173 174 | 
             
            extra_rdoc_files: []
         | 
| 174 175 | 
             
            files:
         | 
| @@ -188,7 +189,8 @@ files: | |
| 188 189 | 
             
            - bin/plantuml2lutaml
         | 
| 189 190 | 
             
            - bin/setup
         | 
| 190 191 | 
             
            - bin/yaml2lutaml
         | 
| 191 | 
            -
            - exe/lutaml- | 
| 192 | 
            +
            - exe/lutaml-wsd2uml
         | 
| 193 | 
            +
            - exe/lutaml-yaml2uml
         | 
| 192 194 | 
             
            - lib/lutaml/layout/engine.rb
         | 
| 193 195 | 
             
            - lib/lutaml/layout/graph_viz_engine.rb
         | 
| 194 196 | 
             
            - lib/lutaml/uml.rb
         | 
| @@ -214,8 +216,6 @@ files: | |
| 214 216 | 
             
            - lib/lutaml/uml/has_attributes.rb
         | 
| 215 217 | 
             
            - lib/lutaml/uml/has_members.rb
         | 
| 216 218 | 
             
            - lib/lutaml/uml/instance.rb
         | 
| 217 | 
            -
            - lib/lutaml/uml/interface/base.rb
         | 
| 218 | 
            -
            - lib/lutaml/uml/interface/command_line.rb
         | 
| 219 219 | 
             
            - lib/lutaml/uml/model.rb
         | 
| 220 220 | 
             
            - lib/lutaml/uml/node/base.rb
         | 
| 221 221 | 
             
            - lib/lutaml/uml/node/class_node.rb
         | 
| @@ -319,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 319 319 | 
             
                - !ruby/object:Gem::Version
         | 
| 320 320 | 
             
                  version: '0'
         | 
| 321 321 | 
             
            requirements: []
         | 
| 322 | 
            -
            rubygems_version: 3.0. | 
| 322 | 
            +
            rubygems_version: 3.0.3
         | 
| 323 323 | 
             
            signing_key:
         | 
| 324 324 | 
             
            specification_version: 4
         | 
| 325 325 | 
             
            summary: UML model module for LutaML.
         | 
    
        data/exe/lutaml-uml
    DELETED
    
    | @@ -1,21 +0,0 @@ | |
| 1 | 
            -
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
            # encoding: UTF-8
         | 
| 3 | 
            -
            # frozen_string_literal: true
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            # resolve bin path, ignoring symlinks
         | 
| 6 | 
            -
            require "pathname"
         | 
| 7 | 
            -
            bin_file = Pathname.new(__FILE__).realpath
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            # add self to libpath
         | 
| 10 | 
            -
            $:.unshift File.expand_path("../../lib", bin_file)
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            # Fixes https://github.com/rubygems/rubygems/issues/1420
         | 
| 13 | 
            -
            require "rubygems/specification"
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            class Gem::Specification
         | 
| 16 | 
            -
              def this; self; end
         | 
| 17 | 
            -
            end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            require "lutaml/uml/interface/command_line"
         | 
| 20 | 
            -
             | 
| 21 | 
            -
            Lutaml::Uml::Interface::CommandLine.run
         | 
| @@ -1,28 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require "optparse"
         | 
| 4 | 
            -
            require "lutaml/uml/has_attributes"
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            module Lutaml
         | 
| 7 | 
            -
              module Uml
         | 
| 8 | 
            -
                module Interface
         | 
| 9 | 
            -
                  class Base
         | 
| 10 | 
            -
                    def self.run(attributes = {})
         | 
| 11 | 
            -
                      new(attributes).run
         | 
| 12 | 
            -
                    end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                    include HasAttributes
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                    # rubocop:disable Rails/ActiveRecordAliases
         | 
| 17 | 
            -
                    def initialize(attributes = {})
         | 
| 18 | 
            -
                      update_attributes(attributes)
         | 
| 19 | 
            -
                    end
         | 
| 20 | 
            -
                    # rubocop:enable Rails/ActiveRecordAliases
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                    def run
         | 
| 23 | 
            -
                      raise NotImplementedError
         | 
| 24 | 
            -
                    end
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
              end
         | 
| 28 | 
            -
            end
         | 
| @@ -1,265 +0,0 @@ | |
| 1 | 
            -
            require "optparse"
         | 
| 2 | 
            -
            require "pathname"
         | 
| 3 | 
            -
            require "lutaml/uml/interface/base"
         | 
| 4 | 
            -
            require "lutaml/uml/parsers/dsl"
         | 
| 5 | 
            -
            require "lutaml/uml/parsers/yaml"
         | 
| 6 | 
            -
            require "lutaml/uml/parsers/attribute"
         | 
| 7 | 
            -
            require "lutaml/uml/formatter"
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            module Lutaml
         | 
| 10 | 
            -
              module Uml
         | 
| 11 | 
            -
                module Interface
         | 
| 12 | 
            -
                  class CommandLine < Base
         | 
| 13 | 
            -
                    class Error < StandardError; end
         | 
| 14 | 
            -
                    class FileError < Error; end
         | 
| 15 | 
            -
                    class NotSupportedInputFormat < Error; end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                    SUPPORTED_FORMATS = %w[yaml dsl].freeze
         | 
| 18 | 
            -
                    DEFAULT_INPUT_FORMAT = "dsl".freeze
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                    def initialize(attributes = {})
         | 
| 21 | 
            -
                      @formatter     = Formatter::Graphviz.new
         | 
| 22 | 
            -
                      @verbose       = false
         | 
| 23 | 
            -
                      @option_parser = OptionParser.new
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                      setup_parser_options
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                      super
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                    def output_path=(value)
         | 
| 31 | 
            -
                      @output_path = determine_output_path_value(value)
         | 
| 32 | 
            -
                    end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                    def determine_output_path_value(value)
         | 
| 35 | 
            -
                      unless value.nil? || @output_path = value.is_a?(Pathname)
         | 
| 36 | 
            -
                        return Pathname.new(value.to_s)
         | 
| 37 | 
            -
                      end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                      value
         | 
| 40 | 
            -
                    end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                    def paths=(values)
         | 
| 43 | 
            -
                      @paths = values.to_a.map { |path| Pathname.new(path) }
         | 
| 44 | 
            -
                    end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                    def formatter=(value)
         | 
| 47 | 
            -
                      value = value.to_s.strip.downcase.to_sym
         | 
| 48 | 
            -
                      value = Formatter.find_by(name: value)
         | 
| 49 | 
            -
                      raise Error, "Formatter not found: #{value}" if value.nil?
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                      @formatter = value
         | 
| 52 | 
            -
                    end
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                    def input_format=(value)
         | 
| 55 | 
            -
                      if value.nil?
         | 
| 56 | 
            -
                        @input_format = DEFAULT_INPUT_FORMAT
         | 
| 57 | 
            -
                        return
         | 
| 58 | 
            -
                      end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                      @input_format = SUPPORTED_FORMATS.detect { |n| n == value }
         | 
| 61 | 
            -
                      raise(NotSupportedInputFormat, value) if @input_format.nil?
         | 
| 62 | 
            -
                    end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                    def run
         | 
| 65 | 
            -
                      args = ARGV.dup # TODO: This is hacky
         | 
| 66 | 
            -
                      begin
         | 
| 67 | 
            -
                        @option_parser.parse!(args)
         | 
| 68 | 
            -
                      rescue StandardError
         | 
| 69 | 
            -
                        nil
         | 
| 70 | 
            -
                      end
         | 
| 71 | 
            -
                      setup_parser_formatter_options
         | 
| 72 | 
            -
                      @option_parser.parse!
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                      self.paths      = ARGV
         | 
| 75 | 
            -
                      @formatter.type = @type
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                      if @output_path&.file? && @paths.length > 1
         | 
| 78 | 
            -
                        raise Error,
         | 
| 79 | 
            -
                              'Output path must be a directory \
         | 
| 80 | 
            -
                              if multiple input files are given'
         | 
| 81 | 
            -
                      end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                      @paths.each do |input_path|
         | 
| 84 | 
            -
                        unless input_path.exist?
         | 
| 85 | 
            -
                          raise FileError, "File does not exist: #{input_path}"
         | 
| 86 | 
            -
                        end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                        document = if @input_format == "yaml"
         | 
| 89 | 
            -
                                     Parsers::Yaml.parse(input_path)
         | 
| 90 | 
            -
                                   else
         | 
| 91 | 
            -
                                     Parsers::Dsl.parse(File.new(input_path))
         | 
| 92 | 
            -
                                   end
         | 
| 93 | 
            -
                        result = @formatter.format(document)
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                        if @output_path
         | 
| 96 | 
            -
                          output_path = @output_path
         | 
| 97 | 
            -
                          if output_path.directory?
         | 
| 98 | 
            -
                            output_path = output_path.join(input_path
         | 
| 99 | 
            -
                                                            .basename(".*").to_s +
         | 
| 100 | 
            -
                                                          ".#{@formatter.type}")
         | 
| 101 | 
            -
                          end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                          output_path.open("w+") { |file| file.write(result) }
         | 
| 104 | 
            -
                        else
         | 
| 105 | 
            -
                          puts result
         | 
| 106 | 
            -
                        end
         | 
| 107 | 
            -
                      end
         | 
| 108 | 
            -
                    end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                    protected
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                    def text_bold(body = nil)
         | 
| 113 | 
            -
                      text_effect(1, body)
         | 
| 114 | 
            -
                    end
         | 
| 115 | 
            -
             | 
| 116 | 
            -
                    def text_italic(body = nil)
         | 
| 117 | 
            -
                      text_effect(3, body)
         | 
| 118 | 
            -
                    end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                    def text_bold_italic(body = nil)
         | 
| 121 | 
            -
                      text_bold(text_italic(body))
         | 
| 122 | 
            -
                    end
         | 
| 123 | 
            -
             | 
| 124 | 
            -
                    def text_underline(body = nil)
         | 
| 125 | 
            -
                      text_effect(4, body)
         | 
| 126 | 
            -
                    end
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                    def text_effect(num, body = nil)
         | 
| 129 | 
            -
                      result = "\e[#{num}m"
         | 
| 130 | 
            -
                      result << "#{body}#{text_reset}" unless body.nil?
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                      result
         | 
| 133 | 
            -
                    end
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                    def text_reset
         | 
| 136 | 
            -
                      "\e[0m"
         | 
| 137 | 
            -
                    end
         | 
| 138 | 
            -
             | 
| 139 | 
            -
                    def setup_parser_options
         | 
| 140 | 
            -
                      @option_parser.banner = ""
         | 
| 141 | 
            -
                      format_desc = "The output formatter (Default: '#{@formatter.name}')"
         | 
| 142 | 
            -
                      @option_parser
         | 
| 143 | 
            -
                        .on("-f",
         | 
| 144 | 
            -
                            "--formatter VALUE",
         | 
| 145 | 
            -
                            format_desc) do |value|
         | 
| 146 | 
            -
                        self.formatter = value
         | 
| 147 | 
            -
                      end
         | 
| 148 | 
            -
                      @option_parser
         | 
| 149 | 
            -
                        .on("-t", "--type VALUE", "The output format type") do |value|
         | 
| 150 | 
            -
                          @type = value
         | 
| 151 | 
            -
                        end
         | 
| 152 | 
            -
                      @option_parser
         | 
| 153 | 
            -
                        .on("-o", "--output VALUE", "The output path") do |value|
         | 
| 154 | 
            -
                          self.output_path = value
         | 
| 155 | 
            -
                        end
         | 
| 156 | 
            -
                      @option_parser
         | 
| 157 | 
            -
                        .on("-i", "--input-format VALUE", "The input format") do |value|
         | 
| 158 | 
            -
                          self.input_format = value
         | 
| 159 | 
            -
                        end
         | 
| 160 | 
            -
                      @option_parser
         | 
| 161 | 
            -
                        .on("-h", "--help", "Prints this help") do
         | 
| 162 | 
            -
                        print_help
         | 
| 163 | 
            -
                        exit
         | 
| 164 | 
            -
                      end
         | 
| 165 | 
            -
                    end
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                    def setup_parser_formatter_options
         | 
| 168 | 
            -
                      case @formatter.name
         | 
| 169 | 
            -
                      when :graphviz
         | 
| 170 | 
            -
                        @option_parser.on("-g", "--graph VALUE") do |value|
         | 
| 171 | 
            -
                          Parsers::Attribute.parse(value).each do |key, attr_value|
         | 
| 172 | 
            -
                            @formatter.graph[key] = attr_value
         | 
| 173 | 
            -
                          end
         | 
| 174 | 
            -
                        end
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                        @option_parser.on("-e", "--edge VALUE") do |value|
         | 
| 177 | 
            -
                          Parsers::Attribute.parse(value).each do |key, attr_value|
         | 
| 178 | 
            -
                            @formatter.edge[key] = attr_value
         | 
| 179 | 
            -
                          end
         | 
| 180 | 
            -
                        end
         | 
| 181 | 
            -
             | 
| 182 | 
            -
                        @option_parser.on("-n", "--node VALUE") do |value|
         | 
| 183 | 
            -
                          Parsers::Attribute.parse(value).each do |key, attr_value|
         | 
| 184 | 
            -
                            @formatter.node[key] = attr_value
         | 
| 185 | 
            -
                          end
         | 
| 186 | 
            -
                        end
         | 
| 187 | 
            -
             | 
| 188 | 
            -
                        @option_parser.on("-a", "--all VALUE") do |value|
         | 
| 189 | 
            -
                          Parsers::Attribute.parse(value).each do |key, attr_value|
         | 
| 190 | 
            -
                            @formatter.graph[key] = attr_value
         | 
| 191 | 
            -
                            @formatter.edge[key] = attr_value
         | 
| 192 | 
            -
                            @formatter.node[key] = attr_value
         | 
| 193 | 
            -
                          end
         | 
| 194 | 
            -
                        end
         | 
| 195 | 
            -
                      end
         | 
| 196 | 
            -
                    end
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                    def print_help
         | 
| 199 | 
            -
                      puts <<~HELP
         | 
| 200 | 
            -
                        #{text_bold('Usage:')} lutaml-uml [options] PATHS
         | 
| 201 | 
            -
             | 
| 202 | 
            -
                        #{text_bold('Overview:')} Generate output from UML Class Diagram language files
         | 
| 203 | 
            -
             | 
| 204 | 
            -
                        #{text_bold('Options:')}
         | 
| 205 | 
            -
                        #{@option_parser}
         | 
| 206 | 
            -
                        #{text_bold('Paths:')}
         | 
| 207 | 
            -
             | 
| 208 | 
            -
                            UCD can accept multiple paths for parsing for easier batch processing.
         | 
| 209 | 
            -
             | 
| 210 | 
            -
                            The location of the output by default is standard output.
         | 
| 211 | 
            -
             | 
| 212 | 
            -
                            The output can be directed to a path with #{text_bold_italic('--output')}, which can be a file or a directory.
         | 
| 213 | 
            -
                            If the output path is a directory, then the filename will be the same as the input filename,
         | 
| 214 | 
            -
                              with it's file extension substituted with the #{text_bold_italic('--type')}.
         | 
| 215 | 
            -
             | 
| 216 | 
            -
                            #{text_underline('Examples')}
         | 
| 217 | 
            -
             | 
| 218 | 
            -
                                `lutaml-uml project.lutaml`
         | 
| 219 | 
            -
             | 
| 220 | 
            -
                                    Produces DOT notation, sent to standard output
         | 
| 221 | 
            -
             | 
| 222 | 
            -
                                `lutaml-uml -o . project.lutaml`
         | 
| 223 | 
            -
             | 
| 224 | 
            -
                                    Produces DOT notation, written to #{text_italic('./project.dot')}
         | 
| 225 | 
            -
             | 
| 226 | 
            -
                                `lutaml-uml -o ./diagram.dot project.lutaml`
         | 
| 227 | 
            -
             | 
| 228 | 
            -
                                    Produces DOT notation, written to #{text_italic('./diagram.dot')}
         | 
| 229 | 
            -
             | 
| 230 | 
            -
                                `lutaml-uml -o ./diagram.png project.lutaml`
         | 
| 231 | 
            -
             | 
| 232 | 
            -
                                    Produces PNG image, written to #{text_italic('./diagram.png')}
         | 
| 233 | 
            -
             | 
| 234 | 
            -
                                `lutaml-uml -t png -o . project.lutaml`
         | 
| 235 | 
            -
             | 
| 236 | 
            -
                                    Produces PNG image, written to #{text_italic('./project.png')}
         | 
| 237 | 
            -
             | 
| 238 | 
            -
                                `lutaml-uml -t png -o . project.lutaml-uml core_ext.lutaml`
         | 
| 239 | 
            -
             | 
| 240 | 
            -
                                    Produces PNG images, written to #{text_italic('./project.png')} and #{text_italic('./core_ext.png')}
         | 
| 241 | 
            -
             | 
| 242 | 
            -
                        #{text_bold('Formatters:')}
         | 
| 243 | 
            -
             | 
| 244 | 
            -
                            #{text_underline('Graphviz')}
         | 
| 245 | 
            -
             | 
| 246 | 
            -
                              Generates DOT notation and can use the DOT notation to generate any format Graphviz can produce.
         | 
| 247 | 
            -
             | 
| 248 | 
            -
                              The output format is based on #{text_bold_italic('--type')}, which by default is "dot".
         | 
| 249 | 
            -
                              If #{text_bold_italic('--type')} is not given and #{text_bold_italic('--output')} is, the file extension of the #{text_bold_italic('--output')} path will be used.
         | 
| 250 | 
            -
             | 
| 251 | 
            -
                              Valid types/extensions are: #{Formatter::Graphviz::VALID_TYPES.join(', ')}
         | 
| 252 | 
            -
             | 
| 253 | 
            -
                              #{text_bold('Options:')}
         | 
| 254 | 
            -
             | 
| 255 | 
            -
                                  -g, --graph VALUE                The graph attributes
         | 
| 256 | 
            -
                                  -e, --edge VALUE                 The edge attributes
         | 
| 257 | 
            -
                                  -n, --node VALUE                 The node attributes
         | 
| 258 | 
            -
                                  -a, --all VALUE                  Set attributes for graph, edge, and node
         | 
| 259 | 
            -
             | 
| 260 | 
            -
                      HELP
         | 
| 261 | 
            -
                    end
         | 
| 262 | 
            -
                  end
         | 
| 263 | 
            -
                end
         | 
| 264 | 
            -
              end
         | 
| 265 | 
            -
            end
         |