2024-02-06 10:17:14 +01:00
|
|
|
use serde::Deserialize;
|
|
|
|
use std::fs;
|
|
|
|
use std::path::Path;
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use crate::law::{self, responsible::*};
|
|
|
|
use crate::law::{ClassifierApplicable, LawBuilder};
|
|
|
|
use crate::misc::Error;
|
2024-02-06 11:45:44 +01:00
|
|
|
use crate::paragraph::Parser;
|
2024-02-06 10:17:14 +01:00
|
|
|
|
|
|
|
// TODO: more generic
|
|
|
|
fn create_classifier(match_function: &str) -> Result<ClassifierApplicable, Error> {
|
|
|
|
let func: ClassifierApplicable = match match_function {
|
|
|
|
"contains" => Arc::new(contains),
|
|
|
|
"starts_with_roman_number" => Arc::new(starts_with_roman_number),
|
|
|
|
"contains_at_start" => Arc::new(contains_at_start),
|
|
|
|
"starts_with_number" => Arc::new(starts_with_number),
|
|
|
|
"starts_with_letter" => Arc::new(starts_with_letter),
|
2024-02-06 13:10:59 +01:00
|
|
|
"starts_with_dash" => Arc::new(starts_with_dash),
|
|
|
|
"starts_with_uppercaseletter" => Arc::new(starts_with_uppercaseletter),
|
2024-02-06 10:17:14 +01:00
|
|
|
"contains_without_unter" => Arc::new(contains_without_unter),
|
|
|
|
_ => {
|
|
|
|
return Err(Error::new(&format!(
|
|
|
|
"Unknown match function: {}",
|
|
|
|
match_function
|
|
|
|
)))
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(func)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
pub struct Config {
|
|
|
|
law: Law,
|
2024-02-06 11:18:40 +01:00
|
|
|
#[serde(default)]
|
2024-02-06 10:17:14 +01:00
|
|
|
parser: ParserConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Config {
|
|
|
|
pub fn load<P: AsRef<Path>>(path: P) -> Result<(usize, LawBuilder, Parser), Error> {
|
|
|
|
let config_str = fs::read_to_string(path)?;
|
|
|
|
let config: Config = toml::from_str(&config_str)?;
|
|
|
|
|
|
|
|
let mut builder = LawBuilder::new();
|
|
|
|
for classifier in config.law.classifiers {
|
|
|
|
let to_add = law::Classifier::new(
|
|
|
|
&classifier.name,
|
|
|
|
create_classifier(&classifier.match_function)?,
|
|
|
|
);
|
|
|
|
if classifier.is_root {
|
|
|
|
builder.add_classifier(to_add.root());
|
|
|
|
} else {
|
|
|
|
builder.add_classifier(to_add);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut parser = Parser::new();
|
|
|
|
|
|
|
|
for to_remove in config.parser.remove_strings {
|
|
|
|
parser.add_string_to_remove(&to_remove);
|
|
|
|
}
|
|
|
|
|
|
|
|
for to_replace in config.parser.replace_rules {
|
|
|
|
parser.add_string_to_replace(&to_replace.find, &to_replace.replace_with);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok((config.law.id, builder, parser))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
struct Law {
|
|
|
|
id: usize,
|
|
|
|
classifiers: Vec<Classifier>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
struct Classifier {
|
|
|
|
name: String,
|
|
|
|
is_root: bool,
|
|
|
|
match_function: String,
|
|
|
|
}
|
|
|
|
|
2024-02-06 11:18:40 +01:00
|
|
|
#[derive(Debug, Deserialize, Default)]
|
2024-02-06 10:17:14 +01:00
|
|
|
struct ParserConfig {
|
2024-02-06 11:18:40 +01:00
|
|
|
#[serde(default)] //okay to not have this part in the config
|
2024-02-06 10:17:14 +01:00
|
|
|
remove_strings: Vec<String>,
|
2024-02-06 11:18:40 +01:00
|
|
|
#[serde(default)] //okay to not have this part in the config
|
2024-02-06 10:17:14 +01:00
|
|
|
replace_rules: Vec<ReplaceRule>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
struct ReplaceRule {
|
|
|
|
find: String,
|
|
|
|
replace_with: String,
|
|
|
|
}
|
2024-02-06 11:18:40 +01:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use std::fs;
|
|
|
|
|
|
|
|
use super::Config;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn all_configs_are_deserializable() {
|
|
|
|
let configs = fs::read_dir("./data/configs").expect("No folder with config files");
|
|
|
|
|
|
|
|
for config in configs {
|
|
|
|
let path = format!("{}", config.unwrap().path().display());
|
|
|
|
Config::load(&path).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|