use crate::cache::TemplateConfigurationFactory;
use crate::cache::TemplateConfigurationFactoryException;
use crate::core::TemplateConfiguration;
use std::sync::Arc;
pub struct FirstMatchTemplateConfigurationFactory {
factories: Vec<Box<dyn TemplateConfigurationFactory>>,
allow_no_match: bool,
no_match_error_details: Option<String>,
}
impl FirstMatchTemplateConfigurationFactory {
pub fn new(factories: Vec<Box<dyn TemplateConfigurationFactory>>) -> Self {
FirstMatchTemplateConfigurationFactory {
factories,
allow_no_match: false,
no_match_error_details: None,
}
}
pub fn get_allow_no_match(&self) -> bool {
self.allow_no_match
}
pub fn set_allow_no_match(&mut self, allow_no_match: bool) {
self.allow_no_match = allow_no_match;
}
pub fn get_no_match_error_details(&self) -> Option<&str> {
self.no_match_error_details.as_deref()
}
pub fn set_no_match_error_details(&mut self, no_match_error_details: String) {
self.no_match_error_details = Some(no_match_error_details);
}
pub fn allow_no_match(mut self, allow: bool) -> Self {
self.set_allow_no_match(allow);
self
}
pub fn no_match_error_details(mut self, message: String) -> Self {
self.set_no_match_error_details(message);
self
}
}
impl TemplateConfigurationFactory for FirstMatchTemplateConfigurationFactory {
fn get(
&self,
source_name: &str,
) -> Result<Option<Arc<TemplateConfiguration>>, TemplateConfigurationFactoryException> {
for f in &self.factories {
if let Some(tc) = f.get(source_name)? {
return Ok(Some(tc));
}
}
if !self.allow_no_match {
return Err(TemplateConfigurationFactoryException(format!(
"FirstMatchTemplateConfigurationFactory has found no matching choice for source name \"{source_name}\". {}",
match &self.no_match_error_details {
Some(d) => format!("Error details: {d}"),
None => "(Set the noMatchErrorDetails property of the factory bean to give a more specific error message. Set allowNoMatch to true if this shouldn't be an error.)".to_string(),
}
)));
}
Ok(None)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cache::ConditionalTemplateConfigurationFactory;
use crate::cache::FileExtensionMatcher;
#[test]
fn first_match_and_no_match_error() {
let cfg = Arc::new(TemplateConfiguration::default());
let cond = ConditionalTemplateConfigurationFactory::with_configuration(
Box::new(FileExtensionMatcher::new("ftl")),
cfg.clone(),
);
let first =
FirstMatchTemplateConfigurationFactory::new(vec![Box::new(cond)]).allow_no_match(true);
assert!(first.get("a.ftl").unwrap().is_some());
assert!(first.get("a.txt").unwrap().is_none()); let first = FirstMatchTemplateConfigurationFactory::new(vec![Box::new(
ConditionalTemplateConfigurationFactory::with_configuration(
Box::new(FileExtensionMatcher::new("ftl")),
cfg,
),
)])
.no_match_error_details("nope".to_string());
let err = first.get("a.txt").unwrap_err();
assert!(err.0.contains("FirstMatchTemplateConfigurationFactory has found no matching choice for source name \"a.txt\""), "{}", err.0);
assert!(err.0.contains("Error details: nope"), "{}", err.0);
}
}