001package gudusoft.gsqlparser.dlineage.impl.powerquery;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.TGSqlParser;
005
006import java.util.ArrayList;
007import java.util.List;
008
009/**
010 * Result of running {@link TPowerQueryAnalyzer} over a Power Query
011 * document.  Contains both raw navigation-style references and the
012 * inner-SQL-parser instance(s) produced for {@code Value.NativeQuery}
013 * steps.
014 *
015 * <p>Callers typically inspect:
016 *
017 * <ul>
018 *   <li>{@link #getNativeQueryReferences()} — iterate each entry's
019 *       {@link NativeQueryRef#innerParser} to harvest column-level
020 *       lineage via the usual {@code DataFlowAnalyzer}/{@code TGetTableColumn}
021 *       machinery.</li>
022 *   <li>{@link #getNavigationReferences()} — iterate each entry's
023 *       {@link NavigationRef#syntheticSelect} to feed into the downstream
024 *       lineage pipeline as synthetic SELECTs.</li>
025 *   <li>{@link #getWarnings()} — surface any "did not fully understand"
026 *       notices for diagnostic display.</li>
027 * </ul>
028 */
029public class PowerQueryLineageResult {
030
031    public static class NamedPart {
032        public final String kind;
033        public final String name;
034        public NamedPart(String kind, String name) {
035            this.kind = kind;
036            this.name = name;
037        }
038        @Override public String toString() {
039            return (kind == null ? "?" : kind) + "=" + name;
040        }
041    }
042
043    public static class NativeQueryRef {
044        public String stepName;
045        public String decodedSql;
046        public EDbVendor resolvedVendor;
047        public TGSqlParser innerParser;
048        public int innerParseReturnCode = -1;
049    }
050
051    public static class NavigationRef {
052        public String stepName;
053        public EDbVendor resolvedVendor;
054        public final List<NamedPart> segments = new ArrayList<>();
055        public String syntheticSelect;
056
057        public void addSegment(String kind, String name) {
058            segments.add(new NamedPart(kind, name));
059        }
060    }
061
062    private final List<NativeQueryRef> nativeQueries = new ArrayList<>();
063    private final List<NavigationRef> navigations = new ArrayList<>();
064    private final List<String> warnings = new ArrayList<>();
065
066    public List<NativeQueryRef> getNativeQueryReferences() { return nativeQueries; }
067    public List<NavigationRef> getNavigationReferences()   { return navigations; }
068    public List<String> getWarnings()                       { return warnings; }
069
070    void addNativeQuery(NativeQueryRef ref) { if (ref != null) nativeQueries.add(ref); }
071    void addNavigation(NavigationRef ref)   { if (ref != null) navigations.add(ref); }
072    public void addWarning(String w)        { if (w != null) warnings.add(w); }
073
074    public boolean isEmpty() {
075        return nativeQueries.isEmpty() && navigations.isEmpty();
076    }
077}