swift_mt_message/
sample.rs

1//! Sample generation functionality for SWIFT MT messages
2//!
3//! This module provides utilities for generating sample SWIFT MT messages
4//! based on test scenarios using datafake-rs for dynamic data generation.
5
6use crate::errors::{self, Result};
7use crate::scenario_config::{
8    ScenarioConfig, find_scenario_by_name_with_config, find_scenario_for_message_type_with_config,
9};
10use crate::swift_message::SwiftMessage;
11use crate::traits::SwiftMessageBody;
12use datafake_rs::DataGenerator;
13use std::path::PathBuf;
14
15/// Generate a sample SWIFT MT message based on test scenarios with custom configuration
16///
17/// This function loads a test scenario configuration for the specified message type
18/// and generates a realistic SWIFT message using datafake-rs for dynamic data generation.
19///
20/// # Arguments
21///
22/// * `message_type` - The MT message type (e.g., "MT103", "MT202")
23/// * `scenario_name` - Optional scenario name. If None, uses the default scenario
24/// * `config` - Configuration for scenario file paths
25///
26/// # Returns
27///
28/// Returns a complete SwiftMessage object with headers and the message body
29///
30/// # Example
31///
32/// ```no_run
33/// # use swift_mt_message::{generate_sample_with_config, ScenarioConfig, SwiftMessage, messages::mt103::MT103};
34/// # use std::path::PathBuf;
35/// // Generate with custom paths
36/// let config = ScenarioConfig::with_paths(vec![PathBuf::from("./my_scenarios")]);
37/// let mt103_msg: SwiftMessage<MT103> = generate_sample_with_config("MT103", None, &config).unwrap();
38/// println!("{}", mt103_msg.to_mt_message());
39/// ```
40pub fn generate_sample_with_config<T>(
41    message_type: &str,
42    scenario_name: Option<&str>,
43    config: &ScenarioConfig,
44) -> Result<SwiftMessage<T>>
45where
46    T: SwiftMessageBody + serde::de::DeserializeOwned,
47{
48    // Load the scenario configuration JSON
49    let scenario_json = if let Some(name) = scenario_name {
50        find_scenario_by_name_with_config(message_type, name, config)?
51    } else {
52        find_scenario_for_message_type_with_config(message_type, config)?
53    };
54
55    // Create datafake-rs generator from the scenario
56    let generator = DataGenerator::from_value(scenario_json).map_err(|e| {
57        errors::ParseError::InvalidFormat {
58            message: format!("Failed to create datafake generator: {e:?}"),
59        }
60    })?;
61
62    // Generate the data
63    let generated_data = generator
64        .generate()
65        .map_err(|e| errors::ParseError::InvalidFormat {
66            message: format!("datafake-rs generation failed: {e:?}"),
67        })?;
68
69    // Convert generated data to string for parsing
70    let generated_json = serde_json::to_string_pretty(&generated_data).map_err(|e| {
71        errors::ParseError::InvalidFormat {
72            message: format!("Failed to serialize generated data: {e}"),
73        }
74    })?;
75
76    // Parse the generated JSON into the complete SwiftMessage
77    serde_json::from_str(&generated_json).map_err(|e| errors::ParseError::InvalidFormat {
78        message: format!("Failed to parse generated JSON into SwiftMessage<{message_type}>: {e}"),
79    })
80}
81
82/// Generate a sample SWIFT MT message based on test scenarios (backward compatibility)
83///
84/// This function loads a test scenario configuration for the specified message type
85/// and generates a realistic SWIFT message using datafake-rs for dynamic data generation.
86///
87/// # Arguments
88///
89/// * `message_type` - The MT message type (e.g., "MT103", "MT202")
90/// * `scenario_name` - Optional scenario name. If None, uses the default scenario
91///
92/// # Returns
93///
94/// Returns a complete SwiftMessage object with headers and the message body
95///
96/// # Example
97///
98/// ```no_run
99/// # use swift_mt_message::{generate_sample, SwiftMessage, messages::mt103::MT103};
100/// // Generate a standard MT103 message
101/// let mt103_msg: SwiftMessage<MT103> = generate_sample("MT103", None).unwrap();
102/// println!("{}", mt103_msg.to_mt_message());
103///
104/// // Generate a specific scenario
105/// let mt103_high_value: SwiftMessage<MT103> = generate_sample("MT103", Some("high_value_payment")).unwrap();
106/// ```
107pub fn generate_sample<T>(
108    message_type: &str,
109    scenario_name: Option<&str>,
110) -> Result<SwiftMessage<T>>
111where
112    T: SwiftMessageBody + serde::de::DeserializeOwned,
113{
114    generate_sample_with_config(message_type, scenario_name, &ScenarioConfig::default())
115}
116
117/// A builder for generating SWIFT MT message samples with custom configuration
118///
119/// The `SampleGenerator` provides a fluent interface for configuring and generating
120/// SWIFT MT message samples with custom scenario paths.
121///
122/// # Example
123///
124/// ```no_run
125/// # use swift_mt_message::{SampleGenerator, SwiftMessage, messages::mt103::MT103};
126/// # use std::path::PathBuf;
127/// let generator = SampleGenerator::new()
128///     .with_path(PathBuf::from("./custom_scenarios"))
129///     .with_path(PathBuf::from("./backup_scenarios"));
130///
131/// let mt103: SwiftMessage<MT103> = generator.generate("MT103", None).unwrap();
132/// let mt103_stp: SwiftMessage<MT103> = generator.generate("MT103", Some("stp")).unwrap();
133/// ```
134#[derive(Debug, Clone)]
135pub struct SampleGenerator {
136    config: ScenarioConfig,
137}
138
139impl Default for SampleGenerator {
140    fn default() -> Self {
141        Self::new()
142    }
143}
144
145impl SampleGenerator {
146    /// Create a new sample generator with default configuration
147    pub fn new() -> Self {
148        Self {
149            config: ScenarioConfig::default(),
150        }
151    }
152
153    /// Create a sample generator with specific configuration
154    pub fn with_config(config: ScenarioConfig) -> Self {
155        Self { config }
156    }
157
158    /// Add a path to search for scenario files
159    pub fn with_path(mut self, path: PathBuf) -> Self {
160        self.config = self.config.add_path(path);
161        self
162    }
163
164    /// Set multiple paths to search for scenario files (replaces existing paths)
165    pub fn with_paths(mut self, paths: Vec<PathBuf>) -> Self {
166        self.config = self.config.set_paths(paths);
167        self
168    }
169
170    /// Generate a sample SWIFT MT message
171    ///
172    /// # Arguments
173    ///
174    /// * `message_type` - The MT message type (e.g., "MT103", "MT202")
175    /// * `scenario_name` - Optional scenario name. If None, uses the default scenario
176    pub fn generate<T>(
177        &self,
178        message_type: &str,
179        scenario_name: Option<&str>,
180    ) -> Result<SwiftMessage<T>>
181    where
182        T: SwiftMessageBody + serde::de::DeserializeOwned,
183    {
184        generate_sample_with_config(message_type, scenario_name, &self.config)
185    }
186
187    /// Get a reference to the current configuration
188    pub fn config(&self) -> &ScenarioConfig {
189        &self.config
190    }
191}