001package gudusoft.gsqlparser.ir.semantic.diff; 002 003import java.util.ArrayList; 004import java.util.Collections; 005import java.util.EnumMap; 006import java.util.LinkedHashMap; 007import java.util.List; 008import java.util.Map; 009 010/** 011 * Result of comparing two {@link CanonicalLineageModel} projections of the 012 * same SQL. 013 */ 014public final class DivergenceReport { 015 016 private final String sqlName; 017 private final CanonicalLineageModel irModel; 018 private final CanonicalLineageModel dlineageModel; 019 private final List<Divergence> divergences; 020 private final Map<DivergenceClass, Integer> summary; 021 022 public DivergenceReport(String sqlName, 023 CanonicalLineageModel irModel, 024 CanonicalLineageModel dlineageModel, 025 List<Divergence> divergences) { 026 if (sqlName == null || sqlName.isEmpty()) { 027 throw new IllegalArgumentException("sqlName must be non-empty"); 028 } 029 if (irModel == null || dlineageModel == null || divergences == null) { 030 throw new IllegalArgumentException("models and divergences must not be null"); 031 } 032 this.sqlName = sqlName; 033 this.irModel = irModel; 034 this.dlineageModel = dlineageModel; 035 this.divergences = Collections.unmodifiableList(new ArrayList<>(divergences)); 036 037 // Always include every class with a numeric count (zero if absent). 038 // Use a LinkedHashMap with a fixed enum-name iteration order so the 039 // exporter doesn't depend on EnumMap's internal traversal. 040 Map<DivergenceClass, Integer> counts = new EnumMap<>(DivergenceClass.class); 041 for (DivergenceClass c : DivergenceClass.values()) counts.put(c, 0); 042 for (Divergence d : this.divergences) { 043 counts.put(d.getKind(), counts.get(d.getKind()) + 1); 044 } 045 Map<DivergenceClass, Integer> ordered = new LinkedHashMap<>(); 046 for (DivergenceClass c : DivergenceClass.values()) ordered.put(c, counts.get(c)); 047 this.summary = Collections.unmodifiableMap(ordered); 048 } 049 050 public String getSqlName() { 051 return sqlName; 052 } 053 054 public CanonicalLineageModel getIrModel() { 055 return irModel; 056 } 057 058 public CanonicalLineageModel getDlineageModel() { 059 return dlineageModel; 060 } 061 062 public List<Divergence> getDivergences() { 063 return divergences; 064 } 065 066 /** Class → count, including zero counts. Iteration order is enum declaration order. */ 067 public Map<DivergenceClass, Integer> getSummary() { 068 return summary; 069 } 070}