001package gudusoft.gsqlparser.resolver2.binding;
002
003import java.util.Objects;
004import java.util.Optional;
005
006/**
007 * Source-location and clause attribution for a {@link BindingReference} or
008 * {@link BindingDiagnostic}.
009 *
010 * <p>Immutable; build via {@link #builder()}. Plan ยง7.3 S6 lists the fields
011 * exposed: statement-index, clause, optional line/column, scope kind, and the
012 * raw reference text.</p>
013 */
014public final class BindingReferenceSite {
015
016    private final int statementIndex;
017    private final BindingClause clause;
018    private final Integer line;
019    private final Integer column;
020    private final String scopeKind;
021    private final String referenceText;
022
023    private BindingReferenceSite(Builder b) {
024        if (b.clause == null) {
025            throw new IllegalArgumentException("BindingReferenceSite.clause is required");
026        }
027        if (b.referenceText == null || b.referenceText.isEmpty()) {
028            throw new IllegalArgumentException("BindingReferenceSite.referenceText is required");
029        }
030        this.statementIndex = b.statementIndex;
031        this.clause = b.clause;
032        this.line = b.line;
033        this.column = b.column;
034        this.scopeKind = b.scopeKind;
035        this.referenceText = b.referenceText;
036    }
037
038    public static Builder builder() {
039        return new Builder();
040    }
041
042    public int statementIndex() {
043        return statementIndex;
044    }
045
046    public BindingClause clause() {
047        return clause;
048    }
049
050    public Optional<Integer> line() {
051        return Optional.ofNullable(line);
052    }
053
054    public Optional<Integer> column() {
055        return Optional.ofNullable(column);
056    }
057
058    public Optional<String> scopeKind() {
059        return Optional.ofNullable(scopeKind);
060    }
061
062    public String referenceText() {
063        return referenceText;
064    }
065
066    @Override
067    public boolean equals(Object o) {
068        if (this == o) return true;
069        if (!(o instanceof BindingReferenceSite)) return false;
070        BindingReferenceSite that = (BindingReferenceSite) o;
071        return statementIndex == that.statementIndex
072            && clause == that.clause
073            && Objects.equals(line, that.line)
074            && Objects.equals(column, that.column)
075            && Objects.equals(scopeKind, that.scopeKind)
076            && referenceText.equals(that.referenceText);
077    }
078
079    @Override
080    public int hashCode() {
081        return Objects.hash(statementIndex, clause, line, column, scopeKind, referenceText);
082    }
083
084    @Override
085    public String toString() {
086        StringBuilder sb = new StringBuilder("BindingReferenceSite{stmt=").append(statementIndex)
087            .append(' ').append(clause).append(" text=").append(referenceText);
088        if (line != null) sb.append(" line=").append(line);
089        if (column != null) sb.append(" col=").append(column);
090        if (scopeKind != null) sb.append(" scope=").append(scopeKind);
091        return sb.append('}').toString();
092    }
093
094    public static final class Builder {
095
096        private int statementIndex;
097        private BindingClause clause;
098        private Integer line;
099        private Integer column;
100        private String scopeKind;
101        private String referenceText;
102
103        private Builder() {
104        }
105
106        public Builder statementIndex(int v) {
107            this.statementIndex = v;
108            return this;
109        }
110
111        public Builder clause(BindingClause v) {
112            this.clause = v;
113            return this;
114        }
115
116        public Builder line(int v) {
117            this.line = v;
118            return this;
119        }
120
121        public Builder column(int v) {
122            this.column = v;
123            return this;
124        }
125
126        public Builder scopeKind(String v) {
127            this.scopeKind = v;
128            return this;
129        }
130
131        public Builder referenceText(String v) {
132            this.referenceText = v;
133            return this;
134        }
135
136        public BindingReferenceSite build() {
137            return new BindingReferenceSite(this);
138        }
139    }
140}