001package gudusoft.gsqlparser.resolver2.binding; 002 003import gudusoft.gsqlparser.TCustomSqlStatement; 004 005import java.util.ArrayList; 006import java.util.Collections; 007import java.util.List; 008 009/** 010 * Aggregate output of the resolver2 binding post-pass. 011 * 012 * <p>Immutable. {@link #empty()} is the singleton returned when binding flags 013 * are off (the default) — accessors are guaranteed non-null even in this case 014 * (plan §5.6, §12).</p> 015 * 016 * <p>Filter accessors ({@link #getDiagnosticsForStatement(TCustomSqlStatement)}, 017 * {@link #getDiagnosticsForCode(BindingDiagnosticCode)}, 018 * {@link #getDiagnosticsForClause(BindingClause)}) return immutable, possibly 019 * empty lists. They never throw on unknown inputs (including {@code null}).</p> 020 */ 021public final class BindingResult { 022 023 private static final BindingResult EMPTY = new BindingResult( 024 Collections.<BindingDiagnostic>emptyList(), 025 Collections.<BindingReference>emptyList()); 026 027 private final List<BindingDiagnostic> diagnostics; 028 private final List<BindingReference> references; 029 030 private BindingResult(List<BindingDiagnostic> diagnostics, List<BindingReference> references) { 031 this.diagnostics = diagnostics; 032 this.references = references; 033 } 034 035 /** Non-null empty singleton; safe to return when binding is disabled. */ 036 public static BindingResult empty() { 037 return EMPTY; 038 } 039 040 public static BindingResult of(List<BindingDiagnostic> diagnostics, 041 List<BindingReference> references) { 042 if (diagnostics == null) { 043 throw new IllegalArgumentException("BindingResult.diagnostics is required"); 044 } 045 if (references == null) { 046 throw new IllegalArgumentException("BindingResult.references is required"); 047 } 048 return new BindingResult( 049 Collections.unmodifiableList(new ArrayList<BindingDiagnostic>(diagnostics)), 050 Collections.unmodifiableList(new ArrayList<BindingReference>(references))); 051 } 052 053 public List<BindingDiagnostic> getDiagnostics() { 054 return diagnostics; 055 } 056 057 public List<BindingReference> getReferences() { 058 return references; 059 } 060 061 public boolean hasErrors() { 062 for (BindingDiagnostic d : diagnostics) { 063 if (d.severity() == BindingDiagnosticSeverity.ERROR) { 064 return true; 065 } 066 } 067 return false; 068 } 069 070 public List<BindingDiagnostic> getDiagnosticsForStatement(TCustomSqlStatement stmt) { 071 if (stmt == null || diagnostics.isEmpty()) { 072 return Collections.emptyList(); 073 } 074 List<BindingDiagnostic> out = new ArrayList<BindingDiagnostic>(); 075 for (BindingDiagnostic d : diagnostics) { 076 if (d.statement().isPresent() && d.statement().get() == stmt) { 077 out.add(d); 078 } 079 } 080 return Collections.unmodifiableList(out); 081 } 082 083 public List<BindingDiagnostic> getDiagnosticsForCode(BindingDiagnosticCode code) { 084 if (code == null || diagnostics.isEmpty()) { 085 return Collections.emptyList(); 086 } 087 List<BindingDiagnostic> out = new ArrayList<BindingDiagnostic>(); 088 for (BindingDiagnostic d : diagnostics) { 089 if (d.code() == code) { 090 out.add(d); 091 } 092 } 093 return Collections.unmodifiableList(out); 094 } 095 096 public List<BindingDiagnostic> getDiagnosticsForClause(BindingClause clause) { 097 if (clause == null || diagnostics.isEmpty()) { 098 return Collections.emptyList(); 099 } 100 List<BindingDiagnostic> out = new ArrayList<BindingDiagnostic>(); 101 for (BindingDiagnostic d : diagnostics) { 102 if (d.site().isPresent() && d.site().get().clause() == clause) { 103 out.add(d); 104 } 105 } 106 return Collections.unmodifiableList(out); 107 } 108 109 public List<BindingReference> getUnresolvedReferences() { 110 if (references.isEmpty()) { 111 return Collections.emptyList(); 112 } 113 List<BindingReference> out = new ArrayList<BindingReference>(); 114 for (BindingReference r : references) { 115 if (!r.bound()) { 116 out.add(r); 117 } 118 } 119 return Collections.unmodifiableList(out); 120 } 121 122 @Override 123 public String toString() { 124 return "BindingResult{diagnostics=" + diagnostics.size() 125 + " references=" + references.size() 126 + " hasErrors=" + hasErrors() + '}'; 127 } 128}