diff --git a/data/configs/kschg.toml b/data/configs/kschg.toml new file mode 100644 index 0000000..a856e90 --- /dev/null +++ b/data/configs/kschg.toml @@ -0,0 +1,15 @@ +[law] +id = 10002462 + +[[law.classifiers]] +name = "Hauptstück" +is_root = true +match_function = "contains" + +[[law.classifiers]] +name = "Abschnitt" +is_root = false +match_function = "contains" + +[parser] +remove_strings = ["", ""] diff --git a/data/configs/mschg.toml b/data/configs/mschg.toml index db3f0f0..bfd1a89 100644 --- a/data/configs/mschg.toml +++ b/data/configs/mschg.toml @@ -1,21 +1,19 @@ [law] -id = "10002180" +id = 10002180 [[law.classifiers]] name = "Abschnitt" +is_root = true match_function = "contains" [[law.classifiers]] name = "Number" +is_root = false match_function = "starts_with_number" [parser] remove_strings = ["", ""] -[[parser.replace_rules]] -find = "\\u{a0}" -replace_with = " " - [[parser.replace_rules]] find = "bis" replace_with = "bis" diff --git a/data/configs/stgb.toml b/data/configs/stgb.toml new file mode 100644 index 0000000..c663955 --- /dev/null +++ b/data/configs/stgb.toml @@ -0,0 +1,47 @@ +[law] +id = 10002296 + +[[law.classifiers]] +name = "Teil" +is_root = true +match_function = "contains" + +[[law.classifiers]] +name = "Abschnitt" +is_root = false +match_function = "contains" + +[parser] +remove_strings = [ + "", "", + "", "", + "", "", + "", "", + """""" +] + +[[parser.replace_rules]] +find = """Allgemeine Bestimmungen""" +replace_with = """Allgemeine Bestimmungen""" + +[[parser.replace_rules]] +find = """1. Verwertungsrechte.""" +replace_with = """1. Verwertungsrechte.""" + + +[[parser.replace_rules]] +find = """(3) Die Verjährungsfrist beträgtzwanzig Jahre,wenn die Handlung zwar nicht mit lebenslanger Freiheitsstrafe, aber mit mehr als zehnjähriger Freiheitsstrafe bedroht ist;zehn Jahre,wenn die Handlung mit mehr als fünfjähriger, aber höchstens zehnjähriger Freiheitsstrafe bedroht ist;fünf Jahre,wenn die Handlung mit mehr als einjähriger, aber höchstens fünfjähriger Freiheitsstrafe bedroht ist;drei Jahre,wenn die Handlung mit mehr als sechsmonatiger, aber höchstens einjähriger Freiheitsstrafe bedroht ist;ein Jahr,wenn die Handlung mit nicht mehr als sechsmonatiger Freiheitsstrafe oder nur mit Geldstrafe bedroht ist.""" +replace_with = """(3) Die Verjährungsfrist beträgt zwanzig Jahre, wenn die Handlung zwar nicht mit lebenslanger Freiheitsstrafe, aber mit mehr als zehnjähriger Freiheitsstrafe bedroht ist; zehn Jahre, wenn die Handlung mit mehr als fünfjähriger, aber höchstens zehnjähriger Freiheitsstrafe bedroht ist; fünf Jahre, wenn die Handlung mit mehr als einjähriger, aber höchstens fünfjähriger Freiheitsstrafe bedroht ist; drei Jahre, wenn die Handlung mit mehr als sechsmonatiger, aber höchstens einjähriger Freiheitsstrafe bedroht ist; ein Jahr, wenn die Handlung mit nicht mehr als sechsmonatiger Freiheitsstrafe oder nur mit Geldstrafe bedroht ist.""" + +[[parser.replace_rules]] +find = """(3) Die Frist beträgtfünfzehn Jahre,wenn auf Freiheitsstrafe von mehr als einem Jahr, aber nicht mehr als zehn Jahren erkannt worden ist;zehn Jahre,wenn auf Freiheitsstrafe von mehr als drei Monaten, aber nicht mehr als einem Jahr oder auf eine Geldstrafe unter Festsetzung einer Ersatzfreiheitsstrafe von mehr als drei Monaten erkannt worden ist;fünf Jahrein allen übrigen Fällen.""" +replace_with = """(3) Die Frist beträgt fünfzehn Jahre, wenn auf Freiheitsstrafe von mehr als einem Jahr, aber nicht mehr als zehn Jahren erkannt worden ist; zehn Jahre, wenn auf Freiheitsstrafe von mehr als drei Monaten, aber nicht mehr als einem Jahr oder auf eine Geldstrafe unter Festsetzung einer Ersatzfreiheitsstrafe von mehr als drei Monaten erkannt worden ist; fünf Jahre in allen übrigen Fällen.""" + +[[parser.replace_rules]] +find = """Strafbare Handlungen gegen Leib und Leben""" +replace_with = """Strafbare Handlungen gegen Leib und Leben""" + +[[parser.replace_rules]] +find = "" +replace_with = "-" + diff --git a/data/configs/teg.toml b/data/configs/teg.toml new file mode 100644 index 0000000..4b36039 --- /dev/null +++ b/data/configs/teg.toml @@ -0,0 +1,19 @@ +[law] +id = 10001905 + +[[law.classifiers]] +name = "Abschnitt" +is_root = true +match_function = "contains" + +[parser] +remove_strings = [ + """(§§ 1, 2, 3, 4,6, § 8 Abs. 1 und 2 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)""", + """(§§ 1 bis 11 des Gesetzes über die Verschollenheit, die Todeserklärung und die Feststellung der Todeszeit vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)""", + """(§ 56 Abs. 3 des Gesetzes vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)""", + """(§ 10 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)""", + """(§§ 10a, 10b und 10c des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)""", + "", + "" +] + diff --git a/data/configs/urhg.toml b/data/configs/urhg.toml new file mode 100644 index 0000000..a12673d --- /dev/null +++ b/data/configs/urhg.toml @@ -0,0 +1,29 @@ +[law] +id = 10001848 + +[[law.classifiers]] +name = "Hauptstück" +is_root = true +match_function = "contains" + +[[law.classifiers]] +name = "Abschnitt" +is_root = false +match_function = "contains" + +[[law.classifiers]] +name = "Number" +is_root = false +match_function = "starts_with_number" + +[[parser.replace_rules]] +find = "." +replace_with = "." + +[[parser.replace_rules]] +find = "" +replace_with = "-" + +[[parser.replace_rules]] +find = """(2) Einer Rundfunksendung steht es gleich, wenn ein Werk von einer im In- oder im Ausland gelegenen Stelle aus der Öffentlichkeit im Inland, ähnlich wie durch Rundfunk, aber mit Hilfe von Leitungen wahrnehmbar gemacht wird.""" +replace_with = """(2) Einer Rundfunksendung steht es gleich, wenn ein Werk von einer im In- oder im Ausland gelegenen Stelle aus der Öffentlichkeit im Inland, ähnlich wie durch Rundfunk, aber mit Hilfe von Leitungen wahrnehmbar gemacht wird.""" diff --git a/data/configs/vvg.toml b/data/configs/vvg.toml new file mode 100644 index 0000000..5de77ea --- /dev/null +++ b/data/configs/vvg.toml @@ -0,0 +1,7 @@ +[law] +id = 20011654 + +[[law.classifiers]] +name = "Abschnitt" +is_root = true +match_function = "contains" diff --git a/src/config.rs b/src/config.rs index a0dc3d4..242a8ed 100644 --- a/src/config.rs +++ b/src/config.rs @@ -32,6 +32,7 @@ fn create_classifier(match_function: &str) -> Result, + #[serde(default)] //okay to not have this part in the config replace_rules: Vec, } @@ -91,3 +94,20 @@ struct ReplaceRule { find: String, replace_with: String, } + +#[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(); + } + } +} diff --git a/src/risparser/paragraph/mod.rs b/src/risparser/paragraph/mod.rs index 8560a6f..b003b5a 100644 --- a/src/risparser/paragraph/mod.rs +++ b/src/risparser/paragraph/mod.rs @@ -33,6 +33,8 @@ impl Parser { info!("Parsing {url}"); let xml = fetch(url)?; + let xml = xml.replace("\u{a0}", " "); + self.parse_from_str(&xml, builder) } @@ -85,6 +87,7 @@ mod tests { use std::{fs, sync::Arc}; use crate::{ + config::Config, law::{ responsible::{contains, starts_with_number}, Classifier, LawBuilder, @@ -93,55 +96,6 @@ mod tests { }; use pretty_assertions::assert_eq; - // TODO: Instead of specific test cases, use this general method once there is a nice way to - // add classifiers + custom removals/edits of law texts - // - //#[test] - //fn paragraph() { - // let laws = fs::read_dir("./data/expected/overview/") - // .expect("No folder with expected overview files"); - - // for law in laws { - // let path = law.unwrap(); - // let law_path = format!("{}", path.path().display()); - // let law_id = path.file_name().into_string().unwrap().to_string(); - - // //TODO: Remove this if once all law texts pass - // if ["10001905".into()].contains(&law_id) { - // let expected_path = format!("./data/expected/par/{law_id}"); - - // let pars = fs::read_to_string(law_path).expect("Could not read file {file_path}."); - // let pars = pars.trim().split('\n').collect::>(); - - // let mut builder = LawBuilder::new("law"); - // builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains)).root()); - - // let mut parser = Parser::new(); - // parser.add_string_to_remove(r#"(§§ 1, 2, 3, 4,6, § 8 Abs. 1 und 2 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)"#); - // parser.add_string_to_remove(r#"(§§ 1 bis 11 des Gesetzes über die Verschollenheit, die Todeserklärung und die Feststellung der Todeszeit vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)"#); - // parser.add_string_to_remove(r#"(§ 56 Abs. 3 des Gesetzes vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)"#); - // parser.add_string_to_remove(r#"(§ 10 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)"#); - // parser.add_string_to_remove(r#"(§§ 10a, 10b und 10c des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)"#); - // parser.add_string_to_remove(""); - // parser.add_string_to_remove(""); - // for par in pars { - // let cont = parser.parse(par, &mut builder).unwrap(); - // if !cont { - // break; - // } - // } - - // let actual = builder.history; - - // let expected = fs::read_to_string(&expected_path) - // .expect(&format!("Could not read file {expected_path}.")); - // let expected = expected.trim().split('\n').collect::>(); - - // assert_eq!(actual, expected); - // } - // } - //} - fn test(law_id: &str, builder: &mut LawBuilder, parser: Parser) { let paragraph_path = format!("./data/expected/overview/{law_id}"); let expected_path = format!("./data/expected/par/{law_id}"); @@ -170,136 +124,36 @@ mod tests { } #[test] - fn teg() { - let law_id = "10001905"; - let mut builder = LawBuilder::new(); - builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains)).root()); + fn all_configs_produce_expected_output() { + let configs = fs::read_dir("./data/configs").expect("No folder with config files"); - let mut parser = Parser::new(); - parser.add_string_to_remove(r#"(§§ 1, 2, 3, 4,6, § 8 Abs. 1 und 2 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)"#); - parser.add_string_to_remove(r#"(§§ 1 bis 11 des Gesetzes über die Verschollenheit, die Todeserklärung und die Feststellung der Todeszeit vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)"#); - parser.add_string_to_remove(r#"(§ 56 Abs. 3 des Gesetzes vom 4. Juli 1939, Deutsches RGBl. I S. 1186:)"#); - parser.add_string_to_remove(r#"(§ 10 des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)"#); - parser.add_string_to_remove(r#"(§§ 10a, 10b und 10c des Gesetzes vom 16. Februar 1883, RGBl. Nr. 20, betreffend das Verfahren zum Zwecke der Todeserklärung und der Beweisführung des Todes, in der Fassung des Gesetzes vom 31. März 1918, RGBl. Nr. 129:)"#); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); + for config in configs { + let path = format!("{}", config.unwrap().path().display()); - test(law_id, &mut builder, parser); + let (law_id, mut builder, parser) = Config::load(&path).unwrap(); + + let paragraph_path = format!("./data/expected/overview/{law_id}"); + let expected_path = format!("./data/expected/par/{law_id}"); + + let pars = + fs::read_to_string(paragraph_path).expect("Could not read file {paragraph_path}."); + let pars = pars.trim().split('\n').collect::>(); + + for par in pars { + println!("{par}"); + let cont = parser.parse(par, &mut builder).unwrap(); + if !cont { + break; + } + } + + let actual = &builder.history; + + let expected = fs::read_to_string(&expected_path) + .expect(&format!("Could not read file {expected_path}.")); + let expected = expected.trim().split('\n').collect::>(); + + assert_eq!(actual, &expected); + } } - - #[test] - fn mschg() { - let law_id = "10002180"; - let mut builder = LawBuilder::new(); - builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains)).root()); - builder.add_classifier(Classifier::new("Number", Arc::new(&starts_with_number))); - - let mut parser = Parser::new(); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - - parser.add_string_to_replace("\u{a0}", " "); - parser.add_string_to_replace("bis", "bis"); - parser.add_string_to_replace("ter", "ter"); - parser.add_string_to_replace("", "-"); - parser.add_string_to_replace( - "(Anm.: § 69 aufgehoben durch Art. 1 Z 12, BGBl. I Nr. 124/2017)", - "§ 69.(Anm.: § 69 aufgehoben durch Art. 1 Z 12, BGBl. I Nr. 124/2017)", - ); - - test(law_id, &mut builder, parser); - } - - #[test] - fn stgb() { - let law_id = "10002296"; - let mut builder = LawBuilder::new(); - builder.add_classifier(Classifier::new("Teil", Arc::new(&contains)).root()); - builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains))); - - let mut parser = Parser::new(); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - parser.add_string_to_remove(r#""#); - - parser.add_string_to_replace("\u{a0}", " "); - parser.add_string_to_replace( - r#"Allgemeine Bestimmungen"#, - r#"Allgemeine Bestimmungen"# - ); - parser.add_string_to_replace( - r#"1. Verwertungsrechte."#, - r#"1. Verwertungsrechte."#, - ); - parser.add_string_to_replace( - r#"(3) Die Verjährungsfrist beträgtzwanzig Jahre,wenn die Handlung zwar nicht mit lebenslanger Freiheitsstrafe, aber mit mehr als zehnjähriger Freiheitsstrafe bedroht ist;zehn Jahre,wenn die Handlung mit mehr als fünfjähriger, aber höchstens zehnjähriger Freiheitsstrafe bedroht ist;fünf Jahre,wenn die Handlung mit mehr als einjähriger, aber höchstens fünfjähriger Freiheitsstrafe bedroht ist;drei Jahre,wenn die Handlung mit mehr als sechsmonatiger, aber höchstens einjähriger Freiheitsstrafe bedroht ist;ein Jahr,wenn die Handlung mit nicht mehr als sechsmonatiger Freiheitsstrafe oder nur mit Geldstrafe bedroht ist."#, - r#"(3) Die Verjährungsfrist beträgt zwanzig Jahre, wenn die Handlung zwar nicht mit lebenslanger Freiheitsstrafe, aber mit mehr als zehnjähriger Freiheitsstrafe bedroht ist; zehn Jahre, wenn die Handlung mit mehr als fünfjähriger, aber höchstens zehnjähriger Freiheitsstrafe bedroht ist; fünf Jahre, wenn die Handlung mit mehr als einjähriger, aber höchstens fünfjähriger Freiheitsstrafe bedroht ist; drei Jahre, wenn die Handlung mit mehr als sechsmonatiger, aber höchstens einjähriger Freiheitsstrafe bedroht ist; ein Jahr, wenn die Handlung mit nicht mehr als sechsmonatiger Freiheitsstrafe oder nur mit Geldstrafe bedroht ist."#, - ); - - parser.add_string_to_replace( - r#"(3) Die Frist beträgtfünfzehn Jahre,wenn auf Freiheitsstrafe von mehr als einem Jahr, aber nicht mehr als zehn Jahren erkannt worden ist;zehn Jahre,wenn auf Freiheitsstrafe von mehr als drei Monaten, aber nicht mehr als einem Jahr oder auf eine Geldstrafe unter Festsetzung einer Ersatzfreiheitsstrafe von mehr als drei Monaten erkannt worden ist;fünf Jahrein allen übrigen Fällen."#, - r#"(3) Die Frist beträgt fünfzehn Jahre, wenn auf Freiheitsstrafe von mehr als einem Jahr, aber nicht mehr als zehn Jahren erkannt worden ist; zehn Jahre, wenn auf Freiheitsstrafe von mehr als drei Monaten, aber nicht mehr als einem Jahr oder auf eine Geldstrafe unter Festsetzung einer Ersatzfreiheitsstrafe von mehr als drei Monaten erkannt worden ist; fünf Jahre in allen übrigen Fällen."#, - ); - parser.add_string_to_replace("\u{a0}", " "); - parser.add_string_to_replace( - r#"Strafbare Handlungen gegen Leib und Leben"#, - r#"Strafbare Handlungen gegen Leib und Leben"#, - ); - parser.add_string_to_replace("", "-"); - - test(law_id, &mut builder, parser); - } - - #[test] - fn kschg() { - let law_id = "10002462"; - let mut builder = LawBuilder::new(); - builder.add_classifier(Classifier::new("Hauptstück", Arc::new(&contains)).root()); - builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains))); - - let mut parser = Parser::new(); - parser.add_string_to_remove(""); - parser.add_string_to_remove(""); - - test(law_id, &mut builder, parser); - } - - #[test] - fn vvg() { - let law_id = "20011654"; - let mut builder = LawBuilder::new(); - builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains)).root()); - - let parser = Parser::new(); - - test(law_id, &mut builder, parser); - } - #[test] - fn urhg() { - let law_id = "10001848"; - let mut builder = LawBuilder::new(); - builder.add_classifier(Classifier::new("Hauptstück", Arc::new(&contains)).root()); - builder.add_classifier(Classifier::new("Abschnitt", Arc::new(&contains))); - builder.add_classifier(Classifier::new("Number", Arc::new(&starts_with_number))); - - let mut parser = Parser::new(); - parser.add_string_to_replace(".", "."); - parser.add_string_to_replace("", "-"); - parser.add_string_to_replace( - r#"(2) Einer Rundfunksendung steht es gleich, wenn ein Werk von einer im In- oder im Ausland gelegenen Stelle aus der Öffentlichkeit im Inland, ähnlich wie durch Rundfunk, aber mit Hilfe von Leitungen wahrnehmbar gemacht wird."#, - r#"(2) Einer Rundfunksendung steht es gleich, wenn ein Werk von einer im In- oder im Ausland gelegenen Stelle aus der Öffentlichkeit im Inland, ähnlich wie durch Rundfunk, aber mit Hilfe von Leitungen wahrnehmbar gemacht wird."#, - ); - parser.add_string_to_replace("\u{a0}", " "); - - test(law_id, &mut builder, parser); - } - - // TODO: 10001622(ABGB) - // https://www.ris.bka.gv.at/GeltendeFassung.wxe?Abfrage=Bundesnormen&Gesetzesnummer=10002180 }