001package gudusoft.gsqlparser.resolver2.model; 002 003import java.util.ArrayList; 004import java.util.Collections; 005import java.util.List; 006 007/** 008 * Represents a column reference that has multiple possible sources. 009 * Candidates are ordered by confidence (highest first). 010 * 011 * Example scenario: 012 * SELECT id FROM users u JOIN orders o 013 * If both users and orders have an 'id' column, this is ambiguous. 014 */ 015public class AmbiguousColumnSource { 016 /** All possible sources, ordered by confidence (descending) */ 017 private final List<ColumnSource> candidates; 018 019 /** The column name that is ambiguous */ 020 private final String columnName; 021 022 public AmbiguousColumnSource(String columnName, List<ColumnSource> candidates) { 023 this.columnName = columnName; 024 this.candidates = new ArrayList<>(candidates); 025 // Sort by confidence descending 026 this.candidates.sort((a, b) -> Double.compare(b.getConfidence(), a.getConfidence())); 027 } 028 029 public String getColumnName() { 030 return columnName; 031 } 032 033 public List<ColumnSource> getCandidates() { 034 return Collections.unmodifiableList(candidates); 035 } 036 037 /** 038 * Gets the most likely candidate (highest confidence) 039 */ 040 public ColumnSource getBestCandidate() { 041 return candidates.isEmpty() ? null : candidates.get(0); 042 } 043 044 /** 045 * Gets the number of candidates 046 */ 047 public int getCandidateCount() { 048 return candidates.size(); 049 } 050 051 /** 052 * Checks if there are definite matches (confidence = 1.0) 053 * among the candidates 054 */ 055 public boolean hasDefiniteMatches() { 056 return candidates.stream().anyMatch(ColumnSource::isDefinite); 057 } 058 059 @Override 060 public String toString() { 061 StringBuilder sb = new StringBuilder(); 062 sb.append("Ambiguous column '").append(columnName).append("' ("); 063 sb.append(candidates.size()).append(" candidates):\n"); 064 for (int i = 0; i < candidates.size(); i++) { 065 sb.append(" ").append(i + 1).append(". ").append(candidates.get(i)).append("\n"); 066 } 067 return sb.toString(); 068 } 069}