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}