001package gudusoft.gsqlparser.catalog.diagnostic; 002 003import gudusoft.gsqlparser.catalog.runtime.CatalogQualifiedName; 004 005import java.util.Objects; 006import java.util.Optional; 007 008/** 009 * One catalog diagnostic record (validator, reader, provider, or runtime). 010 * 011 * <p>Plan §7.3. Diagnostics are immutable value objects; build via {@link #builder()}.</p> 012 * 013 * <p>{@code location} is intentionally left as a free-form {@link String} until P1E 014 * introduces a structured {@code SourceLocation} type — the JSON / DDL readers landing 015 * in P1B and Phase 2.A have no shared shape worth committing to yet.</p> 016 */ 017public final class CatalogDiagnostic { 018 019 private final CatalogDiagnosticSeverity severity; 020 private final CatalogDiagnosticCode code; 021 private final String message; 022 private final CatalogQualifiedName name; 023 private final String location; 024 private final String repairHint; 025 026 private CatalogDiagnostic(Builder b) { 027 if (b.severity == null) { 028 throw new IllegalArgumentException("CatalogDiagnostic.severity is required"); 029 } 030 if (b.code == null) { 031 throw new IllegalArgumentException("CatalogDiagnostic.code is required"); 032 } 033 if (b.message == null || b.message.isEmpty()) { 034 throw new IllegalArgumentException("CatalogDiagnostic.message is required"); 035 } 036 this.severity = b.severity; 037 this.code = b.code; 038 this.message = b.message; 039 this.name = b.name; 040 this.location = b.location; 041 this.repairHint = b.repairHint; 042 } 043 044 public static Builder builder() { 045 return new Builder(); 046 } 047 048 /** 049 * Convenience: build a diagnostic from severity + code + message only. Most 050 * validator emissions don't have a qualified name or location yet. 051 */ 052 public static CatalogDiagnostic of(CatalogDiagnosticSeverity severity, 053 CatalogDiagnosticCode code, 054 String message) { 055 return builder().severity(severity).code(code).message(message).build(); 056 } 057 058 public CatalogDiagnosticSeverity severity() { 059 return severity; 060 } 061 062 public CatalogDiagnosticCode code() { 063 return code; 064 } 065 066 public String message() { 067 return message; 068 } 069 070 public Optional<CatalogQualifiedName> name() { 071 return Optional.ofNullable(name); 072 } 073 074 public Optional<String> location() { 075 return Optional.ofNullable(location); 076 } 077 078 public Optional<String> repairHint() { 079 return Optional.ofNullable(repairHint); 080 } 081 082 @Override 083 public boolean equals(Object o) { 084 if (this == o) return true; 085 if (!(o instanceof CatalogDiagnostic)) return false; 086 CatalogDiagnostic that = (CatalogDiagnostic) o; 087 return severity == that.severity 088 && code == that.code 089 && message.equals(that.message) 090 && Objects.equals(name, that.name) 091 && Objects.equals(location, that.location) 092 && Objects.equals(repairHint, that.repairHint); 093 } 094 095 @Override 096 public int hashCode() { 097 return Objects.hash(severity, code, message, name, location, repairHint); 098 } 099 100 @Override 101 public String toString() { 102 return "CatalogDiagnostic{" + severity + " " + code + ": " + message 103 + (name != null ? " name=" + name : "") 104 + (location != null ? " at=" + location : "") 105 + (repairHint != null ? " hint=" + repairHint : "") 106 + '}'; 107 } 108 109 public static final class Builder { 110 111 private CatalogDiagnosticSeverity severity; 112 private CatalogDiagnosticCode code; 113 private String message; 114 private CatalogQualifiedName name; 115 private String location; 116 private String repairHint; 117 118 private Builder() { 119 } 120 121 public Builder severity(CatalogDiagnosticSeverity v) { 122 this.severity = v; 123 return this; 124 } 125 126 public Builder code(CatalogDiagnosticCode v) { 127 this.code = v; 128 return this; 129 } 130 131 public Builder message(String v) { 132 this.message = v; 133 return this; 134 } 135 136 public Builder name(CatalogQualifiedName v) { 137 this.name = v; 138 return this; 139 } 140 141 public Builder location(String v) { 142 this.location = v; 143 return this; 144 } 145 146 public Builder repairHint(String v) { 147 this.repairHint = v; 148 return this; 149 } 150 151 public CatalogDiagnostic build() { 152 return new CatalogDiagnostic(this); 153 } 154 } 155}