diff --git a/README.md b/README.md index 98aae33..3d54040 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,11 @@ Bei der Auflistung der Inhalte, kann die Option `--sorted` dazu verwendet werden Die Sortierung erfolgt dabei nach Namen des Katalogs oder des Formulars. Beim Modifizieren der Inhalte kann ebenfalls die Option `--sorted` dazu verwendet werden, die Einträge im Anschluss an die Modifikation -nach Namen zu sortieren. +nach Namen und der Abhängigkeit von Formularverweisen und Unterformularen zu sortieren. + +Formulare, die von anderen Formularen in einem Formularverweis oder als Unterformular verwendet werden, werden dabei weiter oben angeordnet, +da Onkostar einen Formularimport sequenziell, ohne Berücksichtigung von Abhängigkeiten, durchführt. + Dies erlaubt eine konsistente Reihenfolge der Einträge, wodurch ein direkter Vergleich mit Vorversionen ermöglicht wird. ##### Entfernen von Inhalten der Systembibliothek bei Modifikation diff --git a/src/model/data_form.rs b/src/model/data_form.rs index 6e863dc..87a219c 100644 --- a/src/model/data_form.rs +++ b/src/model/data_form.rs @@ -22,6 +22,7 @@ * SOFTWARE. */ +use std::cmp::Ordering; use std::collections::HashSet; use console::style; @@ -252,9 +253,39 @@ impl Comparable for DataForm { fn get_revision(&self) -> u16 { self.revision } + + fn compare_by_requirement(a: &Self, b: &Self) -> Ordering { + if a.get_name() == b.get_name() { + return Ordering::Equal; + } + + if a.requires_form_reference(&b.get_name()) || a.requires_subform(&b.get_name()) { + return Ordering::Greater; + } + + Ordering::Less + } } impl Requires for DataForm { + fn requires_form_reference(&self, name: &str) -> bool { + self.entries + .entry + .iter() + .map(|item| item.type_ == "formReference" && item.name == name) + .filter(|&it| it) + .last() + .unwrap_or_default() + } + fn requires_subform(&self, name: &str) -> bool { + self.entries + .entry + .iter() + .map(|item| item.type_ == "subform" && item.name == name) + .filter(|&it| it) + .last() + .unwrap_or_default() + } fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec { let mut result = self .data_catalogues diff --git a/src/model/mod.rs b/src/model/mod.rs index 6026157..a0e9548 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -22,10 +22,12 @@ * SOFTWARE. */ +use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; use std::fmt::Debug; use std::hash::{Hash, Hasher}; +use crate::model::requirements::Requires; use serde::{Deserialize, Serialize}; use crate::profile::{FormField, FormReference, Profile}; @@ -251,6 +253,7 @@ pub trait Listable { pub trait Sortable { fn sorting_key(&self) -> String; + fn sorted(&mut self) -> &Self where Self: Sized, @@ -267,6 +270,12 @@ pub trait Comparable: Debug { format!("{:?}", self).hash(&mut h); h.finish().to_string() } + fn compare_by_requirement(_: &Self, _: &Self) -> Ordering + where + Self: Requires, + { + Ordering::Equal + } } pub trait FormEntry { diff --git a/src/model/onkostar_editor.rs b/src/model/onkostar_editor.rs index 03ae9d4..b1fb8ab 100644 --- a/src/model/onkostar_editor.rs +++ b/src/model/onkostar_editor.rs @@ -233,6 +233,10 @@ impl OnkostarEditor { .data_form .sort_unstable_by_key(|e| e.sorting_key()); + self.editor + .data_form + .sort_unstable_by(DataForm::compare_by_requirement); + self.editor.data_form.iter_mut().for_each(|item| { item.sorted(); }); @@ -241,6 +245,10 @@ impl OnkostarEditor { .unterformular .sort_unstable_by_key(|e| e.sorting_key()); + self.editor + .unterformular + .sort_unstable_by(Unterformular::compare_by_requirement); + self.editor.unterformular.iter_mut().for_each(|item| { item.sorted(); }); diff --git a/src/model/requirements.rs b/src/model/requirements.rs index 4a3fb65..4a89379 100644 --- a/src/model/requirements.rs +++ b/src/model/requirements.rs @@ -98,6 +98,14 @@ pub trait Requires where Self: Listable, { + fn requires_form_reference(&self, _: &str) -> bool { + false + } + + fn requires_subform(&self, _: &str) -> bool { + false + } + fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec; fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String { diff --git a/src/model/unterformular.rs b/src/model/unterformular.rs index 9459024..915baac 100644 --- a/src/model/unterformular.rs +++ b/src/model/unterformular.rs @@ -22,6 +22,7 @@ * SOFTWARE. */ +use std::cmp::Ordering; use std::collections::HashSet; use console::style; @@ -256,9 +257,40 @@ impl Comparable for Unterformular { fn get_revision(&self) -> u16 { self.revision } + + fn compare_by_requirement(a: &Self, b: &Self) -> Ordering { + if a.get_name() == b.get_name() { + return Ordering::Equal; + } + + if a.requires_form_reference(&b.get_name()) || a.requires_subform(&b.get_name()) { + return Ordering::Greater; + } + + Ordering::Less + } } impl Requires for Unterformular { + fn requires_form_reference(&self, name: &str) -> bool { + self.entries + .entry + .iter() + .map(|item| item.type_ == "formReference" && item.name == name) + .filter(|&it| it) + .last() + .unwrap_or_default() + } + fn requires_subform(&self, name: &str) -> bool { + self.entries + .entry + .iter() + .map(|item| item.type_ == "subform" && item.name == name) + .filter(|&it| it) + .last() + .unwrap_or_default() + } + fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec { let mut result = self .data_catalogues