Module: Oscal

Defined in:
lib/oscal.rb,
lib/oscal/v1_2_1.rb,
lib/oscal/version.rb,
lib/oscal/versioned.rb,
lib/oscal/version_registry.rb

Overview

Oscal provides a clean facade for OSCAL model access.

Usage:

require "oscal"

# Default version (latest) — auto-resolves constants
catalog = Oscal::Catalog.from_xml(File.read("catalog.xml"))

# Explicit version
v121 = Oscal.version("1.2.1")
catalog = v121::Catalog.from_xml(xml)

# Auto-detect version and parse
doc = Oscal.parse(File.read("catalog.xml"))

Defined Under Namespace

Modules: V1_2_1, VersionRegistry, Versioned Classes: Error

Constant Summary collapse

VERSION =
"0.4.0"

Class Method Summary collapse

Class Method Details

.const_missing(name) ⇒ Object

Resolve missing constants from the default version module.



86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/oscal.rb', line 86

def const_missing(name)
  name_s = name.to_s
  mod = default_version_module
  mod.init_models! unless mod.initialized?

  if mod.const_defined?(name_s)
    klass = mod.const_get(name_s)
    const_set(name, klass)
    klass
  else
    super
  end
end

.default_version_moduleObject

Load the default version module. Called lazily on first access.



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

def default_version_module
  @default_version_module ||= begin
    require_relative "oscal/v1_2_1"
    VersionRegistry.latest_module
  end
end

.parse(content, model: nil) ⇒ Lutaml::Model::Serializable

Parse an OSCAL document with automatic version detection.

Parameters:

  • content (String)

    XML, JSON, or YAML string

  • model (Symbol) (defaults to: nil)

    Model type (:catalog, :profile, etc.)

Returns:

  • (Lutaml::Model::Serializable)

    Parsed instance



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/oscal.rb', line 54

def parse(content, model: nil)
  version = VersionRegistry.detect_version(content)
  if version
    ver_mod = VersionRegistry.version_module(version)
    if ver_mod
      ver_mod.init_models! unless ver_mod.initialized?
      register = ver_mod.register
    end
  end

  ver_mod ||= default_version_module
  register ||= ver_mod.register

  model_type = model || VersionRegistry.detect_model_type(content)
  raise Error, "Cannot detect model type. Specify with model: :catalog" unless model_type

  class_name = model_type.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
  klass = ver_mod.resolve_class(class_name)
  raise Error, "Unknown model type: #{class_name}" unless klass

  if content.lstrip.start_with?("<")
    register ? klass.from_xml(content, register: register) : klass.from_xml(content)
  elsif content.lstrip.start_with?("{")
    klass.from_json(content)
  else
    klass.from_yaml(content)
  end
rescue StandardError => e
  raise Error, "Failed to parse OSCAL document: #{e.message}"
end

.version(version_string) ⇒ Module

Use a specific OSCAL version.

Parameters:

  • version_string (String)

    OSCAL version (e.g., “1.2.1”)

Returns:

  • (Module)

    The version module

Raises:



41
42
43
44
45
46
47
# File 'lib/oscal.rb', line 41

def version(version_string)
  mod = VersionRegistry.version_module(version_string)
  raise Error, "Unknown OSCAL version: #{version_string}" unless mod

  mod.init_models! unless mod.initialized?
  mod
end