001package gudusoft.gsqlparser.resolver2.enhancement;
002
003import gudusoft.gsqlparser.nodes.TObjectName;
004import gudusoft.gsqlparser.resolver2.model.ResolutionEvidence;
005import gudusoft.gsqlparser.resolver2.model.SourceLocation;
006import gudusoft.gsqlparser.resolver2.namespace.INamespace;
007
008/**
009 * Represents a column reference collected during resolution that needs
010 * to be added to a namespace.
011 *
012 * This is used by the explicit namespace enhancement phase to track
013 * which columns should be added to which namespaces between resolution passes.
014 */
015public class CollectedColumnRef {
016
017    /** The column name to add */
018    private final String columnName;
019
020    /** The target namespace to add the column to */
021    private final INamespace targetNamespace;
022
023    /** The AST node that referenced this column */
024    private final TObjectName sourceReference;
025
026    /** The pass number when this was collected */
027    private final int passNumber;
028
029    /**
030     * Confidence score for this column (0.0 to 1.0)
031     * @deprecated Use {@link #evidenceDetail} instead
032     */
033    private final double confidence;
034
035    /**
036     * Evidence/reason for adding this column
037     * @deprecated Use {@link #evidenceDetail} instead
038     */
039    private final String evidence;
040
041    /** Structured evidence detail for this column reference */
042    private final ResolutionEvidence evidenceDetail;
043
044    /** Source location description (for debugging) */
045    private final String sourceLocation;
046
047    /**
048     * Legacy constructor for backward compatibility.
049     *
050     * @deprecated Use {@link #CollectedColumnRef(String, INamespace, TObjectName, int, ResolutionEvidence)} instead
051     */
052    public CollectedColumnRef(String columnName,
053                              INamespace targetNamespace,
054                              TObjectName sourceReference,
055                              int passNumber,
056                              double confidence,
057                              String evidence) {
058        this.columnName = columnName;
059        this.targetNamespace = targetNamespace;
060        this.sourceReference = sourceReference;
061        this.passNumber = passNumber;
062        this.confidence = confidence;
063        this.evidence = evidence;
064        this.sourceLocation = formatLocation(sourceReference);
065        // Create evidenceDetail from legacy parameters
066        this.evidenceDetail = ResolutionEvidence.fromLegacyEvidence(evidence, confidence, sourceReference);
067    }
068
069    /**
070     * Constructor with ResolutionEvidence (preferred for new code).
071     *
072     * @param columnName The column name to add
073     * @param targetNamespace The target namespace
074     * @param sourceReference The AST node that referenced this column
075     * @param passNumber The resolution pass number
076     * @param evidenceDetail Structured evidence detail
077     */
078    public CollectedColumnRef(String columnName,
079                              INamespace targetNamespace,
080                              TObjectName sourceReference,
081                              int passNumber,
082                              ResolutionEvidence evidenceDetail) {
083        this.columnName = columnName;
084        this.targetNamespace = targetNamespace;
085        this.sourceReference = sourceReference;
086        this.passNumber = passNumber;
087        this.evidenceDetail = evidenceDetail;
088        // Derive legacy fields from evidenceDetail
089        this.confidence = evidenceDetail != null ? evidenceDetail.getWeight() : 0.5;
090        this.evidence = evidenceDetail != null ? evidenceDetail.toLegacyEvidence() : null;
091        this.sourceLocation = formatLocation(sourceReference);
092    }
093
094    private String formatLocation(TObjectName objName) {
095        if (objName == null) return "unknown";
096        return String.format("line %d, col %d",
097            objName.getLineNo(), objName.getColumnNo());
098    }
099
100    public String getColumnName() {
101        return columnName;
102    }
103
104    public INamespace getTargetNamespace() {
105        return targetNamespace;
106    }
107
108    public TObjectName getSourceReference() {
109        return sourceReference;
110    }
111
112    public int getPassNumber() {
113        return passNumber;
114    }
115
116    public double getConfidence() {
117        return confidence;
118    }
119
120    public String getEvidence() {
121        return evidence;
122    }
123
124    /**
125     * Get the structured evidence detail for this column reference.
126     *
127     * @return The structured evidence detail
128     */
129    public ResolutionEvidence getEvidenceDetail() {
130        return evidenceDetail;
131    }
132
133    public String getSourceLocation() {
134        return sourceLocation;
135    }
136
137    @Override
138    public String toString() {
139        return String.format("CollectedColumnRef{column='%s', namespace='%s', pass=%d, conf=%.2f, evidence='%s', loc=%s}",
140            columnName,
141            targetNamespace != null ? targetNamespace.getDisplayName() : "null",
142            passNumber,
143            confidence,
144            evidence,
145            sourceLocation);
146    }
147
148    @Override
149    public boolean equals(Object o) {
150        if (this == o) return true;
151        if (o == null || getClass() != o.getClass()) return false;
152
153        CollectedColumnRef that = (CollectedColumnRef) o;
154
155        if (!columnName.equalsIgnoreCase(that.columnName)) return false;
156        return targetNamespace == that.targetNamespace; // Identity comparison for namespace
157    }
158
159    @Override
160    public int hashCode() {
161        int result = columnName.toLowerCase().hashCode();
162        result = 31 * result + System.identityHashCode(targetNamespace);
163        return result;
164    }
165}