1use super::{
8 DdexVersion, MessageProfile, PartnerPreset, PresetConfig, PresetDefaults, PresetSource,
9 ValidationRule,
10};
11use indexmap::IndexMap;
12
13pub fn audio_album() -> PartnerPreset {
19 let mut validation_rules = IndexMap::new();
20 validation_rules.insert("ISRC".to_string(), ValidationRule::Required);
21 validation_rules.insert("ReleaseDate".to_string(), ValidationRule::Required);
22 validation_rules.insert("Genre".to_string(), ValidationRule::Required);
23 validation_rules.insert("AlbumTitle".to_string(), ValidationRule::Required);
24 validation_rules.insert("ArtistName".to_string(), ValidationRule::Required);
25 validation_rules.insert("TrackTitle".to_string(), ValidationRule::Required);
26 validation_rules.insert(
27 "ISRC".to_string(),
28 ValidationRule::Pattern(r"^[A-Z]{2}[A-Z0-9]{3}\d{7}$".to_string()),
29 );
30 validation_rules.insert(
31 "Duration".to_string(),
32 ValidationRule::Pattern(r"^PT(\d+H)?(\d+M)?(\d+(\.\d+)?S)?$".to_string()),
33 );
34
35 let mut default_values = IndexMap::new();
36 default_values.insert("MessageControlType".to_string(), "LiveMessage".to_string());
37 default_values.insert("ReleaseType".to_string(), "Album".to_string());
38
39 let config = PresetConfig {
40 version: DdexVersion::Ern43,
41 profile: MessageProfile::AudioAlbum,
42 required_fields: vec![
43 "ISRC".to_string(),
44 "ReleaseDate".to_string(),
45 "Genre".to_string(),
46 "AlbumTitle".to_string(),
47 "ArtistName".to_string(),
48 "TrackTitle".to_string(),
49 ],
50 validation_rules: validation_rules.clone(),
51 default_values,
52 custom_mappings: IndexMap::new(),
53 territory_codes: vec!["Worldwide".to_string()],
54 distribution_channels: vec!["01".to_string()], release_types: vec![
56 "Album".to_string(),
57 "CompilationAlbum".to_string(),
58 "LiveAlbum".to_string(),
59 ],
60 };
61
62 PartnerPreset {
63 name: "audio_album".to_string(),
64 description: "Generic Audio Album ERN 4.3 - DDEX-compliant baseline configuration".to_string(),
65 source: PresetSource::Community,
66 provenance_url: Some("https://ddex.net/standards/".to_string()),
67 version: "1.0.0".to_string(),
68 locked: false,
69 disclaimer: "Generic industry-standard preset based on DDEX ERN 4.3 specification. Customize for specific platform requirements.".to_string(),
70 determinism: super::super::determinism::DeterminismConfig::default(),
71 defaults: PresetDefaults {
72 message_control_type: Some("LiveMessage".to_string()),
73 territory_code: vec!["Worldwide".to_string()],
74 distribution_channel: vec!["01".to_string()],
75 },
76 required_fields: config.required_fields.clone(),
77 format_overrides: IndexMap::new(),
78 config,
79 validation_rules,
80 custom_mappings: IndexMap::new(),
81 }
82}
83
84pub fn audio_single() -> PartnerPreset {
89 let mut validation_rules = IndexMap::new();
90 validation_rules.insert("ISRC".to_string(), ValidationRule::Required);
91 validation_rules.insert("ReleaseDate".to_string(), ValidationRule::Required);
92 validation_rules.insert("Genre".to_string(), ValidationRule::Required);
93 validation_rules.insert("TrackTitle".to_string(), ValidationRule::Required);
94 validation_rules.insert("ArtistName".to_string(), ValidationRule::Required);
95 validation_rules.insert(
96 "ISRC".to_string(),
97 ValidationRule::Pattern(r"^[A-Z]{2}[A-Z0-9]{3}\d{7}$".to_string()),
98 );
99 validation_rules.insert(
100 "Duration".to_string(),
101 ValidationRule::Pattern(r"^PT(\d+H)?(\d+M)?(\d+(\.\d+)?S)?$".to_string()),
102 );
103
104 let mut default_values = IndexMap::new();
105 default_values.insert("MessageControlType".to_string(), "LiveMessage".to_string());
106 default_values.insert("ReleaseType".to_string(), "Single".to_string());
107
108 let config = PresetConfig {
109 version: DdexVersion::Ern43,
110 profile: MessageProfile::AudioSingle,
111 required_fields: vec![
112 "ISRC".to_string(),
113 "ReleaseDate".to_string(),
114 "Genre".to_string(),
115 "TrackTitle".to_string(),
116 "ArtistName".to_string(),
117 ],
118 validation_rules: validation_rules.clone(),
119 default_values,
120 custom_mappings: IndexMap::new(),
121 territory_codes: vec!["Worldwide".to_string()],
122 distribution_channels: vec!["01".to_string()],
123 release_types: vec!["Single".to_string()],
124 };
125
126 PartnerPreset {
127 name: "audio_single".to_string(),
128 description: "Generic Audio Single ERN 4.3 - DDEX-compliant single track configuration".to_string(),
129 source: PresetSource::Community,
130 provenance_url: Some("https://ddex.net/standards/".to_string()),
131 version: "1.0.0".to_string(),
132 locked: false,
133 disclaimer: "Generic industry-standard preset based on DDEX ERN 4.3 specification. Customize for specific platform requirements.".to_string(),
134 determinism: super::super::determinism::DeterminismConfig::default(),
135 defaults: PresetDefaults {
136 message_control_type: Some("LiveMessage".to_string()),
137 territory_code: vec!["Worldwide".to_string()],
138 distribution_channel: vec!["01".to_string()],
139 },
140 required_fields: config.required_fields.clone(),
141 format_overrides: IndexMap::new(),
142 config,
143 validation_rules,
144 custom_mappings: IndexMap::new(),
145 }
146}
147
148pub fn video_single() -> PartnerPreset {
153 let mut validation_rules = IndexMap::new();
154 validation_rules.insert("ISRC".to_string(), ValidationRule::Required);
155 validation_rules.insert("ReleaseDate".to_string(), ValidationRule::Required);
156 validation_rules.insert("Genre".to_string(), ValidationRule::Required);
157 validation_rules.insert("VideoTitle".to_string(), ValidationRule::Required);
158 validation_rules.insert("ArtistName".to_string(), ValidationRule::Required);
159 validation_rules.insert("VideoResource".to_string(), ValidationRule::Required);
160 validation_rules.insert("AudioResource".to_string(), ValidationRule::Required);
161 validation_rules.insert(
162 "ISRC".to_string(),
163 ValidationRule::Pattern(r"^[A-Z]{2}[A-Z0-9]{3}\d{7}$".to_string()),
164 );
165
166 let mut default_values = IndexMap::new();
167 default_values.insert("MessageControlType".to_string(), "LiveMessage".to_string());
168 default_values.insert("ReleaseType".to_string(), "VideoSingle".to_string());
169
170 let mut custom_mappings = IndexMap::new();
171 custom_mappings.insert(
172 "VideoResource".to_string(),
173 "VideoTechnicalResourceDetails".to_string(),
174 );
175 custom_mappings.insert(
176 "AudioResource".to_string(),
177 "SoundRecordingTechnicalResourceDetails".to_string(),
178 );
179
180 let config = PresetConfig {
181 version: DdexVersion::Ern43,
182 profile: MessageProfile::VideoSingle,
183 required_fields: vec![
184 "ISRC".to_string(),
185 "ReleaseDate".to_string(),
186 "Genre".to_string(),
187 "VideoTitle".to_string(),
188 "ArtistName".to_string(),
189 "VideoResource".to_string(),
190 "AudioResource".to_string(),
191 ],
192 validation_rules: validation_rules.clone(),
193 default_values,
194 custom_mappings: custom_mappings.clone(),
195 territory_codes: vec!["Worldwide".to_string()],
196 distribution_channels: vec!["01".to_string(), "02".to_string()], release_types: vec!["VideoSingle".to_string(), "MusicVideo".to_string()],
198 };
199
200 PartnerPreset {
201 name: "video_single".to_string(),
202 description: "Generic Video Single ERN 4.3 - DDEX-compliant video release configuration".to_string(),
203 source: PresetSource::Community,
204 provenance_url: Some("https://ddex.net/standards/".to_string()),
205 version: "1.0.0".to_string(),
206 locked: false,
207 disclaimer: "Generic industry-standard preset based on DDEX ERN 4.3 specification. Customize for specific platform requirements.".to_string(),
208 determinism: super::super::determinism::DeterminismConfig::default(),
209 defaults: PresetDefaults {
210 message_control_type: Some("LiveMessage".to_string()),
211 territory_code: vec!["Worldwide".to_string()],
212 distribution_channel: vec!["01".to_string(), "02".to_string()],
213 },
214 required_fields: config.required_fields.clone(),
215 format_overrides: IndexMap::new(),
216 config,
217 validation_rules,
218 custom_mappings,
219 }
220}
221
222pub fn compilation() -> PartnerPreset {
227 let mut preset = audio_album();
228
229 preset.name = "compilation".to_string();
231 preset.description =
232 "Generic Compilation ERN 4.3 - DDEX-compliant multi-artist compilation configuration"
233 .to_string();
234 preset.config.release_types = vec!["CompilationAlbum".to_string()];
235 preset
236 .config
237 .default_values
238 .insert("ReleaseType".to_string(), "CompilationAlbum".to_string());
239
240 preset
242 .validation_rules
243 .insert("CompilationIndicator".to_string(), ValidationRule::Required);
244 preset.validation_rules.insert(
245 "VariousArtists".to_string(),
246 ValidationRule::Custom("Multiple contributing artists".to_string()),
247 );
248 preset
249 .config
250 .required_fields
251 .push("CompilationIndicator".to_string());
252 preset
253 .required_fields
254 .push("CompilationIndicator".to_string());
255
256 preset
257}
258
259pub fn all_generic_presets() -> IndexMap<String, PartnerPreset> {
261 let mut presets = IndexMap::new();
262 presets.insert("audio_album".to_string(), audio_album());
263 presets.insert("audio_single".to_string(), audio_single());
264 presets.insert("video_single".to_string(), video_single());
265 presets.insert("compilation".to_string(), compilation());
266 presets
267}
268
269#[cfg(test)]
270mod tests {
271 use super::*;
272
273 #[test]
274 fn test_audio_album_preset() {
275 let preset = audio_album();
276 assert_eq!(preset.name, "audio_album");
277 assert_eq!(preset.config.version, DdexVersion::Ern43);
278 assert_eq!(preset.config.profile, MessageProfile::AudioAlbum);
279 assert!(preset.required_fields.contains(&"ISRC".to_string()));
280 assert!(preset.required_fields.contains(&"AlbumTitle".to_string()));
281 assert_eq!(preset.source, PresetSource::Community);
282 }
283
284 #[test]
285 fn test_audio_single_preset() {
286 let preset = audio_single();
287 assert_eq!(preset.name, "audio_single");
288 assert_eq!(preset.config.profile, MessageProfile::AudioSingle);
289 assert!(preset.required_fields.contains(&"TrackTitle".to_string()));
290 assert!(!preset.required_fields.contains(&"AlbumTitle".to_string()));
291 }
292
293 #[test]
294 fn test_video_single_preset() {
295 let preset = video_single();
296 assert_eq!(preset.name, "video_single");
297 assert_eq!(preset.config.profile, MessageProfile::VideoSingle);
298 assert!(preset
299 .required_fields
300 .contains(&"VideoResource".to_string()));
301 assert!(preset
302 .required_fields
303 .contains(&"AudioResource".to_string()));
304 }
305
306 #[test]
307 fn test_compilation_preset() {
308 let preset = compilation();
309 assert_eq!(preset.name, "compilation");
310 assert!(preset
311 .config
312 .release_types
313 .contains(&"CompilationAlbum".to_string()));
314 assert!(preset
315 .required_fields
316 .contains(&"CompilationIndicator".to_string()));
317 }
318
319 #[test]
320 fn test_all_generic_presets() {
321 let presets = all_generic_presets();
322 assert_eq!(presets.len(), 4);
323 assert!(presets.contains_key("audio_album"));
324 assert!(presets.contains_key("audio_single"));
325 assert!(presets.contains_key("video_single"));
326 assert!(presets.contains_key("compilation"));
327 }
328
329 #[test]
330 fn test_generic_presets_source() {
331 let presets = all_generic_presets();
332 for (_, preset) in presets {
333 assert_eq!(preset.source, PresetSource::Community);
334 assert!(preset.disclaimer.contains("Generic industry-standard"));
335 }
336 }
337}