001package gudusoft.gsqlparser.ir.semantic;
002
003import java.util.Objects;
004
005/**
006 * Exact vendor error enrichment for a GSP {@link Diagnostic}.
007 *
008 * <p>This metadata is explanatory only: consumers must continue to branch on
009 * {@link DiagnosticCode}. A vendor error may be attached only when the
010 * diagnostic factory has exact evidence that the vendor's documented cause
011 * matches the source construct.
012 *
013 * <p><b>API status:</b> read-only consumption of analyzer-produced vendor
014 * enrichment is part of Join Analysis Consumption Profile v1. Constructors
015 * are producer-oriented and are outside that profile.
016 */
017public final class VendorError {
018
019    private final String vendor;
020    private final String code;
021    private final String title;
022    private final String helpUri;
023    private final String matchedProfile;
024
025    public VendorError(String vendor, String code, String title,
026                       String helpUri, String matchedProfile) {
027        this.vendor = requireNonEmpty(vendor, "vendor");
028        this.code = requireNonEmpty(code, "code");
029        this.title = requireNonEmpty(title, "title");
030        this.helpUri = requireNonEmpty(helpUri, "helpUri");
031        this.matchedProfile = matchedProfile == null
032                ? null : requireNonEmpty(matchedProfile, "matchedProfile");
033    }
034
035    public String getVendor() {
036        return vendor;
037    }
038
039    public String getCode() {
040        return code;
041    }
042
043    public String getTitle() {
044        return title;
045    }
046
047    public String getHelpUri() {
048        return helpUri;
049    }
050
051    /** @return matched dialect profile, or {@code null} when not profile-specific. */
052    public String getMatchedProfile() {
053        return matchedProfile;
054    }
055
056    private static String requireNonEmpty(String value, String name) {
057        Objects.requireNonNull(value, name);
058        if (value.trim().isEmpty()) {
059            throw new IllegalArgumentException(name + " must not be empty");
060        }
061        return value;
062    }
063
064    @Override
065    public boolean equals(Object o) {
066        if (this == o) return true;
067        if (!(o instanceof VendorError)) return false;
068        VendorError that = (VendorError) o;
069        return vendor.equals(that.vendor)
070                && code.equals(that.code)
071                && title.equals(that.title)
072                && helpUri.equals(that.helpUri)
073                && Objects.equals(matchedProfile, that.matchedProfile);
074    }
075
076    @Override
077    public int hashCode() {
078        return Objects.hash(vendor, code, title, helpUri, matchedProfile);
079    }
080
081    @Override
082    public String toString() {
083        return code + " (" + vendor + "): " + title;
084    }
085}