lutaml-uml 0.2.5 → 0.2.10
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 +12 -7
- data/README.adoc +9 -10
- data/bin/plantuml2lutaml +1 -0
- data/bin/yaml2lutaml +4 -4
- 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/enum.rb +0 -4
- data/lib/lutaml/uml/parsers/dsl.rb +10 -7
- 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 -2
- data/spec/fixtures/dsl/diagram_class_fields.lutaml +2 -0
- data/spec/fixtures/dsl/diagram_data_types.lutaml +1 -1
- data/spec/fixtures/dsl/diagram_definitions.lutaml +10 -5
- data/spec/lutaml/uml/parsers/dsl_spec.rb +15 -4
- metadata +7 -21
- 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: 2a4318a33ee0facc590ee478a533551314aa96290ff3f9beb2a8506518f107fb
|
4
|
+
data.tar.gz: 18164bb8e957223dc1f1fdeacd7603f61705482d3299de01edcd6c96bb1860a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcb70562cec32586375a93e1a80a575bd6dc3b7150d2867046447af6461dec4af6e0c59ed179607dc03408e285c8cb6f1c627004f36118372027c8e9b9890bc2
|
7
|
+
data.tar.gz: 304d5c7326dbe2378a431c07cb50f0f21596a18dca6e0d694b2c7de26d1726a30e3932b3b2fd52f7f404a0a0453d7d7ec098b731f9460bab8eb24dd61939cbff
|
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:
|
@@ -118,9 +123,9 @@ Full syntax:
|
|
118
123
|
|
119
124
|
[source,java]
|
120
125
|
----
|
121
|
-
definition
|
126
|
+
definition {
|
122
127
|
inner text
|
123
|
-
|
128
|
+
}
|
124
129
|
----
|
125
130
|
|
126
131
|
|
@@ -204,9 +209,9 @@ example:
|
|
204
209
|
----
|
205
210
|
class Figure {
|
206
211
|
+ radius {
|
207
|
-
definition
|
212
|
+
definition {
|
208
213
|
Radius of the Figure
|
209
|
-
|
214
|
+
}
|
210
215
|
}
|
211
216
|
}
|
212
217
|
----
|
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
@@ -89,9 +89,9 @@ view_yaml["imports"].keys.each do |entry|
|
|
89
89
|
sync_puts("#{import['modelType']} #{import_name} {", 2)
|
90
90
|
if import["definition"]
|
91
91
|
definition = <<~TEXT
|
92
|
-
definition
|
92
|
+
definition {
|
93
93
|
#{import['definition']}
|
94
|
-
|
94
|
+
}
|
95
95
|
TEXT
|
96
96
|
sync_puts(definition, 4)
|
97
97
|
end
|
@@ -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
|
-
|
105
|
+
}
|
106
106
|
}
|
107
107
|
TEXT
|
108
108
|
end
|
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/enum.rb
CHANGED
@@ -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 >>
|
@@ -291,9 +291,11 @@ module Lutaml
|
|
291
291
|
spaces? >>
|
292
292
|
str("definition") >>
|
293
293
|
whitespace? >>
|
294
|
-
|
294
|
+
str("{") >>
|
295
|
+
whitespace? >>
|
296
|
+
(match("[\n\s]}").absent? >> any).repeat.as(:definition) >>
|
295
297
|
whitespace? >>
|
296
|
-
str(
|
298
|
+
str('}')
|
297
299
|
end
|
298
300
|
|
299
301
|
# -- Enum
|
@@ -320,6 +322,7 @@ module Lutaml
|
|
320
322
|
match['"\''].maybe >>
|
321
323
|
class_name.as(:name) >>
|
322
324
|
match['"\''].maybe >>
|
325
|
+
attribute_keyword? >>
|
323
326
|
enum_body?
|
324
327
|
end
|
325
328
|
|
@@ -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,9 +22,8 @@ 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
|
-
spec.add_runtime_dependency "activesupport", "~> 5.0"
|
28
27
|
spec.add_runtime_dependency "hashie", "~> 4.1.0"
|
29
28
|
spec.add_runtime_dependency "parslet", "~> 1.7.1"
|
30
29
|
spec.add_runtime_dependency "ruby-graphviz", "~> 1.2"
|
@@ -2,19 +2,24 @@ diagram MyView {
|
|
2
2
|
title "my diagram"
|
3
3
|
|
4
4
|
class AddressClassProfile {
|
5
|
-
definition
|
5
|
+
definition {
|
6
6
|
this is multiline with `ascidoc`
|
7
7
|
comments
|
8
8
|
and list
|
9
|
-
|
9
|
+
\{foo\} \{name\}
|
10
|
+
}
|
10
11
|
+addressClassProfile: CharacterString [0..1]
|
11
12
|
}
|
12
13
|
|
13
14
|
class AttributeProfile {
|
14
15
|
imlicistAttributeProfile: CharacterString [0..1] {
|
15
|
-
definition
|
16
|
-
|
17
|
-
|
16
|
+
definition
|
17
|
+
{
|
18
|
+
this is attribute definition
|
19
|
+
with multiply lines
|
20
|
+
\{foo\} \{name\}
|
21
|
+
end definition
|
22
|
+
}
|
18
23
|
}
|
19
24
|
}
|
20
25
|
}
|
@@ -68,7 +68,18 @@ 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(9)
|
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"]))
|
72
83
|
end
|
73
84
|
|
74
85
|
it "creates the correct attributes with the correct visibility" do
|
@@ -121,7 +132,7 @@ RSpec.describe Lutaml::Uml::Parsers::Dsl do
|
|
121
132
|
expect(association.member_end).to(eq("AttributeProfile"))
|
122
133
|
expect(association.member_end_attribute_name)
|
123
134
|
.to(eq("attributeProfile"))
|
124
|
-
expect(association.member_end_cardinality).to(eq(min
|
135
|
+
expect(association.member_end_cardinality).to(eq("min" => "0", "max" => "*"))
|
125
136
|
end
|
126
137
|
end
|
127
138
|
|
@@ -254,10 +265,10 @@ RSpec.describe Lutaml::Uml::Parsers::Dsl do
|
|
254
265
|
File.new(fixtures_path("dsl/diagram_definitions.lutaml"))
|
255
266
|
end
|
256
267
|
let(:class_definition) do
|
257
|
-
"this is multiline with `ascidoc`\
|
268
|
+
"this is multiline with `ascidoc`\ncomments\nand list\n{foo} {name}"
|
258
269
|
end
|
259
270
|
let(:attribute_definition) do
|
260
|
-
"this is attribute definition\
|
271
|
+
"this is attribute definition\nwith multiply lines\n{foo} {name}\nend definition"
|
261
272
|
end
|
262
273
|
|
263
274
|
it "create comments for document and classes" do
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lutaml-uml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.10
|
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-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '5.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '5.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: hashie
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,7 +168,8 @@ description: UML model module for LutaML.
|
|
182
168
|
email:
|
183
169
|
- open.source@ribose.com'
|
184
170
|
executables:
|
185
|
-
- lutaml-
|
171
|
+
- lutaml-wsd2uml
|
172
|
+
- lutaml-yaml2uml
|
186
173
|
extensions: []
|
187
174
|
extra_rdoc_files: []
|
188
175
|
files:
|
@@ -202,7 +189,8 @@ files:
|
|
202
189
|
- bin/plantuml2lutaml
|
203
190
|
- bin/setup
|
204
191
|
- bin/yaml2lutaml
|
205
|
-
- exe/lutaml-
|
192
|
+
- exe/lutaml-wsd2uml
|
193
|
+
- exe/lutaml-yaml2uml
|
206
194
|
- lib/lutaml/layout/engine.rb
|
207
195
|
- lib/lutaml/layout/graph_viz_engine.rb
|
208
196
|
- lib/lutaml/uml.rb
|
@@ -228,8 +216,6 @@ files:
|
|
228
216
|
- lib/lutaml/uml/has_attributes.rb
|
229
217
|
- lib/lutaml/uml/has_members.rb
|
230
218
|
- lib/lutaml/uml/instance.rb
|
231
|
-
- lib/lutaml/uml/interface/base.rb
|
232
|
-
- lib/lutaml/uml/interface/command_line.rb
|
233
219
|
- lib/lutaml/uml/model.rb
|
234
220
|
- lib/lutaml/uml/node/base.rb
|
235
221
|
- lib/lutaml/uml/node/class_node.rb
|
@@ -333,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
333
319
|
- !ruby/object:Gem::Version
|
334
320
|
version: '0'
|
335
321
|
requirements: []
|
336
|
-
rubygems_version: 3.0.
|
322
|
+
rubygems_version: 3.0.3
|
337
323
|
signing_key:
|
338
324
|
specification_version: 4
|
339
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
|