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)



44
45
46
47
48
49
50
51
52
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 44

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:



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

def configuration
  @configuration
end

#current_parserParser (readonly)

Returns Parser instance.

Returns:

  • (Parser)

    Parser instance



38
39
40
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 38

def current_parser
  @current_parser
end

#format_registryFormatRegistry (readonly)

Returns Format registry.

Returns:



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

def format_registry
  @format_registry
end

#transformation_historyArray<Hash> (readonly)

Returns Transformation history.

Returns:

  • (Array<Hash>)

    Transformation history



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

def transformation_history
  @transformation_history
end

Instance Method Details

#clear_historyvoid

This method returns an undefined value.

Clear transformation history



209
210
211
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 209

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



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 116

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



217
218
219
220
221
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 217

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:



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
102
103
104
105
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 64

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



227
228
229
230
231
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 227

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



161
162
163
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 161

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

#statisticsHash

Get comprehensive transformation statistics

Returns:

  • (Hash)

    Statistics about transformations



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 186

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



143
144
145
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 143

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



151
152
153
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 151

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



169
170
171
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 169

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

#validate_setupHash

Validate configuration and parsers

Returns:

  • (Hash)

    Validation results



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
268
269
270
271
# File 'lib/lutaml/model_transformations/transformation_engine.rb', line 236

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.respond_to?(: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