001package gudusoft.gsqlparser.lineage2.contract; 002 003/** 004 * Contract {@code Endpoint} (lineage2-contract.md ยง4.1). 005 * 006 * <p>Physical endpoints are always emitted fully expanded 007 * ({@code database}/{@code schema}/{@code object} all non-empty, D-15); 008 * endpoints that cannot be fully qualified get a non-RESOLVED 009 * {@link ResolutionStatus} and the surface name observed. 010 * 011 * <p>Location emission is tri-state, mirroring the gold-fixture 012 * conventions: a non-null {@code sourceLocation} is emitted as-is; a null 013 * location with a {@link LocationNullReason} is emitted as 014 * {@code "sourceLocation": null} plus the reason; when both are absent the 015 * keys are omitted entirely. 016 * 017 * <p>Internal API: not part of the public gsqlparser surface. 018 */ 019public final class Endpoint { 020 021 private final String database; 022 private final String schema; 023 private final String object; 024 private final String column; 025 private final ObjectKind objectKind; 026 private final ResolutionStatus resolutionStatus; 027 private final ScopeKind scopeKind; 028 private final Integer definedAtStatementIndex; 029 private final SourceLocation sourceLocation; 030 private final LocationNullReason locationNullReason; 031 032 private Endpoint(Builder b) { 033 if (b.object == null) { 034 throw new IllegalArgumentException("object must not be null"); 035 } 036 if (b.objectKind == null || b.resolutionStatus == null) { 037 throw new IllegalArgumentException( 038 "objectKind and resolutionStatus must not be null"); 039 } 040 this.database = b.database; 041 this.schema = b.schema; 042 this.object = b.object; 043 this.column = b.column; 044 this.objectKind = b.objectKind; 045 this.resolutionStatus = b.resolutionStatus; 046 this.scopeKind = b.scopeKind; 047 this.definedAtStatementIndex = b.definedAtStatementIndex; 048 this.sourceLocation = b.sourceLocation; 049 this.locationNullReason = b.locationNullReason; 050 } 051 052 public static Builder builder(String object) { 053 return new Builder(object); 054 } 055 056 public String getDatabase() { 057 return database; 058 } 059 060 public String getSchema() { 061 return schema; 062 } 063 064 public String getObject() { 065 return object; 066 } 067 068 public String getColumn() { 069 return column; 070 } 071 072 public ObjectKind getObjectKind() { 073 return objectKind; 074 } 075 076 public ResolutionStatus getResolutionStatus() { 077 return resolutionStatus; 078 } 079 080 /** Nullable โ only set for temp/variable/cursor endpoints (D-11). */ 081 public ScopeKind getScopeKind() { 082 return scopeKind; 083 } 084 085 /** Nullable โ only set for temp/variable/cursor endpoints (D-11). */ 086 public Integer getDefinedAtStatementIndex() { 087 return definedAtStatementIndex; 088 } 089 090 /** Nullable. */ 091 public SourceLocation getSourceLocation() { 092 return sourceLocation; 093 } 094 095 /** Nullable โ set only when {@code sourceLocation} is null. */ 096 public LocationNullReason getLocationNullReason() { 097 return locationNullReason; 098 } 099 100 public static final class Builder { 101 private String database; 102 private String schema; 103 private final String object; 104 private String column; 105 private ObjectKind objectKind = ObjectKind.UNKNOWN; 106 private ResolutionStatus resolutionStatus = ResolutionStatus.RESOLVED; 107 private ScopeKind scopeKind; 108 private Integer definedAtStatementIndex; 109 private SourceLocation sourceLocation; 110 private LocationNullReason locationNullReason; 111 112 private Builder(String object) { 113 this.object = object; 114 } 115 116 public Builder database(String database) { 117 this.database = database; 118 return this; 119 } 120 121 public Builder schema(String schema) { 122 this.schema = schema; 123 return this; 124 } 125 126 public Builder column(String column) { 127 this.column = column; 128 return this; 129 } 130 131 public Builder objectKind(ObjectKind objectKind) { 132 this.objectKind = objectKind; 133 return this; 134 } 135 136 public Builder resolutionStatus(ResolutionStatus resolutionStatus) { 137 this.resolutionStatus = resolutionStatus; 138 return this; 139 } 140 141 public Builder scopeKind(ScopeKind scopeKind) { 142 this.scopeKind = scopeKind; 143 return this; 144 } 145 146 public Builder definedAtStatementIndex(Integer definedAtStatementIndex) { 147 this.definedAtStatementIndex = definedAtStatementIndex; 148 return this; 149 } 150 151 public Builder sourceLocation(SourceLocation sourceLocation) { 152 this.sourceLocation = sourceLocation; 153 return this; 154 } 155 156 public Builder locationNullReason(LocationNullReason reason) { 157 this.locationNullReason = reason; 158 return this; 159 } 160 161 public Endpoint build() { 162 return new Endpoint(this); 163 } 164 } 165}