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.
@@ -0,0 +1,111 @@
1
+ module Stepmod
2
+ module Utils
3
+ class ExpressBibdata
4
+ DOCNUMBER = 10303
5
+
6
+ attr_accessor *%w(
7
+ type doctype part title_en version pub_year pubid published_info number
8
+ )
9
+
10
+ def initialize(schema:)
11
+ # module, resource, application_protocol, business_object_model
12
+ # @type = document.name
13
+
14
+ # raise "UnknownFileError" unless %w(module resource
15
+ # application_protocol business_object_model).include?(@type)
16
+
17
+ @published_info = schema.find("__published_in")&.remarks&.first
18
+ @number = schema.find("__identifier")&.remarks&.first&.split("N")&.last
19
+ @schema = schema
20
+
21
+ if !published_info.nil?
22
+ @pubid = Pubid::Iso::Identifier.parse(published_info)
23
+
24
+ @part = pubid.part
25
+ @version = pubid.edition
26
+ @pub_year = pubid.year
27
+ elsif !schema.version.nil?
28
+ @part = schema.version.items.find { |i| i.name == "part" }.value
29
+ @version = schema.version.items.find { |i| i.name == "part" }.value
30
+ @pub_year = schema.version.items.find { |i| i.name == "part" }.value
31
+ else
32
+ raise "PublishedInfoNotFound"
33
+ end
34
+
35
+ @doctype = schema.find("__status")&.remarks&.first
36
+ self
37
+ end
38
+
39
+ def title_en
40
+ @title_en ||= @schema.find("__title")
41
+ .remarks
42
+ .first
43
+ .gsub("_", " ")
44
+ .capitalize
45
+ .gsub("2d", "2D")
46
+ .gsub("3d", "3D")
47
+ end
48
+
49
+ def docid
50
+ no_date = case doctype
51
+ when "IS"
52
+ "ISO #{DOCNUMBER}-#{part}"
53
+ when "WD"
54
+ "ISO/WD #{DOCNUMBER}-#{part}"
55
+ when "CD"
56
+ "ISO/CD #{DOCNUMBER}-#{part}"
57
+ when "DIS"
58
+ "ISO/DIS #{DOCNUMBER}-#{part}"
59
+ when "FDIS"
60
+ "ISO/FDIS #{DOCNUMBER}-#{part}"
61
+ when "TS"
62
+ "ISO/TS #{DOCNUMBER}-#{part}"
63
+ when "CD-TS"
64
+ "ISO/CD TS #{DOCNUMBER}-#{part}"
65
+ else
66
+ "UNKNOWN DOCTYPE: (#{doctype})"
67
+ end
68
+
69
+ if pub_year
70
+ "#{no_date}:#{pub_year}"
71
+ else
72
+ no_date
73
+ end
74
+ end
75
+
76
+ def part_title
77
+ case part
78
+ when [200..299]
79
+ "Application protocol: #{title_en}"
80
+ when [300..399]
81
+ "Abstract test suite: #{title_en}"
82
+ when [400..499]
83
+ "Application module: #{title_en}"
84
+ when [500..599]
85
+ "Application interpreted construct: #{title_en}"
86
+ when [1000..1799]
87
+ "Application module: #{title_en}"
88
+ else
89
+ title_en
90
+ end
91
+ end
92
+
93
+ def full_title
94
+ "Industrial automation systems and integration -- Product data" \
95
+ " representation and exchange -- Part #{part}: #{part_title}"
96
+ end
97
+
98
+ def anchor
99
+ docid.gsub("/", "-").gsub(" ", "_").gsub(":", "_")
100
+ end
101
+
102
+ def to_mn_adoc
103
+ if title_en
104
+ "* [[[#{anchor},#{docid}]]], _#{full_title}_"
105
+ else
106
+ "* [[[#{anchor},#{docid}]]]"
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -15,6 +15,7 @@ require "stepmod/utils/converters/ext_descriptions"
15
15
  require "stepmod/utils/converters/head"
16
16
  require "stepmod/utils/converters/hr"
17
17
  require "stepmod/utils/converters/ignore"
18
+ require "stepmod/utils/converters/module_ref_express_description"
18
19
  require "stepmod/utils/converters/note"
19
20
  require "stepmod/utils/converters/p"
20
21
  require "stepmod/utils/converters/pass_through"
@@ -15,6 +15,7 @@ require "stepmod/utils/converters/dt"
15
15
  require "stepmod/utils/converters/drop"
16
16
  require "stepmod/utils/converters/example"
17
17
  require "stepmod/utils/converters/express_g"
18
+ require "stepmod/utils/converters/figure"
18
19
  require "stepmod/utils/converters/fund_cons"
19
20
  require "stepmod/utils/converters/eqn"
20
21
  require "stepmod/utils/converters/head"
@@ -25,6 +26,7 @@ require "stepmod/utils/converters/note"
25
26
  require "stepmod/utils/converters/ol"
26
27
  require "stepmod/utils/converters/p"
27
28
  require "stepmod/utils/converters/pass_through"
29
+ require "stepmod/utils/converters/module_ref"
28
30
  require "stepmod/utils/converters/q"
29
31
  require "stepmod/utils/converters/resource"
30
32
  require "stepmod/utils/converters/schema_diag"
@@ -36,7 +38,6 @@ require "stepmod/utils/converters/table"
36
38
  require "stepmod/utils/converters/text"
37
39
  require "stepmod/utils/cleaner"
38
40
 
39
- require "reverse_adoc/converters/figure"
40
41
  require "reverse_adoc/converters/img"
41
42
  require "reverse_adoc/converters/li"
42
43
  require "reverse_adoc/converters/tr"
@@ -17,6 +17,7 @@ require "stepmod/utils/converters/term"
17
17
  require "stepmod/utils/converters/synonym"
18
18
  require "stepmod/utils/converters/uof"
19
19
  require "stepmod/utils/converters/figure"
20
+ require "stepmod/utils/converters/table"
20
21
  require "stepmod/utils/cleaner"
21
22
 
22
23
  require "reverse_adoc/converters/a"
@@ -3,6 +3,11 @@ require "stepmod/utils/smrl_description_converter"
3
3
  require "stepmod/utils/smrl_resource_converter"
4
4
  require "stepmod/utils/converters/express_note"
5
5
  require "stepmod/utils/converters/express_example"
6
+ require "stepmod/utils/converters/express_figure"
7
+ require "stepmod/utils/converters/express_table"
8
+ require "expressir"
9
+ require "expressir/express/parser"
10
+ require "pubid-iso"
6
11
 
7
12
  module Stepmod
8
13
  module Utils
@@ -15,26 +20,37 @@ module Stepmod
15
20
  @express_file = express_file
16
21
  @resource_docs_cache_file = resource_docs_cache_file
17
22
  @stepmod_dir = stepmod_dir || Dir.pwd
23
+ @added_bibdata = {}
24
+
25
+ @schema_name = Expressir::Express::Parser.from_file(express_file)
26
+ .schemas
27
+ .first
28
+ .id
18
29
  end
19
30
 
20
31
  def call
21
32
  match = File.basename(express_file).match('^(arm|mim|bom)\.exp$')
22
33
  descriptions_base = match ? "#{match.captures[0]}_descriptions.xml" : "descriptions.xml"
34
+
23
35
  descriptions_file = File.join(File.dirname(express_file),
24
36
  descriptions_base)
37
+
25
38
  output_express = File.read(express_file)
26
- resource_docs_cache = JSON.parse(File.read(resource_docs_cache_file))
39
+ converted_description = ""
40
+ base_linked = ""
27
41
 
28
42
  if File.exists?(descriptions_file)
29
43
  descriptions = Nokogiri::XML(File.read(descriptions_file)).root
30
44
  added_resource_descriptions = {}
45
+
31
46
  descriptions.xpath("ext_description").each do |description|
32
47
  # Add base resource from linked path if exists, eg "language_schema.language.wr:WR1" -> "language_schema"
33
48
  base_linked = description["linkend"].to_s.split(".").first
49
+
34
50
  if added_resource_descriptions[base_linked].nil?
35
51
  base_reource_doc_dir = resource_docs_cache[description["linkend"].to_s.split(".").first]
36
52
  if base_reource_doc_dir
37
- output_express << convert_from_resource_file(
53
+ converted_description << convert_from_resource_file(
38
54
  base_reource_doc_dir, stepmod_dir, base_linked, descriptions_file
39
55
  )
40
56
  end
@@ -45,7 +61,7 @@ module Stepmod
45
61
  # when a schema description is available from resource.xml and also descriptions.xml, the description from resource.xml is only used.
46
62
  # https://github.com/metanorma/annotated-express/issues/32#issuecomment-792609078
47
63
  if description.text.strip.length.positive? && resource_docs_dir.nil?
48
- output_express << convert_from_description_text(
64
+ converted_description << convert_from_description_text(
49
65
  descriptions_file, description
50
66
  )
51
67
  end
@@ -58,26 +74,70 @@ module Stepmod
58
74
  end
59
75
  end
60
76
 
61
- output_express
77
+ bib_file_name = extract_bib_file_name(match, resource_docs_cache[@schema_name || ""])
78
+ bib_file = if match
79
+ File.join(File.dirname(express_file), bib_file_name)
80
+ else
81
+ resource_docs_file_path(stepmod_dir, bib_file_name)
82
+ end
83
+
84
+ output_express << if bib_file && File.exists?(bib_file)
85
+ prepend_bibdata(
86
+ converted_description || "",
87
+ # bib_file will not be present for resouces
88
+ # that are not in resource_docs cache.
89
+ # e.g hierarchy_schema
90
+ bib_file,
91
+ @schema_name,
92
+ match,
93
+ )
94
+ else
95
+ converted_description
96
+ end
97
+
98
+ sanitize(output_express)
99
+ rescue StandardError => e
100
+ puts "[ERROR]!!! #{e.message}"
101
+ puts e.backtrace
62
102
  end
63
103
 
64
104
  private
65
105
 
106
+ def sanitize(file_content)
107
+ file_content.gsub("(*)", "(`*`)")
108
+ end
109
+
110
+ def resource_docs_cache
111
+ @resource_docs_cache ||= JSON.parse(File.read(resource_docs_cache_file))
112
+ end
113
+
66
114
  def convert_from_description_text(descriptions_file, description)
67
115
  Dir.chdir(File.dirname(descriptions_file)) do
68
116
  wrapper = "<ext_descriptions>#{description}</ext_descriptions>"
69
117
  notes = description.xpath("note")
70
118
  examples = description.xpath("example")
119
+ figures = description.xpath("figure")
120
+ tables = description.xpath("table")
71
121
 
72
122
  converted_description = <<~DESCRIPTION
73
123
 
74
124
  #{Stepmod::Utils::SmrlDescriptionConverter.convert(wrapper, no_notes_examples: true)}
75
125
  DESCRIPTION
76
126
 
77
- converted_examples = examples.map do |example|
78
- Stepmod::Utils::Converters::ExpressExample
127
+ if description["linkend"].nil?
128
+ raise StandardError.new("[stepmod-file-annotator] ERROR: no linkend for #{descriptions_file}!")
129
+ end
130
+
131
+ converted_figures = figures.map do |figure|
132
+ Stepmod::Utils::Converters::ExpressFigure
79
133
  .new
80
- .convert(example, schema_and_entity: description["linkend"])
134
+ .convert(figure, schema_and_entity: description["linkend"])
135
+ end.join
136
+
137
+ converted_tables = tables.map do |table|
138
+ Stepmod::Utils::Converters::ExpressTable
139
+ .new
140
+ .convert(table, schema_and_entity: description["linkend"])
81
141
  end.join
82
142
 
83
143
  converted_notes = notes.map do |note|
@@ -86,22 +146,186 @@ module Stepmod
86
146
  .convert(note, schema_and_entity: description["linkend"])
87
147
  end.join
88
148
 
89
- "#{converted_description}#{converted_examples}#{converted_notes}"
149
+ converted_examples = examples.map do |example|
150
+ Stepmod::Utils::Converters::ExpressExample
151
+ .new
152
+ .convert(example, schema_and_entity: description["linkend"])
153
+ end.join
154
+
155
+ [
156
+ converted_description,
157
+ converted_figures,
158
+ converted_tables,
159
+ converted_examples,
160
+ converted_notes,
161
+ ].join("")
162
+ end
163
+ end
164
+
165
+ def prepend_bibdata(description, bibdata_file, schema_and_entity, match)
166
+ bib = Nokogiri::XML(File.read(bibdata_file)).root
167
+ bibdata = extract_bib_data(match, bib, schema_and_entity)
168
+
169
+ return description.to_s if @added_bibdata[schema_and_entity]
170
+
171
+ published_in = <<~PUBLISHED_IN
172
+
173
+ (*"#{schema_and_entity}.__published_in"
174
+ #{bibdata[:identifier]}
175
+ *)
176
+ PUBLISHED_IN
177
+
178
+ identifier = <<~IDENTIFIER if bibdata[:number]
179
+ (*"#{schema_and_entity}.__identifier"
180
+ ISO/TC 184/SC 4/WG 12 N#{bibdata[:number]}
181
+ *)
182
+ IDENTIFIER
183
+
184
+ supersedes = <<~SUPERSEDES if bibdata[:supersedes_concept]
185
+ (*"#{schema_and_entity}.__supersedes"
186
+ ISO/TC 184/SC 4/WG 12 N#{bibdata[:supersedes_concept]}
187
+ *)
188
+ SUPERSEDES
189
+
190
+ status = <<~STATUS if bibdata[:status]
191
+ (*"#{schema_and_entity}.__status"
192
+ #{bibdata[:status]}
193
+ *)
194
+ STATUS
195
+
196
+ title = <<~TITLE if bibdata[:title]
197
+ (*"#{schema_and_entity}.__title"
198
+ #{bibdata[:title]}
199
+ *)
200
+ TITLE
201
+
202
+ document = <<~DOCUMENT if bibdata_file
203
+ (*"#{schema_and_entity}.__schema_file"
204
+ #{Pathname(bibdata_file).relative_path_from(@stepmod_dir)}
205
+ *)
206
+ DOCUMENT
207
+
208
+ @added_bibdata[schema_and_entity] = true
209
+
210
+ [
211
+ published_in,
212
+ identifier,
213
+ supersedes,
214
+ status,
215
+ title,
216
+ description,
217
+ document,
218
+ ].compact.join("\n")
219
+ end
220
+
221
+ def module?(match)
222
+ match && %w[arm mim].include?(match.captures[0])
223
+ end
224
+
225
+ def bom?(match)
226
+ match && %w[bom].include?(match.captures[0])
227
+ end
228
+
229
+ def extract_bib_file_name(match, default_file_name = "")
230
+ return default_file_name || "" unless match
231
+
232
+ if %w[arm mim].include?(match.captures[0])
233
+ "module.xml"
234
+ else
235
+ "business_object_model.xml"
236
+ end
237
+ end
238
+
239
+ def extract_bib_data(match, bib, schema_and_entity)
240
+ return resource_bib_data(bib, schema_and_entity) unless match
241
+
242
+ if module?(match)
243
+ module_bib_data(bib, match.captures[0])
244
+ elsif bom?(match)
245
+ bom_bib_data(bib)
90
246
  end
91
247
  end
92
248
 
249
+ def identifier(bib)
250
+ part = bib.attributes["part"].value
251
+ year = bib.attributes["publication.year"].value
252
+
253
+ # year="tbd" in data/modules/geometric_tolerance/module.xml and
254
+ # probabaly in some other places as well
255
+ year = "" if year == "tbd"
256
+ edition = bib.attributes["version"].value
257
+
258
+ pubid = Pubid::Iso::Identifier.new(
259
+ publisher: "ISO",
260
+ number: 10303,
261
+ )
262
+
263
+ pubid.part = part if part && !part.empty?
264
+ pubid.year = year.split("-").first if year && !year.empty?
265
+ pubid.edition = edition if edition && !edition.empty?
266
+
267
+ pubid.to_s(with_edition: true)
268
+ end
269
+
270
+ def resource_bib_data(bib, schema_and_entity)
271
+ schema = bib.xpath("schema[@name='#{schema_and_entity}']").first
272
+
273
+ {
274
+ identifier: identifier(bib),
275
+ number: schema.attributes["number"],
276
+ supersedes_concept: schema.attributes["number.supersedes"],
277
+ status: bib.attributes["status"],
278
+ title: bib.attributes["title"] || bib.attributes["name"],
279
+ }
280
+ end
281
+
282
+ def module_bib_data(bib, type)
283
+ {
284
+ identifier: identifier(bib),
285
+ number: bib.attributes["wg.number.#{type}"],
286
+ supersedes_concept: bib.attributes["wg.number.#{type}.supersedes"],
287
+ status: bib.attributes["status"],
288
+ title: bib.attributes["title"] || bib.attributes["name"],
289
+ }
290
+ end
291
+
292
+ def bom_bib_data(bib)
293
+ {
294
+ identifier: identifier(bib),
295
+ number: bib.attributes["wg.number.bom.exp"],
296
+ supersedes_concept: bib.attributes["wg.number.bom.supersedes"],
297
+ status: bib.attributes["status"],
298
+ title: bib.attributes["title"] || bib.attributes["name"],
299
+ }
300
+ end
301
+
93
302
  def convert_from_resource_file(resource_docs_dir, stepmod_dir, linked, descriptions_file)
94
- resource_docs_file = File.join(stepmod_dir, "data/resource_docs",
95
- resource_docs_dir, "resource.xml")
96
- puts(resource_docs_file)
303
+ resource_docs_file = resource_docs_file_path(stepmod_dir, resource_docs_dir)
304
+
97
305
  resource_docs = Nokogiri::XML(File.read(resource_docs_file)).root
98
306
  schema = resource_docs.xpath("schema[@name='#{linked}']")
99
307
 
100
308
  Dir.chdir(File.dirname(descriptions_file)) do
101
309
  wrapper = "<resource>#{schema}</resource>"
102
- "\n#{Stepmod::Utils::SmrlResourceConverter.convert(wrapper, no_notes_examples: true)}"
310
+
311
+ "\n" + Stepmod::Utils::SmrlResourceConverter.convert(
312
+ wrapper,
313
+ {
314
+ no_notes_examples: false,
315
+ schema_and_entity: linked,
316
+ },
317
+ )
103
318
  end
104
319
  end
320
+
321
+ def resource_docs_file_path(stepmod_dir, resource_docs_dir)
322
+ File.join(
323
+ stepmod_dir,
324
+ "data/resource_docs",
325
+ resource_docs_dir,
326
+ "resource.xml",
327
+ )
328
+ end
105
329
  end
106
330
  end
107
331
  end
@@ -7,9 +7,9 @@ module Stepmod
7
7
  attr_accessor :acronym
8
8
 
9
9
  def to_mn_adoc
10
- mn_adoc = ["=== #{definition}"]
10
+ mn_adoc = ["=== #{definition.map(&:content).join}"]
11
11
  mn_adoc << "\nalt:[#{acronym}]" if acronym
12
- mn_adoc << "\n\n#{designations.join(", ")}" if designations&.any?
12
+ mn_adoc << "\n\n#{designations.map(&:designation).join(", ")}" if designations&.any?
13
13
 
14
14
  mn_adoc.join
15
15
  end
@@ -18,15 +18,28 @@ module Stepmod
18
18
  def from_h(hash)
19
19
  _, definition, acronym = treat_acronym(hash["definition"])
20
20
 
21
- hash["definition"] = definition
21
+ hash["definition"] = [definition]
22
+
22
23
  hash["acronym"] = acronym.gsub(/\(|\)/, "") if acronym
23
- hash["designations"] = hash["synonyms"]
24
+ add_designations(hash, hash["synonyms"]) if hash["synonyms"]
24
25
 
25
- super(hash.reject { |k, _| k == "synonyms" })
26
+ new(hash.reject { |k, _| k == "synonyms" })
26
27
  end
27
28
 
28
29
  private
29
30
 
31
+ def add_designations(hash, synonyms)
32
+ hash["designations"] ||= []
33
+ hash["designations"] << designation_hash(synonyms) if synonyms
34
+ end
35
+
36
+ def designation_hash(value, type = "expression")
37
+ {
38
+ "designation" => value,
39
+ "type" => type,
40
+ }
41
+ end
42
+
30
43
  def treat_acronym(term_def)
31
44
  return [nil, term_def.strip, nil] unless term_def.match?(/.+\(.+?\)$/)
32
45