unitsdb 0.1.1 → 2.0.1
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/.github/workflows/dependent-repos.json +5 -0
- data/.github/workflows/depenedent-gems.yml +16 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -1
- data/.rubocop_todo.yml +168 -15
- data/Gemfile +3 -2
- data/README.adoc +803 -1
- data/exe/unitsdb +7 -0
- data/lib/unitsdb/cli.rb +88 -0
- data/lib/unitsdb/commands/_modify.rb +22 -0
- data/lib/unitsdb/commands/base.rb +26 -0
- data/lib/unitsdb/commands/check_si.rb +124 -0
- data/lib/unitsdb/commands/get.rb +133 -0
- data/lib/unitsdb/commands/normalize.rb +81 -0
- data/lib/unitsdb/commands/release.rb +73 -0
- data/lib/unitsdb/commands/search.rb +219 -0
- data/lib/unitsdb/commands/si_formatter.rb +485 -0
- data/lib/unitsdb/commands/si_matcher.rb +470 -0
- data/lib/unitsdb/commands/si_ttl_parser.rb +100 -0
- data/lib/unitsdb/commands/si_updater.rb +212 -0
- data/lib/unitsdb/commands/ucum/check.rb +126 -0
- data/lib/unitsdb/commands/ucum/formatter.rb +141 -0
- data/lib/unitsdb/commands/ucum/matcher.rb +301 -0
- data/lib/unitsdb/commands/ucum/update.rb +84 -0
- data/lib/unitsdb/commands/ucum/updater.rb +98 -0
- data/lib/unitsdb/commands/ucum/xml_parser.rb +34 -0
- data/lib/unitsdb/commands/ucum.rb +43 -0
- data/lib/unitsdb/commands/validate/identifiers.rb +42 -0
- data/lib/unitsdb/commands/validate/references.rb +318 -0
- data/lib/unitsdb/commands/validate/si_references.rb +109 -0
- data/lib/unitsdb/commands/validate.rb +40 -0
- data/lib/unitsdb/config.rb +19 -0
- data/lib/unitsdb/database.rb +662 -0
- data/lib/unitsdb/dimension.rb +19 -25
- data/lib/unitsdb/dimension_details.rb +20 -0
- data/lib/unitsdb/dimension_reference.rb +8 -0
- data/lib/unitsdb/dimensions.rb +4 -6
- data/lib/unitsdb/errors.rb +13 -0
- data/lib/unitsdb/external_reference.rb +14 -0
- data/lib/unitsdb/identifier.rb +8 -0
- data/lib/unitsdb/localized_string.rb +17 -0
- data/lib/unitsdb/prefix.rb +11 -12
- data/lib/unitsdb/prefix_reference.rb +10 -0
- data/lib/unitsdb/prefixes.rb +4 -6
- data/lib/unitsdb/quantities.rb +4 -27
- data/lib/unitsdb/quantity.rb +12 -24
- data/lib/unitsdb/quantity_reference.rb +4 -7
- data/lib/unitsdb/root_unit_reference.rb +14 -0
- data/lib/unitsdb/scale.rb +17 -0
- data/lib/unitsdb/scale_properties.rb +12 -0
- data/lib/unitsdb/scale_reference.rb +10 -0
- data/lib/unitsdb/scales.rb +12 -0
- data/lib/unitsdb/si_derived_base.rb +13 -14
- data/lib/unitsdb/symbol_presentations.rb +14 -0
- data/lib/unitsdb/ucum.rb +198 -0
- data/lib/unitsdb/unit.rb +20 -26
- data/lib/unitsdb/unit_reference.rb +5 -8
- data/lib/unitsdb/unit_system.rb +8 -10
- data/lib/unitsdb/unit_system_reference.rb +10 -0
- data/lib/unitsdb/unit_systems.rb +4 -16
- data/lib/unitsdb/units.rb +4 -6
- data/lib/unitsdb/utils.rb +84 -0
- data/lib/unitsdb/version.rb +1 -1
- data/lib/unitsdb.rb +13 -10
- data/unitsdb.gemspec +6 -3
- metadata +120 -12
- data/lib/unitsdb/dimension_quantity.rb +0 -28
- data/lib/unitsdb/dimension_symbol.rb +0 -22
- data/lib/unitsdb/prefix_symbol.rb +0 -12
- data/lib/unitsdb/root_unit.rb +0 -17
- data/lib/unitsdb/root_units.rb +0 -20
- data/lib/unitsdb/symbol.rb +0 -17
- data/lib/unitsdb/unit_symbol.rb +0 -15
- data/lib/unitsdb/unitsdb.rb +0 -6
@@ -0,0 +1,212 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
module Unitsdb
|
7
|
+
module Commands
|
8
|
+
# Updater for SI references in YAML
|
9
|
+
module SiUpdater
|
10
|
+
SI_AUTHORITY = "si-digital-framework"
|
11
|
+
|
12
|
+
module_function
|
13
|
+
|
14
|
+
# Update references in YAML file (TTL → DB direction)
|
15
|
+
def update_references(entity_type, missing_matches, db_entities, output_file, include_potential = false)
|
16
|
+
# Use the database objects to access the data directly
|
17
|
+
original_yaml_file = db_entities.first.send(:yaml_file) if db_entities&.first.respond_to?(:yaml_file, true)
|
18
|
+
|
19
|
+
# If we can't get the path from the database object, use the output file path as a fallback
|
20
|
+
if original_yaml_file.nil? || !File.exist?(original_yaml_file)
|
21
|
+
puts "Warning: Could not determine original YAML file path. Using output file as template."
|
22
|
+
original_yaml_file = output_file
|
23
|
+
|
24
|
+
# Create an empty template if output file doesn't exist
|
25
|
+
unless File.exist?(original_yaml_file)
|
26
|
+
FileUtils.mkdir_p(File.dirname(original_yaml_file))
|
27
|
+
File.write(original_yaml_file, { entity_type => [] }.to_yaml)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Load the original YAML file
|
32
|
+
yaml_content = File.read(original_yaml_file)
|
33
|
+
output_data = YAML.safe_load(yaml_content)
|
34
|
+
|
35
|
+
# Group by entity ID to avoid duplicates
|
36
|
+
grouped_matches = missing_matches.group_by { |match| match[:entity_id] }
|
37
|
+
|
38
|
+
# Process each entity that needs updating
|
39
|
+
grouped_matches.each do |entity_id, matches|
|
40
|
+
# Filter matches based on include_potential parameter
|
41
|
+
filtered_matches = matches.select do |match|
|
42
|
+
# Check if it's an exact match or if we're including potential matches
|
43
|
+
match_details = match[:match_details]
|
44
|
+
if match_details&.dig(:exact) == false || %w[symbol_match
|
45
|
+
partial_match].include?(match_details&.dig(:match_desc) || "")
|
46
|
+
include_potential
|
47
|
+
else
|
48
|
+
true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Skip if no matches after filtering
|
53
|
+
next if filtered_matches.empty?
|
54
|
+
|
55
|
+
# Find the entity in the array under the entity_type key
|
56
|
+
entity_index = output_data[entity_type].find_index do |e|
|
57
|
+
# Find entity with matching identifier
|
58
|
+
e["identifiers"]&.any? { |id| id["id"] == entity_id }
|
59
|
+
end
|
60
|
+
|
61
|
+
next unless entity_index
|
62
|
+
|
63
|
+
# Get the entity
|
64
|
+
entity = output_data[entity_type][entity_index]
|
65
|
+
|
66
|
+
# Initialize references array if it doesn't exist
|
67
|
+
entity["references"] ||= []
|
68
|
+
|
69
|
+
# Add new references
|
70
|
+
filtered_matches.each do |match|
|
71
|
+
# If this match has multiple SI references, add them all
|
72
|
+
if match[:multiple_si]
|
73
|
+
match[:multiple_si].each do |si_data|
|
74
|
+
# Check if reference already exists
|
75
|
+
next if entity["references"].any? do |ref|
|
76
|
+
ref["uri"] == si_data[:uri] && ref["authority"] == SI_AUTHORITY
|
77
|
+
end
|
78
|
+
|
79
|
+
# Add new reference
|
80
|
+
entity["references"] << {
|
81
|
+
"uri" => si_data[:uri],
|
82
|
+
"type" => "normative",
|
83
|
+
"authority" => SI_AUTHORITY
|
84
|
+
}
|
85
|
+
end
|
86
|
+
else
|
87
|
+
# Check if reference already exists
|
88
|
+
next if entity["references"].any? do |ref|
|
89
|
+
ref["uri"] == match[:si_uri] && ref["authority"] == SI_AUTHORITY
|
90
|
+
end
|
91
|
+
|
92
|
+
# Add new reference
|
93
|
+
entity["references"] << {
|
94
|
+
"uri" => match[:si_uri],
|
95
|
+
"type" => "normative",
|
96
|
+
"authority" => SI_AUTHORITY
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
write_yaml_file(output_file, output_data)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Update references in YAML file (DB → TTL direction)
|
106
|
+
def update_db_references(entity_type, missing_refs, output_file, include_potential = false)
|
107
|
+
# Try to get the original YAML file from the first entity
|
108
|
+
first_entity = missing_refs.first&.dig(:db_entity)
|
109
|
+
original_yaml_file = first_entity.send(:yaml_file) if first_entity.respond_to?(:yaml_file, true)
|
110
|
+
|
111
|
+
# If we can't get the path from the database object, use the output file path as a fallback
|
112
|
+
if original_yaml_file.nil? || !File.exist?(original_yaml_file)
|
113
|
+
puts "Warning: Could not determine original YAML file path. Using output file as template."
|
114
|
+
original_yaml_file = output_file
|
115
|
+
|
116
|
+
# Create an empty template if output file doesn't exist
|
117
|
+
unless File.exist?(original_yaml_file)
|
118
|
+
FileUtils.mkdir_p(File.dirname(original_yaml_file))
|
119
|
+
File.write(original_yaml_file, { entity_type => [] }.to_yaml)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Load the original YAML file
|
124
|
+
yaml_content = File.read(original_yaml_file)
|
125
|
+
output_data = YAML.safe_load(yaml_content)
|
126
|
+
|
127
|
+
# Group by entity ID to avoid duplicates
|
128
|
+
missing_refs_by_id = {}
|
129
|
+
|
130
|
+
missing_refs.each do |match|
|
131
|
+
entity_id = match[:entity_id] || match[:db_entity].short
|
132
|
+
ttl_entities = match[:ttl_entities]
|
133
|
+
match_types = match[:match_types] || {}
|
134
|
+
|
135
|
+
# Filter TTL entities based on include_potential parameter
|
136
|
+
filtered_ttl_entities = ttl_entities.select do |ttl_entity|
|
137
|
+
# Check if it's an exact match or if we're including potential matches
|
138
|
+
match_type = match_types[ttl_entity[:uri]] || "Exact match" # Default to exact match
|
139
|
+
match_pair_key = "#{entity_id}:#{ttl_entity[:uri]}"
|
140
|
+
match_details = Unitsdb::Commands::SiMatcher.instance_variable_get(:@match_details)&.dig(match_pair_key)
|
141
|
+
|
142
|
+
if match_details && %w[symbol_match partial_match].include?(match_details[:match_desc])
|
143
|
+
include_potential
|
144
|
+
else
|
145
|
+
match_type == "Exact match" || include_potential
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Skip if no entities after filtering
|
150
|
+
next if filtered_ttl_entities.empty?
|
151
|
+
|
152
|
+
missing_refs_by_id[entity_id] ||= []
|
153
|
+
|
154
|
+
# Add filtered matching TTL entities for this DB entity
|
155
|
+
filtered_ttl_entities.each do |ttl_entity|
|
156
|
+
missing_refs_by_id[entity_id] << {
|
157
|
+
uri: ttl_entity[:uri],
|
158
|
+
type: "normative",
|
159
|
+
authority: SI_AUTHORITY
|
160
|
+
}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Update the YAML content
|
165
|
+
output_data[entity_type].each do |entity_yaml|
|
166
|
+
# Find entity by ID or short
|
167
|
+
entity_id = if entity_yaml["identifiers"]
|
168
|
+
begin
|
169
|
+
entity_yaml["identifiers"].first["id"]
|
170
|
+
rescue StandardError
|
171
|
+
nil
|
172
|
+
end
|
173
|
+
elsif entity_yaml["id"]
|
174
|
+
entity_yaml["id"]
|
175
|
+
end
|
176
|
+
|
177
|
+
next unless entity_id && missing_refs_by_id.key?(entity_id)
|
178
|
+
|
179
|
+
# Add references
|
180
|
+
entity_yaml["references"] ||= []
|
181
|
+
|
182
|
+
missing_refs_by_id[entity_id].each do |ref|
|
183
|
+
# Check if this reference already exists
|
184
|
+
next if entity_yaml["references"].any? do |existing_ref|
|
185
|
+
existing_ref["uri"] == ref[:uri] &&
|
186
|
+
existing_ref["authority"] == ref[:authority]
|
187
|
+
end
|
188
|
+
|
189
|
+
# Add the reference
|
190
|
+
entity_yaml["references"] << {
|
191
|
+
"uri" => ref[:uri],
|
192
|
+
"type" => ref[:type],
|
193
|
+
"authority" => ref[:authority]
|
194
|
+
}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
write_yaml_file(output_file, output_data)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Helper to write YAML file
|
202
|
+
def write_yaml_file(output_file, output_data)
|
203
|
+
# Ensure the output directory exists
|
204
|
+
output_dir = File.dirname(output_file)
|
205
|
+
FileUtils.mkdir_p(output_dir) unless Dir.exist?(output_dir)
|
206
|
+
|
207
|
+
# Write to YAML file
|
208
|
+
File.write(output_file, output_data.to_yaml)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../base"
|
4
|
+
require_relative "../../database"
|
5
|
+
require_relative "../../errors"
|
6
|
+
require_relative "xml_parser"
|
7
|
+
require_relative "formatter"
|
8
|
+
require_relative "matcher"
|
9
|
+
require_relative "updater"
|
10
|
+
require "fileutils"
|
11
|
+
|
12
|
+
module Unitsdb
|
13
|
+
module Commands
|
14
|
+
module Ucum
|
15
|
+
class Check < Base
|
16
|
+
# Constants
|
17
|
+
ENTITY_TYPES = %w[units prefixes].freeze
|
18
|
+
|
19
|
+
def run
|
20
|
+
# Get options
|
21
|
+
entity_type = @options[:entity_type]&.downcase
|
22
|
+
direction = @options[:direction]&.downcase || "both"
|
23
|
+
output_dir = @options[:output_updated_database]
|
24
|
+
include_potential = @options[:include_potential_matches] || false
|
25
|
+
database_path = @options[:database]
|
26
|
+
ucum_file = @options[:ucum_file]
|
27
|
+
|
28
|
+
# Validate parameters
|
29
|
+
validate_parameters(direction, ucum_file)
|
30
|
+
|
31
|
+
# Use the path as-is without expansion
|
32
|
+
puts "Using database directory: #{database_path}"
|
33
|
+
|
34
|
+
@db = Unitsdb::Database.from_db(database_path)
|
35
|
+
|
36
|
+
puts "Using UCUM file: #{ucum_file}"
|
37
|
+
puts "Include potential matches: #{include_potential ? "Yes" : "No"}"
|
38
|
+
|
39
|
+
# Parse UCUM XML file
|
40
|
+
ucum_data = XmlParser.parse_ucum_file(ucum_file)
|
41
|
+
|
42
|
+
# Process entity types
|
43
|
+
process_entities(entity_type, ucum_data, direction, output_dir, include_potential)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Process all entity types or a specific one
|
49
|
+
def process_entities(entity_type, ucum_data, direction, output_dir, include_potential)
|
50
|
+
if entity_type && ENTITY_TYPES.include?(entity_type)
|
51
|
+
process_entity_type(entity_type, ucum_data, direction, output_dir, include_potential)
|
52
|
+
else
|
53
|
+
ENTITY_TYPES.each do |type|
|
54
|
+
process_entity_type(type, ucum_data, direction, output_dir, include_potential)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Process a specific entity type
|
60
|
+
def process_entity_type(entity_type, ucum_data, direction, output_dir, include_potential = false)
|
61
|
+
puts "\n========== Processing #{entity_type.upcase} References ==========\n"
|
62
|
+
|
63
|
+
db_entities = @db.send(entity_type)
|
64
|
+
ucum_entities = XmlParser.get_entities_from_ucum(entity_type, ucum_data)
|
65
|
+
|
66
|
+
puts "Found #{ucum_entities.size} #{entity_type} in UCUM"
|
67
|
+
puts "Found #{db_entities.size} #{entity_type} in database"
|
68
|
+
|
69
|
+
check_from_ucum(entity_type, ucum_entities, db_entities, output_dir, include_potential) if %w[from_ucum
|
70
|
+
both].include?(direction)
|
71
|
+
|
72
|
+
return unless %w[to_ucum both].include?(direction)
|
73
|
+
|
74
|
+
check_to_ucum(entity_type, ucum_entities, db_entities, output_dir, include_potential)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Validation helpers
|
78
|
+
def validate_parameters(direction, ucum_file)
|
79
|
+
unless %w[to_ucum from_ucum both].include?(direction)
|
80
|
+
puts "Invalid direction: #{direction}. Must be one of: to_ucum, from_ucum, both"
|
81
|
+
exit(1)
|
82
|
+
end
|
83
|
+
|
84
|
+
return if File.exist?(ucum_file)
|
85
|
+
|
86
|
+
puts "UCUM file not found: #{ucum_file}"
|
87
|
+
exit(1)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Direction handler: UCUM → UnitsDB
|
91
|
+
def check_from_ucum(entity_type, ucum_entities, db_entities, output_dir, include_potential = false)
|
92
|
+
Formatter.print_direction_header("UCUM → UnitsDB")
|
93
|
+
|
94
|
+
matches, missing_matches, unmatched_ucum = Matcher.match_ucum_to_db(entity_type, ucum_entities, db_entities)
|
95
|
+
|
96
|
+
# Print results
|
97
|
+
Formatter.display_ucum_results(entity_type, matches, missing_matches, unmatched_ucum)
|
98
|
+
|
99
|
+
# Update references if needed
|
100
|
+
return unless output_dir && !missing_matches.empty?
|
101
|
+
|
102
|
+
output_file = File.join(output_dir, "#{entity_type}.yaml")
|
103
|
+
Updater.update_references(entity_type, missing_matches, db_entities, output_file, include_potential)
|
104
|
+
puts "\nUpdated references written to #{output_file}"
|
105
|
+
end
|
106
|
+
|
107
|
+
# Direction handler: UnitsDB → UCUM
|
108
|
+
def check_to_ucum(entity_type, ucum_entities, db_entities, output_dir, include_potential = false)
|
109
|
+
Formatter.print_direction_header("UnitsDB → UCUM")
|
110
|
+
|
111
|
+
matches, missing_refs, unmatched_db = Matcher.match_db_to_ucum(entity_type, ucum_entities, db_entities)
|
112
|
+
|
113
|
+
# Print results
|
114
|
+
Formatter.display_db_results(entity_type, matches, missing_refs, unmatched_db)
|
115
|
+
|
116
|
+
# Update references if needed
|
117
|
+
return unless output_dir && !missing_refs.empty?
|
118
|
+
|
119
|
+
output_file = File.join(output_dir, "#{entity_type}.yaml")
|
120
|
+
Updater.update_references(entity_type, missing_refs, db_entities, output_file, include_potential)
|
121
|
+
puts "\nUpdated references written to #{output_file}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Unitsdb
|
4
|
+
module Commands
|
5
|
+
module Ucum
|
6
|
+
# Formats output for UCUM matching results
|
7
|
+
module Formatter
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# Print a direction header (UnitsDB → UCUM or UCUM → UnitsDB)
|
11
|
+
def print_direction_header(direction)
|
12
|
+
puts "\n=== #{direction} ===\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Display results for UCUM → UnitsDB matching
|
16
|
+
def display_ucum_results(entity_type, matches, missing_matches, unmatched_ucum)
|
17
|
+
puts "\nResults for #{entity_type.capitalize} (UCUM → UnitsDB):"
|
18
|
+
puts " Matched: #{matches.size}"
|
19
|
+
puts " Missing matches (could be added): #{missing_matches.size}"
|
20
|
+
puts " Unmatched UCUM entities: #{unmatched_ucum.size}"
|
21
|
+
|
22
|
+
unless unmatched_ucum.empty?
|
23
|
+
puts "\nUnmatched UCUM #{entity_type}:"
|
24
|
+
unmatched_ucum.each do |entity|
|
25
|
+
case entity
|
26
|
+
when Unitsdb::UcumPrefix
|
27
|
+
puts " - #{entity.name} (#{entity.code_sensitive})"
|
28
|
+
when Unitsdb::UcumBaseUnit
|
29
|
+
puts " - #{entity.name} (#{entity.code_sensitive}, dimension: #{entity.dimension})"
|
30
|
+
when Unitsdb::UcumUnit
|
31
|
+
name = entity.name.is_a?(Array) ? entity.name.first : entity.name
|
32
|
+
puts " - #{name} (#{entity.code_sensitive}, class: #{entity.klass})"
|
33
|
+
else
|
34
|
+
puts " - Unknown entity type"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
return if missing_matches.empty?
|
40
|
+
|
41
|
+
puts "\nPotential additions (UCUM #{entity_type} that could be added to UnitsDB):"
|
42
|
+
missing_matches.each do |match|
|
43
|
+
ucum_entity = match[:ucum_entity]
|
44
|
+
db_entity = match[:db_entity]
|
45
|
+
|
46
|
+
# Get entity IDs and names
|
47
|
+
db_id = get_db_entity_id(db_entity)
|
48
|
+
db_name = get_db_entity_name(db_entity)
|
49
|
+
ucum_name = get_ucum_entity_name(ucum_entity)
|
50
|
+
ucum_code = ucum_entity.respond_to?(:code_sensitive) ? ucum_entity.code_sensitive : "unknown"
|
51
|
+
|
52
|
+
case ucum_entity
|
53
|
+
when Unitsdb::UcumPrefix
|
54
|
+
puts " - UnitsDB prefix '#{db_name}' (#{db_id}) → UCUM prefix '#{ucum_name}' (#{ucum_code})"
|
55
|
+
when Unitsdb::UcumBaseUnit
|
56
|
+
puts " - UnitsDB unit '#{db_name}' (#{db_id}) → UCUM base unit '#{ucum_name}' (#{ucum_code})"
|
57
|
+
when Unitsdb::UcumUnit
|
58
|
+
puts " - UnitsDB unit '#{db_name}' (#{db_id}) → UCUM unit '#{ucum_name}' (#{ucum_code})"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Display results for UnitsDB → UCUM matching
|
64
|
+
def display_db_results(entity_type, matches, missing_refs, unmatched_db)
|
65
|
+
puts "\nResults for #{entity_type.capitalize} (UnitsDB → UCUM):"
|
66
|
+
puts " Matched: #{matches.size}"
|
67
|
+
puts " Missing references (could be added): #{missing_refs.size}"
|
68
|
+
puts " Unmatched UnitsDB entities: #{unmatched_db.size}"
|
69
|
+
|
70
|
+
unless unmatched_db.empty?
|
71
|
+
puts "\nUnmatched UnitsDB #{entity_type}:"
|
72
|
+
unmatched_db.each do |entity|
|
73
|
+
id = get_db_entity_id(entity)
|
74
|
+
name = get_db_entity_name(entity)
|
75
|
+
puts " - #{name} (#{id})"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
return if missing_refs.empty?
|
80
|
+
|
81
|
+
puts "\nPotential references (UCUM references that could be added to UnitsDB):"
|
82
|
+
missing_refs.each do |match|
|
83
|
+
ucum_entity = match[:ucum_entity]
|
84
|
+
db_entity = match[:db_entity]
|
85
|
+
|
86
|
+
# Get entity IDs and names
|
87
|
+
db_id = get_db_entity_id(db_entity)
|
88
|
+
db_name = get_db_entity_name(db_entity)
|
89
|
+
ucum_name = get_ucum_entity_name(ucum_entity)
|
90
|
+
ucum_code = ucum_entity.respond_to?(:code_sensitive) ? ucum_entity.code_sensitive : "unknown"
|
91
|
+
|
92
|
+
case ucum_entity
|
93
|
+
when Unitsdb::UcumPrefix
|
94
|
+
puts " - UnitsDB prefix '#{db_name}' (#{db_id}) → UCUM prefix '#{ucum_name}' (#{ucum_code})"
|
95
|
+
when Unitsdb::UcumBaseUnit
|
96
|
+
puts " - UnitsDB unit '#{db_name}' (#{db_id}) → UCUM base unit '#{ucum_name}' (#{ucum_code})"
|
97
|
+
when Unitsdb::UcumUnit
|
98
|
+
puts " - UnitsDB unit '#{db_name}' (#{db_id}) → UCUM unit '#{ucum_name}' (#{ucum_code})"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Helper to get db entity id
|
104
|
+
def get_db_entity_id(entity)
|
105
|
+
if entity.respond_to?(:identifiers) && entity.identifiers && !entity.identifiers.empty?
|
106
|
+
entity.identifiers.first.id
|
107
|
+
elsif entity.respond_to?(:id)
|
108
|
+
entity.id
|
109
|
+
else
|
110
|
+
"unknown-id"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Helper to get db entity name
|
115
|
+
def get_db_entity_name(entity)
|
116
|
+
if entity.respond_to?(:names) && entity.names && !entity.names.empty?
|
117
|
+
entity.names.first.value
|
118
|
+
elsif entity.respond_to?(:short) && entity.short
|
119
|
+
entity.short
|
120
|
+
elsif entity.respond_to?(:name)
|
121
|
+
entity.name
|
122
|
+
else
|
123
|
+
"unknown-name"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Helper to get ucum entity name
|
128
|
+
def get_ucum_entity_name(entity)
|
129
|
+
case entity
|
130
|
+
when Unitsdb::UcumPrefix, Unitsdb::UcumBaseUnit
|
131
|
+
entity.name
|
132
|
+
when Unitsdb::UcumUnit
|
133
|
+
entity.name.is_a?(Array) ? entity.name.first : entity.name
|
134
|
+
else
|
135
|
+
"unknown-name"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|