This commit is contained in:
philipp 2023-11-06 10:44:59 +01:00
parent f30d93844f
commit fdbabb8b9d
3 changed files with 172 additions and 122 deletions

View File

@ -71,7 +71,7 @@ impl From<LawBuilder> for Law {
} }
} }
fn contains(classifier_name: &str, instance_name: &str) -> bool { pub(crate) fn contains(classifier_name: &str, instance_name: &str) -> bool {
instance_name instance_name
.to_lowercase() .to_lowercase()
.contains(&classifier_name.to_lowercase()) .contains(&classifier_name.to_lowercase())
@ -85,41 +85,25 @@ fn starts_with_number(_classifier_name: &str, instance_name: &str) -> bool {
} }
/// Is used to generate a law struct. It's organized mainly by classifier. /// Is used to generate a law struct. It's organized mainly by classifier.
#[derive(Debug)] #[derive(Debug, PartialEq)]
pub(crate) struct LawBuilder { pub(crate) struct LawBuilder {
/// Name of the law /// Name of the law
name: String, //ABGB, UrhG pub(crate) name: String, //ABGB, UrhG
/// Structure of the law text /// Structure of the law text
classifiers: Vec<Classifier>, pub(crate) classifiers: Vec<Classifier>,
last_header_index: Option<usize>, pub(crate) last_header_index: Option<usize>,
/// Stores the header of the next paragraph /// Stores the header of the next paragraph
next_para_header: Option<String>, pub(crate) next_para_header: Option<String>,
} }
impl LawBuilder { impl LawBuilder {
#[cfg(test)] #[cfg(test)]
pub(crate) fn test(name: &str) -> Self { pub(crate) fn test(name: &str) -> Self {
let mut last_header_index = None;
let mut classifiers = Vec::new(); let mut classifiers = Vec::new();
//if name == "UrhG" {
// let hauptstueck = Classifier::new("Hauptstück", Arc::new(&contains));
// classifiers.push(hauptstueck.clone());
// let mut abschnitt = Classifier::new("Abschnitt", Arc::new(&contains));
// abschnitt.set_parent(&hauptstueck);
// classifiers.push(abschnitt.clone());
// let mut numbered_header =
// Classifier::new("Numbered Header", Arc::new(&starts_with_number));
// numbered_header.set_parent(&abschnitt);
// classifiers.push(numbered_header);
//} else if name == "no-headers" {
// let mut class = Classifier::new("", Arc::new(&contains));
// class.add_instance(ClassifierInstance::new(""));
// classifiers.push(class);
//} else
if name == "test" { if name == "test" {
let h1 = Classifier::new("h1", Arc::new(&contains)); let h1 = Classifier::new("h1", Arc::new(&contains));
classifiers.push(h1); classifiers.push(h1);
@ -131,12 +115,17 @@ impl LawBuilder {
let mut h3 = Classifier::new("h3", Arc::new(&contains)); let mut h3 = Classifier::new("h3", Arc::new(&contains));
h3.set_parent(1); h3.set_parent(1);
classifiers.push(h3); classifiers.push(h3);
} else if name == "no-headers" {
let mut h1 = Classifier::new("", Arc::new(&contains));
h1.add_instance(ClassifierInstance::new("", 0));
last_header_index = Some(0);
classifiers.push(h1);
} }
Self { Self {
name: name.into(), name: name.into(),
classifiers, classifiers,
next_para_header: None, next_para_header: None,
last_header_index: None, last_header_index,
} }
} }
@ -284,19 +273,19 @@ impl LawBuilder {
} }
} }
#[derive(Clone)] #[derive(Clone, Debug, PartialEq)]
pub(crate) struct Section { pub(crate) struct Section {
symb: String, // §"1", §"2", ... pub(crate) symb: String, // §"1", §"2", ...
par_header: Option<String>, pub(crate) par_header: Option<String>,
content: Content, pub(crate) content: Content,
} }
impl fmt::Debug for Section { //impl fmt::Debug for Section {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let par_header = self.par_header.as_ref().map(String::as_str).unwrap_or(""); // let par_header = self.par_header.as_ref().map(String::as_str).unwrap_or("");
write!(f, "{} ({})", self.symb, par_header) // write!(f, "{} ({})", self.symb, par_header)
} // }
} //}
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct Header { pub(crate) struct Header {
@ -319,13 +308,13 @@ impl Header {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub(crate) struct ClassifierInstance { pub(crate) struct ClassifierInstance {
name: String, pub(crate) name: String,
desc: Option<String>, pub(crate) desc: Option<String>,
sections: Vec<Section>, pub(crate) sections: Vec<Section>,
parent: Option<Box<ClassifierInstance>>, pub(crate) parent: Option<Box<ClassifierInstance>>,
idx: usize, pub(crate) idx: usize,
} }
impl ClassifierInstance { impl ClassifierInstance {
@ -354,10 +343,18 @@ impl ClassifierInstance {
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct Classifier { pub(crate) struct Classifier {
name: String, // Hauptstück, Theil, Abschnitt, ol pub(crate) name: String, // Hauptstück, Theil, Abschnitt, ol
parent_index: Option<usize>, pub(crate) parent_index: Option<usize>,
instances: Vec<ClassifierInstance>, pub(crate) instances: Vec<ClassifierInstance>,
used_for_fn: Arc<dyn Fn(&str, &str) -> bool>, pub(crate) used_for_fn: Arc<dyn Fn(&str, &str) -> bool>,
}
impl PartialEq for Classifier {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& self.parent_index == other.parent_index
&& self.instances == other.instances
}
} }
impl std::fmt::Debug for Classifier { impl std::fmt::Debug for Classifier {
@ -405,7 +402,7 @@ impl Classifier {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub(crate) enum Content { pub(crate) enum Content {
Text(String), //This is my direct law text Text(String), //This is my direct law text
Item(Vec<Box<Content>>), //(1) This is general law. (2) This is more specific law Item(Vec<Box<Content>>), //(1) This is general law. (2) This is more specific law
@ -416,23 +413,23 @@ pub(crate) enum Content {
mod tests { mod tests {
use super::*; use super::*;
#[test] //#[test]
fn atest() { //fn atest() {
let mut builder = LawBuilder::test("test"); // let mut builder = LawBuilder::test("test");
builder.new_header("h11"); // builder.new_header("h11");
builder.new_par("§11".into(), Content::Text("hi".into())); // builder.new_par("§11".into(), Content::Text("hi".into()));
builder.new_header("h21"); // builder.new_header("h21");
builder.new_header("h31"); // builder.new_header("h31");
builder.new_par("§211".into(), Content::Text("hi".into())); // builder.new_par("§211".into(), Content::Text("hi".into()));
builder.new_par("§212".into(), Content::Text("hi".into())); // builder.new_par("§212".into(), Content::Text("hi".into()));
builder.new_header("h22"); // builder.new_header("h22");
builder.new_par("§22".into(), Content::Text("hi".into())); // builder.new_par("§22".into(), Content::Text("hi".into()));
let law: Law = builder.into(); // let law: Law = builder.into();
println!("{law:#?}"); // println!("{law:#?}");
assert!(false); // assert!(false);
} //}
// #[test] // #[test]
// fn test() { // fn test() {

View File

@ -17,7 +17,7 @@ pub(crate) struct OgdSearchResult {
} }
impl OgdSearchResult { impl OgdSearchResult {
fn has_next_page(&self) -> bool { pub(crate) fn has_next_page(&self) -> bool {
let hits = &self.ogd_document_results.hits; let hits = &self.ogd_document_results.hits;
let curr_page_number = hits.page_number; let curr_page_number = hits.page_number;
let page_size = hits.page_size; let page_size = hits.page_size;

View File

@ -1,4 +1,3 @@
use log::info;
use roxmltree::Node; use roxmltree::Node;
use crate::{ use crate::{
@ -588,63 +587,117 @@ impl Layoutdaten {
} }
} }
//#[cfg(test)] #[cfg(test)]
//mod tests { mod tests {
// use std::{fs::File, io::Read}; use std::{fs::File, io::Read, sync::Arc};
//
// use log::error; use log::error;
//
// use super::*; use crate::law::{contains, Classifier, ClassifierInstance, Section};
//
// #[test] use super::*;
// fn deserialize_wucher1_success() {
// let mut file = File::open("data/par/wucher1.xml").unwrap(); #[test]
// let mut xml = String::new(); fn deserialize_wucher1_success() {
// file.read_to_string(&mut xml).unwrap(); let mut file = File::open("data/par/wucher1.xml").unwrap();
// let mut xml = String::new();
// let mut builder = LawBuilder::test("no-headers"); file.read_to_string(&mut xml).unwrap();
// let risdok = Risdok::from_str(&xml, &mut builder);
// if risdok.is_err() { let mut builder = LawBuilder::test("no-headers");
// error!("{:#?}", risdok.as_ref().err()); let risdok = Risdok::from_str(&xml, &mut builder);
// } if risdok.is_err() {
// assert!(risdok.is_ok()); error!("{:#?}", risdok.as_ref().err());
// }
// let abschnitt = risdok.unwrap().nutzdaten.abschnitt; assert!(risdok.is_ok());
// let expected = LawBuilder {
// let expected = vec![ name: "no-headers".into(),
// AbsatzAbs { classifiers: vec![
// gldsym: Some("§ 1.".into()), Classifier {
// content: "Ein Vertrag ist nichtig, wenn jemand den Leichtsinn, die Zwangslage, Verstandesschwäche, Unerfahrenheit oder Gemütsaufregung eines anderen dadurch ausbeutet, daß er sich oder einem Dritten für eine Leistung eine Gegenleistung versprechen oder gewähren läßt, deren Vermögenswert zu dem Werte seiner Leistung in auffallendem Mißverhältnis steht.".into() used_for_fn: Arc::new(&contains),
// } name: "".into(),
// ]; parent_index: None,
// assert_eq!(abschnitt.absatze, expected); instances: vec![
// } ClassifierInstance {
// name: "".into(),
// #[test] desc: None,
// fn deserialize_wucher2_success() { sections: vec![
// let mut file = File::open("data/par/wucher7.xml").unwrap(); Section {
// let mut xml = String::new(); symb: "§ 1.".into(),
// file.read_to_string(&mut xml).unwrap(); par_header: Some(
// let mut builder = LawBuilder::test("no-headers"); "Nichtigkeit eines wucherischen Vertrages.".into(),
// ),
// let risdok = Risdok::from_str(&xml, &mut builder); content: Content::Text(
// if risdok.is_err() { "Ein Vertrag ist nichtig, wenn jemand den Leichtsinn, die Zwangslage, Verstandesschwäche, Unerfahrenheit oder Gemütsaufregung eines anderen dadurch ausbeutet, daß er sich oder einem Dritten für eine Leistung eine Gegenleistung versprechen oder gewähren läßt, deren Vermögenswert zu dem Werte seiner Leistung in auffallendem Mißverhältnis steht.".into(),
// println!("{:#?}", risdok.as_ref().err()); ),
// } },
// assert!(risdok.is_ok()); ],
// parent: None,
// let abschnitt = risdok.unwrap().nutzdaten.abschnitt; idx: 0,
// },
// let expected = vec![ ],
// AbsatzAbs { },
// gldsym: Some("§ 7.".into()), ],
// content: "(1) Ist ein Vertrag nach den vorstehenden Bestimmungen nichtig, so hat jeder der beiden Teile alles zurückzustellen, was er aus dem nichtigen Geschäfte zu seinem Vorteil erhalten hat. Insbesondere sind Geldzahlungen mit den gesetzlichen Zinsen vom Empfangstage zurückzuerstatten, die übergebenen Sachen zurückzustellen oder deren Wert zur Zeit des Empfanges zu ersetzen, die auf die Sache gemachten notwendigen und nützlichen Verwendungen zu ersetzen und für die Benützung und die Entwertung der Sache in der Zwischenzeit eine angemessene Vergütung zu leisten. Ergibt sich aus der Berechnung der beiderseitigen Ansprüche ein Mehranspruch für einen der Vertragsteile, so haftet hiefür die für den vertragsmäßigen Anspruch erworbene Sicherstellung.".into() last_header_index: Some(
// }, 0,
// AbsatzAbs { ),
// gldsym: None, next_para_header: None,
// content: "(2) Ist jedoch die Gewährung oder Verlängerung von Kredit nach den vorstehenden Bestimmungen nichtig, so hat der Benachteiligte für den erhaltenen Kreditbetrag vom Empfangstag bis zur Rückzahlung sofern im Vertrag nicht eine geringere Verzinsung vorgesehen ist - Zinsen in der Höhe des Zweifachen des im Zeitpunkt der Schließung des Vertrags geltenden Basiszinssatzes zu vergüten. Er kann für die Rückzahlung des Erhaltenen die im Vertrag vorgesehenen Zahlungsfristen in Anspruch nehmen. Bestimmungen, nach denen der Benachteiligte in besonderen Fällen weitergehende Rechte hat, bleiben unberührt.".into() };
// } assert_eq!(builder, expected);
// ]; }
// assert_eq!(abschnitt.absatze, expected);
// } #[test]
//} fn deserialize_wucher2_success() {
let mut file = File::open("data/par/wucher7.xml").unwrap();
let mut xml = String::new();
file.read_to_string(&mut xml).unwrap();
let mut builder = LawBuilder::test("no-headers");
let risdok = Risdok::from_str(&xml, &mut builder);
if risdok.is_err() {
println!("{:#?}", risdok.as_ref().err());
}
assert!(risdok.is_ok());
let expected = LawBuilder {
name: "no-headers".into(),
classifiers: vec![
Classifier {
used_for_fn: Arc::new(&contains),
name: "".into(),
parent_index: None,
instances: vec![
ClassifierInstance {
name: "".into(),
desc: None,
sections: vec![
Section {
symb: "§ 7.".into(),
par_header: Some(
"Rechtsfolgen der Nichtigkeit eines wucherischen Vertrages.".into(),
),
content: Content::Item(
vec![
Box::new(Content::Text(
"(1) Ist ein Vertrag nach den vorstehenden Bestimmungen nichtig, so hat jeder der beiden Teile alles zurückzustellen, was er aus dem nichtigen Geschäfte zu seinem Vorteil erhalten hat. Insbesondere sind Geldzahlungen mit den gesetzlichen Zinsen vom Empfangstage zurückzuerstatten, die übergebenen Sachen zurückzustellen oder deren Wert zur Zeit des Empfanges zu ersetzen, die auf die Sache gemachten notwendigen und nützlichen Verwendungen zu ersetzen und für die Benützung und die Entwertung der Sache in der Zwischenzeit eine angemessene Vergütung zu leisten. Ergibt sich aus der Berechnung der beiderseitigen Ansprüche ein Mehranspruch für einen der Vertragsteile, so haftet hiefür die für den vertragsmäßigen Anspruch erworbene Sicherstellung.".into(),
)),
Box::new(Content::Text(
"(2) Ist jedoch die Gewährung oder Verlängerung von Kredit nach den vorstehenden Bestimmungen nichtig, so hat der Benachteiligte für den erhaltenen Kreditbetrag vom Empfangstag bis zur Rückzahlung sofern im Vertrag nicht eine geringere Verzinsung vorgesehen ist - Zinsen in der Höhe des Zweifachen des im Zeitpunkt der Schließung des Vertrags geltenden Basiszinssatzes zu vergüten. Er kann für die Rückzahlung des Erhaltenen die im Vertrag vorgesehenen Zahlungsfristen in Anspruch nehmen. Bestimmungen, nach denen der Benachteiligte in besonderen Fällen weitergehende Rechte hat, bleiben unberührt.".into(),
)),
],
),
},
],
parent: None,
idx: 0,
},
],
},
],
last_header_index: Some(
0,
),
next_para_header: None,
};
assert_eq!(builder, expected);
}
}