EN · DE · RU · FR · ES

#1873: DiffMatchPatch.java

projectforge-common/src/main/java/name/fraser/neil/plaintext/DiffMatchPatch.java Drittanbieter-Bibliothek (eingebettet) — Google diff-match-patch, projectforge-common/src/main/java/name/fraser/neil/plaintext/DiffMatchPatch.java 2464 Zeilen · 1638 Code · 688 Kommentare · 138 leer
Googles diff-match-patch Algorithmus-Bibliothek von Neil Fraser, direkt in ProjectForge unter dem ursprünglichen Paket name.fraser.neil.plaintext eingebettet. Lizenziert unter Apache License 2.0. Bietet synchronen Textvergleich (Diff), unscharfe Suche (Match) und Patch-Anwendung (Patch) — dieselben Algorithmen, die Google Docs, Etherpad und Wikipedias Versionsvergleich antreiben. Wird von ProjectForge für Textänderungsverfolgung und Versionsvergleiche verwendet.

Architektur

Ursprung und Lizenz

Algorithmen-Überblick

Die Bibliothek implementiert drei verwandte Algorithmen, die alle auf Klartext operieren:

1. Diff — Myers' O(ND)-Differenzalgorithmus

Berechnet die minimale Menge an Änderungen, um Text1 in Text2 zu überführen. Der Kernalgorithmus ist Myers' Diff-Algorithmus (1986), der das kürzeste Bearbeitungsskript mit einem O(ND)-Zeit-/Platzansatz findet, wobei N die Summe der Zeichenkettenlängen und D die Anzahl der Unterschiede ist.

2. Match — Bitap-Algorithmus (Shift-Or)

Lokalisiert die beste ungefähre Übereinstimmung für ein Muster innerhalb eines größeren Textes. Verwendet den Bitap-Algorithmus (auch bekannt als Shift-Or oder Baeza-Yates–Gonnet-Algorithmus), der:

3. Patch — Unified-Diff-Format + unscharfe Anwendung

Erstellt Patches (Textdarstellungen von Diffs), die serialisiert, übertragen und auf andere Texte angewendet werden können:

Wichtige Konfigurationsparameter

FeldStandardZweck
Diff_Timeout1,0 SekundenMaximale Sekunden für eine Diff-Berechnung, bevor ein Teilergebnis zurückgegeben wird (0 = unendlich)
Diff_EditCost4Kosten einer leeren Bearbeitungsoperation — höhere Werte erzeugen sauberere, weniger fragmentierte Diffs
Match_Threshold0,5Schwelle für unscharfe Übereinstimmungen (0,0 = exakt, 1,0 = sehr locker)
Match_Distance1000Lokalitätsbonus — Entfernung in Zeichen von der erwarteten Übereinstimmungsposition
Patch_DeleteThreshold0,5Wie genau Löschblöcke mit dem erwarteten Inhalt übereinstimmen müssen, um akzeptiert zu werden
Patch_Margin4Kontextzeichenanzahl um Patch-Hunks herum
Match_MaxBits32Bitbreite für den Bitap-Algorithmus (entspricht der Java-int-Größe)

Datenstruktur: Diff (Innere Klasse)

Diffs werden als LinkedList<Diff> dargestellt, wobei jedes Diff eine innere statische Klasse ist mit:

Internes Hilfsmittel: LinesToCharsResult

Eine Optimierung für große Texte: Konvertiert Zeilen in eindeutige Unicode-Zeichen, führt das Diff auf der komprimierten Darstellung durch und rekonstruiert dann die Ausgabe auf Zeilenebene. Dies reduziert den Vergleichsraum für zeilenorientierten Text (z. B. Quellcode) drastisch.

Importe

ProjectForge-Verwendung

ProjectForge bettet diese Bibliothek ein, anstatt sie als externes JAR zu verwenden. Dies wurde wahrscheinlich aus folgenden Gründen getan:

  1. Die Bibliothek ist stabil und ändert sich selten (die letzte bedeutende Aktualisierung war der Java-Port um 2010)
  2. Das Einbetten vermeidet Abhängigkeitsmanagement-Probleme
  3. Der Paketname (name.fraser.neil.plaintext) ist eindeutig und konfliktfrei
  4. Es könnte kundenspezifische Änderungen für ProjectForge-spezifische Anforderungen geben (obwohl der Code dem Standard-Port zu entsprechen scheint)
DiffMatchPatch wird verwendet, um Änderungen an Textfeldern in ProjectForge-Datenobjekten zu verfolgen — anzuzeigen, was sich zwischen Versionen einer Adresse, Projektbeschreibung oder anderem Textinhalt geändert hat.

Die Bibliothek wurde in mehrere Sprachen portiert (Python, JavaScript, Java, C++, C#, Lua, Dart). Die Java-Version verwendet LinkedList für die Diff-Speicherung, da Diffs hauptsächlich sequenziell durchlaufen werden (kein wahlfreier Zugriff) und der Algorithmus häufig Elemente voranstellt/anhängt.

Git-Verlauf

48a93dedb Farbige Konsolenausgabe. UserGroupCache-Export zum Debuggen und Vergleichen von Arbeiten jetzt möglich. CollectionUtil verbessert. KotlinStringExtension.shortenMiddle() hinzugefügt.