metanorma-plugin-lutaml 0.7.10 → 0.7.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 -%}