--- type: Data Model title: Datenmodelle & Konfiguration description: Alle Pydantic-Modelle von DocuMentor – AppSettings, Project, ProjectData, TreeNode/XslFile/XmlFile, Tool-Konfigurationen, Hash-System und PostgreSQL-Integration. tags: [datenmodelle, pydantic, konfiguration, hash, postgresql] --- # Datenmodelle & Konfiguration Alle Modelle sind in `src/conf.py` definiert und verwenden Pydantic für Typsicherheit und Validierung. ## Globale Konfiguration: AppSettings `AppSettings` ist ein `BaseSettings`-Singleton (`app_settings`), das als JSON gespeichert wird. Der Pfad ist plattformabhängig (siehe [Schnellstart](quickstart.md)). ### Tool-Konfigurationen Jedes Tool-Modell hat eine `id` (int) und eine `version` bzw. `name`: | Modell | Felder | Zweck | |--------|--------|------| | `JavaVm` | `id`, `version`, `path_to_binary_file` | Pfad zur Java-Executable | | `SaxonJar` | `id`, `version`, `path_to_jar_file`, `output_file_extension` ("fo") | Pfad zur Saxon-JAR | | `ApacheFop` | `id`, `version`, `path_to_dir`, `output_file_extension` ("pdf") | FOP-Installationsverzeichnis | | `DiffPdf` | `id`, `version`, `path_to_binary_file`, `default_params`, `output_file_extension` ("pdf") | diff-pdf-Binary + Standardparameter | | `XslDir` | `id`, `name`, `path_to_root_dir` | Wurzelverzeichnis der XSL-Dateien | | `PostgreSqlDb` | `id`, `name`, `host`, `port` (5432), `database`, `username`, `password`, `ssl_mode`, `timeout` (10) | Datenbankverbindung | ### AppSettings-Listen ```python java_vms: list[JavaVm] = [] diff_pdfs: list[DiffPdf] = [] saxon_jars: list[SaxonJar] = [] apache_fops: list[ApacheFop] = [] xsl_dirs: list[XslDir] = [] pdf_projects: list[Project] = [] postgresql_dbs: list[PostgreSqlDb] = [] ``` ### Worker-Pool-Einstellungen | Feld | Standard | Beschreibung | |------|----------|-------------| | `max_workers` | 8 | Anzahl paralleler Worker pro Pool | | `use_saxon_worker_pool` | True | Saxon-Pool aktivieren (benötigt JDK) | | `saxon_xslt_version` | `XSLT_2_0_3_0` | XSLT-Version: `1.0` (JAXP) oder `2.0/3.0` (s9api) | | `use_fop_worker_pool` | True | FOP-Pool aktivieren (benötigt JDK) | ### UI-Zustand | Feld | Typ | Beschreibung | |------|-----|-------------| | `theme` | `str \| None` | Qt-Theme-Name | | `window_geometry` | `tuple[int,int,int,int] \| None` | (x, y, width, height) | | `splitter_sizes` | `list[int] \| None` | Splitter-Positionen | | `tree_column_widths` | `list[int] \| None` | TreeWidget-Spaltenbreiten | | `graph_layout_settings` | `GraphLayoutSettings` | vis.js Layout-Parameter | ### Speichern `app_settings.save()` serialisiert das gesamte Modell als JSON (`model_dump_json(indent=4)`) an den plattformspezifischen Konfigurationspfad. ## Projekt-Modell: Project `Project` referenziert Tool-Konfigurationen über IDs: ```python class Project(BaseModel): id: int name: str project_dir: Path java_vm_id: int # → app_settings.java_vms diff_pdf_id: int # → app_settings.diff_pdfs saxon_jar_id: int # → app_settings.saxon_jars apache_fop_id: int # → app_settings.apache_fops xsl_dir_id: int # → app_settings.xsl_dirs postgre_sql_db_id: int # → app_settings.postgresql_dbs fop_config_dir: Path | None xslt_params: dict[str, str] # Projektweite XSLT-Parameter ``` Hilfsmethoden (`getXsl()`, `getJavaVm()`, `getSaxon()`, `getApacheFop()`, `getDiffPdf()`, `getPostgreSqlDb()`) lösen IDs in Anzeigewerte auf. ## Projektdaten: ProjectData `ProjectData` wird pro Projekt in `project.yaml` gespeichert: ```python class ProjectData(BaseModel): nodes: list[TreeNode] = [] expanded_nodes: list[tuple] | None = None ``` Die Methode `writeSettings(project_dir)` serialisiert das Modell als YAML in `{project_dir}/project.yaml`. ## Baumstruktur: TreeNode → XslFile → XmlFile ``` TreeNode ├── children: list[TreeNode | XslFile] ├── id: tuple # Eindeutige ID als Tuple ├── bez: str # Bezeichnung └── xslt_params: dict[str, str] # Knotenspezifische XSLT-Parameter XslFile ├── id: tuple ├── bez: str ├── xsl_file: Path # Pfad zur XSL-Datei (absolut) ├── xslt_params: dict[str, str] └── xmls: list[XmlFile] XmlFile ├── xml: Path # Pfad zur XML-Datei (relativ zu project_dir) └── hashsum: str | None # blake2b-Hash oder None ``` Die `id` als Tuple ermöglicht hierarchische Adressierung – z.B. `(1, 2, 3)` für den dritten XSL-Knoten unter dem zweiten TreeNode unter dem ersten Root-Knoten. ### XSLT-Parameter-Vererbung XSLT-Parameter werden hierarchisch vererbt: Projektweite Parameter (`Project.xslt_params`) werden von Knoten-Parametern (`TreeNode.xslt_params`) überschrieben, die wiederum von XSL-Datei-Parametern (`XslFile.xslt_params`) überschrieben werden. Die Methode `_collect_parent_params()` im `TreeManagerMixin` sammelt alle Parameter entlang des Pfades. ## Hash-System (blake2b) ### Berechnung `calculate_blake2b_hash()` in `src/utils.py`: - Verwendet `hashlib.blake2b()` - Format: `blake2b:<64-Zeichen-Hexdigest>` - Wird beim Projekt-Laden für alle XML-Dateien ohne existierenden Hash berechnet - Asynchron via `XmlHashCalculatorThread` (`src/ui/threads.py`) ### Duplikatserkennung Beim Zuordnen von XML-Dateien zu XSL-Knoten (Drag-and-Drop oder Dialog): 1. Hash der neuen Datei berechnen 2. Existierender Hash in `XmlFile.hashsum` wird verglichen 3. Bei Übereinstimmung wird die Datei als Duplikat erkannt und nicht erneut zugewiesen 4. Hashes werden in `project.yaml` persistiert Details: `docs/blake2b_hash_implementation.md` und `docs/xml_hash_duplicate_detection.md` ## PostgreSQL-Integration ### Verbindungsaufbau `PostgreSqlDb` unterstützt SSL-Modi: | Enum-Wert | Bedeutung | |-----------|-----------| | `DISABLE` | Kein SSL | | `ALLOW` | SSL optional | | `PREFER` | SSL bevorzugt (Standard) | | `REQUIRE` | SSL erforderlich | | `VERIFY_CA` | SSL mit CA-Zertifikat-Verifikation | | `VERIFY_FULL` | SSL mit vollständiger Verifikation | ### Abfrage-Ausführung `DatabaseQueryThread` (`src/ui/mixins/database.py`): - Verwendet `polars.read_database_uri()` mit `engine="connectorx"` - Connection-String wird aus `PostgreSqlDb`-Feldern gebaut - Ergebnis wird als Polars DataFrame sortiert nach `reporttyp_bez`, `report_bez`, `repfile_bez` ### Obsolete-Erkennung Nach dem DB-Import vergleicht `obsolete_detector.py` die geladenen XslFile-IDs mit den Projekt-Einträgen. Veraltete Einträge (im Projekt, aber nicht mehr in der DB) werden im `ObsoleteEntriesDialog` angezeigt und können entfernt werden. ## Enums | Enum | Werte | Verwendung | |------|-------|------------| | `XsltVersion` | `XSLT_1_0`, `XSLT_2_0_3_0` | Auswahl der Saxon-API (JAXP vs s9api) | | `SSLMode` | `DISABLE` bis `VERIFY_FULL` | PostgreSQL-SSL-Modus | | `GraphLayout` | `BARNES_HUT`, `FORCE_ATLAS2`, `REPULSION`, `HIERARCHICAL` | vis.js Layout-Modus | | `HierarchicalDirection` | `UD`, `DU`, `LR`, `RL` | Hierarchisches Layout: Richtung | | `HierarchicalSortMethod` | `HUBSIZE`, `DIRECTED` | Hierarchisches Layout: Sortierung |