001package gudusoft.gsqlparser.dlineage.util;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.dlineage.DataFlowAnalyzer;
005import gudusoft.gsqlparser.dlineage.ParallelDataFlowAnalyzer;
006import gudusoft.gsqlparser.dlineage.dataflow.metadata.MetadataReader;
007import gudusoft.gsqlparser.dlineage.dataflow.metadata.sqldep.SQLDepMetadataAnalyzer;
008import gudusoft.gsqlparser.dlineage.dataflow.model.ModelBindingManager;
009import gudusoft.gsqlparser.dlineage.dataflow.model.RelationshipType;
010import gudusoft.gsqlparser.dlineage.dataflow.model.json.Error;
011import gudusoft.gsqlparser.dlineage.dataflow.model.json.Process;
012import gudusoft.gsqlparser.dlineage.dataflow.model.json.*;
013import gudusoft.gsqlparser.dlineage.dataflow.model.xml.*;
014import gudusoft.gsqlparser.dlineage.metadata.Sqlflow;
015import gudusoft.gsqlparser.util.Logger;
016import gudusoft.gsqlparser.util.LoggerFactory;
017import gudusoft.gsqlparser.util.SQLUtil;
018import gudusoft.gsqlparser.util.json.JSON;
019
020import java.util.*;
021import java.util.concurrent.atomic.AtomicLong;
022import java.util.stream.Collectors;
023
024public class DataflowUtility {
025
026    private static final Logger logger = LoggerFactory.getLogger(FunctionUtility.class);
027
028    public static dataflow mergeFunctionCallDataflow(dataflow dataflow, EDbVendor dbVendor) {
029        if (ModelBindingManager.getGlobalVendor() == null) {
030            ModelBindingManager.setGlobalVendor(dbVendor);
031        }
032        dataflow instance = cloneDataflow(dataflow);
033        List<procedure> procedures = new ArrayList<>(instance.getProcedures());
034        if (instance.getPackages() != null) {
035            for (oraclePackage pkg : instance.getPackages()) {
036                if (pkg.getProcedures() != null) {
037                    for (procedure procedure : pkg.getProcedures()) {
038                        procedure.setOraclePackage(pkg);
039                        procedures.add(procedure);
040                    }
041                }
042            }
043        }
044
045        Map<String, procedure> procedureIdMap = procedures.stream().collect(Collectors.toMap(
046                t -> t.getId(),
047                t -> t,
048                (existingValue, newValue) -> newValue
049        ));
050        Map<String, table> functionIdMap = dataflow.getResultsets().stream().collect(Collectors.toMap(
051                t -> t.getId(),
052                t -> t,
053                (existingValue, newValue) -> newValue
054        ));
055
056        Map<String, table> functionMap = new HashMap<>();
057        Map<String, procedure> procedureMap = new HashMap<>();
058        Map<String, oraclePackage> oraclePackageMap = new HashMap<>();
059        Map<String, Set<String>> oraclePackageProcedureMap = new HashMap<>();
060        if (instance.getPackages() != null) {
061            for (oraclePackage pkg : instance.getPackages()) {
062                String qualifiedPackageName = DlineageUtil.getIdentifierOraclePackageNameWithArgNum(pkg);
063                if (!oraclePackageMap.containsKey(qualifiedPackageName)) {
064                    oraclePackageMap.put(qualifiedPackageName, pkg);
065                }
066                for (procedure procedure : pkg.getProcedures()) {
067                    String qualifiedProcedureName = qualifiedPackageName + "." + DlineageUtil.getIdentifierProcedureNameWithArgNum(procedure);
068                    if (!oraclePackageProcedureMap.containsKey(qualifiedPackageName)) {
069                        oraclePackageProcedureMap.put(qualifiedPackageName, new HashSet<>());
070                    }
071                    oraclePackageProcedureMap.get(qualifiedPackageName).add(qualifiedProcedureName);
072                }
073            }
074        }
075
076
077
078        for (procedure procedure : procedures) {
079            String qualifiedProcedureName = DlineageUtil.getIdentifierProcedureNameWithArgNum(procedure);
080            if (procedure.getOraclePackage() != null) {
081                String qualifiedPackageName = DlineageUtil.getIdentifierOraclePackageNameWithArgNum(procedure.getOraclePackage());
082                qualifiedProcedureName = qualifiedPackageName + "." + DlineageUtil.getIdentifierProcedureNameWithArgNum(procedure);
083            }
084            if (!procedureMap.containsKey(qualifiedProcedureName)) {
085                procedureMap.put(qualifiedProcedureName, procedure);
086            }
087        }
088
089        for (table function : instance.getResultsets()) {
090            String qualifiedFunctionName = DlineageUtil.getIdentifierFunctionName(function);
091            if (!functionMap.containsKey(qualifiedFunctionName)) {
092                functionMap.put(qualifiedFunctionName, function);
093            }
094        }
095
096        Set<oraclePackage> oraclePackages = new LinkedHashSet<>();
097        for (String key : oraclePackageMap.keySet()) {
098            oraclePackage standardPackage = oraclePackageMap.get(key);
099            oraclePackages.add(standardPackage);
100            Set<String> procedureNames = oraclePackageProcedureMap.get(key);
101            if (procedureNames != null) {
102                for (String procedureName : procedureNames) {
103                    procedureName = key + "." + procedureName;
104                    if (procedureMap.containsKey(procedureName)) {
105                        procedure standardProcedure = procedureMap.get(procedureName);
106                        if (!standardPackage.getProcedures().contains(standardProcedure)) {
107                            standardPackage.getProcedures().add(standardProcedure);
108                        }
109                        procedureMap.remove(procedureName);
110                    }
111                }
112            }
113        }
114
115        instance.setPackages(new ArrayList<>(oraclePackages));
116        instance.setProcedures(new ArrayList<>(procedureMap.values()));
117        instance.setResultsets(new ArrayList<>(functionMap.values()));
118
119        Map<String, relationship> mergeRelations = new LinkedHashMap<String, relationship>();
120
121        for (relationship relationship : instance.getRelationships()) {
122            if (relationship.getCaller() == null || relationship.getCallees() == null || relationship.getCallees().size() == 0) {
123                continue;
124            }
125
126            String targetId = relationship.getCaller().getId();
127            if (procedureIdMap.containsKey(targetId)) {
128                procedure procedure = procedureIdMap.get(targetId);
129                String procedureName = DlineageUtil.getIdentifierProcedureNameWithArgNum(procedure);
130                if (procedure.getOraclePackage() != null) {
131                    String qualifiedPackageName = DlineageUtil.getIdentifierOraclePackageNameWithArgNum(procedure.getOraclePackage());
132                    procedureName = qualifiedPackageName + "." + procedureName;
133                }
134                procedure standardProcedure = procedureMap.get(procedureName);
135                relationship.getCaller().setId(standardProcedure.getId());
136            } else if (functionIdMap.containsKey(targetId)) {
137                table function = functionIdMap.get(targetId);
138                String functionName = DlineageUtil.getIdentifierFunctionName(function);
139                table standardFunction = functionMap.get(functionName);
140                relationship.getCaller().setId(standardFunction.getId());
141            }
142
143            for (sourceColumn sourceColumn : relationship.getCallees()) {
144                String sourceId = sourceColumn.getId();
145                if (procedureIdMap.containsKey(sourceId)) {
146                    procedure procedure = procedureIdMap.get(sourceId);
147                    String procedureName = DlineageUtil.getIdentifierProcedureNameWithArgNum(procedure);
148                    if (procedure.getOraclePackage() != null) {
149                        String qualifiedPackageName = DlineageUtil.getIdentifierOraclePackageNameWithArgNum(procedure.getOraclePackage());
150                        procedureName = qualifiedPackageName + "." + procedureName;
151                    }
152                    procedure standardProcedure = procedureMap.get(procedureName);
153                    sourceColumn.setId(standardProcedure.getId());
154                } else if (functionIdMap.containsKey(sourceId)) {
155                    table function = functionIdMap.get(sourceId);
156                    String functionName = DlineageUtil.getIdentifierFunctionName(function);
157                    table standardFunction = functionMap.get(functionName);
158                    sourceColumn.setId(standardFunction.getId());
159                }
160            }
161
162            String jsonString = JSON.toJSONString(relationship).replaceAll("\"id\":\".+?\"", "");
163            String key = SHA256.getMd5(jsonString);
164            if (!mergeRelations.containsKey(key)) {
165                mergeRelations.put(key, relationship);
166            }
167        }
168
169        instance.setRelationships(new ArrayList<relationship>(mergeRelations.values()));
170
171        if (instance.getPackages() != null) {
172            for (oraclePackage pkg : instance.getPackages()) {
173                if (pkg.getProcedures() != null) {
174                    for (procedure procedure : pkg.getProcedures()) {
175                        procedure.setOraclePackage(null);
176                    }
177                }
178            }
179        }
180
181        return instance;
182    }
183
184    public static dataflow convertTableLevelToFunctionCallDataflow(dataflow dataflow, boolean showBuiltIn, EDbVendor dbVendor) {
185        if (ModelBindingManager.getGlobalVendor() == null) {
186            ModelBindingManager.setGlobalVendor(dbVendor);
187        }
188
189        dataflow instance = cloneDataflow(dataflow);
190
191        if (instance.getRelationships() == null) {
192            return instance;
193        }
194
195        List<relationship> callRelationships = instance.getRelationships().stream()
196                .filter(t -> RelationshipType.call.name().equals(t.getType()))
197                .filter(t -> !showBuiltIn ? !Boolean.TRUE.equals(t.getBuiltIn()): true).collect(Collectors.toList());
198        instance.setRelationships(callRelationships);
199
200        Set<String> ids = new HashSet<>();
201
202
203        callRelationships.stream().forEach(t -> {
204            ids.add(t.getCaller().getId());
205            t.getCallees().stream().forEach(t1 -> ids.add(t1.getId()));
206        });
207
208        Iterator<table> iterator = instance.getTables().iterator();
209        while (iterator.hasNext()) {
210            table t = iterator.next();
211            if (!ids.contains(t.getId())) {
212                iterator.remove();
213            }
214        }
215
216        iterator = instance.getResultsets().iterator();
217        while (iterator.hasNext()) {
218            table t = iterator.next();
219            if (!ids.contains(t.getId())) {
220                iterator.remove();
221            }
222        }
223
224        iterator = instance.getViews().iterator();
225        while (iterator.hasNext()) {
226            table t = iterator.next();
227            if (!ids.contains(t.getId())) {
228                iterator.remove();
229            }
230        }
231
232        iterator = instance.getStages().iterator();
233        while (iterator.hasNext()) {
234            table t = iterator.next();
235            if (!ids.contains(t.getId())) {
236                iterator.remove();
237            }
238        }
239
240        iterator = instance.getStreams().iterator();
241        while (iterator.hasNext()) {
242            table t = iterator.next();
243            if (!ids.contains(t.getId())) {
244                iterator.remove();
245            }
246        }
247
248        iterator = instance.getVariables().iterator();
249        while (iterator.hasNext()) {
250            table t = iterator.next();
251            if (!ids.contains(t.getId())) {
252                iterator.remove();
253            }
254        }
255
256        iterator = instance.getPaths().iterator();
257        while (iterator.hasNext()) {
258            table t = iterator.next();
259            if (!ids.contains(t.getId())) {
260                iterator.remove();
261            }
262        }
263
264        iterator = instance.getDatasources().iterator();
265        while (iterator.hasNext()) {
266            table t = iterator.next();
267            if (!ids.contains(t.getId())) {
268                iterator.remove();
269            }
270        }
271
272        iterator = instance.getDatabases().iterator();
273        while (iterator.hasNext()) {
274            table t = iterator.next();
275            if (!ids.contains(t.getId())) {
276                iterator.remove();
277            }
278        }
279
280        iterator = instance.getSchemas().iterator();
281        while (iterator.hasNext()) {
282            table t = iterator.next();
283            if (!ids.contains(t.getId())) {
284                iterator.remove();
285            }
286        }
287
288        iterator = instance.getSequences().iterator();
289        while (iterator.hasNext()) {
290            table t = iterator.next();
291            if (!ids.contains(t.getId())) {
292                iterator.remove();
293            }
294        }
295
296        return mergeFunctionCallDataflow(instance, dbVendor);
297    }
298
299    public static dataflow convertToTableLevelDataflow(dataflow dataflow) {
300        dataflow instance = cloneDataflow(dataflow);
301
302        if (instance.getRelationships() == null) {
303            return instance;
304        }
305
306        Map<String, LinkedHashSet<Pair<String, String>>> relationMap = new HashMap<String, LinkedHashSet<Pair<String, String>>>();
307        Map<String, LinkedHashSet<Pair3<String, String, relationship>>> callRelationMap = new HashMap<String, LinkedHashSet<Pair3<String, String, relationship>>>();
308        for (RelationshipType type : RelationshipType.values()) {
309            relationMap.put(type.name(), new LinkedHashSet<Pair<String, String>>());
310            callRelationMap.put(type.name(), new LinkedHashSet<Pair3<String, String, relationship>>());
311        }
312        for (relationship relationship : instance.getRelationships()) {
313            if (RelationshipType.call.name().equals(relationship.getType())) {
314                String targetId = relationship.getCaller().getId();
315                for (sourceColumn sourceColumn : relationship.getCallees()) {
316                    String sourceId = sourceColumn.getId();
317                    callRelationMap.get(relationship.getType()).add(new Pair3<>(targetId, sourceId, relationship));
318                }
319            } else {
320                String targetId = relationship.getTarget().getParent_id();
321                for (sourceColumn sourceColumn : relationship.getSources()) {
322                    String sourceId = sourceColumn.getParent_id();
323                    relationMap.get(relationship.getType()).add(new Pair<>(targetId, sourceId));
324                }
325            }
326        }
327
328        long maxId = 0;
329        Map<String, table> dbObjMap = getDataflowDbObjMap(instance);
330
331        List<procedure> procedures = new ArrayList<>(instance.getProcedures());
332        if (instance.getPackages() != null) {
333            for (oraclePackage pkg : instance.getPackages()) {
334                procedures.addAll(pkg.getProcedures());
335            }
336        }
337
338        Map<String, procedure> procedureMap = procedures.stream().collect(Collectors.toMap(
339                t -> t.getId(),
340                t -> t,
341                (existingValue, newValue) -> newValue
342        ));
343
344        for (table table : dbObjMap.values()) {
345            if (Long.valueOf(table.getId()) > maxId) {
346                maxId = Long.valueOf(table.getId());
347            }
348        }
349
350        AtomicLong id = new AtomicLong(maxId + 10000000);
351
352        for (table table : dbObjMap.values()) {
353            column column = new column();
354            column.setId(String.valueOf(id.incrementAndGet()));
355            column.setName(table.getType());
356            table.setColumns(Arrays.asList(column));
357        }
358
359        List<relationship> relations = new ArrayList<relationship>();
360        for (RelationshipType type : RelationshipType.values()) {
361            LinkedHashSet<Pair<String, String>> relationSet = relationMap.get(type.name());
362             LinkedHashSet<Pair3<String, String, relationship>> callRelationSet = callRelationMap.get(type.name());
363            if (RelationshipType.call.equals(type)) {
364                for (Pair3<String, String, relationship> pair : callRelationSet) {
365                    if ((dbObjMap.get(pair.first) == null && procedureMap.get(pair.first) == null)
366                            || (dbObjMap.get(pair.second) == null && procedureMap.get(pair.second) == null)) {
367                        continue;
368                    }
369
370                    relationship relationship = new relationship();
371                    relationship.setType(type.name());
372                    relationship.setId(String.valueOf(id.incrementAndGet()));
373                    relationship.setCallStmt(pair.third.getCallStmt());
374                    relationship.setCallCoordinate(pair.third.getCallCoordinate());
375
376                    targetColumn targetColumn = new targetColumn();
377                    if (dbObjMap.containsKey(pair.first)) {
378                        targetColumn.setId(dbObjMap.get(pair.first).getId());
379                        targetColumn.setName(dbObjMap.get(pair.first).getName());
380                        targetColumn.setCoordinate(dbObjMap.get(pair.first).getCoordinate());
381                    } else {
382                        targetColumn.setId(procedureMap.get(pair.first).getId());
383                        targetColumn.setName(procedureMap.get(pair.first).getName());
384                        targetColumn.setCoordinate(procedureMap.get(pair.first).getCoordinate());
385                    }
386
387                    sourceColumn sourceColumn = new sourceColumn();
388                    if (dbObjMap.containsKey(pair.second)) {
389                        sourceColumn.setId(dbObjMap.get(pair.second).getId());
390                        sourceColumn.setName(dbObjMap.get(pair.second).getName());
391                        sourceColumn.setCoordinate(dbObjMap.get(pair.second).getCoordinate());
392                    } else {
393                        sourceColumn.setId(procedureMap.get(pair.second).getId());
394                        sourceColumn.setName(procedureMap.get(pair.second).getName());
395                        sourceColumn.setCoordinate(procedureMap.get(pair.second).getCoordinate());
396                    }
397
398                    relationship.setCaller(targetColumn);
399                    relationship.setCallees(Arrays.asList(sourceColumn));
400                    relationship.setBuiltIn(pair.third.getBuiltIn());
401                    relations.add(relationship);
402                }
403            } else {
404                for (Pair<String, String> pair : relationSet) {
405                    if (dbObjMap.get(pair.first) == null || dbObjMap.get(pair.second) == null) {
406                        continue;
407                    }
408                    relationship relationship = new relationship();
409                    relationship.setType(type.name());
410                    relationship.setId(String.valueOf(id.incrementAndGet()));
411                    targetColumn targetColumn = new targetColumn();
412                    targetColumn.setId(dbObjMap.get(pair.first).getColumns().get(0).getId());
413                    targetColumn.setColumn(dbObjMap.get(pair.first).getColumns().get(0).getName());
414                    targetColumn.setParent_id(pair.first);
415                    targetColumn.setParent_name(dbObjMap.get(pair.first).getName());
416                    sourceColumn sourceColumn = new sourceColumn();
417                    sourceColumn.setId(dbObjMap.get(pair.second).getColumns().get(0).getId());
418                    sourceColumn.setColumn(dbObjMap.get(pair.second).getColumns().get(0).getName());
419                    sourceColumn.setParent_id(pair.second);
420                    sourceColumn.setParent_name(dbObjMap.get(pair.second).getName());
421                    relationship.setTarget(targetColumn);
422                    relationship.setSources(Arrays.asList(sourceColumn));
423                    relations.add(relationship);
424                }
425            }
426        }
427        instance.setRelationships(relations);
428        return instance;
429    }
430
431    public static dataflow convertToSchemaLevelDataflow(dataflow dataflow, EDbVendor dbVendor) throws Exception {
432        return convertToSchemaLevelDataflow(dataflow, dbVendor, false);
433    }
434
435    public static dataflow convertToSchemaLevelDataflow(dataflow dataflow, EDbVendor dbVendor, boolean isSimple) throws Exception {
436        dataflow instance = cloneDataflow(dataflow);
437
438        if (!isSimple) {
439            DataFlowAnalyzer analyzer = new DataFlowAnalyzer("", dbVendor, true);
440            instance = analyzer.getSimpleDataflow(instance, true, Arrays.asList(new String[]{"fdd", "fdr"}));
441        }
442
443        List<table> allTables = new ArrayList<table>();
444        allTables.addAll(instance.getTables());
445        allTables.addAll(instance.getViews());
446
447        ModelBindingManager.setGlobalVendor(dbVendor);
448
449        Map<String, String> tableIdSchameNameMap = allTables.stream().collect(Collectors.toMap(table -> table.getId(), table -> table.getFullSchemaName(), (existingValue, newValue) -> newValue));
450
451        if (instance.getRelationships() == null) {
452            return instance;
453        }
454
455        Map<String, LinkedHashSet<Pair<String, String>>> relationMap = new HashMap<String, LinkedHashSet<Pair<String, String>>>();
456        for (RelationshipType type : RelationshipType.values()) {
457            relationMap.put(type.name(), new LinkedHashSet<Pair<String, String>>());
458        }
459        for (relationship relationship : instance.getRelationships()) {
460            String targetId = relationship.getTarget().getParent_id();
461            for (sourceColumn sourceColumn : relationship.getSources()) {
462                String sourceId = sourceColumn.getParent_id();
463                relationMap.get(relationship.getType()).add(new Pair<>(tableIdSchameNameMap.get(targetId), tableIdSchameNameMap.get(sourceId)));
464            }
465        }
466
467        Map<String, table> dbObjMap = getDataflowDbObjMap(instance);
468        LinkedHashSet<String> schemaNameSet = new LinkedHashSet<String>();
469        schemaNameSet.addAll(tableIdSchameNameMap.values());
470        List<table> schemaTables = new ArrayList<table>();
471
472        AtomicLong id = new AtomicLong(0);
473
474        for (String schemaName : schemaNameSet) {
475            table table = new table();
476            table.setId(String.valueOf(id.incrementAndGet()));
477            table.setName(schemaName);
478            table.setType("schema");
479            schemaTables.add(table);
480            dbObjMap.put(schemaName, table);
481        }
482
483        for (table table : schemaTables) {
484            column column = new column();
485            column.setId(String.valueOf(id.incrementAndGet()));
486            column.setName(table.getType());
487            table.setColumns(Arrays.asList(column));
488        }
489
490        List<relationship> relations = new ArrayList<relationship>();
491        for (RelationshipType type : RelationshipType.values()) {
492            LinkedHashSet<Pair<String, String>> relationSet = relationMap.get(type.name());
493
494            for (Pair<String, String> pair : relationSet) {
495                if (dbObjMap.get(pair.first) == null || dbObjMap.get(pair.second) == null) {
496                    continue;
497                }
498                relationship relationship = new relationship();
499                relationship.setType(type.name());
500                relationship.setId(String.valueOf(id.incrementAndGet()));
501                targetColumn targetColumn = new targetColumn();
502                targetColumn.setId(dbObjMap.get(pair.first).getColumns().get(0).getId());
503                targetColumn.setColumn(dbObjMap.get(pair.first).getColumns().get(0).getName());
504                targetColumn.setParent_id(dbObjMap.get(pair.first).getId());
505                targetColumn.setParent_name(dbObjMap.get(pair.first).getName());
506                sourceColumn sourceColumn = new sourceColumn();
507                sourceColumn.setId(dbObjMap.get(pair.second).getColumns().get(0).getId());
508                sourceColumn.setColumn(dbObjMap.get(pair.second).getColumns().get(0).getName());
509                sourceColumn.setParent_id(dbObjMap.get(pair.second).getId());
510                sourceColumn.setParent_name(dbObjMap.get(pair.second).getName());
511                relationship.setTarget(targetColumn);
512                relationship.setSources(Arrays.asList(sourceColumn));
513                relations.add(relationship);
514            }
515        }
516
517        dataflow schemaDataflow = new dataflow();
518        schemaDataflow.setTables(schemaTables);
519        schemaDataflow.setRelationships(relations);
520        return schemaDataflow;
521    }
522
523    public static dataflow cloneDataflow(dataflow dataflow) {
524        dataflow dataflowCopy = new dataflow();
525        if (dataflow.getTables() != null) {
526            dataflowCopy.setTables(cloneTables(dataflow.getTables()));
527        }
528        if (dataflow.getViews() != null) {
529            dataflowCopy.setViews(cloneTables(dataflow.getViews()));
530        }
531        if (dataflow.getRelationships() != null) {
532            dataflowCopy.setRelationships(new ArrayList<>(dataflow.getRelationships()));
533        }
534        if (dataflow.getErrors() != null) {
535            dataflowCopy.setErrors(new ArrayList<>(dataflow.getErrors()));
536        }
537        if (dataflow.getPaths() != null) {
538            dataflowCopy.setPaths(cloneTables(dataflow.getPaths()));
539        }
540        if (dataflow.getPackages() != null) {
541            dataflowCopy.setPackages(new ArrayList<>(dataflow.getPackages()));
542        }
543        if (dataflow.getProcedures() != null) {
544            dataflowCopy.setProcedures(new ArrayList<>(dataflow.getProcedures()));
545        }
546        if (dataflow.getProcesses() != null) {
547            dataflowCopy.setProcesses(new ArrayList<>(dataflow.getProcesses()));
548        }
549        if (dataflow.getResultsets() != null) {
550            dataflowCopy.setResultsets(cloneTables(dataflow.getResultsets()));
551        }
552        if (dataflow.getVariables() != null) {
553            dataflowCopy.setVariables(cloneTables(dataflow.getVariables()));
554        }
555        if (dataflow.getStages() != null) {
556            dataflowCopy.setStages(cloneTables(dataflow.getStages()));
557        }
558        if (dataflow.getSequences() != null) {
559            dataflowCopy.setSequences(cloneTables(dataflow.getSequences()));
560        }
561        if (dataflow.getDatasources() != null) {
562            dataflowCopy.setDatasources(cloneTables(dataflow.getDatasources()));
563        }
564        if (dataflow.getDatabases() != null) {
565            dataflowCopy.setDatabases(cloneTables(dataflow.getDatabases()));
566        }
567        if (dataflow.getSchemas() != null) {
568            dataflowCopy.setSchemas(cloneTables(dataflow.getSchemas()));
569        }
570        if (dataflow.getStreams() != null) {
571            dataflowCopy.setStreams(cloneTables(dataflow.getStreams()));
572        }
573        dataflowCopy.setOrientation(dataflow.getOrientation());
574        return dataflowCopy;
575    }
576
577    private static List<table> cloneTables(List<table> tableList) {
578        if (tableList == null) {
579            return null;
580        }
581        List<table> tables = new ArrayList<>(tableList.size());
582        for (table item : tableList) {
583            try {
584                table table = (table) item.clone();
585                if (item.getColumns() != null) {
586                    table.setColumns(new ArrayList<column>(item.getColumns()));
587                }
588                tables.add(table);
589            } catch (CloneNotSupportedException e) {
590                logger.error("Clone table failed.", e);
591            }
592        }
593        return tables;
594    }
595
596    public static Map<String, table> getDataflowDbObjMap(dataflow dataflow) {
597        List<table> tables = new ArrayList<table>();
598        if (dataflow.getTables() != null) {
599            tables.addAll(dataflow.getTables());
600        }
601        if (dataflow.getViews() != null) {
602            tables.addAll(dataflow.getViews());
603        }
604        if (dataflow.getPaths() != null) {
605            tables.addAll(dataflow.getPaths());
606        }
607        if (dataflow.getResultsets() != null) {
608            tables.addAll(dataflow.getResultsets());
609        }
610        if (dataflow.getVariables() != null) {
611            tables.addAll(dataflow.getVariables());
612        }
613        if (dataflow.getStages() != null) {
614            tables.addAll(dataflow.getStages());
615        }
616        if (dataflow.getSequences() != null) {
617            tables.addAll(dataflow.getSequences());
618        }
619        if (dataflow.getDatasources() != null) {
620            tables.addAll(dataflow.getDatasources());
621        }
622        if (dataflow.getDatabases() != null) {
623            tables.addAll(dataflow.getDatabases());
624        }
625        if (dataflow.getSchemas() != null) {
626            tables.addAll(dataflow.getSchemas());
627        }
628        if (dataflow.getStreams() != null) {
629            tables.addAll(dataflow.getStreams());
630        }
631
632        Map<String, table> dbObjMap = new HashMap<>();
633        for (table table : tables) {
634            dbObjMap.put(table.getId(), table);
635        }
636        return dbObjMap;
637        }
638        public static Map<String, table> getDataflowDbObjNameMap(dataflow dataflow) {
639                List<table> tables = new ArrayList<table>();
640                if (dataflow.getTables() != null) {
641                        tables.addAll(dataflow.getTables());
642                }
643                if (dataflow.getViews() != null) {
644                        tables.addAll(dataflow.getViews());
645                }
646                if (dataflow.getPaths() != null) {
647                        tables.addAll(dataflow.getPaths());
648                }
649                if (dataflow.getResultsets() != null) {
650                        tables.addAll(dataflow.getResultsets());
651                }
652                if (dataflow.getVariables() != null) {
653                        tables.addAll(dataflow.getVariables());
654                }
655                if (dataflow.getStages() != null) {
656                        tables.addAll(dataflow.getStages());
657                }
658                if (dataflow.getSequences() != null) {
659                        tables.addAll(dataflow.getSequences());
660                }
661                if (dataflow.getDatasources() != null) {
662                        tables.addAll(dataflow.getDatasources());
663                }
664                if (dataflow.getDatabases() != null) {
665                        tables.addAll(dataflow.getDatabases());
666                }
667                if (dataflow.getSchemas() != null) {
668                        tables.addAll(dataflow.getSchemas());
669                }
670                if (dataflow.getStreams() != null) {
671                        tables.addAll(dataflow.getStreams());
672                }
673
674                Map<String, table> dbObjMap = new HashMap<>();
675                for(table table: tables){
676                        dbObjMap.put(table.getFullName(), table);
677                }
678                return dbObjMap;
679        }
680        public static dataflow mergeDataflows(Collection<dataflow> dataflows, EDbVendor vendor) {
681                return ParallelDataFlowAnalyzer.mergeDataFlows(dataflows, vendor);
682        }
683
684        public static dataflow readDataflowFromCsvMetadata(String csvMetadata, EDbVendor vendor) {
685                if (!MetadataReader.isMetadata(csvMetadata)) {
686                        throw new IllegalArgumentException("Illegal csv metadata.");
687                }
688                return new SQLDepMetadataAnalyzer().analyzeMetadata(vendor, csvMetadata);
689        }
690
691        public static Dataflow mergeDataflowsAndCsv(List<Pair<EDbVendor,dataflow>> pairs, String csvMetadata) {
692                //重置ID防止重复
693                Long index = 0L;
694                for(int i=0; i<pairs.size(); i++){
695                        dataflow dataflow = pairs.get(i).second;
696                        Map<String, table> objIDMap = getDataflowDbObjMap(dataflow);
697                        Map<String, String> idMaps = new HashMap<>();
698                        for (Map.Entry<String, table> entry : objIDMap.entrySet()) {
699                                index = index + 1;
700                                String id = index.toString();
701                                idMaps.put(entry.getKey(), id);
702                                table table = entry.getValue();
703                                table.setId(id);
704                                if(table.getColumns() != null){
705                                        for(column col: table.getColumns()){
706                                                index = index + 1;
707                                                id = index.toString();
708                                                idMaps.put(col.getId(), id);
709                                                col.setId(id);
710                                        }
711                                }
712                        }
713                        if(dataflow.getProcedures() != null){
714                                for(procedure procedure: dataflow.getProcedures()){
715                                        index = index + 1;
716                                        String id = index.toString();
717                                        idMaps.put(procedure.getId(), id);
718                                        procedure.setId(id);
719                                }
720                        }
721                        if(dataflow.getProcesses() != null){
722                                for(process process: dataflow.getProcesses()){
723                                        index = index + 1;
724                                        String id = index.toString();
725                                        idMaps.put(process.getId(), id);
726                                        process.setId(id);
727                                }
728                        }
729                        if(dataflow.getPackages() != null){
730                                for(oraclePackage oraclePackage: dataflow.getPackages()){
731                                        index = index + 1;
732                                        String id = index.toString();
733                                        idMaps.put(oraclePackage.getId(), id);
734                                        oraclePackage.setId(id);
735                                        if(oraclePackage.getProcedures() != null){
736                                                for(procedure procedure: oraclePackage.getProcedures()){
737                                                        index = index + 1;
738                                                        id = index.toString();
739                                                        idMaps.put(procedure.getId(), id);
740                                                        procedure.setId(id);
741                                                }
742                                        }
743                                }
744                        }
745                        if(dataflow.getRelationships() != null && dataflow.getRelationships().size()>0){
746                                for(relationship rel: dataflow.getRelationships()){
747                                        index = index + 1;
748                                        String id = index.toString();
749                                        rel.setId(id);
750                                        rel.setProcedureId(idMaps.get(rel.getProcedureId()));
751                                        rel.setProcessId(idMaps.get(rel.getProcessId()));
752                                        rel.getTarget().setParent_id(idMaps.get(rel.getTarget().getParent_id()));
753                                        rel.getTarget().setTarget_id(idMaps.get(rel.getTarget().getTarget_id()));
754                                        rel.getTarget().setId(idMaps.get(rel.getTarget().getId()));
755                                        for(sourceColumn column: rel.getSources()){
756                                                column.setParent_id(idMaps.get(column.getParent_id()));
757                                                column.setId(idMaps.get(column.getId()));
758                                        }
759                                }
760                        }
761                }
762                Dataflow mDataflow = DataFlowAnalyzer.getSqlflowJSONModel(pairs.get(0).first, pairs.get(0).second, false);
763                Map<String, table> objNameMap = getDataflowDbObjNameMap(pairs.get(0).second);
764                Sqlflow dbobjs = mDataflow.getDbobjs();
765                List<Relationship> mRelationshipList = new ArrayList<>();
766                if(mDataflow.getRelationships() != null && mDataflow.getRelationships().length>0){
767                        mRelationshipList = new LinkedList<>(Arrays.asList(mDataflow.getRelationships()));
768                }
769
770                List<Error> mErrorList = new ArrayList<>();
771                if(mDataflow.getErrors() != null && mDataflow.getErrors().length>0){
772                        mErrorList = new LinkedList<>(Arrays.asList(mDataflow.getErrors()));
773                }
774
775                List<Process> mProcessList = new ArrayList<>();
776                if(mDataflow.getProcesses() != null && mDataflow.getProcesses().length>0){
777                        mProcessList = new LinkedList<>(Arrays.asList(mDataflow.getProcesses()));
778                }
779
780                for(int i=1; i<pairs.size(); i++){
781                        objNameMap.putAll(getDataflowDbObjNameMap(pairs.get(i).second));
782                        Dataflow dataflow = DataFlowAnalyzer.getSqlflowJSONModel(pairs.get(i).first, pairs.get(i).second, false);
783                        if(dataflow.getDbobjs().getServers() != null && dataflow.getDbobjs().getServers().size()>0){
784                                if(dbobjs.getServers() == null){
785                                        dbobjs.setServers(new ArrayList<>());
786                                }
787                                dbobjs.getServers().addAll(dataflow.getDbobjs().getServers());
788                        }
789
790                        if(dataflow.getDbobjs().getErrorMessages() != null && dataflow.getDbobjs().getErrorMessages().size()>0){
791                                if(dbobjs.getErrorMessages() == null){
792                                        dbobjs.setErrorMessages(new ArrayList<>());
793                                }
794                                dbobjs.getErrorMessages().addAll(dataflow.getDbobjs().getErrorMessages());
795                        }
796
797                        if(dataflow.getRelationships() != null && dataflow.getRelationships().length>0){
798                                List<Relationship> relationshipList = new LinkedList<>(Arrays.asList(dataflow.getRelationships()));
799                                mRelationshipList.addAll(relationshipList);
800                        }
801
802                        if(dataflow.getErrors() != null && dataflow.getErrors().length>0){
803                                List<Error> errorList = new LinkedList<>(Arrays.asList(dataflow.getErrors()));
804                                mErrorList.addAll(errorList);
805                        }
806
807                        if(dataflow.getProcesses() != null && dataflow.getProcesses().length>0){
808                                List<Process> processList = new LinkedList<>(Arrays.asList(dataflow.getProcesses()));
809                                mProcessList.addAll(processList);
810                        }
811
812                }
813                if(!SQLUtil.isEmpty(csvMetadata)){
814                        /**
815                         * excel内的血缘 只合并关系 就是只做关联,如果找不到obj 就算了
816                         */
817                        dataflow df = readDataflowFromCsvMetadata(csvMetadata);
818                        Map<String, table> objIDMap = getDataflowDbObjMap(df);
819                        if(df.getRelationships() != null && df.getRelationships().size()>0){
820                                for(relationship rel: df.getRelationships()){
821                                        rel.setId("m"+rel.getId());
822                                        table sTable = objIDMap.get(rel.getTarget().getParent_id());
823                                        table tTable = objNameMap.get(sTable.getFullName());
824                                        rel.getTarget().setParent_id(tTable.getId());
825                                        for(column col: tTable.getColumns()){
826                                                if(col.getName().equalsIgnoreCase(rel.getTarget().getColumn())){
827                                                        rel.getTarget().setId(col.getId());
828                                                        break;
829                                                }
830                                        }
831                                        for(sourceColumn column: rel.getSources()){
832                                                sTable = objIDMap.get(column.getParent_id());
833                                                tTable = objNameMap.get(sTable.getFullName());
834                                                column.setParent_id(tTable.getId());
835                                                for(column col: tTable.getColumns()){
836                                                        if(col.getName().equalsIgnoreCase(column.getColumn())){
837                                                                column.setId(col.getId());
838                                                                break;
839                                                        }
840                                                }
841                                        }
842                                        mRelationshipList.add(toRelationship(rel));
843                                }
844                        }
845                }
846
847                mDataflow.setDbobjs(dbobjs);
848                mDataflow.setRelationships(mRelationshipList.toArray(new Relationship[mRelationshipList.size()]));
849                mDataflow.setProcesses(mProcessList.toArray(new Process[mProcessList.size()]));
850                mDataflow.setErrors(mErrorList.toArray(new Error[mErrorList.size()]));
851                return mDataflow;
852        }
853
854        public static dataflow readDataflowFromCsvMetadata(String csvMetadata) {
855                if (!MetadataReader.isMetadata(csvMetadata)) {
856                        throw new IllegalArgumentException("Illegal csv metadata.");
857                }
858                return new SQLDepMetadataAnalyzer().analyzeMetadata(null, csvMetadata);
859        }
860
861        private static Relationship toRelationship(relationship relation){
862                Relationship relationModel;
863                if (relation.getType().equals("join")) {
864                        JoinRelationship joinRelationModel = new JoinRelationship();
865                        joinRelationModel.setCondition(relation.getCondition());
866                        joinRelationModel.setJoinType(relation.getJoinType());
867                        joinRelationModel.setClause(relation.getClause());
868                        relationModel = joinRelationModel;
869                } else {
870                        relationModel = new Relationship();
871                }
872                relationModel.setId(relation.getId());
873                relationModel.setProcessId(relation.getProcessId());
874                relationModel.setProcessType(relation.getProcessType());
875                relationModel.setType(relation.getType());
876                relationModel.setEffectType(relation.getEffectType());
877                relationModel.setPartition(relation.getPartition());
878                relationModel.setFunction(relation.getFunction());
879                relationModel.setProcedureId(relation.getProcedureId());
880                relationModel.setSqlHash(relation.getSqlHash());
881                relationModel.setCondition(relation.getCondition());
882                relationModel.setSqlComment(relation.getSqlComment());
883                relationModel.setTimestampMax(relation.getTimestampMax());
884                relationModel.setTimestampMin(relation.getTimestampMin());
885
886                if (relation.getTarget() != null && relation.getSources() != null && !relation.getSources().isEmpty()) {
887                        RelationshipElement targetModel = new RelationshipElement();
888                        targetColumn target = relation.getTarget();
889                        targetModel.setColumn(target.getColumn());
890                        targetModel.setParentName(target.getParent_name());
891                        targetModel.setTargetName(target.getTarget_name());
892                        targetModel.setId(target.getId());
893                        targetModel.setTargetId(target.getTarget_id());
894                        targetModel.setParentId(target.getParent_id());
895                        targetModel.setCoordinates(Coordinate.parse(target.getCoordinate()));
896                        targetModel.setFunction(target.getFunction());
897                        targetModel.setType(target.getType());
898                        relationModel.setTarget(targetModel);
899
900                        List<RelationshipElement> sourceModels = new ArrayList<>();
901                        for (sourceColumn source : relation.getSources()) {
902                                RelationshipElement sourceModel = new RelationshipElement();
903                                sourceModel.setColumn(source.getColumn());
904                                sourceModel.setParentName(source.getParent_name());
905                                sourceModel.setSourceName(source.getSource_name());
906                                sourceModel.setColumnType(source.getColumn_type());
907                                sourceModel.setId(source.getId());
908                                sourceModel.setParentId(source.getParent_id());
909                                sourceModel.setSourceId(source.getSource_id());
910                                sourceModel.setCoordinates(Coordinate.parse(source.getCoordinate()));
911                                sourceModel.setClauseType(source.getClauseType());
912                                sourceModel.setType(source.getType());
913                                sourceModels.add(sourceModel);
914                                if (source.getTransforms() != null && !source.getTransforms().isEmpty()) {
915                                        List<Transform> transforms = new ArrayList<gudusoft.gsqlparser.dlineage.dataflow.model.json.Transform>();
916                                        for (transform transform : source.getTransforms()) {
917                                                Transform item = new Transform();
918                                                item.setCode(transform.getCode());
919                                                item.setType(transform.getType());
920                                                item.setCoordinate(transform.getCoordinate(true));
921                                                transforms.add(item);
922                                        }
923                                        sourceModel.setTransforms(transforms.toArray(new Transform[0]));
924                                }
925                        }
926                        relationModel.setSources(sourceModels.toArray(new RelationshipElement[0]));
927                } else if (relation.getCaller() != null && relation.getCallees() != null
928                                && !relation.getCallees().isEmpty()) {
929                        RelationshipElement targetModel = new RelationshipElement();
930                        targetColumn target = relation.getCaller();
931                        targetModel.setName(target.getName());
932                        targetModel.setId(target.getId());
933                        targetModel.setCoordinates(Coordinate.parse(target.getCoordinate()));
934                        targetModel.setType(target.getType());
935                        relationModel.setCaller(targetModel);
936                        List<RelationshipElement> sourceModels = new ArrayList<gudusoft.gsqlparser.dlineage.dataflow.model.json.RelationshipElement>();
937                        for (sourceColumn source : relation.getCallees()) {
938                                RelationshipElement sourceModel = new RelationshipElement();
939                                sourceModel.setName(source.getName());
940                                sourceModel.setId(source.getId());
941                                sourceModel.setCoordinates(Coordinate.parse(source.getCoordinate()));
942                                sourceModel.setType(source.getType());
943                                sourceModels.add(sourceModel);
944                        }
945                        relationModel.setCallees(sourceModels.toArray(new RelationshipElement[0]));
946                }
947                return relationModel;
948        }
949}