001package gudusoft.gsqlparser.catalog.input.model; 002 003import java.util.ArrayList; 004import java.util.Collections; 005import java.util.List; 006import java.util.Objects; 007 008/** 009 * Column entry inside a {@link TableModel} or {@link ViewModel}. 010 * 011 * <p>Plan ยง6. {@code dataType} is a free-form string for forward-compatibility 012 * with vendor type systems (Oracle {@code NUMBER(10,2)}, BigQuery 013 * {@code STRUCT<...>}, etc.). {@link #nullable()} defaults to {@code true} in 014 * line with ANSI SQL.</p> 015 */ 016public final class ColumnModel { 017 018 private final String name; 019 private final String dataType; 020 private final boolean nullable; 021 private final List<PolicyTagModel> policyTags; 022 023 private ColumnModel(Builder b) { 024 if (b.name == null || b.name.isEmpty()) { 025 throw new IllegalArgumentException("ColumnModel.name is required"); 026 } 027 this.name = b.name; 028 this.dataType = b.dataType; 029 this.nullable = b.nullable; 030 this.policyTags = Collections.unmodifiableList(new ArrayList<PolicyTagModel>(b.policyTags)); 031 } 032 033 public static Builder builder() { 034 return new Builder(); 035 } 036 037 public String name() { 038 return name; 039 } 040 041 /** Vendor data-type string. May be {@code null} when adapters omit it. */ 042 public String dataType() { 043 return dataType; 044 } 045 046 public boolean nullable() { 047 return nullable; 048 } 049 050 public List<PolicyTagModel> policyTags() { 051 return policyTags; 052 } 053 054 @Override 055 public boolean equals(Object o) { 056 if (this == o) return true; 057 if (!(o instanceof ColumnModel)) return false; 058 ColumnModel that = (ColumnModel) o; 059 return nullable == that.nullable 060 && name.equals(that.name) 061 && Objects.equals(dataType, that.dataType) 062 && policyTags.equals(that.policyTags); 063 } 064 065 @Override 066 public int hashCode() { 067 return Objects.hash(name, dataType, nullable, policyTags); 068 } 069 070 @Override 071 public String toString() { 072 return "ColumnModel{name=" + name 073 + ", dataType=" + dataType 074 + ", nullable=" + nullable 075 + ", policyTags=" + policyTags + '}'; 076 } 077 078 public static final class Builder { 079 080 private String name; 081 private String dataType; 082 private boolean nullable = true; 083 private final List<PolicyTagModel> policyTags = new ArrayList<PolicyTagModel>(); 084 085 private Builder() { 086 } 087 088 public Builder name(String v) { 089 this.name = v; 090 return this; 091 } 092 093 public Builder dataType(String v) { 094 this.dataType = v; 095 return this; 096 } 097 098 public Builder nullable(boolean v) { 099 this.nullable = v; 100 return this; 101 } 102 103 public Builder addPolicyTag(PolicyTagModel v) { 104 if (v == null) { 105 throw new IllegalArgumentException("ColumnModel policy tag may not be null"); 106 } 107 this.policyTags.add(v); 108 return this; 109 } 110 111 public ColumnModel build() { 112 return new ColumnModel(this); 113 } 114 } 115}