stepmod-utils 0.3.22 → 0.3.24
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/.rubocop.yml +3 -0
- data/exe/stepmod-annotate-all +1 -1
- data/exe/stepmod-extract-terms +14 -6
- data/exe/stepmod-extract-yaml-terms +149 -0
- data/lib/stepmod/utils/concept.rb +42 -12
- data/lib/stepmod/utils/converters/express_figure.rb +25 -0
- data/lib/stepmod/utils/converters/express_table.rb +25 -0
- data/lib/stepmod/utils/converters/figure.rb +19 -1
- data/lib/stepmod/utils/converters/module_ref.rb +55 -17
- data/lib/stepmod/utils/converters/module_ref_express_description.rb +44 -2
- data/lib/stepmod/utils/converters/table.rb +14 -1
- data/lib/stepmod/utils/express_bibdata.rb +111 -0
- data/lib/stepmod/utils/smrl_description_converter.rb +1 -0
- data/lib/stepmod/utils/smrl_resource_converter.rb +2 -1
- data/lib/stepmod/utils/stepmod_definition_converter.rb +1 -0
- data/lib/stepmod/utils/stepmod_file_annotator.rb +236 -12
- data/lib/stepmod/utils/term.rb +18 -5
- data/lib/stepmod/utils/terms_extractor.rb +253 -298
- data/lib/stepmod/utils/version.rb +1 -1
- data/stepmod-utils.gemspec +2 -1
- metadata +25 -6
@@ -1,11 +1,12 @@
|
|
1
1
|
require "stepmod/utils/stepmod_definition_converter"
|
2
|
-
require "stepmod/utils/
|
2
|
+
require "stepmod/utils/express_bibdata"
|
3
3
|
require "stepmod/utils/concept"
|
4
4
|
require "glossarist"
|
5
5
|
require "securerandom"
|
6
6
|
require "expressir"
|
7
7
|
require "expressir/express/parser"
|
8
8
|
require "indefinite_article"
|
9
|
+
require "pubid-iso"
|
9
10
|
|
10
11
|
ReverseAdoc.config.unknown_tags = :bypass
|
11
12
|
|
@@ -38,13 +39,15 @@ module Stepmod
|
|
38
39
|
@stepmod_dir = stepmod_dir
|
39
40
|
@stepmod_path = Pathname.new(stepmod_dir).realpath
|
40
41
|
@index_path = Pathname.new(index_path).to_s
|
41
|
-
@general_concepts = Glossarist::
|
42
|
-
@resource_concepts = Glossarist::
|
42
|
+
@general_concepts = Glossarist::ManagedConceptCollection.new
|
43
|
+
@resource_concepts = Glossarist::ManagedConceptCollection.new
|
43
44
|
@parsed_bibliography = []
|
45
|
+
@added_bibdata = {}
|
44
46
|
@part_concepts = []
|
45
|
-
@part_resources =
|
46
|
-
@part_modules =
|
47
|
+
@part_resources = {}
|
48
|
+
@part_modules = {}
|
47
49
|
@encountered_terms = {}
|
50
|
+
@sequence = 0
|
48
51
|
end
|
49
52
|
|
50
53
|
def log(message)
|
@@ -80,313 +83,282 @@ module Stepmod
|
|
80
83
|
repo_index.xpath("//module").each do |x|
|
81
84
|
next if x['status'] == WITHDRAWN_STATUS
|
82
85
|
|
83
|
-
|
84
|
-
|
86
|
+
arm_path = Pathname.new("#{stepmod_dir}/modules/#{x['name']}/arm_annotated.exp")
|
87
|
+
mim_path = Pathname.new("#{stepmod_dir}/modules/#{x['name']}/mim_annotated.exp")
|
88
|
+
|
89
|
+
files << arm_path if File.exists? arm_path
|
90
|
+
files << mim_path if File.exists? mim_path
|
85
91
|
end
|
86
92
|
|
87
|
-
#
|
88
|
-
|
89
|
-
|
93
|
+
# Should ignore these because the `<resource_docs>` elements do not provide any EXPRESS schemas
|
94
|
+
# # add resource_docs paths
|
95
|
+
# repo_index.xpath("//resource_doc").each do |x|
|
96
|
+
# next if x['status'] == WITHDRAWN_STATUS
|
90
97
|
|
91
|
-
|
92
|
-
|
93
|
-
end
|
98
|
+
# path = Pathname.new("#{stepmod_dir}/resource_docs/#{x['name']}/resource.xml")
|
99
|
+
# files << path if File.exists? path
|
100
|
+
# end
|
94
101
|
|
95
|
-
# add
|
96
|
-
repo_index.xpath("//
|
102
|
+
# add resource paths
|
103
|
+
repo_index.xpath("//resource").each do |x|
|
97
104
|
next if x['status'] == WITHDRAWN_STATUS
|
98
105
|
|
99
|
-
path = Pathname.new("#{stepmod_dir}/
|
106
|
+
path = Pathname.new("#{stepmod_dir}/resources/#{x['name']}/#{x['name']}_annotated.exp")
|
100
107
|
files << path if File.exists? path
|
101
108
|
end
|
102
109
|
|
103
|
-
#
|
104
|
-
|
105
|
-
|
110
|
+
# Should ignore these because we are skiping Clause 3 terms
|
111
|
+
# add business_object_models paths
|
112
|
+
# repo_index.xpath("//business_object_model").each do |x|
|
113
|
+
# next if x['status'] == WITHDRAWN_STATUS
|
114
|
+
|
115
|
+
# annotated_path = Pathname.new("#{stepmod_dir}/business_object_models/#{x['name']}/bom_annotated.exp")
|
116
|
+
# path = Pathname.new("#{stepmod_dir}/business_object_models/#{x['name']}/bom.exp")
|
117
|
+
# files << if File.exists?(annotated_path)
|
118
|
+
# annotated_path
|
119
|
+
# elsif File.exists?(path)
|
120
|
+
# path
|
121
|
+
# end
|
122
|
+
# end
|
106
123
|
|
107
|
-
|
108
|
-
|
109
|
-
|
124
|
+
# Should ignore these because there are no EXPRESS schemas here (they are implemented inside modules
|
125
|
+
# # add application_protocols paths
|
126
|
+
# repo_index.xpath("//application_protocol").each do |x|
|
127
|
+
# next if x['status'] == WITHDRAWN_STATUS
|
110
128
|
|
111
|
-
|
129
|
+
# path = Pathname.new("#{stepmod_dir}/application_protocols/#{x['name']}/application_protocol.xml")
|
130
|
+
# files << path if File.exists? path
|
131
|
+
# end
|
132
|
+
|
133
|
+
files.compact.sort!.uniq!
|
112
134
|
process_term_files(files)
|
113
135
|
|
114
136
|
[
|
115
|
-
general_concepts,
|
137
|
+
general_concepts, # Should be empty because skiping all Clause 3 terms
|
116
138
|
resource_concepts,
|
117
139
|
parsed_bibliography,
|
118
|
-
part_concepts,
|
119
|
-
part_resources,
|
120
|
-
part_modules,
|
140
|
+
part_concepts, # Should be empty because skiping all Clause 3 terms
|
141
|
+
part_resources.values.compact,
|
142
|
+
part_modules.values.compact,
|
121
143
|
]
|
122
144
|
end
|
123
145
|
|
124
146
|
private
|
125
147
|
|
126
148
|
def process_term_files(files)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
149
|
+
repo = Expressir::Express::Parser.from_files(files)
|
150
|
+
|
151
|
+
repo.schemas.each do |schema|
|
152
|
+
parsed_schema_names = {}
|
131
153
|
|
132
|
-
|
133
|
-
|
154
|
+
schema_name = schema.id
|
155
|
+
file_path = schema.file
|
156
|
+
type = extract_file_type(file_path)
|
157
|
+
|
158
|
+
if parsed_schema_names[schema_name]
|
159
|
+
log <<~ERROR.gsub("\n", " ")
|
160
|
+
ERROR: We have encountered this schema before: #{schema_name} from
|
161
|
+
path #{parsed_schema_names[schema_name]}, now at #{schema.file}
|
162
|
+
ERROR
|
163
|
+
|
164
|
+
next
|
165
|
+
else
|
166
|
+
parsed_schema_names[schema_name] = file_path
|
167
|
+
end
|
168
|
+
|
169
|
+
log "INFO: Processing schema: #{schema.id}"
|
134
170
|
|
135
|
-
bibdata = nil
|
136
171
|
begin
|
137
|
-
bibdata = Stepmod::Utils::
|
138
|
-
rescue
|
139
|
-
log
|
172
|
+
bibdata = Stepmod::Utils::ExpressBibdata.new(schema: schema)
|
173
|
+
rescue => e
|
174
|
+
log e
|
175
|
+
log "ERROR: while processing bibdata for `#{schema_name}`"
|
176
|
+
|
140
177
|
next
|
141
178
|
end
|
142
179
|
|
143
180
|
unless ACCEPTED_STAGES.include? bibdata.doctype
|
144
|
-
log "INFO: skipped #{bibdata.
|
145
|
-
|
181
|
+
log "INFO: skipped #{bibdata.doctype} as it is not " \
|
182
|
+
"one of (#{ACCEPTED_STAGES.join(', ')})."
|
146
183
|
next
|
147
184
|
end
|
148
185
|
|
149
186
|
if bibdata.part.to_s.empty?
|
150
|
-
log "FATAL: missing `part` attribute: #{
|
151
|
-
log "INFO:
|
187
|
+
log "FATAL: missing `part` attribute: #{file_path}"
|
188
|
+
log "INFO: skipped #{schema.id} as it is missing `part` attribute."
|
152
189
|
next
|
153
190
|
end
|
154
191
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
end
|
163
|
-
encountered_terms[term_id] = true
|
164
|
-
end
|
165
|
-
|
166
|
-
# Assume that definition is located in clause 3 of the ISO document
|
167
|
-
# in order. We really don't have a good reference here.
|
168
|
-
ref_clause = "3.#{definition_index}"
|
169
|
-
|
170
|
-
concept = Stepmod::Utils::Concept.parse(
|
171
|
-
definition,
|
172
|
-
reference_anchor: bibdata.anchor,
|
173
|
-
reference_clause: ref_clause,
|
174
|
-
file_path: fpath,
|
175
|
-
)
|
176
|
-
next unless concept
|
177
|
-
|
178
|
-
if term_special_category(bibdata)
|
179
|
-
# log "INFO: this part is special"
|
180
|
-
find_or_initialize_concept(current_part_concepts, concept)
|
181
|
-
else
|
182
|
-
# log "INFO: this part is generic"
|
183
|
-
find_or_initialize_concept(general_concepts, concept)
|
184
|
-
end
|
185
|
-
|
186
|
-
parsed_bibliography << bibdata
|
187
|
-
end
|
188
|
-
|
189
|
-
current_part_resources = Glossarist::Collection.new
|
190
|
-
current_part_modules_arm = {}
|
191
|
-
current_part_modules_mim = {}
|
192
|
-
|
193
|
-
# log "INFO: FILE PATH IS #{file_path}"
|
194
|
-
case file_path.to_s
|
195
|
-
when /resource.xml$/
|
196
|
-
log "INFO: Processing resource.xml for #{fpath}"
|
197
|
-
|
198
|
-
current_document.xpath("//schema").each do |schema_node|
|
199
|
-
schema_name = schema_node["name"]
|
200
|
-
if parsed_schema_names[schema_name]
|
201
|
-
log "ERROR: We have encountered this schema before: \
|
202
|
-
#{schema_name} from path \
|
203
|
-
#{parsed_schema_names[schema_name]}, now at #{file_path}"
|
204
|
-
next
|
205
|
-
else
|
206
|
-
parsed_schema_names[schema_name] = file_path
|
207
|
-
end
|
208
|
-
|
209
|
-
exp_annotated_path =
|
210
|
-
"#{stepmod_path}/resources/#{schema_name}/#{schema_name}_annotated.exp"
|
211
|
-
|
212
|
-
log "INFO: Processing resources schema #{exp_annotated_path}"
|
213
|
-
|
214
|
-
if File.exists?(exp_annotated_path)
|
215
|
-
repo = Expressir::Express::Parser.from_file(exp_annotated_path)
|
216
|
-
schema = repo.schemas.first
|
217
|
-
|
218
|
-
schema.entities.each do |entity|
|
219
|
-
old_definition = entity.remarks.first
|
220
|
-
|
221
|
-
domain = "resource: #{schema.id}"
|
222
|
-
entity_definition = generate_entity_definition(entity, domain, old_definition)
|
223
|
-
|
224
|
-
reference_anchor = bibdata.anchor
|
225
|
-
reference_clause = nil
|
226
|
-
|
227
|
-
concept = Stepmod::Utils::Concept.new(
|
228
|
-
designations: [entity.id],
|
229
|
-
definition: old_definition,
|
230
|
-
converted_definition: entity_definition,
|
231
|
-
id: "#{reference_anchor}.#{reference_clause}",
|
232
|
-
reference_anchor: reference_anchor,
|
233
|
-
reference_clause: reference_clause,
|
234
|
-
file_path: Pathname.new(exp_annotated_path)
|
235
|
-
.relative_path_from(stepmod_path),
|
236
|
-
language_code: "en",
|
237
|
-
)
|
238
|
-
|
239
|
-
next unless concept
|
240
|
-
|
241
|
-
if term_special_category(bibdata)
|
242
|
-
# log "INFO: this part is special"
|
243
|
-
find_or_initialize_concept(current_part_resources, concept)
|
244
|
-
else
|
245
|
-
# log "INFO: this part is generic"
|
246
|
-
find_or_initialize_concept(resource_concepts, concept)
|
247
|
-
end
|
248
|
-
|
249
|
-
parsed_bibliography << bibdata
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
when /module.xml$/
|
255
|
-
log "INFO: Processing module.xml for #{fpath}"
|
256
|
-
# Assumption: every schema is only linked by a single module document.
|
257
|
-
# puts current_document.xpath('//module').length
|
258
|
-
schema_name = current_document.xpath("//module").first["name"]
|
259
|
-
if parsed_schema_names[schema_name]
|
260
|
-
log "ERROR: We have encountered this schema before: \
|
261
|
-
#{schema_name} from path #{parsed_schema_names[schema_name]}, \
|
262
|
-
now at #{file_path}"
|
263
|
-
next
|
264
|
-
else
|
265
|
-
parsed_schema_names[schema_name] = file_path
|
266
|
-
end
|
267
|
-
|
268
|
-
arm_schema, arm_concepts = parse_annotated_module(
|
269
|
-
type: :arm,
|
270
|
-
stepmod_path: stepmod_path,
|
271
|
-
path: "modules/#{schema_name}/arm_annotated.exp",
|
272
|
-
bibdata: bibdata
|
192
|
+
case type
|
193
|
+
when "module_arm"
|
194
|
+
arm_concepts = parse_annotated_module(
|
195
|
+
schema: schema,
|
196
|
+
bibdata: bibdata,
|
197
|
+
# See: metanorma/iso-10303-2#90
|
198
|
+
domain_prefix: "application module",
|
273
199
|
)
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
200
|
+
when "module_mim"
|
201
|
+
mim_concepts = parse_annotated_module(
|
202
|
+
schema: schema,
|
203
|
+
bibdata: bibdata,
|
204
|
+
# See: metanorma/iso-10303-2#90
|
205
|
+
domain_prefix: "application object",
|
280
206
|
)
|
281
|
-
|
282
|
-
|
283
|
-
current_part_modules_arm[arm_schema] = arm_concepts
|
284
|
-
end
|
285
|
-
|
286
|
-
if mim_concepts.to_a.size > 0
|
287
|
-
current_part_modules_mim[mim_schema] = mim_concepts
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
log "INFO: Completed processing XML file #{fpath}"
|
292
|
-
if current_part_concepts.to_a.empty?
|
293
|
-
log "INFO: Skipping #{fpath} (#{bibdata.docid}) " \
|
294
|
-
"because it contains no concepts."
|
295
|
-
elsif current_part_concepts.to_a.length < 3
|
296
|
-
log "INFO: Skipping #{fpath} (#{bibdata.docid}) " \
|
297
|
-
"because it only has #{current_part_concepts.to_a.length} terms."
|
298
|
-
|
299
|
-
current_part_concepts.to_a.each do |x|
|
300
|
-
general_concepts.store(x)
|
301
|
-
end
|
302
|
-
else
|
303
|
-
unless current_part_concepts.to_a.empty?
|
304
|
-
part_concepts << [bibdata,
|
305
|
-
current_part_concepts]
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
unless current_part_resources.to_a.empty?
|
310
|
-
part_resources << [bibdata,
|
311
|
-
current_part_resources]
|
207
|
+
when "resource"
|
208
|
+
parse_annotated_resource(schema: schema, bibdata: bibdata)
|
312
209
|
end
|
210
|
+
end
|
211
|
+
end
|
313
212
|
|
314
|
-
|
315
|
-
|
213
|
+
def extract_file_type(filename)
|
214
|
+
match = filename.match(/(arm|mim|bom)_annotated\.exp$/)
|
215
|
+
return "resource" unless match
|
316
216
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
end
|
217
|
+
{
|
218
|
+
"arm" => "module_arm",
|
219
|
+
"mim" => "module_mim",
|
220
|
+
"bom" => "business_object_model",
|
221
|
+
}[match.captures[0]] || "resource"
|
323
222
|
end
|
324
223
|
|
325
|
-
def parse_annotated_module(
|
326
|
-
log "INFO: parse_annotated_module:
|
224
|
+
def parse_annotated_module(schema:, bibdata:, domain_prefix:)
|
225
|
+
log "INFO: parse_annotated_module: " \
|
226
|
+
"Processing modules schema #{schema.file}"
|
327
227
|
|
328
|
-
|
228
|
+
collection = Glossarist::ManagedConceptCollection.new
|
329
229
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
230
|
+
schema.entities.each do |entity|
|
231
|
+
@sequence += 1
|
232
|
+
document = entity.find("__schema_file")&.remarks&.first
|
233
|
+
|
234
|
+
concept = generate_concept_from_entity(
|
235
|
+
entity: entity,
|
236
|
+
domain: "#{domain_prefix}: #{schema.id}",
|
237
|
+
schema: {
|
238
|
+
"name" => schema.id,
|
239
|
+
"type" => "module",
|
240
|
+
"path" => extract_file_path(entity.parent.file),
|
241
|
+
},
|
242
|
+
document: {
|
243
|
+
"type" => "module",
|
244
|
+
"module" => document && document.split("/")[-2],
|
245
|
+
"path" => document,
|
246
|
+
},
|
247
|
+
bibdata: bibdata,
|
248
|
+
)
|
334
249
|
|
335
|
-
|
250
|
+
next unless concept
|
336
251
|
|
337
|
-
|
338
|
-
log "ERROR: parse_annotated_module: failed to parse EXPRESS file at #{path}."
|
339
|
-
return
|
252
|
+
find_or_initialize_concept(collection, concept)
|
340
253
|
end
|
341
254
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
when :arm
|
347
|
-
"application object"
|
255
|
+
if collection.to_a.size.positive?
|
256
|
+
part_index = domain_prefix == "application module" ? 1 : 2
|
257
|
+
part_modules[bibdata.part] ||= [bibdata, {}, {}]
|
258
|
+
part_modules[bibdata.part][part_index][schema.id] = collection
|
348
259
|
end
|
349
260
|
|
350
|
-
if
|
351
|
-
|
352
|
-
|
353
|
-
"#{repo.schemas.map(&:id).join(", ")} (not supposed to happen!!)"
|
354
|
-
)
|
261
|
+
if collection && !@added_bibdata[bibdata.part]
|
262
|
+
parsed_bibliography << bibdata
|
263
|
+
@added_bibdata[bibdata.part] = true
|
355
264
|
end
|
356
265
|
|
357
|
-
|
358
|
-
|
359
|
-
|
266
|
+
collection
|
267
|
+
end
|
268
|
+
|
269
|
+
def parse_annotated_resource(schema:, bibdata:)
|
270
|
+
log "INFO: parse_annotated_resource: " \
|
271
|
+
"Processing resources schema #{schema.file}"
|
360
272
|
|
361
273
|
schema.entities.each do |entity|
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
274
|
+
@sequence += 1
|
275
|
+
log "INFO: Processing entity: #{entity.id}"
|
276
|
+
|
277
|
+
document = entity.find("__schema_file")&.remarks&.first
|
278
|
+
|
279
|
+
concept = generate_concept_from_entity(
|
280
|
+
entity: entity,
|
281
|
+
domain: "resource: #{schema.id}",
|
282
|
+
schema: {
|
283
|
+
"name" => schema.id,
|
284
|
+
"type" => "resource",
|
285
|
+
"path" => extract_file_path(entity.parent.file),
|
286
|
+
},
|
287
|
+
document: {
|
288
|
+
"type" => "resource",
|
289
|
+
"resource" => document && document.split("/")[-2],
|
290
|
+
"path" => document,
|
291
|
+
},
|
292
|
+
bibdata: bibdata,
|
375
293
|
)
|
376
294
|
|
377
295
|
next unless concept
|
378
|
-
|
296
|
+
|
297
|
+
if term_special_category(bibdata)
|
298
|
+
part_resources[bibdata.part] ||= [
|
299
|
+
bibdata,
|
300
|
+
Glossarist::ManagedConceptCollection.new,
|
301
|
+
]
|
302
|
+
# log "INFO: this part is special"
|
303
|
+
find_or_initialize_concept(part_resources[bibdata.part][1], concept)
|
304
|
+
else
|
305
|
+
# log "INFO: this part is generic"
|
306
|
+
find_or_initialize_concept(resource_concepts, concept)
|
307
|
+
end
|
308
|
+
|
309
|
+
unless @added_bibdata[bibdata.part]
|
310
|
+
parsed_bibliography << bibdata
|
311
|
+
@added_bibdata[bibdata.part] = true
|
312
|
+
end
|
379
313
|
end
|
314
|
+
end
|
380
315
|
|
381
|
-
|
316
|
+
# rubocop:disable Metrics/MethodLength
|
317
|
+
def generate_concept_from_entity(entity:, schema:, domain:, bibdata:, document:)
|
318
|
+
old_definition = trim_definition(entity.remarks.first)
|
319
|
+
definition = generate_entity_definition(entity, domain)
|
320
|
+
|
321
|
+
Stepmod::Utils::Concept.new(
|
322
|
+
designations: [
|
323
|
+
{
|
324
|
+
"type" => "expression",
|
325
|
+
"normative_status" => "preferred",
|
326
|
+
"designation" => entity.id,
|
327
|
+
},
|
328
|
+
],
|
329
|
+
domain: domain,
|
330
|
+
definition: [definition.strip],
|
331
|
+
id: "#{bibdata.part}-#{@sequence}",
|
332
|
+
sources: [
|
333
|
+
{
|
334
|
+
"type" => "authoritative",
|
335
|
+
"ref" => bibdata.docid,
|
336
|
+
"link" => "https://www.iso.org/standard/32858.html",
|
337
|
+
},
|
338
|
+
],
|
339
|
+
notes: [old_definition].compact,
|
340
|
+
language_code: "en",
|
341
|
+
part: bibdata.part,
|
342
|
+
schema: schema,
|
343
|
+
document: document,
|
344
|
+
)
|
345
|
+
end
|
346
|
+
# rubocop:enable Metrics/MethodLength
|
347
|
+
|
348
|
+
def extract_file_path(file_path)
|
349
|
+
Pathname
|
350
|
+
.new(file_path)
|
351
|
+
.realpath
|
352
|
+
.relative_path_from(stepmod_path)
|
353
|
+
.to_s
|
382
354
|
end
|
383
355
|
|
384
356
|
def find_or_initialize_concept(collection, localized_concept)
|
385
|
-
concept = collection
|
386
|
-
.store(Glossarist::Concept.new(id: SecureRandom.uuid))
|
357
|
+
concept = collection.fetch_or_initialize(localized_concept.id)
|
387
358
|
concept.add_l10n(localized_concept)
|
388
359
|
end
|
389
360
|
|
361
|
+
# rubocop:disable Metrics/MethodLength
|
390
362
|
def combine_paragraphs(full_paragraph, next_paragraph)
|
391
363
|
# If full_paragraph already contains a period, extract that.
|
392
364
|
if m = full_paragraph.match(/\A(?<inner_first>[^\n]*?\.)\s/)
|
@@ -421,6 +393,8 @@ module Stepmod
|
|
421
393
|
end
|
422
394
|
|
423
395
|
def trim_definition(definition)
|
396
|
+
return nil if definition.nil? || definition.empty?
|
397
|
+
|
424
398
|
# Unless the first paragraph ends with "between" and is followed by a
|
425
399
|
# list, don't split
|
426
400
|
paragraphs = definition.split("\n\n")
|
@@ -429,25 +403,26 @@ module Stepmod
|
|
429
403
|
|
430
404
|
first_paragraph = paragraphs.first
|
431
405
|
|
432
|
-
if paragraphs.length > 1
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
406
|
+
combined = if paragraphs.length > 1
|
407
|
+
paragraphs[1..-1].inject(first_paragraph) do |acc, p|
|
408
|
+
combine_paragraphs(acc, p)
|
409
|
+
end
|
410
|
+
else
|
411
|
+
combine_paragraphs(first_paragraph, "")
|
412
|
+
end
|
439
413
|
|
440
414
|
# puts "combined--------- #{combined}"
|
441
415
|
|
442
416
|
# Remove comments until end of line
|
443
|
-
combined = combined
|
417
|
+
combined = "#{combined}\n"
|
444
418
|
combined.gsub!(/\n\/\/.*?\n/, "\n")
|
445
419
|
combined.strip!
|
446
420
|
|
447
421
|
express_reference_to_mention(combined)
|
448
422
|
|
449
423
|
# combined
|
450
|
-
# # TODO: If the definition contains a list immediately after
|
424
|
+
# # TODO: If the definition contains a list immediately after
|
425
|
+
# # the first paragraph, don't split
|
451
426
|
# return definition if definition =~ /\n\* /
|
452
427
|
|
453
428
|
# unless (
|
@@ -462,6 +437,7 @@ module Stepmod
|
|
462
437
|
# first_paragraph
|
463
438
|
# end
|
464
439
|
end
|
440
|
+
# rubocop:enable Metrics/MethodLength
|
465
441
|
|
466
442
|
# Replace `<<express:{schema}.{entity},{render}>>` with {{entity,render}}
|
467
443
|
def express_reference_to_mention(description)
|
@@ -476,61 +452,40 @@ module Stepmod
|
|
476
452
|
entity_id.downcase.gsub(/_/, " ")
|
477
453
|
end
|
478
454
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
end
|
455
|
+
# No longer used
|
456
|
+
# def entity_ref(entity_id)
|
457
|
+
# if entity_id == entity_name_to_text(entity_id)
|
458
|
+
# "{{#{entity_id}}}"
|
459
|
+
# else
|
460
|
+
# "{{#{entity_id},#{entity_name_to_text(entity_id)}}}"
|
461
|
+
# end
|
462
|
+
# end
|
486
463
|
|
487
464
|
# rubocop:disable Layout/LineLength
|
488
|
-
def generate_entity_definition(entity, domain
|
465
|
+
def generate_entity_definition(entity, domain)
|
489
466
|
return "" if entity.nil?
|
490
467
|
|
491
468
|
# See: metanorma/iso-10303-2#90
|
492
469
|
entity_type = if domain_type = domain.match(/\A(application object):/)
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
"#{entity_type} "
|
500
|
-
|
470
|
+
"{{#{domain_type[1]}}}"
|
471
|
+
else
|
472
|
+
"{{entity data type}}"
|
473
|
+
end
|
474
|
+
|
475
|
+
if entity.subtype_of.size.zero?
|
476
|
+
"#{entity_type} " \
|
477
|
+
"that represents the " \
|
478
|
+
"#{entity_name_to_text(entity.id)} {{entity}}"
|
501
479
|
else
|
502
480
|
entity_subtypes = entity.subtype_of.map do |e|
|
503
481
|
"{{#{e.id}}}"
|
504
482
|
end
|
505
|
-
"#{entity_type} that is a type of " +
|
506
|
-
"#{entity_subtypes.join(' and ')} " +
|
507
|
-
"that represents the " + entity_ref(entity.id) + " entity"
|
508
|
-
end
|
509
|
-
|
510
|
-
definition = <<~DEFINITION
|
511
|
-
=== #{entity.id}
|
512
|
-
domain:[#{domain}]
|
513
|
-
|
514
|
-
#{entity_text}
|
515
483
|
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
old_definition = trim_definition(old_definition)
|
521
|
-
|
522
|
-
definition << <<~OLD_DEFINITION
|
523
|
-
[NOTE]
|
524
|
-
--
|
525
|
-
#{old_definition.strip}
|
526
|
-
--
|
527
|
-
OLD_DEFINITION
|
484
|
+
"#{entity_type} that is a type of " \
|
485
|
+
"#{entity_subtypes.join(' and ')} " \
|
486
|
+
"that represents the " \
|
487
|
+
"#{entity_name_to_text(entity.id)} {{entity}}"
|
528
488
|
end
|
529
|
-
|
530
|
-
# We no longer add Notes and Examples to the extracted terms
|
531
|
-
# definition + format_remark_items(entity.remark_items)
|
532
|
-
|
533
|
-
definition
|
534
489
|
end
|
535
490
|
|
536
491
|
def format_remark_items(remark_items)
|