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
|