use super::{
DdexVersion, MessageProfile, PartnerPreset, PresetConfig, PresetDefaults, PresetSource,
ValidationRule,
};
use indexmap::IndexMap;
pub fn audio_album() -> PartnerPreset {
let mut validation_rules = IndexMap::new();
validation_rules.insert("ISRC".to_string(), ValidationRule::Required);
validation_rules.insert("ReleaseDate".to_string(), ValidationRule::Required);
validation_rules.insert("Genre".to_string(), ValidationRule::Required);
validation_rules.insert("AlbumTitle".to_string(), ValidationRule::Required);
validation_rules.insert("ArtistName".to_string(), ValidationRule::Required);
validation_rules.insert("TrackTitle".to_string(), ValidationRule::Required);
validation_rules.insert(
"ISRC".to_string(),
ValidationRule::Pattern(r"^[A-Z]{2}[A-Z0-9]{3}\d{7}$".to_string()),
);
validation_rules.insert(
"Duration".to_string(),
ValidationRule::Pattern(r"^PT(\d+H)?(\d+M)?(\d+(\.\d+)?S)?$".to_string()),
);
let mut default_values = IndexMap::new();
default_values.insert("MessageControlType".to_string(), "LiveMessage".to_string());
default_values.insert("ReleaseType".to_string(), "Album".to_string());
let config = PresetConfig {
version: DdexVersion::Ern43,
profile: MessageProfile::AudioAlbum,
required_fields: vec![
"ISRC".to_string(),
"ReleaseDate".to_string(),
"Genre".to_string(),
"AlbumTitle".to_string(),
"ArtistName".to_string(),
"TrackTitle".to_string(),
],
validation_rules: validation_rules.clone(),
default_values,
custom_mappings: IndexMap::new(),
territory_codes: vec!["Worldwide".to_string()],
distribution_channels: vec!["01".to_string()], release_types: vec![
"Album".to_string(),
"CompilationAlbum".to_string(),
"LiveAlbum".to_string(),
],
};
PartnerPreset {
name: "audio_album".to_string(),
description: "Generic Audio Album ERN 4.3 - DDEX-compliant baseline configuration".to_string(),
source: PresetSource::Community,
provenance_url: Some("https://ddex.net/standards/".to_string()),
version: "1.0.0".to_string(),
locked: false,
disclaimer: "Generic industry-standard preset based on DDEX ERN 4.3 specification. Customize for specific platform requirements.".to_string(),
determinism: super::super::determinism::DeterminismConfig::default(),
defaults: PresetDefaults {
message_control_type: Some("LiveMessage".to_string()),
territory_code: vec!["Worldwide".to_string()],
distribution_channel: vec!["01".to_string()],
},
required_fields: config.required_fields.clone(),
format_overrides: IndexMap::new(),
config,
validation_rules,
custom_mappings: IndexMap::new(),
}
}
pub fn audio_single() -> PartnerPreset {
let mut validation_rules = IndexMap::new();
validation_rules.insert("ISRC".to_string(), ValidationRule::Required);
validation_rules.insert("ReleaseDate".to_string(), ValidationRule::Required);
validation_rules.insert("Genre".to_string(), ValidationRule::Required);
validation_rules.insert("TrackTitle".to_string(), ValidationRule::Required);
validation_rules.insert("ArtistName".to_string(), ValidationRule::Required);
validation_rules.insert(
"ISRC".to_string(),
ValidationRule::Pattern(r"^[A-Z]{2}[A-Z0-9]{3}\d{7}$".to_string()),
);
validation_rules.insert(
"Duration".to_string(),
ValidationRule::Pattern(r"^PT(\d+H)?(\d+M)?(\d+(\.\d+)?S)?$".to_string()),
);
let mut default_values = IndexMap::new();
default_values.insert("MessageControlType".to_string(), "LiveMessage".to_string());
default_values.insert("ReleaseType".to_string(), "Single".to_string());
let config = PresetConfig {
version: DdexVersion::Ern43,
profile: MessageProfile::AudioSingle,
required_fields: vec![
"ISRC".to_string(),
"ReleaseDate".to_string(),
"Genre".to_string(),
"TrackTitle".to_string(),
"ArtistName".to_string(),
],
validation_rules: validation_rules.clone(),
default_values,
custom_mappings: IndexMap::new(),
territory_codes: vec!["Worldwide".to_string()],
distribution_channels: vec!["01".to_string()],
release_types: vec!["Single".to_string()],
};
PartnerPreset {
name: "audio_single".to_string(),
description: "Generic Audio Single ERN 4.3 - DDEX-compliant single track configuration".to_string(),
source: PresetSource::Community,
provenance_url: Some("https://ddex.net/standards/".to_string()),
version: "1.0.0".to_string(),
locked: false,
disclaimer: "Generic industry-standard preset based on DDEX ERN 4.3 specification. Customize for specific platform requirements.".to_string(),
determinism: super::super::determinism::DeterminismConfig::default(),
defaults: PresetDefaults {
message_control_type: Some("LiveMessage".to_string()),
territory_code: vec!["Worldwide".to_string()],
distribution_channel: vec!["01".to_string()],
},
required_fields: config.required_fields.clone(),
format_overrides: IndexMap::new(),
config,
validation_rules,
custom_mappings: IndexMap::new(),
}
}
pub fn video_single() -> PartnerPreset {
let mut validation_rules = IndexMap::new();
validation_rules.insert("ISRC".to_string(), ValidationRule::Required);
validation_rules.insert("ReleaseDate".to_string(), ValidationRule::Required);
validation_rules.insert("Genre".to_string(), ValidationRule::Required);
validation_rules.insert("VideoTitle".to_string(), ValidationRule::Required);
validation_rules.insert("ArtistName".to_string(), ValidationRule::Required);
validation_rules.insert("VideoResource".to_string(), ValidationRule::Required);
validation_rules.insert("AudioResource".to_string(), ValidationRule::Required);
validation_rules.insert(
"ISRC".to_string(),
ValidationRule::Pattern(r"^[A-Z]{2}[A-Z0-9]{3}\d{7}$".to_string()),
);
let mut default_values = IndexMap::new();
default_values.insert("MessageControlType".to_string(), "LiveMessage".to_string());
default_values.insert("ReleaseType".to_string(), "VideoSingle".to_string());
let mut custom_mappings = IndexMap::new();
custom_mappings.insert(
"VideoResource".to_string(),
"VideoTechnicalResourceDetails".to_string(),
);
custom_mappings.insert(
"AudioResource".to_string(),
"SoundRecordingTechnicalResourceDetails".to_string(),
);
let config = PresetConfig {
version: DdexVersion::Ern43,
profile: MessageProfile::VideoSingle,
required_fields: vec![
"ISRC".to_string(),
"ReleaseDate".to_string(),
"Genre".to_string(),
"VideoTitle".to_string(),
"ArtistName".to_string(),
"VideoResource".to_string(),
"AudioResource".to_string(),
],
validation_rules: validation_rules.clone(),
default_values,
custom_mappings: custom_mappings.clone(),
territory_codes: vec!["Worldwide".to_string()],
distribution_channels: vec!["01".to_string(), "02".to_string()], release_types: vec!["VideoSingle".to_string(), "MusicVideo".to_string()],
};
PartnerPreset {
name: "video_single".to_string(),
description: "Generic Video Single ERN 4.3 - DDEX-compliant video release configuration".to_string(),
source: PresetSource::Community,
provenance_url: Some("https://ddex.net/standards/".to_string()),
version: "1.0.0".to_string(),
locked: false,
disclaimer: "Generic industry-standard preset based on DDEX ERN 4.3 specification. Customize for specific platform requirements.".to_string(),
determinism: super::super::determinism::DeterminismConfig::default(),
defaults: PresetDefaults {
message_control_type: Some("LiveMessage".to_string()),
territory_code: vec!["Worldwide".to_string()],
distribution_channel: vec!["01".to_string(), "02".to_string()],
},
required_fields: config.required_fields.clone(),
format_overrides: IndexMap::new(),
config,
validation_rules,
custom_mappings,
}
}
pub fn compilation() -> PartnerPreset {
let mut preset = audio_album();
preset.name = "compilation".to_string();
preset.description =
"Generic Compilation ERN 4.3 - DDEX-compliant multi-artist compilation configuration"
.to_string();
preset.config.release_types = vec!["CompilationAlbum".to_string()];
preset
.config
.default_values
.insert("ReleaseType".to_string(), "CompilationAlbum".to_string());
preset
.validation_rules
.insert("CompilationIndicator".to_string(), ValidationRule::Required);
preset.validation_rules.insert(
"VariousArtists".to_string(),
ValidationRule::Custom("Multiple contributing artists".to_string()),
);
preset
.config
.required_fields
.push("CompilationIndicator".to_string());
preset
.required_fields
.push("CompilationIndicator".to_string());
preset
}
pub fn all_generic_presets() -> IndexMap<String, PartnerPreset> {
let mut presets = IndexMap::new();
presets.insert("audio_album".to_string(), audio_album());
presets.insert("audio_single".to_string(), audio_single());
presets.insert("video_single".to_string(), video_single());
presets.insert("compilation".to_string(), compilation());
presets
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_audio_album_preset() {
let preset = audio_album();
assert_eq!(preset.name, "audio_album");
assert_eq!(preset.config.version, DdexVersion::Ern43);
assert_eq!(preset.config.profile, MessageProfile::AudioAlbum);
assert!(preset.required_fields.contains(&"ISRC".to_string()));
assert!(preset.required_fields.contains(&"AlbumTitle".to_string()));
assert_eq!(preset.source, PresetSource::Community);
}
#[test]
fn test_audio_single_preset() {
let preset = audio_single();
assert_eq!(preset.name, "audio_single");
assert_eq!(preset.config.profile, MessageProfile::AudioSingle);
assert!(preset.required_fields.contains(&"TrackTitle".to_string()));
assert!(!preset.required_fields.contains(&"AlbumTitle".to_string()));
}
#[test]
fn test_video_single_preset() {
let preset = video_single();
assert_eq!(preset.name, "video_single");
assert_eq!(preset.config.profile, MessageProfile::VideoSingle);
assert!(preset
.required_fields
.contains(&"VideoResource".to_string()));
assert!(preset
.required_fields
.contains(&"AudioResource".to_string()));
}
#[test]
fn test_compilation_preset() {
let preset = compilation();
assert_eq!(preset.name, "compilation");
assert!(preset
.config
.release_types
.contains(&"CompilationAlbum".to_string()));
assert!(preset
.required_fields
.contains(&"CompilationIndicator".to_string()));
}
#[test]
fn test_all_generic_presets() {
let presets = all_generic_presets();
assert_eq!(presets.len(), 4);
assert!(presets.contains_key("audio_album"));
assert!(presets.contains_key("audio_single"));
assert!(presets.contains_key("video_single"));
assert!(presets.contains_key("compilation"));
}
#[test]
fn test_generic_presets_source() {
let presets = all_generic_presets();
for (_, preset) in presets {
assert_eq!(preset.source, PresetSource::Community);
assert!(preset.disclaimer.contains("Generic industry-standard"));
}
}
}