unitsdb 1.0.0 → 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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/.rspec +2 -1
  4. data/.rubocop_todo.yml +168 -15
  5. data/Gemfile +3 -2
  6. data/README.adoc +803 -1
  7. data/exe/unitsdb +7 -0
  8. data/lib/unitsdb/cli.rb +88 -0
  9. data/lib/unitsdb/commands/_modify.rb +22 -0
  10. data/lib/unitsdb/commands/base.rb +26 -0
  11. data/lib/unitsdb/commands/check_si.rb +124 -0
  12. data/lib/unitsdb/commands/get.rb +133 -0
  13. data/lib/unitsdb/commands/normalize.rb +81 -0
  14. data/lib/unitsdb/commands/release.rb +73 -0
  15. data/lib/unitsdb/commands/search.rb +219 -0
  16. data/lib/unitsdb/commands/si_formatter.rb +485 -0
  17. data/lib/unitsdb/commands/si_matcher.rb +470 -0
  18. data/lib/unitsdb/commands/si_ttl_parser.rb +100 -0
  19. data/lib/unitsdb/commands/si_updater.rb +212 -0
  20. data/lib/unitsdb/commands/ucum/check.rb +126 -0
  21. data/lib/unitsdb/commands/ucum/formatter.rb +141 -0
  22. data/lib/unitsdb/commands/ucum/matcher.rb +301 -0
  23. data/lib/unitsdb/commands/ucum/update.rb +84 -0
  24. data/lib/unitsdb/commands/ucum/updater.rb +98 -0
  25. data/lib/unitsdb/commands/ucum/xml_parser.rb +34 -0
  26. data/lib/unitsdb/commands/ucum.rb +43 -0
  27. data/lib/unitsdb/commands/validate/identifiers.rb +42 -0
  28. data/lib/unitsdb/commands/validate/references.rb +318 -0
  29. data/lib/unitsdb/commands/validate/si_references.rb +109 -0
  30. data/lib/unitsdb/commands/validate.rb +40 -0
  31. data/lib/unitsdb/database.rb +662 -0
  32. data/lib/unitsdb/dimension.rb +49 -0
  33. data/lib/unitsdb/dimension_details.rb +20 -0
  34. data/lib/unitsdb/dimension_reference.rb +8 -0
  35. data/lib/unitsdb/dimensions.rb +5 -10
  36. data/lib/unitsdb/errors.rb +13 -0
  37. data/lib/unitsdb/external_reference.rb +14 -0
  38. data/lib/unitsdb/identifier.rb +8 -0
  39. data/lib/unitsdb/localized_string.rb +17 -0
  40. data/lib/unitsdb/prefix.rb +30 -0
  41. data/lib/unitsdb/prefix_reference.rb +10 -0
  42. data/lib/unitsdb/prefixes.rb +5 -11
  43. data/lib/unitsdb/quantities.rb +5 -31
  44. data/lib/unitsdb/quantity.rb +21 -0
  45. data/lib/unitsdb/quantity_reference.rb +10 -0
  46. data/lib/unitsdb/root_unit_reference.rb +14 -0
  47. data/lib/unitsdb/scale.rb +17 -0
  48. data/lib/unitsdb/scale_properties.rb +12 -0
  49. data/lib/unitsdb/scale_reference.rb +10 -0
  50. data/lib/unitsdb/scales.rb +12 -0
  51. data/lib/unitsdb/si_derived_base.rb +19 -0
  52. data/lib/unitsdb/symbol_presentations.rb +3 -8
  53. data/lib/unitsdb/ucum.rb +198 -0
  54. data/lib/unitsdb/unit.rb +63 -0
  55. data/lib/unitsdb/unit_reference.rb +10 -0
  56. data/lib/unitsdb/unit_system.rb +15 -0
  57. data/lib/unitsdb/unit_system_reference.rb +10 -0
  58. data/lib/unitsdb/unit_systems.rb +5 -10
  59. data/lib/unitsdb/units.rb +5 -10
  60. data/lib/unitsdb/utils.rb +84 -0
  61. data/lib/unitsdb/version.rb +1 -1
  62. data/lib/unitsdb.rb +12 -2
  63. data/unitsdb.gemspec +6 -3
  64. metadata +124 -20
  65. data/lib/unitsdb/dimensions/dimension.rb +0 -59
  66. data/lib/unitsdb/dimensions/quantity.rb +0 -32
  67. data/lib/unitsdb/dimensions/symbol.rb +0 -26
  68. data/lib/unitsdb/prefixes/prefix.rb +0 -35
  69. data/lib/unitsdb/prefixes/symbol.rb +0 -17
  70. data/lib/unitsdb/quantities/quantity.rb +0 -37
  71. data/lib/unitsdb/quantities/unit_reference.rb +0 -15
  72. data/lib/unitsdb/unit_systems/unit_system.rb +0 -19
  73. data/lib/unitsdb/units/quantity_reference.rb +0 -17
  74. data/lib/unitsdb/units/root_unit.rb +0 -21
  75. data/lib/unitsdb/units/root_units.rb +0 -18
  76. data/lib/unitsdb/units/si_derived_base.rb +0 -26
  77. data/lib/unitsdb/units/symbol.rb +0 -19
  78. data/lib/unitsdb/units/system.rb +0 -17
  79. data/lib/unitsdb/units/unit.rb +0 -73
  80. 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