mirror of
https://github.com/pcvolkmer/osc-variant.git
synced 2025-04-19 11:46:50 +00:00
Add sub command 'tree' to show dependencies
This commit is contained in:
parent
37c8b47d1f
commit
103075ab78
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -126,7 +126,7 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "osc-variant"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"console",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "osc-variant"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
authors = ["Paul-Christian Volkmer <volkmer_p@ukw.de>"]
|
||||
description = "Anwendung zum Anpassen einer OSC-Datei an einen Standort"
|
||||
|
@ -22,6 +22,15 @@ Zum Auflisten der Inhalte einer Datei wird folgender Befehl verwendet:
|
||||
osc-variant list meine-beispieldatei.osc
|
||||
```
|
||||
|
||||
Zum Auflisten der Inhalte mit allen Abhängigkeiten, z.B. Daten- und Merkmalkataloge und bei Formularen wird der Befehl
|
||||
`tree` verwendet:
|
||||
|
||||
```
|
||||
osc-variant tree meine-beispieldatei.osc
|
||||
```
|
||||
|
||||
Achtung! Dies erzeugt eine sehr umfangreiche Ausgabe.
|
||||
|
||||
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.
|
||||
|
@ -43,6 +43,15 @@ pub enum Command {
|
||||
)]
|
||||
sorted: bool,
|
||||
},
|
||||
#[command(about = "Zeigt Kataloge und Formulare mit Revision und Abhängigkeiten an.")]
|
||||
Tree {
|
||||
inputfile: String,
|
||||
#[arg(
|
||||
long = "sorted",
|
||||
help = "Sortiere Kataloge und Formulare nach Name (Optional)"
|
||||
)]
|
||||
sorted: bool,
|
||||
},
|
||||
#[command(about = "Modifiziert die angegebene Datei anhand der Profildatei")]
|
||||
Modify {
|
||||
inputfile: String,
|
||||
|
@ -117,6 +117,13 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
data.print_list();
|
||||
}
|
||||
Command::Tree { inputfile, sorted } => {
|
||||
let mut data = read_inputfile(inputfile)?;
|
||||
if sorted {
|
||||
data.sorted()
|
||||
}
|
||||
OnkostarEditor::print_tree(&data);
|
||||
}
|
||||
Command::Modify {
|
||||
inputfile,
|
||||
profile,
|
||||
|
@ -22,9 +22,13 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use console::style;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::model::requirements::{Requirement, Requires};
|
||||
use crate::model::{Comparable, Listable, Ordner, Sortable};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@ -92,6 +96,45 @@ impl Comparable for DataCatalogue {
|
||||
}
|
||||
}
|
||||
|
||||
impl Requires for DataCatalogue {
|
||||
fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement> {
|
||||
self.entries
|
||||
.entry
|
||||
.iter()
|
||||
.filter(|&entry| entry.property_catalogue.is_some())
|
||||
.map(|entry| match &entry.property_catalogue {
|
||||
Some(entry) => entry.to_string(),
|
||||
_ => String::new(),
|
||||
})
|
||||
.collect::<HashSet<_>>()
|
||||
.into_iter()
|
||||
.map(|entry| all.find_property_catalogue(entry.as_str()))
|
||||
.filter(Option::is_some)
|
||||
.map(|entry| Requirement::PropertyCatalogue(entry.unwrap()))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String {
|
||||
format!(
|
||||
"Datenkatalog '{}' in Revision '{}'\n{}",
|
||||
style(&self.name).yellow(),
|
||||
style(&self.revision).yellow(),
|
||||
self.get_required_entries(all)
|
||||
.iter()
|
||||
.map(|entry| match entry {
|
||||
Requirement::PropertyCatalogue(x) => {
|
||||
Some(format!(" + {}\n", x.to_listed_string()))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Entries {
|
||||
|
@ -22,9 +22,13 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use console::style;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::model::requirements::{Requirement, Requires};
|
||||
use crate::model::{
|
||||
apply_profile_to_form_entry, Ansichten, Comparable, Entries, Filter, FormEntry,
|
||||
FormEntryContainer, Listable, MenuCategory, PlausibilityRules, Script, Sortable,
|
||||
@ -227,6 +231,56 @@ impl Comparable for DataForm {
|
||||
}
|
||||
}
|
||||
|
||||
impl Requires for DataForm {
|
||||
fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement> {
|
||||
self.data_catalogues
|
||||
.data_catalogue
|
||||
.iter()
|
||||
.collect::<HashSet<_>>()
|
||||
.into_iter()
|
||||
.map(|entry| all.find_data_catalogue(entry.as_str()))
|
||||
.filter(Option::is_some)
|
||||
.map(|entry| Requirement::DataCatalogue(entry.unwrap()))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String {
|
||||
format!(
|
||||
"Formular '{}' in Revision '{}'\n{}",
|
||||
style(&self.name).yellow(),
|
||||
style(&self.revision).yellow(),
|
||||
self.get_required_entries(all)
|
||||
.iter()
|
||||
.map(|entry| match entry {
|
||||
Requirement::DataCatalogue(x) => {
|
||||
let inner = x
|
||||
.get_required_entries(all)
|
||||
.iter()
|
||||
.map(|inner_entry| match inner_entry {
|
||||
Requirement::PropertyCatalogue(y) => Some(y.to_listed_string()),
|
||||
_ => None,
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.map(|item| format!(" - {}\n", item.unwrap()))
|
||||
.collect::<Vec<_>>()
|
||||
.join("");
|
||||
|
||||
if inner.is_empty() {
|
||||
Some(format!(" + {}\n", x.to_listed_string()))
|
||||
} else {
|
||||
Some(format!(" + {}\n{}", x.to_listed_string(), inner))
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DataCatalogues {
|
||||
|
@ -22,16 +22,19 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::profile::{FormReference, Profile};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::profile::{FormReference, Profile};
|
||||
|
||||
pub mod data_catalogue;
|
||||
pub mod data_form;
|
||||
pub mod onkostar_editor;
|
||||
pub mod property_catalogue;
|
||||
pub mod requirements;
|
||||
pub mod unterformular;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -22,16 +22,18 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
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 console::style;
|
||||
use quick_xml::de::from_str;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::model::data_catalogue::DataCatalogue;
|
||||
use crate::model::data_form::DataForm;
|
||||
use crate::model::property_catalogue::PropertyCatalogue;
|
||||
use crate::model::requirements::Requires;
|
||||
use crate::model::unterformular::Unterformular;
|
||||
use crate::model::{Comparable, FormEntryContainer, Listable, Sortable};
|
||||
use crate::profile::Profile;
|
||||
@ -46,6 +48,32 @@ pub struct OnkostarEditor {
|
||||
}
|
||||
|
||||
impl OnkostarEditor {
|
||||
pub fn find_property_catalogue<'a>(&'a self, name: &str) -> Option<&'a PropertyCatalogue> {
|
||||
match self
|
||||
.editor
|
||||
.property_catalogue
|
||||
.iter()
|
||||
.filter(|&item| item.get_name().eq_ignore_ascii_case(name))
|
||||
.nth(0)
|
||||
{
|
||||
Some(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_data_catalogue<'a>(&'a self, name: &str) -> Option<&'a DataCatalogue> {
|
||||
match self
|
||||
.editor
|
||||
.data_catalogue
|
||||
.iter()
|
||||
.filter(|&item| item.get_name().eq_ignore_ascii_case(name))
|
||||
.nth(0)
|
||||
{
|
||||
Some(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_profile(&mut self, profile: &Profile) {
|
||||
self.editor.data_form.iter_mut().for_each(|data_form| {
|
||||
data_form.apply_profile(profile);
|
||||
@ -74,6 +102,26 @@ impl OnkostarEditor {
|
||||
.for_each(|entry| println!("{}", entry.to_listed_string()));
|
||||
}
|
||||
|
||||
pub fn print_tree(&self) {
|
||||
println!(
|
||||
"Die Datei wurde am {} mit {} in Version {} erstellt.\n\nFolgende Inhalte sind gespeichert",
|
||||
style(&self.info_xml.datum_xml).yellow(),
|
||||
style(&self.info_xml.name).yellow(),
|
||||
style(&self.info_xml.version).yellow()
|
||||
);
|
||||
|
||||
Self::print_items("Merkmalskataloge", &self.editor.property_catalogue);
|
||||
self.print_items_tree("Datenkataloge", &self.editor.data_catalogue);
|
||||
self.print_items_tree("Formulare", &self.editor.data_form);
|
||||
self.print_items_tree("Unterformulare", &self.editor.unterformular);
|
||||
}
|
||||
|
||||
fn print_items_tree(&self, title: &str, list: &[impl Requires]) {
|
||||
println!("\n{} {}", list.len(), style(title).underlined());
|
||||
list.iter()
|
||||
.for_each(|entry| println!("{}", entry.to_requirement_string(self)));
|
||||
}
|
||||
|
||||
pub fn sorted(&mut self) {
|
||||
self.editor
|
||||
.property_catalogue
|
||||
|
38
src/model/requirements.rs
Normal file
38
src/model/requirements.rs
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* 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
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use crate::model::data_catalogue::DataCatalogue;
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::model::property_catalogue::PropertyCatalogue;
|
||||
|
||||
pub enum Requirement<'a> {
|
||||
PropertyCatalogue(&'a PropertyCatalogue),
|
||||
DataCatalogue(&'a DataCatalogue),
|
||||
}
|
||||
|
||||
pub trait Requires {
|
||||
fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement>;
|
||||
|
||||
fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String;
|
||||
}
|
@ -22,9 +22,13 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use console::style;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::model::requirements::{Requirement, Requires};
|
||||
use crate::model::{
|
||||
apply_profile_to_form_entry, Ansichten, Comparable, Entries, Filter, FormEntry,
|
||||
FormEntryContainer, Listable, MenuCategory, PlausibilityRules, Script, Sortable,
|
||||
@ -246,6 +250,56 @@ impl Comparable for Unterformular {
|
||||
}
|
||||
}
|
||||
|
||||
impl Requires for Unterformular {
|
||||
fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement> {
|
||||
self.data_catalogues
|
||||
.data_catalogue
|
||||
.iter()
|
||||
.collect::<HashSet<_>>()
|
||||
.into_iter()
|
||||
.map(|entry| all.find_data_catalogue(entry.as_str()))
|
||||
.filter(Option::is_some)
|
||||
.map(|entry| Requirement::DataCatalogue(entry.unwrap()))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String {
|
||||
format!(
|
||||
"Unterformular '{}' in Revision '{}'\n{}",
|
||||
style(&self.name).yellow(),
|
||||
style(&self.revision).yellow(),
|
||||
self.get_required_entries(all)
|
||||
.iter()
|
||||
.map(|entry| match entry {
|
||||
Requirement::DataCatalogue(x) => {
|
||||
let inner = x
|
||||
.get_required_entries(all)
|
||||
.iter()
|
||||
.map(|inner_entry| match inner_entry {
|
||||
Requirement::PropertyCatalogue(y) => Some(y.to_listed_string()),
|
||||
_ => None,
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.map(|item| format!(" - {}\n", item.unwrap()))
|
||||
.collect::<Vec<_>>()
|
||||
.join("");
|
||||
|
||||
if inner.is_empty() {
|
||||
Some(format!(" + {}\n", x.to_listed_string()))
|
||||
} else {
|
||||
Some(format!(" + {}\n{}", x.to_listed_string(), inner))
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DataCatalogues {
|
||||
|
Loading…
x
Reference in New Issue
Block a user