metanorma-plugin-lutaml 0.7.10 → 0.7.12

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.
@@ -8,6 +8,7 @@ require "lutaml/uml"
8
8
  require "lutaml/xmi"
9
9
  require "metanorma/plugin/lutaml/utils"
10
10
  require "metanorma/plugin/lutaml/asciidoctor/preprocessor"
11
+ require "metanorma/plugin/lutaml/lutaml_ea_xmi_base"
11
12
 
12
13
  module Metanorma
13
14
  module Plugin
@@ -16,288 +17,15 @@ module Metanorma
16
17
  # @example [lutaml_uml_attributes_table,path/to/lutaml,EntityName]
17
18
  class LutamlUmlDatamodelDescriptionPreprocessor <
18
19
  ::Asciidoctor::Extensions::Preprocessor
20
+ include LutamlEaXmiBase
21
+
19
22
  MACRO_REGEXP =
20
23
  /\[lutaml_uml_datamodel_description,([^,]+),?(.+)?\]/.freeze
21
- LIQUID_INCLUDE_PATH = File.join(
22
- Gem.loaded_specs["metanorma-plugin-lutaml"].full_gem_path,
23
- "lib", "metanorma", "plugin", "lutaml", "liquid_templates"
24
- )
25
- DEFAULT_RENDER_INCLUDE = "packages"
26
- RENDER_STYLES_INCLUDES = {
27
- "default" => "packages",
28
- "entity_list" => "packages_entity_list",
29
- "entity_list_class" => "packages_entity_list_class",
30
- "data_dictionary" => "packages_data_dictionary",
31
- }.freeze
32
- RENDER_STYLE_ATTRIBUTE = "render_style"
33
- SUPPORTED_NESTED_MACRO = %w[
34
- before diagram_include_block after include_block package_text
35
- ].freeze
36
- # search document for block `lutaml_uml_datamodel_description`
37
- # read include derectives that goes after that in block and transform
38
- # into yaml2text blocks
39
- def process(document, reader)
40
- r = Asciidoctor::PreprocessorNoIfdefsReader.new document, reader.lines
41
- input_lines = r.readlines.to_enum
42
- Asciidoctor::PreprocessorNoIfdefsReader
43
- .new(document, processed_lines(document, input_lines))
44
- end
45
24
 
46
25
  private
47
26
 
48
- def lutaml_document_from_file_or_cache(document, file_path, yaml_config)
49
- full_path = Utils.relative_file_path(document, file_path)
50
- if document.attributes["lutaml_xmi_cache"] &&
51
- document.attributes["lutaml_xmi_cache"][full_path]
52
- return document.attributes["lutaml_xmi_cache"][full_path]
53
- end
54
-
55
- yaml_config["ea_extension"]&.each do |ea_extension_path|
56
- ea_extension_full_path = File.expand_path(
57
- ea_extension_path, File.dirname(file_path)
58
- )
59
- Xmi::EaRoot.load_extension(ea_extension_full_path)
60
- end
61
-
62
- result_document = ::Lutaml::Parser
63
- .parse(File.new(full_path, encoding: "UTF-8")).first
64
- document.attributes["lutaml_xmi_cache"] ||= {}
65
- document.attributes["lutaml_xmi_cache"][full_path] = result_document
66
- result_document
67
- end
68
-
69
- def parse_yaml_config_file(document, file_path)
70
- return {} if file_path.nil?
71
-
72
- relative_file_path = Utils.relative_file_path(document, file_path)
73
- YAML.safe_load(File.read(relative_file_path, encoding: "UTF-8"))
74
- end
75
-
76
- def processed_lines(document, input_lines)
77
- result = []
78
- loop do
79
- result.push(*process_text_blocks(document, input_lines))
80
- end
81
- result
82
- end
83
-
84
- def process_text_blocks(document, input_lines)
85
- line = input_lines.next
86
- block_match = line.match(MACRO_REGEXP)
87
- return [line] if block_match.nil?
88
-
89
- yaml_config = parse_yaml_config_file(document, block_match[2])
90
- lutaml_document = lutaml_document_from_file_or_cache(document,
91
- block_match[1],
92
- yaml_config)
93
- fill_in_diagrams_attributes(document, lutaml_document)
94
- model_representation(
95
- lutaml_document, document,
96
- collect_additional_context(document, input_lines, input_lines.next),
97
- yaml_config
98
- )
99
- end
100
-
101
- def fill_in_entities_refs_attributes(document, lutaml_document_wrapper,
102
- options)
103
- lutaml_document = lutaml_document_wrapper.original_document
104
- render_style = options.fetch(RENDER_STYLE_ATTRIBUTE, "default")
105
- all_children_packages = lutaml_document.packages
106
- .map(&:children_packages).flatten
107
- package_flat_packages = lambda do |pks|
108
- pks.each_with_object({}) do |package, res|
109
- res[package.name] = package.xmi_id
110
- end
111
- end
112
- children_pks = package_flat_packages.call(all_children_packages)
113
- ref_dictionary = package_flat_packages.call(lutaml_document.packages)
114
- .merge(children_pks)
115
- %w[class enum data_type].each do |type|
116
- package_flat = lambda do |pks|
117
- pks.each_with_object({}) do |package, res|
118
- plural = type == "class" ? "classes" : "#{type}s"
119
- package.send(plural).map do |entity|
120
- res["#{type}:#{package.name}:#{entity.name}"] = entity.xmi_id
121
- end
122
- end
123
- end
124
- children_pks_diags = package_flat.call(all_children_packages)
125
- ref_dictionary = ref_dictionary
126
- .merge(package_flat.call(lutaml_document.packages)
127
- .merge(children_pks_diags))
128
- end
129
- document.attributes["lutaml_entity_id"] = ref_dictionary
130
- end
131
-
132
- def fill_in_diagrams_attributes(document, lutaml_document_wrapper)
133
- lutaml_document = lutaml_document_wrapper.original_document
134
- package_flat_diagrams = lambda do |pks|
135
- pks.each_with_object({}) do |package, res|
136
- package.diagrams.map do |diag|
137
- res["#{package.name}:#{diag.name}"] = diag.xmi_id
138
- end
139
- end
140
- end
141
- children_pks_diags = package_flat_diagrams.call(
142
- lutaml_document.packages.map(&:children_packages).flatten,
143
- )
144
- document.attributes["lutaml_figure_id"] = package_flat_diagrams
145
- .call(lutaml_document.packages)
146
- .merge(children_pks_diags)
147
- end
148
-
149
- def collect_additional_context(document, input_lines, end_mark)
150
- additional_context = Hash.new { |hash, key| hash[key] = [] }
151
- additional_context["all_macros"] = []
152
- block_lines = []
153
- while (block_line = input_lines.next) != end_mark
154
- block_lines.push(block_line)
155
- end
156
- processed_lines =
157
- process(document, ::Asciidoctor::PreprocessorReader.new(
158
- document, block_lines
159
- ))
160
- .read_lines
161
- block_document = ::Asciidoctor::Document
162
- .new(processed_lines, {}).parse
163
- block_document.blocks.each do |block|
164
- next unless SUPPORTED_NESTED_MACRO.include?(block.attributes["role"])
165
-
166
- attrs = block.attributes
167
- name = attrs.delete("role")
168
- package = attrs.delete("package")
169
- macro_keyword = [name, package].compact.join(";")
170
- block_text = block.lines.length.positive? ? block.lines.join("\n") : ""
171
- additional_context[macro_keyword]
172
- .push({ "text" => block_text }.merge(attrs))
173
- additional_context["all_macros"]
174
- .push({ "text" => block_text,
175
- "type" => name, "package" => package }.merge(attrs))
176
- end
177
- additional_context
178
- end
179
-
180
- def package_level(lutaml_document, level)
181
- return lutaml_document if level <= 0
182
-
183
- package_level(lutaml_document["packages"].first, level - 1)
184
- end
185
-
186
- def create_context_object(lutaml_document, additional_context, options)
187
- root_package = package_level(lutaml_document.to_liquid,
188
- options["package_root_level"] || 1)
189
- if options.empty? || options["packages"].nil?
190
- return {
191
- "render_nested_packages" => true,
192
- "packages" => root_package["packages"],
193
- "root_packages" => [root_package],
194
- "additional_context" => additional_context
195
- .merge("external_classes" => options["external_classes"]),
196
- "name" => root_package["name"],
197
- }
198
- end
199
-
200
- all_packages = [root_package, *root_package["children_packages"]]
201
- {
202
- "packages" => sort_and_filter_out_packages(all_packages, options),
203
- "package_entities" => package_entities(options),
204
- "package_skip_sections" => package_skip_sections(options),
205
- "additional_context" => additional_context
206
- .merge("external_classes" => options["external_classes"]),
207
- "root_packages" => [root_package],
208
- "render_nested_packages" => options["render_nested_packages"] ||
209
- false,
210
- "name" => root_package["name"],
211
- }
212
- end
213
-
214
- def package_entities(options)
215
- return {} unless options["packages"]
216
-
217
- options["packages"]
218
- .find_all { |entity| entity.is_a?(Hash) && entity.values.first["render_entities"] }
219
- .map do |entity|
220
- [entity.keys.first,
221
- entity.values.first["render_entities"].map { |n| [n, true] }.to_h]
222
- end.to_h
223
- end
224
-
225
- def package_skip_sections(options)
226
- return {} unless options["packages"]
227
-
228
- options["packages"]
229
- .find_all { |entity| entity.is_a?(Hash) && entity.values.first["skip_tables"] }
230
- .map do |entity|
231
- [entity.keys.first, entity.values.first["skip_tables"].map do |n|
232
- [n, true]
233
- end.to_h]
234
- end.to_h
235
- end
236
-
237
- def sort_and_filter_out_packages(all_packages, options)
238
- return all_packages if options["packages"].nil?
239
-
240
- result = []
241
- # Step one - filter out all skipped packages
242
- options["packages"]
243
- .find_all { |entity| entity.is_a?(Hash) && entity["skip"] }
244
- .each do |entity|
245
- entity_regexp = config_entity_regexp(entity["skip"])
246
- all_packages
247
- .delete_if { |package| package["name"] =~ entity_regexp }
248
- end
249
- # Step two - select supplied packages by pattern
250
- options["packages"]
251
- .find_all { |entity| entity.is_a?(String) || (entity.is_a?(Hash) && !entity["skip"]) }
252
- .each do |entity_obj|
253
- entity = entity_obj.is_a?(String) ? entity_obj : entity_obj.keys.first
254
- entity_regexp = config_entity_regexp(entity)
255
- all_packages.each do |package|
256
- if package["name"]&.match?(entity_regexp)
257
- result.push(package)
258
- all_packages
259
- .delete_if { |nest_package| nest_package["name"] == package["name"] }
260
- end
261
- end
262
- end
263
- result
264
- end
265
-
266
- def config_entity_regexp(entity)
267
- additional_sym = ".*" if /\*$/.match?(entity)
268
- %r{^#{Regexp.escape(entity.delete('*'))}#{additional_sym}$}
269
- end
270
-
271
- def model_representation(lutaml_document, document, additional_context,
272
- options)
273
- fill_in_entities_refs_attributes(document, lutaml_document, options)
274
- render_result, errors = Utils.render_liquid_string(
275
- template_string: template(options["section_depth"] || 2,
276
- options["render_style"],
277
- options["include_root"]),
278
- context_items: create_context_object(lutaml_document,
279
- additional_context,
280
- options),
281
- context_name: "context",
282
- document: document,
283
- include_path: LIQUID_INCLUDE_PATH,
284
- )
285
- Utils.notify_render_errors(document, errors)
286
- render_result.split("\n")
287
- end
288
-
289
- def template(section_depth, render_style, include_root)
290
- include_name = RENDER_STYLES_INCLUDES.fetch(render_style,
291
- DEFAULT_RENDER_INCLUDE)
292
- result = ""
293
- if include_root
294
- result += <<~LIQUID
295
- {% include "#{include_name}", package_skip_sections: context.package_skip_sections, package_entities: context.package_entities, context: context.root_packages, additional_context: context.additional_context, render_nested_packages: false %}
296
- LIQUID
297
- end
298
- result + <<~LIQUID
299
- {% include "#{include_name}", depth: #{section_depth}, package_skip_sections: context.package_skip_sections, package_entities: context.package_entities, context: context, additional_context: context.additional_context, render_nested_packages: context.render_nested_packages %}
300
- LIQUID
27
+ def parse_result_document(full_path, _guidance = nil)
28
+ ::Lutaml::Parser.parse(File.new(full_path, encoding: "UTF-8")).first
301
29
  end
302
30
  end
303
31
  end
@@ -56,8 +56,15 @@ module Metanorma
56
56
  end
57
57
  end
58
58
 
59
- def load_express_repositories(path:, cache_path:, document:, force_read: false)
59
+ def get_original_document(wrapper)
60
+ doc = wrapper
61
+ return doc if doc.instance_of?(::Lutaml::XMI::RootDrop)
60
62
 
63
+ doc.original_document
64
+ end
65
+
66
+ def load_express_repositories(path:, cache_path:, document:,
67
+ force_read: false)
61
68
  cache_full_path = cache_path &&
62
69
  Utils.relative_file_path(document, cache_path)
63
70
 
@@ -73,7 +80,7 @@ module Metanorma
73
80
  if cache_full_path && !File.file?(cache_full_path)
74
81
  save_express_repo_to_cache(
75
82
  cache_full_path,
76
- lutaml_wrapper.original_document,
83
+ get_original_document(lutaml_wrapper),
77
84
  document,
78
85
  )
79
86
  end
@@ -1,7 +1,7 @@
1
1
  module Metanorma
2
2
  module Plugin
3
3
  module Lutaml
4
- VERSION = "0.7.10".freeze
4
+ VERSION = "0.7.12".freeze
5
5
  end
6
6
  end
7
7
  end
@@ -29,14 +29,13 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency "coradoc", "~> 1.1.1"
30
30
  spec.add_dependency "expressir", "~> 1.4.0"
31
31
  spec.add_dependency "liquid"
32
- spec.add_dependency "lutaml", ">= 0.9.4"
33
- spec.add_dependency "ogc-gml"
32
+ spec.add_dependency "lutaml", ">= 0.9.18"
33
+ spec.add_dependency "ogc-gml", "1.0.0"
34
34
  spec.add_dependency "relaton-cli"
35
35
 
36
36
  spec.add_development_dependency "debug"
37
37
  spec.add_development_dependency "equivalent-xml"
38
38
  spec.add_development_dependency "metanorma-standoc"
39
- spec.add_development_dependency "ogc-gml"
40
39
  spec.add_development_dependency "rake", "~> 13"
41
40
  spec.add_development_dependency "rspec", "~> 3.6"
42
41
  spec.add_development_dependency "rspec-html-matchers"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-plugin-lutaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.10
4
+ version: 0.7.12
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-09-23 00:00:00.000000000 Z
11
+ date: 2024-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -72,28 +72,28 @@ dependencies:
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: 0.9.4
75
+ version: 0.9.18
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 0.9.4
82
+ version: 0.9.18
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: ogc-gml
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: 1.0.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: 1.0.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: relaton-cli
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -150,20 +150,6 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: ogc-gml
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
153
  - !ruby/object:Gem::Dependency
168
154
  name: rake
169
155
  requirement: !ruby/object:Gem::Requirement
@@ -332,13 +318,7 @@ files:
332
318
  - lib/metanorma/plugin/lutaml/liquid/multiply_local_file_system.rb
333
319
  - lib/metanorma/plugin/lutaml/liquid_drops/gml_dictionary_drop.rb
334
320
  - lib/metanorma/plugin/lutaml/liquid_drops/gml_dictionary_entry_drop.rb
335
- - lib/metanorma/plugin/lutaml/liquid_drops/klass_table_attribute_drop.rb
336
- - lib/metanorma/plugin/lutaml/liquid_drops/klass_table_content_drop.rb
337
- - lib/metanorma/plugin/lutaml/liquid_drops/klass_table_drop.rb
338
- - lib/metanorma/plugin/lutaml/liquid_drops/klass_table_general_drop.rb
339
321
  - lib/metanorma/plugin/lutaml/liquid_templates/_diagrams_block.liquid
340
- - lib/metanorma/plugin/lutaml/liquid_templates/_klass_assoc_row.liquid
341
- - lib/metanorma/plugin/lutaml/liquid_templates/_klass_row.liquid
342
322
  - lib/metanorma/plugin/lutaml/liquid_templates/_klass_table.liquid
343
323
  - lib/metanorma/plugin/lutaml/liquid_templates/_packages.liquid
344
324
  - lib/metanorma/plugin/lutaml/liquid_templates/_packages_class.liquid
@@ -355,6 +335,7 @@ files:
355
335
  - lib/metanorma/plugin/lutaml/lutaml_diagram_block.rb
356
336
  - lib/metanorma/plugin/lutaml/lutaml_diagram_block_macro.rb
357
337
  - lib/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro.rb
338
+ - lib/metanorma/plugin/lutaml/lutaml_ea_xmi_base.rb
358
339
  - lib/metanorma/plugin/lutaml/lutaml_ea_xmi_preprocessor.rb
359
340
  - lib/metanorma/plugin/lutaml/lutaml_figure_inline_macro.rb
360
341
  - lib/metanorma/plugin/lutaml/lutaml_gml_dictionary_base.rb
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class KlassTableAttributeDrop < Liquid::Drop
4
- LOWER_VALUE_MAPPINGS = {
5
- "C" => "0",
6
- "M" => "1",
7
- }.freeze
8
-
9
- def initialize(attr) # rubocop:disable Lint/MissingSuper
10
- @attr = attr
11
- end
12
-
13
- def id
14
- @attr[:id]
15
- end
16
-
17
- def name
18
- @attr[:name]
19
- end
20
-
21
- def type
22
- @attr[:type]
23
- end
24
-
25
- def xmi_id
26
- @attr[:xmi_id]
27
- end
28
-
29
- def is_derived
30
- @attr[:is_derived]
31
- end
32
-
33
- def cardinality
34
- min = @attr[:cardinality]["min"]
35
- min = min.nil? ? nil : LOWER_VALUE_MAPPINGS[min]
36
-
37
- "#{min}..#{@attr[:cardinality]['max']}"
38
- end
39
-
40
- def definition
41
- @attr[:definition]
42
- end
43
-
44
- def association
45
- @attr[:association]
46
- end
47
-
48
- def has_association?
49
- !!@attr[:association]
50
- end
51
-
52
- def upper_klass
53
- @attr[:upper_klass]
54
- end
55
-
56
- def name_ns
57
- @attr[:name_ns]
58
- end
59
-
60
- def type_ns
61
- @attr[:type_ns]
62
- end
63
-
64
- def gen_name
65
- @attr[:gen_name]
66
- end
67
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class KlassTableContentDrop < Liquid::Drop
4
- def initialize(content) # rubocop:disable Lint/MissingSuper
5
- @content = content
6
- end
7
-
8
- def owned_props
9
- @content[:owned_props]
10
- end
11
-
12
- def assoc_props
13
- @content[:assoc_props]
14
- end
15
-
16
- def inherited_props
17
- @content[:inherited_props]
18
- end
19
-
20
- def inherited_assoc_props
21
- @content[:inherited_assoc_props]
22
- end
23
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class KlassTableDrop < Liquid::Drop
4
- def initialize(klass) # rubocop:disable Lint/MissingSuper
5
- @klass = klass
6
- end
7
-
8
- def id
9
- @klass[:general_id]
10
- end
11
-
12
- def name
13
- @klass[:name]
14
- end
15
-
16
- def stereotype
17
- @klass[:stereotype]
18
- end
19
-
20
- def definition
21
- @klass[:definition]
22
- end
23
-
24
- def type
25
- @klass[:type]
26
- end
27
-
28
- def upper_klass
29
- @klass[:general_upper_klass]
30
- end
31
-
32
- def general
33
- KlassTableGeneralDrop.new(@klass[:general]) if @klass[:general]
34
- end
35
-
36
- def has_general?
37
- !!@klass[:general]
38
- end
39
-
40
- def attributes
41
- @klass[:general_attributes].map do |attr|
42
- KlassTableAttributeDrop.new(attr)
43
- end
44
- end
45
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class KlassTableGeneralDrop < Liquid::Drop
4
- def initialize(gen) # rubocop:disable Lint/MissingSuper
5
- @gen = gen
6
- end
7
-
8
- def id
9
- @gen[:general_id]
10
- end
11
-
12
- def name
13
- @gen[:general_name]
14
- end
15
-
16
- def upper_klass
17
- @gen[:general_upper_klass]
18
- end
19
-
20
- def general
21
- KlassTableGeneralDrop.new(@gen[:general]) if @gen[:general]
22
- end
23
-
24
- def has_general?
25
- !!@gen[:general]
26
- end
27
-
28
- def attributes
29
- @gen[:general_attributes].map do |attr|
30
- KlassTableAttributeDrop.new(attr)
31
- end
32
- end
33
- end
@@ -1,11 +0,0 @@
1
- {%- for attr in attributes -%}
2
- {%- if attr.has_association? != false -%}
3
- {%- capture name_col -%}
4
- {{ attr.name_ns }}:{{ attr.name }}
5
- ({{ attr.gen_name }})
6
- {%- endcapture -%}
7
- | {{ name_col | newline_to_br }}
8
- | {{ attr.type_ns }}:{{ attr.type }} [{{ attr.cardinality }}]
9
- | {{ attr.definition }}
10
- {%- endif -%}
11
- {%- endfor -%}
@@ -1,11 +0,0 @@
1
- {%- for attr in attributes -%}
2
- {%- if attr.has_association? == false -%}
3
- {%- capture name_col -%}
4
- {{ attr.name_ns }}:{{ attr.name }}
5
- ({{ attr.gen_name }})
6
- {%- endcapture -%}
7
- | {{ name_col | newline_to_br }}
8
- | {{ attr.type }} [{{ attr.cardinality }}]
9
- | {{ attr.definition }}
10
- {%- endif -%}
11
- {%- endfor -%}