ddex_builder/presets/
mod.rs

1//! # DDEX Configuration Presets
2//! 
3//! This module provides pre-configured settings for DDEX message generation.
4//! Presets are community-maintained configuration templates that help ensure
5//! DDEX compliance and reduce configuration complexity.
6//! 
7//! ## Available Presets
8//! 
9//! ### Generic Industry-Standard Presets
10//! - **audio_album**: DDEX-compliant audio album configuration
11//! - **audio_single**: DDEX-compliant single track configuration  
12//! - **video_single**: DDEX-compliant video release configuration
13//! - **compilation**: DDEX-compliant compilation album configuration
14//! 
15//! ### Platform Presets (Based on Public Documentation)
16//! - **YouTube Music**: Audio and video releases (based on public Partner docs)
17//! 
18//! ## Architecture
19//! 
20//! ```text
21//! Preset System
22//! ┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
23//! │  Base Config    │───▶│  Partner Rules   │───▶│ Final Settings  │
24//! │ (DDEX defaults) │    │ (customizations) │    │ (ready to use)  │
25//! └─────────────────┘    └──────────────────┘    └─────────────────┘
26//!           │                       │                       │
27//!           ▼                       ▼                       ▼
28//!    ┌─────────────┐      ┌─────────────────┐    ┌─────────────────┐
29//!    │ • Version   │      │ • Required      │    │ • Validation    │
30//!    │ • Profile   │      │ • Validation    │    │ • Defaults      │
31//!    │ • Schema    │      │ • Territories   │    │ • Mappings      │
32//!    │ • Defaults  │      │ • Quality       │    │ • Overrides     │
33//!    └─────────────┘      └─────────────────┘    └─────────────────┘
34//! ```
35//! 
36//! ## Usage Example
37//! 
38//! ```rust
39//! use ddex_builder::presets::*;
40//! use ddex_builder::Builder;
41//! 
42//! // Use generic audio album preset
43//! let mut builder = Builder::new();
44//! builder.apply_preset(&generic::audio_album())?;
45//! 
46//! // Use YouTube preset for video content
47//! builder.apply_preset(&youtube::youtube_video())?;
48//! 
49//! // Load by name
50//! let presets = all_presets();
51//! let audio_album = &presets["audio_album"];
52//! builder.apply_partner_preset(audio_album)?;
53//! 
54//! // List available presets
55//! for (name, preset) in all_presets() {
56//!     println!("{}: {}", name, preset.description);
57//! }
58//! ```
59//! 
60//! ## Preset Features
61//! 
62//! Each preset includes:
63//! 
64//! - **Schema Version**: DDEX ERN version (3.8.2, 4.2, 4.3)
65//! - **Message Profile**: Audio, Video, or Mixed content
66//! - **Required Fields**: Mandatory metadata fields
67//! - **Validation Rules**: Data format and quality requirements
68//! - **Default Values**: Common field defaults
69//! - **Territory Codes**: Allowed distribution territories
70//! - **Quality Standards**: Audio/video quality minimums
71//! 
72//! ## Custom Presets
73//! 
74//! Create your own preset for internal standards:
75//! 
76//! ```rust
77//! use ddex_builder::presets::*;
78//! use indexmap::IndexMap;
79//! 
80//! // Start with a generic preset as base
81//! let mut custom_preset = generic::audio_album();
82//! custom_preset.name = "my_label_preset".to_string();
83//! custom_preset.description = "My Record Label Requirements".to_string();
84//! 
85//! // Add custom validation rules
86//! custom_preset.validation_rules.insert(
87//!     "Genre".to_string(), 
88//!     ValidationRule::OneOf(vec!["Rock".to_string(), "Pop".to_string()])
89//! );
90//! 
91//! // Add custom territory restrictions
92//! custom_preset.config.territory_codes = vec!["US".to_string(), "CA".to_string()];
93//! ```
94//! 
95//! ## Validation Rules
96//! 
97//! Presets support comprehensive validation:
98//! 
99//! - **Required**: Field must be present
100//! - **MinLength/MaxLength**: String length constraints
101//! - **Pattern**: Regex pattern matching
102//! - **OneOf**: Value must be from allowed list
103//! - **AudioQuality**: Minimum bit depth and sample rate
104//! - **TerritoryCode**: Allowed distribution territories
105//! - **Custom**: Partner-specific validation logic
106
107pub mod generic;
108pub mod youtube;
109
110use indexmap::IndexMap;
111use serde::{Deserialize, Serialize};
112
113/// DDEX version enum
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
115pub enum DdexVersion {
116    #[serde(rename = "ERN/3.8.2")]
117    Ern382,
118    #[serde(rename = "ERN/4.2")]
119    Ern42,
120    #[serde(rename = "ERN/4.3")]
121    Ern43,
122    #[serde(rename = "ERN/4.1")]
123    Ern41,
124}
125
126impl std::fmt::Display for DdexVersion {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        match self {
129            DdexVersion::Ern382 => write!(f, "ERN/3.8.2"),
130            DdexVersion::Ern42 => write!(f, "ERN/4.2"),
131            DdexVersion::Ern43 => write!(f, "ERN/4.3"),
132            DdexVersion::Ern41 => write!(f, "ERN/4.1"),
133        }
134    }
135}
136
137/// Message profile enum
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
139pub enum MessageProfile {
140    AudioAlbum,
141    AudioSingle,
142    VideoAlbum,
143    VideoSingle,
144    Mixed,
145}
146
147/// Validation rule types
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub enum ValidationRule {
150    Required,
151    MinLength(usize),
152    MaxLength(usize),
153    Pattern(String),
154    OneOf(Vec<String>),
155    AudioQuality { min_bit_depth: u8, min_sample_rate: u32 },
156    TerritoryCode { allowed: Vec<String> },
157    Custom(String),
158}
159
160/// Enhanced preset configuration with validation rules
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct PresetConfig {
163    pub version: DdexVersion,
164    pub profile: MessageProfile,
165    pub required_fields: Vec<String>,
166    pub validation_rules: IndexMap<String, ValidationRule>,
167    pub default_values: IndexMap<String, String>,
168    pub custom_mappings: IndexMap<String, String>,
169    pub territory_codes: Vec<String>,
170    pub distribution_channels: Vec<String>,
171    pub release_types: Vec<String>,
172}
173
174/// Partner preset configuration (legacy structure, enhanced)
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct PartnerPreset {
177    pub name: String,
178    pub description: String,
179    pub source: PresetSource,
180    pub provenance_url: Option<String>,
181    pub version: String,
182    pub locked: bool,
183    pub disclaimer: String,
184    pub determinism: super::determinism::DeterminismConfig,
185    pub defaults: PresetDefaults,
186    pub required_fields: Vec<String>,
187    pub format_overrides: IndexMap<String, String>,
188    // Enhanced fields
189    pub config: PresetConfig,
190    pub validation_rules: IndexMap<String, ValidationRule>,
191    pub custom_mappings: IndexMap<String, String>,
192}
193
194/// Preset source
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
196pub enum PresetSource {
197    PublicDocs,
198    CustomerFeedback,
199    Community,
200}
201
202/// Preset defaults
203#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct PresetDefaults {
205    pub message_control_type: Option<String>,
206    pub territory_code: Vec<String>,
207    pub distribution_channel: Vec<String>,
208}
209
210
211
212/// Get all built-in presets
213/// 
214/// Returns a collection of community-maintained DDEX configuration presets.
215/// These presets provide baseline DDEX-compliant configurations and platform-specific
216/// templates based on publicly available documentation.
217pub fn all_presets() -> IndexMap<String, PartnerPreset> {
218    let mut presets = IndexMap::new();
219    
220    // Generic industry-standard presets
221    presets.extend(generic::all_generic_presets());
222    
223    // Platform presets (based on public documentation)
224    presets.extend(youtube::all_youtube_presets());
225    
226    presets
227}