dcc 0.2.0

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 (336) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +16 -0
  5. data/.rubocop_todo.yml +10 -0
  6. data/CHANGELOG.adoc +54 -0
  7. data/CONTRIBUTING.adoc +64 -0
  8. data/Gemfile +25 -0
  9. data/LICENSE +21 -0
  10. data/README.adoc +69 -0
  11. data/Rakefile +13 -0
  12. data/dcc.gemspec +41 -0
  13. data/docs/cli-reference.adoc +67 -0
  14. data/docs/getting-started.adoc +117 -0
  15. data/docs/schema-versions.adoc +65 -0
  16. data/examples/build_minimal_dcc.rb +23 -0
  17. data/examples/convert_all_formats.rb +19 -0
  18. data/examples/parse_and_inspect.rb +19 -0
  19. data/examples/quantity_math_demo.rb +32 -0
  20. data/examples/validate_full.rb +27 -0
  21. data/exe/dcc +7 -0
  22. data/lib/dcc/base/administrative_data.rb +43 -0
  23. data/lib/dcc/base/byte_data.rb +36 -0
  24. data/lib/dcc/base/calibration_laboratory.rb +29 -0
  25. data/lib/dcc/base/comment.rb +23 -0
  26. data/lib/dcc/base/condition.rb +34 -0
  27. data/lib/dcc/base/contact.rb +38 -0
  28. data/lib/dcc/base/contact_not_strict.rb +38 -0
  29. data/lib/dcc/base/core_data.rb +44 -0
  30. data/lib/dcc/base/data.rb +42 -0
  31. data/lib/dcc/base/digital_calibration_certificate.rb +32 -0
  32. data/lib/dcc/base/equipment_class.rb +24 -0
  33. data/lib/dcc/base/formula.rb +33 -0
  34. data/lib/dcc/base/hash_type.rb +34 -0
  35. data/lib/dcc/base/identification.rb +27 -0
  36. data/lib/dcc/base/identifications.rb +27 -0
  37. data/lib/dcc/base/influence_condition.rb +16 -0
  38. data/lib/dcc/base/influence_condition_list.rb +40 -0
  39. data/lib/dcc/base/item.rb +38 -0
  40. data/lib/dcc/base/item_list.rb +38 -0
  41. data/lib/dcc/base/list.rb +44 -0
  42. data/lib/dcc/base/location.rb +36 -0
  43. data/lib/dcc/base/measurement_meta_data.rb +15 -0
  44. data/lib/dcc/base/measurement_meta_data_list.rb +27 -0
  45. data/lib/dcc/base/measurement_result.rb +41 -0
  46. data/lib/dcc/base/measurement_result_list.rb +28 -0
  47. data/lib/dcc/base/measuring_equipment.rb +41 -0
  48. data/lib/dcc/base/measuring_equipment_list.rb +38 -0
  49. data/lib/dcc/base/quantity.rb +61 -0
  50. data/lib/dcc/base/ref_type_definition.rb +36 -0
  51. data/lib/dcc/base/ref_type_definition_list.rb +21 -0
  52. data/lib/dcc/base/resp_person.rb +38 -0
  53. data/lib/dcc/base/resp_person_list.rb +27 -0
  54. data/lib/dcc/base/result.rb +31 -0
  55. data/lib/dcc/base/result_list.rb +27 -0
  56. data/lib/dcc/base/rich_content.rb +34 -0
  57. data/lib/dcc/base/software.rb +35 -0
  58. data/lib/dcc/base/software_list.rb +27 -0
  59. data/lib/dcc/base/statement.rb +50 -0
  60. data/lib/dcc/base/statement_list.rb +27 -0
  61. data/lib/dcc/base/string_with_lang.rb +24 -0
  62. data/lib/dcc/base/text.rb +33 -0
  63. data/lib/dcc/base/used_method.rb +31 -0
  64. data/lib/dcc/base/used_method_list.rb +27 -0
  65. data/lib/dcc/base/xml_blob.rb +20 -0
  66. data/lib/dcc/base.rb +58 -0
  67. data/lib/dcc/builder/dsl.rb +10 -0
  68. data/lib/dcc/builder/session.rb +170 -0
  69. data/lib/dcc/builder.rb +34 -0
  70. data/lib/dcc/cli/cli.rb +149 -0
  71. data/lib/dcc/cli/formatters.rb +77 -0
  72. data/lib/dcc/cli.rb +7 -0
  73. data/lib/dcc/common_elements.rb +20 -0
  74. data/lib/dcc/context_configuration.rb +167 -0
  75. data/lib/dcc/context_options.rb +47 -0
  76. data/lib/dcc/convert/csv.rb +129 -0
  77. data/lib/dcc/convert/html.rb +127 -0
  78. data/lib/dcc/convert/json.rb +62 -0
  79. data/lib/dcc/convert/result.rb +51 -0
  80. data/lib/dcc/convert/yaml.rb +21 -0
  81. data/lib/dcc/convert.rb +14 -0
  82. data/lib/dcc/diff/change.rb +21 -0
  83. data/lib/dcc/diff/result.rb +58 -0
  84. data/lib/dcc/diff.rb +83 -0
  85. data/lib/dcc/error.rb +54 -0
  86. data/lib/dcc/extract/file.rb +143 -0
  87. data/lib/dcc/extract/ring.rb +28 -0
  88. data/lib/dcc/extract.rb +9 -0
  89. data/lib/dcc/i18n/text_lookup.rb +67 -0
  90. data/lib/dcc/i18n.rb +12 -0
  91. data/lib/dcc/inspect/report.rb +139 -0
  92. data/lib/dcc/inspect.rb +9 -0
  93. data/lib/dcc/migrate.rb +41 -0
  94. data/lib/dcc/namespace/dcc.rb +30 -0
  95. data/lib/dcc/namespace/dsig.rb +15 -0
  96. data/lib/dcc/namespace/math_ml.rb +14 -0
  97. data/lib/dcc/namespace/qudt.rb +15 -0
  98. data/lib/dcc/namespace/si.rb +26 -0
  99. data/lib/dcc/namespace.rb +18 -0
  100. data/lib/dcc/plugin/registry.rb +45 -0
  101. data/lib/dcc/plugin.rb +42 -0
  102. data/lib/dcc/quantity_format/formatter.rb +90 -0
  103. data/lib/dcc/quantity_format.rb +10 -0
  104. data/lib/dcc/quantity_math/quantity.rb +46 -0
  105. data/lib/dcc/quantity_math/real.rb +116 -0
  106. data/lib/dcc/quantity_math.rb +14 -0
  107. data/lib/dcc/schema/resources/dcc/dsi/v1.0.1.xsd +415 -0
  108. data/lib/dcc/schema/resources/dcc/dsi/v1.3.0.xsd +814 -0
  109. data/lib/dcc/schema/resources/dcc/dsi/v1.3.1.xsd +814 -0
  110. data/lib/dcc/schema/resources/dcc/dsi/v2.0.0.xsd +869 -0
  111. data/lib/dcc/schema/resources/dcc/dsi/v2.1.0.xsd +1031 -0
  112. data/lib/dcc/schema/resources/dcc/dsi/v2.2.1.xsd +1574 -0
  113. data/lib/dcc/schema/resources/dcc/qudt/v2.2.1.xsd +44 -0
  114. data/lib/dcc/schema/resources/dcc/v2.1.0/dcc.xsd +650 -0
  115. data/lib/dcc/schema/resources/dcc/v2.1.1/dcc.xsd +669 -0
  116. data/lib/dcc/schema/resources/dcc/v2.2.0/dcc.xsd +730 -0
  117. data/lib/dcc/schema/resources/dcc/v2.3.0/dcc.xsd +708 -0
  118. data/lib/dcc/schema/resources/dcc/v2.4.0/dcc.xsd +725 -0
  119. data/lib/dcc/schema/resources/dcc/v3.0.0/dcc.xsd +749 -0
  120. data/lib/dcc/schema/resources/dcc/v3.1.0/dcc.xsd +843 -0
  121. data/lib/dcc/schema/resources/dcc/v3.1.1/dcc.xsd +843 -0
  122. data/lib/dcc/schema/resources/dcc/v3.1.2/dcc.xsd +844 -0
  123. data/lib/dcc/schema/resources/dcc/v3.2.0/dcc.xsd +940 -0
  124. data/lib/dcc/schema/resources/dcc/v3.2.1/dcc.xsd +963 -0
  125. data/lib/dcc/schema/resources/dcc/v3.3.0/dcc.xsd +1008 -0
  126. data/lib/dcc/schema/resources/dcc/xmldsig-core-schema.xsd +312 -0
  127. data/lib/dcc/schema/resources/dsi/qudt/v2.2.1.xsd +44 -0
  128. data/lib/dcc/schema/resources/dsi/v1.0.1/SI_Format.xsd +415 -0
  129. data/lib/dcc/schema/resources/dsi/v1.3.0/SI_Format.xsd +814 -0
  130. data/lib/dcc/schema/resources/dsi/v1.3.1/SI_Format.xsd +814 -0
  131. data/lib/dcc/schema/resources/dsi/v2.0.0/SI_Format.xsd +869 -0
  132. data/lib/dcc/schema/resources/dsi/v2.1.0/SI_Format.xsd +1031 -0
  133. data/lib/dcc/schema/resources/dsi/v2.2.1/SI_Format.xsd +1574 -0
  134. data/lib/dcc/schema/resources/qudt/qudt.xsd +44 -0
  135. data/lib/dcc/schema/resources/schematron/dcc.sch +523 -0
  136. data/lib/dcc/schema/resources/schematron/dcc.svrl +2302 -0
  137. data/lib/dcc/schema/resources/xmldsig/xmldsig-core-schema.xsd +312 -0
  138. data/lib/dcc/schema/version.rb +94 -0
  139. data/lib/dcc/schema.rb +35 -0
  140. data/lib/dcc/server/app.rb +133 -0
  141. data/lib/dcc/server/storage/entry.rb +15 -0
  142. data/lib/dcc/server/storage/memory.rb +57 -0
  143. data/lib/dcc/server/storage.rb +13 -0
  144. data/lib/dcc/server.rb +33 -0
  145. data/lib/dcc/si/base/complex.rb +43 -0
  146. data/lib/dcc/si/base/complex_list_xml_list.rb +39 -0
  147. data/lib/dcc/si/base/constant.rb +39 -0
  148. data/lib/dcc/si/base/coverage_interval_mu.rb +31 -0
  149. data/lib/dcc/si/base/expanded_mu.rb +29 -0
  150. data/lib/dcc/si/base/expanded_unc_xml_list.rb +30 -0
  151. data/lib/dcc/si/base/hybrid.rb +42 -0
  152. data/lib/dcc/si/base/measurement_uncertainty_univariate.rb +28 -0
  153. data/lib/dcc/si/base/real.rb +48 -0
  154. data/lib/dcc/si/base/real_list_xml_list.rb +45 -0
  155. data/lib/dcc/si/base/si_list.rb +37 -0
  156. data/lib/dcc/si/base/standard_mu.rb +25 -0
  157. data/lib/dcc/si/base.rb +24 -0
  158. data/lib/dcc/si/common_elements.rb +13 -0
  159. data/lib/dcc/si/namespace.rb +7 -0
  160. data/lib/dcc/si/v1/common_elements.rb +13 -0
  161. data/lib/dcc/si/v1/complex.rb +8 -0
  162. data/lib/dcc/si/v1/complex_list_xml_list.rb +8 -0
  163. data/lib/dcc/si/v1/configuration.rb +13 -0
  164. data/lib/dcc/si/v1/constant.rb +8 -0
  165. data/lib/dcc/si/v1/coverage_interval_mu.rb +8 -0
  166. data/lib/dcc/si/v1/expanded_mu.rb +8 -0
  167. data/lib/dcc/si/v1/expanded_unc.rb +23 -0
  168. data/lib/dcc/si/v1/expanded_unc_xml_list.rb +8 -0
  169. data/lib/dcc/si/v1/hybrid.rb +8 -0
  170. data/lib/dcc/si/v1/measurement_uncertainty_univariate.rb +8 -0
  171. data/lib/dcc/si/v1/namespace.rb +9 -0
  172. data/lib/dcc/si/v1/real.rb +8 -0
  173. data/lib/dcc/si/v1/real_list_xml_list.rb +8 -0
  174. data/lib/dcc/si/v1/si_list.rb +8 -0
  175. data/lib/dcc/si/v1/standard_mu.rb +8 -0
  176. data/lib/dcc/si/v1.rb +46 -0
  177. data/lib/dcc/si/v2/common_elements.rb +13 -0
  178. data/lib/dcc/si/v2/complex.rb +8 -0
  179. data/lib/dcc/si/v2/complex_list_xml_list.rb +8 -0
  180. data/lib/dcc/si/v2/configuration.rb +13 -0
  181. data/lib/dcc/si/v2/constant.rb +8 -0
  182. data/lib/dcc/si/v2/coverage_interval_mu.rb +8 -0
  183. data/lib/dcc/si/v2/coverage_interval_mu_xml_list.rb +24 -0
  184. data/lib/dcc/si/v2/expanded_mu.rb +8 -0
  185. data/lib/dcc/si/v2/expanded_mu_xml_list.rb +22 -0
  186. data/lib/dcc/si/v2/expanded_unc_xml_list.rb +8 -0
  187. data/lib/dcc/si/v2/hybrid.rb +8 -0
  188. data/lib/dcc/si/v2/measurement_uncertainty_univariate.rb +8 -0
  189. data/lib/dcc/si/v2/namespace.rb +9 -0
  190. data/lib/dcc/si/v2/real.rb +8 -0
  191. data/lib/dcc/si/v2/real_list_xml_list.rb +8 -0
  192. data/lib/dcc/si/v2/si_list.rb +8 -0
  193. data/lib/dcc/si/v2/standard_mu.rb +8 -0
  194. data/lib/dcc/si/v2/standard_mu_xml_list.rb +18 -0
  195. data/lib/dcc/si/v2.rb +49 -0
  196. data/lib/dcc/si.rb +34 -0
  197. data/lib/dcc/signature/result.rb +43 -0
  198. data/lib/dcc/signature/signer.rb +36 -0
  199. data/lib/dcc/signature/verifier.rb +41 -0
  200. data/lib/dcc/signature.rb +13 -0
  201. data/lib/dcc/transform/result.rb +24 -0
  202. data/lib/dcc/transform/xslt.rb +72 -0
  203. data/lib/dcc/transform.rb +12 -0
  204. data/lib/dcc/type/base64_binary.rb +55 -0
  205. data/lib/dcc/type/decimal_xml_list.rb +47 -0
  206. data/lib/dcc/type/iso_country_code.rb +23 -0
  207. data/lib/dcc/type/iso_language_code.rb +23 -0
  208. data/lib/dcc/type/schema_version.rb +37 -0
  209. data/lib/dcc/type/si_unit.rb +26 -0
  210. data/lib/dcc/type.rb +16 -0
  211. data/lib/dcc/type_guards.rb +140 -0
  212. data/lib/dcc/v2/administrative_data.rb +8 -0
  213. data/lib/dcc/v2/byte_data.rb +8 -0
  214. data/lib/dcc/v2/calibration_laboratory.rb +8 -0
  215. data/lib/dcc/v2/comment.rb +8 -0
  216. data/lib/dcc/v2/common_elements.rb +13 -0
  217. data/lib/dcc/v2/condition.rb +8 -0
  218. data/lib/dcc/v2/configuration.rb +17 -0
  219. data/lib/dcc/v2/contact.rb +8 -0
  220. data/lib/dcc/v2/contact_not_strict.rb +8 -0
  221. data/lib/dcc/v2/core_data.rb +8 -0
  222. data/lib/dcc/v2/data.rb +8 -0
  223. data/lib/dcc/v2/digital_calibration_certificate.rb +8 -0
  224. data/lib/dcc/v2/equipment_class.rb +8 -0
  225. data/lib/dcc/v2/formula.rb +8 -0
  226. data/lib/dcc/v2/hash_type.rb +8 -0
  227. data/lib/dcc/v2/identification.rb +8 -0
  228. data/lib/dcc/v2/identifications.rb +8 -0
  229. data/lib/dcc/v2/influence_condition.rb +7 -0
  230. data/lib/dcc/v2/influence_condition_list.rb +8 -0
  231. data/lib/dcc/v2/item.rb +8 -0
  232. data/lib/dcc/v2/item_list.rb +8 -0
  233. data/lib/dcc/v2/list.rb +8 -0
  234. data/lib/dcc/v2/location.rb +8 -0
  235. data/lib/dcc/v2/measurement_meta_data.rb +8 -0
  236. data/lib/dcc/v2/measurement_meta_data_list.rb +8 -0
  237. data/lib/dcc/v2/measurement_result.rb +8 -0
  238. data/lib/dcc/v2/measurement_result_list.rb +8 -0
  239. data/lib/dcc/v2/measuring_equipment.rb +8 -0
  240. data/lib/dcc/v2/measuring_equipment_list.rb +8 -0
  241. data/lib/dcc/v2/namespace.rb +8 -0
  242. data/lib/dcc/v2/quantity.rb +49 -0
  243. data/lib/dcc/v2/ref_type_definition.rb +11 -0
  244. data/lib/dcc/v2/ref_type_definition_list.rb +15 -0
  245. data/lib/dcc/v2/resp_person.rb +8 -0
  246. data/lib/dcc/v2/resp_person_list.rb +8 -0
  247. data/lib/dcc/v2/result.rb +8 -0
  248. data/lib/dcc/v2/result_list.rb +8 -0
  249. data/lib/dcc/v2/rich_content.rb +12 -0
  250. data/lib/dcc/v2/software.rb +8 -0
  251. data/lib/dcc/v2/software_list.rb +8 -0
  252. data/lib/dcc/v2/statement.rb +8 -0
  253. data/lib/dcc/v2/statement_list.rb +8 -0
  254. data/lib/dcc/v2/string_with_lang.rb +8 -0
  255. data/lib/dcc/v2/text.rb +8 -0
  256. data/lib/dcc/v2/used_method.rb +8 -0
  257. data/lib/dcc/v2/used_method_list.rb +8 -0
  258. data/lib/dcc/v2/xml_blob.rb +8 -0
  259. data/lib/dcc/v2.rb +84 -0
  260. data/lib/dcc/v3/administrative_data.rb +8 -0
  261. data/lib/dcc/v3/byte_data.rb +8 -0
  262. data/lib/dcc/v3/calibration_laboratory.rb +8 -0
  263. data/lib/dcc/v3/comment.rb +8 -0
  264. data/lib/dcc/v3/common_elements.rb +11 -0
  265. data/lib/dcc/v3/condition.rb +8 -0
  266. data/lib/dcc/v3/configuration.rb +17 -0
  267. data/lib/dcc/v3/contact.rb +8 -0
  268. data/lib/dcc/v3/contact_not_strict.rb +8 -0
  269. data/lib/dcc/v3/core_data.rb +8 -0
  270. data/lib/dcc/v3/data.rb +8 -0
  271. data/lib/dcc/v3/digital_calibration_certificate.rb +8 -0
  272. data/lib/dcc/v3/equipment_class.rb +8 -0
  273. data/lib/dcc/v3/formula.rb +8 -0
  274. data/lib/dcc/v3/hash_type.rb +8 -0
  275. data/lib/dcc/v3/identification.rb +8 -0
  276. data/lib/dcc/v3/identifications.rb +8 -0
  277. data/lib/dcc/v3/influence_condition.rb +7 -0
  278. data/lib/dcc/v3/influence_condition_list.rb +8 -0
  279. data/lib/dcc/v3/item.rb +8 -0
  280. data/lib/dcc/v3/item_list.rb +8 -0
  281. data/lib/dcc/v3/list.rb +8 -0
  282. data/lib/dcc/v3/location.rb +8 -0
  283. data/lib/dcc/v3/measurement_meta_data.rb +8 -0
  284. data/lib/dcc/v3/measurement_meta_data_list.rb +8 -0
  285. data/lib/dcc/v3/measurement_result.rb +8 -0
  286. data/lib/dcc/v3/measurement_result_list.rb +8 -0
  287. data/lib/dcc/v3/measuring_equipment.rb +8 -0
  288. data/lib/dcc/v3/measuring_equipment_list.rb +8 -0
  289. data/lib/dcc/v3/namespace.rb +7 -0
  290. data/lib/dcc/v3/quantity.rb +49 -0
  291. data/lib/dcc/v3/ref_type_definition.rb +8 -0
  292. data/lib/dcc/v3/ref_type_definition_list.rb +8 -0
  293. data/lib/dcc/v3/resp_person.rb +8 -0
  294. data/lib/dcc/v3/resp_person_list.rb +8 -0
  295. data/lib/dcc/v3/result.rb +8 -0
  296. data/lib/dcc/v3/result_list.rb +8 -0
  297. data/lib/dcc/v3/rich_content.rb +8 -0
  298. data/lib/dcc/v3/software.rb +8 -0
  299. data/lib/dcc/v3/software_list.rb +8 -0
  300. data/lib/dcc/v3/statement.rb +8 -0
  301. data/lib/dcc/v3/statement_list.rb +8 -0
  302. data/lib/dcc/v3/string_with_lang.rb +8 -0
  303. data/lib/dcc/v3/text.rb +8 -0
  304. data/lib/dcc/v3/used_method.rb +8 -0
  305. data/lib/dcc/v3/used_method_list.rb +8 -0
  306. data/lib/dcc/v3/xml_blob.rb +8 -0
  307. data/lib/dcc/v3.rb +111 -0
  308. data/lib/dcc/validate/business_rules.rb +121 -0
  309. data/lib/dcc/validate/issue.rb +56 -0
  310. data/lib/dcc/validate/result.rb +105 -0
  311. data/lib/dcc/validate/schematron/profile.rb +64 -0
  312. data/lib/dcc/validate/schematron/rule.rb +49 -0
  313. data/lib/dcc/validate/schematron/rules/administrative_data_completeness.rb +42 -0
  314. data/lib/dcc/validate/schematron/rules/base.rb +15 -0
  315. data/lib/dcc/validate/schematron/rules/date_range_check.rb +41 -0
  316. data/lib/dcc/validate/schematron/rules/id_refid_linking.rb +61 -0
  317. data/lib/dcc/validate/schematron/rules/influence_conditions_placement.rb +58 -0
  318. data/lib/dcc/validate/schematron/rules/iso_code_validation.rb +53 -0
  319. data/lib/dcc/validate/schematron/rules/language_code_dedup.rb +39 -0
  320. data/lib/dcc/validate/schematron/rules/non_si_declaration.rb +82 -0
  321. data/lib/dcc/validate/schematron/rules/release_format_check.rb +44 -0
  322. data/lib/dcc/validate/schematron/rules/schema_version_check.rb +31 -0
  323. data/lib/dcc/validate/schematron/rules/uncertainty_consistency.rb +58 -0
  324. data/lib/dcc/validate/schematron/rules/unit_format_check.rb +74 -0
  325. data/lib/dcc/validate/schematron/rules/used_methods_placement.rb +65 -0
  326. data/lib/dcc/validate/schematron/rules/used_software_placement.rb +43 -0
  327. data/lib/dcc/validate/schematron/rules/xml_list_spacing.rb +42 -0
  328. data/lib/dcc/validate/schematron/rules.rb +30 -0
  329. data/lib/dcc/validate/schematron.rb +22 -0
  330. data/lib/dcc/validate/severity.rb +39 -0
  331. data/lib/dcc/validate/xsd.rb +97 -0
  332. data/lib/dcc/validate.rb +15 -0
  333. data/lib/dcc/version.rb +5 -0
  334. data/lib/dcc/versioned_parser.rb +48 -0
  335. data/lib/dcc.rb +141 -0
  336. metadata +425 -0
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+ require "lutaml/model"
5
+
6
+ module Dcc
7
+ module Type
8
+ # Base64-encoded binary data, used by `dcc:dataBase64` in
9
+ # `dcc:byteDataType`.
10
+ #
11
+ # The wire format is base64 text (`VGVzdAo=`). We pass it through
12
+ # unchanged on `cast` so that round-trip serialization is byte-identical.
13
+ # Callers that need the decoded binary bytes call `.decode`.
14
+ class Base64Binary < Lutaml::Model::Type::Value
15
+ def self.cast(value)
16
+ return nil if value.nil? || value == ""
17
+ unless value.is_a?(::String)
18
+ raise Lutaml::Model::Type::InvalidValueError.new(value, "expected binary String")
19
+ end
20
+
21
+ value
22
+ end
23
+
24
+ def self.serialize(value)
25
+ return nil if value.nil?
26
+
27
+ unless value.is_a?(::String)
28
+ raise Lutaml::Model::Type::InvalidValueError.new(value, "expected binary String")
29
+ end
30
+
31
+ value
32
+ end
33
+
34
+ # Convenience: decode the base64 string to binary bytes.
35
+ # @param value [String, nil]
36
+ # @return [String] binary ASCII-8BIT string, or `""` if invalid.
37
+ def self.decode(value)
38
+ return "" unless value && !value.to_s.empty?
39
+
40
+ ::Base64.strict_decode64(value.to_s).b
41
+ rescue ::ArgumentError
42
+ ""
43
+ end
44
+
45
+ # Convenience: encode binary bytes to base64 text.
46
+ # @param value [String, nil]
47
+ # @return [String, nil]
48
+ def self.encode(value)
49
+ return nil if value.nil?
50
+
51
+ ::Base64.strict_encode64(value)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bigdecimal"
4
+ require "lutaml/model"
5
+
6
+ module Dcc
7
+ module Type
8
+ # Space-separated list of decimals, as used by D-SI `*XMLList` elements
9
+ # (e.g. `<si:valueXMLList>306 373 448</si:valueXMLList>`). Parses to/from
10
+ # an Array of BigDecimal values.
11
+ class DecimalXmlList < Lutaml::Model::Type::Value
12
+ def self.cast(value)
13
+ return [] if value.nil?
14
+ return value.map { |v| cast_one(v) } if value.is_a?(::Array)
15
+
16
+ value.to_s.split(/\s+/).reject(&:empty?).map { |s| cast_one(s) }
17
+ end
18
+
19
+ def self.serialize(value)
20
+ return "" if value.nil?
21
+
22
+ Array(value).map { |v| serialize_one(v) }.join(" ")
23
+ end
24
+
25
+ class << self
26
+ private
27
+
28
+ def cast_one(token)
29
+ return token if token.is_a?(::BigDecimal)
30
+
31
+ BigDecimal(token.to_s)
32
+ rescue ::ArgumentError => e
33
+ raise Lutaml::Model::Type::InvalidValueError.new(token,
34
+ "invalid decimal in XML list: #{e.message}")
35
+ end
36
+
37
+ def serialize_one(value)
38
+ case value
39
+ when ::BigDecimal then value.to_i.to_s == value.to_s("F") ? value.to_i.to_s : value.to_s("F").sub(/\.0\z/, "")
40
+ when ::Float then format("%.15g", value)
41
+ else value.to_s
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Dcc
6
+ module Type
7
+ # ISO 3166-1 alpha-2 country code (two uppercase letters, e.g. `"DE"`).
8
+ # Used by `dcc:countryCodeISO3166_1`.
9
+ class IsoCountryCode < Lutaml::Model::Type::String
10
+ PATTERN = /\A[A-Z]{2}\z/.freeze
11
+
12
+ def self.cast(value)
13
+ return nil unless value.is_a?(::String) && value != ""
14
+
15
+ unless PATTERN.match?(value)
16
+ raise Lutaml::Model::Type::InvalidValueError.new(value, "invalid ISO 3166-1 alpha-2 country code: #{value.inspect}")
17
+ end
18
+
19
+ value
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Dcc
6
+ module Type
7
+ # ISO 639-1 language code (two lowercase letters, e.g. `"en"`).
8
+ # Used by `dcc:usedLangCodeISO639_1` and `dcc:mandatoryLangCodeISO639_1`.
9
+ class IsoLanguageCode < Lutaml::Model::Type::String
10
+ PATTERN = /\A[a-z]{2}\z/.freeze
11
+
12
+ def self.cast(value)
13
+ return nil unless value.is_a?(::String) && value != ""
14
+
15
+ unless PATTERN.match?(value)
16
+ raise Lutaml::Model::Type::InvalidValueError.new(value, "invalid ISO 639-1 language code: #{value.inspect}")
17
+ end
18
+
19
+ value
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Dcc
6
+ module Type
7
+ # DCC `schemaVersion` attribute (e.g. `"3.3.0"`, `"3.4.0-rc.2"`).
8
+ # Validates the format on cast. Use `Dcc::Schema::Version.major(v)` to
9
+ # extract the major number from any version string.
10
+ class SchemaVersion < Lutaml::Model::Type::String
11
+ PATTERN = /\A
12
+ (?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)
13
+ (?:-(?<pre>[0-9A-Za-z.-]+))?
14
+ (?:\+(?<build>[0-9A-Za-z.-]+))?
15
+ \z/x.freeze
16
+
17
+ def self.cast(value)
18
+ return nil unless value.is_a?(::String) && value != ""
19
+
20
+ unless PATTERN.match?(value)
21
+ raise Lutaml::Model::Type::InvalidValueError.new(value, "invalid schemaVersion")
22
+ end
23
+
24
+ value
25
+ end
26
+
27
+ def major
28
+ self.class.extract_major(to_s)
29
+ end
30
+
31
+ def self.extract_major(value)
32
+ m = PATTERN.match(value.to_s)
33
+ m && Integer(m[:major])
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Dcc
6
+ module Type
7
+ # D-SI unit expression in siunitx notation (e.g. `"\kelvin"`,
8
+ # `"\meter\per\second\squared"`). The full siunitx grammar is enforced by
9
+ # the D-SI ontology's SHACL profile; here we apply a lightweight syntactic
10
+ # check: the string must not contain whitespace (Schematron rule), and the
11
+ # non-SI declaration prefix (`|unit`) is allowed.
12
+ class SiUnit < Lutaml::Model::Type::String
13
+ NO_WHITESPACE_PATTERN = /\A\S+\z/.freeze
14
+
15
+ def self.cast(value)
16
+ return nil unless value.is_a?(::String) && value != ""
17
+
18
+ unless NO_WHITESPACE_PATTERN.match?(value)
19
+ raise Lutaml::Model::Type::InvalidValueError.new(value, "invalid SI unit expression (whitespace not allowed): #{value.inspect}")
20
+ end
21
+
22
+ value
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/dcc/type.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # `Dcc::Type` hosts the gem's custom `Lutaml::Model::Type::Value` subclasses.
4
+ # These encode XML-level constraints (ISO code patterns, siunitx unit grammar,
5
+ # base64 binary, space-separated decimal lists) that the framework's built-in
6
+ # types do not cover.
7
+ module Dcc
8
+ module Type
9
+ autoload :IsoCountryCode, "dcc/type/iso_country_code"
10
+ autoload :IsoLanguageCode, "dcc/type/iso_language_code"
11
+ autoload :SiUnit, "dcc/type/si_unit"
12
+ autoload :DecimalXmlList, "dcc/type/decimal_xml_list"
13
+ autoload :Base64Binary, "dcc/type/base64_binary"
14
+ autoload :SchemaVersion, "dcc/type/schema_version"
15
+ end
16
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ # `Dcc::TypeGuards` provides type-safe introspection helpers that replace
4
+ # `respond_to?` (banned per project rule) with explicit `is_a?` checks.
5
+ # Each helper returns true/false without raising.
6
+ module Dcc
7
+ module TypeGuards
8
+ module_function
9
+
10
+ # True if `node` is any version of DCC root.
11
+ def digital_calibration_certificate?(node)
12
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
13
+
14
+ node.class.name.end_with?("::DigitalCalibrationCertificate")
15
+ end
16
+
17
+ # True if `node` has an `administrative_data` attribute (DCC root only).
18
+ def has_administrative_data?(node)
19
+ digital_calibration_certificate?(node)
20
+ end
21
+
22
+ # True if `node` is a `MeasurementResultList` (any version).
23
+ def measurement_result_list?(node)
24
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
25
+
26
+ node.class.name.end_with?("::MeasurementResultList")
27
+ end
28
+
29
+ # True if `node` is an `AdministrativeData` (any version).
30
+ def administrative_data?(node)
31
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
32
+
33
+ node.class.name.end_with?("::AdministrativeData")
34
+ end
35
+
36
+ # True if `node` is a `CoreData` (any version).
37
+ def core_data?(node)
38
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
39
+
40
+ node.class.name.end_with?("::CoreData")
41
+ end
42
+
43
+ # True if `node` is a `RespPersonList` (any version).
44
+ def resp_person_list?(node)
45
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
46
+
47
+ node.class.name.end_with?("::RespPersonList")
48
+ end
49
+
50
+ # True if `node` is a `RespPerson` (any version).
51
+ def resp_person?(node)
52
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
53
+
54
+ node.class.name.end_with?("::RespPerson")
55
+ end
56
+
57
+ # True if `node` is a `SoftwareList` (any version).
58
+ def software_list?(node)
59
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
60
+
61
+ node.class.name.end_with?("::SoftwareList")
62
+ end
63
+
64
+ # True if `node` is a `Software` (any version).
65
+ def software?(node)
66
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
67
+
68
+ node.class.name.end_with?("::Software")
69
+ end
70
+
71
+ # True if `node` is a `RealListXmlList` (any version).
72
+ def real_list_xml_list?(node)
73
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
74
+
75
+ node.class.name.end_with?("::RealListXmlList")
76
+ end
77
+
78
+ # True if `node` is a `Text` (any version).
79
+ def text?(node)
80
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
81
+
82
+ node.class.name.end_with?("::Text")
83
+ end
84
+
85
+ # True if `node` is a `MeasurementResult` (any version).
86
+ def measurement_result?(node)
87
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
88
+
89
+ node.class.name.end_with?("::MeasurementResult")
90
+ end
91
+
92
+ # True if `node` is a `ByteData` (any version).
93
+ def byte_data?(node)
94
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
95
+
96
+ node.class.name.end_with?("::ByteData")
97
+ end
98
+
99
+ # True if `node` is a `Quantity` (any version).
100
+ def quantity?(node)
101
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
102
+
103
+ node.class.name.end_with?("::Quantity")
104
+ end
105
+
106
+ # Safe attribute reader: returns the value or nil if the node doesn't
107
+ # have the attribute. Uses explicit class introspection rather than
108
+ # `respond_to?`.
109
+ def read_attribute(node, name)
110
+ return nil unless node.is_a?(::Lutaml::Model::Serializable)
111
+ return nil unless node.class.attributes.key?(name)
112
+
113
+ node.public_send(name)
114
+ end
115
+
116
+ # Safe predicate: true if the node has the declared attribute.
117
+ # Replaces `node.respond_to?(:name)`.
118
+ def has_attribute?(node, name)
119
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
120
+
121
+ node.class.attributes.key?(name)
122
+ end
123
+
124
+ # Safe predicate: true if the node has a writer for the attribute.
125
+ # Replaces `node.respond_to?(:name=)`.
126
+ def has_writer?(node, name)
127
+ return false unless node.is_a?(::Lutaml::Model::Serializable)
128
+
129
+ node.class.attributes.key?(name)
130
+ end
131
+
132
+ # Safe method call: invokes the method if the node's class declares it.
133
+ def call_if_present(node, method_name, *args)
134
+ return nil unless node.is_a?(::Lutaml::Model::Serializable)
135
+ return nil unless node.class.attributes.key?(method_name)
136
+
137
+ node.public_send(method_name, *args)
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class AdministrativeData < CommonElements
5
+ include ::Dcc::Base::AdministrativeData
6
+ end
7
+ Configuration.register_model(AdministrativeData, id: :administrativeData)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class ByteData < CommonElements
5
+ include ::Dcc::Base::ByteData
6
+ end
7
+ Configuration.register_model(ByteData, id: :byteData)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class CalibrationLaboratory < CommonElements
5
+ include ::Dcc::Base::CalibrationLaboratory
6
+ end
7
+ Configuration.register_model(CalibrationLaboratory, id: :calibrationLaboratory)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Comment < CommonElements
5
+ include ::Dcc::Base::Comment
6
+ end
7
+ Configuration.register_model(Comment, id: :comment)
8
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc
4
+ module V2
5
+ # V2 base class. All V2 element wrappers inherit from this so they get
6
+ # `lutaml_default_register` returning `:dcc_v2` automatically.
7
+ class CommonElements < ::Dcc::CommonElements
8
+ def self.lutaml_default_register
9
+ :dcc_v2
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Condition < CommonElements
5
+ include ::Dcc::Base::Condition
6
+ end
7
+ Configuration.register_model(Condition, id: :influenceCondition)
8
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc
4
+ module V2
5
+ module Configuration
6
+ extend ::Dcc::ContextConfiguration
7
+
8
+ CONTEXT_ID = :dcc_v2
9
+
10
+ # V2 DCC imports D-SI v1.x (registered as :dsi_v1). We also fall back
11
+ # to :dsi_v2 for forward-compatible parsing.
12
+ def self.fallback_contexts
13
+ [:dsi_v1, :dsi_v2, :default]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Contact < CommonElements
5
+ include ::Dcc::Base::Contact
6
+ end
7
+ Configuration.register_model(Contact, id: :contact)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class ContactNotStrict < CommonElements
5
+ include ::Dcc::Base::ContactNotStrict
6
+ end
7
+ Configuration.register_model(ContactNotStrict, id: :contactNotStrict)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class CoreData < CommonElements
5
+ include ::Dcc::Base::CoreData
6
+ end
7
+ Configuration.register_model(CoreData, id: :coreData)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Data < CommonElements
5
+ include ::Dcc::Base::Data
6
+ end
7
+ Configuration.register_model(Data, id: :data)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class DigitalCalibrationCertificate < CommonElements
5
+ include ::Dcc::Base::DigitalCalibrationCertificate
6
+ end
7
+ Configuration.register_model(DigitalCalibrationCertificate, id: :digitalCalibrationCertificate)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class EquipmentClass < CommonElements
5
+ include ::Dcc::Base::EquipmentClass
6
+ end
7
+ Configuration.register_model(EquipmentClass, id: :equipmentClass)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Formula < CommonElements
5
+ include ::Dcc::Base::Formula
6
+ end
7
+ Configuration.register_model(Formula, id: :formula)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class HashType < CommonElements
5
+ include ::Dcc::Base::HashType
6
+ end
7
+ Configuration.register_model(HashType, id: :previousReport)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Identification < CommonElements
5
+ include ::Dcc::Base::Identification
6
+ end
7
+ Configuration.register_model(Identification, id: :identification)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Identifications < CommonElements
5
+ include ::Dcc::Base::Identifications
6
+ end
7
+ Configuration.register_model(Identifications, id: :identifications)
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class InfluenceCondition < CommonElements
5
+ include ::Dcc::Base::InfluenceCondition
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class InfluenceConditionList < CommonElements
5
+ include ::Dcc::Base::InfluenceConditionList
6
+ end
7
+ Configuration.register_model(InfluenceConditionList, id: :influenceConditions)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Item < CommonElements
5
+ include ::Dcc::Base::Item
6
+ end
7
+ Configuration.register_model(Item, id: :item)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class ItemList < CommonElements
5
+ include ::Dcc::Base::ItemList
6
+ end
7
+ Configuration.register_model(ItemList, id: :items)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class List < CommonElements
5
+ include ::Dcc::Base::List
6
+ end
7
+ Configuration.register_model(List, id: :list)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class Location < CommonElements
5
+ include ::Dcc::Base::Location
6
+ end
7
+ Configuration.register_model(Location, id: :location)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class MeasurementMetaData < CommonElements
5
+ include ::Dcc::Base::MeasurementMetaData
6
+ end
7
+ Configuration.register_model(MeasurementMetaData, id: :metaData)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class MeasurementMetaDataList < CommonElements
5
+ include ::Dcc::Base::MeasurementMetaDataList
6
+ end
7
+ Configuration.register_model(MeasurementMetaDataList, id: :measurementMetaData)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class MeasurementResult < CommonElements
5
+ include ::Dcc::Base::MeasurementResult
6
+ end
7
+ Configuration.register_model(MeasurementResult, id: :measurementResult)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class MeasurementResultList < CommonElements
5
+ include ::Dcc::Base::MeasurementResultList
6
+ end
7
+ Configuration.register_model(MeasurementResultList, id: :measurementResults)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class MeasuringEquipment < CommonElements
5
+ include ::Dcc::Base::MeasuringEquipment
6
+ end
7
+ Configuration.register_model(MeasuringEquipment, id: :measuringEquipment)
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dcc::V2
4
+ class MeasuringEquipmentList < CommonElements
5
+ include ::Dcc::Base::MeasuringEquipmentList
6
+ end
7
+ Configuration.register_model(MeasuringEquipmentList, id: :measuringEquipments)
8
+ end