dcc 0.2.0 → 0.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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +19 -0
  3. data/.github/workflows/release.yml +28 -0
  4. data/.gitignore +4 -0
  5. data/.rubocop_todo.yml +560 -10
  6. data/CHANGELOG.adoc +34 -1
  7. data/CONTRIBUTING.adoc +8 -1
  8. data/Gemfile +5 -7
  9. data/README.adoc +162 -7
  10. data/dcc.gemspec +8 -2
  11. data/docs/schema-versions.adoc +20 -7
  12. data/examples/build_minimal_dcc.rb +0 -0
  13. data/examples/convert_all_formats.rb +2 -1
  14. data/examples/parse_and_inspect.rb +0 -0
  15. data/examples/quantity_math_demo.rb +7 -7
  16. data/examples/validate_full.rb +1 -1
  17. data/lib/dcc/base/calibration_laboratory.rb +2 -1
  18. data/lib/dcc/base/condition.rb +5 -2
  19. data/lib/dcc/base/core_data.rb +8 -3
  20. data/lib/dcc/base/formula.rb +3 -3
  21. data/lib/dcc/base/identification.rb +6 -3
  22. data/lib/dcc/base/mathml.rb +33 -0
  23. data/lib/dcc/base/quantity.rb +2 -1
  24. data/lib/dcc/base/resp_person.rb +4 -2
  25. data/lib/dcc/base/text.rb +1 -1
  26. data/lib/dcc/base.rb +2 -1
  27. data/lib/dcc/builder/dsl.rb +1 -1
  28. data/lib/dcc/builder/session.rb +16 -14
  29. data/lib/dcc/builder.rb +3 -3
  30. data/lib/dcc/cli/cli.rb +36 -18
  31. data/lib/dcc/cli/formatters.rb +35 -7
  32. data/lib/dcc/cli.rb +1 -1
  33. data/lib/dcc/context_configuration.rb +2 -1
  34. data/lib/dcc/context_options.rb +4 -2
  35. data/lib/dcc/convert/csv.rb +27 -9
  36. data/lib/dcc/convert/html.rb +26 -110
  37. data/lib/dcc/convert/json.rb +10 -7
  38. data/lib/dcc/convert/liquid_filters.rb +58 -0
  39. data/lib/dcc/convert/result.rb +1 -1
  40. data/lib/dcc/convert/templates/report.liquid +250 -0
  41. data/lib/dcc/convert/yaml.rb +1 -1
  42. data/lib/dcc/convert.rb +1 -0
  43. data/lib/dcc/diff/change.rb +1 -1
  44. data/lib/dcc/diff/result.rb +8 -4
  45. data/lib/dcc/diff.rb +43 -11
  46. data/lib/dcc/error.rb +7 -0
  47. data/lib/dcc/extract/file.rb +3 -4
  48. data/lib/dcc/extract/ring.rb +1 -1
  49. data/lib/dcc/extract.rb +1 -1
  50. data/lib/dcc/i18n/text_lookup.rb +8 -4
  51. data/lib/dcc/i18n.rb +1 -1
  52. data/lib/dcc/inspect/report.rb +51 -14
  53. data/lib/dcc/inspect.rb +1 -1
  54. data/lib/dcc/migrate/route.rb +44 -0
  55. data/lib/dcc/migrate/v2_to_v3.rb +445 -0
  56. data/lib/dcc/migrate.rb +130 -26
  57. data/lib/dcc/plugin/base.rb +64 -0
  58. data/lib/dcc/plugin/registry.rb +7 -2
  59. data/lib/dcc/plugin.rb +6 -2
  60. data/lib/dcc/quantity_format/formatter.rb +16 -10
  61. data/lib/dcc/quantity_format.rb +1 -1
  62. data/lib/dcc/quantity_math/quantity.rb +1 -1
  63. data/lib/dcc/quantity_math/real.rb +6 -6
  64. data/lib/dcc/quantity_math.rb +1 -1
  65. data/lib/dcc/schema/version.rb +2 -2
  66. data/lib/dcc/server/app.html +282 -0
  67. data/lib/dcc/server/app.rb +171 -87
  68. data/lib/dcc/server/demo_cert.xml +244 -0
  69. data/lib/dcc/server/storage/entry.rb +1 -1
  70. data/lib/dcc/server/storage/memory.rb +3 -2
  71. data/lib/dcc/server/storage.rb +1 -1
  72. data/lib/dcc/server.rb +1 -1
  73. data/lib/dcc/si/base/complex.rb +1 -1
  74. data/lib/dcc/si/base/complex_list_xml_list.rb +1 -1
  75. data/lib/dcc/si/base/constant.rb +1 -1
  76. data/lib/dcc/si/base/coverage_interval.rb +36 -0
  77. data/lib/dcc/si/base/coverage_interval_mu.rb +1 -1
  78. data/lib/dcc/si/base/expanded_mu.rb +1 -1
  79. data/lib/dcc/si/base/expanded_unc.rb +34 -0
  80. data/lib/dcc/si/base/expanded_unc_xml_list.rb +3 -2
  81. data/lib/dcc/si/base/hybrid.rb +3 -2
  82. data/lib/dcc/si/base/measurement_uncertainty_univariate.rb +1 -1
  83. data/lib/dcc/si/base/real.rb +13 -3
  84. data/lib/dcc/si/base/real_list_xml_list.rb +5 -3
  85. data/lib/dcc/si/base/si_list.rb +3 -2
  86. data/lib/dcc/si/base/standard_mu.rb +1 -1
  87. data/lib/dcc/si/base.rb +5 -2
  88. data/lib/dcc/si/v1/coverage_interval.rb +8 -0
  89. data/lib/dcc/si/v1/expanded_unc.rb +1 -16
  90. data/lib/dcc/si/v1/measurement_uncertainty_univariate.rb +2 -1
  91. data/lib/dcc/si/v1.rb +5 -2
  92. data/lib/dcc/si/v2/coverage_interval.rb +8 -0
  93. data/lib/dcc/si/v2/coverage_interval_mu_xml_list.rb +4 -2
  94. data/lib/dcc/si/v2/expanded_mu_xml_list.rb +2 -1
  95. data/lib/dcc/si/v2/expanded_unc.rb +8 -0
  96. data/lib/dcc/si/v2/measurement_uncertainty_univariate.rb +2 -1
  97. data/lib/dcc/si/v2.rb +8 -3
  98. data/lib/dcc/signature/result.rb +2 -2
  99. data/lib/dcc/signature/signer.rb +31 -18
  100. data/lib/dcc/signature/verifier.rb +23 -21
  101. data/lib/dcc/signature.rb +1 -1
  102. data/lib/dcc/transform/result.rb +1 -1
  103. data/lib/dcc/transform/xslt.rb +22 -12
  104. data/lib/dcc/transform.rb +5 -4
  105. data/lib/dcc/type/base64_binary.rb +5 -3
  106. data/lib/dcc/type/decimal_xml_list.rb +99 -13
  107. data/lib/dcc/type/iso_country_code.rb +3 -2
  108. data/lib/dcc/type/iso_language_code.rb +3 -2
  109. data/lib/dcc/type/schema_version.rb +3 -2
  110. data/lib/dcc/type/si_unit.rb +3 -2
  111. data/lib/dcc/type_guards.rb +3 -3
  112. data/lib/dcc/v2/calibration_laboratory.rb +2 -1
  113. data/lib/dcc/v2/condition.rb +22 -1
  114. data/lib/dcc/v2/configuration.rb +1 -1
  115. data/lib/dcc/v2/digital_calibration_certificate.rb +2 -1
  116. data/lib/dcc/v2/identification.rb +14 -1
  117. data/lib/dcc/v2/mathml.rb +8 -0
  118. data/lib/dcc/v2/measurement_meta_data_list.rb +2 -1
  119. data/lib/dcc/v2/quantity.rb +4 -2
  120. data/lib/dcc/v2.rb +4 -2
  121. data/lib/dcc/v3/calibration_laboratory.rb +2 -1
  122. data/lib/dcc/v3/configuration.rb +1 -1
  123. data/lib/dcc/v3/digital_calibration_certificate.rb +2 -1
  124. data/lib/dcc/v3/mathml.rb +8 -0
  125. data/lib/dcc/v3/measurement_meta_data_list.rb +2 -1
  126. data/lib/dcc/v3/quantity.rb +4 -2
  127. data/lib/dcc/v3.rb +12 -2
  128. data/lib/dcc/validate/business_rules.rb +23 -9
  129. data/lib/dcc/validate/issue.rb +2 -1
  130. data/lib/dcc/validate/result.rb +6 -4
  131. data/lib/dcc/validate/schematron/profile.rb +73 -18
  132. data/lib/dcc/validate/schematron/rule.rb +13 -3
  133. data/lib/dcc/validate/schematron/rules/administrative_data_completeness.rb +11 -4
  134. data/lib/dcc/validate/schematron/rules/base.rb +1 -2
  135. data/lib/dcc/validate/schematron/rules/date_range_check.rb +11 -5
  136. data/lib/dcc/validate/schematron/rules/id_refid_linking.rb +0 -3
  137. data/lib/dcc/validate/schematron/rules/influence_conditions_placement.rb +22 -12
  138. data/lib/dcc/validate/schematron/rules/iso_code_validation.rb +31 -14
  139. data/lib/dcc/validate/schematron/rules/language_code_dedup.rb +12 -5
  140. data/lib/dcc/validate/schematron/rules/non_si_declaration.rb +7 -4
  141. data/lib/dcc/validate/schematron/rules/release_format_check.rb +7 -4
  142. data/lib/dcc/validate/schematron/rules/schema_version_check.rb +13 -9
  143. data/lib/dcc/validate/schematron/rules/uncertainty_consistency.rb +39 -10
  144. data/lib/dcc/validate/schematron/rules/unit_format_check.rb +2 -3
  145. data/lib/dcc/validate/schematron/rules/used_methods_placement.rb +15 -10
  146. data/lib/dcc/validate/schematron/rules/used_software_placement.rb +15 -10
  147. data/lib/dcc/validate/schematron/rules/xml_list_spacing.rb +4 -3
  148. data/lib/dcc/validate/schematron/rules.rb +28 -14
  149. data/lib/dcc/validate/schematron.rb +1 -1
  150. data/lib/dcc/validate/xsd.rb +9 -3
  151. data/lib/dcc/validate.rb +1 -1
  152. data/lib/dcc/version.rb +1 -1
  153. data/lib/dcc/versioned_parser.rb +1 -1
  154. data/lib/dcc.rb +55 -7
  155. data/sample_dcc.xml +140 -0
  156. data/web/index.html +12 -0
  157. data/web/package-lock.json +1599 -0
  158. data/web/package.json +22 -0
  159. data/web/src/App.vue +349 -0
  160. data/web/src/lib/builder.ts +171 -0
  161. data/web/src/lib/dcc.ts +338 -0
  162. data/web/src/lib/units.json +5581 -0
  163. data/web/src/main.ts +5 -0
  164. data/web/src/style.css +27 -0
  165. data/web/tsconfig.json +15 -0
  166. data/web/vite.config.ts +14 -0
  167. metadata +125 -9
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Dcc
5
4
  module Validate
6
5
  module Schematron
@@ -10,20 +9,24 @@ module Dcc
10
9
  class UsedMethodsPlacement < Base
11
10
  def check_on(dcc)
12
11
  issues = []
13
- return issues unless Dcc::TypeGuards.has_attribute?(dcc, :measurement_results)
12
+ return issues unless Dcc::TypeGuards.has_attribute?(dcc,
13
+ :measurement_results)
14
14
 
15
15
  mr_list = safe_attr(dcc.measurement_results, :measurement_result)
16
16
  return issues if mr_list.empty?
17
17
 
18
18
  any_used = mr_list.any? do |mr|
19
- Dcc::TypeGuards.has_attribute?(mr, :used_methods) && !mr.used_methods.nil? ||
19
+ (Dcc::TypeGuards.has_attribute?(mr,
20
+ :used_methods) && !mr.used_methods.nil?) ||
20
21
  mr_has_descendant?(mr, :used_methods)
21
22
  end
22
23
 
23
- issues << issue(
24
- severity: :error,
25
- message: "dcc:usedMethods is missing in every measurementResult and its descendants",
26
- ) unless any_used
24
+ unless any_used
25
+ issues << issue(
26
+ severity: :error,
27
+ message: "dcc:usedMethods is missing in every measurementResult and its descendants",
28
+ )
29
+ end
27
30
 
28
31
  issues
29
32
  end
@@ -31,7 +34,8 @@ module Dcc
31
34
  private
32
35
 
33
36
  def mr_has_descendant?(mr, attr_name)
34
- return false unless Dcc::TypeGuards.has_attribute?(mr, :results) && mr.results
37
+ return false unless Dcc::TypeGuards.has_attribute?(mr,
38
+ :results) && mr.results
35
39
 
36
40
  result = safe_attr(mr.results, :result)
37
41
  result.any? { |r| descendant_has?(r, attr_name) }
@@ -40,7 +44,8 @@ module Dcc
40
44
  def descendant_has?(node, attr_name)
41
45
  return false unless node.is_a?(::Lutaml::Model::Serializable)
42
46
 
43
- if Dcc::TypeGuards.has_attribute?(node, attr_name) && !node.public_send(attr_name).nil?
47
+ if Dcc::TypeGuards.has_attribute?(node,
48
+ attr_name) && !node.public_send(attr_name).nil?
44
49
  return true
45
50
  end
46
51
 
@@ -62,4 +67,4 @@ module Dcc
62
67
  end
63
68
  end
64
69
  end
65
- end
70
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Dcc
5
4
  module Validate
6
5
  module Schematron
@@ -12,21 +11,27 @@ module Dcc
12
11
  end
13
12
 
14
13
  def check_on(dcc)
15
- return [] unless Dcc::TypeGuards.has_attribute?(dcc, :measurement_results)
14
+ return [] unless Dcc::TypeGuards.has_attribute?(dcc,
15
+ :measurement_results)
16
16
 
17
17
  mr_list = safe_attr(dcc.measurement_results, :measurement_result)
18
18
  return [] if mr_list.empty?
19
19
 
20
20
  present = mr_list.any? do |mr|
21
- Dcc::TypeGuards.has_attribute?(mr, :used_software) && !mr.used_software.nil?
21
+ Dcc::TypeGuards.has_attribute?(mr,
22
+ :used_software) && !mr.used_software.nil?
22
23
  end
23
24
 
24
- present ? [] : [
25
- issue(
26
- severity: :warning,
27
- message: "dcc:usedSoftware is missing on every measurementResult",
28
- ),
29
- ]
25
+ if present
26
+ []
27
+ else
28
+ [
29
+ issue(
30
+ severity: :warning,
31
+ message: "dcc:usedSoftware is missing on every measurementResult",
32
+ ),
33
+ ]
34
+ end
30
35
  end
31
36
 
32
37
  private
@@ -40,4 +45,4 @@ module Dcc
40
45
  end
41
46
  end
42
47
  end
43
- end
48
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Dcc
5
4
  module Validate
6
5
  module Schematron
@@ -32,11 +31,13 @@ module Dcc
32
31
 
33
32
  node.class.attributes.each_key do |a|
34
33
  v = node.public_send(a)
35
- Array(v).each { |child| check_string_list_attribute(child, issues, attr, label) }
34
+ Array(v).each do |child|
35
+ check_string_list_attribute(child, issues, attr, label)
36
+ end
36
37
  end
37
38
  end
38
39
  end
39
40
  end
40
41
  end
41
42
  end
42
- end
43
+ end
@@ -10,20 +10,34 @@ module Dcc
10
10
  module Schematron
11
11
  module Rules
12
12
  autoload :Base, "dcc/validate/schematron/rules/base"
13
- autoload :UsedMethodsPlacement, "dcc/validate/schematron/rules/used_methods_placement"
14
- autoload :UsedSoftwarePlacement, "dcc/validate/schematron/rules/used_software_placement"
15
- autoload :InfluenceConditionsPlacement, "dcc/validate/schematron/rules/influence_conditions_placement"
16
- autoload :SchemaVersionCheck, "dcc/validate/schematron/rules/schema_version_check"
17
- autoload :IdRefIdLinking, "dcc/validate/schematron/rules/id_refid_linking"
18
- autoload :IsoCodeValidation, "dcc/validate/schematron/rules/iso_code_validation"
19
- autoload :DateRangeCheck, "dcc/validate/schematron/rules/date_range_check"
20
- autoload :ReleaseFormatCheck, "dcc/validate/schematron/rules/release_format_check"
21
- autoload :UncertaintyConsistency, "dcc/validate/schematron/rules/uncertainty_consistency"
22
- autoload :UnitFormatCheck, "dcc/validate/schematron/rules/unit_format_check"
23
- autoload :NonSiDeclaration, "dcc/validate/schematron/rules/non_si_declaration"
24
- autoload :LanguageCodeDedup, "dcc/validate/schematron/rules/language_code_dedup"
25
- autoload :XmlListSpacing, "dcc/validate/schematron/rules/xml_list_spacing"
26
- autoload :AdministrativeDataCompleteness, "dcc/validate/schematron/rules/administrative_data_completeness"
13
+ autoload :UsedMethodsPlacement,
14
+ "dcc/validate/schematron/rules/used_methods_placement"
15
+ autoload :UsedSoftwarePlacement,
16
+ "dcc/validate/schematron/rules/used_software_placement"
17
+ autoload :InfluenceConditionsPlacement,
18
+ "dcc/validate/schematron/rules/influence_conditions_placement"
19
+ autoload :SchemaVersionCheck,
20
+ "dcc/validate/schematron/rules/schema_version_check"
21
+ autoload :IdRefIdLinking,
22
+ "dcc/validate/schematron/rules/id_refid_linking"
23
+ autoload :IsoCodeValidation,
24
+ "dcc/validate/schematron/rules/iso_code_validation"
25
+ autoload :DateRangeCheck,
26
+ "dcc/validate/schematron/rules/date_range_check"
27
+ autoload :ReleaseFormatCheck,
28
+ "dcc/validate/schematron/rules/release_format_check"
29
+ autoload :UncertaintyConsistency,
30
+ "dcc/validate/schematron/rules/uncertainty_consistency"
31
+ autoload :UnitFormatCheck,
32
+ "dcc/validate/schematron/rules/unit_format_check"
33
+ autoload :NonSiDeclaration,
34
+ "dcc/validate/schematron/rules/non_si_declaration"
35
+ autoload :LanguageCodeDedup,
36
+ "dcc/validate/schematron/rules/language_code_dedup"
37
+ autoload :XmlListSpacing,
38
+ "dcc/validate/schematron/rules/xml_list_spacing"
39
+ autoload :AdministrativeDataCompleteness,
40
+ "dcc/validate/schematron/rules/administrative_data_completeness"
27
41
  end
28
42
  end
29
43
  end
@@ -19,4 +19,4 @@ module Dcc
19
19
  end
20
20
  end
21
21
  end
22
- end
22
+ end
@@ -27,7 +27,9 @@ module Dcc
27
27
  resolved = ::Dcc::Schema::Version.resolve_dcc(version, xml: xml)
28
28
  schema = schema_for(resolved)
29
29
  doc = parse_xml(xml)
30
- errors = schema.validate(doc).map { |e| issue_from_nokogiri(e, resolved) }
30
+ errors = schema.validate(doc).map do |e|
31
+ issue_from_nokogiri(e, resolved)
32
+ end
31
33
 
32
34
  ::Dcc::Validate::Result.new(
33
35
  issues: errors,
@@ -60,10 +62,14 @@ module Dcc
60
62
  content = ::File.read(xsd_path)
61
63
  content.gsub(/schemaLocation\s*=\s*"([^"]+)"/) do |_match|
62
64
  relative = ::Regexp.last_match(1)
63
- next %{schemaLocation="#{relative}"} if relative.start_with?("http", "file://")
65
+ next %{schemaLocation="#{relative}"} if relative.start_with?(
66
+ "http", "file://"
67
+ )
64
68
 
65
69
  absolute = ::File.expand_path(relative, base_dir)
66
- %{schemaLocation="file://#{absolute}"}
70
+ uri_path = absolute.gsub(::File::ALT_SEPARATOR || "\\", "/")
71
+ uri_path = "/#{uri_path}" unless uri_path.start_with?("/")
72
+ %{schemaLocation="file://#{uri_path}"}
67
73
  end
68
74
  end
69
75
 
data/lib/dcc/validate.rb CHANGED
@@ -12,4 +12,4 @@ module Dcc
12
12
  autoload :Schematron, "dcc/validate/schematron"
13
13
  autoload :BusinessRules, "dcc/validate/business_rules"
14
14
  end
15
- end
15
+ end
data/lib/dcc/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dcc
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
@@ -42,7 +42,7 @@ module Dcc
42
42
  end
43
43
 
44
44
  def root_element_symbol
45
- self.const_get(:ROOT_ELEMENT_TAG).to_sym
45
+ const_get(:ROOT_ELEMENT_TAG).to_sym
46
46
  end
47
47
  end
48
48
  end
data/lib/dcc.rb CHANGED
@@ -74,16 +74,63 @@ module Dcc
74
74
  # Build a new DCC programmatically using the builder DSL.
75
75
  # @yield [Dcc::Builder::Session] builder session
76
76
  # @param version [Integer, nil] major DCC version (default: 3).
77
- def build(version: 3, &block)
78
- Builder.call(version: version, &block)
77
+ def build(version: 3, &)
78
+ Builder.call(version: version, &)
79
79
  end
80
80
 
81
- # Migrate a parsed DCC object from one schema version to another.
82
- # @param dcc [Dcc::V2::DigitalCalibrationCertificate, Dcc::V3::DigitalCalibrationCertificate]
81
+ # Load plugin gems by name.
82
+ #
83
+ # A gem name maps to its entry file the usual way: "dcc-audit" loads
84
+ # "dcc/audit". A slash-separated path is accepted unchanged.
85
+ #
86
+ # @param names [Array<String, Symbol>] plugin gem names.
87
+ # @raise [Dcc::PluginError] if a plugin's entry file cannot be loaded.
88
+ # @return [Array<String>] the entry-file path for each name given.
89
+ # A plugin already loaded is left alone and its path still returned.
90
+ #
91
+ # A plugin whose own `require` fails raises from inside a file we did
92
+ # find. Reporting that as a missing entry file points the author at the
93
+ # wrong problem, so only the entry path's own LoadError is wrapped.
94
+ def load_plugins(*names)
95
+ names.flatten.map do |name|
96
+ path = plugin_path(name)
97
+ require path
98
+ path
99
+ rescue ::LoadError => e
100
+ raise unless e.path == path
101
+
102
+ raise PluginError, "could not load plugin #{name}: tried " \
103
+ "require #{path.inspect} (#{e.message})"
104
+ end
105
+ end
106
+
107
+ # "dcc-audit" is a gem name and maps to "dcc/audit". Anything already
108
+ # carrying a slash is a require path and is left alone, hyphens included.
109
+ def plugin_path(name)
110
+ text = name.to_s
111
+ text.include?("/") ? text : text.tr("-", "/")
112
+ end
113
+ private :plugin_path
114
+
115
+ # Migrate a DCC from one schema version to another.
116
+ #
117
+ # Prefer passing the source XML. A parsed model has to be serialized back
118
+ # to XML before the transform runs, so anything the model could not
119
+ # round-trip is already gone and cannot be migrated or reported.
120
+ #
121
+ # @param input [String, IO, Dcc::V2::DigitalCalibrationCertificate,
122
+ # Dcc::V3::DigitalCalibrationCertificate] DCC source XML, or a parsed DCC.
83
123
  # @param from [String] source version, e.g. "2.3.0".
84
124
  # @param to [String] target version, e.g. "3.3.0".
85
- def migrate(dcc, from:, to:)
86
- Migrate.call(dcc, from: from, to: to)
125
+ # @param on_loss [#call, nil] callable receiving each message describing a
126
+ # construct the migration changed or discarded (a String per loss).
127
+ # When given, the messages go to the callable and nothing is sent to
128
+ # `Kernel.warn`; when nil (the default), each loss report is warned to
129
+ # stderr as before.
130
+ # @return [Dcc::V2::DigitalCalibrationCertificate,
131
+ # Dcc::V3::DigitalCalibrationCertificate] always a parsed DCC.
132
+ def migrate(input, from:, to:, on_loss: nil)
133
+ Migrate.call(input, from: from, to: to, on_loss: on_loss)
87
134
  end
88
135
 
89
136
  # Return the parser module for the given major version.
@@ -94,7 +141,8 @@ module Dcc
94
141
  when 2 then V2
95
142
  when 3 then V3
96
143
  else
97
- raise UnknownVersionError, "Unsupported DCC version: #{version.inspect} (expected 2 or 3)"
144
+ raise UnknownVersionError,
145
+ "Unsupported DCC version: #{version.inspect} (expected 2 or 3)"
98
146
  end
99
147
  end
100
148
 
data/sample_dcc.xml ADDED
@@ -0,0 +1,140 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <dcc:digitalCalibrationCertificate
3
+ xmlns:dcc="https://ptb.de/dcc"
4
+ xmlns:si="https://ptb.de/si"
5
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6
+ xsi:schemaLocation="https://ptb.de/dcc https://ptb.de/dcc/v3.3.0/dcc.xsd"
7
+ schemaVersion="3.3.0">
8
+
9
+ <dcc:administrativeData>
10
+ <dcc:dccSoftware>
11
+ <dcc:software>
12
+ <dcc:name><dcc:content lang="en">DCC Validator Builder</dcc:content></dcc:name>
13
+ <dcc:release>0.1.0</dcc:release>
14
+ </dcc:software>
15
+ </dcc:dccSoftware>
16
+
17
+ <dcc:coreData>
18
+ <dcc:countryCodeISO3166_1>DE</dcc:countryCodeISO3166_1>
19
+ <dcc:usedLangCodeISO639_1>en</dcc:usedLangCodeISO639_1>
20
+ <dcc:usedLangCodeISO639_1>de</dcc:usedLangCodeISO639_1>
21
+ <dcc:mandatoryLangCodeISO639_1>en</dcc:mandatoryLangCodeISO639_1>
22
+ <dcc:uniqueIdentifier>PTB-A0123-2026</dcc:uniqueIdentifier>
23
+ <dcc:beginPerformanceDate>2026-07-23</dcc:beginPerformanceDate>
24
+ <dcc:endPerformanceDate>2026-07-23</dcc:endPerformanceDate>
25
+ </dcc:coreData>
26
+
27
+ <dcc:items>
28
+ <dcc:item>
29
+ <dcc:name><dcc:content lang="en">Precision Resistance Decade 10 kΩ</dcc:content></dcc:name>
30
+ <dcc:manufacturer><dcc:name><dcc:content lang="en">Burster Präzisionsmesstechnik GmbH</dcc:content></dcc:name></dcc:manufacturer>
31
+ <dcc:model>BURSTER 1424</dcc:model>
32
+ </dcc:item>
33
+ </dcc:items>
34
+
35
+ <dcc:calibrationLaboratory>
36
+ <dcc:calibrationLaboratoryCode>DE1</dcc:calibrationLaboratoryCode>
37
+ <dcc:contact>
38
+ <dcc:name><dcc:content lang="en">Physikalisch-Technische Bundesanstalt</dcc:content></dcc:name>
39
+ <dcc:eMail>calibration@ptb.de</dcc:eMail>
40
+ </dcc:contact>
41
+ </dcc:calibrationLaboratory>
42
+
43
+ <dcc:respPersons>
44
+ <dcc:respPerson>
45
+ <dcc:person>
46
+ <dcc:name><dcc:content lang="en">Dr. Klaus-Dieter Sommer</dcc:content></dcc:name>
47
+ <dcc:eMail>k.sommer@ptb.de</dcc:eMail>
48
+ </dcc:person>
49
+ <dcc:mainSigner>true</dcc:mainSigner>
50
+ </dcc:respPerson>
51
+ </dcc:respPersons>
52
+
53
+ <dcc:customer>
54
+ <dcc:name><dcc:content lang="en">Burster Präzisionsmesstechnik GmbH</dcc:content></dcc:name>
55
+ </dcc:customer>
56
+ </dcc:administrativeData>
57
+
58
+ <dcc:measurementResults>
59
+ <dcc:measurementResult>
60
+ <dcc:name><dcc:content lang="en">Calibration Results</dcc:content></dcc:name>
61
+ <dcc:results>
62
+ <dcc:result>
63
+ <dcc:name><dcc:content lang="en">Resistance calibration at 1 kΩ</dcc:content></dcc:name>
64
+ <dcc:data>
65
+ <dcc:quantity>
66
+ <dcc:name><dcc:content lang="en">Actual resistance</dcc:content></dcc:name>
67
+ <si:real>
68
+ <si:value>999.982</si:value>
69
+ <si:unit>\ohm</si:unit>
70
+ <si:expandedMU>
71
+ <si:valueExpandedMU>0.012</si:valueExpandedMU>
72
+ <si:coverageFactor>2</si:coverageFactor>
73
+ <si:coverageProbability>0.95</si:coverageProbability>
74
+ </si:expandedMU>
75
+ </si:real>
76
+ </dcc:quantity>
77
+ <dcc:quantity>
78
+ <dcc:name><dcc:content lang="en">Temperature coefficient</dcc:content></dcc:name>
79
+ <si:real>
80
+ <si:value>5.2e-6</si:value>
81
+ <si:unit>\per\kelvin</si:unit>
82
+ <si:expandedMU>
83
+ <si:valueExpandedMU>0.3e-6</si:valueExpandedMU>
84
+ <si:coverageFactor>2</si:coverageFactor>
85
+ <si:coverageProbability>0.95</si:coverageProbability>
86
+ </si:expandedMU>
87
+ </si:real>
88
+ </dcc:quantity>
89
+ </dcc:data>
90
+ </dcc:result>
91
+ <dcc:result>
92
+ <dcc:name><dcc:content lang="en">Resistance calibration at 10 kΩ</dcc:content></dcc:name>
93
+ <dcc:data>
94
+ <dcc:quantity>
95
+ <dcc:name><dcc:content lang="en">Actual resistance</dcc:content></dcc:name>
96
+ <si:real>
97
+ <si:value>10000.04</si:value>
98
+ <si:unit>\kilo\ohm</si:unit>
99
+ <si:expandedMU>
100
+ <si:valueExpandedMU>0.03</si:valueExpandedMU>
101
+ <si:coverageFactor>2</si:coverageFactor>
102
+ <si:coverageProbability>0.95</si:coverageProbability>
103
+ </si:expandedMU>
104
+ </si:real>
105
+ </dcc:quantity>
106
+ </dcc:data>
107
+ </dcc:result>
108
+ <dcc:result>
109
+ <dcc:name><dcc:content lang="en">Environmental conditions</dcc:content></dcc:name>
110
+ <dcc:data>
111
+ <dcc:quantity>
112
+ <dcc:name><dcc:content lang="en">Ambient temperature</dcc:content></dcc:name>
113
+ <si:real>
114
+ <si:value>23.0</si:value>
115
+ <si:unit>\degreeCelsius</si:unit>
116
+ <si:expandedMU>
117
+ <si:valueExpandedMU>0.2</si:valueExpandedMU>
118
+ <si:coverageFactor>2</si:coverageFactor>
119
+ <si:coverageProbability>0.95</si:coverageProbability>
120
+ </si:expandedMU>
121
+ </si:real>
122
+ </dcc:quantity>
123
+ <dcc:quantity>
124
+ <dcc:name><dcc:content lang="en">Relative humidity</dcc:content></dcc:name>
125
+ <si:real>
126
+ <si:value>48</si:value>
127
+ <si:unit>\percent</si:unit>
128
+ <si:expandedMU>
129
+ <si:valueExpandedMU>2</si:valueExpandedMU>
130
+ <si:coverageFactor>2</si:coverageFactor>
131
+ <si:coverageProbability>0.95</si:coverageProbability>
132
+ </si:expandedMU>
133
+ </si:real>
134
+ </dcc:quantity>
135
+ </dcc:data>
136
+ </dcc:result>
137
+ </dcc:results>
138
+ </dcc:measurementResult>
139
+ </dcc:measurementResults>
140
+ </dcc:digitalCalibrationCertificate>
data/web/index.html ADDED
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1.0" />
6
+ <title>DCC Validator</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.ts"></script>
11
+ </body>
12
+ </html>