stepmod-utils 0.3.24 → 0.3.25

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92d04b3c30620d813fbff40cfa84ed809f0129440dd1f6be45c4206aaa44a12e
4
- data.tar.gz: 54289d1067ccba3a61cd0ca07bd5455081efe70aae946811cf8028f6e77afb9a
3
+ metadata.gz: 46ea2364546e11b067f0d3d21e78d0a1df701ec5189aeb94d08461d551b22786
4
+ data.tar.gz: ab5adf48414ca093c86ff2fbe12155ff7eab79102412f1c1f9949ee5e7eac591
5
5
  SHA512:
6
- metadata.gz: e83145314175c1797f8de0fe08bdbf3ba95e06346b49f80beb3cdadb31d1b2423cb60230d869b91850de3685b0fb6c805a2b4ddebbfd72ff2b55ffde234f4d9f
7
- data.tar.gz: 309a341bead6e54225f14101c3bea989f2f7873409c4d8e1fedbc6e8b2144d3e21ed2034c5ebcfd76279d73234a84e8d0d67c86fb77e1e1b715f6f1ba2ad661b
6
+ metadata.gz: 16eb837cff97033e742a20f2513ca426f69d41bb49cce9956c450f41c90290bd3404083c378a40b0ac6c35a68c974c57db1b11e5919cc6a1d5da9b65845b310b
7
+ data.tar.gz: c3df83672ebda912b592c487698b61e1e19e91cc31da78959dae7d3f4d3836b6a1940d78e33eec34dca92815fe7385e0289f3170303f989187132e1ef21ebc82
@@ -0,0 +1,38 @@
1
+ name: test-concept-generation
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ v* ]
7
+ pull_request:
8
+
9
+ jobs:
10
+ generate_yaml_concepts:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v3
15
+
16
+ - name: Setup Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: '3.1'
20
+ bundler-cache: true
21
+
22
+ - name: Check out iso-10303-stepmod-wg12 repo
23
+ uses: actions/checkout@v3
24
+ with:
25
+ repository: metanorma/iso-10303-stepmod-wg12
26
+ token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
27
+ path: iso-10303-stepmod-wg12
28
+
29
+ - name: Generate Annotated EXPRESS files
30
+ run: bundle exec stepmod-annotate-all ./iso-10303-stepmod-wg12
31
+
32
+ - name: Generate Concept YAML files
33
+ working-directory: iso-10303-stepmod-wg12
34
+ run: |
35
+ bundle exec stepmod-extract-concepts \
36
+ -p ./data \
37
+ -i ./repository_index.xml \
38
+ -o ./output-yaml
data/.gitignore CHANGED
@@ -9,4 +9,7 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ .rubocop*
12
13
  Gemfile.lock
14
+
15
+ .rubocop-https*
@@ -5,14 +5,28 @@ require "stepmod/utils/stepmod_file_annotator"
5
5
 
6
6
  stepmod_dir = ARGV.first || Dir.pwd
7
7
 
8
- # build resource_docs cache
9
- resource_docs_cache_file = `mktemp`
10
- `"#{File.join(__dir__,
11
- "stepmod-build-resource-docs-cache")}" "#{stepmod_dir}" > "#{resource_docs_cache_file}"`
12
-
13
- # annotate each file
14
- files = `"#{File.join(__dir__,
15
- "stepmod-find-express-files")}" "#{stepmod_dir}"`.strip.split("\n")
8
+ def all_express_files(stepmod_dir)
9
+ index_file = File.read(File.join(stepmod_dir, "repository_index.xml"))
10
+ index = Nokogiri::XML(index_file).root
11
+
12
+ files = []
13
+ index.xpath("modules/module").each do |item|
14
+ files << "#{stepmod_dir}/data/modules/#{item['name']}/arm.exp"
15
+ files << "#{stepmod_dir}/data/modules/#{item['name']}/mim.exp"
16
+ end
17
+
18
+ index.xpath("resources/resource").each do |item|
19
+ files << "#{stepmod_dir}/data/resources/#{item['name']}/#{item['name']}.exp"
20
+ end
21
+
22
+ index.xpath("business_object_models/business_object_model").each do |item|
23
+ files << "#{stepmod_dir}/data/business_object_models/#{item['name']}/bom.exp"
24
+ files << "#{stepmod_dir}/data/business_object_models/#{item['name']}/DomainModel.exp"
25
+ end
26
+
27
+ files.filter { |file| File.exist?(file) }
28
+ end
29
+
16
30
  MAX_THREADS = 1 #[2, Concurrent.processor_count].max * 2
17
31
  MAX_QUEUE_SIZE = MAX_THREADS * 4
18
32
  # https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs-source/thread_pools.md
@@ -22,14 +36,16 @@ pool = Concurrent::ThreadPoolExecutor.new(
22
36
  max_queue: MAX_QUEUE_SIZE,
23
37
  fallback_policy: :caller_runs,
24
38
  )
39
+
40
+ files = all_express_files(stepmod_dir)
41
+
25
42
  files.each_slice(MAX_QUEUE_SIZE) do |batch|
26
43
  puts("Queueing next batch")
27
44
  batch.each do |file|
28
45
  pool.post do
29
- puts("#{Thread.current.object_id}: Queued processing #{file}")
46
+ puts "#{Thread.current.object_id}: Queued processing #{file}"
30
47
  annotated = Stepmod::Utils::StepmodFileAnnotator.new(
31
48
  express_file: file,
32
- resource_docs_cache_file: resource_docs_cache_file,
33
49
  stepmod_dir: stepmod_dir
34
50
  ).call
35
51
 
@@ -40,11 +56,8 @@ files.each_slice(MAX_QUEUE_SIZE) do |batch|
40
56
  file.puts(annotated)
41
57
  end
42
58
 
43
- puts("#{Thread.current.object_id}: Done processing #{File.basename(file)} => #{annotated_file_path}.")
59
+ puts "#{Thread.current.object_id}: Done processing #{File.basename(file)} => #{annotated_file_path}."
44
60
  end
45
61
  end
46
62
  pool.shutdown
47
63
  end
48
-
49
- # cleanup
50
- `rm "#{resource_docs_cache_file}"`
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # resolve bin path, ignoring symlinks
4
+ require "pathname"
5
+ bin_file = Pathname.new(__FILE__).realpath
6
+
7
+ # add self to libpath
8
+ $:.unshift File.expand_path("../../lib", bin_file)
9
+
10
+ # Fixes https://github.com/rubygems/rubygems/issues/1420
11
+ require "rubygems/specification"
12
+
13
+ module Gem
14
+ class Specification
15
+ def this; self; end
16
+ end
17
+ end
18
+
19
+ require "bundler/setup"
20
+ require "stepmod/utils/changes_extractor"
21
+ require "optparse"
22
+
23
+ def log(message)
24
+ puts "[stepmod-utils] #{message}"
25
+ end
26
+
27
+ options = {}
28
+ OptionParser.new do |opts|
29
+ opts.banner = "Usage: #{$0} [options]"
30
+
31
+ opts.on(
32
+ "-p",
33
+ "--path STEPMOD_DATA_PATH",
34
+ String,
35
+ "Path to STEPmod data directory",
36
+ ) do |path|
37
+ options[:stepmod_dir] = path
38
+ end
39
+
40
+ opts.on_tail("-h", "--help", "Show this message") do
41
+ puts opts
42
+ exit
43
+ end
44
+ end.parse!
45
+
46
+ stepmod_dir = options[:stepmod_dir]
47
+ if stepmod_dir.nil?
48
+ raise StandardError.new("STEPmod data path not set, set with the `-p` option")
49
+ else
50
+ log "STEPmod data path: `#{stepmod_dir}`"
51
+ end
52
+
53
+ changes = Stepmod::Utils::ChangesExtractor.call(
54
+ stepmod_dir: Pathname.new(stepmod_dir).realpath,
55
+ )
56
+
57
+ changes.save_to_files
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: UTF-8
3
3
 
4
- require "pry"
4
+ require "fileutils"
5
5
  # resolve bin path, ignoring symlinks
6
6
  require "pathname"
7
7
  bin_file = Pathname.new(__FILE__).realpath
@@ -50,6 +50,17 @@ OptionParser.new do |opts|
50
50
  end
51
51
  end
52
52
 
53
+ opts.on(
54
+ "-o",
55
+ "--output INDEX_PATH",
56
+ String,
57
+ "Path to output directory",
58
+ ) do |path|
59
+ unless path.nil?
60
+ options[:output_dir] = Pathname.new(path).to_s
61
+ end
62
+ end
63
+
53
64
  opts.on_tail("-h", "--help", "Show this message") do
54
65
  puts opts
55
66
  exit
@@ -67,7 +78,7 @@ end
67
78
 
68
79
  default_index_path = File.join(stepmod_dir, "repository_index.xml")
69
80
  index_path = options[:index_path] || default_index_path
70
- if File.exists?(index_path)
81
+ if File.exist?(index_path)
71
82
  log "Repository index path: `#{index_path}`"
72
83
  else
73
84
  raise StandardError.new(
@@ -75,6 +86,13 @@ else
75
86
  )
76
87
  end
77
88
 
89
+ default_output_dir = File.join(stepmod_dir, "output_yaml")
90
+ output_dir = options[:output_dir] || default_output_dir
91
+ unless File.directory?(output_dir)
92
+ FileUtils.mkdir_p(output_dir)
93
+ end
94
+ log "Output directory path: `#{output_dir}`"
95
+
78
96
  _general_concepts,
79
97
  resource_concepts,
80
98
  _parsed_bibliography,
@@ -122,28 +140,26 @@ def replace_content(content)
122
140
  end
123
141
 
124
142
  part_resources.each do |(_bibdata, current_part_resources)|
125
- current_part_resources.save_to_files("./")
143
+ current_part_resources.save_to_files(output_dir)
126
144
  end
127
145
  log "INFO: part_resources written to yaml files"
128
146
 
129
-
130
- log "INFO: written summary file to: 04x-stepmod-entities-resources.adoc"
131
147
  part_modules.sort_by do |(bibdata, _part_modules_arm, _part_modules_mim)|
132
148
  bibdata.part.to_i
133
149
  end.each do |(_bibdata, part_modules_arm, part_modules_mim)|
134
150
  unless part_modules_arm.empty?
135
151
  part_modules_arm.values.map do |managed_concept|
136
- managed_concept.save_to_files("./")
152
+ managed_concept.save_to_files(output_dir)
137
153
  end
138
154
  end
139
155
 
140
156
  unless part_modules_mim.empty?
141
157
  part_modules_mim.values.map do |managed_concept|
142
- managed_concept.save_to_files("./")
158
+ managed_concept.save_to_files(output_dir)
143
159
  end
144
160
  end
145
161
  end
146
162
  log "INFO: part_modules written to yaml files"
147
163
 
148
- resource_concepts.save_to_files("./")
164
+ resource_concepts.save_to_files(output_dir)
149
165
  log "INFO: resource_concepts written to yaml files"
@@ -0,0 +1,74 @@
1
+ require "psych"
2
+ require "stepmod/utils/change_edition"
3
+ require "stepmod/utils/change_edition_collection"
4
+
5
+ module Stepmod
6
+ module Utils
7
+ class Change
8
+ attr_accessor :schema_name
9
+ attr_reader :change_editions
10
+
11
+ MODULE_TYPES = {
12
+ arm: "arm",
13
+ mim: "mim",
14
+ arm_longform: "arm_lf",
15
+ mim_longform: "mim_lf",
16
+ }.freeze
17
+
18
+ def initialize(stepmod_dir:, schema_name:, type:)
19
+ @stepmod_dir = stepmod_dir
20
+ @change_editions = Stepmod::Utils::ChangeEditionCollection.new
21
+ @schema_name = schema_name
22
+ @type = type
23
+ end
24
+
25
+ def resource?
26
+ !module?
27
+ end
28
+
29
+ def module?
30
+ MODULE_TYPES.key?(@type.to_sym) || MODULE_TYPES.value?(@type.to_s)
31
+ end
32
+
33
+ def add_change_edition(change_edition)
34
+ @change_editions[change_edition[:version]] = change_edition
35
+ end
36
+
37
+ def fetch_change_edition(version)
38
+ @change_editions[version]
39
+ end
40
+ alias_method :[], :fetch_change_edition
41
+
42
+ def save_to_file
43
+ File.write(filepath(@type), Psych.dump(to_h))
44
+ end
45
+
46
+ def to_h
47
+ {
48
+ "schema" => schema_name,
49
+ "change_edition" => change_editions.to_h,
50
+ }
51
+ end
52
+
53
+ private
54
+
55
+ def filepath(type)
56
+ File.join(
57
+ @stepmod_dir,
58
+ "data",
59
+ base_folder,
60
+ schema_name,
61
+ "#{MODULE_TYPES[type.to_sym] || schema_name}.changes.yaml",
62
+ )
63
+ end
64
+
65
+ def base_folder
66
+ if resource?
67
+ "resources"
68
+ else
69
+ "modules"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,50 @@
1
+ require "stepmod/utils/change"
2
+
3
+ module Stepmod
4
+ module Utils
5
+ class ChangeCollection
6
+ def initialize(stepmod_dir:)
7
+ @stepmod_dir = stepmod_dir
8
+ @changes = {}
9
+ end
10
+
11
+ def fetch_or_initialize(change, type)
12
+ schema = schema_name(change)
13
+
14
+ @changes[schema_identifier(schema, type)] ||= Change.new(
15
+ type: type,
16
+ stepmod_dir: @stepmod_dir,
17
+ schema_name: schema,
18
+ )
19
+ end
20
+
21
+ def fetch(change, type)
22
+ schema = schema_name(change)
23
+ @changes[schema_identifier(schema, type)]
24
+ end
25
+
26
+ def save_to_files
27
+ @changes.values.each(&:save_to_file)
28
+ end
29
+
30
+ def count
31
+ @changes.keys.count
32
+ end
33
+ alias_method :size, :count
34
+
35
+ def each(&block)
36
+ @changes.values.each(&block)
37
+ end
38
+
39
+ private
40
+
41
+ def schema_name(change)
42
+ change.is_a?(Stepmod::Utils::Change) ? change.schema_name : change
43
+ end
44
+
45
+ def schema_identifier(schema_name, type)
46
+ "#{schema_name}_#{type}"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,60 @@
1
+ module Stepmod
2
+ module Utils
3
+ class ChangeEdition
4
+ attr_accessor :version, :description
5
+ attr_reader :additions, :modifications, :deletions, :mapping
6
+
7
+ def initialize(options)
8
+ @version = options[:version]
9
+ @description = options[:description]
10
+ self.additions = options[:additions] || []
11
+ self.modifications = options[:modifications] || []
12
+ self.deletions = options[:deletions] || []
13
+ self.mapping = options[:mapping] || []
14
+ end
15
+
16
+ def additions=(additions)
17
+ validate_type("additions", additions, Array)
18
+
19
+ @additions = additions
20
+ end
21
+
22
+ def modifications=(modifications)
23
+ validate_type("modifications", modifications, Array)
24
+
25
+ @modifications = modifications
26
+ end
27
+
28
+ def deletions=(deletions)
29
+ validate_type("deletions", deletions, Array)
30
+
31
+ @deletions = deletions
32
+ end
33
+
34
+ def mapping=(mapping)
35
+ validate_type("mapping", mapping, Array)
36
+
37
+ @mapping = mapping
38
+ end
39
+
40
+ def to_h
41
+ {
42
+ "version" => version,
43
+ "description" => description,
44
+ "additions" => additions,
45
+ "modifications" => modifications,
46
+ "deletions" => deletions,
47
+ "mapping" => mapping,
48
+ }.reject { |_k, v| v.nil? || v.empty? }
49
+ end
50
+
51
+ private
52
+
53
+ def validate_type(column, value, type)
54
+ error = "#{column} must be of type ::#{type}, Got ::#{value.class}"
55
+
56
+ raise error unless value.is_a?(type)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,38 @@
1
+ require "stepmod/utils/change_edition"
2
+
3
+ module Stepmod
4
+ module Utils
5
+ class ChangeEditionCollection
6
+ def initialize
7
+ @collection = {}
8
+ end
9
+
10
+ def fetch_or_initialize(version)
11
+ @collection[version] ||=
12
+ Stepmod::Utils::ChangeEdition.new(version: version)
13
+ end
14
+
15
+ def to_h
16
+ @collection.values.map(&:to_h)
17
+ end
18
+
19
+ def []=(version, change_edition)
20
+ klass = Stepmod::Utils::ChangeEdition
21
+ @collection[version] = if change_edition.is_a?(klass)
22
+ change_edition
23
+ else
24
+ klass.new(change_edition)
25
+ end
26
+ end
27
+
28
+ def [](version)
29
+ @collection[version]
30
+ end
31
+
32
+ def count
33
+ @collection.values.count
34
+ end
35
+ alias_method :size, :count
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,194 @@
1
+ require "nokogiri"
2
+ require "stepmod/utils/change_collection"
3
+ require "stepmod/utils/smrl_description_converter"
4
+
5
+ module Stepmod
6
+ module Utils
7
+ class ChangesExtractor
8
+ MODULE_TYPES = %w[arm mim arm_longform mim_longform].freeze
9
+
10
+ attr_accessor :stepmod_dir
11
+
12
+ def self.call(stepmod_dir:, stdout: $stdout)
13
+ new(stepmod_dir: stepmod_dir, stdout: stdout).call
14
+ end
15
+
16
+ def initialize(stepmod_dir:, stdout: $stdout)
17
+ @stdout = stdout
18
+ @stepmod_dir = stepmod_dir
19
+ @collection = Stepmod::Utils::ChangeCollection.new(
20
+ stepmod_dir: stepmod_dir,
21
+ )
22
+ end
23
+
24
+ def call
25
+ all_resource_changes_files.each do |resource_change_file|
26
+ xml_changes = Nokogiri::XML(File.read(resource_change_file)).root
27
+ add_resource_changes_to_collection(xml_changes, @collection)
28
+ end
29
+
30
+ all_modules_changes_files.each do |module_change_file|
31
+ xml_changes = Nokogiri::XML(File.read(module_change_file)).root
32
+ schema_name = Pathname.new(module_change_file).parent.basename.to_s
33
+ add_module_changes_to_collection(xml_changes, @collection, schema_name)
34
+ end
35
+
36
+ @collection
37
+ end
38
+
39
+ private
40
+
41
+ # rubocop:disable Metrics/MethodLength
42
+ def add_resource_changes_to_collection(xml_data, collection)
43
+ xml_data.xpath("//changes").each do |changes_node|
44
+ changes_node.xpath("change_edition").each do |change_edition_node|
45
+ options = {
46
+ version: change_edition_node.attr("version"),
47
+ description: Stepmod::Utils::SmrlDescriptionConverter.convert(
48
+ change_edition_node.at("description"),
49
+ ),
50
+ }
51
+
52
+ add_resource_changes(
53
+ collection,
54
+ change_edition_node,
55
+ options,
56
+ )
57
+ end
58
+ end
59
+ end
60
+
61
+ def add_module_changes_to_collection(xml_data, collection, schema_name)
62
+ xml_data.xpath("//changes").each do |changes_node|
63
+ changes_node.xpath("change").each do |change_node|
64
+ options = {
65
+ schema_name: schema_name,
66
+ version: change_node.attr("version"),
67
+ description: converted_description(change_node.at("description")),
68
+ }
69
+
70
+ MODULE_TYPES.each do |type|
71
+ add_module_changes(
72
+ collection,
73
+ change_node,
74
+ options,
75
+ type,
76
+ )
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ def add_resource_changes(collection, change_node, options)
83
+ change_node.xpath("schema.changes").each do |changes|
84
+ schema_name = correct_schema_name(changes.attr("schema_name"))
85
+ change = collection.fetch_or_initialize(schema_name, "schema")
86
+
87
+ change_edition = extract_change_edition(changes, options)
88
+ change.add_change_edition(change_edition)
89
+ end
90
+ end
91
+
92
+ def add_module_changes(collection, change_node, options, type)
93
+ options[:type] = type
94
+ # assuming there will only be one change related to a type in the
95
+ # same version.
96
+ changes = change_node.xpath("#{type}.changes").first
97
+ schema_name = options[:schema_name]
98
+ change = collection.fetch_or_initialize(schema_name, type)
99
+
100
+ change_edition = extract_change_edition(changes, options)
101
+ change.add_change_edition(change_edition)
102
+
103
+ if type == "arm"
104
+ add_mapping_changes(collection, change_node, options)
105
+ end
106
+ end
107
+
108
+ def add_mapping_changes(collection, change_node, options)
109
+ change_edition = collection
110
+ .fetch_or_initialize(options[:schema_name], "arm")
111
+ .change_editions
112
+ .fetch_or_initialize(options[:version])
113
+
114
+ change_edition.mapping = extract_mapping_changes(change_node)
115
+ end
116
+
117
+ def extract_mapping_changes(change_node)
118
+ mappings = []
119
+
120
+ change_node.xpath("mapping.changes").each do |changes|
121
+ changes.xpath("mapping.change").each do |change|
122
+ mappings << { "change" => change.text }
123
+ end
124
+
125
+ changes.xpath("description").each do |change|
126
+ mappings << { "description" => change.text }
127
+ end
128
+ end
129
+
130
+ mappings
131
+ end
132
+
133
+ def extract_change_edition(schema_changes, options)
134
+ type = options[:type] || "schema"
135
+ addition_nodes = schema_changes&.xpath("#{type}.additions") || []
136
+ modification_nodes = schema_changes&.xpath("#{type}.modifications") || []
137
+ deletion_nodes = schema_changes&.xpath("#{type}.deletions") || []
138
+
139
+ {
140
+ version: options[:version],
141
+ description: options[:description],
142
+ additions: extract_modified_objects(addition_nodes),
143
+ modifications: extract_modified_objects(modification_nodes),
144
+ deletions: extract_modified_objects(deletion_nodes),
145
+ }
146
+ end
147
+ # rubocop:enable Metrics/MethodLength
148
+
149
+ def extract_modified_objects(nodes)
150
+ nodes.map do |node|
151
+ node.xpath("modified.object").map do |object|
152
+ {
153
+ type: object.attr("type"),
154
+ name: object.attr("name"),
155
+ description: converted_description(object.at("description")),
156
+ interfaced_items: object.attr("interfaced.items"),
157
+ }.compact
158
+ end
159
+ end.flatten
160
+ end
161
+
162
+ def converted_description(description)
163
+ return if description.to_s.empty?
164
+
165
+ Stepmod::Utils::SmrlDescriptionConverter.convert(description)
166
+ end
167
+
168
+ def all_resource_changes_files
169
+ Dir.glob(
170
+ File.join(stepmod_dir, "data", "resource_docs", "*", "resource.xml"),
171
+ )
172
+ end
173
+
174
+ def all_modules_changes_files
175
+ Dir.glob(
176
+ File.join(stepmod_dir, "data", "modules", "*", "module.xml"),
177
+ )
178
+ end
179
+
180
+ # rubocop:disable Layout/LineLength
181
+ def correct_schema_name(schema_name)
182
+ schema_name_corrector = {
183
+ "material_property_definition" => "material_property_definition_schema",
184
+ "qualified_measure" => "qualified_measure_schema",
185
+ "material_property_representation" => "material_property_representation_schema",
186
+ "annotated_3d_model_data_quality_criteria" => "annotated_3d_model_data_quality_criteria_schema",
187
+ }
188
+
189
+ schema_name_corrector[schema_name] || schema_name
190
+ end
191
+ # rubocop:enable Layout/LineLength
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Stepmod
4
+ module Utils
5
+ module Converters
6
+ class Description < ReverseAdoc::Converters::Base
7
+ def convert(node, state = {})
8
+ treat_children(node, state)
9
+ end
10
+
11
+ private
12
+
13
+ def treat_children(node, state)
14
+ res = node.children.map { |child| treat(child, state) }
15
+ res.map(&:strip).reject(&:empty?).join("\n\n")
16
+ end
17
+ end
18
+
19
+ ReverseAdoc::Converters.register :description, Description.new
20
+ end
21
+ end
22
+ end
@@ -6,6 +6,7 @@ require "stepmod/utils/converters/blockquote"
6
6
  require "stepmod/utils/converters/br"
7
7
  require "stepmod/utils/converters/bypass"
8
8
  require "stepmod/utils/converters/code"
9
+ require "stepmod/utils/converters/description"
9
10
  require "stepmod/utils/converters/drop"
10
11
  require "stepmod/utils/converters/em_express_description"
11
12
  require "stepmod/utils/converters/example"
@@ -12,13 +12,13 @@ require "pubid-iso"
12
12
  module Stepmod
13
13
  module Utils
14
14
  class StepmodFileAnnotator
15
- attr_reader :express_file, :resource_docs_cache_file, :stepmod_dir
15
+ attr_reader :express_file, :resource_docs_cache, :stepmod_dir
16
16
 
17
17
  # @param express_file [String] path to the exp file needed to annotate
18
- # @param resource_docs_cache_file [String] output of ./stepmod-build-resource-docs-cache
19
- def initialize(express_file:, resource_docs_cache_file:, stepmod_dir: nil)
18
+ # @param resource_docs_cache [String] output of ./stepmod-build-resource-docs-cache
19
+ def initialize(express_file:, stepmod_dir: nil)
20
20
  @express_file = express_file
21
- @resource_docs_cache_file = resource_docs_cache_file
21
+ @resource_docs_cache = resource_docs_schemas(stepmod_dir)
22
22
  @stepmod_dir = stepmod_dir || Dir.pwd
23
23
  @added_bibdata = {}
24
24
 
@@ -28,6 +28,23 @@ module Stepmod
28
28
  .id
29
29
  end
30
30
 
31
+ def resource_docs_schemas(stepmod_dir)
32
+ filepath = File.join(stepmod_dir, "data/resource_docs/*/resource.xml")
33
+
34
+ schemas = {}
35
+ Dir.glob(filepath).each do |resource_docs_file|
36
+ match = resource_docs_file.match("data/resource_docs/([^/]+)/resource.xml")
37
+ resource_docs_dir = match.captures[0]
38
+
39
+ resource_docs = Nokogiri::XML(File.read(resource_docs_file)).root
40
+ resource_docs.xpath("schema").each do |schema|
41
+ schemas[schema["name"]] = resource_docs_dir
42
+ end
43
+ end
44
+
45
+ schemas
46
+ end
47
+
31
48
  def call
32
49
  match = File.basename(express_file).match('^(arm|mim|bom)\.exp$')
33
50
  descriptions_base = match ? "#{match.captures[0]}_descriptions.xml" : "descriptions.xml"
@@ -39,7 +56,7 @@ module Stepmod
39
56
  converted_description = ""
40
57
  base_linked = ""
41
58
 
42
- if File.exists?(descriptions_file)
59
+ if File.exist?(descriptions_file)
43
60
  descriptions = Nokogiri::XML(File.read(descriptions_file)).root
44
61
  added_resource_descriptions = {}
45
62
 
@@ -81,7 +98,7 @@ module Stepmod
81
98
  resource_docs_file_path(stepmod_dir, bib_file_name)
82
99
  end
83
100
 
84
- output_express << if bib_file && File.exists?(bib_file)
101
+ output_express << if bib_file && File.exist?(bib_file)
85
102
  prepend_bibdata(
86
103
  converted_description || "",
87
104
  # bib_file will not be present for resouces
@@ -107,10 +124,6 @@ module Stepmod
107
124
  file_content.gsub("(*)", "(`*`)")
108
125
  end
109
126
 
110
- def resource_docs_cache
111
- @resource_docs_cache ||= JSON.parse(File.read(resource_docs_cache_file))
112
- end
113
-
114
127
  def convert_from_description_text(descriptions_file, description)
115
128
  Dir.chdir(File.dirname(descriptions_file)) do
116
129
  wrapper = "<ext_descriptions>#{description}</ext_descriptions>"
@@ -16,6 +16,7 @@ module Stepmod
16
16
  # TODO: we may want a command line option to override this in the future
17
17
  ACCEPTED_STAGES = %w(IS DIS FDIS TS).freeze
18
18
  WITHDRAWN_STATUS = "withdrawn".freeze
19
+ REDUNDENT_NOTE_REGEX = /^An? .*? is a type of \{\{[^}]*\}\}\s*?\.?$/.freeze
19
20
 
20
21
  attr_reader :stepmod_path,
21
22
  :stepmod_dir,
@@ -86,8 +87,8 @@ module Stepmod
86
87
  arm_path = Pathname.new("#{stepmod_dir}/modules/#{x['name']}/arm_annotated.exp")
87
88
  mim_path = Pathname.new("#{stepmod_dir}/modules/#{x['name']}/mim_annotated.exp")
88
89
 
89
- files << arm_path if File.exists? arm_path
90
- files << mim_path if File.exists? mim_path
90
+ files << arm_path if File.exist? arm_path
91
+ files << mim_path if File.exist? mim_path
91
92
  end
92
93
 
93
94
  # Should ignore these because the `<resource_docs>` elements do not provide any EXPRESS schemas
@@ -104,7 +105,7 @@ module Stepmod
104
105
  next if x['status'] == WITHDRAWN_STATUS
105
106
 
106
107
  path = Pathname.new("#{stepmod_dir}/resources/#{x['name']}/#{x['name']}_annotated.exp")
107
- files << path if File.exists? path
108
+ files << path if File.exist? path
108
109
  end
109
110
 
110
111
  # Should ignore these because we are skiping Clause 3 terms
@@ -318,6 +319,8 @@ module Stepmod
318
319
  old_definition = trim_definition(entity.remarks.first)
319
320
  definition = generate_entity_definition(entity, domain)
320
321
 
322
+ notes = [old_definition].reject { |note| redundant_note?(note) }
323
+
321
324
  Stepmod::Utils::Concept.new(
322
325
  designations: [
323
326
  {
@@ -336,7 +339,7 @@ module Stepmod
336
339
  "link" => "https://www.iso.org/standard/32858.html",
337
340
  },
338
341
  ],
339
- notes: [old_definition].compact,
342
+ notes: notes,
340
343
  language_code: "en",
341
344
  part: bibdata.part,
342
345
  schema: schema,
@@ -512,6 +515,10 @@ module Stepmod
512
515
  REMARK
513
516
  end.join
514
517
  end
518
+
519
+ def redundant_note?(note)
520
+ note && note.match?(REDUNDENT_NOTE_REGEX) && !note.include?("\n")
521
+ end
515
522
  end
516
523
  end
517
524
  end
@@ -1,5 +1,5 @@
1
1
  module Stepmod
2
2
  module Utils
3
- VERSION = "0.3.24".freeze
3
+ VERSION = "0.3.25".freeze
4
4
  end
5
5
  end
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  spec.add_runtime_dependency "concurrent-ruby"
35
35
  spec.add_runtime_dependency "expressir"
36
- spec.add_runtime_dependency "glossarist-new", "~> 1.0.1"
36
+ spec.add_runtime_dependency "glossarist", "~> 1.0.5"
37
37
  spec.add_runtime_dependency "indefinite_article"
38
38
  spec.add_runtime_dependency "ptools"
39
39
  spec.add_runtime_dependency "pubid-iso"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stepmod-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.24
4
+ version: 0.3.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-24 00:00:00.000000000 Z
11
+ date: 2023-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: glossarist-new
42
+ name: glossarist
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.1
47
+ version: 1.0.5
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.1
54
+ version: 1.0.5
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: indefinite_article
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -171,17 +171,16 @@ email:
171
171
  - open.source@ribose.com
172
172
  executables:
173
173
  - stepmod-annotate-all
174
- - stepmod-build-resource-docs-cache
175
174
  - stepmod-convert-express-description
176
175
  - stepmod-convert-express-resource
177
- - stepmod-extract-terms
178
- - stepmod-extract-yaml-terms
179
- - stepmod-find-express-files
176
+ - stepmod-extract-changes
177
+ - stepmod-extract-concepts
180
178
  extensions: []
181
179
  extra_rdoc_files: []
182
180
  files:
183
181
  - ".github/workflows/rake.yml"
184
182
  - ".github/workflows/release.yml"
183
+ - ".github/workflows/test-concept-generation.yml"
185
184
  - ".gitignore"
186
185
  - ".hound.yml"
187
186
  - ".rspec"
@@ -194,14 +193,17 @@ files:
194
193
  - bin/console
195
194
  - bin/setup
196
195
  - exe/stepmod-annotate-all
197
- - exe/stepmod-build-resource-docs-cache
198
196
  - exe/stepmod-convert-express-description
199
197
  - exe/stepmod-convert-express-resource
200
- - exe/stepmod-extract-terms
201
- - exe/stepmod-extract-yaml-terms
202
- - exe/stepmod-find-express-files
198
+ - exe/stepmod-extract-changes
199
+ - exe/stepmod-extract-concepts
203
200
  - lib/stepmod/utils.rb
204
201
  - lib/stepmod/utils/bibdata.rb
202
+ - lib/stepmod/utils/change.rb
203
+ - lib/stepmod/utils/change_collection.rb
204
+ - lib/stepmod/utils/change_edition.rb
205
+ - lib/stepmod/utils/change_edition_collection.rb
206
+ - lib/stepmod/utils/changes_extractor.rb
205
207
  - lib/stepmod/utils/cleaner.rb
206
208
  - lib/stepmod/utils/concept.rb
207
209
  - lib/stepmod/utils/converters/a.rb
@@ -215,6 +217,7 @@ files:
215
217
  - lib/stepmod/utils/converters/dd.rb
216
218
  - lib/stepmod/utils/converters/def.rb
217
219
  - lib/stepmod/utils/converters/definition.rb
220
+ - lib/stepmod/utils/converters/description.rb
218
221
  - lib/stepmod/utils/converters/dl.rb
219
222
  - lib/stepmod/utils/converters/drop.rb
220
223
  - lib/stepmod/utils/converters/dt.rb
@@ -287,7 +290,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
290
  - !ruby/object:Gem::Version
288
291
  version: '0'
289
292
  requirements: []
290
- rubygems_version: 3.3.7
293
+ rubygems_version: 3.3.26
291
294
  signing_key:
292
295
  specification_version: 4
293
296
  summary: Stepmod-utils is a toolkit that works on STEPmod data.
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "nokogiri"
4
- require "json"
5
-
6
- stepmod_dir = ARGV.first || Dir.pwd
7
-
8
- schemas = {}
9
- Dir.glob(File.join(stepmod_dir,
10
- "data/resource_docs/*/resource.xml")).each do |resource_docs_file|
11
- match = resource_docs_file.match("data/resource_docs/([^/]+)/resource.xml")
12
- resource_docs_dir = match.captures[0]
13
-
14
- resource_docs = Nokogiri::XML(File.read(resource_docs_file)).root
15
- resource_docs.xpath("schema").each do |schema|
16
- schemas[schema["name"]] = resource_docs_dir
17
- end
18
- end
19
-
20
- puts JSON.pretty_generate(schemas)
@@ -1,237 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- require "pry"
5
- # resolve bin path, ignoring symlinks
6
- require "pathname"
7
- bin_file = Pathname.new(__FILE__).realpath
8
-
9
- # add self to libpath
10
- $:.unshift File.expand_path("../../lib", bin_file)
11
-
12
- # Fixes https://github.com/rubygems/rubygems/issues/1420
13
- require "rubygems/specification"
14
-
15
- module Gem
16
- class Specification
17
- def this; self; end
18
- end
19
- end
20
-
21
- require "bundler/setup"
22
- require "stepmod/utils/terms_extractor"
23
- require 'optparse'
24
-
25
- def log(message)
26
- puts "[stepmod-utils] #{message}"
27
- end
28
-
29
- options = {}
30
- OptionParser.new do |opts|
31
- opts.banner = "Usage: #{$0} [options]"
32
-
33
- opts.on("-p", "--path STEPMOD_DATA_PATH", String, "Path to STEPmod data directory") do |path|
34
- options[:stepmod_dir] = path
35
- end
36
-
37
- opts.on("-i", "--index INDEX_PATH", String, "Path to repository_index.xml") do |path|
38
- unless path.nil?
39
- options[:index_path] = Pathname.new(path).to_s
40
- end
41
- end
42
-
43
- opts.on_tail("-h", "--help", "Show this message") do
44
- puts opts
45
- exit
46
- end
47
- end.parse!
48
-
49
- stepmod_dir = options[:stepmod_dir]
50
- if stepmod_dir.nil?
51
- raise StandardError.new("STEPmod data path not set, set with the `-p` option.")
52
- else
53
- log "STEPmod data path: `#{stepmod_dir}`"
54
- end
55
-
56
- index_path = options[:index_path] || File.join(stepmod_dir, "repository_index.xml")
57
- unless File.exists?(index_path)
58
- raise StandardError.new("Index file not present at #{index_path}, set with the `-i` option.")
59
- else
60
- log "Repository index path: `#{index_path}`"
61
- end
62
-
63
- general_concepts,
64
- resource_concepts,
65
- parsed_bibliography,
66
- part_concepts,
67
- part_resources,
68
- part_modules = Stepmod::Utils::TermsExtractor.call(stepmod_dir, index_path)
69
-
70
- def part_to_title(bibdata)
71
- case bibdata.part.to_i
72
- when 41
73
- "Fundamentals of product description and support"
74
- when 42
75
- "Geometric and topological representation"
76
- when 43
77
- "Foundation representation"
78
- when 44
79
- "Product structure, concept and configuration"
80
- when 45
81
- "Material and other engineering properties"
82
- when 46
83
- "Visual presentation"
84
- when 47
85
- "Shape tolerance"
86
- when 51
87
- "Mathematical representation"
88
- else
89
- bibdata.title_en
90
- end
91
- end
92
-
93
- IMAGE_REPLACEMENTS = {
94
- 'image::eq01.gif[]' => 'stem:[H(A,B) = max {h(A, B), h(B,A)}]',
95
- 'image::eq02.gif[]' => 'stem:[max_{a in A} { min_{b in B} d(a,b) }]',
96
- 'image::vector_z_c.gif[]' => 'stem:[bar z_{c}]',
97
- 'image::one_direction_repeat_factor_expression.gif[]' => 'stem:[I + k cdot R; k = -1, 1]',
98
- 'image::two_direction_repeat_factor_expression.gif[]' => 'stem:[I + k_1 cdot R_1 + k_2 cdot R_2; k_1, k_2 = -1, 0, 1, k^2_1 + k^2_2 != 0]',
99
- }
100
-
101
- TEXT_REPLACEMENTS = {
102
- ' (see <module_ref linkend="ply_orientation_specification:4_entities:figure:f2"> Figure 2</module_ref>)' => '',
103
- ' (see <module_ref linkend="ply_orientation_specification:4_entities:figure:f3"> Figure 3</module_ref>)' => ''
104
- }
105
-
106
- def replace_content(content)
107
- IMAGE_REPLACEMENTS.each_pair do |k, v|
108
- content.gsub!(k, v)
109
- end
110
- TEXT_REPLACEMENTS.each_pair do |k, v|
111
- content.gsub!(k, v)
112
- end
113
-
114
- content
115
- end
116
-
117
- ## Skip all Clause 3 terms
118
- # part_concepts.each do |(bibdata, current_part_concepts)|
119
- # current_part_concepts = current_part_concepts.to_a.map do |n|
120
- # n.localizations["en"]
121
- # end
122
- # fn = "03x-stepmod-#{bibdata.part}.adoc"
123
- # File.open(fn, "w") do |file|
124
- # file.puts("== #{part_to_title(bibdata)}\n\n")
125
- # file.puts(replace_images(current_part_concepts.map(&:to_mn_adoc).join("\n")))
126
- # end
127
- # log "INFO: written to: #{fn}"
128
- # end
129
-
130
- # File.open("03x-stepmod.adoc", "w") do |file|
131
- # part_concepts.sort_by do |(bibdata, current_part_concepts)|
132
- # bibdata.part.to_i
133
- # end.each do |(bibdata, current_part_concepts)|
134
- # fn = "03x-stepmod-#{bibdata.part}.adoc"
135
- # file.puts("\ninclude::#{fn}[]\n")
136
- # end
137
- # end
138
-
139
- # log "INFO: written summary file to: 03x-stepmod.adoc"
140
-
141
- part_resources.each do |(bibdata, current_part_resources)|
142
- current_part_resources = current_part_resources.to_a.map do |n|
143
- n.localizations["en"]
144
- end
145
- fn = "04x-stepmod-entities-resources-#{bibdata.part}.adoc"
146
- File.open(fn, "w") do |file|
147
- # file.puts("== #{part_to_title(bibdata)}\n\n")
148
- file.puts(replace_content(current_part_resources.map(&:to_mn_adoc).join("\n")))
149
- end
150
- log "INFO: written to: #{fn}"
151
- end
152
-
153
- File.open("04x-stepmod-entities-resources.adoc", "w") do |file|
154
- part_resources.sort_by do |(bibdata, current_part_resources)|
155
- bibdata.part.to_i
156
- end.each do |(bibdata, current_part_resources)|
157
- fn = "04x-stepmod-entities-resources-#{bibdata.part}.adoc"
158
- file.puts("\ninclude::#{fn}[]\n")
159
- end
160
- end
161
-
162
- log "INFO: written summary file to: 04x-stepmod-entities-resources.adoc"
163
-
164
- part_modules.sort_by do |(bibdata, part_modules_arm, part_modules_mim)|
165
- bibdata.part.to_i
166
- end.each do |(bibdata, part_modules_arm, part_modules_mim)|
167
- fn = "05x-stepmod-entities-modules-#{bibdata.part}.adoc"
168
- File.open(fn, "w") do |file|
169
- file.puts("")
170
-
171
- unless part_modules_arm.empty?
172
- schema_name = part_modules_arm.first.first
173
- concepts = part_modules_arm.first.last.to_a.map do |n|
174
- n.localizations["en"]
175
- end
176
-
177
- # puts "SCHEMA NAME ARM: #{schema_name}"
178
- file.puts("== #{schema_name}\n\n")
179
- file.puts(concepts.map(&:to_mn_adoc).join("\n"))
180
- end
181
-
182
- file.puts("")
183
-
184
- unless part_modules_mim.empty?
185
- schema_name = part_modules_mim.first.first
186
-
187
- # puts "SCHEMA NAME MIM: #{schema_name}"
188
- concepts = part_modules_mim.first.last.to_a.map do |n|
189
- n.localizations["en"]
190
- end
191
- file.puts("== #{schema_name}\n\n")
192
- file.puts(replace_content(concepts.map(&:to_mn_adoc).join("\n")))
193
- end
194
- end
195
-
196
- log "INFO: written to: #{fn}"
197
- end
198
-
199
- File.open("05x-stepmod-entities-modules.adoc", "w") do |file|
200
- part_modules.sort_by do |(bibdata, part_modules_arm, part_modules_mim)|
201
- bibdata.part.to_i
202
- end.each do |(bibdata, part_modules_arm, part_modules_mim)|
203
- fn = "05x-stepmod-entities-modules-#{bibdata.part}.adoc"
204
- file.puts("\ninclude::#{fn}[]\n")
205
- end
206
- end
207
-
208
- log "INFO: written summary file to: 05x-stepmod-entities-modules.adoc"
209
-
210
- ## Skipping all Clause 3 terms
211
- # File.open("031-stepmod-general.adoc", "w") do |file|
212
- # file.puts(
213
- # replace_images(
214
- # general_concepts.to_a.map do |n|
215
- # n.localizations["en"]
216
- # end.map(&:to_mn_adoc).join("\n")
217
- # )
218
- # )
219
- # end
220
-
221
- # log "INFO: written to: 031-stepmod-general.adoc"
222
-
223
- File.open("041-stepmod-entities-resources.adoc", "w") do |file|
224
- file.puts(
225
- replace_content(
226
- resource_concepts.to_a.map do |n|
227
- n.localizations["en"]
228
- end.map(&:to_mn_adoc).join("\n")
229
- )
230
- )
231
- end
232
- log "INFO: written to: 041-stepmod-entities-resources.adoc"
233
-
234
- File.open("991-generated-bibliography.adoc", "w") do |file|
235
- file.puts(parsed_bibliography.map(&:to_mn_adoc).sort.uniq.join("\n"))
236
- end
237
- log "INFO: written to: 991-generated-bibliography.adoc"
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "nokogiri"
4
-
5
- stepmod_dir = ARGV.first || Dir.pwd
6
-
7
- index = Nokogiri::XML(File.read(File.join(stepmod_dir,
8
- "repository_index.xml"))).root
9
-
10
- files = []
11
- index.xpath("modules/module").each do |item|
12
- files << "#{stepmod_dir}/data/modules/#{item['name']}/arm.exp"
13
- files << "#{stepmod_dir}/data/modules/#{item['name']}/mim.exp"
14
- end
15
- index.xpath("resources/resource").each do |item|
16
- files << "#{stepmod_dir}/data/resources/#{item['name']}/#{item['name']}.exp"
17
- end
18
- index.xpath("business_object_models/business_object_model").each do |item|
19
- files << "#{stepmod_dir}/data/business_object_models/#{item['name']}/bom.exp"
20
- files << "#{stepmod_dir}/data/business_object_models/#{item['name']}/DomainModel.exp"
21
- end
22
-
23
- existing_files = files.filter { |file| File.exists?(file) }
24
- puts existing_files