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}