001package gudusoft.gsqlparser.dlineage.dynamicsql;
002
003import java.util.ArrayList;
004import java.util.Collections;
005import java.util.List;
006
007/**
008 * Top-level result of {@code DataFlowAnalyzer.resolveDynamicSqlLineage}: one
009 * {@link DynamicSiteResult} per dynamic-SQL EXEC site discovered in the
010 * procedure, plus convenience views over the resolved edges and the unresolved
011 * sites.
012 */
013public final class DynamicLineageResult {
014
015    private final String sourceProc;
016    private final String bindingHash;
017    private final List<DynamicSiteResult> sites = new ArrayList<DynamicSiteResult>();
018
019    DynamicLineageResult(String sourceProc, String bindingHash) {
020        this.sourceProc = sourceProc;
021        this.bindingHash = bindingHash;
022    }
023
024    void addSite(DynamicSiteResult site) {
025        sites.add(site);
026    }
027
028    public String getSourceProc() {
029        return sourceProc;
030    }
031
032    public String getBindingHash() {
033        return bindingHash;
034    }
035
036    public List<DynamicSiteResult> getSites() {
037        return Collections.unmodifiableList(sites);
038    }
039
040    /** All lineage edges across all resolved sites. */
041    public List<DynamicLineageEdge> getAllEdges() {
042        List<DynamicLineageEdge> all = new ArrayList<DynamicLineageEdge>();
043        for (DynamicSiteResult s : sites) {
044            all.addAll(s.getEdges());
045        }
046        return all;
047    }
048
049    /** Projected (data) lineage edges only — dlineage {@code fdd}, excluding join/filter influence. */
050    public List<DynamicLineageEdge> getProjectedEdges() {
051        List<DynamicLineageEdge> all = new ArrayList<DynamicLineageEdge>();
052        for (DynamicSiteResult s : sites) {
053            for (DynamicLineageEdge e : s.getEdges()) {
054                if (e.isProjectedData()) {
055                    all.add(e);
056                }
057            }
058        }
059        return all;
060    }
061
062    /** Sites that could not be reduced — keep as honest diagnostics, do not guess. */
063    public List<DynamicSiteResult> getUnresolvedSites() {
064        List<DynamicSiteResult> out = new ArrayList<DynamicSiteResult>();
065        for (DynamicSiteResult s : sites) {
066            if (!s.isResolved()) {
067                out.add(s);
068            }
069        }
070        return out;
071    }
072
073    public boolean hasResolvedLineage() {
074        for (DynamicSiteResult s : sites) {
075            if (s.isResolved() && !s.getEdges().isEmpty()) {
076                return true;
077            }
078        }
079        return false;
080    }
081
082    @Override
083    public String toString() {
084        return "DynamicLineageResult{proc=" + sourceProc + ", sites=" + sites.size()
085                + ", edges=" + getAllEdges().size() + "}";
086    }
087}