lutaml 0.9.8 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d1677e27d1216994f6619acc558721d9b2d6107dd30fd6776232965d6d1d219
4
- data.tar.gz: e8999116cdee14d6316f9bedaa781893ae2d27b88f93aef514fdda435e8d29b6
3
+ metadata.gz: 59f3f41813beaec8f6ffe17b8077aa9ad9d0a1a49861d12075b86e579e4d8287
4
+ data.tar.gz: f52b06e26ebecc5088248fa0d83696bfae5d26b6b2c31d32bca1d3210db5493d
5
5
  SHA512:
6
- metadata.gz: 37c0d7fb4a3676a45fc8ebbab3bfab3e993ad84e005a8a7d642a1af66c3600271d1a03b723a2b7ff8462a96a75605c5bce06425393047c9fcdcd16c38c1b603f
7
- data.tar.gz: e287823e6e238754223823ccabaebe31f13332b26efb67ac97d1c3f103cdf512f5a7be9276653f826983fe87e991b221772115b1c3d0bb09bb5745db1f2b0dd2
6
+ metadata.gz: f0b91cc8fcf077286165cb879a9896f401ccd45f72db55fb8a2ef0f89aca841f7d57bdf581194f3487f2f8edfc83103c68b174f36f95cdaa4710d2303ac01d64
7
+ data.tar.gz: e16c5a41385564b5e9c3c89850114daa5e8ff0ae1a0a4bac5ed5f12c40155d4164c087e74b1e80841ab8a5d58af305ab6caa621f93a321f97fe44fa0604960f2
@@ -1,3 +1,3 @@
1
1
  module Lutaml
2
- VERSION = "0.9.8".freeze
2
+ VERSION = "0.9.10".freeze
3
3
  end
@@ -16,20 +16,37 @@ module Lutaml
16
16
  }.freeze
17
17
  attr_reader :xmi_cache, :xmi_root_model
18
18
 
19
- # @param xml [String] path to xml
20
- # @param options [Hash] options for parsing
21
- # @return [Lutaml::Uml::Document]
22
- def self.parse(xml, _options = {})
23
- sparx_root = Xmi::Sparx::SparxRoot
24
- xmi_doc = Nokogiri::XML(File.read(xml))
25
- namespace = xmi_doc.at_xpath("//xmi:XMI").namespaces
26
- if namespace["xmlns:uml"].split("/").last == "20131001"
27
- sparx_root = Xmi::Sparx::SparxRoot2013
19
+ class << self
20
+ # @param xml [String] path to xml
21
+ # @param options [Hash] options for parsing
22
+ # @return [Lutaml::Uml::Document]
23
+ def parse(xml, _options = {})
24
+ xmi_model = get_xmi_model(xml)
25
+ new.parse(xmi_model)
26
+ end
27
+
28
+ # @param xml [String] path to xml
29
+ # @return [Hash]
30
+ def serialize_xmi(xml)
31
+ xmi_model = get_xmi_model(xml)
32
+ new.serialize_xmi(xmi_model)
33
+ end
34
+
35
+ # @param xml [String] path to xml
36
+ # @param name [String]
37
+ # @return [Hash]
38
+ def serialize_generalization_by_name(xml, name)
39
+ xmi_model = get_xmi_model(xml)
40
+ new.serialize_generalization_by_name(xmi_model, name)
28
41
  end
29
42
 
30
- xml_content = File.read(xml)
31
- xmi_model = sparx_root.from_xml(xml_content)
32
- new.parse(xmi_model)
43
+ private
44
+
45
+ # @param xml [String]
46
+ # @return [Shale::Mapper]
47
+ def get_xmi_model(xml)
48
+ Xmi::Sparx::SparxRoot.parse_xml(File.read(xml))
49
+ end
33
50
  end
34
51
 
35
52
  # @param xmi_model [Shale::Mapper]
@@ -37,7 +54,27 @@ module Lutaml
37
54
  def parse(xmi_model)
38
55
  @xmi_cache = {}
39
56
  @xmi_root_model = xmi_model
40
- ::Lutaml::Uml::Document.new(serialize_to_hash(xmi_model))
57
+ serialized_hash = serialize_xmi(xmi_model)
58
+
59
+ ::Lutaml::Uml::Document.new(serialized_hash)
60
+ end
61
+
62
+ # @param xmi_model [Shale::Mapper]
63
+ # return [Hash]
64
+ def serialize_xmi(xmi_model)
65
+ @xmi_cache = {}
66
+ @xmi_root_model = xmi_model
67
+ serialize_to_hash(xmi_model)
68
+ end
69
+
70
+ # @param xmi_model [Shale::Mapper]
71
+ # @param name [String]
72
+ # @return [Hash]
73
+ def serialize_generalization_by_name(xmi_model, name)
74
+ @xmi_cache = {}
75
+ @xmi_root_model = xmi_model
76
+ klass = find_klass_packaged_element_by_name(name)
77
+ serialize_generalization(klass)
41
78
  end
42
79
 
43
80
  private
@@ -112,6 +149,138 @@ module Lutaml
112
149
  end
113
150
  end
114
151
 
152
+ # @param klass [Shale::Mapper]
153
+ # # @return [Hash]
154
+ def serialize_generalization(klass)
155
+ general_hash, next_general_node_id = get_top_level_general_hash(klass)
156
+ return general_hash unless next_general_node_id
157
+
158
+ general_hash[:general] = serialize_generalization_attributes(
159
+ next_general_node_id,
160
+ )
161
+
162
+ general_hash
163
+ end
164
+
165
+ # @param klass [Shale::Mapper]
166
+ # @return [Array<Hash>]
167
+ def get_top_level_general_hash(klass) # rubocop:disable Metrics/AbcSize
168
+ general_hash, next_general_node_id = get_general_hash(klass.id)
169
+ general_hash[:name] = klass.name
170
+ general_hash[:type] = klass.type
171
+ general_hash[:definition] = lookup_general_documentation(klass.id)
172
+ general_hash[:stereotype] = doc_node_attribute_value(
173
+ klass.id, "stereotype"
174
+ )
175
+
176
+ # update_inherited_attributes(general_hash)
177
+ # update_gen_attributes(general_hash)
178
+
179
+ [general_hash, next_general_node_id]
180
+ end
181
+
182
+ def lookup_general_documentation(klass_id)
183
+ # lookup_attribute_documentation(klass_id) ||
184
+ # lookup_element_prop_documentation(klass_id)
185
+
186
+ lookup_element_prop_documentation(klass_id)
187
+ end
188
+
189
+ def update_gen_attributes(general_hash)
190
+ general_hash[:gen_attributes] = serialize_gen_attributes
191
+ end
192
+
193
+ def update_inherited_attributes(general_hash)
194
+ general_hash[:gml_attributes] = serialize_gml_attributes
195
+ general_hash[:core_attributes] = serialize_core_attributes
196
+ end
197
+
198
+ # @param xmi_id [String]
199
+ # @param model [Shale::Mapper]
200
+ # @return [Array<Hash>]
201
+ # @note get generalization node and its owned attributes
202
+ def serialize_generalization_attributes(general_id)
203
+ general_hash, next_general_node_id = get_general_hash(general_id)
204
+
205
+ if next_general_node_id
206
+ general_hash[:general] = serialize_generalization_attributes(
207
+ next_general_node_id,
208
+ )
209
+ end
210
+
211
+ general_hash
212
+ end
213
+
214
+ # @param xmi_id [String]
215
+ # @return [Shale::Mapper]
216
+ def get_general_node(xmi_id)
217
+ find_packaged_element_by_id(xmi_id)
218
+ end
219
+
220
+ # @param general_node [Shale::Mapper]
221
+ # # @return [Hash]
222
+ def get_general_attributes(general_node)
223
+ attrs = serialize_class_attributes(general_node, with_assoc: true)
224
+ attrs.sort_by { |i| i[:name] }
225
+ end
226
+
227
+ # @param general_node [Shale::Mapper]
228
+ # @return [String]
229
+ def get_next_general_node_id(general_node)
230
+ general_node.generalization.first&.general
231
+ end
232
+
233
+ # @param general_id [String]
234
+ # @return [Array<Hash>]
235
+ def get_general_hash(general_id)
236
+ general_node = get_general_node(general_id)
237
+ general_node_attrs = get_general_attributes(general_node)
238
+ general_upper_klass = find_upper_level_packaged_element(general_id)
239
+ next_general_node_id = get_next_general_node_id(general_node)
240
+
241
+ [
242
+ {
243
+ general_id: general_id,
244
+ general_name: general_node.name,
245
+ general_attributes: general_node_attrs,
246
+ general_upper_klass: general_upper_klass,
247
+ general: {},
248
+ },
249
+ next_general_node_id,
250
+ ]
251
+ end
252
+
253
+ # @param id [String]
254
+ # @return [Shale::Mapper]
255
+ def find_packaged_element_by_id(id)
256
+ all_packaged_elements.find { |e| e.id == id }
257
+ end
258
+
259
+ # @param id [String]
260
+ # @return [Shale::Mapper]
261
+ def find_upper_level_packaged_element(klass_id)
262
+ upper_klass = all_packaged_elements.find do |e|
263
+ e.packaged_element.find { |pe| pe.id == klass_id }
264
+ end
265
+ upper_klass&.name
266
+ end
267
+
268
+ # @param name [String]
269
+ # @return [Shale::Mapper]
270
+ def find_klass_packaged_element_by_name(name)
271
+ all_packaged_elements.find do |e|
272
+ e.type?("uml:Class") && e.name == name
273
+ end
274
+ end
275
+
276
+ # @param name [String]
277
+ # @return [Shale::Mapper]
278
+ def find_packaged_element_by_name(name)
279
+ all_packaged_elements.find do |e|
280
+ e.name == name
281
+ end
282
+ end
283
+
115
284
  # @param package [Shale::Mapper]
116
285
  # @return [Array<Hash>]
117
286
  # @note xpath ./packagedElement[@xmi:type="uml:Enumeration"]
@@ -233,9 +402,9 @@ module Lutaml
233
402
  # @return [Shale::Mapper]
234
403
  # @note xpath %(//connector[@xmi:idref="#{link_id}"])
235
404
  def fetch_connector(link_id)
236
- @xmi_root_model.extension.connectors.connector.select do |con|
405
+ @xmi_root_model.extension.connectors.connector.find do |con|
237
406
  con.idref == link_id
238
- end.first
407
+ end
239
408
  end
240
409
 
241
410
  # @param link_id [String]
@@ -435,9 +604,9 @@ module Lutaml
435
604
  all_elements = all_packaged_elements
436
605
 
437
606
  owned_attributes = all_elements.map(&:owned_attribute).flatten
438
- oa = owned_attributes.select do |a|
607
+ oa = owned_attributes.find do |a|
439
608
  !!a.association && a.uml_type && a.uml_type.idref == xmi_id
440
- end.first
609
+ end
441
610
 
442
611
  if oa
443
612
  cardinality = cardinality_min_max_value(
@@ -453,37 +622,104 @@ module Lutaml
453
622
  # @return [Shale::Mapper]
454
623
  # @note xpath %(//element[@xmi:idref="#{klass['xmi:id']}"])
455
624
  def fetch_element(klass_id)
456
- @xmi_root_model.extension.elements.element.select do |e|
625
+ @xmi_root_model.extension.elements.element.find do |e|
457
626
  e.idref == klass_id
458
- end.first
627
+ end
459
628
  end
460
629
 
461
630
  # @param klass [Shale::Mapper]
631
+ # @param with_assoc [Boolean]
462
632
  # @return [Array<Hash>]
463
633
  # @note xpath .//ownedAttribute[@xmi:type="uml:Property"]
464
- def serialize_class_attributes(klass)
634
+ def serialize_class_attributes(klass, with_assoc: false)
465
635
  klass.owned_attribute.select { |attr| attr.type?("uml:Property") }
466
636
  .map do |oa|
467
- uml_type = oa.uml_type
468
- uml_type_idref = uml_type.idref if uml_type
637
+ if with_assoc || oa.association.nil?
638
+ attrs = build_class_attributes(oa)
469
639
 
470
- if oa.association.nil?
471
- {
472
- id: oa.id,
473
- name: oa.name,
474
- type: lookup_entity_name(uml_type_idref) || uml_type_idref,
475
- xmi_id: uml_type_idref,
476
- is_derived: oa.is_derived,
477
- cardinality: cardinality_min_max_value(
478
- oa.lower_value&.value,
479
- oa.upper_value&.value,
480
- ),
481
- definition: lookup_attribute_documentation(oa.id),
482
- }
640
+ if with_assoc && oa.association
641
+ attrs[:association] = oa.association
642
+ attrs[:definition] = loopup_assoc_def(oa.association)
643
+ attrs[:type_ns] = get_ns_by_type(attrs[:type])
644
+ end
645
+
646
+ attrs
483
647
  end
484
648
  end.compact
485
649
  end
486
650
 
651
+ def loopup_assoc_def(association)
652
+ connector = fetch_connector(association)
653
+ connector&.documentation&.value
654
+ end
655
+
656
+ # @return [Array<Hash>]
657
+ def serialize_gml_attributes
658
+ element = find_packaged_element_by_name("_Feature")
659
+ attrs = serialize_class_attributes(element, with_assoc: true)
660
+ attrs.each { |attr| attr[:upper_klass] = "gml" }
661
+ end
662
+
663
+ # @return [Array<Hash>]
664
+ def serialize_core_attributes
665
+ element = find_packaged_element_by_name("_CityObject")
666
+ attrs = serialize_class_attributes(element, with_assoc: false)
667
+ attrs.each { |attr| attr[:upper_klass] = "core" }
668
+ end
669
+
670
+ # @return [Array<Hash>]
671
+ def select_gen_attributes
672
+ element = find_packaged_element_by_name("gen")
673
+ gen_attr_element = find_packaged_element_by_name("_genericAttribute")
674
+
675
+ element.packaged_element.select do |e|
676
+ e.type?("uml:Class") &&
677
+ e.generalization&.first&.general == gen_attr_element.id
678
+ end
679
+ end
680
+
681
+ # @return [Array<Hash>]
682
+ def serialize_gen_attributes
683
+ klasses = select_gen_attributes
684
+
685
+ klasses.map do |klass|
686
+ attr = serialize_class_attributes(klass, with_assoc: false)
687
+ attr.first[:name] = klass.name
688
+ attr.first[:type] = "gen:#{klass.name}"
689
+ attr.first[:upper_klass] = "gen"
690
+ attr
691
+ end.flatten!
692
+ end
693
+
694
+ # @param type [String]
695
+ # @return [String]
696
+ def get_ns_by_type(type)
697
+ return unless type
698
+
699
+ p = find_klass_packaged_element_by_name(type)
700
+ find_upper_level_packaged_element(p.id)
701
+ end
702
+
703
+ # @param klass_id [String]
704
+ # @return [Array<Hash>]
705
+ def build_class_attributes(owned_attr) # rubocop:disable Metrics/MethodLength
706
+ uml_type = owned_attr.uml_type
707
+ uml_type_idref = uml_type.idref if uml_type
708
+
709
+ {
710
+ id: owned_attr.id,
711
+ name: owned_attr.name,
712
+ type: lookup_entity_name(uml_type_idref) || uml_type_idref,
713
+ xmi_id: uml_type_idref,
714
+ is_derived: owned_attr.is_derived,
715
+ cardinality: cardinality_min_max_value(
716
+ owned_attr.lower_value&.value,
717
+ owned_attr.upper_value&.value,
718
+ ),
719
+ definition: lookup_attribute_documentation(owned_attr.id),
720
+ }
721
+ end
722
+
487
723
  # @param min [String]
488
724
  # @param max [String]
489
725
  # @return [Hash]
@@ -540,6 +776,18 @@ module Lutaml
540
776
  attribute_node&.documentation&.value
541
777
  end
542
778
 
779
+ # @param xmi_id [String]
780
+ # @return [String]
781
+ def lookup_element_prop_documentation(xmi_id)
782
+ element_node = @xmi_root_model.extension.elements.element.find do |e|
783
+ e.idref == xmi_id
784
+ end
785
+
786
+ return unless element_node&.properties
787
+
788
+ element_node&.properties&.documentation
789
+ end
790
+
543
791
  # @param xmi_id [String]
544
792
  # @return [String]
545
793
  def lookup_entity_name(xmi_id)
@@ -630,8 +878,7 @@ module Lutaml
630
878
  def select_all_packaged_elements(all_elements, model, type)
631
879
  select_all_items(all_elements, model, type, :packaged_element)
632
880
  all_elements.delete_if do |e|
633
- !e.is_a?(Xmi::Uml::PackagedElement) &&
634
- !e.is_a?(Xmi::Uml::PackagedElement2013)
881
+ !e.is_a?(Xmi::Uml::PackagedElement)
635
882
  end
636
883
  end
637
884
 
data/lutaml.gemspec CHANGED
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_runtime_dependency "parslet", "~> 2.0.0"
37
37
  spec.add_runtime_dependency "ruby-graphviz", "~> 1.2"
38
38
  spec.add_runtime_dependency "thor", "~> 1.0"
39
- spec.add_runtime_dependency "xmi", ">= 0.3.8"
39
+ spec.add_runtime_dependency "xmi", "~> 0.3.10"
40
40
 
41
41
  spec.add_development_dependency "byebug"
42
42
  spec.add_development_dependency "equivalent-xml", "~> 0.6.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.8
4
+ version: 0.9.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: 2024-07-30 00:00:00.000000000 Z
11
+ date: 2024-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: expressir
@@ -112,16 +112,16 @@ dependencies:
112
112
  name: xmi
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.3.8
117
+ version: 0.3.10
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.3.8
124
+ version: 0.3.10
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: byebug
127
127
  requirement: !ruby/object:Gem::Requirement