Module: Xmi::VersionRegistry

Defined in:
lib/xmi/version_registry.rb

Overview

Registry for XMI version-specific model trees.

Manages the mapping between XMI versions and their registers.

Examples:

# Get register for a specific version
register = Xmi::VersionRegistry.register_for_version("20131001")
# Detect version from XML
register = Xmi::VersionRegistry.detect_register(xml_content)

Class Method Summary collapse

Class Method Details

.available_versionsArray<String>

Get all registered versions

Returns:

  • (Array<String>)


60
61
62
# File 'lib/xmi/version_registry.rb', line 60

def available_versions
  @versions.keys
end

.detect_register(xml_content) ⇒ Lutaml::Model::Register?

Detect version from XML content and return appropriate register

For mixed namespace documents (e.g., XMI=20131001, UML=20161101), this extends the primary register’s fallback chain to include registers for additional namespace versions, enabling correct type resolution.

Parameters:

  • xml_content (String)

    XML content

Returns:

  • (Lutaml::Model::Register, nil)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/xmi/version_registry.rb', line 82

def detect_register(xml_content)
  versions = NamespaceDetector.detect_versions(xml_content)
  xmi_version = versions[:xmi]

  return nil unless xmi_version

  primary_register = register_for_version(xmi_version)
  return nil unless primary_register

  # Handle mixed namespace documents (e.g., XMI=20131001 but UML=20161101).
  # We need to ensure the primary register's fallback chain includes
  # registers for any additional namespace versions, and bind those
  # namespace URIs to the primary register so type resolution works.
  all_versions = [versions[:xmi], versions[:uml], versions[:umldi],
                  versions[:umldc]].compact.uniq

  if all_versions.length > 1
    extend_fallback_for_mixed_namespaces(primary_register,
                                         all_versions)
  end

  primary_register
end

.extend_fallback_for_mixed_namespaces(primary_register, all_versions) ⇒ void

This method returns an undefined value.

Handle mixed namespace documents by binding additional namespace URIs to the primary register and extending its fallback chain.

The namespace binding allows the primary register to handle elements from additional namespace versions. The fallback chain extension allows type resolution for types that exist only in those additional registers.

Cycles are prevented by checking that the additional register’s fallback chain doesn’t include the primary register (which would create a cycle).

rubocop:disable Metrics/CyclomaticComplexity

Parameters:

  • primary_register (Lutaml::Model::Register)

    The primary register

  • all_versions (Array<String>)

    All detected namespace versions



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/xmi/version_registry.rb', line 137

def extend_fallback_for_mixed_namespaces(primary_register, all_versions)
  xmi_version = all_versions.first
  other_versions = all_versions.drop(1)

  other_versions.each do |ver|
    next if ver == xmi_version

    reg = register_for_version(ver)
    next unless reg

    # Bind additional namespace URIs to the primary register using
    # proper namespace classes from NamespaceRegistry.
    reg.bound_namespace_uris.each do |uri|
      next if primary_register.handles_namespace?(uri)

      ns_class = NamespaceRegistry.resolve(uri)
      next unless ns_class

      primary_register.bind_namespace(ns_class)
    end

    # Extend fallback chain only if it won't create a cycle.
    # A cycle would occur if reg's fallback chain includes primary_register.
    # We check this by seeing if primary_register.id appears in reg's fallback.
    primary_register.fallback << reg.id unless reg.fallback.include?(primary_register.id)
  end
end

.parse_with_detected_version(xml_content, model_class) ⇒ Object

Parse XML with automatic version detection

Parameters:

  • xml_content (String)

    XML content

  • model_class (Class)

    The model class to parse into

Returns:

  • (Object)

    Parsed model instance



112
113
114
115
116
117
118
119
120
121
# File 'lib/xmi/version_registry.rb', line 112

def parse_with_detected_version(xml_content, model_class)
  register = detect_register(xml_content)

  if register
    model_class.from_xml(xml_content, register: register)
  else
    # Fallback to default parsing (existing behavior)
    model_class.from_xml(xml_content)
  end
end

.register_for_namespace(namespace_uri) ⇒ Lutaml::Model::Register?

Get register for a namespace URI

Parameters:

  • namespace_uri (String)

    The namespace URI

Returns:

  • (Lutaml::Model::Register, nil)


42
43
44
# File 'lib/xmi/version_registry.rb', line 42

def register_for_namespace(namespace_uri)
  Lutaml::Model::GlobalContext.register_for_namespace(namespace_uri)
end

.register_for_version(version) ⇒ Lutaml::Model::Register?

Get register for a specific XMI version

Parameters:

  • version (String)

    Version string (e.g., “20131001”)

Returns:

  • (Lutaml::Model::Register, nil)


30
31
32
33
34
35
# File 'lib/xmi/version_registry.rb', line 30

def register_for_version(version)
  version_module = @versions[version]
  return nil unless version_module

  version_module.register
end

.register_version(version, mod) ⇒ void

This method returns an undefined value.

Register a version module

Parameters:

  • version (String)

    Version string

  • mod (Module)

    The version module



52
53
54
# File 'lib/xmi/version_registry.rb', line 52

def register_version(version, mod)
  @versions = @versions.merge(version => mod)
end

.version_module(version) ⇒ Module?

Get the version module for a version string

Parameters:

  • version (String)

    Version string

Returns:

  • (Module, nil)


69
70
71
# File 'lib/xmi/version_registry.rb', line 69

def version_module(version)
  @versions[version]
end