001package gudusoft.gsqlparser.dlineage.dynamicsql;
002
003import java.util.ArrayList;
004import java.util.Collections;
005import java.util.LinkedHashMap;
006import java.util.LinkedHashSet;
007import java.util.List;
008import java.util.Map;
009import java.util.Set;
010
011/**
012 * Public observation result of {@link ProceduralLineageAnalyzer}.
013 *
014 * <p>This result deliberately does not masquerade as a mutated legacy
015 * {@code dataflow}. Composed edges are observations only in every mode.
016 * {@link #getAppliedAdditions()} remains empty until call validity, type
017 * compatibility, actual mutability, and execution context are exhaustively
018 * proven. Every observation carries {@link ShadowSummaryApplier.EdgeOrigin},
019 * {@link ShadowSummaryApplier.ApplicationGate#OBSERVATION_ONLY}, and a stable
020 * application-deferral reason.
021 */
022public final class ProceduralLineageResult {
023
024    private final ProceduralLineageOptions.Mode mode;
025    private final Set<ShadowSummaryApplier.ComposedEdge> observedAdditions;
026    private final Set<ShadowSummaryApplier.ComposedEdge> appliedAdditions;
027    private final List<String> diagnostics;
028    private final Map<RoutineIdentity, RoutineSummary> summaries;
029    private final Map<RoutineIdentity, Integer> fixedPointIterations;
030
031    ProceduralLineageResult(ProceduralLineageOptions.Mode mode,
032            ShadowSummaryApplier.ShadowResult result) {
033        this.mode = mode;
034        this.observedAdditions = Collections.unmodifiableSet(
035                new LinkedHashSet<ShadowSummaryApplier.ComposedEdge>(
036                        result.getAdditions()));
037        this.appliedAdditions =
038                Collections.<ShadowSummaryApplier.ComposedEdge>emptySet();
039        this.diagnostics = Collections.unmodifiableList(
040                new ArrayList<String>(result.getDiagnostics()));
041        this.summaries = Collections.unmodifiableMap(
042                new LinkedHashMap<RoutineIdentity, RoutineSummary>(
043                        result.getSummaries()));
044        this.fixedPointIterations = Collections.unmodifiableMap(
045                new LinkedHashMap<RoutineIdentity, Integer>(
046                        result.getFixedPointIterations()));
047    }
048
049    public ProceduralLineageOptions.Mode getMode() { return mode; }
050
051    /** Isolated summary-composed edges; non-empty in SHADOW and ENHANCED. */
052    public Set<ShadowSummaryApplier.ComposedEdge> getObservedAdditions() {
053        return observedAdditions;
054    }
055
056    /**
057     * Reserved future additive projection. Empty in LEGACY, SHADOW, and
058     * ENHANCED while call-validity proof is incomplete. Consumers must not
059     * merge {@link #getObservedAdditions()} into an authoritative model.
060     */
061    public Set<ShadowSummaryApplier.ComposedEdge> getAppliedAdditions() {
062        return appliedAdditions;
063    }
064
065    public List<String> getDiagnostics() { return diagnostics; }
066    public Map<RoutineIdentity, RoutineSummary> getSummaries() { return summaries; }
067    public Map<RoutineIdentity, Integer> getFixedPointIterations() {
068        return fixedPointIterations;
069    }
070
071    /** Reserved future view; currently always empty. */
072    public Set<ShadowSummaryApplier.ComposedEdge> getReplacementEligible() {
073        return byGate(ShadowSummaryApplier.ApplicationGate.REPLACEMENT_ELIGIBLE);
074    }
075
076    public Set<ShadowSummaryApplier.ComposedEdge> getObservationOnly() {
077        return byGate(ShadowSummaryApplier.ApplicationGate.OBSERVATION_ONLY);
078    }
079
080    /**
081     * @deprecated composed edges are not authorized to augment lineage.
082     * This compatibility view is deliberately always empty.
083     */
084    @Deprecated
085    public Set<ShadowSummaryApplier.ComposedEdge> getAugmentOnly() {
086        return Collections.emptySet();
087    }
088
089    private Set<ShadowSummaryApplier.ComposedEdge> byGate(
090            ShadowSummaryApplier.ApplicationGate gate) {
091        Set<ShadowSummaryApplier.ComposedEdge> result =
092                new LinkedHashSet<ShadowSummaryApplier.ComposedEdge>();
093        for (ShadowSummaryApplier.ComposedEdge edge : observedAdditions) {
094            if (edge.getApplicationGate() == gate) {
095                result.add(edge);
096            }
097        }
098        return Collections.unmodifiableSet(result);
099    }
100}