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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: caa272840dbf2e26c09465e9fc43ce87e27264d1304f3e517177e1c2aeb5ddd5
4
- data.tar.gz: 63accfb7dc6651f7df5a2fa16e1f3049efeac98f2b7c45ab33797e5589955011
3
+ metadata.gz: 3436e32ef66aba3d38cf8418de2ecef7bd475a1379e62e787aaddb0701397b55
4
+ data.tar.gz: da160c6b5ffaa013cb0d4bc4df8a23175acdff14da402c15b883c96a424cbd83
5
5
  SHA512:
6
- metadata.gz: 60f0496d0d68e7ec42f96d2dea4e28b2f48be4ff46f079afc0a0041a31e9a0a32d6353f8a208a7194585c4e95a31a7fdaeb5e8bc21e94752b9ce8953d8b4655e
7
- data.tar.gz: f1c58b701b5eff18c42c4fb8a38c9beab572663a345ea048abc112993f671b38e17ff8af9852951cc7650969715130996639bb4cb1eb517ba3cae83a023ee30e
6
+ metadata.gz: f76a00663fa9a4a8167930d4114ef4995ce7b488034336dd1134953ca9ed09ab4fd2da6e32a425082b6cf212b97bf47493e0b3f45c4b181fa93966f581ad7265
7
+ data.tar.gz: 85f1fd71d5df7d0e673a5c4994f7d524dbaa915afca26bdacd483e384889003114e3f91ac1d7c0a28bc9a649b675036458c4fcc685b9e8534b6a49c346bb269d
@@ -18,7 +18,7 @@ jobs:
18
18
  strategy:
19
19
  fail-fast: false
20
20
  matrix:
21
- ruby: [ '2.6', '2.5', '2.4' ]
21
+ ruby: [ '2.6', '2.5' ]
22
22
  experimental: [false]
23
23
  include:
24
24
  - ruby: '2.7'
data/LUTAML.adoc CHANGED
@@ -7,13 +7,18 @@
7
7
  [source,java]
8
8
  ----
9
9
  diagram MyView {
10
- import Relationship, Element
11
- render_option typed_as_associations
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
- ## Executable
11
+ ## Language
12
12
 
13
- [source,sh]
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
- # Display detailed help message
19
- $ lutaml-uml --help
20
- --
15
+ ## Usage
21
16
 
22
- ## Language
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
@@ -100,9 +100,9 @@ view_yaml["imports"].keys.each do |entry|
100
100
  if values["definition"]
101
101
  result_string += <<~TEXT
102
102
  {
103
- definition
103
+ definition {
104
104
  #{values['definition']}
105
- end definition
105
+ }
106
106
  }
107
107
  TEXT
108
108
  end
@@ -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("}")
@@ -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/interface/command_line"
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
@@ -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)
@@ -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 data_types=(value)
37
- @data_types = value.to_a.map { |attributes| DataType.new(attributes) }
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
@@ -27,10 +27,6 @@ module Lutaml
27
27
  end
28
28
  end
29
29
 
30
- def definition=(value)
31
- @definition = value.to_s
32
- end
33
-
34
30
  # TODO: reserved name, change
35
31
  def methods
36
32
  []
@@ -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 initialize
9
- @imports = []
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(:min) >>
85
+ match['0-9\*'].as('min') >>
86
86
  str("..").maybe >>
87
- match['0-9\*'].as(:max).maybe
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) { name.as(: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
- (str("}").absent? >> any).repeat.as(:definition) >>
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
- attribute_definition
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Uml
5
- VERSION = "0.2.7"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
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-uml]
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
- "art code"
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(7)
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: "0", max: "*"))
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`\n comments\n and list"
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\n with multiply lines\n end 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.2.7
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: 2020-11-27 00:00:00.000000000 Z
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-uml
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-uml
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.6
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