001package gudusoft.gsqlparser.dlineage.graph;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.dlineage.DataFlowAnalyzer;
005import gudusoft.gsqlparser.dlineage.dataflow.model.RelationshipType;
006import gudusoft.gsqlparser.dlineage.dataflow.model.json.Dataflow;
007import gudusoft.gsqlparser.dlineage.dataflow.model.xml.*;
008import gudusoft.gsqlparser.dlineage.graph.model.Data;
009import gudusoft.gsqlparser.dlineage.graph.model.Result;
010import gudusoft.gsqlparser.dlineage.graph.ui.EdgeRelation;
011import gudusoft.gsqlparser.dlineage.graph.ui.Item;
012import gudusoft.gsqlparser.dlineage.graph.ui.Label;
013import gudusoft.gsqlparser.dlineage.graph.ui.Table;
014import gudusoft.gsqlparser.dlineage.graph.utils.XMLUtil;
015import gudusoft.gsqlparser.dlineage.metadata.*;
016import gudusoft.gsqlparser.dlineage.util.Pair;
017import gudusoft.gsqlparser.dlineage.util.Pair3;
018import gudusoft.gsqlparser.dlineage.util.RemoveDataflowFunction;
019import gudusoft.gsqlparser.sqlenv.TSQLEnv;
020import gudusoft.gsqlparser.util.json.JSON;
021import org.w3c.dom.Document;
022import java.util.*;
023import java.util.regex.Matcher;
024import java.util.regex.Pattern;
025import java.util.stream.Collectors;
026
027public class DataFlowGraphGenerator {
028
029    public String genDlineageGraph(EDbVendor vendor, boolean isIndirect, dataflow dataflow) throws Exception {
030        return genDlineageGraph(vendor, isIndirect, dataflow, false);
031    }
032
033    /**
034     * Graph JSON of {@code dataflow}.
035     *
036     * @param includeIsolatedNodes {@code false}, what {@link #genDlineageGraph(EDbVendor, boolean, dataflow)} uses,
037     *                             keeps only the tables, resultsets and columns that take part in a relationship;
038     *                             {@code true} also keeps the isolated ones, such as a table a {@code CREATE TABLE}
039     *                             declares that nothing reads, or the resultset of {@code SELECT 1 AS n}, and the
040     *                             unlinked columns of every node. No relationship is added either way (Mantis 4812).
041     */
042    public String genDlineageGraph(EDbVendor vendor, boolean isIndirect, dataflow dataflow, boolean includeIsolatedNodes)
043            throws Exception {
044        Result result = new Result();
045        Data data = new Data();
046        data.setMode("global");
047        List<RelationshipType> relationshipTypes =new ArrayList<>();
048        if(isIndirect){
049            relationshipTypes.add(RelationshipType.fdd);
050            relationshipTypes.add(RelationshipType.fdr);
051            relationshipTypes.add(RelationshipType.fddi);
052            relationshipTypes.add(RelationshipType.frd);
053        }
054        else{
055            relationshipTypes.add(RelationshipType.fdd);
056        }
057        Map graph = getSqlflowGraph(vendor, relationshipTypes, !includeIsolatedNodes, false, false, dataflow, false,
058                includeIsolatedNodes);
059        data.setGraph(graph);
060        result.setData(data);
061        Dataflow model = DataFlowAnalyzer.getSqlflowJSONModel(dataflow, vendor);
062        data.setSqlflow(gudusoft.gsqlparser.util.json.JSON.parseObject(gudusoft.gsqlparser.util.json.JSON.toJSONString(model)));
063        result.setCode(200);
064        result.setData(data);
065        result.setMsg(dataflow.getErrors());
066        return JSON.toJSONString(result);
067
068    }
069
070    public String genERGraph(EDbVendor vendor, dataflow dataflow) throws Exception {
071        Result result = new Result();
072        Data data = new Data();
073        data.setMode("global");
074        dataflow.setRelationships(dataflow.getRelationships().stream().filter(t ->  t.getType().equals("er")).collect(Collectors.toList()));
075        List<RelationshipType> relationshipTypes = new ArrayList<>();
076        relationshipTypes.add(RelationshipType.er);
077        Map graph = getSqlflowGraph(vendor, relationshipTypes, false, false, true, dataflow, false, false);
078        data.setGraph(graph);
079        result.setData(data);
080        Dataflow model = DataFlowAnalyzer.getSqlflowJSONModel(dataflow, vendor);
081        data.setSqlflow(gudusoft.gsqlparser.util.json.JSON.parseObject(gudusoft.gsqlparser.util.json.JSON.toJSONString(model)));
082        result.setCode(200);
083        result.setData(data);
084        result.setMsg(dataflow.getErrors());
085        return JSON.toJSONString(result);
086
087    }
088
089    public String genDataflowGraph(Dataflow model) throws Exception {
090        return genDataflowGraph(model, false);
091    }
092
093    /**
094     * Graph JSON of a SQLFlow JSON model.
095     *
096     * @param includeIsolatedNodes {@code false}, what {@link #genDataflowGraph(Dataflow)} uses, keeps only the
097     *                             tables, resultsets and columns that take part in a relationship; {@code true} also
098     *                             keeps the isolated ones, such as a table a {@code CREATE TABLE} declares that nothing
099     *                             reads, or the resultset of {@code SELECT 1 AS n}, and the unlinked columns of every
100     *                             node. No relationship is added either way (Mantis 4812).
101     */
102    public String genDataflowGraph(Dataflow model, boolean includeIsolatedNodes) throws Exception {
103        Result result = new Result();
104        Data data = new Data();
105        data.setMode("global");
106        List<RelationshipType> relationshipTypes =new ArrayList<>();
107        relationshipTypes.add(RelationshipType.fdd);
108        relationshipTypes.add(RelationshipType.fdr);
109        relationshipTypes.add(RelationshipType.fddi);
110        relationshipTypes.add(RelationshipType.frd);
111        dataflow dataflow = generateGraphFromDataflow(model);
112        Map graph = getSqlflowGraph(null, relationshipTypes, !includeIsolatedNodes, false, false, dataflow, false,
113                includeIsolatedNodes);
114        data.setGraph(graph);
115        result.setData(data);
116        data.setSqlflow(gudusoft.gsqlparser.util.json.JSON.parseObject(gudusoft.gsqlparser.util.json.JSON.toJSONString(model)));
117        result.setCode(200);
118        result.setData(data);
119        result.setMsg(dataflow.getErrors());
120        return JSON.toJSONString(result);
121
122    }
123
124    private Map getSqlflowGraph(EDbVendor vendor, List<RelationshipType> relationshipTypes,
125                                boolean showLinkOnly, boolean hideColumn, boolean ignoreFunction, dataflow dataflow,
126                                boolean containGraphML, boolean includeIsolatedNodes) throws Exception {
127        Map graph = new LinkedHashMap();
128        DataFlowGraph dataFlowGraph = new DataFlowGraph();
129        Map<String, String> tooltipMap = new HashMap<String, String>();
130        String orientation = dataflow.getOrientation();
131
132        if (ignoreFunction && (!relationshipTypes.contains(RelationshipType.er)) && (vendor!=null)) {
133            dataflow = new RemoveDataflowFunction().removeFunction(dataflow, vendor);
134        }
135        final Pair3<String, Boolean, Set<String>> graphContent = dataFlowGraph
136                .generateDataFlowGraph(dataflow,
137                        showLinkOnly, hideColumn,
138                        relationshipTypes,
139                        tooltipMap, includeIsolatedNodes);
140        List<Object> graphNodes = dataFlowGraph.getNodes();
141        List<relationship> relationships = dataFlowGraph.getRelationships();
142        String graphml;
143        if (graphContent != null && graphContent.first != null) {
144            graphml = graphContent.first
145                    .replace("\r\n", "\n").replace("\n", " ");
146        } else {
147            graphml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:java=\"http://www.yworks.com/xml/yfiles-model/1.0/java\" xmlns:sys=\"http://www.yworks.com/xml/yfiles-model/markup/primitives/2.0\" xmlns:x=\"http://www.yworks.com/xml/yfiles-model/markup/2.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:y=\"http://www.yworks.com/xml/graphml\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\"></graphml>";
148        }
149
150        String graphML = graphml;
151        String xml = graphML.replace("y:", "");
152
153        int groupNum = -1;
154        int columnNum = -1;
155        int index = 0;
156        String id;
157
158        Map<String, String[]> listIdMap = new LinkedHashMap<String, String[]>();
159        Map<String, String> modelColumnIdMap = new LinkedHashMap<String, String>();
160        Map<String, String> modelTableIdMap = new LinkedHashMap<String, String>();
161        Map<String, String[]> relationshipIdMap = new LinkedHashMap<String, String[]>();
162
163        LinkedList<Table> tables = new LinkedList<Table>();
164        List<Item> items = new ArrayList<Item>();
165
166        Pattern nodePattern = Pattern.compile("<node\\s+id=\"(.+?)\".+?(<data.+?</data>)", Pattern.DOTALL);
167        Matcher nodeMatcher = nodePattern.matcher(xml);
168        Map<String, Document> nodeMap = new LinkedHashMap<>();
169        while (nodeMatcher.find()) {
170            Document document = XMLUtil.parseXmlString(nodeMatcher.group(2));
171            if (document != null) {
172                nodeMap.put(nodeMatcher.group(1), document);
173            }
174        }
175
176        boolean showCallRelation = relationshipTypes.contains(RelationshipType.call);
177
178        if (!nodeMap.isEmpty()) {
179            for (String nodeId : nodeMap.keySet()) {
180                Document node = nodeMap.get(nodeId);
181                if (XMLUtil.containsNode(node, "ProxyAutoBoundsNode")) {
182                    if (!tables.isEmpty()) {
183                        tables.getLast().setColumns(items.toArray(new Item[0]));
184                    }
185                    items.clear();
186                    groupNum++;
187                    id = "n" + groupNum;
188                    columnNum = -1;
189                    appendTableGraph(tables, nodeMap.get(nodeId), id);
190                } else {
191                    if (XMLUtil.containsText(node, "hide-table-column")) {
192                        continue;
193                    }
194                    columnNum++;
195                    id = "n" + groupNum + "::n" + columnNum;
196                    appendColumnGraph(items, nodeMap.get(nodeId), id);
197                }
198                int nodeIndex = index;
199                if(showCallRelation){
200                    nodeIndex = nodeIndex/2;
201                }
202                Object selection = graphNodes.get(nodeIndex);
203                if (selection instanceof List) {
204                    List<column> columns = (List<column>) selection;
205                    List<String> ids = new ArrayList<String>();
206                    if (columns != null) {
207                        for (column column : columns) {
208                            ids.add(column.getId());
209                            modelColumnIdMap.put(column.getId(), id);
210                        }
211                    }
212                    listIdMap.put(id, ids.toArray(new String[0]));
213                } else if (selection instanceof column) {
214                    column column = (column) selection;
215                    modelColumnIdMap.put(column.getId(), id);
216                    listIdMap.put(id, new String[]{column.getId()});
217                } else if (selection instanceof table) {
218                    table table = (table) selection;
219                    modelTableIdMap.put(table.getId(), id);
220                    listIdMap.put(id, new String[]{table.getId()});
221                } else if (selection instanceof process) {
222                    process process = (process) selection;
223                    modelTableIdMap.put(process.getId(), id);
224                    listIdMap.put(id, new String[]{process.getId()});
225                } else if (selection instanceof procedure) {
226                    procedure procedure = (procedure) selection;
227                    modelTableIdMap.put(procedure.getId(), id);
228                    listIdMap.put(id, new String[]{procedure.getId()});
229                }
230                index++;
231            }
232        }
233
234        if (!tables.isEmpty()) {
235            tables.getLast().setColumns(items.toArray(new Item[0]));
236        }
237
238        Pattern relationshipPattern = Pattern.compile("<edge\\s+id=\"(.+?)\".+?source=\"(.+?)\".+?target=\"(.+?)\">", Pattern.DOTALL);
239        Matcher relationshipMatcher = relationshipPattern.matcher(xml);
240        Map<String, String[]> relationshipMap = new HashMap<String, String[]>();
241        while (relationshipMatcher.find()) {
242            relationshipMap.put(relationshipMatcher.group(1), new String[]{relationshipMatcher.group(2), relationshipMatcher.group(3)});
243        }
244        LinkedList<EdgeRelation> edges = new LinkedList<EdgeRelation>();
245
246        int edgeNum = 0;
247        if (relationships != null) {
248            Collections.reverse(relationships);
249            Set<Pair<String, String>> fddRelations = new HashSet<Pair<String, String>>();
250            Map<Pair<String, String>, String> relationshipEdgeMap = new HashMap<Pair<String, String>, String>();
251            for (relationship relationship : relationships) {
252                targetColumn target = relationship.getTarget();
253                List<sourceColumn> sourceColumn = relationship.getSources();
254                if(RelationshipType.call.name().equals(relationship.getType())){
255                    target = relationship.getCaller();
256                    sourceColumn = relationship.getCallees();
257                    if (target != null && sourceColumn != null) {
258                        for (sourceColumn source : sourceColumn) {
259                            String sourceId = modelTableIdMap.get(source.getId());
260                            String targetId = modelTableIdMap.get(target.getId());
261                            if (sourceId != null && targetId != null) {
262                                Pair<String, String> relationshipPair = new Pair<String, String>(sourceId, targetId);
263                                if (!fddRelations.contains(relationshipPair)) {
264                                    if (RelationshipType.fdd.name().equals(relationship.getType())) {
265                                        fddRelations.add(relationshipPair);
266                                    }
267                                    if (relationshipEdgeMap.containsKey(relationshipPair)) {
268                                        if (RelationshipType.fdd.name().equals(relationship.getType())) {
269                                            relationshipIdMap.put(relationshipEdgeMap.get(relationshipPair), new String[]{relationship.getId(), relationship.getType()});
270                                        }
271                                    } else {
272                                        EdgeRelation edge = new EdgeRelation();
273                                        edge.setId("e" + edgeNum);
274                                        //call relation的箭头方向和fdd是相反的
275                                        edge.setSourceId(targetId);
276                                        edge.setTargetId(sourceId);
277                                        edges.add(edge);
278                                        relationshipIdMap.put(edge.getId(), new String[]{relationship.getId(), relationship.getType()});
279                                        relationshipEdgeMap.put(relationshipPair, edge.getId());
280                                        edgeNum++;
281                                    }
282                                }
283                            }
284                        }
285                    }
286                }
287                else {
288                    if (target != null && sourceColumn != null) {
289                        for (sourceColumn source : sourceColumn) {
290                            String sourceId = getSourceId(source, modelColumnIdMap, modelTableIdMap);
291                            String targetId = getTargetId(target, modelColumnIdMap, modelTableIdMap);
292                            if (sourceId != null && targetId != null) {
293                                Pair<String, String> relationshipPair = new Pair<String, String>(sourceId, targetId);
294                                if (!fddRelations.contains(relationshipPair)) {
295                                    if (RelationshipType.fdd.name().equals(relationship.getType())) {
296                                        fddRelations.add(relationshipPair);
297                                    }
298                                    if (relationshipEdgeMap.containsKey(relationshipPair)) {
299                                        if (RelationshipType.fdd.name().equals(relationship.getType())) {
300                                            relationshipIdMap.put(relationshipEdgeMap.get(relationshipPair), new String[]{relationship.getId(), relationship.getType()});
301                                        }
302                                    } else {
303                                        EdgeRelation edge = new EdgeRelation();
304                                        edge.setId("e" + edgeNum);
305                                        edge.setSourceId(sourceId);
306                                        edge.setTargetId(targetId);
307                                        edges.add(edge);
308                                        relationshipIdMap.put(edge.getId(), new String[]{relationship.getId(), relationship.getType()});
309                                        relationshipEdgeMap.put(relationshipPair, edge.getId());
310                                        edgeNum++;
311                                    }
312                                }
313                            }
314                        }
315                    }
316                }
317            }
318        }
319
320        Map graphObject = new LinkedHashMap();
321        graphObject.put("tables", tables.toArray(new Table[0]));
322        graphObject.put("edges", edges.toArray(new EdgeRelation[0]));
323
324        graph.put("elements", graphObject);
325        graph.put("tooltip", tooltipMap);
326        graph.put("listIdMap", listIdMap);
327        graph.put("relationshipIdMap", relationshipIdMap);
328
329        if (containGraphML) {
330            graph.put("graphML", graphML);
331        }
332        Pair3<Map, dataflow, Set<String>> pair =  new Pair3<>(graph, dataflow, graphContent.third);
333        return pair.first;
334    }
335
336    private void appendColumnGraph(List<Item> items, Document document, String id) {
337        Item item = new Item();
338        item.setId(id);
339        String content = XMLUtil.getFirstNodeLabelTextRecursive(document.getDocumentElement());
340        Label label = new Label();
341        label.setContent(content);
342        item.setLabel(label);
343        items.add(item);
344    }
345
346    private void appendTableGraph(List<Table> tables, Document document, String id) {
347        Table table = new Table();
348        table.setId(id);
349        String content = XMLUtil.getFirstNodeLabelTextRecursive(document.getDocumentElement());
350        Label label = new Label();
351        label.setContent(content);
352        table.setLabel(label);
353        tables.add(table);
354    }
355
356    private String getTargetId(targetColumn target, Map<String, String> modelColumnIdMap, Map<String, String> modelTableIdMap) {
357        if (target.getId() != null) {
358            String targetId = modelColumnIdMap.get(target.getId());
359            if (targetId != null) {
360                return targetId;
361            } else if (target.getTarget_id() != null) {
362                return modelTableIdMap.get(target.getTarget_id());
363            }
364        }
365        return null;
366    }
367
368
369    private String getSourceId(sourceColumn source, Map<String, String> modelColumnIdMap, Map<String, String> modelTableIdMap) {
370        if (source.getId() != null) {
371            String sourceId = modelColumnIdMap.get(source.getId());
372            if (sourceId != null) {
373                return sourceId;
374            } else if (source.getSource_id() != null) {
375                return modelTableIdMap.get(source.getSource_id());
376            }
377        } else if (source.getSource_id() != null) {
378            return modelTableIdMap.get(source.getSource_id());
379        }
380        return null;
381    }
382
383    private gudusoft.gsqlparser.dlineage.dataflow.model.xml.table totable(gudusoft.gsqlparser.dlineage.metadata.Table table){
384        gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = new table();
385        aTable.setId(table.getId());
386        aTable.setName(table.getName());
387        aTable.setType(table.getType());
388        aTable.setDisplayName(table.getDisplayName());
389        aTable.setSubType(table.getSubType());
390        aTable.setCoordinate(table.getCoordinates().toString());
391        List<gudusoft.gsqlparser.dlineage.dataflow.model.xml.column> columns = new ArrayList<>();
392        aTable.setColumns(columns);
393        for(gudusoft.gsqlparser.dlineage.metadata.Column col: table.getColumns()){
394            gudusoft.gsqlparser.dlineage.dataflow.model.xml.column column = new column();
395            columns.add(column);
396            column.setId(col.getId());
397            column.setName(col.getName());
398            column.setSource(col.getSource());
399            column.setDataType(col.getDataType());
400            column.setCoordinate(col.getCoordinates().toString());
401            column.setPrimaryKey(col.isPrimaryKey());
402            column.setUnqiueKey(col.isUnqiueKey());
403            column.setIndexKey(col.isIndexKey());
404            column.setForeignKey(col.isForeignKey());
405        }
406        return aTable;
407    }
408    private dataflow generateGraphFromDataflow(Dataflow dataFlow) {
409        dataflow dataflow = new dataflow();
410        List<gudusoft.gsqlparser.dlineage.dataflow.model.xml.table> tables = new ArrayList<>();
411
412        if (dataFlow.getDbobjs() != null) {
413            Sqlflow sqlflow = dataFlow.getDbobjs();
414            if (sqlflow.getServers() != null) {
415                for (Server server : sqlflow.getServers()) {
416                    if (server.isSupportsCatalogs() && server.isSupportsSchemas()) {
417                        if (server.getDatabases() == null)
418                            continue;
419                        for (Database database : server.getDatabases()) {
420                            if (database.getSchemas() == null)
421                                continue;
422                            for (Schema schema : database.getSchemas()) {
423                                if (schema.getTables() != null) {
424                                    for (gudusoft.gsqlparser.dlineage.metadata.Table table : schema.getTables()) {
425                                        gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
426                                        if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
427                                            aTable.setServer(server.getName());
428                                        }
429                                        if (database.getName() != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(database.getName())) {
430                                            aTable.setDatabase(database.getName());
431                                        }
432                                        if (schema.getName() != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schema.getName())) {
433                                            aTable.setSchema(schema.getName());
434                                        }
435                                        tables.add(aTable);
436                                    }
437                                }
438                                if (schema.getViews() != null) {
439                                    for (gudusoft.gsqlparser.dlineage.metadata.Table table : schema.getViews()) {
440                                        gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
441                                        if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
442                                            aTable.setServer(server.getName());
443                                        }
444                                        if (database.getName() != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(database.getName())) {
445                                            aTable.setDatabase(database.getName());
446                                        }
447                                        if (schema.getName() != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schema.getName())) {
448                                            aTable.setSchema(schema.getName());
449                                        }
450                                        tables.add(aTable);
451                                    }
452                                }
453                                if (schema.getOthers() != null) {
454                                    for (gudusoft.gsqlparser.dlineage.metadata.Table table : schema.getOthers()) {
455                                        gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
456                                        if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
457                                            aTable.setServer(server.getName());
458                                        }
459                                        if (database.getName() != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(database.getName())) {
460                                            aTable.setDatabase(database.getName());
461                                        }
462                                        if (schema.getName() != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schema.getName())) {
463                                            aTable.setSchema(schema.getName());
464                                        }
465                                        tables.add(aTable);
466                                    }
467                                }
468                            }
469                        }
470                    } else if (server.isSupportsCatalogs() && server.getDatabases() != null) {
471                        for (Database database : server.getDatabases()) {
472                            if (database.getTables() != null) {
473                                for (gudusoft.gsqlparser.dlineage.metadata.Table table : database.getTables()) {
474                                    gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
475                                    if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
476                                        aTable.setServer(server.getName());
477                                    }
478                                    if (database.getName() != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(database.getName())) {
479                                        aTable.setDatabase(database.getName());
480                                    }
481                                    tables.add(aTable);
482                                }
483                            }
484                            if (database.getViews() != null) {
485                                for (gudusoft.gsqlparser.dlineage.metadata.Table table : database.getViews()) {
486                                    gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
487                                    if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
488                                        aTable.setServer(server.getName());
489                                    }
490                                    if (database.getName() != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(database.getName())) {
491                                        aTable.setDatabase(database.getName());
492                                    }
493                                    tables.add(aTable);
494                                }
495                            }
496                            if (database.getOthers() != null) {
497                                for (gudusoft.gsqlparser.dlineage.metadata.Table table : database.getOthers()) {
498                                    gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
499                                    if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
500                                        aTable.setServer(server.getName());
501                                    }
502                                    if (database.getName() != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(database.getName())) {
503                                        aTable.setDatabase(database.getName());
504                                    }
505                                    tables.add(aTable);
506                                }
507                            }
508                        }
509                    } else if (server.isSupportsSchemas() && server.getSchemas() != null) {
510                        for (Schema schema : server.getSchemas()) {
511                            if (schema.getTables() != null) {
512                                for (gudusoft.gsqlparser.dlineage.metadata.Table table : schema.getTables()) {
513                                    gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
514                                    if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
515                                        aTable.setServer(server.getName());
516                                    }
517                                    if (schema.getName() != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schema.getName())) {
518                                        aTable.setSchema(schema.getName());
519                                    }
520                                    tables.add(aTable);
521                                }
522                            }
523                            if (schema.getViews() != null) {
524                                for (gudusoft.gsqlparser.dlineage.metadata.Table table : schema.getViews()) {
525                                    gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
526                                    if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
527                                        aTable.setServer(server.getName());
528                                    }
529                                    if (schema.getName() != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schema.getName())) {
530                                        aTable.setSchema(schema.getName());
531                                    }
532                                    tables.add(aTable);
533                                }
534                            }
535                            if (schema.getOthers() != null) {
536                                for (gudusoft.gsqlparser.dlineage.metadata.Table table : schema.getOthers()) {
537                                    gudusoft.gsqlparser.dlineage.dataflow.model.xml.table aTable = totable(table);
538                                    if (server != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(server.getName())) {
539                                        aTable.setServer(server.getName());
540                                    }
541                                    if (schema.getName() != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schema.getName())) {
542                                        aTable.setSchema(schema.getName());
543                                    }
544                                    tables.add(aTable);
545                                }
546                            }
547                        }
548                    }
549                }
550            }
551        }
552
553        for (gudusoft.gsqlparser.dlineage.dataflow.model.xml.table dbObject : tables) {
554            if (dbObject.getColumns() == null)
555                continue;
556            table table = new table();
557            table.setId(dbObject.getId());
558            table.setCoordinate("[{\"x\":-1,\"y\":-1,\"hashCode\":\"0\"},{\"x\":-1,\"y\":-1,\"hashCode\":\"0\"}]");
559            table.setName(dbObject.getFullName());
560            table.setDisplayName(dbObject.getDisplayName());
561            table.setDatabase(dbObject.getDatabase());
562            table.setSchema(dbObject.getSchema());
563            table.setType(dbObject.getType());
564            table.setMore(dbObject.getMore());
565            switch (dbObject.getType()) {
566                case "table":
567                    dataflow.getTables().add(table);
568                    break;
569                case "view":
570                case "materialized view":
571                    dataflow.getViews().add(table);
572                    break;
573                case "resultset":
574                    if (table.getSubType() != null) {
575                        table.setType(table.getSubType());
576                        table.setSubType(null);
577                    }
578                    dataflow.getResultsets().add(table);
579                    break;
580                case "variable":
581                    dataflow.getVariables().add(table);
582                    break;
583                case "path":
584                    dataflow.getPaths().add(table);
585                    break;
586                case "stream":
587                    dataflow.getStreams().add(table);
588                    break;
589                case "datasource":
590                    dataflow.getDatasources().add(table);
591                    break;
592                case "stage":
593                    dataflow.getStages().add(table);
594                    break;
595                case "sequence":
596                    dataflow.getSequences().add(table);
597                    break;
598                case "schema":
599                    dataflow.getSchemas().add(table);
600                    break;
601                case "database":
602                    dataflow.getDatabases().add(table);
603                    break;
604                default:
605                    dataflow.getResultsets().add(table);
606            }
607
608            table.setColumns(new ArrayList<>());
609            for (gudusoft.gsqlparser.dlineage.dataflow.model.xml.column columnObject : dbObject.getColumns()) {
610                if (columnObject == null) {
611                    continue;
612                }
613                column column = new column();
614                column.setId(columnObject.getId());
615                column.setCoordinate("[{\"x\":-1,\"y\":-1,\"hashCode\":\"0\"},{\"x\":-1,\"y\":-1,\"hashCode\":\"0\"}]");
616                column.setName(columnObject.getName());
617                column.setStar(columnObject.getStar());
618                column.setDataType(columnObject.getDataType());
619                column.setPrimaryKey(columnObject.isPrimaryKey());
620                column.setIndexKey(columnObject.isIndexKey());
621                column.setUnqiueKey(columnObject.isUnqiueKey());
622                column.setForeignKey(columnObject.isForeignKey());
623                table.getColumns().add(column);
624            }
625        }
626
627        dataflow.setRelationships(new ArrayList<>());
628        for (gudusoft.gsqlparser.dlineage.dataflow.model.json.Relationship relationshipObject : dataFlow.getRelationships()) {
629            if (relationshipObject == null ||
630                    relationshipObject.getTarget() == null ||
631                    relationshipObject.getSources() == null ||
632                    relationshipObject.getSources().length == 0) {
633                continue;
634            }
635            relationship relationship = new relationship();
636            relationship.setId(relationshipObject.getId());
637            relationship.setType(relationshipObject.getType());
638            relationship.setEffectType(relationshipObject.getEffectType());
639            relationship.setTimestampMin(relationshipObject.getTimestampMin());
640            relationship.setTimestampMax(relationshipObject.getTimestampMax());
641
642            targetColumn targetColumn = new targetColumn();
643            targetColumn.setId(relationshipObject.getTarget().getId());
644            targetColumn.setParent_name(relationshipObject.getTarget().getParentName());
645            targetColumn.setParent_id(relationshipObject.getTarget().getParentId());
646            targetColumn.setColumn(relationshipObject.getTarget().getColumn());
647            relationship.setTarget(targetColumn);
648
649            relationship.setSources(new ArrayList<>());
650            if (relationshipObject.getSources() != null) {
651                for (gudusoft.gsqlparser.dlineage.dataflow.model.json.RelationshipElement sourceObject : relationshipObject.getSources()) {
652                    sourceColumn sourceColumn = new sourceColumn();
653                    sourceColumn.setParent_name(sourceObject.getParentName());
654                    sourceColumn.setParent_id(sourceObject.getParentId());
655                    sourceColumn.setColumn(sourceObject.getColumn());
656                    sourceColumn.setId(sourceObject.getId());
657                    relationship.getSources().add(sourceColumn);
658                }
659            }
660            dataflow.getRelationships().add(relationship);
661        }
662        dataflow.setOrientation(dataFlow.getOrientation());
663        return dataflow;
664    }
665}