001package gudusoft.gsqlparser.catalog.input.model;
002
003import gudusoft.gsqlparser.EDbVendor;
004
005import java.util.ArrayList;
006import java.util.Collections;
007import java.util.List;
008import java.util.Objects;
009
010/**
011 * Top-level immutable catalog model produced by {@code CatalogInputReader}s and consumed by
012 * the runtime + bridge layers.
013 *
014 * <p>Plan §6 (artifact layout) / §7.1 (schema). Format-agnostic: JSON / YAML / DDL / dbt
015 * manifests / vendor dumps all funnel into this shape.</p>
016 *
017 * <p>The build-time checks here cover only structural invariants. Deeper consistency
018 * (duplicate qualified names, identifier round-trip, table↔column referential integrity)
019 * is enforced by {@code CatalogModelValidator} per plan §9.6 — see Round 3 (T1B.2).</p>
020 */
021public final class UnifiedCatalogModel {
022
023    /** Default {@code apiVersion} carried by manifests that don't set one. Plan Q9. */
024    public static final String DEFAULT_API_VERSION = "1";
025
026    private final String apiVersion;
027    private final EDbVendor vendor;
028    private final IdentifierConfig identifierConfig;
029    private final DefaultsConfig defaults;
030    private final List<CatalogModel> catalogs;
031    private final CatalogSourceInfo sourceInfo;
032
033    private UnifiedCatalogModel(Builder b) {
034        if (b.vendor == null) {
035            throw new IllegalArgumentException("UnifiedCatalogModel.vendor is required");
036        }
037        this.vendor = b.vendor;
038        this.apiVersion = (b.apiVersion == null || b.apiVersion.isEmpty())
039            ? DEFAULT_API_VERSION
040            : b.apiVersion;
041        this.identifierConfig = (b.identifierConfig == null)
042            ? IdentifierConfig.defaultsFor(b.vendor)
043            : b.identifierConfig;
044        this.defaults = (b.defaults == null) ? DefaultsConfig.empty() : b.defaults;
045        this.catalogs = Collections.unmodifiableList(new ArrayList<CatalogModel>(b.catalogs));
046        this.sourceInfo = b.sourceInfo;
047    }
048
049    public static Builder builder() {
050        return new Builder();
051    }
052
053    public String apiVersion() {
054        return apiVersion;
055    }
056
057    public EDbVendor vendor() {
058        return vendor;
059    }
060
061    public IdentifierConfig identifierConfig() {
062        return identifierConfig;
063    }
064
065    public DefaultsConfig defaults() {
066        return defaults;
067    }
068
069    public List<CatalogModel> catalogs() {
070        return catalogs;
071    }
072
073    /** Provenance of this model. May be {@code null} for in-memory / programmatic builds. */
074    public CatalogSourceInfo sourceInfo() {
075        return sourceInfo;
076    }
077
078    @Override
079    public boolean equals(Object o) {
080        if (this == o) return true;
081        if (!(o instanceof UnifiedCatalogModel)) return false;
082        UnifiedCatalogModel that = (UnifiedCatalogModel) o;
083        return apiVersion.equals(that.apiVersion)
084            && vendor == that.vendor
085            && identifierConfig.equals(that.identifierConfig)
086            && defaults.equals(that.defaults)
087            && catalogs.equals(that.catalogs)
088            && Objects.equals(sourceInfo, that.sourceInfo);
089    }
090
091    @Override
092    public int hashCode() {
093        return Objects.hash(apiVersion, vendor, identifierConfig, defaults, catalogs, sourceInfo);
094    }
095
096    @Override
097    public String toString() {
098        return "UnifiedCatalogModel{apiVersion=" + apiVersion
099            + ", vendor=" + vendor
100            + ", catalogs=" + catalogs.size()
101            + ", sourceInfo=" + sourceInfo + '}';
102    }
103
104    public static final class Builder {
105
106        private String apiVersion;
107        private EDbVendor vendor;
108        private IdentifierConfig identifierConfig;
109        private DefaultsConfig defaults;
110        private final List<CatalogModel> catalogs = new ArrayList<CatalogModel>();
111        private CatalogSourceInfo sourceInfo;
112
113        private Builder() {
114        }
115
116        public Builder apiVersion(String v) {
117            this.apiVersion = v;
118            return this;
119        }
120
121        public Builder vendor(EDbVendor v) {
122            this.vendor = v;
123            return this;
124        }
125
126        public Builder identifierConfig(IdentifierConfig v) {
127            this.identifierConfig = v;
128            return this;
129        }
130
131        public Builder defaults(DefaultsConfig v) {
132            this.defaults = v;
133            return this;
134        }
135
136        public Builder addCatalog(CatalogModel v) {
137            if (v == null) {
138                throw new IllegalArgumentException("UnifiedCatalogModel catalog may not be null");
139            }
140            this.catalogs.add(v);
141            return this;
142        }
143
144        public Builder sourceInfo(CatalogSourceInfo v) {
145            this.sourceInfo = v;
146            return this;
147        }
148
149        public UnifiedCatalogModel build() {
150            return new UnifiedCatalogModel(this);
151        }
152    }
153}