Skip to main content

camel_component_validator/
config.rs

1use std::path::{Path, PathBuf};
2
3use camel_component_api::CamelError;
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum SchemaType {
7    Xml,
8    Json,
9    Yaml,
10}
11
12#[derive(Debug, Clone)]
13pub struct ValidatorConfig {
14    pub schema_path: PathBuf,
15    pub schema_type: SchemaType,
16}
17
18impl ValidatorConfig {
19    pub fn from_uri(uri: &str) -> Result<Self, CamelError> {
20        let without_scheme = uri.strip_prefix("validator:").ok_or_else(|| {
21            CamelError::EndpointCreationFailed(format!(
22                "invalid validator URI: must start with 'validator:' — got '{uri}'"
23            ))
24        })?;
25
26        let (path_str, query) = match without_scheme.find('?') {
27            Some(idx) => (&without_scheme[..idx], Some(&without_scheme[idx + 1..])),
28            None => (without_scheme, None),
29        };
30
31        if path_str.is_empty() {
32            return Err(CamelError::EndpointCreationFailed(
33                "validator URI must specify a schema path".to_string(),
34            ));
35        }
36
37        let schema_path = PathBuf::from(path_str);
38
39        let schema_type = if let Some(q) = query {
40            let type_val = q.split('&').find_map(|kv| kv.strip_prefix("type="));
41            match type_val {
42                Some("xml") | Some("xml-schema") | Some("xsd") => SchemaType::Xml,
43                Some("json") | Some("json-schema") => SchemaType::Json,
44                Some("yaml") | Some("yaml-schema") => SchemaType::Yaml,
45                Some(other) => {
46                    return Err(CamelError::EndpointCreationFailed(format!(
47                        "unknown schema type '{other}'; expected xml, json, or yaml"
48                    )));
49                }
50                None => detect_type_from_extension(&schema_path)?,
51            }
52        } else {
53            detect_type_from_extension(&schema_path)?
54        };
55
56        Ok(ValidatorConfig {
57            schema_path,
58            schema_type,
59        })
60    }
61}
62
63fn detect_type_from_extension(path: &Path) -> Result<SchemaType, CamelError> {
64    match path.extension().and_then(|e| e.to_str()) {
65        Some("xsd") => Ok(SchemaType::Xml),
66        Some("json") => Ok(SchemaType::Json),
67        Some("yaml") | Some("yml") => Ok(SchemaType::Yaml),
68        ext => Err(CamelError::EndpointCreationFailed(format!(
69            "cannot infer schema type from extension {ext:?}; use ?type=xml|json|yaml"
70        ))),
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn detects_xml_from_xsd_extension() {
80        let cfg = ValidatorConfig::from_uri("validator:schemas/order.xsd").unwrap();
81        assert_eq!(cfg.schema_path, PathBuf::from("schemas/order.xsd"));
82        assert_eq!(cfg.schema_type, SchemaType::Xml);
83    }
84
85    #[test]
86    fn detects_json_from_json_extension() {
87        let cfg = ValidatorConfig::from_uri("validator:schemas/order.json").unwrap();
88        assert_eq!(cfg.schema_type, SchemaType::Json);
89    }
90
91    #[test]
92    fn detects_yaml_from_yaml_extension() {
93        let cfg = ValidatorConfig::from_uri("validator:schemas/order.yaml").unwrap();
94        assert_eq!(cfg.schema_type, SchemaType::Yaml);
95    }
96
97    #[test]
98    fn detects_yaml_from_yml_extension() {
99        let cfg = ValidatorConfig::from_uri("validator:schemas/order.yml").unwrap();
100        assert_eq!(cfg.schema_type, SchemaType::Yaml);
101    }
102
103    #[test]
104    fn type_param_overrides_extension() {
105        let cfg = ValidatorConfig::from_uri("validator:schemas/order.xsd?type=json").unwrap();
106        assert_eq!(cfg.schema_type, SchemaType::Json);
107    }
108
109    #[test]
110    fn wrong_scheme_errors() {
111        assert!(ValidatorConfig::from_uri("timer:tick").is_err());
112    }
113
114    #[test]
115    fn empty_path_errors() {
116        assert!(ValidatorConfig::from_uri("validator:").is_err());
117    }
118
119    #[test]
120    fn unknown_type_param_errors() {
121        assert!(ValidatorConfig::from_uri("validator:schema.xsd?type=csv").is_err());
122    }
123
124    #[test]
125    fn no_extension_no_type_param_errors() {
126        assert!(ValidatorConfig::from_uri("validator:schema").is_err());
127    }
128}