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}