lutaml 0.7.7 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -6
  3. data/.rubocop.yml +1 -0
  4. data/LUTAML.adoc +372 -0
  5. data/Makefile +2 -0
  6. data/bin/console +5 -0
  7. data/bin/folder_yaml2lutaml.sh +6 -0
  8. data/bin/plantuml2lutaml +59 -0
  9. data/bin/yaml2lutaml +144 -0
  10. data/exe/lutaml-sysml +20 -0
  11. data/exe/lutaml-wsd2uml +59 -0
  12. data/exe/lutaml-yaml2uml +144 -0
  13. data/lib/lutaml/express/README.adoc +55 -0
  14. data/lib/lutaml/express/parsers/exp.rb +21 -0
  15. data/lib/lutaml/express/version.rb +7 -0
  16. data/lib/lutaml/express.rb +9 -0
  17. data/lib/lutaml/parser.rb +7 -0
  18. data/lib/lutaml/sysml/README.md +40 -0
  19. data/lib/lutaml/sysml/allocate.rb +8 -0
  20. data/lib/lutaml/sysml/allocated.rb +7 -0
  21. data/lib/lutaml/sysml/binding_connector.rb +7 -0
  22. data/lib/lutaml/sysml/block.rb +27 -0
  23. data/lib/lutaml/sysml/constraint_block.rb +12 -0
  24. data/lib/lutaml/sysml/copy.rb +6 -0
  25. data/lib/lutaml/sysml/derive_requirement.rb +7 -0
  26. data/lib/lutaml/sysml/nested_connector_end.rb +11 -0
  27. data/lib/lutaml/sysml/refine.rb +7 -0
  28. data/lib/lutaml/sysml/requirement.rb +34 -0
  29. data/lib/lutaml/sysml/requirement_related.rb +7 -0
  30. data/lib/lutaml/sysml/satisfy.rb +7 -0
  31. data/lib/lutaml/sysml/test_case.rb +22 -0
  32. data/lib/lutaml/sysml/trace.rb +7 -0
  33. data/lib/lutaml/sysml/verify.rb +6 -0
  34. data/lib/lutaml/sysml/version.rb +5 -0
  35. data/lib/lutaml/sysml/xmi_file.rb +417 -0
  36. data/lib/lutaml/sysml.rb +10 -0
  37. data/lib/lutaml/uml/README.adoc +44 -0
  38. data/lib/lutaml/uml/abstraction.rb +11 -0
  39. data/lib/lutaml/uml/activity.rb +11 -0
  40. data/lib/lutaml/uml/actor.rb +19 -0
  41. data/lib/lutaml/uml/association.rb +43 -0
  42. data/lib/lutaml/uml/behavior.rb +11 -0
  43. data/lib/lutaml/uml/class.rb +83 -0
  44. data/lib/lutaml/uml/classifier.rb +11 -0
  45. data/lib/lutaml/uml/connector.rb +21 -0
  46. data/lib/lutaml/uml/constraint.rb +12 -0
  47. data/lib/lutaml/uml/constructor_end.rb +16 -0
  48. data/lib/lutaml/uml/data_type.rb +75 -0
  49. data/lib/lutaml/uml/dependency.rb +21 -0
  50. data/lib/lutaml/uml/diagram.rb +8 -0
  51. data/lib/lutaml/uml/document.rb +81 -0
  52. data/lib/lutaml/uml/enum.rb +45 -0
  53. data/lib/lutaml/uml/event.rb +12 -0
  54. data/lib/lutaml/uml/final_state.rb +11 -0
  55. data/lib/lutaml/uml/formatter/base.rb +67 -0
  56. data/lib/lutaml/uml/formatter/graphviz.rb +334 -0
  57. data/lib/lutaml/uml/formatter.rb +21 -0
  58. data/lib/lutaml/uml/has_attributes.rb +14 -0
  59. data/lib/lutaml/uml/has_members.rb +30 -0
  60. data/lib/lutaml/uml/instance.rb +17 -0
  61. data/lib/lutaml/uml/model.rb +13 -0
  62. data/lib/lutaml/uml/node/base.rb +21 -0
  63. data/lib/lutaml/uml/node/class_node.rb +57 -0
  64. data/lib/lutaml/uml/node/class_relationship.rb +14 -0
  65. data/lib/lutaml/uml/node/document.rb +18 -0
  66. data/lib/lutaml/uml/node/field.rb +34 -0
  67. data/lib/lutaml/uml/node/has_name.rb +15 -0
  68. data/lib/lutaml/uml/node/has_type.rb +15 -0
  69. data/lib/lutaml/uml/node/method.rb +29 -0
  70. data/lib/lutaml/uml/node/method_argument.rb +16 -0
  71. data/lib/lutaml/uml/node/relationship.rb +28 -0
  72. data/lib/lutaml/uml/opaque_behavior.rb +11 -0
  73. data/lib/lutaml/uml/operation.rb +31 -0
  74. data/lib/lutaml/uml/package.rb +53 -0
  75. data/lib/lutaml/uml/parsers/attribute.rb +70 -0
  76. data/lib/lutaml/uml/parsers/dsl.rb +413 -0
  77. data/lib/lutaml/uml/parsers/dsl_preprocessor.rb +59 -0
  78. data/lib/lutaml/uml/parsers/dsl_transform.rb +27 -0
  79. data/lib/lutaml/uml/parsers/yaml.rb +46 -0
  80. data/lib/lutaml/uml/port.rb +8 -0
  81. data/lib/lutaml/uml/primitive_type.rb +14 -0
  82. data/lib/lutaml/uml/property.rb +27 -0
  83. data/lib/lutaml/uml/pseudostate.rb +11 -0
  84. data/lib/lutaml/uml/realization.rb +11 -0
  85. data/lib/lutaml/uml/region.rb +12 -0
  86. data/lib/lutaml/uml/serializers/association.rb +58 -0
  87. data/lib/lutaml/uml/serializers/base.rb +16 -0
  88. data/lib/lutaml/uml/serializers/class.rb +29 -0
  89. data/lib/lutaml/uml/serializers/top_element_attribute.rb +14 -0
  90. data/lib/lutaml/uml/serializers/yaml_view.rb +18 -0
  91. data/lib/lutaml/uml/state.rb +12 -0
  92. data/lib/lutaml/uml/state_machine.rb +12 -0
  93. data/lib/lutaml/uml/top_element.rb +58 -0
  94. data/lib/lutaml/uml/top_element_attribute.rb +39 -0
  95. data/lib/lutaml/uml/transition.rb +12 -0
  96. data/lib/lutaml/uml/trigger.rb +12 -0
  97. data/lib/lutaml/uml/value.rb +31 -0
  98. data/lib/lutaml/uml/version.rb +7 -0
  99. data/lib/lutaml/uml/vertex.rb +11 -0
  100. data/lib/lutaml/uml.rb +13 -0
  101. data/lib/lutaml/version.rb +1 -1
  102. data/lib/lutaml/xmi/README.adoc +24 -0
  103. data/lib/lutaml/xmi/parsers/xml.rb +600 -0
  104. data/lib/lutaml/xmi/version.rb +5 -0
  105. data/lib/lutaml/xmi.rb +7 -0
  106. data/lib/lutaml/xml/lutaml_path/document_wrapper.rb +45 -0
  107. data/lib/lutaml/xml/mapper.rb +448 -0
  108. data/lib/lutaml/xml/parsers/xml.rb +57 -0
  109. data/lib/lutaml/xml.rb +9 -0
  110. data/lutaml.gemspec +8 -3
  111. metadata +192 -16
@@ -0,0 +1,413 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+ require "parslet/convenience"
5
+ require "lutaml/uml/parsers/dsl_preprocessor"
6
+ require "lutaml/uml/parsers/dsl_transform"
7
+ require "lutaml/uml/node/document"
8
+
9
+ module Lutaml
10
+ module Uml
11
+ module Parsers
12
+ class ParsingError < StandardError; end
13
+ # Class for parsing LutaML dsl into Lutaml::Uml::Document
14
+ class Dsl < Parslet::Parser
15
+ # @param [String] io - LutaML string representation
16
+ # [Hash] options - options for parsing
17
+ #
18
+ # @return [Lutaml::Uml::Document]
19
+ def self.parse(io, options = {})
20
+ new.parse(io, options)
21
+ end
22
+
23
+ def parse(input_file, _options = {})
24
+ data = Lutaml::Uml::Parsers::DslPreprocessor.call(input_file)
25
+ # https://kschiess.github.io/parslet/tricks.html#Reporter engines
26
+ # Parslet::ErrorReporter::Deepest allows more
27
+ # detailed display of error
28
+ reporter = Parslet::ErrorReporter::Deepest.new
29
+ ::Lutaml::Uml::Document
30
+ .new(DslTransform.new.apply(super(data, reporter: reporter)))
31
+ rescue Parslet::ParseFailed => e
32
+ raise(ParsingError,
33
+ "#{e.message}\ncause: #{e.parse_failure_cause.ascii_tree}")
34
+ end
35
+
36
+ KEYWORDS = %w[
37
+ abstract
38
+ aggregation
39
+ association
40
+ association
41
+ attribute
42
+ bidirectional
43
+ class
44
+ composition
45
+ data_type
46
+ dependency
47
+ diagram
48
+ directional
49
+ enum
50
+ fontname
51
+ generalizes
52
+ include
53
+ interface
54
+ member
55
+ member_type
56
+ method
57
+ owner
58
+ owner_type
59
+ primitive
60
+ private
61
+ protected
62
+ public
63
+ realizes
64
+ static
65
+ title
66
+ caption
67
+ ].freeze
68
+
69
+ KEYWORDS.each do |keyword|
70
+ rule("kw_#{keyword}") { str(keyword) }
71
+ end
72
+
73
+ rule(:spaces) { match("\s").repeat(1) }
74
+ rule(:spaces?) { spaces.maybe }
75
+ rule(:whitespace) do
76
+ (match("\s") | match(" ") | match("\r?\n") | match("\r") | str(";")).repeat(1)
77
+ end
78
+ rule(:whitespace?) { whitespace.maybe }
79
+ rule(:name) { match["a-zA-Z0-9 _-"].repeat(1) }
80
+ rule(:newline) { str("\n") >> str("\r").maybe }
81
+ rule(:comment_definition) do
82
+ spaces? >> str("**") >> (newline.absent? >> any).repeat.as(:comments)
83
+ end
84
+ rule(:comment_multiline_definition) do
85
+ spaces? >> str("*|") >> (str("|*").absent? >> any).repeat.as(:comments) >> whitespace? >> str("|*")
86
+ end
87
+ rule(:class_name_chars) { match('(?:[a-zA-Z0-9 _-]|\:|\.)').repeat(1) }
88
+ rule(:class_name) do
89
+ class_name_chars >>
90
+ (str("(") >>
91
+ class_name_chars >>
92
+ str(")")).maybe
93
+ end
94
+ rule(:cardinality_body_definition) do
95
+ match['0-9\*'].as('min') >>
96
+ str("..").maybe >>
97
+ match['0-9\*'].as('max').maybe
98
+ end
99
+ rule(:cardinality) do
100
+ str("[") >>
101
+ cardinality_body_definition.as(:cardinality) >>
102
+ str("]")
103
+ end
104
+ rule(:cardinality?) { cardinality.maybe }
105
+
106
+ # -- attribute/Method
107
+ rule(:kw_visibility_modifier) do
108
+ str("+") | str("-") | str("#") | str("~")
109
+ end
110
+
111
+ rule(:member_static) { (kw_static.as(:static) >> spaces).maybe }
112
+ rule(:visibility) do
113
+ kw_visibility_modifier.as(:visibility_modifier)
114
+ end
115
+ rule(:visibility?) { visibility.maybe }
116
+
117
+ rule(:method_abstract) { (kw_abstract.as(:abstract) >> spaces).maybe }
118
+ rule(:attribute_keyword) do
119
+ str("<<") >>
120
+ match['a-zA-Z0-9_\-\/'].repeat(1).as(:keyword) >>
121
+ str(">>")
122
+ end
123
+ rule(:attribute_keyword?) { attribute_keyword.maybe }
124
+ rule(:attribute_type) do
125
+ (str(":") >>
126
+ spaces? >>
127
+ attribute_keyword? >>
128
+ spaces? >>
129
+ match['"\''].maybe >>
130
+ match['a-zA-Z0-9_\- \/\+'].repeat(1).as(:type) >>
131
+ match['"\''].maybe >>
132
+ spaces?
133
+ )
134
+ end
135
+ rule(:attribute_type?) do
136
+ attribute_type.maybe
137
+ end
138
+
139
+ rule(:attribute_name) { match['a-zA-Z0-9_\- \/\+'].repeat(1).as(:name) }
140
+ rule(:attribute_definition) do
141
+ (visibility?.as(:visibility) >>
142
+ match['"\''].maybe >>
143
+ attribute_name >>
144
+ match['"\''].maybe >>
145
+ attribute_type? >>
146
+ cardinality? >>
147
+ class_body?)
148
+ .as(:attributes)
149
+ end
150
+
151
+ rule(:title_keyword) { kw_title >> spaces }
152
+ rule(:title_text) do
153
+ match['"\''].maybe >>
154
+ match['a-zA-Z0-9_\- ,.:;'].repeat(1).as(:title) >>
155
+ match['"\''].maybe
156
+ end
157
+ rule(:title_definition) { title_keyword >> title_text }
158
+ rule(:caption_keyword) { kw_caption >> spaces }
159
+ rule(:caption_text) do
160
+ match['"\''].maybe >>
161
+ match['a-zA-Z0-9_\- ,.:;'].repeat(1).as(:caption) >>
162
+ match['"\''].maybe
163
+ end
164
+ rule(:caption_definition) { caption_keyword >> caption_text }
165
+
166
+ rule(:fontname_keyword) { kw_fontname >> spaces }
167
+ rule(:fontname_text) do
168
+ match['"\''].maybe >>
169
+ match['a-zA-Z0-9_\- '].repeat(1).as(:fontname) >>
170
+ match['"\''].maybe
171
+ end
172
+ rule(:fontname_definition) { fontname_keyword >> fontname_text }
173
+
174
+ # Method
175
+ # rule(:method_keyword) { kw_method >> spaces }
176
+ # rule(:method_argument) { name.as(:name) >> member_type }
177
+ # rule(:method_arguments_inner) do
178
+ # (method_argument >>
179
+ # (spaces? >> str(",") >> spaces? >> method_argument).repeat)
180
+ # .repeat.as(:arguments)
181
+ # end
182
+ # rule(:method_arguments) do
183
+ # (str("(") >>
184
+ # spaces? >>
185
+ # method_arguments_inner >>
186
+ # spaces? >>
187
+ # str(")"))
188
+ # .maybe
189
+ # end
190
+
191
+ # rule(:method_name) { name.as(:name) }
192
+ # rule(:method_return_type) { member_type.maybe }
193
+ # rule(:method_definition) do
194
+ # (method_abstract >>
195
+ # member_static >>
196
+ # visibility >>
197
+ # method_keyword >>
198
+ # method_name >>
199
+ # method_arguments >>
200
+ # method_return_type)
201
+ # .as(:method)
202
+ # end
203
+
204
+ # -- Association
205
+
206
+ rule(:association_keyword) { kw_association >> spaces }
207
+
208
+ %w[owner member].each do |association_end_type|
209
+ rule("#{association_end_type}_cardinality") do
210
+ spaces? >>
211
+ str("[") >>
212
+ cardinality_body_definition
213
+ .as("#{association_end_type}_end_cardinality") >>
214
+ str("]")
215
+ end
216
+ rule("#{association_end_type}_cardinality?") do
217
+ send("#{association_end_type}_cardinality").maybe
218
+ end
219
+ rule("#{association_end_type}_attribute_name") do
220
+ str("#") >>
221
+ visibility? >>
222
+ name.as("#{association_end_type}_end_attribute_name")
223
+ end
224
+ rule("#{association_end_type}_attribute_name?") do
225
+ send("#{association_end_type}_attribute_name").maybe
226
+ end
227
+ rule("#{association_end_type}_definition") do
228
+ send("kw_#{association_end_type}") >>
229
+ spaces >>
230
+ name.as("#{association_end_type}_end") >>
231
+ send("#{association_end_type}_attribute_name?") >>
232
+ send("#{association_end_type}_cardinality?")
233
+ end
234
+ rule("#{association_end_type}_type") do
235
+ send("kw_#{association_end_type}_type") >>
236
+ spaces >>
237
+ name.as("#{association_end_type}_end_type")
238
+ end
239
+ end
240
+
241
+ rule(:association_inner_definitions) do
242
+ owner_type |
243
+ member_type |
244
+ owner_definition |
245
+ member_definition |
246
+ comment_definition |
247
+ comment_multiline_definition
248
+ end
249
+ rule(:association_inner_definition) do
250
+ association_inner_definitions >> whitespace?
251
+ end
252
+ rule(:association_body) do
253
+ spaces? >>
254
+ str("{") >>
255
+ whitespace? >>
256
+ association_inner_definition.repeat.as(:members) >>
257
+ str("}")
258
+ end
259
+ rule(:association_definition) do
260
+ association_keyword >>
261
+ name.as(:name).maybe >>
262
+ association_body
263
+ end
264
+
265
+ # -- Class
266
+
267
+ rule(:kw_class_modifier) { kw_abstract | kw_interface }
268
+
269
+ rule(:class_modifier) do
270
+ (kw_class_modifier.as(:modifier) >> spaces).maybe
271
+ end
272
+ rule(:class_keyword) { kw_class >> spaces }
273
+ rule(:class_inner_definitions) do
274
+ definition_body |
275
+ attribute_definition |
276
+ comment_definition |
277
+ comment_multiline_definition
278
+ end
279
+ rule(:class_inner_definition) do
280
+ class_inner_definitions >> whitespace?
281
+ end
282
+ rule(:class_body) do
283
+ spaces? >>
284
+ str("{") >>
285
+ whitespace? >>
286
+ class_inner_definition.repeat.as(:members) >>
287
+ str("}")
288
+ end
289
+ rule(:class_body?) { class_body.maybe }
290
+ rule(:class_definition) do
291
+ class_modifier >>
292
+ class_keyword >>
293
+ class_name.as(:name) >>
294
+ spaces? >>
295
+ attribute_keyword? >>
296
+ class_body?
297
+ end
298
+
299
+ # -- Definition
300
+ rule(:definition_body) do
301
+ spaces? >>
302
+ str("definition") >>
303
+ whitespace? >>
304
+ str("{") >>
305
+ ((str("\\") >> any) | (str("}").absent? >> any)).repeat.maybe.as(:definition) >>
306
+ str('}')
307
+ end
308
+
309
+ # -- Enum
310
+ rule(:enum_keyword) { kw_enum >> spaces }
311
+ rule(:enum_inner_definitions) do
312
+ definition_body |
313
+ attribute_definition |
314
+ comment_definition |
315
+ comment_multiline_definition
316
+ end
317
+ rule(:enum_inner_definition) do
318
+ enum_inner_definitions >> whitespace?
319
+ end
320
+ rule(:enum_body) do
321
+ spaces? >>
322
+ str("{") >>
323
+ whitespace? >>
324
+ enum_inner_definition.repeat.as(:members) >>
325
+ str("}")
326
+ end
327
+ rule(:enum_body?) { enum_body.maybe }
328
+ rule(:enum_definition) do
329
+ enum_keyword >>
330
+ match['"\''].maybe >>
331
+ class_name.as(:name) >>
332
+ match['"\''].maybe >>
333
+ attribute_keyword? >>
334
+ enum_body?
335
+ end
336
+
337
+ # -- data_type
338
+ rule(:data_type_keyword) { kw_data_type >> spaces }
339
+ rule(:data_type_inner_definitions) do
340
+ definition_body |
341
+ attribute_definition |
342
+ comment_definition |
343
+ comment_multiline_definition
344
+ end
345
+ rule(:data_type_inner_definition) do
346
+ data_type_inner_definitions >> whitespace?
347
+ end
348
+ rule(:data_type_body) do
349
+ spaces? >>
350
+ str("{") >>
351
+ whitespace? >>
352
+ data_type_inner_definition.repeat.as(:members) >>
353
+ str("}")
354
+ end
355
+ rule(:data_type_body?) { data_type_body.maybe }
356
+ rule(:data_type_definition) do
357
+ data_type_keyword >>
358
+ match['"\''].maybe >>
359
+ class_name.as(:name) >>
360
+ match['"\''].maybe >>
361
+ attribute_keyword? >>
362
+ data_type_body?
363
+ end
364
+
365
+ # -- primitive
366
+ rule(:primitive_keyword) { kw_primitive >> spaces }
367
+ rule(:primitive_definition) do
368
+ primitive_keyword >>
369
+ match['"\''].maybe >>
370
+ class_name.as(:name) >>
371
+ match['"\''].maybe
372
+ end
373
+
374
+ # -- Diagram
375
+ rule(:diagram_keyword) { kw_diagram >> spaces? }
376
+ rule(:diagram_inner_definitions) do
377
+ title_definition |
378
+ caption_definition |
379
+ fontname_definition |
380
+ class_definition.as(:classes) |
381
+ enum_definition.as(:enums) |
382
+ primitive_definition.as(:primitives) |
383
+ data_type_definition.as(:data_types) |
384
+ association_definition.as(:associations) |
385
+ comment_definition |
386
+ comment_multiline_definition
387
+ end
388
+ rule(:diagram_inner_definition) do
389
+ diagram_inner_definitions >> whitespace?
390
+ end
391
+ rule(:diagram_body) do
392
+ spaces? >>
393
+ str("{") >>
394
+ whitespace? >>
395
+ diagram_inner_definition.repeat.as(:members) >>
396
+ str("}")
397
+ end
398
+ rule(:diagram_definition) do
399
+ diagram_keyword >>
400
+ spaces? >>
401
+ class_name.as(:name) >>
402
+ diagram_body >>
403
+ whitespace?
404
+ end
405
+ rule(:diagram_definitions) { diagram_definition >> whitespace? }
406
+ rule(:diagram) { whitespace? >> diagram_definition }
407
+ # -- Root
408
+
409
+ root(:diagram)
410
+ end
411
+ end
412
+ end
413
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Uml
5
+ module Parsers
6
+ # Class for preprocessing dsl ascii file special directives:
7
+ # - include
8
+ class DslPreprocessor
9
+ attr_reader :input_file
10
+
11
+ def initialize(input_file)
12
+ @input_file = input_file
13
+ end
14
+
15
+ class << self
16
+ def call(input_file)
17
+ new(input_file).call
18
+ end
19
+ end
20
+
21
+ def call
22
+ include_root = File.dirname(input_file.path)
23
+ input_file.read.split("\n").reduce([]) do |res, line|
24
+ res.push(*process_dsl_line(include_root, line))
25
+ end.join("\n")
26
+ end
27
+
28
+ private
29
+
30
+ def process_dsl_line(include_root, line)
31
+ process_include_line(include_root, process_comment_line(line))
32
+ end
33
+
34
+ def process_comment_line(line)
35
+ has_comment = line.match(%r{//.*})
36
+ return line if has_comment.nil?
37
+
38
+ line.gsub(%r{//.*}, "")
39
+ end
40
+
41
+ def process_include_line(include_root, line)
42
+ include_path_match = line.match(/^\s*include\s+(.+)/)
43
+ return line if include_path_match.nil? || line =~ /^\s\*\*/
44
+
45
+ path_to_file = include_path_match[1].strip
46
+ path_to_file = if path_to_file.match?(/^\//)
47
+ path_to_file
48
+ else
49
+ File.join(include_root, path_to_file)
50
+ end
51
+ File.read(path_to_file).split("\n").map { |line| process_comment_line(line) }
52
+ rescue Errno::ENOENT
53
+ puts("No such file or directory @ rb_sysopen - #{path_to_file}, \
54
+ include file paths need to be supplied relative to the main document")
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+
5
+ module Lutaml
6
+ module Uml
7
+ module Parsers
8
+ # Class for additional transformations of LutaML syntax:
9
+ # visibility modifier etc
10
+ class DslTransform < Parslet::Transform
11
+ rule(visibility_modifier: simple(:visibility_value)) do
12
+ case visibility_value
13
+ when "-"
14
+ "private"
15
+ when "#"
16
+ "protected"
17
+ when "~"
18
+ "friendly"
19
+ else
20
+ "public"
21
+ end
22
+ end
23
+ rule(simple(:member)) { member.nil? ? member : member.to_s.strip }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "lutaml/uml/class"
5
+ require "lutaml/uml/document"
6
+ require "lutaml/uml/serializers/yaml_view"
7
+
8
+ module Lutaml
9
+ module Uml
10
+ module Parsers
11
+ class Yaml
12
+ def self.parse(yaml_path, options = {})
13
+ new.parse(yaml_path, options)
14
+ end
15
+
16
+ def parse(yaml_path, _options = {})
17
+ yaml_parse(yaml_path)
18
+ end
19
+
20
+ def yaml_parse(yaml_path)
21
+ yaml_content = YAML.safe_load(File.read(yaml_path))
22
+ serialized_yaml = Lutaml::Uml::Serializers::YamlView
23
+ .new(yaml_content)
24
+ result = Lutaml::Uml::Document.new(serialized_yaml)
25
+ result.classes = imports_to_classes(yaml_content, yaml_path)
26
+ result
27
+ end
28
+
29
+ private
30
+
31
+ def imports_to_classes(yaml_content, yaml_path)
32
+ models_path = File.join(File.dirname(yaml_path), "..", "models")
33
+ yaml_content["imports"].map do |(klass_name, _)|
34
+ klass_attrs = YAML.safe_load(
35
+ File.read(
36
+ File.join(models_path, "#{klass_name}.yml")
37
+ )
38
+ )
39
+ klass_attrs["name"] = klass_name if klass_attrs["name"].nil?
40
+ Lutaml::Uml::Serializers::Class.new(klass_attrs)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Uml
5
+ class Port < Property
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Uml
5
+ class PrimitiveType < DataType
6
+ attr_reader :keyword
7
+
8
+ def initialize(attributes = {})
9
+ super
10
+ @keyword = "primitive"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Uml
5
+ class Property < TopElement
6
+ attr_accessor :type,
7
+ :aggregation,
8
+ :association,
9
+ :is_derived,
10
+ :lowerValue,
11
+ :upperValue
12
+
13
+ def initialize
14
+ @name = nil
15
+ @xmi_id = nil
16
+ @xmi_uuid = nil
17
+ @aggregation = nil
18
+ @association = nil
19
+ @namespace = nil
20
+ @is_derived = false
21
+ @visibility = "public"
22
+ @lowerValue = "1"
23
+ @upperValue = "1"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ ## Behaviour metamodel
5
+ ##
6
+ module Lutaml
7
+ module Uml
8
+ class Pseudostate < Vertex
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ ## Behaviour metamodel
5
+ ##
6
+ module Lutaml
7
+ module Uml
8
+ class Realization < Abstraction
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ ## Behaviour metamodel
5
+ ##
6
+
7
+ module Lutaml
8
+ module Uml
9
+ class Region < TopElement
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/uml/serializers/base"
4
+ require "lutaml/uml/serializers/class"
5
+
6
+ module Lutaml
7
+ module Uml
8
+ module Serializers
9
+ class Association < Base
10
+ property :member_end, from: :target
11
+ property :member_end_attribute_name,
12
+ from: "relationship",
13
+ transform_with: (lambda do |val|
14
+ val.dig("target", "attributes")&.keys&.first ||
15
+ val.dig("target", "attribute")&.keys&.first
16
+ end)
17
+ property :member_end_cardinality,
18
+ from: "relationship",
19
+ transform_with: (lambda do |val|
20
+ res = val.dig("source", "attributes")&.values&.first ||
21
+ val.dig("source", "attribute")&.values&.first
22
+ res["cardinality"] if res
23
+ end)
24
+ property :member_end_type,
25
+ from: "relationship",
26
+ transform_with: (lambda do |val|
27
+ val.dig("target", "type")
28
+ end)
29
+ property :owner_end_attribute_name,
30
+ from: "relationship",
31
+ transform_with: (lambda do |val|
32
+ val.dig("source", "attributes")&.keys&.first ||
33
+ val.dig("source", "attribute")&.keys&.first
34
+ end)
35
+ property :owner_end_cardinality,
36
+ from: "relationship",
37
+ transform_with: (lambda do |val|
38
+ res = val.dig("source", "attributes")&.values&.first ||
39
+ val.dig("source", "attribute")&.values&.first
40
+ res["cardinality"] if res
41
+ end)
42
+ property :owner_end_type,
43
+ from: "relationship",
44
+ transform_with: (lambda do |val|
45
+ val.dig("source", "type")
46
+ end)
47
+ property :action,
48
+ transform_with: (lambda do |val|
49
+ if val["direction"] == "target"
50
+ "#{val['verb']} ▶"
51
+ else
52
+ "◀ #{val['verb']}"
53
+ end
54
+ end)
55
+ end
56
+ end
57
+ end
58
+ end