001package gudusoft.gsqlparser.lineage.v2.shape;
002
003import java.util.Collections;
004import java.util.List;
005import java.util.Map;
006
007/**
008 * Mirror of {@code gudusoft.gsqlparser.dlineage.dataflow.model.SqllrObservations}, the recorder, as it stood when the
009 * analysis froze: the root of the shape (plan 09, slice 1b). Hand-written, with its record mirrors, because two of its
010 * members take an argument: they are answered from tables the projection precomputed for every possible argument.
011 *
012 * <p>Internal API of the SQL-LR producer.</p>
013 *
014 * @since 4.2.17
015 */
016public final class SqllrObservations extends ShapeObject {
017
018    private final Object vUnits;
019    private final Object vElements;
020    private final Object vReferences;
021    private final Object vFrozenRelations;
022    private final Object vFrozenResultSets;
023    private final Object vDerived;
024    private final Object vStatements;
025    private final Map<Integer, Object> frozenColumns;
026    private final Map<Integer, Integer> structItems;
027
028    SqllrObservations(Shape shape, int handle, Object[] v, Map<Integer, Object> frozenColumns,
029            Map<Integer, Integer> structItems) {
030        super(shape, handle);
031        this.vUnits = v[0];
032        this.vElements = v[1];
033        this.vReferences = v[2];
034        this.vFrozenRelations = v[3];
035        this.vFrozenResultSets = v[4];
036        this.vDerived = v[5];
037        this.vStatements = v[6];
038        this.frozenColumns = Collections.unmodifiableMap(frozenColumns);
039        this.structItems = Collections.unmodifiableMap(structItems);
040    }
041
042    public List<UnitRecord> getUnits() {
043        return slot(vUnits);
044    }
045
046    public List<ElementRecord> getElements() {
047        return slot(vElements);
048    }
049
050    public List<ReferenceRecord> getReferences() {
051        return slot(vReferences);
052    }
053
054    public List<FrozenRelation> getFrozenRelations() {
055        return slot(vFrozenRelations);
056    }
057
058    public List<ResultSet> getFrozenResultSets() {
059        return slot(vFrozenResultSets);
060    }
061
062    public List<DerivedRecord> getDerived() {
063        return slot(vDerived);
064    }
065
066    public List<StatementRecord> getStatements() {
067        return slot(vStatements);
068    }
069
070    /** The columns of a result set at the freeze, or {@code null} when no frozen relationship reaches it. */
071    public List<ResultColumn> getFrozenColumns(ResultSet resultSet) {
072        Object columns = resultSet == null ? null : frozenColumns.get(Integer.valueOf(resultSet.shapeHandle()));
073        return columns == null ? null : this.<List<ResultColumn>>slot(columns);
074    }
075
076    /** The select item whose STRUCT a field column belongs to, or null. */
077    public TResultColumn getStructItem(Object column) {
078        if (!(column instanceof ShapeObject)) {
079            return null;
080        }
081        Integer item = structItems.get(Integer.valueOf(((ShapeObject) column).shapeHandle()));
082        return item == null ? null : (TResultColumn) shape.at(item.intValue());
083    }
084
085    /** Mirror of the recorder's element record. */
086    public static final class ElementRecord extends ShapeObject {
087        private final Object vRelation;
088        private final Object vElement;
089        private final boolean target;
090        private final Object vReference;
091        private final Object vStatement;
092        private final long sequence;
093
094        ElementRecord(Shape shape, int handle, Object[] v) {
095            super(shape, handle);
096            this.vRelation = v[0];
097            this.vElement = v[1];
098            this.target = ((Boolean) v[2]).booleanValue();
099            this.vReference = v[3];
100            this.vStatement = v[4];
101            this.sequence = ((Long) v[5]).longValue();
102        }
103
104        public AbstractRelationship getRelation() {
105            return slot(vRelation);
106        }
107
108        public RelationshipElement getElement() {
109            return slot(vElement);
110        }
111
112        public boolean isTarget() {
113            return target;
114        }
115
116        public TObjectName getReference() {
117            return slot(vReference);
118        }
119
120        public TCustomSqlStatement getStatement() {
121            return slot(vStatement);
122        }
123
124        public long getSequence() {
125            return sequence;
126        }
127    }
128
129    /** Mirror of the recorder's reference record. */
130    public static final class ReferenceRecord extends ShapeObject {
131        private final Object vReference;
132        private final Object vTarget;
133        private final Object vStatement;
134        private final long sequence;
135
136        ReferenceRecord(Shape shape, int handle, Object[] v) {
137            super(shape, handle);
138            this.vReference = v[0];
139            this.vTarget = v[1];
140            this.vStatement = v[2];
141            this.sequence = ((Long) v[3]).longValue();
142        }
143
144        public TObjectName getReference() {
145            return slot(vReference);
146        }
147
148        public Object getTarget() {
149            return slot(vTarget);
150        }
151
152        public TCustomSqlStatement getStatement() {
153            return slot(vStatement);
154        }
155
156        public long getSequence() {
157            return sequence;
158        }
159    }
160
161    /** Mirror of the recorder's statement record. */
162    public static final class StatementRecord extends ShapeObject {
163        private final Object vStatement;
164        private final String failureClass;
165        private final String failureMessage;
166        private final boolean finished;
167        private final String failureSimpleName;
168
169        StatementRecord(Shape shape, int handle, Object[] v) {
170            super(shape, handle);
171            this.vStatement = v[0];
172            this.failureClass = (String) v[1];
173            this.failureMessage = (String) v[2];
174            this.finished = ((Boolean) v[3]).booleanValue();
175            this.failureSimpleName = (String) v[4];
176        }
177
178        /** The simple name of the class of the exception that ended the statement's analysis, or {@code null}. */
179        public String getFailureSimpleName() {
180            return failureSimpleName;
181        }
182
183        public TCustomSqlStatement getStatement() {
184            return slot(vStatement);
185        }
186
187        /**
188         * The exception that ended the statement's analysis, made again from its class and message (the snapshot
189         * holds no Throwable), or {@code null}.
190         */
191        public Throwable getFailure() {
192            if (failureClass == null) {
193                return null;
194            }
195            try {
196                Class<?> c = Class.forName(failureClass);
197                try {
198                    return (Throwable) c.getConstructor(String.class).newInstance(failureMessage);
199                } catch (NoSuchMethodException e) {
200                    return (Throwable) c.getConstructor().newInstance();
201                }
202            } catch (Exception e) {
203                return new IllegalStateException(failureClass + ": " + failureMessage);
204            }
205        }
206
207        public boolean isFinished() {
208            return finished;
209        }
210    }
211
212    /** Mirror of the recorder's unit record. */
213    public static final class UnitRecord extends ShapeObject {
214        private final int unitIndex;
215        private final int parseResult;
216        private final Object vStatements;
217        private final Object vSyntaxErrors;
218        private final Object vRecoveredSyntaxErrors;
219
220        UnitRecord(Shape shape, int handle, Object[] v) {
221            super(shape, handle);
222            this.unitIndex = ((Integer) v[0]).intValue();
223            this.parseResult = ((Integer) v[1]).intValue();
224            this.vStatements = v[2];
225            this.vSyntaxErrors = v[3];
226            this.vRecoveredSyntaxErrors = v[4];
227        }
228
229        public int getUnitIndex() {
230            return unitIndex;
231        }
232
233        public int getParseResult() {
234            return parseResult;
235        }
236
237        public List<TCustomSqlStatement> getStatements() {
238            return slot(vStatements);
239        }
240
241        public List<TSyntaxError> getSyntaxErrors() {
242            return slot(vSyntaxErrors);
243        }
244
245        public List<TSyntaxError> getRecoveredSyntaxErrors() {
246            return slot(vRecoveredSyntaxErrors);
247        }
248    }
249
250    /** Mirror of the recorder's derived record. */
251    public static final class DerivedRecord extends ShapeObject {
252        private final Object vStatement;
253        private final Object vSite;
254
255        DerivedRecord(Shape shape, int handle, Object[] v) {
256            super(shape, handle);
257            this.vStatement = v[0];
258            this.vSite = v[1];
259        }
260
261        public TCustomSqlStatement getStatement() {
262            return slot(vStatement);
263        }
264
265        public TCustomSqlStatement getSite() {
266            return slot(vSite);
267        }
268    }
269
270    /** Mirror of a relationship frozen at the end of the analysis. */
271    public static final class FrozenRelation extends ShapeObject {
272        private final Object vRelation;
273        private final Object vTarget;
274
275        FrozenRelation(Shape shape, int handle, Object[] v) {
276            super(shape, handle);
277            this.vRelation = v[0];
278            this.vTarget = v[1];
279        }
280
281        public AbstractRelationship getRelation() {
282            return slot(vRelation);
283        }
284
285        public RelationshipElement getTarget() {
286            return slot(vTarget);
287        }
288    }
289}