001package gudusoft.gsqlparser.resolver2.binding; 002 003import java.util.Objects; 004 005/** 006 * One name reference observed by the binding pass. 007 * 008 * <p>Immutable; build via {@link #builder()}. {@link #bound()} indicates 009 * whether resolver2 successfully resolved the reference. References are 010 * surfaced only when the consumer opts in via 011 * {@code TSQLResolverConfig.setBindingIncludeSuccessfulReferences(true)}; 012 * unresolved references are also surfaced via {@link BindingResult#getUnresolvedReferences()}.</p> 013 * 014 * <p>{@code objectNameText} carries the textual reference (e.g. {@code "o.id1"}) 015 * — the public binding API does NOT expose internal resolver2 nodes 016 * ({@code ResolutionResult}, {@code IScope}, namespaces) per plan §15 R5/R6.</p> 017 */ 018public final class BindingReference { 019 020 private final BindingReferenceKind kind; 021 private final String objectNameText; 022 private final BindingReferenceSite site; 023 private final boolean bound; 024 025 private BindingReference(Builder b) { 026 if (b.kind == null) { 027 throw new IllegalArgumentException("BindingReference.kind is required"); 028 } 029 if (b.objectNameText == null || b.objectNameText.isEmpty()) { 030 throw new IllegalArgumentException("BindingReference.objectNameText is required"); 031 } 032 if (b.site == null) { 033 throw new IllegalArgumentException("BindingReference.site is required"); 034 } 035 this.kind = b.kind; 036 this.objectNameText = b.objectNameText; 037 this.site = b.site; 038 this.bound = b.bound; 039 } 040 041 public static Builder builder() { 042 return new Builder(); 043 } 044 045 public BindingReferenceKind kind() { 046 return kind; 047 } 048 049 public String objectNameText() { 050 return objectNameText; 051 } 052 053 public BindingReferenceSite site() { 054 return site; 055 } 056 057 public boolean bound() { 058 return bound; 059 } 060 061 @Override 062 public boolean equals(Object o) { 063 if (this == o) return true; 064 if (!(o instanceof BindingReference)) return false; 065 BindingReference that = (BindingReference) o; 066 return bound == that.bound 067 && kind == that.kind 068 && objectNameText.equals(that.objectNameText) 069 && site.equals(that.site); 070 } 071 072 @Override 073 public int hashCode() { 074 return Objects.hash(kind, objectNameText, site, bound); 075 } 076 077 @Override 078 public String toString() { 079 return "BindingReference{" + kind + " " + objectNameText 080 + (bound ? " (bound)" : " (unbound)") 081 + " " + site + '}'; 082 } 083 084 public static final class Builder { 085 086 private BindingReferenceKind kind; 087 private String objectNameText; 088 private BindingReferenceSite site; 089 private boolean bound; 090 091 private Builder() { 092 } 093 094 public Builder kind(BindingReferenceKind v) { 095 this.kind = v; 096 return this; 097 } 098 099 public Builder objectNameText(String v) { 100 this.objectNameText = v; 101 return this; 102 } 103 104 public Builder site(BindingReferenceSite v) { 105 this.site = v; 106 return this; 107 } 108 109 public Builder bound(boolean v) { 110 this.bound = v; 111 return this; 112 } 113 114 public BindingReference build() { 115 return new BindingReference(this); 116 } 117 } 118}