Class: Lutaml::Xsd::SchemaRepositoryPackage

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/xsd/schema_repository_package.rb

Overview

Represents a schema repository package (ZIP file) Handles package creation, validation, and loading Provides a clean separation between package management and repository logic

Defined Under Namespace

Classes: ValidationResult

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(zip_path) ⇒ SchemaRepositoryPackage

Create a new package instance

Parameters:

  • zip_path (String)

    Path to the ZIP package file



43
44
45
46
47
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 43

def initialize(zip_path)
  @zip_path = zip_path
  @metadata = nil
  @repository = nil
end

Instance Attribute Details

#metadataObject (readonly)

Returns the value of attribute metadata.



39
40
41
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 39

def 
  @metadata
end

#repositoryObject (readonly)

Returns the value of attribute repository.



39
40
41
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 39

def repository
  @repository
end

#zip_pathObject (readonly)

Returns the value of attribute zip_path.



39
40
41
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 39

def zip_path
  @zip_path
end

Class Method Details

.create(repository:, output_path:, config:, metadata: {}) ⇒ SchemaRepositoryPackage

Create a package from a schema repository

Parameters:

  • repository (SchemaRepository)

    Repository to package

  • output_path (String)

    Path for output ZIP file

  • config (PackageConfiguration)

    Package configuration

  • metadata (Hash) (defaults to: {})

    Additional metadata

Returns:



64
65
66
67
68
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 64

def self.create(repository:, output_path:, config:, metadata: {})
  package = new(output_path)
  package.write_from_repository(repository, config, )
  package
end

.load(zip_path) ⇒ SchemaRepositoryPackage

Load a package and its repository

Parameters:

  • zip_path (String)

    Path to the ZIP package file

Returns:



52
53
54
55
56
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 52

def self.load(zip_path)
  package = new(zip_path)
  package.load_repository
  package
end

Instance Method Details

#load_repositorySchemaRepository

Load repository from this package

Returns:



136
137
138
139
140
141
142
143
144
145
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 136

def load_repository
  validation = validate
  unless validation.valid?
    raise Error,
          "Invalid package: #{validation.errors.join(', ')}"
  end

  @metadata = validation.
  @repository = extract_and_build_repository
end

#schemasArray<Schema>

Get schemas from the repository

Returns:

  • (Array<Schema>)

    Array of schemas



149
150
151
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 149

def schemas
  repository&.schemas || []
end

#validateValidationResult

Validate the package

Returns:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 72

def validate
  errors = []
  warnings = []

  # Check file exists
  unless File.exist?(zip_path)
    return ValidationResult.new(
      valid: false,
      errors: ["Package file not found: #{zip_path}"],
    )
  end

   = nil
  schema_entries = []
   = false

  begin
    # Read and validate ZIP structure
    Zip::File.open(zip_path) do |zipfile|
      zipfile.each do |entry|
        case entry.name
        when "metadata.yaml"
           = true
           = YAML.safe_load(
            entry.get_input_stream.read,
            permitted_classes: [Time, Date, Symbol],
          )
        when %r{^schemas/.+\.xsd$}
          schema_entries << entry.name
        end
      end
    end

    # Validate structure
    validate_structure(, schema_entries, errors)

    unless 
      return ValidationResult.new(valid: false,
                                  errors: errors)
    end

    # Validate metadata
    (, schema_entries, errors, warnings)

    # Check self-containment
    validate_self_containment(, errors, warnings)
  rescue Zip::Error => e
    errors << "Failed to read ZIP package: #{e.message}"
  rescue Psych::SyntaxError => e
    errors << "Invalid YAML in metadata: #{e.message}"
  rescue StandardError => e
    errors << "Package validation error: #{e.message}"
  end

  ValidationResult.new(
    valid: errors.empty?,
    errors: errors,
    warnings: warnings,
    metadata: ,
  )
end

#write_from_repository(repository, config, additional_metadata = {}) ⇒ String

Write package from repository

Parameters:

  • repository (SchemaRepository)

    Repository to write

  • config (PackageConfiguration)

    Package configuration

  • additional_metadata (Hash) (defaults to: {})

    Additional metadata

Returns:

  • (String)

    Path to created package



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/lutaml/xsd/schema_repository_package.rb', line 158

def write_from_repository(repository, config,  = {})
  # Use PackageBuilder to build package data
  builder = PackageBuilder.new(config)
  package_data = builder.build(repository, )

  @metadata = package_data[:metadata]
  @repository = repository
  xsd_files = package_data[:xsd_files]
  serialized_schemas = package_data[:serialized_schemas]

  # Remove existing file if it exists to avoid duplicates
  FileUtils.rm_f(zip_path)

  # On Windows, give OS time to fully release file handles after deletion
  # This prevents "Permission denied" errors during ZIP file creation
  sleep 0.05 if Gem.win_platform?

  # Create ZIP file
  Zip::File.open(zip_path, create: true) do |zipfile|
    # Write metadata using Lutaml::Model's to_yaml
    zipfile.get_output_stream("metadata.yaml") do |f|
      f.write(@metadata.to_yaml)
    end

    # Write XSD files collected by bundler
    xsd_files.each do |source_path, package_data|
      if package_data.is_a?(Hash)
        # New format with rewritten content (include_all mode)
        zipfile.get_output_stream(package_data[:package_path]) do |f|
          f.write(package_data[:content])
        end
      else
        # Old format with just package_path string (allow_external mode)
        zipfile.add(package_data, source_path)
      end
    end

    # Write serialized schemas to schemas_data/ directory
    if serialized_schemas&.any?
      write_serialized_schemas(
        zipfile,
        serialized_schemas,
        xsd_files,
        config.serialization_format,
        repository.namespace_mappings,
      )
    end
  end

  zip_path
end