# 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.