Files
xsl-validator/docs/xml_hash_duplicate_detection.md
T

308 lines
11 KiB
Markdown
Raw Normal View History

# XML-Hash-Duplikatserkennung und intelligente Dateinamen-Verwaltung
## Übersicht
Diese Dokumentation beschreibt die erweiterte Funktionalität zur Hash-basierten Duplikatserkennung von XML-Dateien und intelligenten Dateinamen-Verwaltung in der XSL-Validator-Anwendung.
## Neue Funktionalitäten
### 1. Hash-basierte Duplikatserkennung
Beim Hinzufügen neuer XML-Dateien wird automatisch geprüft, ob bereits eine Datei mit identischem Inhalt (basierend auf blake2b-Hash) im Projekt vorhanden ist.
**Vorteile:**
- Vermeidung von Datei-Duplikaten
- Automatische Zuordnung vorhandener Dateien
- Speicherplatz-Optimierung
- Konsistente Datenintegrität
### 2. Intelligente Dateinamen-Verwaltung
Bei Dateinamen-Konflikten werden automatisch alternative Namen im Format `datei_1.xml`, `datei_2.xml`, etc. generiert.
**Features:**
- Automatische Generierung alternativer Dateinamen
- Benutzerfreundlicher Auswahl-Dialog
- Vermeidung von Überschreibungen
- Konsistente Namenskonventionen
### 3. Nahtlose Integration
Die neuen Funktionalitäten sind vollständig in bestehende Workflows integriert:
- **Drag & Drop**: Automatische Hash-Prüfung beim Ziehen von XML-Dateien
- **Kontextmenü**: Hash-Prüfung beim manuellen Hinzufügen über "XML-Datei hinzufügen"
## Technische Implementierung
### Kern-Architektur
```python
def _assign_xml_to_xsl_nodes(self, xml_file_path: Path, selected_xsl_nodes: list):
# 1. Hash berechnen
file_hash = self._calculate_hash_for_file(xml_file_path)
# 2. Duplikatsprüfung
existing_xml = self._find_xml_file_by_hash(file_hash)
if existing_xml:
# 3. Automatische Zuordnung bei Hash-Match
self._assign_existing_xml_to_nodes(existing_xml, selected_xsl_nodes)
else:
# 4. Neue Datei verarbeiten
self._process_new_xml_file(xml_file_path, selected_xsl_nodes, file_hash)
```
### Neue Hilfsmethoden
#### Hash-Vergleich und Suche
```python
def _get_all_project_xml_files(self) -> List[XmlFile]:
"""Sammelt alle XML-Dateien aus dem gesamten Projekt."""
def _find_xml_file_by_hash(self, target_hash: str) -> XmlFile | None:
"""Sucht XML-Datei mit spezifischem Hash im Projekt."""
def _calculate_hash_for_file(self, file_path: Path) -> str | None:
"""Berechnet blake2b-Hash für eine Datei."""
```
#### Dateinamen-Verwaltung
```python
def _generate_alternative_filename(self, original_path: Path, xml_dir: Path) -> Path:
"""Generiert alternative Dateinamen im Format: datei_1.xml, datei_2.xml, ..."""
def _is_filename_used_in_project(self, relative_xml_path: Path) -> bool:
"""Prüft ob Dateiname bereits im Projekt verwendet wird."""
def _show_filename_selection_dialog(self, original_name: str, alternative_paths: List[Path]) -> Path | None:
"""Zeigt Dialog zur Auswahl alternativer Dateinamen."""
```
#### Verarbeitungslogik
```python
def _assign_existing_xml_to_nodes(self, existing_xml: XmlFile, selected_xsl_nodes: list):
"""Ordnet vorhandene XML-Datei (Hash-Match) den XSL-Knoten zu."""
def _process_new_xml_file(self, xml_file_path: Path, selected_xsl_nodes: list, file_hash: str | None):
"""Verarbeitet neue XML-Datei (kein Hash-Match)."""
```
## Benutzer-Workflows
### Workflow 1: Hash-Duplikat gefunden
1. Benutzer fügt XML-Datei hinzu (Drag&Drop oder Kontextmenü)
2. System berechnet Hash der neuen Datei
3. Hash-Match mit vorhandener Datei gefunden
4. **Automatische Zuordnung**: Vorhandene Datei wird den ausgewählten XSL-Knoten zugeordnet
5. Erfolgsmeldung: "XML-Datei mit gleichem Inhalt bereits vorhanden - automatisch zugeordnet"
### Workflow 2: Neue Datei, Dateiname-Konflikt
1. Benutzer fügt XML-Datei hinzu
2. Kein Hash-Match gefunden (neue Datei)
3. Dateiname bereits vorhanden
4. **Dialog angezeigt**: Auswahl alternativer Dateinamen
5. Benutzer wählt gewünschten Namen
6. Datei wird kopiert und zugeordnet
7. Erfolgsmeldung mit Hinweis auf Umbenennung
### Workflow 3: Neue Datei, kein Konflikt
1. Benutzer fügt XML-Datei hinzu
2. Kein Hash-Match gefunden
3. Dateiname verfügbar
4. **Direkte Verarbeitung**: Datei wird kopiert und zugeordnet
5. Standard-Erfolgsmeldung
## Benutzeroberfläche
### Hash-Duplikat Dialog
```
┌─────────────────────────────────────────┐
│ XML-Datei zugeordnet │
├─────────────────────────────────────────┤
│ Eine XML-Datei mit gleichem Inhalt war │
│ bereits im Projekt vorhanden. │
│ │
│ Die vorhandene Datei 'dokument.xml' │
│ wurde automatisch zu 2 XSL-Knoten │
│ zugeordnet. │
├─────────────────────────────────────────┤
│ [OK] │
└─────────────────────────────────────────┘
```
### Dateiname-Auswahl Dialog
```
┌─────────────────────────────────────────┐
│ Dateiname auswählen │
├─────────────────────────────────────────┤
│ Eine Datei mit dem Namen 'test.xml' │
│ existiert bereits. │
│ │
│ Bitte wählen Sie einen alternativen │
│ Dateinamen: │
│ │
│ ○ test_1.xml │
│ ● test_2.xml │
│ ○ test_3.xml │
│ ○ test_4.xml │
├─────────────────────────────────────────┤
│ [OK] [Abbrechen] │
└─────────────────────────────────────────┘
```
## Performance-Optimierungen
### Hash-Berechnung
- **Synchrone Berechnung** für neue Dateien (akzeptable Verzögerung)
- **Effiziente blake2b-Implementierung** aus Python's hashlib
- **Caching** von Hash-Werten in XmlFile-Objekten
### Projekt-weite Suche
- **Einmalige Sammlung** aller XML-Dateien pro Operation
- **Optimierte Rekursion** durch die Node-Struktur
- **Duplikat-Vermeidung** bei der Sammlung
### Dateinamen-Generierung
- **Sequenzielle Suche** mit Sicherheitsgrenze (max. 1000 Versuche)
- **Fallback-Mechanismus** mit Zeitstempel
- **Kombinierte Prüfung** von physischer Existenz und Projekt-Verwendung
## Fehlerbehandlung
### Hash-Berechnung Fehler
```python
try:
file_hash = self._calculate_hash_for_file(xml_file_path)
except Exception as e:
logger.error(f"Hash-Berechnung fehlgeschlagen: {e}")
# Fortsetzung ohne Hash (Fallback-Verhalten)
```
### Datei-Zugriff Fehler
```python
if not file_path.exists():
logger.warning(f"Datei nicht gefunden: {file_path}")
return None
```
### Dialog-Fehler
```python
try:
selected_path = self._show_filename_selection_dialog(...)
except Exception as e:
logger.error(f"Dialog-Fehler: {e}")
# Fallback: Ersten alternativen Namen verwenden
return alternative_paths[0] if alternative_paths else None
```
## Logging
Das System verwendet strukturiertes Logging für alle Operationen:
```python
logger.info(f"Hash-Duplikat gefunden: {existing_xml.xml} hat gleichen Hash wie {xml_file_path.name}")
logger.debug(f"Hash-Vergleich: {len(xml_files)} XML-Dateien im Projekt gefunden")
logger.warning(f"Hash-Berechnung für {xml_file_path} fehlgeschlagen")
logger.error(f"Fehler beim Zuordnen der XML-Datei: {str(e)}")
```
## Testing
### Umfassende Test-Suite
Die Implementierung wird durch eine umfassende Test-Suite validiert:
```bash
uv run python test_xml_hash_duplicate_detection.py
```
**Test-Abdeckung:**
- Hash-Berechnung und -Konsistenz
- XmlFile-Modell mit Hash-Unterstützung
- Duplikatserkennung-Logik
- Alternative Dateinamen-Generierung
- Integration Workflow
### Test-Ergebnisse
```
=== Test: Hash-Berechnung ===
[OK] Hash-Berechnung funktioniert korrekt
=== Test: XmlFile-Modell mit Hash ===
[OK] XmlFile-Modell mit Hash funktioniert korrekt
=== Test: Duplikatserkennung-Logik ===
[OK] Duplikatserkennung-Logik funktioniert korrekt
=== Test: Alternative Dateinamen-Generierung ===
[OK] Alternative Dateinamen-Generierung funktioniert korrekt
=== Test: Integration Workflow ===
[OK] Integration Workflow funktioniert korrekt
[SUCCESS] Alle Tests erfolgreich abgeschlossen!
```
## Kompatibilität
### Rückwärtskompatibilität
- **Bestehende Projekte** funktionieren unverändert
- **Vorhandene XML-Dateien** ohne Hash werden automatisch nachberechnet
- **Keine Breaking Changes** in der API
### Datenformat
- **XmlFile.hashsum** ist optional (kann None sein)
- **Automatische Migration** beim Projektladen
- **Graceful Degradation** bei Hash-Fehlern
## Wartung und Erweiterung
### Konfigurierbarkeit
Die Implementierung kann einfach erweitert werden:
```python
# Verschiedene Hash-Algorithmen
def _calculate_hash(self, file_path: Path, algorithm: str = "blake2b"):
if algorithm == "blake2b":
return self._calculate_blake2b_hash(file_path)
elif algorithm == "sha256":
return self._calculate_sha256_hash(file_path)
# Konfigurierbare Dateinamen-Formate
def _generate_alternative_filename(self, original_path: Path, format_pattern: str = "{name}_{counter}{ext}"):
# Implementierung mit konfigurierbaren Mustern
```
### Monitoring
```python
# Performance-Metriken
start_time = time.time()
# ... Operation ...
duration = time.time() - start_time
logger.info(f"Hash-Vergleich abgeschlossen in {duration:.3f}s")
```
## Changelog
### Version 1.0.0 (2025-01-20)
- ✅ Hash-basierte Duplikatserkennung im gesamten Projekt
- ✅ Automatische Zuordnung bei Hash-Match
- ✅ Intelligente Dateinamen-Generierung (datei_1.xml Format)
- ✅ Integration in Drag&Drop und Kontextmenü
- ✅ Benutzerfreundliche Dateiname-Auswahl-Dialoge
- ✅ Umfassende Test-Suite
- ✅ Strukturiertes Logging
- ✅ Fehlerbehandlung und Fallback-Mechanismen
## Fazit
Die erweiterte XML-Hash-Duplikatserkennung bietet eine robuste, benutzerfreundliche Lösung für die intelligente Verwaltung von XML-Dateien in XSL-Validator-Projekten. Die Implementierung ist vollständig getestet, performant und nahtlos in bestehende Workflows integriert.