Files
info 4733ea6b82 chore: OpenWiki-Dokumentation einrichten, AGENTS.md ergänzen
Fügt OpenWiki-Setup (Workflow, Seiten, CLAUDE.md-Verweis) und AGENTS.md
hinzu, damit wiederkehrende Code-Dokumentation automatisch gepflegt wird.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 14:22:57 +02:00

179 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 |