001package gudusoft.gsqlparser.dlineage.routine; 002 003import java.util.Collections; 004import java.util.List; 005 006/** 007 * What a routine lookup found: a status, the branch of the match, and the distinct candidate declarations 008 * in declaration order. 009 * 010 * <p>{@link Status#RESOLVED} only for exactly one candidate matched on every named level, with no level 011 * one side names and the other omits. A match that needs caller context to fill an omitted level 012 * ({@code f} against {@code s.f}, {@code db..p} against {@code db.dbo.p}) is {@link Status#REQUIRES_CONTEXT}, 013 * and more than one candidate is {@link Status#AMBIGUOUS}: an ambiguous callee binds nothing (the 014 * {@code RoutineCallBinder} contract).</p> 015 */ 016public final class RoutineLookupResult { 017 018 public enum Status { 019 RESOLVED, AMBIGUOUS, NOT_FOUND, REQUIRES_CONTEXT 020 } 021 022 public enum Branch { 023 /** Every level equal, and the argument alias. */ 024 EXACT, 025 /** A name-only lookup that found declarations of that name keyed with a signature. */ 026 NAME_FALLBACK, 027 /** The lookup omits levels the declaration names ({@code f} against {@code s.f}). */ 028 LEAF_QUALIFIED, 029 /** The declaration omits levels the lookup names ({@code s.f} against {@code f}). */ 030 LEAF_UNQUALIFIED, 031 /** Each side omits a level the other names. */ 032 PARTIAL, 033 NONE 034 } 035 036 static final RoutineLookupResult NOT_FOUND = new RoutineLookupResult(Status.NOT_FOUND, Branch.NONE, 037 Collections.<RoutineDeclaration>emptyList()); 038 039 private final Status status; 040 private final Branch branch; 041 private final List<RoutineDeclaration> candidates; 042 private final Object legacyWinner; 043 044 RoutineLookupResult(Status status, Branch branch, List<RoutineDeclaration> candidates) { 045 this(status, branch, candidates, null); 046 } 047 048 private RoutineLookupResult(Status status, Branch branch, List<RoutineDeclaration> candidates, Object legacyWinner) { 049 this.status = status; 050 this.branch = branch; 051 this.candidates = Collections.unmodifiableList(candidates); 052 this.legacyWinner = legacyWinner; 053 } 054 055 /** This result with the routine the legacy registry answered at the same lookup (measurement only). */ 056 public RoutineLookupResult withLegacyWinner(Object legacy) { 057 return new RoutineLookupResult(status, branch, candidates, legacy); 058 } 059 060 /** What the legacy registry answered at the same lookup, when recorded: compatibility evidence, never a winner. */ 061 public Object getLegacyWinner() { 062 return legacyWinner; 063 } 064 065 public Status getStatus() { 066 return status; 067 } 068 069 public Branch getBranch() { 070 return branch; 071 } 072 073 public List<RoutineDeclaration> getCandidates() { 074 return candidates; 075 } 076 077 /** The one declaration found, only when {@link #getStatus()} is RESOLVED. */ 078 public RoutineDeclaration getResolved() { 079 return status == Status.RESOLVED ? candidates.get(0) : null; 080 } 081 082 @Override 083 public String toString() { 084 return status + "/" + branch + candidates; 085 } 086}