reqif 0.1.0 → 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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +7 -4
  3. data/.rubocop.yml +17 -6
  4. data/.rubocop_todo.yml +241 -0
  5. data/CLAUDE.md +73 -0
  6. data/Gemfile +5 -2
  7. data/README.adoc +61 -1
  8. data/lib/reqif/alternative_id.rb +2 -2
  9. data/lib/reqif/attribute_definition_boolean.rb +5 -4
  10. data/lib/reqif/attribute_definition_date.rb +5 -4
  11. data/lib/reqif/attribute_definition_enumeration.rb +5 -4
  12. data/lib/reqif/attribute_definition_integer.rb +5 -4
  13. data/lib/reqif/attribute_definition_real.rb +5 -4
  14. data/lib/reqif/attribute_definition_string.rb +5 -4
  15. data/lib/reqif/attribute_definition_xhtml.rb +5 -4
  16. data/lib/reqif/attribute_value_boolean.rb +3 -2
  17. data/lib/reqif/attribute_value_date.rb +4 -3
  18. data/lib/reqif/attribute_value_enumeration.rb +3 -2
  19. data/lib/reqif/attribute_value_integer.rb +4 -3
  20. data/lib/reqif/attribute_value_real.rb +4 -3
  21. data/lib/reqif/attribute_value_string.rb +3 -2
  22. data/lib/reqif/attribute_value_xhtml.rb +3 -2
  23. data/lib/reqif/children.rb +3 -2
  24. data/lib/reqif/core_content.rb +3 -2
  25. data/lib/reqif/datatype_definition_boolean.rb +5 -4
  26. data/lib/reqif/datatype_definition_date.rb +5 -4
  27. data/lib/reqif/datatype_definition_enumeration.rb +5 -4
  28. data/lib/reqif/datatype_definition_integer.rb +7 -6
  29. data/lib/reqif/datatype_definition_real.rb +7 -6
  30. data/lib/reqif/datatype_definition_string.rb +5 -4
  31. data/lib/reqif/datatype_definition_xhtml.rb +5 -4
  32. data/lib/reqif/datatypes.rb +23 -12
  33. data/lib/reqif/default_value.rb +4 -3
  34. data/lib/reqif/definition.rb +24 -16
  35. data/lib/reqif/doors/identifier.rb +15 -0
  36. data/lib/reqif/doors/module_definition.rb +23 -0
  37. data/lib/reqif/doors/namespace.rb +10 -0
  38. data/lib/reqif/doors/readonly_attributes.rb +48 -0
  39. data/lib/reqif/doors/rif_definition.rb +26 -0
  40. data/lib/reqif/doors/string_type.rb +12 -0
  41. data/lib/reqif/doors.rb +12 -0
  42. data/lib/reqif/editable_atts.rb +24 -16
  43. data/lib/reqif/embedded_value.rb +4 -3
  44. data/lib/reqif/enum_value.rb +4 -4
  45. data/lib/reqif/high_precision_date_time.rb +52 -0
  46. data/lib/reqif/namespace.rb +16 -0
  47. data/lib/reqif/object.rb +3 -3
  48. data/lib/reqif/properties.rb +2 -2
  49. data/lib/reqif/relation_group.rb +5 -4
  50. data/lib/reqif/relation_group_type.rb +5 -4
  51. data/lib/reqif/req_if.rb +7 -2
  52. data/lib/reqif/req_if_content.rb +3 -2
  53. data/lib/reqif/req_if_header.rb +4 -5
  54. data/lib/reqif/req_if_tool_extension.rb +48 -2
  55. data/lib/reqif/reqif_float.rb +97 -0
  56. data/lib/reqif/reqif_integer.rb +36 -0
  57. data/lib/reqif/source.rb +3 -3
  58. data/lib/reqif/source_specification.rb +3 -3
  59. data/lib/reqif/spec_attributes.rb +25 -13
  60. data/lib/reqif/spec_hierarchy.rb +5 -4
  61. data/lib/reqif/spec_object.rb +5 -4
  62. data/lib/reqif/spec_object_type.rb +5 -4
  63. data/lib/reqif/spec_objects.rb +3 -2
  64. data/lib/reqif/spec_relation.rb +5 -4
  65. data/lib/reqif/spec_relation_groups.rb +2 -2
  66. data/lib/reqif/spec_relation_type.rb +5 -4
  67. data/lib/reqif/spec_relations.rb +3 -3
  68. data/lib/reqif/spec_types.rb +3 -2
  69. data/lib/reqif/specification.rb +5 -4
  70. data/lib/reqif/specification_type.rb +5 -4
  71. data/lib/reqif/specifications.rb +3 -2
  72. data/lib/reqif/specified_values.rb +2 -2
  73. data/lib/reqif/string_type.rb +7 -0
  74. data/lib/reqif/target.rb +3 -3
  75. data/lib/reqif/target_specification.rb +3 -3
  76. data/lib/reqif/the_header.rb +3 -2
  77. data/lib/reqif/tool_extensions.rb +2 -2
  78. data/lib/reqif/type.rb +28 -20
  79. data/lib/reqif/values.rb +8 -5
  80. data/lib/reqif/version.rb +1 -1
  81. data/lib/reqif/xhtml/div.rb +18 -0
  82. data/lib/reqif/xhtml/namespace.rb +10 -0
  83. data/lib/reqif/xhtml/p.rb +18 -0
  84. data/lib/reqif/xhtml/span.rb +18 -0
  85. data/lib/reqif/xhtml.rb +12 -0
  86. data/lib/reqif/xhtml_content.rb +182 -2
  87. data/lib/reqif.rb +70 -14
  88. data/references/driver.xsd +270 -270
  89. data/references/reqif.xsd +892 -892
  90. data/reqif.gemspec +4 -3
  91. data/spec/fixtures/antcc_MAG8000-LTE-FeatureSpecReqBL4.reqif +4299 -0
  92. data/spec/fixtures/ea_example.reqif.xml +236 -0
  93. data/spec/fixtures/eclipse_capella_Sample.xml +177 -0
  94. data/spec/fixtures/eclipse_capella_Sample1.xml +239 -0
  95. data/spec/fixtures/eclipse_capella_Sample2.xml +239 -0
  96. data/spec/fixtures/eclipse_capella_Sample3.xml +304 -0
  97. data/spec/fixtures/eclipse_capella_model1.xml +4080 -0
  98. data/spec/fixtures/eclipse_rmf_sample.reqif +96 -0
  99. data/spec/fixtures/eclipse_rmf_specRelationTest.reqif +110 -0
  100. data/spec/fixtures/polarion_export.xml +70 -0
  101. data/spec/fixtures/strictdoc_01_minimal_reqif_sample.reqif +4 -0
  102. data/spec/fixtures/strictdoc_02_read_reqif_input.reqif +3996 -0
  103. data/spec/fixtures/strictdoc_04_convert_reqif_to_json_sample1_polarion.reqif +197 -0
  104. data/spec/fixtures/strictdoc_04_convert_reqif_to_json_sample2_sdoc.reqif +451 -0
  105. data/spec/fixtures/strictdoc_04_convert_reqif_to_json_sample3_eclipse_rmf.reqif +334 -0
  106. data/spec/fixtures/strictdoc_04_convert_reqif_to_json_sample_polarion_reqifz.reqifz +0 -0
  107. data/spec/reqif/data_types_spec.rb +29 -0
  108. data/spec/reqif/polarion_export_spec.rb +22 -0
  109. data/spec/reqif/req_if_header_spec.rb +31 -0
  110. data/spec/reqif/req_if_spec.rb +43 -0
  111. data/spec/reqif/spec_objects_spec.rb +35 -0
  112. data/spec/reqif/spec_relations_spec.rb +33 -0
  113. data/spec/reqif/spec_types_spec.rb +40 -0
  114. data/spec/reqif/specifications_spec.rb +35 -0
  115. data/spec/reqif/tool_extension_spec.rb +27 -0
  116. data/spec/reqif_spec.rb +56 -0
  117. data/spec/spec_helper.rb +70 -0
  118. metadata +58 -11
@@ -4,16 +4,16 @@ module Reqif
4
4
  class EnumValue < Lutaml::Model::Serializable
5
5
  attribute :desc, :string
6
6
  attribute :identifier, :string
7
- attribute :last_change, :time
7
+ attribute :last_change, HighPrecisionDateTime
8
8
  attribute :long_name, :string
9
9
  attribute :alternative_id, AlternativeId
10
10
  attribute :properties, Properties
11
11
 
12
12
  xml do
13
- root "ENUM-VALUE"
14
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
13
+ element "ENUM-VALUE"
14
+ namespace Namespace
15
15
 
16
- map_attribute "DESC", to: :desc
16
+ map_attribute "DESC", to: :desc, render_empty: true
17
17
  map_attribute "IDENTIFIER", to: :identifier
18
18
  map_attribute "LAST-CHANGE", to: :last_change
19
19
  map_attribute "LONG-NAME", to: :long_name
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model/type/date_time"
4
+
5
+ module Reqif
6
+ # High precision DateTime type that preserves fractional seconds precision
7
+ class HighPrecisionDateTime < Lutaml::Model::Type::DateTime
8
+ attr_accessor :precision, :has_explicit_timezone
9
+
10
+ def initialize(value = nil)
11
+ super
12
+ @precision = 0
13
+ end
14
+
15
+ # The format looks like this `2012-04-07T01:51:37.112+02:00`
16
+ # or this `2021-07-01T01:12:06.749Z`
17
+ def self.from_xml(xml_string)
18
+ new(::DateTime.parse(xml_string)).tap do |date_time|
19
+ date_time.precision = extract_precision(xml_string)
20
+ date_time.has_explicit_timezone = xml_string.match?(/[Zz]|[+-]\d{2}:\d{2}$/)
21
+ end
22
+ end
23
+
24
+ # Extract the precision of the milliseconds from the XML string
25
+ def self.extract_precision(xml_string)
26
+ if xml_string.include?(".")
27
+ milliseconds_part = xml_string.split(".").last.split(/Z|\+|-/).first
28
+ milliseconds_part.length
29
+ else
30
+ 0
31
+ end
32
+ end
33
+
34
+ def to_xml
35
+ base = "%Y-%m-%dT%H:%M:%S"
36
+ pattern = precision.positive? ? "#{base}.%#{precision}N" : base
37
+ if has_explicit_timezone
38
+ value.offset.zero? ? value.strftime("#{pattern}Z") : value.strftime("#{pattern}%:z")
39
+ else
40
+ value.strftime(pattern)
41
+ end
42
+ end
43
+
44
+ def iso8601(precision = nil)
45
+ if precision.nil? || precision.zero?
46
+ value.iso8601
47
+ else
48
+ value.strftime("%Y-%m-%dT%H:%M:%S.%#{precision}N%z")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/xml/namespace"
4
+
5
+ module Reqif
6
+ # Namespace class for ReqIF XML elements.
7
+ # Supports alias URIs for backwards compatibility with different ReqIF versions.
8
+ # ReqIF 1.1 uses http://www.omg.org/spec/ReqIF/20110401/reqif.xsd
9
+ # Some older tools (e.g., Eclipse RMF) used http://www.omg.org/spec/ReqIF/20101201
10
+ class Namespace < Lutaml::Xml::Namespace
11
+ uri "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"
12
+ uri_aliases "http://www.omg.org/spec/ReqIF/20101201"
13
+ element_form_default :qualified
14
+ attribute_form_default :qualified
15
+ end
16
+ end
data/lib/reqif/object.rb CHANGED
@@ -2,11 +2,11 @@ require "lutaml/model"
2
2
 
3
3
  module Reqif
4
4
  class Object < Lutaml::Model::Serializable
5
- attribute :spec_object_ref, :string
5
+ attribute :spec_object_ref, StringType
6
6
 
7
7
  xml do
8
- root "OBJECT"
9
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
8
+ element "OBJECT"
9
+ namespace Namespace
10
10
 
11
11
  map_element "SPEC-OBJECT-REF", to: :spec_object_ref
12
12
  end
@@ -5,8 +5,8 @@ module Reqif
5
5
  attribute :embedded_value, EmbeddedValue
6
6
 
7
7
  xml do
8
- root "PROPERTIES"
9
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
8
+ element "PROPERTIES"
9
+ namespace Namespace
10
10
 
11
11
  map_element "EMBEDDED-VALUE", to: :embedded_value
12
12
  end
@@ -4,7 +4,7 @@ module Reqif
4
4
  class RelationGroup < Lutaml::Model::Serializable
5
5
  attribute :desc, :string
6
6
  attribute :identifier, :string
7
- attribute :last_change, :time
7
+ attribute :last_change, HighPrecisionDateTime
8
8
  attribute :long_name, :string
9
9
  attribute :alternative_id, AlternativeId
10
10
  attribute :source_specification, SourceSpecification
@@ -13,10 +13,11 @@ module Reqif
13
13
  attribute :type, Type
14
14
 
15
15
  xml do
16
- root "RELATION-GROUP"
17
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
16
+ element "RELATION-GROUP"
17
+ namespace Namespace
18
+ ordered
18
19
 
19
- map_attribute "DESC", to: :desc
20
+ map_attribute "DESC", to: :desc, render_empty: true
20
21
  map_attribute "IDENTIFIER", to: :identifier
21
22
  map_attribute "LAST-CHANGE", to: :last_change
22
23
  map_attribute "LONG-NAME", to: :long_name
@@ -4,16 +4,17 @@ module Reqif
4
4
  class RelationGroupType < Lutaml::Model::Serializable
5
5
  attribute :desc, :string
6
6
  attribute :identifier, :string
7
- attribute :last_change, :time
7
+ attribute :last_change, HighPrecisionDateTime
8
8
  attribute :long_name, :string
9
9
  attribute :alternative_id, AlternativeId
10
10
  attribute :spec_attributes, SpecAttributes
11
11
 
12
12
  xml do
13
- root "RELATION-GROUP-TYPE"
14
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
13
+ element "RELATION-GROUP-TYPE"
14
+ namespace Namespace
15
+ ordered
15
16
 
16
- map_attribute "DESC", to: :desc
17
+ map_attribute "DESC", to: :desc, render_empty: true
17
18
  map_attribute "IDENTIFIER", to: :identifier
18
19
  map_attribute "LAST-CHANGE", to: :last_change
19
20
  map_attribute "LONG-NAME", to: :long_name
data/lib/reqif/req_if.rb CHANGED
@@ -1,15 +1,20 @@
1
1
  require "lutaml/model"
2
+ require "hyperlang"
2
3
 
3
4
  module Reqif
4
5
  class ReqIf < Lutaml::Model::Serializable
5
6
  attribute :the_header, TheHeader
6
7
  attribute :core_content, CoreContent
7
8
  attribute :tool_extensions, ToolExtensions
9
+ attribute :lang, Lutaml::Xml::W3c::XmlLangType
8
10
 
9
11
  xml do
10
- root "REQ-IF"
11
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
12
+ element "REQ-IF"
13
+ namespace Namespace
14
+ namespace_scope [Xhtml::Namespace]
15
+ ordered
12
16
 
17
+ map_attribute "lang", to: :lang
13
18
  map_element "THE-HEADER", to: :the_header
14
19
  map_element "CORE-CONTENT", to: :core_content
15
20
  map_element "TOOL-EXTENSIONS", to: :tool_extensions
@@ -10,8 +10,9 @@ module Reqif
10
10
  attribute :spec_relation_groups, SpecRelationGroups
11
11
 
12
12
  xml do
13
- root "REQ-IF-CONTENT"
14
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
13
+ element "REQ-IF-CONTENT"
14
+ namespace Namespace
15
+ ordered
15
16
 
16
17
  map_element "DATATYPES", to: :datatypes
17
18
  map_element "SPEC-TYPES", to: :spec_types
@@ -1,10 +1,8 @@
1
- require "lutaml/model"
2
-
3
1
  module Reqif
4
2
  class ReqIfHeader < Lutaml::Model::Serializable
5
3
  attribute :identifier, :string
6
4
  attribute :comment, :string
7
- attribute :creation_time, :time
5
+ attribute :creation_time, HighPrecisionDateTime
8
6
  attribute :repository_id, :string
9
7
  attribute :req_if_tool_id, :string
10
8
  attribute :req_if_version, :string
@@ -12,8 +10,9 @@ module Reqif
12
10
  attribute :title, :string
13
11
 
14
12
  xml do
15
- root "REQ-IF-HEADER"
16
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
13
+ element "REQ-IF-HEADER"
14
+ namespace Namespace
15
+ ordered
17
16
 
18
17
  map_attribute "IDENTIFIER", to: :identifier
19
18
  map_element "COMMENT", to: :comment
@@ -2,9 +2,55 @@ require "lutaml/model"
2
2
 
3
3
  module Reqif
4
4
  class ReqIfToolExtension < Lutaml::Model::Serializable
5
+ # <DOORS-RIF-DEFINITION░xmlns="http://www.ibm.com/rdm/doors/REQIF/xmlns/1.0">
6
+ # <IDENTIFIER>_ae71eb64-2aa6-4780-9212-bda594614a7f</IDENTIFIER>
7
+ # <MODULE-DEFINITION>
8
+ # <DDC-MODE>DDC_FULL_MODULE</DDC-MODE>
9
+ # <SPECIFICATION-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">_3166b6de-d4b9-4334-a13f-a55792546604</SPECIFICATION-REF>
10
+ # </MODULE-DEFINITION>
11
+ # </DOORS-RIF-DEFINITION>
12
+
13
+ # <READONLY-ATTRIBUTES░xmlns="http://www.ibm.com/rdm/doors/REQIF/xmlns/1.0">
14
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-0d13686b-83c4-487b-9bcc-2f11a673c97a</ATTRIBUTE-DEFINITION-STRING-REF>
15
+
16
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-48ed4896-28e9-492a-a45a-ca3716a64632</ATTRIBUTE-DEFINITION-STRING-REF>
17
+
18
+ # <ATTRIBUTE-DEFINITION-DATE-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-b5ff951b-70fc-440f-b775-cda530e97083</ATTRIBUTE-DEFINITION-DATE-REF>
19
+
20
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-81da08a0-6257-488b-b373-04d59395c81a</ATTRIBUTE-DEFINITION-STRING-REF>
21
+
22
+ # <ATTRIBUTE-DEFINITION-XHTML-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-0c2fc6c9-50e9-43ae-970b-c04ab506d834</ATTRIBUTE-DEFINITION-XHTML-REF>
23
+
24
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-f0d39171-054d-43e9-aec3-810b47c32334</ATTRIBUTE-DEFINITION-STRING-REF>
25
+
26
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-34c59c32-81d4-43ef-99be-a445358cd4bd</ATTRIBUTE-DEFINITION-STRING-REF>
27
+
28
+ # <ATTRIBUTE-DEFINITION-DATE-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-d683201b-4545-4afc-beee-401855fa2ded</ATTRIBUTE-DEFINITION-DATE-REF>
29
+
30
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-baad7651-7ec7-4694-8913-68daa9927781</ATTRIBUTE-DEFINITION-STRING-REF>
31
+
32
+ # <ATTRIBUTE-DEFINITION-XHTML-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-ee42329b-d592-44fb-91d2-469a9a9b9dce</ATTRIBUTE-DEFINITION-XHTML-REF>
33
+
34
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-47a379f0-441b-4df1-bbd8-a4281b890c26</ATTRIBUTE-DEFINITION-STRING-REF>
35
+
36
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-5c6c023c-8ace-4f68-807b-80190ba90552</ATTRIBUTE-DEFINITION-STRING-REF>
37
+
38
+ # <ATTRIBUTE-DEFINITION-DATE-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-6b83e957-ff2c-4de6-8bf8-4d2549d0d7bc</ATTRIBUTE-DEFINITION-DATE-REF>
39
+
40
+ # <ATTRIBUTE-DEFINITION-STRING-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-a8329820-0ccd-4ebf-8701-a2fd599dc463</ATTRIBUTE-DEFINITION-STRING-REF>
41
+
42
+ # <ATTRIBUTE-DEFINITION-XHTML-REF░xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd">rmf-012fb471-e36e-4785-91e6-fdb754ad3613</ATTRIBUTE-DEFINITION-XHTML-REF>
43
+ # </READONLY-ATTRIBUTES>
44
+
45
+ attribute :doors_rif_definition, ::Reqif::Doors::RifDefinition
46
+ attribute :readonly_attributes, ::Reqif::Doors::ReadonlyAttributes
47
+
5
48
  xml do
6
- root "REQ-IF-TOOL-EXTENSION"
7
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
49
+ element "REQ-IF-TOOL-EXTENSION"
50
+ namespace Namespace
51
+
52
+ map_element "DOORS-RIF-DEFINITION", to: :doors_rif_definition
53
+ map_element "READONLY-ATTRIBUTES", to: :readonly_attributes
8
54
  end
9
55
  end
10
56
  end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bigdecimal"
4
+ require "lutaml/model/type/float"
5
+
6
+ module Reqif
7
+ # Custom Float type that handles ReqIF float serialization.
8
+ # Preserves decimal notation for simple values and uses scientific
9
+ # notation only when necessary (very large/small numbers).
10
+ class ReqifFloat < Lutaml::Model::Type::Float
11
+ # Format a float value for ReqIF.
12
+ # Uses decimal notation for values that can be represented cleanly,
13
+ # otherwise uses scientific notation with uppercase E.
14
+ #
15
+ # @param f [Float] The float value
16
+ # @return [String] ReqIF formatted string
17
+ def self.reqif_format(float_value)
18
+ # Try to represent as a clean decimal first
19
+ decimal_str = format_float_as_decimal(float_value)
20
+ return decimal_str if decimal_str
21
+
22
+ # Fall back to scientific notation
23
+ format_scientific(float_value)
24
+ end
25
+
26
+ # Format as decimal if it can be done cleanly
27
+ def self.format_float_as_decimal(float_value)
28
+ # Use a reasonable precision to avoid floating point artifacts
29
+ # Check if the value can be represented cleanly in decimal
30
+ decimal_str = format("%.10g", float_value)
31
+
32
+ # Skip if it's in scientific notation (contains 'e' or 'E')
33
+ return nil if decimal_str.include?("e") || decimal_str.include?("E")
34
+
35
+ # Verify round-trip: parse back and check if we get the same value
36
+ parsed = BigDecimal(decimal_str).to_f
37
+ return decimal_str if parsed == float_value
38
+
39
+ # Try with higher precision
40
+ decimal_str = format("%.15g", float_value)
41
+ return nil if decimal_str.include?("e") || decimal_str.include?("E")
42
+
43
+ parsed = BigDecimal(decimal_str).to_f
44
+ return decimal_str if parsed == float_value
45
+
46
+ nil # Couldn't represent cleanly
47
+ end
48
+
49
+ # Format in scientific notation
50
+ def self.format_scientific(float_value)
51
+ formatted = format("%.15e", float_value).upcase
52
+ mantissa, exp = formatted.split("E")
53
+
54
+ # Strip trailing zeros from mantissa
55
+ mantissa = mantissa.sub(/\.?0+$/, "")
56
+ mantissa = "0" if mantissa.empty?
57
+ # Remove decimal point if it becomes trailing (e.g. "1.")
58
+ mantissa = mantissa.chomp(".")
59
+
60
+ # Handle exponent sign and strip leading zeros
61
+ sign = exp.start_with?("-") ? "-" : ""
62
+ digits = exp.sub(/^[+-]/, "").sub(/\A0+/, "")
63
+ digits = "0" if digits.empty?
64
+
65
+ "#{mantissa}E#{sign}#{digits}"
66
+ end
67
+
68
+ def self.cast(value, options = {})
69
+ return nil if value.nil?
70
+
71
+ unless options.equal?(EMPTY_OPTIONS)
72
+ Lutaml::Model::Services::Type::Validator::Number.validate!(value,
73
+ options)
74
+ end
75
+
76
+ case value
77
+ when String then BigDecimal(value).to_f
78
+ when Float then value
79
+ when BigDecimal then value.to_f
80
+ else Float(value.to_s)
81
+ end
82
+ end
83
+
84
+ def self.to_xml(value)
85
+ return nil if value.nil?
86
+
87
+ result = cast(value)
88
+ return nil if result.nil?
89
+
90
+ reqif_format(result)
91
+ end
92
+
93
+ def to_xml
94
+ self.class.to_xml(value)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bigdecimal"
4
+ require "lutaml/model/type/decimal"
5
+
6
+ module Reqif
7
+ # Custom Integer type using BigDecimal internally to support
8
+ # arbitrary precision integers beyond Ruby's native 64-bit range.
9
+ # Serializes without a decimal point for ReqIF compatibility.
10
+ class ReqifInteger < Lutaml::Model::Type::Decimal
11
+ def self.cast(value, options = {})
12
+ return nil if value.nil?
13
+
14
+ result = super
15
+ return nil if result.nil?
16
+
17
+ result
18
+ end
19
+
20
+ # Serialize to XML as a plain integer (no decimal point, no fractional part).
21
+ # Uses BigDecimal#to_i to strip any fractional part, ensuring output
22
+ # matches ReqIF's integer format.
23
+ def self.to_xml(value)
24
+ return nil if value.nil?
25
+
26
+ result = cast(value)
27
+ return nil if result.nil?
28
+
29
+ result.to_i.to_s
30
+ end
31
+
32
+ def to_xml
33
+ self.class.to_xml(value)
34
+ end
35
+ end
36
+ end
data/lib/reqif/source.rb CHANGED
@@ -2,11 +2,11 @@ require "lutaml/model"
2
2
 
3
3
  module Reqif
4
4
  class Source < Lutaml::Model::Serializable
5
- attribute :spec_object_ref, :string
5
+ attribute :spec_object_ref, StringType
6
6
 
7
7
  xml do
8
- root "SOURCE"
9
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
8
+ element "SOURCE"
9
+ namespace Namespace
10
10
 
11
11
  map_element "SPEC-OBJECT-REF", to: :spec_object_ref
12
12
  end
@@ -2,11 +2,11 @@ require "lutaml/model"
2
2
 
3
3
  module Reqif
4
4
  class SourceSpecification < Lutaml::Model::Serializable
5
- attribute :specification_ref, :string
5
+ attribute :specification_ref, StringType
6
6
 
7
7
  xml do
8
- root "SOURCE-SPECIFICATION"
9
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
8
+ element "SOURCE-SPECIFICATION"
9
+ namespace Namespace
10
10
 
11
11
  map_element "SPECIFICATION-REF", to: :specification_ref
12
12
  end
@@ -2,24 +2,36 @@ require "lutaml/model"
2
2
 
3
3
  module Reqif
4
4
  class SpecAttributes < Lutaml::Model::Serializable
5
- attribute :attribute_definition_boolean, AttributeDefinitionBoolean, collection: true
6
- attribute :attribute_definition_date, AttributeDefinitionDate, collection: true
7
- attribute :attribute_definition_enumeration, AttributeDefinitionEnumeration, collection: true
8
- attribute :attribute_definition_integer, AttributeDefinitionInteger, collection: true
9
- attribute :attribute_definition_real, AttributeDefinitionReal, collection: true
10
- attribute :attribute_definition_string, AttributeDefinitionString, collection: true
11
- attribute :attribute_definition_xhtml, AttributeDefinitionXhtml, collection: true
5
+ attribute :attribute_definition_boolean, AttributeDefinitionBoolean,
6
+ collection: true
7
+ attribute :attribute_definition_date, AttributeDefinitionDate,
8
+ collection: true
9
+ attribute :attribute_definition_enumeration,
10
+ AttributeDefinitionEnumeration, collection: true
11
+ attribute :attribute_definition_integer, AttributeDefinitionInteger,
12
+ collection: true
13
+ attribute :attribute_definition_real, AttributeDefinitionReal,
14
+ collection: true
15
+ attribute :attribute_definition_string, AttributeDefinitionString,
16
+ collection: true
17
+ attribute :attribute_definition_xhtml, AttributeDefinitionXhtml,
18
+ collection: true
12
19
 
13
20
  xml do
14
- root "SPEC-ATTRIBUTES"
15
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
21
+ element "SPEC-ATTRIBUTES"
22
+ namespace Namespace
23
+ ordered
16
24
 
17
- map_element "ATTRIBUTE-DEFINITION-BOOLEAN", to: :attribute_definition_boolean
25
+ map_element "ATTRIBUTE-DEFINITION-BOOLEAN",
26
+ to: :attribute_definition_boolean
18
27
  map_element "ATTRIBUTE-DEFINITION-DATE", to: :attribute_definition_date
19
- map_element "ATTRIBUTE-DEFINITION-ENUMERATION", to: :attribute_definition_enumeration
20
- map_element "ATTRIBUTE-DEFINITION-INTEGER", to: :attribute_definition_integer
28
+ map_element "ATTRIBUTE-DEFINITION-ENUMERATION",
29
+ to: :attribute_definition_enumeration
30
+ map_element "ATTRIBUTE-DEFINITION-INTEGER",
31
+ to: :attribute_definition_integer
21
32
  map_element "ATTRIBUTE-DEFINITION-REAL", to: :attribute_definition_real
22
- map_element "ATTRIBUTE-DEFINITION-STRING", to: :attribute_definition_string
33
+ map_element "ATTRIBUTE-DEFINITION-STRING",
34
+ to: :attribute_definition_string
23
35
  map_element "ATTRIBUTE-DEFINITION-XHTML", to: :attribute_definition_xhtml
24
36
  end
25
37
  end
@@ -6,7 +6,7 @@ module Reqif
6
6
  attribute :identifier, :string
7
7
  attribute :is_editable, :boolean
8
8
  attribute :is_table_internal, :boolean
9
- attribute :last_change, :time
9
+ attribute :last_change, HighPrecisionDateTime
10
10
  attribute :long_name, :string
11
11
  attribute :alternative_id, AlternativeId
12
12
  attribute :children, Children
@@ -14,10 +14,11 @@ module Reqif
14
14
  attribute :object, Object
15
15
 
16
16
  xml do
17
- root "SPEC-HIERARCHY"
18
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
17
+ element "SPEC-HIERARCHY"
18
+ namespace Namespace
19
+ ordered
19
20
 
20
- map_attribute "DESC", to: :desc
21
+ map_attribute "DESC", to: :desc, render_empty: true
21
22
  map_attribute "IDENTIFIER", to: :identifier
22
23
  map_attribute "IS-EDITABLE", to: :is_editable
23
24
  map_attribute "IS-TABLE-INTERNAL", to: :is_table_internal
@@ -4,17 +4,18 @@ module Reqif
4
4
  class SpecObject < Lutaml::Model::Serializable
5
5
  attribute :desc, :string
6
6
  attribute :identifier, :string
7
- attribute :last_change, :time
7
+ attribute :last_change, HighPrecisionDateTime
8
8
  attribute :long_name, :string
9
9
  attribute :alternative_id, AlternativeId
10
10
  attribute :values, Values
11
11
  attribute :type, Type
12
12
 
13
13
  xml do
14
- root "SPEC-OBJECT"
15
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
14
+ element "SPEC-OBJECT"
15
+ namespace Namespace
16
+ ordered
16
17
 
17
- map_attribute "DESC", to: :desc
18
+ map_attribute "DESC", to: :desc, render_empty: true
18
19
  map_attribute "IDENTIFIER", to: :identifier
19
20
  map_attribute "LAST-CHANGE", to: :last_change
20
21
  map_attribute "LONG-NAME", to: :long_name
@@ -4,16 +4,17 @@ module Reqif
4
4
  class SpecObjectType < Lutaml::Model::Serializable
5
5
  attribute :desc, :string
6
6
  attribute :identifier, :string
7
- attribute :last_change, :time
7
+ attribute :last_change, HighPrecisionDateTime
8
8
  attribute :long_name, :string
9
9
  attribute :alternative_id, AlternativeId
10
10
  attribute :spec_attributes, SpecAttributes
11
11
 
12
12
  xml do
13
- root "SPEC-OBJECT-TYPE"
14
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
13
+ element "SPEC-OBJECT-TYPE"
14
+ namespace Namespace
15
+ ordered
15
16
 
16
- map_attribute "DESC", to: :desc
17
+ map_attribute "DESC", to: :desc, render_empty: true
17
18
  map_attribute "IDENTIFIER", to: :identifier
18
19
  map_attribute "LAST-CHANGE", to: :last_change
19
20
  map_attribute "LONG-NAME", to: :long_name
@@ -5,8 +5,9 @@ module Reqif
5
5
  attribute :spec_object, SpecObject, collection: true
6
6
 
7
7
  xml do
8
- root "SPEC-OBJECTS"
9
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
8
+ element "SPEC-OBJECTS"
9
+ namespace Namespace
10
+ ordered
10
11
 
11
12
  map_element "SPEC-OBJECT", to: :spec_object
12
13
  end
@@ -4,7 +4,7 @@ module Reqif
4
4
  class SpecRelation < Lutaml::Model::Serializable
5
5
  attribute :desc, :string
6
6
  attribute :identifier, :string
7
- attribute :last_change, :time
7
+ attribute :last_change, HighPrecisionDateTime
8
8
  attribute :long_name, :string
9
9
  attribute :alternative_id, AlternativeId
10
10
  attribute :values, Values
@@ -13,10 +13,11 @@ module Reqif
13
13
  attribute :type, Type
14
14
 
15
15
  xml do
16
- root "SPEC-RELATION"
17
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
16
+ element "SPEC-RELATION"
17
+ namespace Namespace
18
+ ordered
18
19
 
19
- map_attribute "DESC", to: :desc
20
+ map_attribute "DESC", to: :desc, render_empty: true
20
21
  map_attribute "IDENTIFIER", to: :identifier
21
22
  map_attribute "LAST-CHANGE", to: :last_change
22
23
  map_attribute "LONG-NAME", to: :long_name
@@ -5,8 +5,8 @@ module Reqif
5
5
  attribute :relation_group, RelationGroup, collection: true
6
6
 
7
7
  xml do
8
- root "SPEC-RELATION-GROUPS"
9
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
8
+ element "SPEC-RELATION-GROUPS"
9
+ namespace Namespace
10
10
 
11
11
  map_element "RELATION-GROUP", to: :relation_group
12
12
  end
@@ -4,16 +4,17 @@ module Reqif
4
4
  class SpecRelationType < Lutaml::Model::Serializable
5
5
  attribute :desc, :string
6
6
  attribute :identifier, :string
7
- attribute :last_change, :time
7
+ attribute :last_change, HighPrecisionDateTime
8
8
  attribute :long_name, :string
9
9
  attribute :alternative_id, AlternativeId
10
10
  attribute :spec_attributes, SpecAttributes
11
11
 
12
12
  xml do
13
- root "SPEC-RELATION-TYPE"
14
- namespace "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd", "REQIF"
13
+ element "SPEC-RELATION-TYPE"
14
+ namespace Namespace
15
+ ordered
15
16
 
16
- map_attribute "DESC", to: :desc
17
+ map_attribute "DESC", to: :desc, render_empty: true
17
18
  map_attribute "IDENTIFIER", to: :identifier
18
19
  map_attribute "LAST-CHANGE", to: :last_change
19
20
  map_attribute "LONG-NAME", to: :long_name