12 Commits

13 changed files with 553 additions and 68 deletions

101
Cargo.lock generated
View File

@@ -4,27 +4,15 @@ version = 3
[[package]]
name = "anstyle"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
[[package]]
name = "clap"
version = "4.3.4"
version = "4.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80672091db20273a15cf9fdd4e47ed43b5091ec9841bf4c6145c9dfbbcae09ed"
checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
dependencies = [
"clap_builder",
"clap_derive",
@@ -33,20 +21,19 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.3.4"
version = "4.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636"
checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
dependencies = [
"anstyle",
"bitflags",
"clap_lex",
]
[[package]]
name = "clap_derive"
version = "4.3.2"
version = "4.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
dependencies = [
"heck",
"proc-macro2",
@@ -80,10 +67,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "hashbrown"
version = "0.12.3"
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "heck"
@@ -93,19 +86,19 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "indexmap"
version = "1.9.3"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"autocfg",
"equivalent",
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.6"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "lazy_static"
@@ -115,9 +108,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.146"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "memchr"
@@ -133,7 +126,7 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "osc-variant"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"clap",
"console",
@@ -145,18 +138,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.60"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-xml"
version = "0.28.2"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1"
checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
dependencies = [
"memchr",
"serde",
@@ -164,33 +157,33 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.28"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.13"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "serde"
version = "1.0.164"
version = "1.0.182"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
checksum = "bdb30a74471f5b7a1fa299f40b4bf1be93af61116df95465b2b5fc419331e430"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.164"
version = "1.0.182"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
checksum = "6f4c2c6ea4bc09b5c419012eafcdb0fcef1d9119d626c8f3a0708a5b92d38a70"
dependencies = [
"proc-macro2",
"quote",
@@ -199,9 +192,9 @@ dependencies = [
[[package]]
name = "serde_yaml"
version = "0.9.21"
version = "0.9.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
dependencies = [
"indexmap",
"itoa",
@@ -212,9 +205,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.18"
version = "2.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
dependencies = [
"proc-macro2",
"quote",
@@ -223,9 +216,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.9"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "unicode-width"
@@ -235,9 +228,9 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unsafe-libyaml"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6"
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
[[package]]
name = "windows-sys"
@@ -307,6 +300,6 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "xml-rs"
version = "0.8.14"
version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c"
checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1"

View File

@@ -1,13 +1,17 @@
[package]
name = "osc-variant"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
authors = ["Paul-Christian Volkmer <volkmer_p@ukw.de>"]
description = "Anwendung zum Anpassen einer OSC-Datei an einen Standort"
license = "MIT"
readme = "README.md"
[dependencies]
clap = { version = "4.3", features = ["std", "help", "usage", "derive", "error-context"], default-features = false }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
quick-xml = { version = "0.28", features = ["escape-html", "serialize"], default-features=false }
quick-xml = { version = "0.30", features = ["escape-html", "serialize"], default-features = false }
xml-rs = "0.8"
console = "0.15"
@@ -17,3 +21,6 @@ codegen-units = 1
lto = "thin"
strip = true
panic = "abort"
[package.metadata.deb]
copyright = "Copyright (c) 2023 Comprehensive Cancer Center Mainfranken"

View File

@@ -38,7 +38,11 @@ win-binary-x86_64:
linux-binary-x86_64:
cargo build --release --target=x86_64-unknown-linux-gnu
.PHONE: clean
.PHONY: install
install:
cargo install --path .
.PHONY: clean
clean:
cargo clean
rm -rf osc-variant 2>/dev/null || true

View File

@@ -22,6 +22,20 @@ Zum Auflisten der Inhalte einer Datei wird folgender Befehl verwendet:
osc-variant list meine-beispieldatei.osc
```
Zum Vergleich zweier OSC-Dateien wird der Unterbefehl `diff` verwendet.
Der optionale Parameter `--strict` vergleicht auch den Inhalt der OSC-Datei.
Ohne diesen wird nur das Vorhandensein von Inhalten und die Revision verglichen.
```
osc-variant diff meine-beispieldatei.osc andere-beispieldatei.osc
```
bzw.
```
osc-variant diff meine-beispieldatei.osc andere-beispieldatei.osc --strict
```
Zum Anpassen des Inhalts einer Datei:
```
@@ -44,6 +58,13 @@ Hierzu ist die Option `--compact` vorgesehen. Es können, je nach Datei, bis zu
Bei der Auflistung der Inhalte, kann die Option `--sorted` dazu verwendet werden, die angezeigten Einträge alphabetisch zu sortieren.
Die Sortierung erfolgt dabei nach Namen des Katalogs oder des Formulars.
##### Experimentell: Sortierung nach Modifikation
Beim Modifizieren der Inhalte kann die experimentelle Option `--x-sorted` dazu verwendet werden, die Einträge im Anschluss an die Modifikation
nach Namen zu sortieren.
Dies erlaubt eine konsistente Reihenfolge der Einträge, wodurch ein direkter Vergleich mit Vorversionen ermöglicht wird.
ACHTUNG: Es kann sein, dass dadurch ein Import der resultierenden OSC-Datei nicht mehr möglich ist, da das genaue Verhalten des Imports aktuell noch nicht bekannt ist.
## Profile
Zum Erstellen von Varianten einer OSC-Datei wird eine Profildatei im YAML-Format verwendet.

View File

@@ -4,3 +4,24 @@ forms:
- name: MTB
referenced_data_form: 'MR.MTB_Anmeldung'
anzeige_auswahl: 'MTB Anmeldung vom {Anmeldedatum}'
- name: 'DNPM Therapieplan'
form_references:
- name: referstemtb
referenced_data_form: 'MR.MTB_Empfehlung'
anzeige_auswahl: 'MTB vom {Datum}'
- name: reftkhumangenber
referenced_data_form: 'MR.MTB_Empfehlung'
anzeige_auswahl: 'MTB vom {Datum}'
- name: reftkreevaluation
referenced_data_form: 'MR.MTB_Empfehlung'
anzeige_auswahl: 'MTB vom {Datum}'
- name: 'DNPM UF Einzelempfehlung'
form_references:
- name: mtb
referenced_data_form: 'MR.MTB_Empfehlung'
anzeige_auswahl: 'MTB vom {Datum}'
- name: 'DNPM UF Rebiopsie'
form_references:
- name: reftumorkonferenz
referenced_data_form: 'MR.MTB_Empfehlung'
anzeige_auswahl: 'MTB vom {Datum}'

View File

@@ -52,5 +52,17 @@ pub enum Command {
outputfile: Option<String>,
#[arg(long = "compact", help = "Kompakte Ausgabe, ohne Einrücken (Optional)")]
compact: bool,
#[arg(
long = "x-sorted",
help = "EXPERIMENTELL: Sortiere Kataloge und Formulare nach Name (Optional). Kann negative Auswirkungen auf den ordnungsgemäßen Import haben."
)]
sorted: bool,
},
#[command(about = "Vergleiche zwei Dateien anhand der Revision der enthaltenen Inhalte")]
Diff {
inputfile_a: String,
inputfile_b: String,
#[arg(long = "strict", help = "Strikter Vergleich des Inhalts")]
strict: bool,
},
}

View File

@@ -31,6 +31,7 @@ use std::ops::Add;
use std::str::FromStr;
use clap::Parser;
use console::style;
use quick_xml::se::Serializer;
use serde::Serialize;
@@ -121,6 +122,7 @@ fn main() -> Result<(), Box<dyn Error>> {
profile,
outputfile,
compact,
sorted,
} => {
let data = &mut read_inputfile(inputfile)?;
@@ -131,6 +133,10 @@ fn main() -> Result<(), Box<dyn Error>> {
data.apply_profile(&profile);
}
if sorted {
data.sorted();
}
let mut buf = String::new();
let mut serializer = Serializer::new(&mut buf);
@@ -157,6 +163,22 @@ fn main() -> Result<(), Box<dyn Error>> {
}
}
}
Command::Diff {
inputfile_a,
inputfile_b,
strict,
} => {
println!(
"Vergleiche Datei A ({}) mit Datei B ({})",
style(&inputfile_a).yellow(),
style(&inputfile_b).yellow()
);
let data_a = &mut read_inputfile(inputfile_a)?;
let data_b = &mut read_inputfile(inputfile_b)?;
data_a.print_diff(data_b, strict);
}
};
Ok(())

View File

@@ -25,7 +25,7 @@
use console::style;
use serde::{Deserialize, Serialize};
use crate::model::{Listable, Ordner, Sortable};
use crate::model::{Comparable, Listable, Ordner, Sortable};
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
@@ -70,6 +70,26 @@ impl Sortable for DataCatalogue {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self {
self.entries
.entry
.sort_unstable_by_key(|item| item.sorting_key());
self.entries.entry.iter_mut().for_each(|item| {
item.sorted();
});
self
}
}
impl Comparable for DataCatalogue {
fn get_name(&self) -> String {
self.name.clone()
}
fn get_revision(&self) -> u16 {
self.revision
}
}
#[derive(Serialize, Deserialize, Debug)]
@@ -141,6 +161,23 @@ pub struct Entry {
revision: u16,
}
impl Sortable for Entry {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self
where
Self: Sized,
{
if let Some(ref mut use_) = self.use_ {
use_.program_module
.sort_unstable_by_key(|item| item.sorting_key())
}
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Use {
@@ -156,3 +193,9 @@ pub struct ProgramModule {
#[serde(rename = "@name")]
name: String,
}
impl Sortable for ProgramModule {
fn sorting_key(&self) -> String {
format!("{}-{}", self.program, self.name)
}
}

View File

@@ -26,8 +26,8 @@ use console::style;
use serde::{Deserialize, Serialize};
use crate::model::{
apply_profile_to_form_entry, Ansichten, Entries, Filter, FormEntry, FormEntryContainer,
Listable, MenuCategory, PlausibilityRules, Script, Sortable,
apply_profile_to_form_entry, Ansichten, Comparable, Entries, Filter, FormEntry,
FormEntryContainer, Listable, MenuCategory, PlausibilityRules, Script, Sortable,
};
use crate::model::{Haeufigkeiten, Ordner};
use crate::profile::Profile;
@@ -192,6 +192,39 @@ impl Sortable for DataForm {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self {
self.data_catalogues.data_catalogue.sort_unstable();
self.entries
.entry
.sort_unstable_by_key(|item| item.sorting_key());
self.entries.entry.iter_mut().for_each(|item| {
item.sorted();
});
if let Some(ref mut plausibility_rule) = self.plausibility_rules.plausibility_rule {
plausibility_rule.sort_unstable_by_key(|item| item.bezeichnung.clone());
plausibility_rule.iter_mut().for_each(|item| {
if let Some(ref mut data_form_entry_names) = item.data_form_entries.entry_name {
data_form_entry_names.sort_unstable();
}
});
}
self
}
}
impl Comparable for DataForm {
fn get_name(&self) -> String {
self.name.clone()
}
fn get_revision(&self) -> u16 {
self.revision
}
}
#[derive(Serialize, Deserialize, Debug)]
@@ -423,6 +456,26 @@ impl FormEntry for Entry {
}
}
impl Sortable for Entry {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self
where
Self: Sized,
{
if let Some(ref mut filter) = self.filter {
if let Some(ref mut ref_entries) = filter.ref_entries {
if let Some(ref mut ref_entry) = ref_entries.ref_entry {
ref_entry.sort_unstable()
}
}
}
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct DataFormEntries {

View File

@@ -24,6 +24,9 @@
use crate::profile::{FormReference, Profile};
use serde::{Deserialize, Serialize};
use std::collections::hash_map::DefaultHasher;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
pub mod data_catalogue;
pub mod data_form;
@@ -236,6 +239,22 @@ pub trait Listable {
pub trait Sortable {
fn sorting_key(&self) -> String;
fn sorted(&mut self) -> &Self
where
Self: Sized,
{
self
}
}
pub trait Comparable: Debug {
fn get_name(&self) -> String;
fn get_revision(&self) -> u16;
fn get_hash(&self) -> String {
let mut h = DefaultHasher::new();
format!("{:?}", self).hash(&mut h);
h.finish().to_string()
}
}
pub trait FormEntry {

View File

@@ -1,7 +1,7 @@
/*
* MIT License
*
* 2023 Comprehensive Cancer Center Mainfranken
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,13 +25,15 @@
use console::style;
use quick_xml::de::from_str;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::fmt::Debug;
use std::str::FromStr;
use crate::model::data_catalogue::DataCatalogue;
use crate::model::data_form::DataForm;
use crate::model::property_catalogue::PropertyCatalogue;
use crate::model::unterformular::Unterformular;
use crate::model::{FormEntryContainer, Listable, Sortable};
use crate::model::{Comparable, FormEntryContainer, Listable, Sortable};
use crate::profile::Profile;
#[derive(Serialize, Deserialize, Debug)]
@@ -77,17 +79,142 @@ impl OnkostarEditor {
.property_catalogue
.sort_unstable_by_key(|e| e.sorting_key());
self.editor.property_catalogue.iter_mut().for_each(|item| {
item.sorted();
});
self.editor
.data_catalogue
.sort_unstable_by_key(|e| e.sorting_key());
self.editor.data_catalogue.iter_mut().for_each(|item| {
item.sorted();
});
self.editor
.data_form
.sort_unstable_by_key(|e| e.sorting_key());
self.editor.data_form.iter_mut().for_each(|item| {
item.sorted();
});
self.editor
.unterformular
.sort_unstable_by_key(|e| e.sorting_key());
self.editor.unterformular.iter_mut().for_each(|item| {
item.sorted();
});
}
pub fn print_diff(&mut self, other: &mut Self, strict: bool) {
self.sorted();
other.sorted();
Self::print_item_diff(
"Merkmalskataloge",
&self.editor.property_catalogue,
&other.editor.property_catalogue,
strict,
);
Self::print_item_diff(
"Datenkataloge",
&self.editor.data_catalogue,
&other.editor.data_catalogue,
strict,
);
Self::print_item_diff(
"Formulare",
&self.editor.data_form,
&other.editor.data_form,
strict,
);
Self::print_item_diff(
"Unterformulare",
&self.editor.unterformular,
&other.editor.unterformular,
strict,
);
}
fn print_item_diff(
title: &str,
list_a: &[impl Comparable],
list_b: &[impl Comparable],
strict: bool,
) {
println!("\n{}", style(title).underlined());
let mut has_diff = false;
let names_a = list_a
.iter()
.map(|entry| entry.get_name())
.collect::<Vec<_>>();
let names_b = list_b
.iter()
.map(|entry| entry.get_name())
.collect::<Vec<_>>();
names_b.iter().for_each(|entry| {
if !names_a.contains(entry) {
println!("{}: {}", entry, style("Nicht in Datei A enthalten!").red());
has_diff = true;
}
});
names_a.iter().for_each(|entry| {
if !names_b.contains(entry) {
println!("{}: {}", entry, style("Nicht in Datei B enthalten!").red());
has_diff = true;
}
});
list_a.iter().for_each(|entry_a| {
list_b.iter().for_each(|entry_b| {
if entry_a.get_name() == entry_b.get_name() {
match entry_a.get_revision().cmp(&entry_b.get_revision()) {
Ordering::Less => {
println!(
"{}: {} (Revision {} < Revision {})",
entry_a.get_name(),
style("Neuer in Datei B").yellow(),
style(entry_a.get_revision()).blue(),
style(entry_b.get_revision()).green()
);
has_diff = true;
}
Ordering::Greater => {
println!(
"{}: {} (Revision {} > Revision {})",
entry_a.get_name(),
style("Neuer in Datei A").yellow(),
style(entry_a.get_revision()).green(),
style(entry_b.get_revision()).blue()
);
has_diff = true;
}
_ => {
if strict && entry_a.get_hash() != entry_b.get_hash() {
println!(
"{}: {} (z.B. GUID oder Reihenfolge von Unterelementen)",
entry_a.get_name(),
style("Inhaltlich verschieden").yellow()
);
has_diff = true;
} else if strict {
println!("{}: {}", entry_a.get_name(), style("Identisch").green())
}
}
}
}
});
});
if !has_diff {
println!("Keine Unterschiede")
}
}
}

View File

@@ -25,7 +25,7 @@
use console::style;
use serde::{Deserialize, Serialize};
use crate::model::{Listable, Ordner, Sortable};
use crate::model::{Comparable, Listable, Ordner, Sortable};
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
@@ -67,6 +67,26 @@ impl Sortable for PropertyCatalogue {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self {
if let Some(ref mut versions) = self.versions.entry {
versions.sort_unstable_by_key(|item| item.version_number);
versions.iter_mut().for_each(|version| {
version.sorted();
});
}
self
}
}
impl Comparable for PropertyCatalogue {
fn get_name(&self) -> String {
self.name.clone()
}
fn get_revision(&self) -> u16 {
self.revision
}
}
#[derive(Serialize, Deserialize, Debug)]
@@ -105,6 +125,40 @@ pub struct Version {
categories: Categories,
}
impl Sortable for Version {
fn sorting_key(&self) -> String {
self.oid.clone()
}
fn sorted(&mut self) -> &Self
where
Self: Sized,
{
if let Some(ref mut abbildung) = self.abbildung {
abbildung.sort_unstable_by_key(|item| item.sorting_key());
abbildung.iter_mut().for_each(|item| {
item.sorted();
});
}
self.entries
.content
.sort_unstable_by_key(|item| item.sorting_key());
self.entries.content.iter_mut().for_each(|item| {
item.sorted();
});
self.categories
.content
.sort_unstable_by_key(|item| item.sorting_key());
self.categories.content.iter_mut().for_each(|item| {
item.sorted();
});
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct VersionEntries {
@@ -131,6 +185,12 @@ pub struct VersionEntry {
position: String,
}
impl Sortable for VersionEntry {
fn sorting_key(&self) -> String {
self.code.clone()
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Categories {
@@ -155,6 +215,26 @@ pub struct Category {
category_entries: CategoryEntries,
}
impl Sortable for Category {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self
where
Self: Sized,
{
self.category_entries
.content
.sort_unstable_by_key(|item| item.sorting_key());
self.category_entries.content.iter_mut().for_each(|item| {
item.sorted();
});
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct CategoryEntries {
@@ -181,6 +261,12 @@ pub struct CategoryEntry {
note: Option<String>,
}
impl Sortable for CategoryEntry {
fn sorting_key(&self) -> String {
self.code.clone()
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Abbildung {
@@ -190,6 +276,24 @@ pub struct Abbildung {
content: Vec<AbbildungEintrag>,
}
impl Sortable for Abbildung {
fn sorting_key(&self) -> String {
self.ziel_mk_version_oid.clone()
}
fn sorted(&mut self) -> &Self
where
Self: Sized,
{
self.content.sort_unstable_by_key(|item| item.sorting_key());
self.content.iter_mut().for_each(|item| {
item.sorted();
});
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct AbbildungEintrag {
@@ -199,6 +303,12 @@ pub struct AbbildungEintrag {
entry_to: AbbildungEntry,
}
impl Sortable for AbbildungEintrag {
fn sorting_key(&self) -> String {
format!("{}-{}", self.entry_from.code, self.entry_to.code)
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct AbbildungEntry {

View File

@@ -26,8 +26,8 @@ use console::style;
use serde::{Deserialize, Serialize};
use crate::model::{
apply_profile_to_form_entry, Ansichten, Entries, Filter, FormEntry, FormEntryContainer,
Listable, MenuCategory, PlausibilityRules, Script, Sortable,
apply_profile_to_form_entry, Ansichten, Comparable, Entries, Filter, FormEntry,
FormEntryContainer, Listable, MenuCategory, PlausibilityRules, Script, Sortable,
};
use crate::model::{Haeufigkeiten, Ordner};
use crate::profile::Profile;
@@ -211,6 +211,39 @@ impl Sortable for Unterformular {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self {
self.data_catalogues.data_catalogue.sort_unstable();
self.entries
.entry
.sort_unstable_by_key(|item| item.sorting_key());
self.entries.entry.iter_mut().for_each(|item| {
item.sorted();
});
if let Some(ref mut plausibility_rule) = self.plausibility_rules.plausibility_rule {
plausibility_rule.sort_unstable_by_key(|item| item.bezeichnung.clone());
plausibility_rule.iter_mut().for_each(|item| {
if let Some(ref mut data_form_entry_names) = item.data_form_entries.entry_name {
data_form_entry_names.sort_unstable();
}
});
}
self
}
}
impl Comparable for Unterformular {
fn get_name(&self) -> String {
self.name.clone()
}
fn get_revision(&self) -> u16 {
self.revision
}
}
#[derive(Serialize, Deserialize, Debug)]
@@ -443,6 +476,26 @@ impl FormEntry for Entry {
}
}
impl Sortable for Entry {
fn sorting_key(&self) -> String {
self.name.clone()
}
fn sorted(&mut self) -> &Self
where
Self: Sized,
{
if let Some(ref mut filter) = self.filter {
if let Some(ref mut ref_entries) = filter.ref_entries {
if let Some(ref mut ref_entry) = ref_entries.ref_entry {
ref_entry.sort_unstable()
}
}
}
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct DataFormEntries {