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}