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