Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@ and this project adheres to https://semver.org/spec/v2.0.0.html[Semantic Version
* Performance memoization for hot paths
* Plugin system for custom validators and converters

=== Fixed
* `dcc:list` no longer parses as an empty `si:list`. The D-SI re-export was
overwriting the DCC `list` registration, so every list and the quantities
inside it were dropped on parse.
* `si:expandedUnc` and `si:coverageInterval` now survive a parse. Both are
members of the same `si:real` choice group and neither was mapped, so D-SI
v1 uncertainties were discarded.
* `dcc:mathml` now parses. It is a `dcc:xmlType` wrapper around `ml:math`,
not the `ml:math` element itself, so `formula.mathml` was always `nil`.
* Decimal XML lists serialize as one space-separated element again. Each
value was being written as its own element containing a Ruby array
literal, e.g. `<si:valueXMLList>[0.72e-1]</si:valueXMLList>`.
* `UncertaintyConsistency` accepts a single entry broadcast across every
value, and now checks `coverageFactorXMLList`, `coverageProbabilityXMLList`
and `distributionXMLList` rather than the uncertainty list alone.
* CSV export renders list values as plain decimals instead of `0.72e-1`.

=== Changed
* *Breaking:* `formula.mathml` returns a `Dcc::V2::Mathml` / `Dcc::V3::Mathml`
wrapper instead of an `Mml::V3::Math`. The MathML tree moves one level
down, so callers now read `formula.mathml.math`. This matches the XSD,
where `dcc:mathml` is a `dcc:xmlType` wrapper.

== [0.1.0] — 2026-07-22

=== Added
Expand Down
4 changes: 2 additions & 2 deletions lib/dcc/base/formula.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
module Dcc
module Base
# `dcc:formulaType` — formula expression. Contains `latex` string,
# `mathml` (a typed `Mml::V3::Math` model), or legacy `siunitx`.
# `mathml` (a `dcc:xmlType` wrapper around `ml:math`), or legacy `siunitx`.
module Formula
def self.included(klass)
klass.class_eval do
attribute :id, :string
attribute :ref_id, :string
attribute :ref_type, :string
attribute :latex, :string
attribute :mathml, ::Mml::V3::Math
attribute :mathml, :mathml
attribute :siunitx, :string

xml do
Expand Down
33 changes: 33 additions & 0 deletions lib/dcc/base/mathml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

require "mml"

module Dcc
module Base
# `dcc:mathml` — a `dcc:xmlType` wrapper carrying a single foreign-namespace
# child, which for a formula is `ml:math`. The MathML tree hangs below the
# wrapper rather than replacing it.
module Mathml
# rubocop:disable Metrics/MethodLength -- one lutaml mapping block,
# split the same way every sibling module in Dcc::Base is written.
def self.included(klass)
klass.class_eval do
attribute :id, :string
attribute :ref_id, :string
attribute :ref_type, :string
attribute :math, ::Mml::V3::Math

xml do
namespace ::Dcc::Namespace::Dcc
element "mathml"
map_attribute "id", to: :id
map_attribute "refId", to: :ref_id
map_attribute "refType", to: :ref_type
map_element "math", to: :math
end
end
end
# rubocop:enable Metrics/MethodLength
end
end
end
6 changes: 5 additions & 1 deletion lib/dcc/convert/csv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ def value_of(q)
return reals.first.value.to_s if reals.any?

lists = Array(q.real_list_xml_list)
return lists.first.value_xml_list.map(&:to_s).join("; ") if lists.any?
# Serialized rather than mapped over: BigDecimal#to_s renders 0.072
# as "0.72e-1", which is not what the document said.
if lists.any?
return ::Dcc::Type::DecimalXmlList.serialize(lists.first.value_xml_list)
end

""
end
Expand Down
19 changes: 13 additions & 6 deletions lib/dcc/diff.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "bigdecimal"
require "date"
require "lutaml/model"

module Dcc
Expand All @@ -12,6 +13,12 @@ module Diff
autoload :Result, "dcc/diff/result"
autoload :Change, "dcc/diff/change"

# Leaf types compared directly rather than descended into. Numeric covers
# BigDecimal and Date covers DateTime, so neither needs its own entry.
PRIMITIVE_TYPES = [
::String, ::Numeric, ::Symbol, ::Time, ::Date
].freeze
Comment thread
HassanAkbar marked this conversation as resolved.

class << self
# @param a [Lutaml::Model::Serializable]
# @param b [Lutaml::Model::Serializable]
Expand Down Expand Up @@ -68,13 +75,13 @@ def collect_differences(a, b, path, changes)
end

def primitive?(value)
return true if value.nil?
return true if value.is_a?(::String) || value.is_a?(::Numeric) || value.is_a?(::Symbol)
return true if [true, false].include?(value)
return true if value.is_a?(::Time) || value.is_a?(::Date) || value.is_a?(::DateTime)
return true if value.is_a?(::BigDecimal)
return true if value.nil? || [true, false].include?(value)
return false if value.is_a?(::Array)
return true if PRIMITIVE_TYPES.any? { |type| value.is_a?(type) }

false
# Anything we cannot descend into is compared with `==`, which covers
# value objects such as decimal XML lists.
!value.class.respond_to?(:attributes)
end

def summarize(node)
Expand Down
2 changes: 2 additions & 0 deletions lib/dcc/si/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ module Base
autoload :StandardMU, "dcc/si/base/standard_mu"
autoload :ExpandedMU, "dcc/si/base/expanded_mu"
autoload :CoverageIntervalMU, "dcc/si/base/coverage_interval_mu"
autoload :ExpandedUnc, "dcc/si/base/expanded_unc"
autoload :CoverageInterval, "dcc/si/base/coverage_interval"
autoload :ExpandedUncXmlList, "dcc/si/base/expanded_unc_xml_list"
autoload :MeasurementUncertaintyUnivariate,
"dcc/si/base/measurement_uncertainty_univariate"
Expand Down
36 changes: 36 additions & 0 deletions lib/dcc/si/base/coverage_interval.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

module Dcc
module Si
module Base
# `si:coverageIntervalType` — coverage interval stated directly on a real
# quantity, the sibling of `expandedUnc` in the same xs:choice. The v1
# form; v2 keeps it as a deprecated alternative.
module CoverageInterval
# rubocop:disable Metrics/MethodLength -- one lutaml mapping
# block, written the same way as every sibling D-SI module.
def self.included(klass)
klass.class_eval do
attribute :standard_unc, :string
attribute :interval_min, :string
attribute :interval_max, :string
attribute :coverage_probability, :string
attribute :distribution, :string

xml do
namespace ::Dcc::Namespace::Si
element "coverageInterval"
ordered
map_element "standardUnc", to: :standard_unc
map_element "intervalMin", to: :interval_min
map_element "intervalMax", to: :interval_max
map_element "coverageProbability", to: :coverage_probability
map_element "distribution", to: :distribution
end
end
end
# rubocop:enable Metrics/MethodLength
end
end
end
end
34 changes: 34 additions & 0 deletions lib/dcc/si/base/expanded_unc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

module Dcc
module Si
module Base
# `si:expandedUncType` — expanded uncertainty stated directly on a real
# quantity. The v1 form; v2 keeps it as a deprecated alternative to
# `measurementUncertaintyUnivariate`.
module ExpandedUnc
# rubocop:disable Metrics/MethodLength -- one lutaml mapping
# block, written the same way as every sibling D-SI module.
def self.included(klass)
klass.class_eval do
attribute :uncertainty, :string
attribute :coverage_factor, :string
attribute :coverage_probability, :string
attribute :distribution, :string

xml do
namespace ::Dcc::Namespace::Si
element "expandedUnc"
ordered
map_element "uncertainty", to: :uncertainty
map_element "coverageFactor", to: :coverage_factor
map_element "coverageProbability", to: :coverage_probability
map_element "distribution", to: :distribution
end
end
end
# rubocop:enable Metrics/MethodLength
end
end
end
end
8 changes: 8 additions & 0 deletions lib/dcc/si/base/real.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ module Base
# </si:real>
module Real
def self.included(klass)
# rubocop:disable Metrics/BlockLength -- one lutaml mapping block,
# as in the sibling D-SI modules already listed in the todo file.
klass.class_eval do
attribute :id, :string
attribute :ref_type, :string
Expand All @@ -27,6 +29,9 @@ def self.included(klass)
attribute :date_time, :date_time
attribute :measurement_uncertainty_univariate,
:measurementUncertaintyUnivariate
# Deprecated in v2, but the only uncertainty form v1 documents use.
attribute :expanded_unc, :expandedUnc
attribute :coverage_interval, :coverageInterval

xml do
namespace ::Dcc::Namespace::Si
Expand All @@ -41,8 +46,11 @@ def self.included(klass)
map_element "dateTime", to: :date_time
map_element "measurementUncertaintyUnivariate",
to: :measurement_uncertainty_univariate
map_element "expandedUnc", to: :expanded_unc
map_element "coverageInterval", to: :coverage_interval
end
end
# rubocop:enable Metrics/BlockLength
end
end
end
Expand Down
4 changes: 3 additions & 1 deletion lib/dcc/si/v1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module V1
autoload :ExpandedMU, "dcc/si/v1/expanded_mu"
autoload :CoverageIntervalMU, "dcc/si/v1/coverage_interval_mu"
autoload :ExpandedUnc, "dcc/si/v1/expanded_unc"
autoload :CoverageInterval, "dcc/si/v1/coverage_interval"
autoload :ExpandedUncXmlList, "dcc/si/v1/expanded_unc_xml_list"
autoload :MeasurementUncertaintyUnivariate,
"dcc/si/v1/measurement_uncertainty_univariate"
Expand All @@ -34,7 +35,8 @@ module V1
Real Complex Constant
RealListXmlList ComplexListXmlList Hybrid SiList
StandardMU ExpandedMU CoverageIntervalMU
ExpandedUnc ExpandedUncXmlList MeasurementUncertaintyUnivariate
ExpandedUnc CoverageInterval
ExpandedUncXmlList MeasurementUncertaintyUnivariate
].freeze

def self.load_all!
Expand Down
8 changes: 8 additions & 0 deletions lib/dcc/si/v1/coverage_interval.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

module Dcc::Si::V1
class CoverageInterval < CommonElements
include ::Dcc::Si::Base::CoverageInterval
end
Configuration.register_model(CoverageInterval, id: :coverageInterval)
end
17 changes: 1 addition & 16 deletions lib/dcc/si/v1/expanded_unc.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
# frozen_string_literal: true

module Dcc::Si::V1
# Deprecated v1 expandedUnc type — superseded by expandedMU in v2.
# Kept so old fixtures parse without losing data.
class ExpandedUnc < CommonElements
attribute :uncertainty, :string
attribute :coverage_factor, :string
attribute :coverage_probability, :string
attribute :distribution, :string

xml do
namespace ::Dcc::Namespace::Si
element "expandedUnc"
ordered
map_element "uncertainty", to: :uncertainty
map_element "coverageFactor", to: :coverage_factor
map_element "coverageProbability", to: :coverage_probability
map_element "distribution", to: :distribution
end
include ::Dcc::Si::Base::ExpandedUnc
end
Configuration.register_model(ExpandedUnc, id: :expandedUnc)
end
3 changes: 3 additions & 0 deletions lib/dcc/si/v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ module V2
autoload :CoverageIntervalMU, "dcc/si/v2/coverage_interval_mu"
autoload :CoverageIntervalMUXMLList,
"dcc/si/v2/coverage_interval_mu_xml_list"
autoload :ExpandedUnc, "dcc/si/v2/expanded_unc"
autoload :CoverageInterval, "dcc/si/v2/coverage_interval"
autoload :ExpandedUncXmlList, "dcc/si/v2/expanded_unc_xml_list"
autoload :MeasurementUncertaintyUnivariate,
"dcc/si/v2/measurement_uncertainty_univariate"
Expand All @@ -38,6 +40,7 @@ module V2
StandardMU StandardMUXMLList
ExpandedMU ExpandedMUXMLList
CoverageIntervalMU CoverageIntervalMUXMLList
ExpandedUnc CoverageInterval
ExpandedUncXmlList MeasurementUncertaintyUnivariate
].freeze

Expand Down
8 changes: 8 additions & 0 deletions lib/dcc/si/v2/coverage_interval.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

module Dcc::Si::V2
class CoverageInterval < CommonElements
include ::Dcc::Si::Base::CoverageInterval
end
Configuration.register_model(CoverageInterval, id: :coverageInterval)
end
8 changes: 8 additions & 0 deletions lib/dcc/si/v2/expanded_unc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

module Dcc::Si::V2
class ExpandedUnc < CommonElements
include ::Dcc::Si::Base::ExpandedUnc
end
Configuration.register_model(ExpandedUnc, id: :expandedUnc)
end
Loading
Loading