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}