dcc 0.2.0 → 0.2.2
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/ci.yml +19 -0
- data/.github/workflows/release.yml +28 -0
- data/.gitignore +4 -0
- data/.rubocop_todo.yml +560 -10
- data/CHANGELOG.adoc +34 -1
- data/CONTRIBUTING.adoc +8 -1
- data/Gemfile +5 -7
- data/README.adoc +162 -7
- data/dcc.gemspec +9 -2
- data/docs/schema-versions.adoc +20 -7
- data/examples/build_minimal_dcc.rb +0 -0
- data/examples/convert_all_formats.rb +2 -1
- data/examples/parse_and_inspect.rb +0 -0
- data/examples/quantity_math_demo.rb +7 -7
- data/examples/validate_full.rb +1 -1
- data/lib/dcc/base/calibration_laboratory.rb +2 -1
- data/lib/dcc/base/condition.rb +5 -2
- data/lib/dcc/base/core_data.rb +8 -3
- data/lib/dcc/base/formula.rb +3 -3
- data/lib/dcc/base/identification.rb +6 -3
- data/lib/dcc/base/mathml.rb +33 -0
- data/lib/dcc/base/quantity.rb +2 -1
- data/lib/dcc/base/resp_person.rb +4 -2
- data/lib/dcc/base/text.rb +1 -1
- data/lib/dcc/base.rb +2 -1
- data/lib/dcc/builder/dsl.rb +1 -1
- data/lib/dcc/builder/session.rb +16 -14
- data/lib/dcc/builder.rb +3 -3
- data/lib/dcc/cli/cli.rb +152 -26
- data/lib/dcc/cli/formatters.rb +35 -7
- data/lib/dcc/cli.rb +1 -1
- data/lib/dcc/context_configuration.rb +2 -1
- data/lib/dcc/context_options.rb +4 -2
- data/lib/dcc/convert/csv.rb +27 -9
- data/lib/dcc/convert/html.rb +26 -110
- data/lib/dcc/convert/json.rb +10 -7
- data/lib/dcc/convert/liquid_filters.rb +58 -0
- data/lib/dcc/convert/result.rb +1 -1
- data/lib/dcc/convert/templates/report.liquid +250 -0
- data/lib/dcc/convert/yaml.rb +1 -1
- data/lib/dcc/convert.rb +1 -0
- data/lib/dcc/diff/change.rb +1 -1
- data/lib/dcc/diff/result.rb +8 -4
- data/lib/dcc/diff.rb +43 -11
- data/lib/dcc/error.rb +7 -0
- data/lib/dcc/extract/file.rb +3 -4
- data/lib/dcc/extract/formula/ast.rb +137 -0
- data/lib/dcc/extract/formula/evaluator.rb +357 -0
- data/lib/dcc/extract/formula/parser.rb +305 -0
- data/lib/dcc/extract/formula/quantity.rb +89 -0
- data/lib/dcc/extract/formula.rb +110 -0
- data/lib/dcc/extract/ring.rb +1 -1
- data/lib/dcc/extract.rb +1 -1
- data/lib/dcc/i18n/text_lookup.rb +8 -4
- data/lib/dcc/i18n.rb +1 -1
- data/lib/dcc/inspect/report.rb +51 -14
- data/lib/dcc/inspect.rb +1 -1
- data/lib/dcc/migrate/route.rb +44 -0
- data/lib/dcc/migrate/v2_to_v3.rb +445 -0
- data/lib/dcc/migrate.rb +130 -26
- data/lib/dcc/plugin/base.rb +64 -0
- data/lib/dcc/plugin/registry.rb +7 -2
- data/lib/dcc/plugin.rb +6 -2
- data/lib/dcc/quantity_format/formatter.rb +16 -10
- data/lib/dcc/quantity_format.rb +1 -1
- data/lib/dcc/quantity_math/complex.rb +252 -0
- data/lib/dcc/quantity_math/matrix.rb +217 -0
- data/lib/dcc/quantity_math/quantity.rb +1 -1
- data/lib/dcc/quantity_math/real.rb +6 -6
- data/lib/dcc/quantity_math.rb +31 -3
- data/lib/dcc/schema/version.rb +2 -2
- data/lib/dcc/server/app.html +282 -0
- data/lib/dcc/server/app.rb +171 -87
- data/lib/dcc/server/demo_cert.xml +244 -0
- data/lib/dcc/server/storage/entry.rb +1 -1
- data/lib/dcc/server/storage/memory.rb +3 -2
- data/lib/dcc/server/storage.rb +1 -1
- data/lib/dcc/server.rb +1 -1
- data/lib/dcc/si/base/complex.rb +1 -1
- data/lib/dcc/si/base/complex_list_xml_list.rb +1 -1
- data/lib/dcc/si/base/constant.rb +1 -1
- data/lib/dcc/si/base/coverage_interval.rb +36 -0
- data/lib/dcc/si/base/coverage_interval_mu.rb +1 -1
- data/lib/dcc/si/base/expanded_mu.rb +1 -1
- data/lib/dcc/si/base/expanded_unc.rb +34 -0
- data/lib/dcc/si/base/expanded_unc_xml_list.rb +3 -2
- data/lib/dcc/si/base/hybrid.rb +3 -2
- data/lib/dcc/si/base/measurement_uncertainty_univariate.rb +1 -1
- data/lib/dcc/si/base/real.rb +13 -3
- data/lib/dcc/si/base/real_list_xml_list.rb +5 -3
- data/lib/dcc/si/base/si_list.rb +3 -2
- data/lib/dcc/si/base/standard_mu.rb +1 -1
- data/lib/dcc/si/base.rb +5 -2
- data/lib/dcc/si/v1/coverage_interval.rb +8 -0
- data/lib/dcc/si/v1/expanded_unc.rb +1 -16
- data/lib/dcc/si/v1/measurement_uncertainty_univariate.rb +2 -1
- data/lib/dcc/si/v1.rb +5 -2
- data/lib/dcc/si/v2/coverage_interval.rb +8 -0
- data/lib/dcc/si/v2/coverage_interval_mu_xml_list.rb +4 -2
- data/lib/dcc/si/v2/expanded_mu_xml_list.rb +2 -1
- data/lib/dcc/si/v2/expanded_unc.rb +8 -0
- data/lib/dcc/si/v2/measurement_uncertainty_univariate.rb +2 -1
- data/lib/dcc/si/v2.rb +8 -3
- data/lib/dcc/signature/result.rb +2 -2
- data/lib/dcc/signature/signer.rb +31 -18
- data/lib/dcc/signature/verifier.rb +23 -21
- data/lib/dcc/signature.rb +1 -1
- data/lib/dcc/streaming/reader.rb +246 -0
- data/lib/dcc/streaming.rb +79 -0
- data/lib/dcc/transform/result.rb +1 -1
- data/lib/dcc/transform/xslt.rb +22 -12
- data/lib/dcc/transform.rb +5 -4
- data/lib/dcc/type/base64_binary.rb +5 -3
- data/lib/dcc/type/decimal_xml_list.rb +99 -13
- data/lib/dcc/type/iso_country_code.rb +3 -2
- data/lib/dcc/type/iso_language_code.rb +3 -2
- data/lib/dcc/type/schema_version.rb +3 -2
- data/lib/dcc/type/si_unit.rb +3 -2
- data/lib/dcc/type_guards.rb +3 -3
- data/lib/dcc/v2/calibration_laboratory.rb +2 -1
- data/lib/dcc/v2/condition.rb +22 -1
- data/lib/dcc/v2/configuration.rb +1 -1
- data/lib/dcc/v2/digital_calibration_certificate.rb +2 -1
- data/lib/dcc/v2/identification.rb +14 -1
- data/lib/dcc/v2/mathml.rb +8 -0
- data/lib/dcc/v2/measurement_meta_data_list.rb +2 -1
- data/lib/dcc/v2/quantity.rb +4 -2
- data/lib/dcc/v2.rb +4 -2
- data/lib/dcc/v3/calibration_laboratory.rb +2 -1
- data/lib/dcc/v3/configuration.rb +1 -1
- data/lib/dcc/v3/digital_calibration_certificate.rb +2 -1
- data/lib/dcc/v3/mathml.rb +8 -0
- data/lib/dcc/v3/measurement_meta_data_list.rb +2 -1
- data/lib/dcc/v3/quantity.rb +4 -2
- data/lib/dcc/v3.rb +12 -2
- data/lib/dcc/validate/business_rules.rb +23 -9
- data/lib/dcc/validate/issue.rb +2 -1
- data/lib/dcc/validate/result.rb +6 -4
- data/lib/dcc/validate/schematron/profile.rb +73 -18
- data/lib/dcc/validate/schematron/rule.rb +13 -3
- data/lib/dcc/validate/schematron/rules/administrative_data_completeness.rb +11 -4
- data/lib/dcc/validate/schematron/rules/base.rb +1 -2
- data/lib/dcc/validate/schematron/rules/date_range_check.rb +11 -5
- data/lib/dcc/validate/schematron/rules/id_refid_linking.rb +0 -3
- data/lib/dcc/validate/schematron/rules/influence_conditions_placement.rb +22 -12
- data/lib/dcc/validate/schematron/rules/iso_code_validation.rb +31 -14
- data/lib/dcc/validate/schematron/rules/language_code_dedup.rb +12 -5
- data/lib/dcc/validate/schematron/rules/non_si_declaration.rb +7 -4
- data/lib/dcc/validate/schematron/rules/release_format_check.rb +7 -4
- data/lib/dcc/validate/schematron/rules/schema_version_check.rb +13 -9
- data/lib/dcc/validate/schematron/rules/uncertainty_consistency.rb +39 -10
- data/lib/dcc/validate/schematron/rules/unit_format_check.rb +2 -3
- data/lib/dcc/validate/schematron/rules/used_methods_placement.rb +15 -10
- data/lib/dcc/validate/schematron/rules/used_software_placement.rb +15 -10
- data/lib/dcc/validate/schematron/rules/xml_list_spacing.rb +4 -3
- data/lib/dcc/validate/schematron/rules.rb +28 -14
- data/lib/dcc/validate/schematron.rb +1 -1
- data/lib/dcc/validate/xsd.rb +9 -3
- data/lib/dcc/validate.rb +1 -1
- data/lib/dcc/version.rb +1 -1
- data/lib/dcc/versioned_parser.rb +1 -1
- data/lib/dcc.rb +68 -10
- data/sample_dcc.xml +140 -0
- data/web/index.html +12 -0
- data/web/package-lock.json +1599 -0
- data/web/package.json +22 -0
- data/web/src/App.vue +349 -0
- data/web/src/lib/builder.ts +171 -0
- data/web/src/lib/dcc.ts +338 -0
- data/web/src/lib/units.json +5581 -0
- data/web/src/main.ts +5 -0
- data/web/src/style.css +27 -0
- data/web/tsconfig.json +15 -0
- data/web/vite.config.ts +14 -0
- metadata +148 -9
|
@@ -4,5 +4,6 @@ module Dcc::V2
|
|
|
4
4
|
class CalibrationLaboratory < CommonElements
|
|
5
5
|
include ::Dcc::Base::CalibrationLaboratory
|
|
6
6
|
end
|
|
7
|
-
Configuration.register_model(CalibrationLaboratory,
|
|
7
|
+
Configuration.register_model(CalibrationLaboratory,
|
|
8
|
+
id: :calibrationLaboratory)
|
|
8
9
|
end
|
data/lib/dcc/v2/condition.rb
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Dcc::V2
|
|
4
|
+
# v2 calls the influence condition's state element `state`; v3 renamed it to
|
|
5
|
+
# `status`, which the shared base module carries.
|
|
4
6
|
class Condition < CommonElements
|
|
5
|
-
|
|
7
|
+
attribute :id, :string
|
|
8
|
+
attribute :ref_id, :string
|
|
9
|
+
attribute :ref_type, :string
|
|
10
|
+
attribute :name, :text
|
|
11
|
+
attribute :description, :text
|
|
12
|
+
attribute :status, :string
|
|
13
|
+
attribute :data, :data, collection: true
|
|
14
|
+
|
|
15
|
+
xml do
|
|
16
|
+
namespace ::Dcc::Namespace::Dcc
|
|
17
|
+
element "influenceCondition"
|
|
18
|
+
ordered
|
|
19
|
+
map_attribute "id", to: :id
|
|
20
|
+
map_attribute "refId", to: :ref_id
|
|
21
|
+
map_attribute "refType", to: :ref_type
|
|
22
|
+
map_element "name", to: :name
|
|
23
|
+
map_element "description", to: :description
|
|
24
|
+
map_element "state", to: :status
|
|
25
|
+
map_element "data", to: :data
|
|
26
|
+
end
|
|
6
27
|
end
|
|
7
28
|
Configuration.register_model(Condition, id: :influenceCondition)
|
|
8
29
|
end
|
data/lib/dcc/v2/configuration.rb
CHANGED
|
@@ -4,5 +4,6 @@ module Dcc::V2
|
|
|
4
4
|
class DigitalCalibrationCertificate < CommonElements
|
|
5
5
|
include ::Dcc::Base::DigitalCalibrationCertificate
|
|
6
6
|
end
|
|
7
|
-
Configuration.register_model(DigitalCalibrationCertificate,
|
|
7
|
+
Configuration.register_model(DigitalCalibrationCertificate,
|
|
8
|
+
id: :digitalCalibrationCertificate)
|
|
8
9
|
end
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Dcc::V2
|
|
4
|
+
# v2 calls the identification's third child `description`; v3 renamed it to
|
|
5
|
+
# `name`, which the shared base module carries.
|
|
4
6
|
class Identification < CommonElements
|
|
5
|
-
|
|
7
|
+
attribute :issuer, :string
|
|
8
|
+
attribute :value, :string
|
|
9
|
+
attribute :description, :text
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
namespace ::Dcc::Namespace::Dcc
|
|
13
|
+
element "identification"
|
|
14
|
+
ordered
|
|
15
|
+
map_element "issuer", to: :issuer
|
|
16
|
+
map_element "value", to: :value
|
|
17
|
+
map_element "description", to: :description
|
|
18
|
+
end
|
|
6
19
|
end
|
|
7
20
|
Configuration.register_model(Identification, id: :identification)
|
|
8
21
|
end
|
|
@@ -4,5 +4,6 @@ module Dcc::V2
|
|
|
4
4
|
class MeasurementMetaDataList < CommonElements
|
|
5
5
|
include ::Dcc::Base::MeasurementMetaDataList
|
|
6
6
|
end
|
|
7
|
-
Configuration.register_model(MeasurementMetaDataList,
|
|
7
|
+
Configuration.register_model(MeasurementMetaDataList,
|
|
8
|
+
id: :measurementMetaData)
|
|
8
9
|
end
|
data/lib/dcc/v2/quantity.rb
CHANGED
|
@@ -19,8 +19,10 @@ module Dcc::V2
|
|
|
19
19
|
attribute :complex, ::Dcc::Si::V1::Complex, collection: true
|
|
20
20
|
attribute :constant, ::Dcc::Si::V1::Constant, collection: true
|
|
21
21
|
attribute :hybrid, ::Dcc::Si::V1::Hybrid, collection: true
|
|
22
|
-
attribute :real_list_xml_list, ::Dcc::Si::V1::RealListXmlList,
|
|
23
|
-
|
|
22
|
+
attribute :real_list_xml_list, ::Dcc::Si::V1::RealListXmlList,
|
|
23
|
+
collection: true
|
|
24
|
+
attribute :complex_list_xml_list, ::Dcc::Si::V1::ComplexListXmlList,
|
|
25
|
+
collection: true
|
|
24
26
|
attribute :list, ::Dcc::Si::V1::SiList, collection: true
|
|
25
27
|
|
|
26
28
|
xml do
|
data/lib/dcc/v2.rb
CHANGED
|
@@ -14,6 +14,7 @@ module Dcc
|
|
|
14
14
|
autoload :Text, "dcc/v2/text"
|
|
15
15
|
autoload :ByteData, "dcc/v2/byte_data"
|
|
16
16
|
autoload :Formula, "dcc/v2/formula"
|
|
17
|
+
autoload :Mathml, "dcc/v2/mathml"
|
|
17
18
|
autoload :RichContent, "dcc/v2/rich_content"
|
|
18
19
|
autoload :XmlBlob, "dcc/v2/xml_blob"
|
|
19
20
|
autoload :Comment, "dcc/v2/comment"
|
|
@@ -53,14 +54,15 @@ module Dcc
|
|
|
53
54
|
autoload :MeasurementResult, "dcc/v2/measurement_result"
|
|
54
55
|
autoload :MeasurementResultList, "dcc/v2/measurement_result_list"
|
|
55
56
|
autoload :AdministrativeData, "dcc/v2/administrative_data"
|
|
56
|
-
autoload :DigitalCalibrationCertificate,
|
|
57
|
+
autoload :DigitalCalibrationCertificate,
|
|
58
|
+
"dcc/v2/digital_calibration_certificate"
|
|
57
59
|
|
|
58
60
|
ROOT_ELEMENT_TAG = "digitalCalibrationCertificate"
|
|
59
61
|
|
|
60
62
|
extend ::Dcc::VersionedParser
|
|
61
63
|
|
|
62
64
|
ELEMENT_CLASSES = %i[
|
|
63
|
-
StringWithLang Text ByteData Formula RichContent XmlBlob Comment
|
|
65
|
+
StringWithLang Text ByteData Mathml Formula RichContent XmlBlob Comment
|
|
64
66
|
EquipmentClass Location Contact ContactNotStrict HashType
|
|
65
67
|
Identification Identifications Software SoftwareList
|
|
66
68
|
RefTypeDefinition RefTypeDefinitionList
|
|
@@ -4,5 +4,6 @@ module Dcc::V3
|
|
|
4
4
|
class CalibrationLaboratory < CommonElements
|
|
5
5
|
include ::Dcc::Base::CalibrationLaboratory
|
|
6
6
|
end
|
|
7
|
-
Configuration.register_model(CalibrationLaboratory,
|
|
7
|
+
Configuration.register_model(CalibrationLaboratory,
|
|
8
|
+
id: :calibrationLaboratory)
|
|
8
9
|
end
|
data/lib/dcc/v3/configuration.rb
CHANGED
|
@@ -4,5 +4,6 @@ module Dcc::V3
|
|
|
4
4
|
class DigitalCalibrationCertificate < CommonElements
|
|
5
5
|
include ::Dcc::Base::DigitalCalibrationCertificate
|
|
6
6
|
end
|
|
7
|
-
Configuration.register_model(DigitalCalibrationCertificate,
|
|
7
|
+
Configuration.register_model(DigitalCalibrationCertificate,
|
|
8
|
+
id: :digitalCalibrationCertificate)
|
|
8
9
|
end
|
|
@@ -4,5 +4,6 @@ module Dcc::V3
|
|
|
4
4
|
class MeasurementMetaDataList < CommonElements
|
|
5
5
|
include ::Dcc::Base::MeasurementMetaDataList
|
|
6
6
|
end
|
|
7
|
-
Configuration.register_model(MeasurementMetaDataList,
|
|
7
|
+
Configuration.register_model(MeasurementMetaDataList,
|
|
8
|
+
id: :measurementMetaData)
|
|
8
9
|
end
|
data/lib/dcc/v3/quantity.rb
CHANGED
|
@@ -19,8 +19,10 @@ module Dcc::V3
|
|
|
19
19
|
attribute :complex, ::Dcc::Si::V2::Complex, collection: true
|
|
20
20
|
attribute :constant, ::Dcc::Si::V2::Constant, collection: true
|
|
21
21
|
attribute :hybrid, ::Dcc::Si::V2::Hybrid, collection: true
|
|
22
|
-
attribute :real_list_xml_list, ::Dcc::Si::V2::RealListXmlList,
|
|
23
|
-
|
|
22
|
+
attribute :real_list_xml_list, ::Dcc::Si::V2::RealListXmlList,
|
|
23
|
+
collection: true
|
|
24
|
+
attribute :complex_list_xml_list, ::Dcc::Si::V2::ComplexListXmlList,
|
|
25
|
+
collection: true
|
|
24
26
|
attribute :list, ::Dcc::Si::V2::SiList, collection: true
|
|
25
27
|
|
|
26
28
|
xml do
|
data/lib/dcc/v3.rb
CHANGED
|
@@ -14,6 +14,7 @@ module Dcc
|
|
|
14
14
|
autoload :Text, "dcc/v3/text"
|
|
15
15
|
autoload :ByteData, "dcc/v3/byte_data"
|
|
16
16
|
autoload :Formula, "dcc/v3/formula"
|
|
17
|
+
autoload :Mathml, "dcc/v3/mathml"
|
|
17
18
|
autoload :RichContent, "dcc/v3/rich_content"
|
|
18
19
|
autoload :XmlBlob, "dcc/v3/xml_blob"
|
|
19
20
|
autoload :Comment, "dcc/v3/comment"
|
|
@@ -53,7 +54,8 @@ module Dcc
|
|
|
53
54
|
autoload :MeasurementResult, "dcc/v3/measurement_result"
|
|
54
55
|
autoload :MeasurementResultList, "dcc/v3/measurement_result_list"
|
|
55
56
|
autoload :AdministrativeData, "dcc/v3/administrative_data"
|
|
56
|
-
autoload :DigitalCalibrationCertificate,
|
|
57
|
+
autoload :DigitalCalibrationCertificate,
|
|
58
|
+
"dcc/v3/digital_calibration_certificate"
|
|
57
59
|
|
|
58
60
|
ROOT_ELEMENT_TAG = "digitalCalibrationCertificate"
|
|
59
61
|
|
|
@@ -63,7 +65,7 @@ module Dcc
|
|
|
63
65
|
# `Configuration.populate_context!` can register them. Iterating
|
|
64
66
|
# `constants` triggers each autoload lazily.
|
|
65
67
|
ELEMENT_CLASSES = %i[
|
|
66
|
-
StringWithLang Text ByteData Formula RichContent XmlBlob Comment
|
|
68
|
+
StringWithLang Text ByteData Mathml Formula RichContent XmlBlob Comment
|
|
67
69
|
EquipmentClass Location Contact ContactNotStrict HashType
|
|
68
70
|
Identification Identifications Software SoftwareList
|
|
69
71
|
RefTypeDefinition RefTypeDefinitionList
|
|
@@ -90,9 +92,17 @@ module Dcc
|
|
|
90
92
|
|
|
91
93
|
# Re-export D-SI v2 type registrations into the DCC v3 context. Uses
|
|
92
94
|
# only the public `register_model` API (no instance_variable access).
|
|
95
|
+
#
|
|
96
|
+
# Ids DCC already owns are skipped: `register_model` overwrites on
|
|
97
|
+
# duplicate, and both DCC and D-SI define a `list` element, so without this
|
|
98
|
+
# the D-SI one would displace `Dcc::V3::List` and every `dcc:list` would
|
|
99
|
+
# parse as an empty `si:list`.
|
|
93
100
|
def self.register_dsi_types!
|
|
94
101
|
::Dcc::Si::V2.load_all!
|
|
102
|
+
own_ids = Configuration.registered_model_ids
|
|
95
103
|
::Dcc::Si::V2::Configuration.registered_model_ids.each do |id|
|
|
104
|
+
next if own_ids.include?(id)
|
|
105
|
+
|
|
96
106
|
klass = ::Dcc::Si::V2::Configuration.registered_model_class(id)
|
|
97
107
|
Configuration.register_model(klass, id: id)
|
|
98
108
|
end
|
|
@@ -43,7 +43,9 @@ module Dcc
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def code
|
|
46
|
-
"dcc.business_rule.#{self.class.name.split('::').last.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(
|
|
46
|
+
"dcc.business_rule.#{self.class.name.split('::').last.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(
|
|
47
|
+
/([a-z\d])([A-Z])/, '\1_\2'
|
|
48
|
+
).downcase}"
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
# @param _dcc [Lutaml::Model::Serializable]
|
|
@@ -68,10 +70,12 @@ module Dcc
|
|
|
68
70
|
# Require exactly one respPerson with mainSigner = true.
|
|
69
71
|
class MainSignerSingle < Rule
|
|
70
72
|
def check_on(dcc)
|
|
71
|
-
return [] unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
73
|
+
return [] unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
74
|
+
:administrative_data)
|
|
72
75
|
|
|
73
76
|
admin = dcc.administrative_data
|
|
74
|
-
return [] unless admin && Dcc::TypeGuards.has_attribute?(admin,
|
|
77
|
+
return [] unless admin && Dcc::TypeGuards.has_attribute?(admin,
|
|
78
|
+
:resp_persons) && admin.resp_persons
|
|
75
79
|
|
|
76
80
|
resp_persons = Array(admin.resp_persons.resp_person)
|
|
77
81
|
main_signers = resp_persons.select { |p| Dcc::TypeGuards.has_attribute?(p, :main_signer) && p.main_signer }
|
|
@@ -89,15 +93,20 @@ module Dcc
|
|
|
89
93
|
# Require non-empty uniqueIdentifier.
|
|
90
94
|
class UniqueIdentifierPresent < Rule
|
|
91
95
|
def check_on(dcc)
|
|
92
|
-
return [] unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
96
|
+
return [] unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
97
|
+
:administrative_data)
|
|
93
98
|
|
|
94
99
|
core = dcc.administrative_data&.core_data
|
|
95
|
-
|
|
100
|
+
unless core
|
|
101
|
+
return [issue(severity: :error,
|
|
102
|
+
message: "coreData is missing")]
|
|
103
|
+
end
|
|
96
104
|
|
|
97
105
|
id = core.unique_identifier
|
|
98
106
|
return [] if id && !id.to_s.empty?
|
|
99
107
|
|
|
100
|
-
[issue(severity: :error,
|
|
108
|
+
[issue(severity: :error,
|
|
109
|
+
message: "uniqueIdentifier is missing or empty")]
|
|
101
110
|
end
|
|
102
111
|
end
|
|
103
112
|
|
|
@@ -108,14 +117,19 @@ module Dcc
|
|
|
108
117
|
# @param dcc [Lutaml::Model::Serializable]
|
|
109
118
|
# @return [Dcc::Validate::BusinessRules::Result]
|
|
110
119
|
def call(dcc)
|
|
111
|
-
issues = Registry.all.flat_map
|
|
120
|
+
issues = Registry.all.flat_map do |rule_class|
|
|
121
|
+
rule_class.new.check_on(dcc)
|
|
122
|
+
end
|
|
112
123
|
Result.new(
|
|
113
124
|
issues: issues,
|
|
114
|
-
schema_version: Dcc::TypeGuards.has_attribute?(dcc,
|
|
125
|
+
schema_version: if Dcc::TypeGuards.has_attribute?(dcc,
|
|
126
|
+
:schema_version)
|
|
127
|
+
dcc.schema_version.to_s
|
|
128
|
+
end,
|
|
115
129
|
source: "business_rule",
|
|
116
130
|
)
|
|
117
131
|
end
|
|
118
132
|
end
|
|
119
133
|
end
|
|
120
134
|
end
|
|
121
|
-
end
|
|
135
|
+
end
|
data/lib/dcc/validate/issue.rb
CHANGED
|
@@ -24,7 +24,8 @@ module Dcc
|
|
|
24
24
|
# @param column [Integer, nil] XML column number if known.
|
|
25
25
|
# @param path [String, nil] XPath / element path if known.
|
|
26
26
|
# @param source [String, nil] validator name (e.g. "xsd", "schematron").
|
|
27
|
-
def self.build(severity:, message:, code: nil, line: nil, column: nil,
|
|
27
|
+
def self.build(severity:, message:, code: nil, line: nil, column: nil,
|
|
28
|
+
path: nil, source: nil)
|
|
28
29
|
new(
|
|
29
30
|
severity: ::Dcc::Validate::Severity.normalize(severity),
|
|
30
31
|
message: message,
|
data/lib/dcc/validate/result.rb
CHANGED
|
@@ -58,12 +58,12 @@ module Dcc
|
|
|
58
58
|
|
|
59
59
|
def to_s
|
|
60
60
|
if ok?
|
|
61
|
-
"OK: no errors found#{
|
|
61
|
+
"OK: no errors found#{" (schemaVersion #{schema_version})" if schema_version}"
|
|
62
62
|
else
|
|
63
63
|
header = "#{errors.size} error(s), #{warnings.size} warning(s)"
|
|
64
64
|
header += " (schemaVersion #{schema_version})" if schema_version
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
errors.map(&:to_s).unshift(header).join("\n")
|
|
66
|
+
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
@@ -97,7 +97,9 @@ module Dcc
|
|
|
97
97
|
ok: ok?,
|
|
98
98
|
source: source,
|
|
99
99
|
schema_version: schema_version,
|
|
100
|
-
issues: issues.map
|
|
100
|
+
issues: issues.map do |i|
|
|
101
|
+
[i.severity.to_s, i.message, i.line, i.path]
|
|
102
|
+
end,
|
|
101
103
|
}.to_yaml
|
|
102
104
|
end
|
|
103
105
|
end
|
|
@@ -15,37 +15,92 @@ module Dcc
|
|
|
15
15
|
# result.ok? # => true
|
|
16
16
|
# result.issues.size # => 0
|
|
17
17
|
class Profile
|
|
18
|
+
# The rules shipped with the gem, in execution order.
|
|
19
|
+
DEFAULT_RULES = [
|
|
20
|
+
Rules::UsedMethodsPlacement,
|
|
21
|
+
Rules::UsedSoftwarePlacement,
|
|
22
|
+
Rules::InfluenceConditionsPlacement,
|
|
23
|
+
Rules::SchemaVersionCheck,
|
|
24
|
+
Rules::IdRefIdLinking,
|
|
25
|
+
Rules::IsoCodeValidation,
|
|
26
|
+
Rules::DateRangeCheck,
|
|
27
|
+
Rules::ReleaseFormatCheck,
|
|
28
|
+
Rules::UncertaintyConsistency,
|
|
29
|
+
Rules::UnitFormatCheck,
|
|
30
|
+
Rules::NonSiDeclaration,
|
|
31
|
+
Rules::LanguageCodeDedup,
|
|
32
|
+
Rules::XmlListSpacing,
|
|
33
|
+
].freeze
|
|
34
|
+
private_constant :DEFAULT_RULES
|
|
35
|
+
|
|
18
36
|
attr_reader :dcc, :rules
|
|
19
37
|
|
|
38
|
+
# Plugin validators are read here, not at class-definition time, so
|
|
39
|
+
# a plugin loaded after this class still takes effect. Frozen because
|
|
40
|
+
# `attr_reader :rules` hands the array straight to callers.
|
|
20
41
|
def initialize(dcc)
|
|
21
42
|
@dcc = dcc
|
|
22
|
-
@
|
|
23
|
-
|
|
24
|
-
Rules::UsedSoftwarePlacement,
|
|
25
|
-
Rules::InfluenceConditionsPlacement,
|
|
26
|
-
Rules::SchemaVersionCheck,
|
|
27
|
-
Rules::IdRefIdLinking,
|
|
28
|
-
Rules::IsoCodeValidation,
|
|
29
|
-
Rules::DateRangeCheck,
|
|
30
|
-
Rules::ReleaseFormatCheck,
|
|
31
|
-
Rules::UncertaintyConsistency,
|
|
32
|
-
Rules::UnitFormatCheck,
|
|
33
|
-
Rules::NonSiDeclaration,
|
|
34
|
-
Rules::LanguageCodeDedup,
|
|
35
|
-
Rules::XmlListSpacing,
|
|
36
|
-
]
|
|
43
|
+
@plugin_rules = ::Dcc::Plugin.all(:validators).freeze
|
|
44
|
+
@rules = (DEFAULT_RULES + @plugin_rules).freeze
|
|
37
45
|
end
|
|
38
46
|
|
|
39
47
|
# Run all rules and return a `Dcc::Validate::Result`.
|
|
48
|
+
#
|
|
49
|
+
# Built-in rules fail fast: a crash there is a bug in this gem. A
|
|
50
|
+
# plugin rule is third-party code, so its failure is contained and
|
|
51
|
+
# reported as an error issue naming the rule class — one broken
|
|
52
|
+
# plugin must not cost the caller every built-in finding.
|
|
40
53
|
def call
|
|
41
54
|
issues = []
|
|
42
55
|
rules.each do |rule_class|
|
|
43
|
-
issues.concat(
|
|
56
|
+
issues.concat(
|
|
57
|
+
if @plugin_rules.include?(rule_class)
|
|
58
|
+
run_plugin_rule(rule_class)
|
|
59
|
+
else
|
|
60
|
+
rule_class.new.check_on(dcc)
|
|
61
|
+
end,
|
|
62
|
+
)
|
|
44
63
|
end
|
|
45
64
|
|
|
46
65
|
::Dcc::Validate::Result.new(
|
|
47
66
|
issues: issues,
|
|
48
|
-
schema_version: Dcc::TypeGuards.has_attribute?(dcc,
|
|
67
|
+
schema_version: if Dcc::TypeGuards.has_attribute?(dcc,
|
|
68
|
+
:schema_version)
|
|
69
|
+
dcc.schema_version.to_s
|
|
70
|
+
end,
|
|
71
|
+
source: "schematron",
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
# Run one plugin-supplied rule with fault isolation. Instantiation
|
|
78
|
+
# and #check_on both run inside the rescue, and a non-Array return
|
|
79
|
+
# (nil included) is reported rather than passed to Array#concat.
|
|
80
|
+
#
|
|
81
|
+
# @param rule_class [Class]
|
|
82
|
+
# @return [Array<Dcc::Validate::Issue>]
|
|
83
|
+
def run_plugin_rule(rule_class)
|
|
84
|
+
result = rule_class.new.check_on(dcc)
|
|
85
|
+
return result if result.is_a?(::Array)
|
|
86
|
+
|
|
87
|
+
[plugin_failure_issue(
|
|
88
|
+
rule_class,
|
|
89
|
+
"returned #{result.inspect} instead of an Array of issues",
|
|
90
|
+
)]
|
|
91
|
+
rescue ::StandardError => e
|
|
92
|
+
[plugin_failure_issue(rule_class, "raised #{e.class}: #{e.message}")]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @param rule_class [Class]
|
|
96
|
+
# @param detail [String]
|
|
97
|
+
# @return [Dcc::Validate::Issue]
|
|
98
|
+
def plugin_failure_issue(rule_class, detail)
|
|
99
|
+
name = rule_class.name || rule_class.inspect
|
|
100
|
+
::Dcc::Validate::Issue.build(
|
|
101
|
+
severity: ::Dcc::Validate::Severity::ERROR,
|
|
102
|
+
message: "plugin validator #{name} #{detail}",
|
|
103
|
+
code: "dcc.schematron.plugin_failure",
|
|
49
104
|
source: "schematron",
|
|
50
105
|
)
|
|
51
106
|
end
|
|
@@ -61,4 +116,4 @@ module Dcc
|
|
|
61
116
|
end
|
|
62
117
|
end
|
|
63
118
|
end
|
|
64
|
-
end
|
|
119
|
+
end
|
|
@@ -13,9 +13,18 @@ module Dcc
|
|
|
13
13
|
::Dcc::Validate::Severity::ERROR
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# A plugin can register an anonymous rule class, whose `name` is nil.
|
|
17
|
+
# Falling back keeps one such rule from taking the whole run down and
|
|
18
|
+
# losing every issue the built-in rules already found.
|
|
19
|
+
#
|
|
16
20
|
# @return [String] rule code used in `Issue#code`.
|
|
17
21
|
def code
|
|
18
|
-
|
|
22
|
+
class_name = self.class.name
|
|
23
|
+
return "dcc.schematron.anonymous" unless class_name
|
|
24
|
+
|
|
25
|
+
"dcc.schematron.#{class_name.split('::').last.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(
|
|
26
|
+
/([a-z\d])([A-Z])/, '\1_\2'
|
|
27
|
+
).downcase}"
|
|
19
28
|
end
|
|
20
29
|
|
|
21
30
|
# @param dcc [Lutaml::Model::Serializable]
|
|
@@ -32,7 +41,8 @@ module Dcc
|
|
|
32
41
|
# Override in subclasses to traverse the model tree.
|
|
33
42
|
end
|
|
34
43
|
|
|
35
|
-
def issue(severity:, message:, line: nil, column: nil, path: nil,
|
|
44
|
+
def issue(severity:, message:, line: nil, column: nil, path: nil,
|
|
45
|
+
source: "schematron")
|
|
36
46
|
::Dcc::Validate::Issue.build(
|
|
37
47
|
severity: severity,
|
|
38
48
|
message: message,
|
|
@@ -46,4 +56,4 @@ module Dcc
|
|
|
46
56
|
end
|
|
47
57
|
end
|
|
48
58
|
end
|
|
49
|
-
end
|
|
59
|
+
end
|
|
@@ -19,13 +19,20 @@ module Dcc
|
|
|
19
19
|
|
|
20
20
|
def check_on(dcc)
|
|
21
21
|
issues = []
|
|
22
|
-
return issues unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
22
|
+
return issues unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
23
|
+
:administrative_data)
|
|
23
24
|
|
|
24
25
|
admin = dcc.administrative_data
|
|
25
|
-
|
|
26
|
+
unless admin
|
|
27
|
+
return [issue(severity: :error,
|
|
28
|
+
message: "administrativeData is missing")]
|
|
29
|
+
end
|
|
26
30
|
|
|
27
31
|
REQUIRED_SECTIONS.each do |attr, label|
|
|
28
|
-
value = Dcc::TypeGuards.has_attribute?(admin,
|
|
32
|
+
value = if Dcc::TypeGuards.has_attribute?(admin,
|
|
33
|
+
attr)
|
|
34
|
+
admin.public_send(attr)
|
|
35
|
+
end
|
|
29
36
|
next unless value.nil? || ((value.is_a?(::String) || value.is_a?(::Array)) && value.empty?)
|
|
30
37
|
|
|
31
38
|
issues << issue(
|
|
@@ -39,4 +46,4 @@ module Dcc
|
|
|
39
46
|
end
|
|
40
47
|
end
|
|
41
48
|
end
|
|
42
|
-
end
|
|
49
|
+
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
|
|
@@ -8,13 +7,20 @@ module Dcc
|
|
|
8
7
|
# Errors if `endPerformanceDate` precedes `beginPerformanceDate`.
|
|
9
8
|
class DateRangeCheck < Base
|
|
10
9
|
def check_on(dcc)
|
|
11
|
-
return [] unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
10
|
+
return [] unless Dcc::TypeGuards.has_attribute?(dcc,
|
|
11
|
+
:administrative_data)
|
|
12
12
|
|
|
13
13
|
core = safe_attr(dcc.administrative_data, :core_data)
|
|
14
14
|
return [] if core.nil?
|
|
15
15
|
|
|
16
|
-
begin_d = Dcc::TypeGuards.has_attribute?(core,
|
|
17
|
-
|
|
16
|
+
begin_d = if Dcc::TypeGuards.has_attribute?(core,
|
|
17
|
+
:begin_performance_date)
|
|
18
|
+
core.begin_performance_date
|
|
19
|
+
end
|
|
20
|
+
end_d = if Dcc::TypeGuards.has_attribute?(core,
|
|
21
|
+
:end_performance_date)
|
|
22
|
+
core.end_performance_date
|
|
23
|
+
end
|
|
18
24
|
|
|
19
25
|
return [] if begin_d.nil? || end_d.nil?
|
|
20
26
|
return [] unless end_d < begin_d
|
|
@@ -38,4 +44,4 @@ module Dcc
|
|
|
38
44
|
end
|
|
39
45
|
end
|
|
40
46
|
end
|
|
41
|
-
end
|
|
47
|
+
end
|