001package gudusoft.gsqlparser.catalog.runtime; 002 003import java.util.Collections; 004import java.util.LinkedHashMap; 005import java.util.Map; 006import java.util.Objects; 007 008/** 009 * Factory + immutable record for {@link CatalogBinding}. 010 * 011 * <p>Plan §7.2. Bindings are produced by {@link CatalogResolver} after a successful lookup 012 * — they pair the input {@link CatalogQualifiedName} with the canonical resolved name and 013 * stable {@link CatalogObjectId} (which usually carries through to bridge mapping).</p> 014 */ 015public final class CatalogBindings { 016 017 private CatalogBindings() { 018 // Static factory. 019 } 020 021 public static CatalogBinding of(CatalogEntry entry) { 022 if (entry == null) { 023 throw new IllegalArgumentException("CatalogBindings.of: entry is required"); 024 } 025 return new ImmutableCatalogBinding(entry.name(), entry.id(), entry.kind(), entry.properties()); 026 } 027 028 public static CatalogBinding of(CatalogQualifiedName resolvedName, 029 CatalogObjectId id, 030 CatalogObjectKind kind) { 031 return new ImmutableCatalogBinding(resolvedName, id, kind, null); 032 } 033 034 public static CatalogBinding of(CatalogQualifiedName resolvedName, 035 CatalogObjectId id, 036 CatalogObjectKind kind, 037 Map<String, Object> properties) { 038 return new ImmutableCatalogBinding(resolvedName, id, kind, properties); 039 } 040 041 static final class ImmutableCatalogBinding implements CatalogBinding { 042 043 private final CatalogQualifiedName resolvedName; 044 private final CatalogObjectId objectId; 045 private final CatalogObjectKind kind; 046 private final Map<String, Object> properties; 047 048 ImmutableCatalogBinding(CatalogQualifiedName resolvedName, 049 CatalogObjectId objectId, 050 CatalogObjectKind kind, 051 Map<String, Object> properties) { 052 if (resolvedName == null) { 053 throw new IllegalArgumentException("CatalogBinding.resolvedName is required"); 054 } 055 if (objectId == null) { 056 throw new IllegalArgumentException("CatalogBinding.objectId is required"); 057 } 058 if (kind == null) { 059 throw new IllegalArgumentException("CatalogBinding.kind is required"); 060 } 061 this.resolvedName = resolvedName; 062 this.objectId = objectId; 063 this.kind = kind; 064 this.properties = properties == null 065 ? Collections.<String, Object>emptyMap() 066 : Collections.unmodifiableMap(new LinkedHashMap<String, Object>(properties)); 067 } 068 069 @Override 070 public CatalogQualifiedName resolvedName() { 071 return resolvedName; 072 } 073 074 @Override 075 public CatalogObjectId objectId() { 076 return objectId; 077 } 078 079 @Override 080 public CatalogObjectKind kind() { 081 return kind; 082 } 083 084 @Override 085 public Map<String, Object> properties() { 086 return properties; 087 } 088 089 @Override 090 public boolean equals(Object o) { 091 if (this == o) return true; 092 if (!(o instanceof ImmutableCatalogBinding)) return false; 093 ImmutableCatalogBinding that = (ImmutableCatalogBinding) o; 094 return resolvedName.equals(that.resolvedName) 095 && objectId.equals(that.objectId) 096 && kind == that.kind 097 && properties.equals(that.properties); 098 } 099 100 @Override 101 public int hashCode() { 102 return Objects.hash(resolvedName, objectId, kind, properties); 103 } 104 105 @Override 106 public String toString() { 107 return "CatalogBinding{name=" + resolvedName + ", id=" + objectId + ", kind=" + kind + '}'; 108 } 109 } 110}