001package gudusoft.gsqlparser.ir.common; 002 003import java.util.HashMap; 004import java.util.Map; 005import java.util.concurrent.atomic.AtomicLong; 006 007/** 008 * Base class for all IR nodes across all layers (Bound, Logical, Flow). 009 * <p> 010 * Each node has a globally unique ID, an optional source anchor linking back 011 * to the original AST/SQL text, and an extensible properties map for 012 * dialect-specific attributes. 013 */ 014public abstract class IRNode { 015 016 private static final AtomicLong ID_GENERATOR = new AtomicLong(0); 017 018 /** Globally unique node ID. */ 019 private final long id; 020 021 /** Source code anchor (optional but strongly recommended). */ 022 private SourceAnchor sourceAnchor; 023 024 /** Extensible properties for dialect-specific attributes. */ 025 private Map<String, Object> properties; 026 027 protected IRNode() { 028 this.id = ID_GENERATOR.incrementAndGet(); 029 } 030 031 public long getId() { 032 return id; 033 } 034 035 public SourceAnchor getSourceAnchor() { 036 return sourceAnchor; 037 } 038 039 public void setSourceAnchor(SourceAnchor sourceAnchor) { 040 this.sourceAnchor = sourceAnchor; 041 } 042 043 /** Returns the node type enumeration value. */ 044 public abstract IRNodeKind getKind(); 045 046 /** Visitor accept method with generic return type and context. */ 047 public abstract <R, C> R accept(IRVisitor<R, C> visitor, C context); 048 049 /** 050 * Gets a dialect-specific property. 051 */ 052 @SuppressWarnings("unchecked") 053 public <T> T getProperty(String key) { 054 if (properties == null) { 055 return null; 056 } 057 return (T) properties.get(key); 058 } 059 060 /** 061 * Sets a dialect-specific property. 062 */ 063 public void setProperty(String key, Object value) { 064 if (properties == null) { 065 properties = new HashMap<String, Object>(); 066 } 067 properties.put(key, value); 068 } 069 070 /** 071 * Returns the properties map (may be null if no properties set). 072 */ 073 public Map<String, Object> getProperties() { 074 return properties; 075 } 076 077 /** 078 * Resets the global ID generator. For testing only. 079 */ 080 public static void resetIdGenerator() { 081 ID_GENERATOR.set(0); 082 } 083 084 @Override 085 public String toString() { 086 return getKind() + "#" + id; 087 } 088}