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}