Class: Lutaml::ModelTransformations::TransformationEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/model_transformations/transformation_engine.rb

Overview

Transformation Engine orchestrates the entire model transformation process.

This class implements the Facade pattern to provide a simple interface for complex model transformation operations. It coordinates between configuration, format detection, parser selection, and transformation.

The engine follows the Dependency Inversion Principle by depending on abstractions (BaseParser interface) rather than concrete implementations.

Examples:

Basic usage

engine = TransformationEngine.new
document = engine.parse("model.xmi")

With custom configuration

config = Configuration.load("my_config.yml")
engine = TransformationEngine.new(config)
document = engine.parse("model.qea")

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(configuration = nil) ⇒ TransformationEngine

Initialize transformation engine

Parameters:

  • configuration (Configuration, nil) (defaults to: nil)

    Configuration to use (defaults to auto-loaded configuration)



40
41
42
43
44
45
46
47
48
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 40

def initialize(configuration = nil)
  @configuration = configuration || Configuration.load
  @format_registry = FormatRegistry.new
  @transformation_history = []
  @parser_cache = {}

  # Load parsers from configuration
  setup_parsers
end

Instance Attribute Details

#configurationConfiguration

Returns Current configuration.

Returns:



25
26
27
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 25

def configuration
  @configuration
end

#current_parserParser (readonly)

Returns Parser instance.

Returns:

  • (Parser)

    Parser instance



34
35
36
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 34

def current_parser
  @current_parser
end

#format_registryFormatRegistry (readonly)

Returns Format registry.

Returns:



28
29
30
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 28

def format_registry
  @format_registry
end

#transformation_historyArray<Hash> (readonly)

Returns Transformation history.

Returns:

  • (Array<Hash>)

    Transformation history



31
32
33
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 31

def transformation_history
  @transformation_history
end

Instance Method Details

#clear_historyvoid

This method returns an undefined value.

Clear transformation history



205
206
207
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 205

def clear_history
  @transformation_history.clear
end

#detect_parser(file_path) ⇒ Class?

Auto-detect file format and return appropriate parser class

Uses multiple detection strategies:

  1. File extension

  2. Content detection (magic bytes)

  3. Fallback parser from configuration

Parameters:

  • file_path (String)

    Path to the model file

Returns:

  • (Class, nil)

    Parser class, or nil if format cannot be detected



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 112

def detect_parser(file_path) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
  # Strategy 1: File extension detection
  if @configuration.file_extension_detection_enabled?
    parser_class = @format_registry.parser_for_file(file_path)
    return parser_class if parser_class
  end

  # Strategy 2: Content detection
  if @configuration.content_sniffing_enabled?
    parser_class = @format_registry.detect_by_content(file_path)
    return parser_class if parser_class
  end

  # Strategy 3: Fallback parser
  fallback_parser_name = @configuration.fallback_parser
  if fallback_parser_name
    return constantize_class(fallback_parser_name)
  end

  nil
rescue StandardError
  nil
end

#history_for_file(file_path) ⇒ Array<Hash>

Get transformation history for a specific file

Parameters:

  • file_path (String)

    Path to the file

Returns:

  • (Array<Hash>)

    Transformation history entries for the file



213
214
215
216
217
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 213

def history_for_file(file_path)
  @transformation_history.select do |entry|
    entry[:file_path] == file_path
  end
end

#parse(file_path, options = {}) ⇒ Lutaml::Uml::Document

Parse a model file into a UML document

This is the main entry point for model transformation. It auto-detects the file format and uses the appropriate parser.

Parameters:

  • file_path (String)

    Path to the model file

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

    Parsing options (merged with configuration)

Returns:

Raises:



60
61
62
63
64
65
66
67
68
69
70
71
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
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 60

def parse(file_path, options = {}) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
  validate_file_path!(file_path)

  # Detect format and get parser
  parser_class = detect_parser(file_path)
  raise UnsupportedFormatError.new(file_path) unless parser_class

  # Create parser instance with merged options
  merged_options = merge_options(options)
  @current_parser = get_parser_instance(parser_class, merged_options)

  # Record transformation start
  transformation_start = Time.now

  begin
    # Perform parsing
    document = @current_parser.parse(file_path)

    # Record successful transformation
    record_transformation(
      file_path: file_path,
      parser: @current_parser,
      duration: Time.now - transformation_start,
      success: true,
      document: document,
    )

    document
  rescue StandardError => e
    # Record failed transformation
    record_transformation(
      file_path: file_path,
      parser: @current_parser,
      duration: Time.now - transformation_start,
      success: false,
      error: e,
    )

    # Re-raise the error
    raise
  end
end

#recent_failures(limit = 10) ⇒ Array<Hash>

Get recent transformation failures

Parameters:

  • limit (Integer) (defaults to: 10)

    Maximum number of failures to return

Returns:

  • (Array<Hash>)

    Recent failure entries



223
224
225
226
227
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 223

def recent_failures(limit = 10)
  @transformation_history
    .reject { |entry| entry[:success] }
    .last(limit)
end

#register_parser(extension, parser_class) ⇒ void

This method returns an undefined value.

Register a custom parser for a file extension

interface

Parameters:

  • extension (String)

    File extension (e.g., “.custom”)

  • parser_class (Class)

    Parser class implementing BaseParser



157
158
159
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 157

def register_parser(extension, parser_class)
  @format_registry.register(extension, parser_class)
end

#statisticsHash

Get comprehensive transformation statistics

Returns:

  • (Hash)

    Statistics about transformations



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 182

def statistics # rubocop:disable Metrics/MethodLength
  successful_transformations = @transformation_history.count do |t|
    t[:success]
  end
  failed_transformations = @transformation_history.count do |t|
    !t[:success]
  end

  {
    total_transformations: @transformation_history.size,
    successful_transformations: successful_transformations,
    failed_transformations: failed_transformations,
    success_rate: calculate_success_rate,
    average_duration: calculate_average_duration,
    supported_extensions: supported_extensions,
    registered_parsers: @format_registry.all_parsers.keys,
    configuration_version: @configuration.version,
  }
end

#supported_extensionsArray<String>

Get list of supported file extensions

Returns:

  • (Array<String>)

    List of supported extensions



139
140
141
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 139

def supported_extensions
  @format_registry.supported_extensions
end

#supports_file?(file_path) ⇒ Boolean

Check if a file format is supported

Parameters:

  • file_path (String)

    Path to check

Returns:

  • (Boolean)

    true if format is supported



147
148
149
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 147

def supports_file?(file_path)
  detect_parser(file_path) != nil
end

#unregister_parser(extension) ⇒ Class?

Unregister a parser for a file extension

Parameters:

  • extension (String)

    File extension to unregister

Returns:

  • (Class, nil)

    The unregistered parser class



165
166
167
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 165

def unregister_parser(extension)
  @format_registry.unregister(extension)
end

#validate_setupHash

Validate configuration and parsers

Returns:

  • (Hash)

    Validation results



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 232

def validate_setup # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
  results = {
    configuration_valid: false,
    parsers_loaded: 0,
    parser_errors: [],
    warnings: [],
  }

  # Validate configuration
  begin
    if @configuration&.enabled_parsers&.any?
      results[:configuration_valid] = true
    else
      results[:warnings] << "No enabled parsers in configuration"
    end
  rescue StandardError => e
    results[:parser_errors] << "Configuration error: #{e.message}"
  end

  # Validate each parser
  @format_registry.all_parsers.each_value do |parser_class|
    # Try to create instance to validate
    parser = parser_class.new(configuration: @configuration)
    if parser.class.method_defined?(:parse)
      results[:parsers_loaded] += 1
    else
      results[:parser_errors] << "Parser #{parser_class} does not " \
                                 "implement parse method"
    end
  rescue StandardError => e
    results[:parser_errors] << "Failed to instantiate #{parser_class}: " \
                               "#{e.message}"
  end

  results
end