forked from Plugin-JF-Onkostar/osc-variant
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3bbef5d22 | |||
| ef8f6ab1b5 | |||
| a1e5133516 | |||
| 13bcd74f6c | |||
| 6fdbe06106 | |||
| 31c162e977 | |||
| 2413e4b9b8 | |||
| c9ecb8e944 | |||
| 774b57d78e | |||
| a52eb9742e | |||
| 4c76504000 | |||
| 4676a63c69 | |||
| e250e330a5 | |||
| 349b571e09 | |||
| 90423b5b4e | |||
| d45ded939e | |||
| 7ab5523f3c | |||
| f02ea9b065 | |||
| a08abd7688 | |||
| bf7b8cd9ba | |||
| 821b30e452 | |||
| 6a0a356120 | |||
| 352f5e23fc | |||
| 7b13251d34 | |||
| 6da1c48c28 | |||
| e2d5eedd02 | |||
| a55db66e57 | |||
| dce2a5cdda | |||
| 93981f7709 | |||
| b6694b9e53 | |||
| 0e690cbb85 | |||
| 0d6525c398 | |||
| df643b5e60 | |||
| 1746026af8 | |||
| 7cdfe0068f | |||
| 1f5ec80cc6 | |||
| f851e9c424 | |||
| 7ef1638b58 | |||
| 4745a75f2e | |||
| f089ad0b32 |
113
Cargo.lock
generated
113
Cargo.lock
generated
@@ -148,9 +148,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.6"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
|
||||
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -158,9 +158,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.6"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
|
||||
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
@@ -168,18 +168,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.4.3"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7"
|
||||
checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.2"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
||||
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -189,9 +189,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
@@ -214,9 +214,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.10"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4"
|
||||
checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -303,9 +303,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
|
||||
checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
@@ -372,14 +372,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.2"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
|
||||
dependencies = [
|
||||
"console",
|
||||
"instant",
|
||||
"number_prefix",
|
||||
"portable-atomic",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
@@ -389,6 +402,15 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
@@ -412,15 +434,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.149"
|
||||
version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
|
||||
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@@ -437,6 +459,12 @@ dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
@@ -448,13 +476,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "osc-variant"
|
||||
version = "0.5.0"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"console",
|
||||
"deob",
|
||||
"dialoguer",
|
||||
"indicatif",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
@@ -497,6 +526,12 @@ version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
@@ -514,9 +549,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.30.0"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
|
||||
checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
@@ -539,9 +574,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
@@ -554,9 +589,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.20"
|
||||
version = "0.38.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0"
|
||||
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
@@ -573,18 +608,18 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.189"
|
||||
version = "1.0.192"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
|
||||
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.189"
|
||||
version = "1.0.192"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
|
||||
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -593,9 +628,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.25"
|
||||
version = "0.9.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
|
||||
checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
@@ -653,9 +688,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.38"
|
||||
version = "2.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -664,9 +699,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.0"
|
||||
version = "3.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
|
||||
checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
@@ -715,9 +750,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.33.0"
|
||||
version = "1.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
|
||||
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
||||
11
Cargo.toml
11
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "osc-variant"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
edition = "2021"
|
||||
authors = ["Paul-Christian Volkmer <volkmer_p@ukw.de>"]
|
||||
description = "Anwendung zum Anpassen einer OSC-Datei an einen Standort"
|
||||
@@ -16,10 +16,11 @@ members = ["libs/deob"]
|
||||
clap = { version = "4.4", features = ["std", "help", "usage", "derive", "error-context"], default-features = false }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_yaml = "0.9"
|
||||
quick-xml = { version = "0.30", features = ["escape-html", "serialize"], default-features = false }
|
||||
quick-xml = { version = "0.31", features = ["escape-html", "serialize"], default-features = false }
|
||||
console = "0.15"
|
||||
sha256 = "1.4"
|
||||
dialoguer = "0.11"
|
||||
indicatif = "0.17"
|
||||
|
||||
deob = { path = "./libs/deob", optional = true }
|
||||
zip = { version = "0.6", optional = true }
|
||||
@@ -46,3 +47,9 @@ assets = [
|
||||
["target/release/osc-variant", "usr/bin/", "755"],
|
||||
["completion/osc-variant.bash", "etc/bash_completion.d/", "644"]
|
||||
]
|
||||
|
||||
[package.metadata.generate-rpm]
|
||||
assets = [
|
||||
{ source = "target/release/osc-variant", dest = "/usr/bin/", mode = "755" },
|
||||
{ source = "completion/osc-variant.bash", dest = "/etc/bash_completion.d/", mode = "644" }
|
||||
]
|
||||
|
||||
20
README.md
20
README.md
@@ -91,6 +91,15 @@ Ohne Profildatei wird die Datei lediglich eingelesen, Leerzeichen am Ende eines
|
||||
|
||||
Ohne eine Angabe der Ausgabedatei wird auf die Standardausgabe ausgegeben.
|
||||
|
||||
##### Enthaltene Profile
|
||||
|
||||
Die im Ordner [`examples/`](/examples) enthaltenen Profile für Standorte sind in der ausführbaren Anwendung enthalten
|
||||
und die Dateien müssen nicht explizit als Datei vorliegen:
|
||||
|
||||
* `--profile examples/dnpm-ukm.yml` => `--profile UKM`
|
||||
* `--profile examples/dnpm-ukw.yml` => `--profile UKW`
|
||||
* `--profile examples/dnpm-umg.yml` => `--profile UMG`
|
||||
|
||||
#### Unterbefehl `unzip-osb`
|
||||
|
||||
Ab Version 0.6.0 ist die Anwendung zudem in der Lage, die für eine Aktualisierung der OS-Bibliothek genutzten OSB-Dateien zu entpacken:
|
||||
@@ -99,6 +108,17 @@ Ab Version 0.6.0 ist die Anwendung zudem in der Lage, die für eine Aktualisieru
|
||||
osc-variant unzip-osb OSBIB-6.10.osb
|
||||
```
|
||||
|
||||
Dieser Befehl kennt die beiden optionalen Parameter
|
||||
|
||||
* `-d`: Optionale Angabe des Zielverzeichnisses. Wenn keine Angabe vorhanden ist, wird das aktuelle Verzeichnis verwendet.
|
||||
* `-p`/`--password`: Optionale Angabe des Passworts zum Entpacken der OSB-Datei.
|
||||
|
||||
#### Unterbefehl `check`
|
||||
|
||||
Der Unterbefehl `check` prüft eine OSC-Datei auf bekannte Probleme und gibt eine Liste mit erkannten Problemen aus.
|
||||
|
||||
Eine Liste mit bekannten Problemen wird mit `check --list` ausgegeben.
|
||||
|
||||
#### Kompakte Ausgabe
|
||||
|
||||
OSC-Dateien sind XML-Dateien. Diese Anwendung ermöglicht optional die Ausgabe als kompaktere XML-Datei ohne Zeilenumbrüche.
|
||||
|
||||
@@ -7,6 +7,7 @@ forms:
|
||||
scripts_code: |
|
||||
setFieldValue('AnmeldedatumMTB', getFieldValue('MTB').MTBTermin);
|
||||
setFieldValue('WHOGrad', getFieldValue('MTB').WHOGrad);
|
||||
setFieldValue('Leitlinienstatus', getFieldValue('MTB').Leitlinienstatus);
|
||||
- name: 'DNPM Therapieplan'
|
||||
form_references:
|
||||
- name: referstemtb
|
||||
|
||||
@@ -27,5 +27,6 @@ use std::io::Error;
|
||||
fn main() -> Result<(), Error> {
|
||||
cc::Build::new().file("src/deob.c").compile("deob");
|
||||
println!("cargo:rerun-if-changed=src/deob.c");
|
||||
println!("cargo:rerun-if-changed=src/deob.h");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
30
osc-variant.wxs
Normal file
30
osc-variant.wxs
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*"
|
||||
Language="1033"
|
||||
Manufacturer="CCC Mainfranken"
|
||||
Name="OSC-Variant"
|
||||
UpgradeCode="{83088581-5db3-49a2-8932-27da356818c7}"
|
||||
Version="0.6.0">
|
||||
|
||||
<Package InstallScope="perMachine" Compressed="yes" />
|
||||
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="ProgramFiles64Folder">
|
||||
<Directory Id="INSTALLFOLDER" Name="osc-variant">
|
||||
<Component Id="MainExecutable" Guid="*">
|
||||
<File Id="OscVariantExe" Name="osc-variant.exe" KeyPath="yes" Source="target/x86_64-pc-windows-gnu/release/osc-variant.exe" />
|
||||
<File Id="LicenseTxt" Name="LICENSE.txt" Source="LICENSE.txt" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<Feature Id="Complete">
|
||||
<ComponentRef Id="MainExecutable" />
|
||||
</Feature>
|
||||
|
||||
</Product>
|
||||
</Wix>
|
||||
245
src/checks/mod.rs
Normal file
245
src/checks/mod.rs
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* 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 std::fmt::{Display, Formatter};
|
||||
use std::path::Path;
|
||||
|
||||
use console::style;
|
||||
|
||||
#[cfg(feature = "unzip-osb")]
|
||||
pub mod osb;
|
||||
pub mod osc;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum CheckNotice {
|
||||
/// This will result in Error if importing file and has a support code
|
||||
ErrorWithCode {
|
||||
code: String,
|
||||
description: String,
|
||||
line: Option<usize>,
|
||||
example: Option<String>,
|
||||
},
|
||||
/// This will result in Error if importing file
|
||||
Error {
|
||||
description: String,
|
||||
line: Option<usize>,
|
||||
},
|
||||
/// Other known issues
|
||||
Warning {
|
||||
description: String,
|
||||
line: Option<usize>,
|
||||
},
|
||||
/// Other known issues
|
||||
Info {
|
||||
description: String,
|
||||
line: Option<usize>,
|
||||
},
|
||||
/// Ok
|
||||
Ok(String),
|
||||
}
|
||||
|
||||
impl Display for CheckNotice {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
CheckNotice::ErrorWithCode {
|
||||
code,
|
||||
description,
|
||||
line,
|
||||
example,
|
||||
} => match line {
|
||||
Some(line) => write!(
|
||||
f,
|
||||
"{: <7} ({}) at Line {}: {}{}",
|
||||
style("ERROR").red().bold(),
|
||||
code,
|
||||
line,
|
||||
description,
|
||||
match example {
|
||||
Some(example) => format!("\n 🔥 '{}'", style(example).dim()),
|
||||
_ => String::new(),
|
||||
}
|
||||
),
|
||||
None => write!(
|
||||
f,
|
||||
"{: <7} ({}): {}{}",
|
||||
style("ERROR").red().bold(),
|
||||
code,
|
||||
description,
|
||||
match example {
|
||||
Some(example) => format!("\n 🔥 '{}'", style(example).dim()),
|
||||
_ => String::new(),
|
||||
}
|
||||
),
|
||||
},
|
||||
CheckNotice::Error { description, line } => match line {
|
||||
Some(line) => write!(
|
||||
f,
|
||||
"{: <7} at Line {}: {}",
|
||||
style("ERROR").red().bold(),
|
||||
line,
|
||||
description
|
||||
),
|
||||
None => write!(f, "{: <7} {}", style("ERROR").red().bold(), description),
|
||||
},
|
||||
CheckNotice::Warning { description, line } => match line {
|
||||
Some(line) => write!(
|
||||
f,
|
||||
"{: <7} at Line {}: {}",
|
||||
style("WARNING").yellow().bold(),
|
||||
line,
|
||||
description
|
||||
),
|
||||
None => write!(
|
||||
f,
|
||||
"{: <7} {}",
|
||||
style("WARNING").yellow().bold(),
|
||||
description
|
||||
),
|
||||
},
|
||||
CheckNotice::Info { description, line } => match line {
|
||||
Some(line) => write!(
|
||||
f,
|
||||
"{: <7} at Line {}: {}",
|
||||
style("INFO").blue().bold(),
|
||||
line,
|
||||
description
|
||||
),
|
||||
None => write!(f, "{: <7} {}", style("INFO").blue().bold(), description),
|
||||
},
|
||||
CheckNotice::Ok(msg) => write!(f, "{: <7} {}", style("OK").green(), msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Checkable {
|
||||
fn check(&self) -> Vec<CheckNotice>;
|
||||
}
|
||||
|
||||
pub trait Fixable {
|
||||
fn fix(&mut self) -> bool;
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn check_file(file: &Path, password: Option<String>) -> Result<Vec<CheckNotice>, CheckNotice> {
|
||||
match file.extension() {
|
||||
Some(ex) => match ex.to_str() {
|
||||
#[cfg(feature = "unzip-osb")]
|
||||
Some("osb") => match password {
|
||||
Some(password) => osb::check_file(file, password.as_str()),
|
||||
None => {
|
||||
use deob::deobfuscate;
|
||||
osb::check_file(file, deobfuscate(env!("OSB_KEY").trim()).as_str())
|
||||
}
|
||||
},
|
||||
Some("osc") => osc::check_file(file),
|
||||
_ => Err(CheckNotice::Error {
|
||||
description: "Keine prüfbare Datei".to_string(),
|
||||
line: None,
|
||||
}),
|
||||
},
|
||||
_ => Err(CheckNotice::Error {
|
||||
description: "Keine prüfbare Datei".to_string(),
|
||||
line: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_checks() {
|
||||
println!(
|
||||
"{}",
|
||||
style("Die folgenden Probleme sind bekannt\n")
|
||||
.yellow()
|
||||
.bold()
|
||||
);
|
||||
|
||||
struct Problem<'a> {
|
||||
code: &'a str,
|
||||
name: &'a str,
|
||||
description: &'a str,
|
||||
fixable: bool,
|
||||
}
|
||||
|
||||
impl<'a> Display for Problem<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{} {} {}\n\n{}",
|
||||
style(self.code).bold(),
|
||||
style(self.name).underlined(),
|
||||
match self.fixable {
|
||||
true => style("(Behebbar)").green(),
|
||||
false => style("(Nicht behebbar)").red(),
|
||||
},
|
||||
self.description
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
vec![
|
||||
Problem {
|
||||
code: "2023-0001",
|
||||
name: "Unterformular mit Markierung 'hat Unterformulare'",
|
||||
description: " Aktuell gibt es keine Unterformulare in Unterformularen, daher\n \
|
||||
sollte dies nicht vorkommen.\n\n \
|
||||
Eine mögliche Ursache ist die Speicherung eines Unterformulars als Formular.",
|
||||
fixable: false,
|
||||
},
|
||||
Problem {
|
||||
code: "2023-0002",
|
||||
name: "Formular hat keine Angabe zum Prozedurdatum",
|
||||
description: " Formulare benötigen die Angabe des Prozedurdatums, anderenfalls\n \
|
||||
führt dies zu Problemen in Onkostar.\n\n \
|
||||
Unterformulare können ein Prozedurdatum haben, müssen es aber nicht.\n\n \
|
||||
Eine mögliche Ursache ist die Speicherung eines Formulars als Unterformular.",
|
||||
fixable: false,
|
||||
},
|
||||
Problem {
|
||||
code: "2023-0003",
|
||||
name: "Leerzeichen am Ende der Plausibilitätsregel-Bezeichnung (OSTARSUPP-13334)",
|
||||
description:
|
||||
" Treten Leerzeichen am Ende der Plausibilitätsregel-Bezeichnung auf,\n \
|
||||
führt dies zu Fehlern beim Import der OSC-Datei.\n\n \
|
||||
Das Problem wird beim Verwenden des Unterbefehls 'modify' automatisch\n \
|
||||
behoben und Leerzeichen entfernt.
|
||||
",
|
||||
fixable: true,
|
||||
},
|
||||
Problem {
|
||||
code: "2023-0004",
|
||||
name: "Verweis auf noch nicht definiertes Formular (OSTARSUPP-13212)",
|
||||
description: " Wenn ein Formular einen Verweis auf ein anderes Formular enthält,\n \
|
||||
das nicht vor diesem Formular in der OSC-Datei definiert ist, wird der\n \
|
||||
Formularverweis beim Import der OSC-Datei nicht übernommen.\n\n \
|
||||
Dies kann bei wechselseitiger Abhängigkeit zwischen zwei (Unter-)Formularen\n \
|
||||
auftreten.\n\n \
|
||||
In diesem Fall kann ein erneuter/zweiter Import helfen, da das Onkostar in\n \
|
||||
diesem Fall alle Formulare importiert hat und der Formularverweis dann \n \
|
||||
gespeichert werden kann.
|
||||
",
|
||||
fixable: false,
|
||||
},
|
||||
]
|
||||
.iter()
|
||||
.for_each(|problem| println!("{}\n", problem))
|
||||
}
|
||||
108
src/checks/osb.rs
Normal file
108
src/checks/osb.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 std::fs;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
use indicatif::ProgressBar;
|
||||
|
||||
use crate::checks::{osc, CheckNotice};
|
||||
|
||||
#[cfg(feature = "unzip-osb")]
|
||||
pub fn check_file(file: &Path, password: &str) -> Result<Vec<CheckNotice>, CheckNotice> {
|
||||
let file = match fs::File::open(file) {
|
||||
Ok(file) => file,
|
||||
Err(err) => {
|
||||
return Err(CheckNotice::Error {
|
||||
description: format!("Kann Datei nicht lesen: {}", err),
|
||||
line: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let mut archive = match zip::ZipArchive::new(file) {
|
||||
Ok(file) => file,
|
||||
Err(err) => {
|
||||
return Err(CheckNotice::Error {
|
||||
description: format!("Kann Datei nicht lesen: {}", err),
|
||||
line: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let mut result = vec![];
|
||||
|
||||
let progress_bar = ProgressBar::new(archive.len() as u64);
|
||||
|
||||
for i in 0..archive.len() {
|
||||
progress_bar.inc(1);
|
||||
if let Ok(Ok(mut zip_file)) = archive.by_index_decrypt(i, password.as_bytes()) {
|
||||
if zip_file.is_file() && zip_file.name().ends_with(".osc") {
|
||||
let mut buf = String::new();
|
||||
let _ = zip_file.read_to_string(&mut buf);
|
||||
match osc::check(buf) {
|
||||
Ok(ref mut check_result) => {
|
||||
result.push(CheckNotice::Info {
|
||||
description: format!("Prüfe Eintrag '{}'", zip_file.name()),
|
||||
line: None,
|
||||
});
|
||||
if check_result.is_empty() {
|
||||
result.push(CheckNotice::Ok(format!(
|
||||
"Keine Probleme in '{}' erkannt",
|
||||
zip_file.name()
|
||||
)))
|
||||
}
|
||||
result.append(check_result)
|
||||
}
|
||||
Err(_) => result.push(CheckNotice::Warning {
|
||||
description: format!(
|
||||
"Überspringe Eintrag '{}': Inhalt kann nicht geprüft werden",
|
||||
zip_file.name(),
|
||||
),
|
||||
line: None,
|
||||
}),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
if zip_file.is_file() {
|
||||
result.push(CheckNotice::Warning {
|
||||
description: format!(
|
||||
"Überspringe Eintrag '{}': Keine OSC-Datei",
|
||||
zip_file.name()
|
||||
),
|
||||
line: None,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return Err(CheckNotice::Error {
|
||||
description: format!("Kann Datei nicht lesen"),
|
||||
line: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
progress_bar.finish_and_clear();
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
78
src/checks/osc.rs
Normal file
78
src/checks/osc.rs
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 std::fs;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::checks::{CheckNotice, Checkable};
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
|
||||
pub fn check_file(file: &Path) -> Result<Vec<CheckNotice>, CheckNotice> {
|
||||
match fs::read_to_string(file) {
|
||||
Ok(content) => check(content),
|
||||
_ => Err(CheckNotice::Error {
|
||||
description: "Kann Datei nicht lesen".to_string(),
|
||||
line: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(content: String) -> Result<Vec<CheckNotice>, CheckNotice> {
|
||||
let mut result = content
|
||||
.lines()
|
||||
.enumerate()
|
||||
.flat_map(|(line, content)| check_line(line, content.to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let inner_checks = &mut match OnkostarEditor::from_str(content.as_str()) {
|
||||
Ok(data) => data.check(),
|
||||
Err(err) => {
|
||||
return Err(CheckNotice::Error {
|
||||
description: format!("Interner Fehler: {}", err),
|
||||
line: None,
|
||||
})
|
||||
}
|
||||
};
|
||||
result.append(inner_checks);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn check_line(line: usize, content: String) -> Vec<CheckNotice> {
|
||||
let mut result = vec![];
|
||||
|
||||
if content.contains(" </Bezeichnung>") {
|
||||
result.append(&mut vec![CheckNotice::ErrorWithCode {
|
||||
code: "2023-0003".to_string(),
|
||||
description:
|
||||
"Leerzeichen am Ende der Plausibilitätsregel-Bezeichnung (OSTARSUPP-13334)"
|
||||
.to_string(),
|
||||
line: Some(line),
|
||||
example: Some(content.trim().to_string()),
|
||||
}])
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
36
src/cli.rs
36
src/cli.rs
@@ -93,6 +93,11 @@ pub enum SubCommand {
|
||||
help = "Starte interaktiven Dialog zum Modifizieren von OSC-Dateien"
|
||||
)]
|
||||
interactive: bool,
|
||||
#[arg(
|
||||
long = "fix",
|
||||
help = "Erweiterte Problembehandlung und Reparatur der OSC-Datei"
|
||||
)]
|
||||
fix: bool,
|
||||
},
|
||||
#[command(about = "Vergleiche zwei Dateien anhand der Revision der enthaltenen Inhalte")]
|
||||
Diff {
|
||||
@@ -101,7 +106,36 @@ pub enum SubCommand {
|
||||
#[arg(long = "strict", help = "Strikter Vergleich des Inhalts")]
|
||||
strict: bool,
|
||||
},
|
||||
#[command(about = if cfg!(feature = "unzip-osb") { "Prüfe eine OSB- oder OSC-Datei auf bekannte Problemen" } else { "Prüfe eine OSC-Datei auf bekannte Problemen" })]
|
||||
Check {
|
||||
#[arg(help = "Die zu prüfende Datei", group = "check-file", required = true)]
|
||||
file: Option<String>,
|
||||
#[arg(
|
||||
short = 'p',
|
||||
long = "password",
|
||||
help = "Passwort der OSB-Datei (Optional - für OSB-Dateien)",
|
||||
requires = "check-file",
|
||||
hide = !cfg!(feature = "unzip-osb")
|
||||
)]
|
||||
password: Option<String>,
|
||||
#[arg(
|
||||
long = "list",
|
||||
help = "Prüfe nicht und zeige Liste mit Checks auf bekannte Problemen",
|
||||
conflicts_with = "check-file"
|
||||
)]
|
||||
list: bool,
|
||||
},
|
||||
#[cfg(feature = "unzip-osb")]
|
||||
#[command(about = "Entpackt eine OSB-Datei")]
|
||||
UnzipOsb { file: String },
|
||||
UnzipOsb {
|
||||
file: String,
|
||||
#[arg(
|
||||
short = 'p',
|
||||
long = "password",
|
||||
help = "Passwort der OSB-Datei (Optional)"
|
||||
)]
|
||||
password: Option<String>,
|
||||
#[arg(short = 'd', help = "Zielverzeichnis (Optional)")]
|
||||
dir: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
66
src/main.rs
66
src/main.rs
@@ -28,9 +28,10 @@ use std::fs;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use std::ops::Add;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::checks::{check_file, print_checks, CheckNotice};
|
||||
use clap::Parser;
|
||||
use console::style;
|
||||
use dialoguer::Confirm;
|
||||
@@ -42,6 +43,7 @@ use crate::cli::{Cli, SubCommand};
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::profile::Profile;
|
||||
|
||||
mod checks;
|
||||
mod cli;
|
||||
mod model;
|
||||
mod profile;
|
||||
@@ -153,13 +155,19 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
sorted,
|
||||
strip,
|
||||
interactive,
|
||||
fix,
|
||||
} => {
|
||||
let data = &mut read_inputfile(inputfile)?;
|
||||
|
||||
if let Some(profile) = profile {
|
||||
let profile = read_profile(profile.clone()).map_err(|_| {
|
||||
let profile = if profile.contains(".") {
|
||||
read_profile(profile.clone()).map_err(|_| {
|
||||
FileError::Reading(profile, "Kann Profildatei nicht lesen!".into())
|
||||
})?;
|
||||
})?
|
||||
} else {
|
||||
Profile::embedded_profile(profile.as_str())?
|
||||
};
|
||||
|
||||
data.apply_profile(&profile);
|
||||
}
|
||||
|
||||
@@ -189,6 +197,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if fix {
|
||||
// No operation as of now
|
||||
}
|
||||
|
||||
if sorted {
|
||||
data.sorted();
|
||||
}
|
||||
@@ -257,10 +269,52 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
};
|
||||
}
|
||||
SubCommand::Check {
|
||||
file,
|
||||
list,
|
||||
password,
|
||||
} => {
|
||||
if list {
|
||||
print_checks();
|
||||
} else {
|
||||
match check_file(Path::new(file.unwrap_or_default().as_str()), password) {
|
||||
Ok(notices) => {
|
||||
println!(
|
||||
"Es wurden {} Probleme gefunden\n",
|
||||
notices
|
||||
.iter()
|
||||
.filter(|notice| match notice {
|
||||
CheckNotice::ErrorWithCode { .. }
|
||||
| CheckNotice::Error { .. } => true,
|
||||
_ => false,
|
||||
})
|
||||
.count()
|
||||
);
|
||||
notices
|
||||
.iter()
|
||||
.for_each(|check_notice| println!("{}", check_notice));
|
||||
}
|
||||
Err(err) => {
|
||||
println!("{}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "unzip-osb")]
|
||||
SubCommand::UnzipOsb { file } => {
|
||||
use crate::unzip_osb::unzip_osb;
|
||||
unzip_osb(file.as_str())
|
||||
SubCommand::UnzipOsb {
|
||||
file,
|
||||
password,
|
||||
dir,
|
||||
} => {
|
||||
use crate::unzip_osb::{unzip_osb, unzip_osb_using_password};
|
||||
match password {
|
||||
Some(password) => unzip_osb_using_password(
|
||||
file.as_str(),
|
||||
dir.unwrap_or_default().as_str(),
|
||||
password.as_str(),
|
||||
),
|
||||
None => unzip_osb(file.as_str(), dir.unwrap_or_default().as_str()),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::model::requirements::{Requirement, Requires};
|
||||
use crate::model::{Comparable, FolderContent, Listable, Ordner, Sortable};
|
||||
use crate::model::{Ansichten, Comparable, FolderContent, Listable, Ordner, Sortable};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
@@ -58,6 +58,9 @@ pub struct DataCatalogue {
|
||||
entries: Entries,
|
||||
#[serde(rename = "Ordner")]
|
||||
ordner: Ordner,
|
||||
#[serde(rename = "Ansichten", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
ansichten: Option<Ansichten>,
|
||||
}
|
||||
|
||||
impl Listable for DataCatalogue {
|
||||
|
||||
@@ -28,12 +28,14 @@ use std::collections::HashSet;
|
||||
use console::style;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::checks::CheckNotice::ErrorWithCode;
|
||||
use crate::checks::{CheckNotice, Checkable};
|
||||
use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::model::requirements::{Requirement, Requires};
|
||||
use crate::model::{
|
||||
apply_profile_to_form_entry, apply_profile_to_form_field, Ansichten, Comparable, Entries,
|
||||
Filter, FolderContent, FormEntry, FormEntryContainer, Listable, MenuCategory,
|
||||
PlausibilityRules, RefEntries, Script, Sortable,
|
||||
Filter, FolderContent, FormEntry, FormEntryContainer, Kennzahlen, Listable, MenuCategory,
|
||||
PlausibilityRules, PunkteKategorien, RefEntries, Script, Sortable,
|
||||
};
|
||||
use crate::model::{Haeufigkeiten, Ordner};
|
||||
use crate::profile::Profile;
|
||||
@@ -80,18 +82,26 @@ pub struct DataForm {
|
||||
#[serde(rename = "EmailTemplate")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
mail_template: Option<String>,
|
||||
#[serde(rename = "ErkrankungText")]
|
||||
erkrankung_text: String,
|
||||
#[serde(rename = "ErkrankungText", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
erkrankung_text: Option<String>,
|
||||
#[serde(rename = "ErkrankungTextLong")]
|
||||
erkrankung_text_long: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
erkrankung_text_long: Option<String>,
|
||||
#[serde(rename = "ErkrankungProzedurText")]
|
||||
erkrankung_prozedur_text: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
erkrankung_prozedur_text: Option<String>,
|
||||
#[serde(rename = "ErkrankungSummary")]
|
||||
erkrankung_summary: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
erkrankung_summary: Option<String>,
|
||||
#[serde(rename = "ErkrankungBigSummary")]
|
||||
erkrankung_big_summary: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
erkrankung_big_summary: Option<String>,
|
||||
#[serde(rename = "Kontext")]
|
||||
kontext: String,
|
||||
#[serde(rename = "Datenart")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
datenart: Option<String>,
|
||||
#[serde(rename = "TudokReadonly")]
|
||||
tudok_readonly: bool,
|
||||
#[serde(rename = "VitalstatusRelevant")]
|
||||
@@ -138,6 +148,9 @@ pub struct DataForm {
|
||||
guid: String,
|
||||
#[serde(rename = "Revision")]
|
||||
revision: u16,
|
||||
#[serde(rename = "VerknuepftGUID")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
verknuepft_guid: Option<String>,
|
||||
#[serde(rename = "SeitenzahlSichtbar")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
seitenanzahl_sichtbar: Option<bool>,
|
||||
@@ -148,12 +161,15 @@ pub struct DataForm {
|
||||
#[serde(rename = "Haeufigkeiten")]
|
||||
haeufigkeiten: Haeufigkeiten,
|
||||
#[serde(rename = "Kennzahlen")]
|
||||
kennzahlen: String,
|
||||
kennzahlen: Kennzahlen,
|
||||
#[serde(rename = "Ordner")]
|
||||
ordner: Ordner,
|
||||
#[serde(rename = "MenuCategory")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
menu_category: Option<MenuCategory>,
|
||||
#[serde(rename = "PunkteKategorien")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
punkte_kategorien: Option<PunkteKategorien>,
|
||||
#[serde(rename = "Ansichten")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
ansichten: Option<Ansichten>,
|
||||
@@ -369,6 +385,30 @@ impl FolderContent for DataForm {
|
||||
}
|
||||
}
|
||||
|
||||
impl Checkable for DataForm {
|
||||
fn check(&self) -> Vec<CheckNotice> {
|
||||
if self
|
||||
.entries
|
||||
.entry
|
||||
.iter()
|
||||
.filter(|entry| entry.procedure_date_status != "none")
|
||||
.count()
|
||||
== 0
|
||||
{
|
||||
return vec![ErrorWithCode {
|
||||
code: "2023-0002".to_string(),
|
||||
description: format!(
|
||||
"Formular '{}' hat keine Angabe zum Prozedurdatum",
|
||||
self.name
|
||||
),
|
||||
line: None,
|
||||
example: None,
|
||||
}];
|
||||
}
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DataCatalogues {
|
||||
@@ -437,6 +477,9 @@ pub struct Entry {
|
||||
grafik_ausrichtung: Option<String>,
|
||||
#[serde(rename = "Mandatory")]
|
||||
mandatory: String,
|
||||
#[serde(rename = "Datenart", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
datenart: Option<String>,
|
||||
#[serde(rename = "Filter")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
filter: Option<Filter>,
|
||||
@@ -456,6 +499,9 @@ pub struct Entry {
|
||||
#[serde(rename = "AnzeigeAuswahl")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
anzeige_auswahl: Option<String>,
|
||||
#[serde(rename = "Druckvorlage")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
druckvorlage: Option<String>,
|
||||
#[serde(rename = "VersionFrom")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
version_from: Option<String>,
|
||||
@@ -463,6 +509,9 @@ pub struct Entry {
|
||||
speichern: String,
|
||||
#[serde(rename = "LeerAusblenden")]
|
||||
leer_ausblenden: bool,
|
||||
#[serde(rename = "Inhalt")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
inhalt: Option<String>,
|
||||
#[serde(rename = "GeschlossenAnzeigen")]
|
||||
geschlossen_anzeigen: bool,
|
||||
#[serde(rename = "Min")]
|
||||
@@ -472,7 +521,8 @@ pub struct Entry {
|
||||
#[serde(rename = "InUebersichtAnzeigen")]
|
||||
in_uebersicht_anzeigen: bool,
|
||||
#[serde(rename = "Hinweis")]
|
||||
hinweis: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
hinweis: Option<String>,
|
||||
#[serde(rename = "Vorschlagskategorie")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
vorschlagskategorie: Option<String>,
|
||||
@@ -544,6 +594,12 @@ pub struct Entry {
|
||||
in_auswertung: bool,
|
||||
#[serde(rename = "InAuswertungGraph")]
|
||||
in_auswertung_graph: bool,
|
||||
#[serde(rename = "FragebogenItemNummer")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
fragebogen_item_nummer: Option<u8>,
|
||||
#[serde(rename = "Score")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
score: Option<String>,
|
||||
#[serde(rename = "AlignmentPatModul")]
|
||||
alignment_pat_modul: String,
|
||||
#[serde(rename = "DirectionPatModul")]
|
||||
|
||||
100
src/model/mod.rs
100
src/model/mod.rs
@@ -27,9 +27,9 @@ 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::model::requirements::Requires;
|
||||
use crate::profile::{FormField, FormReference, Profile};
|
||||
|
||||
pub mod data_catalogue;
|
||||
@@ -96,11 +96,15 @@ pub struct Ansicht {
|
||||
#[serde(rename = "Konfiguration")]
|
||||
konfiguration: String,
|
||||
#[serde(rename = "DataForm")]
|
||||
data_form: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
data_form: Option<String>,
|
||||
#[serde(rename = "DataCatalogue")]
|
||||
data_catalogue: String,
|
||||
#[serde(rename = "TypAuswahl")]
|
||||
typ_auswahl: String,
|
||||
#[serde(rename = "PersonenstammKontext", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
personenstamm_kontext: Option<String>,
|
||||
#[serde(rename = "Suche")]
|
||||
suche: bool,
|
||||
#[serde(rename = "SID")]
|
||||
@@ -131,6 +135,66 @@ pub struct MenuCategory {
|
||||
column: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct PunkteKategorien {
|
||||
#[serde(rename = "PunkteKategorie", default)]
|
||||
punkte_kategorie: Vec<PunkteKategorie>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct PunkteKategorie {
|
||||
#[serde(rename = "Name")]
|
||||
name: String,
|
||||
#[serde(rename = "Beschreibung")]
|
||||
beschreibung: String,
|
||||
#[serde(rename = "MaxLeerwerte")]
|
||||
max_leerwerte: u16,
|
||||
#[serde(rename = "Berechnung")]
|
||||
berechnung: String,
|
||||
#[serde(rename = "Felder")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
felder: Option<Felder>,
|
||||
#[serde(rename = "Vergleichswerttabellen")]
|
||||
vergleichswerttabellen: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Felder {
|
||||
#[serde(rename = "Feld", default)]
|
||||
feld: Vec<Feld>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Feld {
|
||||
#[serde(rename = "DataFormEntryName")]
|
||||
data_form_entry_name: String,
|
||||
#[serde(rename = "ManuellePunkte")]
|
||||
manuelle_punkte: bool,
|
||||
#[serde(rename = "Werte")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
werte: Option<FeldWerte>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct FeldWerte {
|
||||
#[serde(rename = "Wert", default)]
|
||||
wert: Vec<FeldWert>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct FeldWert {
|
||||
#[serde(rename = "Wert")]
|
||||
wert: String,
|
||||
#[serde(rename = "Punkte")]
|
||||
punkte: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Filter {
|
||||
@@ -189,8 +253,12 @@ pub struct Haeufigkeit {
|
||||
taeglich_aktualisieren: bool,
|
||||
#[serde(rename = "Typ")]
|
||||
typ: String,
|
||||
#[serde(rename = "NichtBerechnen")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
nicht_berechnen: Option<String>,
|
||||
#[serde(rename = "TabellenName")]
|
||||
tabellen_name: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
tabellen_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@@ -214,6 +282,32 @@ pub struct Ordner {
|
||||
parent_order: Option<Box<Ordner>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Kennzahlen {
|
||||
#[serde(rename = "Kennzahl", default)]
|
||||
kennzahl: Vec<Kennzahl>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Kennzahl {
|
||||
#[serde(rename = "Name")]
|
||||
name: String,
|
||||
#[serde(rename = "Nummer")]
|
||||
nummer: String,
|
||||
#[serde(rename = "Beschreibung")]
|
||||
beschreibung: String,
|
||||
#[serde(rename = "Notiz")]
|
||||
notiz: String,
|
||||
#[serde(rename = "Vorgabe")]
|
||||
vorgabe: String,
|
||||
#[serde(rename = "Haeufigkeitenzaehler")]
|
||||
haeufigkeitenzaehler: String,
|
||||
#[serde(rename = "Haeufigkeitennenner")]
|
||||
haeufigkeitennenner: String,
|
||||
}
|
||||
|
||||
fn apply_profile_to_form_entry<E>(entry: &mut E, form_reference: &FormReference)
|
||||
where
|
||||
E: FormEntry,
|
||||
|
||||
@@ -30,10 +30,11 @@ use console::style;
|
||||
use quick_xml::de::from_str;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::checks::{CheckNotice, Checkable};
|
||||
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::requirements::{Requirement, Requires};
|
||||
use crate::model::unterformular::Unterformular;
|
||||
use crate::model::{Comparable, FolderContent, FormEntryContainer, Listable, Sortable};
|
||||
use crate::profile::Profile;
|
||||
@@ -409,6 +410,89 @@ impl FromStr for OnkostarEditor {
|
||||
}
|
||||
}
|
||||
|
||||
impl Checkable for OnkostarEditor {
|
||||
fn check(&self) -> Vec<CheckNotice> {
|
||||
// Inner form checks
|
||||
|
||||
let mut result = self
|
||||
.editor
|
||||
.data_form
|
||||
.iter()
|
||||
.flat_map(|entity| entity.check())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let other = &mut self
|
||||
.editor
|
||||
.unterformular
|
||||
.iter()
|
||||
.flat_map(|entity| entity.check())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
result.append(other);
|
||||
|
||||
// Check requirements
|
||||
|
||||
let mut requirement_checked_forms = vec![];
|
||||
|
||||
fn requirement_error(
|
||||
form: &impl Comparable,
|
||||
item: &impl Comparable,
|
||||
t: &str,
|
||||
) -> CheckNotice {
|
||||
CheckNotice::ErrorWithCode {
|
||||
code: "2023-0004".to_string(),
|
||||
description: format!(
|
||||
"'{}' hat einen Verweis auf zuvor nicht definiertes {t} '{}' (OSTARSUPP-13212)",
|
||||
form.get_name(),
|
||||
item.get_name()
|
||||
),
|
||||
line: None,
|
||||
example: None,
|
||||
}
|
||||
}
|
||||
|
||||
self.editor.unterformular.iter().for_each(|form| {
|
||||
requirement_checked_forms.push(form.get_name());
|
||||
form.get_required_entries(self)
|
||||
.iter()
|
||||
.for_each(|entry| match entry {
|
||||
Requirement::DataFormReference(&ref item) => {
|
||||
if !requirement_checked_forms.contains(&item.get_name()) {
|
||||
result.push(requirement_error(form, item, "Formular"))
|
||||
}
|
||||
}
|
||||
Requirement::UnterformularReference(&ref item) => {
|
||||
if !requirement_checked_forms.contains(&item.get_name()) {
|
||||
result.push(requirement_error(form, item, "Unterformular"))
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
});
|
||||
|
||||
self.editor.data_form.iter().for_each(|form| {
|
||||
requirement_checked_forms.push(form.get_name());
|
||||
form.get_required_entries(self)
|
||||
.iter()
|
||||
.for_each(|entry| match entry {
|
||||
Requirement::DataFormReference(&ref item) => {
|
||||
if !requirement_checked_forms.contains(&item.get_name()) {
|
||||
result.push(requirement_error(form, item, "Formular"))
|
||||
}
|
||||
}
|
||||
Requirement::UnterformularReference(&ref item) => {
|
||||
if !requirement_checked_forms.contains(&item.get_name()) {
|
||||
result.push(requirement_error(form, item, "Unterformular"))
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
});
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct InfoXML {
|
||||
|
||||
@@ -127,12 +127,12 @@ pub struct Version {
|
||||
#[serde(rename = "Revision")]
|
||||
revision: u16,
|
||||
#[serde(rename = "Entries")]
|
||||
entries: VersionEntries,
|
||||
entries: Option<VersionEntries>,
|
||||
#[serde(rename = "Abbildung")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
abbildung: Option<Vec<Abbildung>>,
|
||||
#[serde(rename = "Categories")]
|
||||
categories: Categories,
|
||||
categories: Option<Categories>,
|
||||
}
|
||||
|
||||
impl Sortable for Version {
|
||||
@@ -151,19 +151,23 @@ impl Sortable for Version {
|
||||
});
|
||||
}
|
||||
|
||||
self.entries
|
||||
if let Some(ref mut entries) = self.entries {
|
||||
entries
|
||||
.content
|
||||
.sort_unstable_by_key(|item| item.sorting_key());
|
||||
self.entries.content.iter_mut().for_each(|item| {
|
||||
entries.content.iter_mut().for_each(|item| {
|
||||
item.sorted();
|
||||
});
|
||||
}
|
||||
|
||||
self.categories
|
||||
if let Some(ref mut categories) = self.categories {
|
||||
categories
|
||||
.content
|
||||
.sort_unstable_by_key(|item| item.sorting_key());
|
||||
self.categories.content.iter_mut().for_each(|item| {
|
||||
categories.content.iter_mut().for_each(|item| {
|
||||
item.sorted();
|
||||
});
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
@@ -184,13 +188,16 @@ pub struct VersionEntry {
|
||||
#[serde(rename = "ShortDescription")]
|
||||
short_description: String,
|
||||
#[serde(rename = "Description")]
|
||||
description: String,
|
||||
description: Option<String>,
|
||||
#[serde(rename = "Synonyms", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
synonyms: Option<String>,
|
||||
#[serde(rename = "Note", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
note: Option<String>,
|
||||
#[serde(rename = "Type", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
type_: Option<String>,
|
||||
#[serde(rename = "Position")]
|
||||
position: String,
|
||||
}
|
||||
@@ -331,8 +338,9 @@ pub struct AbbildungEntry {
|
||||
#[serde(rename = "Synonyms")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
synonyms: Option<String>,
|
||||
#[serde(rename = "Note")]
|
||||
note: String,
|
||||
#[serde(rename = "Note", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
note: Option<String>,
|
||||
#[serde(rename = "Position")]
|
||||
position: String,
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::checks::CheckNotice::ErrorWithCode;
|
||||
use crate::checks::{CheckNotice, Checkable};
|
||||
use console::style;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -32,8 +34,8 @@ use crate::model::onkostar_editor::OnkostarEditor;
|
||||
use crate::model::requirements::{Requirement, Requires};
|
||||
use crate::model::{
|
||||
apply_profile_to_form_entry, apply_profile_to_form_field, Ansichten, Comparable, Entries,
|
||||
Filter, FolderContent, FormEntry, FormEntryContainer, Listable, MenuCategory,
|
||||
PlausibilityRules, RefEntries, Script, Sortable,
|
||||
Filter, FolderContent, FormEntry, FormEntryContainer, Kennzahlen, Listable, MenuCategory,
|
||||
PlausibilityRules, PunkteKategorien, RefEntries, Script, Sortable,
|
||||
};
|
||||
use crate::model::{Haeufigkeiten, Ordner};
|
||||
use crate::profile::Profile;
|
||||
@@ -80,7 +82,7 @@ pub struct Unterformular {
|
||||
#[serde(rename = "EmailTemplate")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
mail_template: Option<String>,
|
||||
#[serde(rename = "ErkrankungText")]
|
||||
#[serde(rename = "ErkrankungText", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
erkrankung_text: Option<String>,
|
||||
#[serde(rename = "ErkrankungTextLong")]
|
||||
@@ -97,6 +99,9 @@ pub struct Unterformular {
|
||||
erkrankung_big_summary: Option<String>,
|
||||
#[serde(rename = "Kontext")]
|
||||
kontext: String,
|
||||
#[serde(rename = "Datenart")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
datenart: Option<String>,
|
||||
#[serde(rename = "TudokReadonly")]
|
||||
tudok_readonly: bool,
|
||||
#[serde(rename = "VitalstatusRelevant")]
|
||||
@@ -159,12 +164,15 @@ pub struct Unterformular {
|
||||
#[serde(rename = "Haeufigkeiten")]
|
||||
haeufigkeiten: Haeufigkeiten,
|
||||
#[serde(rename = "Kennzahlen")]
|
||||
kennzahlen: String,
|
||||
kennzahlen: Kennzahlen,
|
||||
#[serde(rename = "Ordner")]
|
||||
ordner: Ordner,
|
||||
#[serde(rename = "MenuCategory")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
menu_category: Option<MenuCategory>,
|
||||
#[serde(rename = "PunkteKategorien")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
punkte_kategorien: Option<PunkteKategorien>,
|
||||
#[serde(rename = "Ansichten")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
ansichten: Option<Ansichten>,
|
||||
@@ -374,6 +382,24 @@ impl FolderContent for Unterformular {
|
||||
}
|
||||
}
|
||||
|
||||
impl Checkable for Unterformular {
|
||||
fn check(&self) -> Vec<CheckNotice> {
|
||||
if self.hat_unterformulare {
|
||||
return vec![ErrorWithCode {
|
||||
code: "2023-0001".to_string(),
|
||||
description: format!(
|
||||
"Unterformular '{}' mit Markierung 'hat Unterformulare'",
|
||||
self.name
|
||||
),
|
||||
line: None,
|
||||
example: None,
|
||||
}];
|
||||
}
|
||||
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DataCatalogues {
|
||||
@@ -442,6 +468,9 @@ pub struct Entry {
|
||||
grafik_ausrichtung: Option<String>,
|
||||
#[serde(rename = "Mandatory")]
|
||||
mandatory: String,
|
||||
#[serde(rename = "Datenart", default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
datenart: Option<String>,
|
||||
#[serde(rename = "Filter")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
filter: Option<Filter>,
|
||||
@@ -461,6 +490,9 @@ pub struct Entry {
|
||||
#[serde(rename = "AnzeigeAuswahl")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
anzeige_auswahl: Option<String>,
|
||||
#[serde(rename = "Druckvorlage")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
druckvorlage: Option<String>,
|
||||
#[serde(rename = "VersionFrom")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
version_from: Option<String>,
|
||||
@@ -468,6 +500,9 @@ pub struct Entry {
|
||||
speichern: String,
|
||||
#[serde(rename = "LeerAusblenden")]
|
||||
leer_ausblenden: bool,
|
||||
#[serde(rename = "Inhalt")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
inhalt: Option<String>,
|
||||
#[serde(rename = "GeschlossenAnzeigen")]
|
||||
geschlossen_anzeigen: bool,
|
||||
#[serde(rename = "Min")]
|
||||
@@ -550,6 +585,12 @@ pub struct Entry {
|
||||
in_auswertung: bool,
|
||||
#[serde(rename = "InAuswertungGraph")]
|
||||
in_auswertung_graph: bool,
|
||||
#[serde(rename = "FragebogenItemNummer")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
fragebogen_item_nummer: Option<u8>,
|
||||
#[serde(rename = "Score")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
score: Option<String>,
|
||||
#[serde(rename = "AlignmentPatModul")]
|
||||
alignment_pat_modul: String,
|
||||
#[serde(rename = "DirectionPatModul")]
|
||||
|
||||
@@ -34,6 +34,19 @@ pub struct Profile {
|
||||
pub forms: Vec<Form>,
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
pub fn embedded_profile(name: &str) -> Result<Profile, String> {
|
||||
let s = match name {
|
||||
"UKM" => include_str!("../examples/dnpm-ukm.yml"),
|
||||
"UKW" => include_str!("../examples/dnpm-ukw.yml"),
|
||||
"UMG" => include_str!("../examples/dnpm-umg.yml"),
|
||||
_ => return Err(format!("Not an embedded profile: '{name}'")),
|
||||
};
|
||||
|
||||
Profile::from_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Profile {
|
||||
type Err = String;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
use console::style;
|
||||
use deob::deobfuscate;
|
||||
use std::path::Path;
|
||||
use std::{fs, io};
|
||||
|
||||
macro_rules! started {
|
||||
@@ -48,11 +49,9 @@ macro_rules! error {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unzip_osb(path: &str) {
|
||||
pub fn unzip_osb_using_password(path: &str, dir: &str, password: &str) {
|
||||
println!("Entpacke OSB-Datei {}\n", style(path).yellow());
|
||||
|
||||
let pw = deobfuscate(env!("OSB_KEY").trim());
|
||||
|
||||
let file = match fs::File::open(path) {
|
||||
Ok(file) => file,
|
||||
Err(err) => {
|
||||
@@ -78,7 +77,7 @@ pub fn unzip_osb(path: &str) {
|
||||
};
|
||||
|
||||
for i in 0..archive.len() {
|
||||
let mut file = if let Ok(Ok(file)) = archive.by_index_decrypt(i, pw.as_bytes()) {
|
||||
let mut file = if let Ok(Ok(file)) = archive.by_index_decrypt(i, password.as_bytes()) {
|
||||
file
|
||||
} else {
|
||||
println!(
|
||||
@@ -89,7 +88,7 @@ pub fn unzip_osb(path: &str) {
|
||||
};
|
||||
|
||||
let outpath = match file.enclosed_name() {
|
||||
Some(path) => path.to_owned(),
|
||||
Some(path) => Path::new(dir).join(path.to_owned()),
|
||||
None => continue,
|
||||
};
|
||||
|
||||
@@ -130,3 +129,7 @@ pub fn unzip_osb(path: &str) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unzip_osb(path: &str, dir: &str) {
|
||||
unzip_osb_using_password(path, dir, deobfuscate(env!("OSB_KEY").trim()).as_str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user