001package gudusoft.gsqlparser.lineage.v2.shape;
002
003/**
004 * The base of every mirror of the shape layer (plan {@code docs/designs/data-lineage/09-sqllr-v2-runtime-driven-
005 * coverage-plan-zh.md}, slice 1b): an immutable value copy of one live object the SQL-LR producer reads (a parse tree
006 * node, a token, a runtime model object, a resolver result, a catalog object, a recorder record), taken when the
007 * analysis froze. A mirror keeps the simple name and the getters of its live class, so producer code reads a mirror
008 * as it read the live object, and holds no live object: references to other mirrors are handles into its
009 * {@link Shape}.
010 *
011 * <p>Mirrors are compared by identity, as the live objects were: one mirror per live object.</p>
012 *
013 * <p>Internal API of the SQL-LR producer.</p>
014 *
015 * @since 4.2.17
016 */
017public abstract class ShapeObject {
018
019    final Shape shape;
020    final int handle;
021
022    protected ShapeObject(Shape shape, int handle) {
023        this.shape = shape;
024        this.handle = handle;
025    }
026
027    /** The handle of the mirror in its shape. */
028    public final int shapeHandle() {
029        return handle;
030    }
031
032    /** The shape the mirror belongs to. */
033    public final Shape shape() {
034        return shape;
035    }
036
037    /** The simple name of the live object's class (a mirror stands for its nearest mirrored class). */
038    public final String liveSimpleName() {
039        return shape.liveSimpleName(handle);
040    }
041
042    /** The name of the live object's class. */
043    public final String liveClassName() {
044        return shape.liveClassName(handle);
045    }
046
047    /**
048     * A mirror has text only where the live object's rendering was taken (names, literals, type names, leaf
049     * expressions; their mirrors override this): any other {@code toString()}, including an implicit one in a string
050     * concatenation, would print the mirror instead of what the live object printed, so it fails.
051     */
052    @Override
053    public String toString() {
054        throw new IllegalStateException("SQL-LR shape: " + liveClassName() + " #" + handle + " has no rendering");
055    }
056
057    /** Resolves a slot: a value, a handle to another mirror, a list of handles, or a getter that threw. */
058    protected final <T> T slot(Object slot) {
059        return shape.resolve(slot);
060    }
061}