unitsdb 2.1.0 → 2.2.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +8 -1
  3. data/.gitignore +2 -0
  4. data/.gitmodules +4 -3
  5. data/.rubocop.yml +13 -8
  6. data/.rubocop_todo.yml +247 -53
  7. data/CLAUDE.md +55 -0
  8. data/Gemfile +5 -1
  9. data/README.adoc +385 -12
  10. data/data/dimensions.yaml +1864 -0
  11. data/data/prefixes.yaml +874 -0
  12. data/data/quantities.yaml +3715 -0
  13. data/data/scales.yaml +97 -0
  14. data/data/schemas/dimensions-schema.yaml +153 -0
  15. data/data/schemas/prefixes-schema.yaml +155 -0
  16. data/data/schemas/quantities-schema.yaml +117 -0
  17. data/data/schemas/scales-schema.yaml +106 -0
  18. data/data/schemas/unit_systems-schema.yaml +116 -0
  19. data/data/schemas/units-schema.yaml +215 -0
  20. data/data/unit_systems.yaml +78 -0
  21. data/data/units.yaml +14052 -0
  22. data/exe/unitsdb +7 -1
  23. data/lib/unitsdb/cli.rb +47 -13
  24. data/lib/unitsdb/commands/_modify.rb +41 -5
  25. data/lib/unitsdb/commands/base.rb +10 -32
  26. data/lib/unitsdb/commands/check_si/si_formatter.rb +488 -0
  27. data/lib/unitsdb/commands/check_si/si_matcher.rb +487 -0
  28. data/lib/unitsdb/commands/check_si/si_ttl_parser.rb +103 -0
  29. data/lib/unitsdb/commands/check_si/si_updater.rb +254 -0
  30. data/lib/unitsdb/commands/check_si.rb +54 -35
  31. data/lib/unitsdb/commands/get.rb +11 -10
  32. data/lib/unitsdb/commands/normalize.rb +21 -7
  33. data/lib/unitsdb/commands/qudt/check.rb +150 -0
  34. data/lib/unitsdb/commands/qudt/formatter.rb +194 -0
  35. data/lib/unitsdb/commands/qudt/matcher.rb +746 -0
  36. data/lib/unitsdb/commands/qudt/ttl_parser.rb +403 -0
  37. data/lib/unitsdb/commands/qudt/update.rb +126 -0
  38. data/lib/unitsdb/commands/qudt/updater.rb +189 -0
  39. data/lib/unitsdb/commands/qudt.rb +82 -0
  40. data/lib/unitsdb/commands/release.rb +50 -86
  41. data/lib/unitsdb/commands/search.rb +12 -11
  42. data/lib/unitsdb/commands/ucum/check.rb +139 -0
  43. data/lib/unitsdb/commands/ucum/formatter.rb +142 -0
  44. data/lib/unitsdb/commands/ucum/matcher.rb +315 -0
  45. data/lib/unitsdb/commands/ucum/update.rb +85 -0
  46. data/lib/unitsdb/commands/ucum/updater.rb +132 -0
  47. data/lib/unitsdb/commands/ucum/xml_parser.rb +32 -0
  48. data/lib/unitsdb/commands/ucum.rb +83 -0
  49. data/lib/unitsdb/commands/validate/identifiers.rb +3 -3
  50. data/lib/unitsdb/commands/validate/qudt_references.rb +111 -0
  51. data/lib/unitsdb/commands/validate/references.rb +37 -18
  52. data/lib/unitsdb/commands/validate/si_references.rb +3 -11
  53. data/lib/unitsdb/commands/validate/ucum_references.rb +105 -0
  54. data/lib/unitsdb/commands/validate.rb +67 -11
  55. data/lib/unitsdb/commands.rb +20 -0
  56. data/lib/unitsdb/database.rb +91 -52
  57. data/lib/unitsdb/dimension.rb +1 -4
  58. data/lib/unitsdb/dimension_details.rb +0 -1
  59. data/lib/unitsdb/dimensions.rb +1 -2
  60. data/lib/unitsdb/errors.rb +7 -0
  61. data/lib/unitsdb/prefix.rb +0 -4
  62. data/lib/unitsdb/prefix_reference.rb +0 -2
  63. data/lib/unitsdb/prefixes.rb +1 -1
  64. data/lib/unitsdb/quantities.rb +1 -2
  65. data/lib/unitsdb/quantity.rb +0 -6
  66. data/lib/unitsdb/qudt.rb +100 -0
  67. data/lib/unitsdb/root_unit_reference.rb +0 -3
  68. data/lib/unitsdb/scale.rb +0 -4
  69. data/lib/unitsdb/scale_reference.rb +0 -2
  70. data/lib/unitsdb/scales.rb +1 -2
  71. data/lib/unitsdb/si_derived_base.rb +0 -2
  72. data/lib/unitsdb/ucum.rb +202 -0
  73. data/lib/unitsdb/unit.rb +0 -10
  74. data/lib/unitsdb/unit_reference.rb +0 -2
  75. data/lib/unitsdb/unit_system.rb +1 -3
  76. data/lib/unitsdb/unit_system_reference.rb +0 -2
  77. data/lib/unitsdb/unit_systems.rb +1 -2
  78. data/lib/unitsdb/units.rb +1 -2
  79. data/lib/unitsdb/utils.rb +32 -21
  80. data/lib/unitsdb/version.rb +5 -1
  81. data/lib/unitsdb.rb +62 -14
  82. data/unitsdb.gemspec +6 -5
  83. metadata +60 -13
  84. data/lib/unitsdb/commands/si_formatter.rb +0 -485
  85. data/lib/unitsdb/commands/si_matcher.rb +0 -470
  86. data/lib/unitsdb/commands/si_ttl_parser.rb +0 -100
  87. data/lib/unitsdb/commands/si_updater.rb +0 -212
@@ -1,17 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "unit"
4
- require_relative "prefix"
5
- require_relative "quantity"
6
- require_relative "dimension"
7
- require_relative "unit_system"
8
- require_relative "errors"
9
-
10
3
  module Unitsdb
11
4
  class Database < Lutaml::Model::Serializable
12
5
  # model Config.model_for(:units)
13
6
 
14
7
  attribute :schema_version, :string
8
+ attribute :version, :string
15
9
  attribute :units, Unit, collection: true
16
10
  attribute :prefixes, Prefix, collection: true
17
11
  attribute :quantities, Quantity, collection: true
@@ -24,7 +18,11 @@ module Unitsdb
24
18
  # @return [Object, nil] the first entity with matching identifier or nil if not found
25
19
  def find_by_type(id:, type:)
26
20
  collection = send(type.to_s)
27
- collection.find { |entity| entity.identifiers&.any? { |identifier| identifier.id == id } }
21
+ collection.find do |entity|
22
+ entity.identifiers&.any? do |identifier|
23
+ identifier.id == id
24
+ end
25
+ end
28
26
  end
29
27
 
30
28
  # Find an entity by its identifier id across all entity types
@@ -32,7 +30,8 @@ module Unitsdb
32
30
  # @param type [String, nil] optional identifier type to match
33
31
  # @return [Object, nil] the first entity with matching identifier or nil if not found
34
32
  def get_by_id(id:, type: nil)
35
- %w[units prefixes quantities dimensions unit_systems].each do |collection_name|
33
+ %w[units prefixes quantities dimensions
34
+ unit_systems].each do |collection_name|
36
35
  next unless respond_to?(collection_name)
37
36
 
38
37
  collection = send(collection_name)
@@ -62,7 +61,12 @@ module Unitsdb
62
61
  results = []
63
62
 
64
63
  # Define which collections to search based on type parameter
65
- collections = type ? [type.to_s] : %w[units prefixes quantities dimensions unit_systems]
64
+ collections = if type
65
+ [type.to_s]
66
+ else
67
+ %w[units prefixes quantities
68
+ dimensions unit_systems]
69
+ end
66
70
 
67
71
  collections.each do |collection_name|
68
72
  next unless respond_to?(collection_name)
@@ -70,7 +74,9 @@ module Unitsdb
70
74
  collection = send(collection_name)
71
75
  collection.each do |entity|
72
76
  # Search in identifiers
73
- if entity.identifiers&.any? { |identifier| identifier.id.to_s.downcase.include?(text.downcase) }
77
+ if entity.identifiers&.any? do |identifier|
78
+ identifier.id.to_s.downcase.include?(text.downcase)
79
+ end
74
80
  results << entity
75
81
  next
76
82
  end
@@ -85,14 +91,14 @@ module Unitsdb
85
91
 
86
92
  # Search in short description
87
93
  if entity.respond_to?(:short) && entity.short &&
88
- entity.short.to_s.downcase.include?(text.downcase)
94
+ entity.short.to_s.downcase.include?(text.downcase)
89
95
  results << entity
90
96
  next
91
97
  end
92
98
 
93
99
  # Special case for prefix name (prefixes don't have names array)
94
100
  next unless collection_name == "prefixes" && entity.respond_to?(:name) &&
95
- entity.name.to_s.downcase.include?(text.downcase)
101
+ entity.name.to_s.downcase.include?(text.downcase)
96
102
 
97
103
  results << entity
98
104
  next
@@ -115,7 +121,8 @@ module Unitsdb
115
121
  collections = entity_type ? [entity_type.to_s] : %w[units prefixes]
116
122
 
117
123
  collections.each do |collection_name|
118
- next unless respond_to?(collection_name) && %w[units prefixes].include?(collection_name)
124
+ next unless respond_to?(collection_name) && %w[units
125
+ prefixes].include?(collection_name)
119
126
 
120
127
  collection = send(collection_name)
121
128
  collection.each do |entity|
@@ -157,11 +164,16 @@ module Unitsdb
157
164
 
158
165
  result = {
159
166
  exact: [],
160
- symbol_match: []
167
+ symbol_match: [],
161
168
  }
162
169
 
163
170
  # Define collections to search based on entity_type parameter
164
- collections = entity_type ? [entity_type.to_s] : %w[units prefixes quantities dimensions unit_systems]
171
+ collections = if entity_type
172
+ [entity_type.to_s]
173
+ else
174
+ %w[units prefixes
175
+ quantities dimensions unit_systems]
176
+ end
165
177
 
166
178
  collections.each do |collection_name|
167
179
  next unless respond_to?(collection_name)
@@ -173,23 +185,25 @@ module Unitsdb
173
185
  if %w[exact all].include?(match_type)
174
186
  # Match by short
175
187
  if entity.respond_to?(:short) && entity.short &&
176
- entity.short.downcase == value.downcase
188
+ entity.short.downcase == value.downcase
177
189
  result[:exact] << {
178
190
  entity: entity,
179
191
  match_desc: "short_to_name",
180
- details: "UnitsDB short '#{entity.short}' matches '#{value}'"
192
+ details: "UnitsDB short '#{entity.short}' matches '#{value}'",
181
193
  }
182
194
  next
183
195
  end
184
196
 
185
197
  # Match by names
186
198
  if entity.respond_to?(:names) && entity.names
187
- matching_name = entity.names.find { |name| name.value.to_s.downcase == value.downcase }
199
+ matching_name = entity.names.find do |name|
200
+ name.value.to_s.downcase == value.downcase
201
+ end
188
202
  if matching_name
189
203
  result[:exact] << {
190
204
  entity: entity,
191
205
  match_desc: "name_to_name",
192
- details: "UnitsDB name '#{matching_name.value}' (#{matching_name.lang}) matches '#{value}'"
206
+ details: "UnitsDB name '#{matching_name.value}' (#{matching_name.lang}) matches '#{value}'",
193
207
  }
194
208
  next
195
209
  end
@@ -198,7 +212,7 @@ module Unitsdb
198
212
 
199
213
  # For symbol matches - only applicable to units and prefixes
200
214
  if %w[symbol all].include?(match_type) &&
201
- %w[units prefixes].include?(collection_name)
215
+ %w[units prefixes].include?(collection_name)
202
216
  if collection_name == "units" && entity.respond_to?(:symbols) && entity.symbols
203
217
  # Units can have multiple symbols
204
218
  matching_symbol = entity.symbols.find do |sym|
@@ -210,7 +224,7 @@ module Unitsdb
210
224
  result[:symbol_match] << {
211
225
  entity: entity,
212
226
  match_desc: "symbol_match",
213
- details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'"
227
+ details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'",
214
228
  }
215
229
  end
216
230
  elsif collection_name == "prefixes" && entity.respond_to?(:symbols) && entity.symbols
@@ -224,7 +238,7 @@ module Unitsdb
224
238
  result[:symbol_match] << {
225
239
  entity: entity,
226
240
  match_desc: "symbol_match",
227
- details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'"
241
+ details: "UnitsDB symbol '#{matching_symbol.ascii}' matches '#{value}'",
228
242
  }
229
243
  end
230
244
  end
@@ -242,7 +256,7 @@ module Unitsdb
242
256
  def validate_uniqueness
243
257
  results = {
244
258
  short: {},
245
- id: {}
259
+ id: {},
246
260
  }
247
261
 
248
262
  # Validate short names for applicable collections
@@ -282,18 +296,24 @@ module Unitsdb
282
296
  puts "Database directory path: #{db_path}"
283
297
 
284
298
  # Check if the directory exists
285
- raise Errors::DatabaseNotFoundError, "Database directory not found: #{db_path}" unless Dir.exist?(db_path)
299
+ unless Dir.exist?(db_path)
300
+ raise Errors::DatabaseNotFoundError,
301
+ "Database directory not found: #{db_path}"
302
+ end
286
303
 
287
304
  # Define required files
288
- required_files = %w[prefixes.yaml dimensions.yaml units.yaml quantities.yaml unit_systems.yaml]
305
+ required_files = %w[prefixes.yaml dimensions.yaml units.yaml
306
+ quantities.yaml unit_systems.yaml]
289
307
  yaml_files = required_files.map { |file| File.join(dir_path, file) }
290
308
 
291
309
  # Check if all required files exist
292
- missing_files = required_files.reject { |file| File.exist?(File.join(dir_path, file)) }
310
+ missing_files = required_files.reject do |file|
311
+ File.exist?(File.join(dir_path, file))
312
+ end
293
313
 
294
314
  if missing_files.any?
295
315
  raise Errors::DatabaseFileNotFoundError,
296
- "Missing required database files: #{missing_files.join(", ")}"
316
+ "Missing required database files: #{missing_files.join(', ')}"
297
317
  end
298
318
 
299
319
  # Ensure we have path properly joined with filenames
@@ -315,15 +335,17 @@ module Unitsdb
315
335
 
316
336
  # Load YAML files with better error handling
317
337
  begin
318
- prefixes_hash = YAML.safe_load(File.read(prefixes_yaml))
319
- dimensions_hash = YAML.safe_load(File.read(dimensions_yaml))
320
- units_hash = YAML.safe_load(File.read(units_yaml))
321
- quantities_hash = YAML.safe_load(File.read(quantities_yaml))
322
- unit_systems_hash = YAML.safe_load(File.read(unit_systems_yaml))
338
+ prefixes_hash = YAML.safe_load_file(prefixes_yaml)
339
+ dimensions_hash = YAML.safe_load_file(dimensions_yaml)
340
+ units_hash = YAML.safe_load_file(units_yaml)
341
+ quantities_hash = YAML.safe_load_file(quantities_yaml)
342
+ unit_systems_hash = YAML.safe_load_file(unit_systems_yaml)
323
343
  rescue Errno::ENOENT => e
324
- raise Errors::DatabaseFileNotFoundError, "Failed to read database file: #{e.message}"
344
+ raise Errors::DatabaseFileNotFoundError,
345
+ "Failed to read database file: #{e.message}"
325
346
  rescue Psych::SyntaxError => e
326
- raise Errors::DatabaseFileInvalidError, "Invalid YAML in database file: #{e.message}"
347
+ raise Errors::DatabaseFileInvalidError,
348
+ "Invalid YAML in database file: #{e.message}"
327
349
  rescue StandardError => e
328
350
  raise Errors::DatabaseLoadError, "Error loading database: #{e.message}"
329
351
  end
@@ -338,7 +360,7 @@ module Unitsdb
338
360
 
339
361
  if missing_schema.any?
340
362
  raise Errors::DatabaseFileInvalidError,
341
- "Missing schema_version in files: #{missing_schema.join(", ")}"
363
+ "Missing schema_version in files: #{missing_schema.join(', ')}"
342
364
  end
343
365
 
344
366
  # Extract versions from each file
@@ -354,7 +376,7 @@ module Unitsdb
354
376
  dimensions_version,
355
377
  units_version,
356
378
  quantities_version,
357
- unit_systems_version
379
+ unit_systems_version,
358
380
  ]
359
381
 
360
382
  unless versions.uniq.size == 1
@@ -363,9 +385,10 @@ module Unitsdb
363
385
  "dimensions.yaml" => dimensions_version,
364
386
  "units.yaml" => units_version,
365
387
  "quantities.yaml" => quantities_version,
366
- "unit_systems.yaml" => unit_systems_version
388
+ "unit_systems.yaml" => unit_systems_version,
367
389
  }
368
- raise Errors::VersionMismatchError, "Version mismatch in database files: #{version_info.inspect}"
390
+ raise Errors::VersionMismatchError,
391
+ "Version mismatch in database files: #{version_info.inspect}"
369
392
  end
370
393
 
371
394
  # Check if the version is supported
@@ -381,7 +404,7 @@ module Unitsdb
381
404
  "dimensions" => dimensions_hash["dimensions"],
382
405
  "units" => units_hash["units"],
383
406
  "quantities" => quantities_hash["quantities"],
384
- "unit_systems" => unit_systems_hash["unit_systems"]
407
+ "unit_systems" => unit_systems_hash["unit_systems"],
385
408
  }.to_yaml
386
409
 
387
410
  from_yaml(combined_yaml)
@@ -532,7 +555,8 @@ module Unitsdb
532
555
  ref_type = "dimensions"
533
556
  ref_path = "dimensions:index:#{index}:dimension_reference"
534
557
 
535
- validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs, "dimensions")
558
+ validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs,
559
+ "dimensions")
536
560
  end
537
561
  end
538
562
 
@@ -544,7 +568,8 @@ module Unitsdb
544
568
  ref_type = "unit_systems"
545
569
  ref_path = "units:index:#{index}:unit_system_reference[#{idx}]"
546
570
 
547
- validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs, "units")
571
+ validate_reference(ref_id, ref_type, ref_path, registry,
572
+ invalid_refs, "units")
548
573
  end
549
574
  end
550
575
  end
@@ -557,7 +582,8 @@ module Unitsdb
557
582
  ref_type = "quantities"
558
583
  ref_path = "units:index:#{index}:quantity_references[#{idx}]"
559
584
 
560
- validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs, "units")
585
+ validate_reference(ref_id, ref_type, ref_path, registry,
586
+ invalid_refs, "units")
561
587
  end
562
588
  end
563
589
  end
@@ -574,7 +600,8 @@ module Unitsdb
574
600
  ref_type = "units"
575
601
  ref_path = "units:index:#{index}:root_units.#{idx}.unit_reference"
576
602
 
577
- validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs, "units")
603
+ validate_reference(ref_id, ref_type, ref_path, registry,
604
+ invalid_refs, "units")
578
605
 
579
606
  # Check prefix reference if present
580
607
  next unless root_unit.respond_to?(:prefix_reference) && root_unit.prefix_reference
@@ -583,12 +610,14 @@ module Unitsdb
583
610
  ref_type = "prefixes"
584
611
  ref_path = "units:index:#{index}:root_units.#{idx}.prefix_reference"
585
612
 
586
- validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs, "units")
613
+ validate_reference(ref_id, ref_type, ref_path, registry,
614
+ invalid_refs, "units")
587
615
  end
588
616
  end
589
617
  end
590
618
 
591
- def validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs, file_type)
619
+ def validate_reference(ref_id, ref_type, ref_path, registry, invalid_refs,
620
+ file_type)
592
621
  # Handle references that are objects with id and type (could be a hash or an object)
593
622
  if ref_id.respond_to?(:id) && ref_id.respond_to?(:type)
594
623
  id = ref_id.id
@@ -607,8 +636,12 @@ module Unitsdb
607
636
  # 3. Try alternate ID formats for unit systems (e.g., SI_base vs si-base)
608
637
  if !valid && type == "unitsml" && ref_type == "unit_systems" && registry.key?(ref_type) && (
609
638
  registry[ref_type].keys.any? { |k| k.end_with?(":#{id}") } ||
610
- registry[ref_type].keys.any? { |k| k.end_with?(":SI_#{id.sub("si-", "")}") } ||
611
- registry[ref_type].keys.any? { |k| k.end_with?(":non-SI_#{id.sub("nonsi-", "")}") }
639
+ registry[ref_type].keys.any? do |k|
640
+ k.end_with?(":SI_#{id.sub('si-', '')}")
641
+ end ||
642
+ registry[ref_type].keys.any? do |k|
643
+ k.end_with?(":non-SI_#{id.sub('nonsi-', '')}")
644
+ end
612
645
  )
613
646
  # Special handling for unit_systems between unitsml and nist types
614
647
  valid = true
@@ -616,7 +649,8 @@ module Unitsdb
616
649
 
617
650
  unless valid
618
651
  invalid_refs[file_type] ||= {}
619
- invalid_refs[file_type][ref_path] = { id: id, type: type, ref_type: ref_type }
652
+ invalid_refs[file_type][ref_path] =
653
+ { id: id, type: type, ref_type: ref_type }
620
654
  end
621
655
  # Handle references that are objects with id and type in a hash
622
656
  elsif ref_id.is_a?(Hash) && ref_id.key?("id") && ref_id.key?("type")
@@ -636,8 +670,12 @@ module Unitsdb
636
670
  # 3. Try alternate ID formats for unit systems (e.g., SI_base vs si-base)
637
671
  if !valid && type == "unitsml" && ref_type == "unit_systems" && registry.key?(ref_type) && (
638
672
  registry[ref_type].keys.any? { |k| k.end_with?(":#{id}") } ||
639
- registry[ref_type].keys.any? { |k| k.end_with?(":SI_#{id.sub("si-", "")}") } ||
640
- registry[ref_type].keys.any? { |k| k.end_with?(":non-SI_#{id.sub("nonsi-", "")}") }
673
+ registry[ref_type].keys.any? do |k|
674
+ k.end_with?(":SI_#{id.sub('si-', '')}")
675
+ end ||
676
+ registry[ref_type].keys.any? do |k|
677
+ k.end_with?(":non-SI_#{id.sub('nonsi-', '')}")
678
+ end
641
679
  )
642
680
  # Special handling for unit_systems between unitsml and nist types
643
681
  valid = true
@@ -645,7 +683,8 @@ module Unitsdb
645
683
 
646
684
  unless valid
647
685
  invalid_refs[file_type] ||= {}
648
- invalid_refs[file_type][ref_path] = { id: id, type: type, ref_type: ref_type }
686
+ invalid_refs[file_type][ref_path] =
687
+ { id: id, type: type, ref_type: ref_type }
649
688
  end
650
689
  else
651
690
  # Handle plain string references (legacy format)
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "identifier"
4
- require_relative "dimension_details"
5
- require_relative "quantity"
6
- require_relative "localized_string"
7
3
  # NISTd1:
8
4
  # length:
9
5
  # power: 1
@@ -45,5 +41,6 @@ module Unitsdb
45
41
  attribute :plane_angle, DimensionDetails
46
42
  attribute :short, :string
47
43
  attribute :names, LocalizedString, collection: true
44
+ attribute :references, ExternalReference, collection: true
48
45
  end
49
46
  end
@@ -10,7 +10,6 @@
10
10
  # mathml: "<mi mathvariant='sans-serif'>M</mi>"
11
11
  # unicode: "\U0001D5AC"
12
12
 
13
- require_relative "symbol_presentations"
14
13
  module Unitsdb
15
14
  class DimensionDetails < Lutaml::Model::Serializable
16
15
  attribute :power, :integer
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "dimension"
4
-
5
3
  module Unitsdb
6
4
  class Dimensions < Lutaml::Model::Serializable
7
5
  # model Config.model_for(:dimensions)
8
6
 
9
7
  attribute :schema_version, :string
8
+ attribute :version, :string
10
9
  attribute :dimensions, Dimension, collection: true
11
10
  end
12
11
  end
@@ -9,5 +9,12 @@ module Unitsdb
9
9
  class DatabaseLoadError < DatabaseError; end
10
10
  class VersionMismatchError < DatabaseError; end
11
11
  class UnsupportedVersionError < DatabaseError; end
12
+
13
+ # CLI-specific errors
14
+ class CLIRuntimeError < StandardError; end
15
+ class InvalidParameterError < CLIRuntimeError; end
16
+ class FileNotFoundError < CLIRuntimeError; end
17
+ class ValidationError < CLIRuntimeError; end
18
+ class InvalidFormatError < CLIRuntimeError; end
12
19
  end
13
20
  end
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "identifier"
4
- require_relative "symbol_presentations"
5
- require_relative "external_reference"
6
- require_relative "localized_string"
7
3
  # ---
8
4
  # NISTp10_30:
9
5
  # name: quetta
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "identifier"
4
-
5
3
  module Unitsdb
6
4
  class PrefixReference < Identifier
7
5
  attribute :id, :string
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "prefix"
4
3
  # ---
5
4
  # NISTp10_30:
6
5
  # name: quetta
@@ -17,6 +16,7 @@ module Unitsdb
17
16
  # model Config.model_for(:prefixes)
18
17
 
19
18
  attribute :schema_version, :string
19
+ attribute :version, :string
20
20
  attribute :prefixes, Prefix, collection: true
21
21
  end
22
22
  end
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "quantity"
4
-
5
3
  module Unitsdb
6
4
  class Quantities < Lutaml::Model::Serializable
7
5
  # model Config.model_for(:quantities)
8
6
  attribute :schema_version, :string
7
+ attribute :version, :string
9
8
  attribute :quantities, Quantity, collection: true
10
9
  end
11
10
  end
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "identifier"
4
- require_relative "unit_reference"
5
- require_relative "dimension_reference"
6
- require_relative "external_reference"
7
- require_relative "localized_string"
8
-
9
3
  module Unitsdb
10
4
  class Quantity < Lutaml::Model::Serializable
11
5
  # model Config.model_for(:quantity)
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsdb
4
+ # QUDT Unit from units vocabulary
5
+ # Example: http://qudt.org/vocab/unit/M (meter)
6
+ class QudtUnit < Lutaml::Model::Serializable
7
+ attribute :uri, :string
8
+ attribute :label, :string
9
+ attribute :symbol, :string
10
+ attribute :has_quantity_kind, :string
11
+ attribute :has_dimension_vector, :string
12
+ attribute :conversion_multiplier, :float
13
+ attribute :conversion_offset, :float
14
+ attribute :description, :string
15
+ attribute :si_exact_match, :string
16
+
17
+ def identifier
18
+ "qudt:unit:#{uri}"
19
+ end
20
+ end
21
+
22
+ # QUDT QuantityKind from quantitykinds vocabulary
23
+ # Example: http://qudt.org/vocab/quantitykind/Length
24
+ class QudtQuantityKind < Lutaml::Model::Serializable
25
+ attribute :uri, :string
26
+ attribute :label, :string
27
+ attribute :has_dimension_vector, :string
28
+ attribute :description, :string
29
+ attribute :symbol, :string
30
+ attribute :si_exact_match, :string
31
+
32
+ def identifier
33
+ "qudt:quantitykind:#{uri}"
34
+ end
35
+ end
36
+
37
+ # QUDT DimensionVector from dimensionvectors vocabulary
38
+ # Example: http://qudt.org/vocab/dimensionvector/A0E0L1I0M0H0T0D0
39
+ class QudtDimensionVector < Lutaml::Model::Serializable
40
+ attribute :uri, :string
41
+ attribute :label, :string
42
+ attribute :dimension_exponent_for_length, :integer
43
+ attribute :dimension_exponent_for_mass, :integer
44
+ attribute :dimension_exponent_for_time, :integer
45
+ attribute :dimension_exponent_for_electric_current, :integer
46
+ attribute :dimension_exponent_for_thermodynamic_temperature, :integer
47
+ attribute :dimension_exponent_for_amount_of_substance, :integer
48
+ attribute :dimension_exponent_for_luminous_intensity, :integer
49
+ attribute :description, :string
50
+
51
+ def identifier
52
+ "qudt:dimensionvector:#{uri}"
53
+ end
54
+ end
55
+
56
+ # QUDT SystemOfUnits from sou vocabulary
57
+ # Example: http://qudt.org/vocab/sou/SI
58
+ class QudtSystemOfUnits < Lutaml::Model::Serializable
59
+ attribute :uri, :string
60
+ attribute :label, :string
61
+ attribute :abbreviation, :string
62
+ attribute :description, :string
63
+
64
+ def identifier
65
+ "qudt:sou:#{uri}"
66
+ end
67
+ end
68
+
69
+ # QUDT Prefix from prefixes vocabulary
70
+ # Example: http://qudt.org/vocab/prefix/Kilo
71
+ class QudtPrefix < Lutaml::Model::Serializable
72
+ attribute :uri, :string
73
+ attribute :label, :string
74
+ attribute :symbol, :string
75
+ attribute :prefix_multiplier, :float
76
+ attribute :prefix_multiplier_sn, :string
77
+ attribute :ucum_code, :string
78
+ attribute :si_exact_match, :string
79
+ attribute :description, :string
80
+ attribute :prefix_type, :string # "DecimalPrefix" or "BinaryPrefix"
81
+
82
+ def identifier
83
+ "qudt:prefix:#{uri}"
84
+ end
85
+ end
86
+
87
+ # Container for all QUDT vocabularies
88
+ class QudtVocabularies
89
+ attr_accessor :units, :quantity_kinds, :dimension_vectors,
90
+ :systems_of_units, :prefixes
91
+
92
+ def initialize
93
+ @units = []
94
+ @quantity_kinds = []
95
+ @dimension_vectors = []
96
+ @systems_of_units = []
97
+ @prefixes = []
98
+ end
99
+ end
100
+ end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "unit_reference"
4
- require_relative "prefix_reference"
5
-
6
3
  module Unitsdb
7
4
  class RootUnitReference < Lutaml::Model::Serializable
8
5
  # model Config.model_for(:root_unit)
data/lib/unitsdb/scale.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "identifier"
4
- require_relative "localized_string"
5
- require_relative "scale_properties"
6
-
7
3
  module Unitsdb
8
4
  class Scale < Lutaml::Model::Serializable
9
5
  # model Config.model_for(:quantity)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "identifier"
4
-
5
3
  module Unitsdb
6
4
  class ScaleReference < Identifier
7
5
  attribute :id, :string
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "scale"
4
-
5
3
  module Unitsdb
6
4
  class Scales < Lutaml::Model::Serializable
7
5
  # model Config.model_for(:Scale)
8
6
  attribute :schema_version, :string
7
+ attribute :version, :string
9
8
  attribute :scales, Scale, collection: true
10
9
  end
11
10
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "root_unit_reference"
4
-
5
3
  # si_derived_bases:
6
4
  # - power: 2
7
5
  # unit_reference: