Giriş
Hukuk ekipleri veya adli analistler bir belgenin değiştirilmediğini kanıtlamaları gerektiğinde, yalnızca görünen içeriğe bakmak yeterli değildir. Yazar, oluşturulma tarihi veya revizyon numarası gibi gizli özellikler, dosyayı kimin ve ne zaman dokunduğunu ortaya çıkarabilir. Bu ince değişiklikleri belge sürümleri arasında tespit etmek, genellikle her özelliğin manuel olarak incelenmesini gerektiren, zaman alıcı ve hata yapmaya açık bir sorundur.
GroupDocs.Metadata for Java, her meta veri alanını programatik olarak çıkarmak ve iki sürüm arasında yapılandırılmış bir fark (diff) hesaplamak için bir yol sunar. Bu öğreticide üç pratik yaklaşımı karşılaştıracağız: tam meta veri farkı, odaklanmış sahiplik değişikliği tespiti ve revizyon geçmişi analizi. Her yöntem, kısa ve kopyala‑yapıştırılabilir kod örnekleriyle gösterilecek ve sonuçların denetim raporlaması için CSV ya da JSON olarak dışa aktarılması da gösterilecektir.
Bunu, aylar süren birden çok tarafça düzenlenen bir sözleşmeyi incelerken fark ettim; görünen metin aynıydı, ancak sahiplik alanları sessizce değişmişti.
İki belge sürümü arasındaki meta veri alanlarının hangilerinin değiştiğini nasıl anlayabilirim?
GroupDocs.Metadata, her dosyayı yükler, erişilebilir tüm özellikleri bir haritaya (map) çıkarır ve ardından eklemeler, kaldırmalar ve değişiklikler için anahtarları iterasyonla sınıflandırır. Kütüphane, yerleşik ve özel etiketleri (tags) yönetir, böylece format‑özel ayrıştırıcılar yazmadan tam bir resim elde edersiniz. Sonuç, uyumluluk raporları için sorgulayabileceğiniz ya da serileştirebileceğiniz bir MetadataDiff nesnesidir.
Önkoşullar
- Java 8 veya üzeri
- GroupDocs.Metadata for Java 24.7 ([geçici lisans][TEMP_LICENSE_URL])
- Karşılaştırmak istediğiniz iki belge dosyası (ör.
contract_v1.pdfvecontract_v2.pdf)
Kurulum
Maven üzerinden bağımlılığı ekleyin:
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-metadata</artifactId>
<version>24.7</version>
</dependency>
Yöntem 1 – Tam Meta Veri Farkı
Bu yöntem, her iki sürümden tüm meta veri özelliklerini çıkarır ve eklenen, kaldırılan ve değişen girdileri raporlar.
// CompareMetadataSets.run – returns a MetadataDiff object
Map<String, String> v1 = ExtractAllMetadata.run(pathV1);
Map<String, String> v2 = ExtractAllMetadata.run(pathV2);
MetadataDiff diff = new MetadataDiff();
// Detect added and changed properties
for (Map.Entry<String, String> e : v2.entrySet()) {
String key = e.getKey();
String val = e.getValue();
if (!v1.containsKey(key)) {
diff.added.put(key, val); // New property in v2
} else if (!v1.get(key).equals(val)) {
diff.changed.put(key, new String[]{v1.get(key), val}); // Value changed
}
}
// Detect removed properties
for (Map.Entry<String, String> e : v1.entrySet()) {
if (!v2.containsKey(e.getKey())) {
diff.removed.put(e.getKey(), e.getValue());
}
}
return diff;
Temel noktalar:
- Kapsamlı: Özel etiketler dahil tüm etiketleri yakalar.
- Basit harita mantığı: Harici bir diff kütüphanesi gerekmez.
- Sonuç nesnesi:
added,removedvechangedharitaları daha fazla işleme hazırdır.
💡 İpucu: Düzenleyici uyumluluk için tam bir denetim izi gerektiğinde bunu kullanın.
Yöntem 2 – Sahiplik Değişikliklerini Tespit Etme
Hukuki anlaşmazlıklar genellikle bir belgenin kim tarafından oluşturulduğu veya düzenlendiği üzerine odaklanır. Bu yöntem, Creator, Editor, Manager ve Company gibi kişi‑ilişkili etiketlere odaklanır.
// DetectOwnershipChanges.run – returns a map of changed ownership fields
Map<String, String> v1 = readOwnership(pathV1);
Map<String, String> v2 = readOwnership(pathV2);
Set<String> allKeys = new HashSet<>(v1.keySet());
allKeys.addAll(v2.keySet());
Map<String, String[]> changes = new LinkedHashMap<>();
for (String key : allKeys) {
String oldVal = v1.getOrDefault(key, "<missing>");
String newVal = v2.getOrDefault(key, "<missing>");
if (!oldVal.equals(newVal)) {
changes.put(key, new String[]{oldVal, newVal});
}
}
return changes;
readOwnership yalnızca ilgili etiketleri çeker:
Map<String, String> result = new LinkedHashMap<>();
try (Metadata metadata = new Metadata(path)) {
if (metadata.getFileFormat() == FileFormat.Unknown) return result;
for (MetadataProperty p : metadata.findProperties(
new ContainsTagSpecification(Tags.getPerson().getCreator())
.or(new ContainsTagSpecification(Tags.getPerson().getEditor()))
.or(new ContainsTagSpecification(Tags.getPerson().getManager()))
.or(new ContainsTagSpecification(Tags.getCorporate().getCompany())))) {
String value = "";
if (p.getValue() != null && p.getValue().getRawValue() != null) {
value = String.valueOf(p.getValue().getRawValue());
}
result.put(p.getName(), value);
}
}
return result;
Temel noktalar:
- Hedefli: Yalnızca kimlik‑taşıyan özellikler incelenir.
- Açık çıktı: Her giriş
[eski, yeni]değerlerini gösteren bir harita döndürür. - Uyumluluk‑hazır: e‑keşif veya sözleşme‑sahipliği anlaşmazlıkları için mükemmeldir.
💡 İpucu: Hem genişlik hem de derinlik istiyorsanız tam farkla birleştirin.
Yöntem 3 – Revizyon Geçmişi Değişikliklerini Tespit Etme
Revizyon numaraları, düzenleme zaman damgaları ve baskı tarihleri son kullanıcılar için görünmez ancak adli zaman çizelgeleri için kritiktir. Bu yöntem zaman‑ilişkili etiketleri izole eder.
Map<String, String> v1 = readRevision(pathV1);
Map<String, String> v2 = readRevision(pathV2);
Set<String> allKeys = new HashSet<>(v1.keySet());
allKeys.addAll(v2.keySet());
Map<String, String[]> changes = new LinkedHashMap<>();
for (String key : allKeys) {
String oldVal = v1.getOrDefault(key, "<missing>");
String newVal = v2.getOrDefault(key, "<missing>");
if (!oldVal.equals(newVal)) {
changes.put(key, new String[]{oldVal, newVal});
}
}
return changes;
readRevision Modified, Created ve Printed zaman damgalarını çıkarır:
Map<String, String> result = new LinkedHashMap<>();
try (Metadata metadata = new Metadata(path)) {
if (metadata.getFileFormat() == FileFormat.Unknown) return result;
for (MetadataProperty p : metadata.findProperties(
new ContainsTagSpecification(Tags.getTime().getModified())
.or(new ContainsTagSpecification(Tags.getTime().getCreated()))
.or(new ContainsTagSpecification(Tags.getTime().getPrinted())))) {
String value = "";
if (p.getValue() != null && p.getValue().getRawValue() != null) {
value = String.valueOf(p.getValue().getRawValue());
}
result.put(p.getName(), value);
}
}
return result;
Temel noktalar:
- Zaman çizelgesi yeniden oluşturma: Dosyanın kaç kez düzenlendiğini veya basıldığını gösterir.
- Sayısal farklar: Şüpheli hızlı revizyonları tespit etmek için yar