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.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +8 -1
- data/.gitignore +2 -0
- data/.gitmodules +4 -3
- data/.rubocop.yml +13 -8
- data/.rubocop_todo.yml +247 -53
- data/CLAUDE.md +55 -0
- data/Gemfile +5 -1
- data/README.adoc +385 -12
- data/data/dimensions.yaml +1864 -0
- data/data/prefixes.yaml +874 -0
- data/data/quantities.yaml +3715 -0
- data/data/scales.yaml +97 -0
- data/data/schemas/dimensions-schema.yaml +153 -0
- data/data/schemas/prefixes-schema.yaml +155 -0
- data/data/schemas/quantities-schema.yaml +117 -0
- data/data/schemas/scales-schema.yaml +106 -0
- data/data/schemas/unit_systems-schema.yaml +116 -0
- data/data/schemas/units-schema.yaml +215 -0
- data/data/unit_systems.yaml +78 -0
- data/data/units.yaml +14052 -0
- data/exe/unitsdb +7 -1
- data/lib/unitsdb/cli.rb +47 -13
- data/lib/unitsdb/commands/_modify.rb +41 -5
- data/lib/unitsdb/commands/base.rb +10 -32
- data/lib/unitsdb/commands/check_si/si_formatter.rb +488 -0
- data/lib/unitsdb/commands/check_si/si_matcher.rb +487 -0
- data/lib/unitsdb/commands/check_si/si_ttl_parser.rb +103 -0
- data/lib/unitsdb/commands/check_si/si_updater.rb +254 -0
- data/lib/unitsdb/commands/check_si.rb +54 -35
- data/lib/unitsdb/commands/get.rb +11 -10
- data/lib/unitsdb/commands/normalize.rb +21 -7
- data/lib/unitsdb/commands/qudt/check.rb +150 -0
- data/lib/unitsdb/commands/qudt/formatter.rb +194 -0
- data/lib/unitsdb/commands/qudt/matcher.rb +746 -0
- data/lib/unitsdb/commands/qudt/ttl_parser.rb +403 -0
- data/lib/unitsdb/commands/qudt/update.rb +126 -0
- data/lib/unitsdb/commands/qudt/updater.rb +189 -0
- data/lib/unitsdb/commands/qudt.rb +82 -0
- data/lib/unitsdb/commands/release.rb +50 -86
- data/lib/unitsdb/commands/search.rb +12 -11
- data/lib/unitsdb/commands/ucum/check.rb +139 -0
- data/lib/unitsdb/commands/ucum/formatter.rb +142 -0
- data/lib/unitsdb/commands/ucum/matcher.rb +315 -0
- data/lib/unitsdb/commands/ucum/update.rb +85 -0
- data/lib/unitsdb/commands/ucum/updater.rb +132 -0
- data/lib/unitsdb/commands/ucum/xml_parser.rb +32 -0
- data/lib/unitsdb/commands/ucum.rb +83 -0
- data/lib/unitsdb/commands/validate/identifiers.rb +3 -3
- data/lib/unitsdb/commands/validate/qudt_references.rb +111 -0
- data/lib/unitsdb/commands/validate/references.rb +37 -18
- data/lib/unitsdb/commands/validate/si_references.rb +3 -11
- data/lib/unitsdb/commands/validate/ucum_references.rb +105 -0
- data/lib/unitsdb/commands/validate.rb +67 -11
- data/lib/unitsdb/commands.rb +20 -0
- data/lib/unitsdb/database.rb +91 -52
- data/lib/unitsdb/dimension.rb +1 -4
- data/lib/unitsdb/dimension_details.rb +0 -1
- data/lib/unitsdb/dimensions.rb +1 -2
- data/lib/unitsdb/errors.rb +7 -0
- data/lib/unitsdb/prefix.rb +0 -4
- data/lib/unitsdb/prefix_reference.rb +0 -2
- data/lib/unitsdb/prefixes.rb +1 -1
- data/lib/unitsdb/quantities.rb +1 -2
- data/lib/unitsdb/quantity.rb +0 -6
- data/lib/unitsdb/qudt.rb +100 -0
- data/lib/unitsdb/root_unit_reference.rb +0 -3
- data/lib/unitsdb/scale.rb +0 -4
- data/lib/unitsdb/scale_reference.rb +0 -2
- data/lib/unitsdb/scales.rb +1 -2
- data/lib/unitsdb/si_derived_base.rb +0 -2
- data/lib/unitsdb/ucum.rb +202 -0
- data/lib/unitsdb/unit.rb +0 -10
- data/lib/unitsdb/unit_reference.rb +0 -2
- data/lib/unitsdb/unit_system.rb +1 -3
- data/lib/unitsdb/unit_system_reference.rb +0 -2
- data/lib/unitsdb/unit_systems.rb +1 -2
- data/lib/unitsdb/units.rb +1 -2
- data/lib/unitsdb/utils.rb +32 -21
- data/lib/unitsdb/version.rb +5 -1
- data/lib/unitsdb.rb +62 -14
- data/unitsdb.gemspec +6 -5
- metadata +60 -13
- data/lib/unitsdb/commands/si_formatter.rb +0 -485
- data/lib/unitsdb/commands/si_matcher.rb +0 -470
- data/lib/unitsdb/commands/si_ttl_parser.rb +0 -100
- data/lib/unitsdb/commands/si_updater.rb +0 -212
data/lib/unitsdb/database.rb
CHANGED
|
@@ -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
|
|
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
|
|
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 =
|
|
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?
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
319
|
-
dimensions_hash = YAML.
|
|
320
|
-
units_hash = YAML.
|
|
321
|
-
quantities_hash = YAML.
|
|
322
|
-
unit_systems_hash = 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,
|
|
344
|
+
raise Errors::DatabaseFileNotFoundError,
|
|
345
|
+
"Failed to read database file: #{e.message}"
|
|
325
346
|
rescue Psych::SyntaxError => e
|
|
326
|
-
raise Errors::DatabaseFileInvalidError,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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?
|
|
611
|
-
|
|
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] =
|
|
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?
|
|
640
|
-
|
|
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] =
|
|
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)
|
data/lib/unitsdb/dimension.rb
CHANGED
|
@@ -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
|
data/lib/unitsdb/dimensions.rb
CHANGED
|
@@ -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
|
data/lib/unitsdb/errors.rb
CHANGED
|
@@ -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
|
data/lib/unitsdb/prefix.rb
CHANGED
data/lib/unitsdb/prefixes.rb
CHANGED
|
@@ -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
|
data/lib/unitsdb/quantities.rb
CHANGED
|
@@ -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
|
data/lib/unitsdb/quantity.rb
CHANGED
|
@@ -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)
|
data/lib/unitsdb/qudt.rb
ADDED
|
@@ -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
|
data/lib/unitsdb/scale.rb
CHANGED
data/lib/unitsdb/scales.rb
CHANGED
|
@@ -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
|