001package gudusoft.gsqlparser.common.structured;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.nodes.TParseTreeNode;
005
006import java.util.ArrayList;
007import java.util.Collections;
008import java.util.List;
009
010/**
011 * Vendor-neutral description of a structured-dataflow operation, e.g. Spark
012 * {@code explode(from_json(col, schema))}. Consumed by the dlineage and
013 * semantic IR layers. Built only by dialect-specific
014 * {@link gudusoft.gsqlparser.common.structured.StructuredDataflowAdapter}s.
015 */
016public final class StructuredDataflowDescriptor {
017
018    private final EDbVendor dialect;
019    private final TParseTreeNode syntaxNode;
020    private final StructuredValueSource source;
021    private final StructuredType sourceType;
022    private final StructuredExpansion expansion;
023    private final List<StructuredFieldBinding> fieldBindings;
024    private final StructuredFallbackPolicy fallbackPolicy;
025
026    private StructuredDataflowDescriptor(Builder b) {
027        this.dialect = b.dialect;
028        this.syntaxNode = b.syntaxNode;
029        this.source = b.source;
030        this.sourceType = b.sourceType;
031        this.expansion = b.expansion;
032        this.fieldBindings = Collections.unmodifiableList(new ArrayList<>(b.fieldBindings));
033        this.fallbackPolicy = b.fallbackPolicy != null
034                ? b.fallbackPolicy
035                : StructuredFallbackPolicy.USE_GENERIC_FUNCTION_LINEAGE;
036    }
037
038    public EDbVendor getDialect() {
039        return dialect;
040    }
041
042    public TParseTreeNode getSyntaxNode() {
043        return syntaxNode;
044    }
045
046    public StructuredValueSource getSource() {
047        return source;
048    }
049
050    public StructuredType getSourceType() {
051        return sourceType;
052    }
053
054    public StructuredExpansion getExpansion() {
055        return expansion;
056    }
057
058    public List<StructuredFieldBinding> getFieldBindings() {
059        return fieldBindings;
060    }
061
062    public StructuredFallbackPolicy getFallbackPolicy() {
063        return fallbackPolicy;
064    }
065
066    public static Builder builder() {
067        return new Builder();
068    }
069
070    public static final class Builder {
071        private EDbVendor dialect;
072        private TParseTreeNode syntaxNode;
073        private StructuredValueSource source;
074        private StructuredType sourceType;
075        private StructuredExpansion expansion;
076        private List<StructuredFieldBinding> fieldBindings = new ArrayList<>();
077        private StructuredFallbackPolicy fallbackPolicy;
078
079        public Builder dialect(EDbVendor d) { this.dialect = d; return this; }
080        public Builder syntaxNode(TParseTreeNode n) { this.syntaxNode = n; return this; }
081        public Builder source(StructuredValueSource s) { this.source = s; return this; }
082        public Builder sourceType(StructuredType t) { this.sourceType = t; return this; }
083        public Builder expansion(StructuredExpansion e) { this.expansion = e; return this; }
084        public Builder addFieldBinding(StructuredFieldBinding fb) {
085            this.fieldBindings.add(fb); return this;
086        }
087        public Builder fieldBindings(List<StructuredFieldBinding> fbs) {
088            this.fieldBindings = new ArrayList<>(fbs); return this;
089        }
090        public Builder fallbackPolicy(StructuredFallbackPolicy p) {
091            this.fallbackPolicy = p; return this;
092        }
093
094        public StructuredDataflowDescriptor build() {
095            if (source == null) {
096                throw new IllegalStateException("source is required");
097            }
098            if (expansion == null) {
099                throw new IllegalStateException("expansion is required");
100            }
101            return new StructuredDataflowDescriptor(this);
102        }
103    }
104}