001package gudusoft.gsqlparser.dlineage.graph; 002 003import gudusoft.gsqlparser.dlineage.dataflow.model.RelationshipType; 004import gudusoft.gsqlparser.dlineage.dataflow.model.xml.*; 005import gudusoft.gsqlparser.dlineage.graph.utils.StringEscapeUtils; 006import gudusoft.gsqlparser.dlineage.util.Pair3; 007import gudusoft.gsqlparser.util.SQLUtil; 008import java.io.IOException; 009import java.util.*; 010import java.util.Map.Entry; 011import java.util.stream.Collectors; 012 013public class DataFlowGraph { 014 015 public Pair3<String, Boolean, Set<String>> generateDataFlowGraph(dataflow dataflow, 016 boolean showLinkOnly, boolean hideColumn, List<RelationshipType> relationshipTypes, 017 Map<String, String> tooltipMap) throws IOException { 018 return convertMetaInfoToGraphXML(dataflow, 019 showLinkOnly, hideColumn, 020 relationshipTypes, 021 tooltipMap); 022 } 023 024 private List<Object> nodes = new ArrayList<>(); 025 026 private Set<relationship> linkRelations = new HashSet<relationship>(); 027 028 private List<Object> linkIds = new ArrayList<Object>(); 029 030 public List<Object> getNodes() { 031 return nodes; 032 } 033 034 public List<relationship> getRelationships() { 035 return new ArrayList<relationship>(linkRelations); 036 } 037 038 private Pair3<String, Boolean, Set<String>> convertMetaInfoToGraphXML(dataflow dataflow, 039 boolean showLinkOnly, boolean hideColumn, List<RelationshipType> relationshipTypes, 040 Map<String, String> tooltipMap) throws IOException { 041 nodes.clear(); 042 linkIds.clear(); 043 linkRelations.clear(); 044 045 boolean containGroup = false; 046 String columnContent = SQLUtil.getInputStreamContent(DataFlowGraph.class.getResourceAsStream("/gudusoft/gsqlparser/graph/column.template"), 047 false); 048 String tableContent = SQLUtil.getInputStreamContent(DataFlowGraph.class.getResourceAsStream("/gudusoft/gsqlparser/graph/table.template"), 049 false); 050 String linkContent = SQLUtil.getInputStreamContent(DataFlowGraph.class.getResourceAsStream("/gudusoft/gsqlparser/graph/link.template"), 051 false); 052 String graphContent = SQLUtil.getInputStreamContent(DataFlowGraph.class.getResourceAsStream("/gudusoft/gsqlparser/graph/graph.template"), 053 false); 054 055 StringBuffer tableFullBuffer = new StringBuffer(); 056 057 List<table> tables = new ArrayList<table>(); 058 if (dataflow.getTables() != null) 059 tables.addAll(dataflow.getTables()); 060 061 if(!relationshipTypes.contains(RelationshipType.er)){ 062 if (dataflow.getViews() != null) 063 tables.addAll(dataflow.getViews()); 064 if (dataflow.getStages() != null) 065 tables.addAll(dataflow.getStages()); 066 if (dataflow.getSequences() != null) 067 tables.addAll(dataflow.getSequences()); 068 if (dataflow.getDatasources() != null) 069 tables.addAll(dataflow.getDatasources()); 070 if (dataflow.getDatabases() != null) 071 tables.addAll(dataflow.getDatabases()); 072 if (dataflow.getSchemas() != null) 073 tables.addAll(dataflow.getSchemas()); 074 if (dataflow.getStreams() != null) 075 tables.addAll(dataflow.getStreams()); 076 if (dataflow.getPaths() != null) 077 tables.addAll(dataflow.getPaths()); 078 if (dataflow.getVariables() != null) 079 tables.addAll(dataflow.getVariables()); 080 if (dataflow.getResultsets() != null) 081 tables.addAll(dataflow.getResultsets()); 082 } 083 Map<String, table> tableMap = new HashMap<>(); 084 for (table table: tables) { 085 tableMap.put(table.getId(), table); 086 } 087 088 Set<String> relationshipTableIds = new HashSet<>(); 089 for (relationship relation : dataflow.getRelationships()) { 090 if( "call".equals(relation.getType())) { 091 relationshipTableIds.add(relation.getCaller().getId()); 092 if(relation.getCallees()!=null){ 093 for (sourceColumn sourceColumn: relation.getCallees()){ 094 relationshipTableIds.add(sourceColumn.getId()); 095 } 096 } 097 continue; 098 } 099 if (relation.getTarget().getParent_id() != null) { 100 relationshipTableIds.add(relation.getTarget().getParent_id()); 101 } else { 102 relationshipTableIds.add(relation.getTarget().getId()); 103 } 104 105 if (relation.getSources() != null) { 106 for (sourceColumn sourceColumn : relation.getSources()) { 107 if (sourceColumn.getParent_id() != null) { 108 relationshipTableIds.add(sourceColumn.getParent_id()); 109 } else { 110 relationshipTableIds.add(sourceColumn.getId()); 111 } 112 } 113 } 114 } 115 Iterator<String> tableIter = tableMap.keySet().iterator(); 116 if(relationshipTypes.contains(RelationshipType.er)){ 117// while(tableIter.hasNext()){ 118// String tableId = tableIter.next(); 119// if(!relationshipTableIds.contains(tableId)){ 120// table tb = tableMap.get(tableId); 121// if((!SQLUtil.isEmpty(tableName) && !tableName.equalsIgnoreCase(tb.getName())) || 122// (!SQLUtil.isEmpty(databaseName) && !databaseName.equalsIgnoreCase(tb.getDatabase())) || 123// (!SQLUtil.isEmpty(schemaName) && !schemaName.equalsIgnoreCase(tb.getSchema())) || 124// (!SQLUtil.isEmpty(serverName) && !serverName.equalsIgnoreCase(tb.getServer()))){ 125// tableIter.remove(); 126// } 127// } 128// } 129 } 130 else{ 131 while(tableIter.hasNext()){ 132 if(!relationshipTableIds.contains(tableIter.next())){ 133 tableIter.remove(); 134 } 135 } 136 } 137 Map<String, Map<String, List<column>>> tableColumns = new HashMap<String, Map<String, List<column>>>(); 138 Set<String> columnSet = new HashSet<String>(); 139 Set<String> linkColumnSet = new HashSet<String>(); 140 141 boolean showCallRelation = relationshipTypes.contains(RelationshipType.call); 142 143 Map<String, procedure> procedureMap = new HashMap<>(); 144 if (relationshipTypes.contains(RelationshipType.call)) { 145 List<procedure> procedures = new ArrayList<>(dataflow.getProcedures()); 146 if (dataflow.getPackages() != null) { 147 for (oraclePackage pkg : dataflow.getPackages()) { 148 procedures.addAll(pkg.getProcedures()); 149 } 150 } 151 procedureMap = procedures.stream().collect(Collectors.toMap( 152 t -> t.getId(), 153 t -> t, 154 (existingValue, newValue) -> newValue 155 )); 156 157 158 Iterator<String> procedureIter = procedureMap.keySet().iterator(); 159 160 while (procedureIter.hasNext()) { 161 if (!relationshipTableIds.contains(procedureIter.next())) { 162 procedureIter.remove(); 163 } 164 } 165 166 procedureIter = procedureMap.keySet().iterator(); 167 168 while (procedureIter.hasNext()) { 169 procedure procedure = procedureMap.get(procedureIter.next()); 170 String tableId = "table-" + procedure.getId(); 171 nodes.add(procedure); 172 String content = new String(tableContent); 173 content = content.replace("{tableId}", "table-" + procedure.getId()); 174 175 String tableLabel = procedure.getName(); 176 if (tableLabel.length() > 25) { 177 String shortLabel = getShortLabel(tableLabel, 25); 178 if (tooltipMap != null) { 179 tooltipMap.put(shortLabel.replace("\r\n", "\n").replace("\n", " "), tableLabel); 180 } 181 tableLabel = shortLabel; 182 183 } 184 185 content = content.replace("{tableLabel}", StringEscapeUtils.escapeXml(tableLabel)); 186 187 StringBuffer columnBuffer = new StringBuffer(); 188 String columnId = "column-" + procedure.getId(); 189 columnSet.add(columnId); 190 String content1 = new String(columnContent); 191 content1 = content1.replace("{columnId}", columnId); 192 content1 = content1.replace("{columnPosY}", "0"); 193 content1 = content1.replace("{columnLabel}", getProcedureType(procedure)); 194// content1 = content1.replace("height=\"16\"", "height=\"0\""); 195 columnBuffer.append(content1).append("\n"); 196 197 content = content.replace("{columns}", columnBuffer.toString()); 198 { 199 content = content.replace("{contentColor}", "#9999ff"); 200 content = content.replace("{labelColor}", "#DBDADA"); 201 } 202 tableFullBuffer.append(content).append("\n"); 203 } 204 205 206 Iterator<String> dbObjIter = tableMap.keySet().iterator(); 207 while (dbObjIter.hasNext()) { 208 table table = tableMap.get(dbObjIter.next()); 209 String tableId = "table-" + table.getId(); 210 nodes.add(table); 211 String content = new String(tableContent); 212 content = content.replace("{tableId}", "table-" + table.getId()); 213 214 String tableLabel = table.getName(); 215 if (tableLabel.length() > 25) { 216 String shortLabel = getShortLabel(tableLabel, 25); 217 if (tooltipMap != null) { 218 tooltipMap.put(shortLabel.replace("\r\n", "\n").replace("\n", " "), tableLabel); 219 } 220 tableLabel = shortLabel; 221 222 } 223 224 content = content.replace("{tableLabel}", StringEscapeUtils.escapeXml(tableLabel)); 225 226 StringBuffer columnBuffer = new StringBuffer(); 227 String columnId = "column-" + table.getId(); 228 columnSet.add(columnId); 229 String content1 = new String(columnContent); 230 content1 = content1.replace("{columnId}", columnId); 231 content1 = content1.replace("{columnPosY}", "0"); 232 content1 = content1.replace("{columnLabel}", table.getType()); 233// content1 = content1.replace("height=\"16\"", "height=\"0\""); 234 columnBuffer.append(content1).append("\n"); 235 236 content = content.replace("{columns}", columnBuffer.toString()); 237 { 238 content = content.replace("{contentColor}", "#9999ff"); 239 content = content.replace("{labelColor}", "#DBDADA"); 240 } 241 tableFullBuffer.append(content).append("\n"); 242 } 243 } 244 245 Map<String, process> processMap = new HashMap<>(); 246 for (process process : dataflow.getProcesses()) { 247 processMap.put(process.getId(), process); 248 } 249 if(dataflow.getProcesses()!=null){ 250 Iterator<String> processIter = processMap.keySet().iterator(); 251 while (processIter.hasNext()) { 252 if (!relationshipTableIds.contains(processIter.next())) { 253 processIter.remove(); 254 } 255 } 256 257 processIter = processMap.keySet().iterator(); 258 while (processIter.hasNext()) { 259 process process = processMap.get(processIter.next()); 260 String tableId = "table-"+process.getId(); 261 columnSet.add(tableId); 262 nodes.add(process); 263 String content = new String(tableContent); 264 content = content.replace("{tableId}", "table-" + process.getId()); 265 266 String tableLabel = process.getName(); 267 if (tableLabel.length() > 25) { 268 String shortLabel = getShortLabel(tableLabel, 25); 269 if (tooltipMap != null) { 270 tooltipMap.put(shortLabel.replace("\r\n", "\n").replace("\n", " "), tableLabel); 271 } 272 tableLabel = shortLabel; 273 274 } 275 276 content = content.replace("{tableLabel}", StringEscapeUtils.escapeXml(tableLabel)); 277 278 StringBuffer columnBuffer = new StringBuffer(); 279 String columnId = "column-" + process.getId(); 280 String content1 = new String(columnContent); 281 content1 = content1.replace("{columnId}", columnId); 282 content1 = content1.replace("{columnPosY}", "0"); 283 content1 = content1.replace("{columnLabel}", "hide-table-column"); 284 content1 = content1.replace("height=\"16\"", "height=\"0\""); 285 columnBuffer.append(content1).append("\n"); 286 287 288 content = content.replace("{columns}", columnBuffer.toString()); 289 { 290 content = content.replace("{contentColor}", "#9999ff"); 291 content = content.replace("{labelColor}", "#DBDADA"); 292 } 293 tableFullBuffer.append(content).append("\n"); 294 } 295 } 296 tableIter = tableMap.keySet().iterator(); 297 while (tableIter.hasNext()) { 298 table currentTable = tableMap.get(tableIter.next()); 299// if (currentTable.getColumns() == null 300// || currentTable.getColumns().isEmpty()) 301// continue; 302 if(showCallRelation){ 303 continue; 304 } 305 nodes.add(currentTable); 306 String tableId = "table-"+currentTable.getId(); 307 columnSet.add(tableId); 308 309 StringBuffer columnBuffer = new StringBuffer(); 310 311 if (currentTable.isTable() || currentTable.isView() || currentTable.isCursor() || currentTable.isDatabaseType() || currentTable.isSchemaType() || currentTable.isStage() || currentTable.isSequence() || currentTable.isDataSource() || currentTable.isStream() || currentTable.isFile()|| currentTable.isVariable()) { 312 Map<String, List<column>> columnMap = new LinkedHashMap<String, List<column>>(); 313 tableColumns.put(currentTable.getId(), columnMap); 314 for (int k = 0; k < currentTable.getColumns().size(); k++) { 315 column column = currentTable.getColumns().get(k); 316 String columnLabel = column.getName(); 317 //add by grq 2023.01.10 issue=I69NOU 318 if(relationshipTypes.contains(RelationshipType.er)){ 319 if(columnLabel.equalsIgnoreCase("*") || columnLabel.equalsIgnoreCase("relationRows")){ 320 continue; 321 } 322 } 323 //end by grq 324 List<column> columns; 325 if (!columnMap.containsKey(columnLabel)) { 326 columns = new ArrayList<column>(); 327 columnMap.put(columnLabel, columns); 328 } else { 329 columns = columnMap.get(columnLabel); 330 } 331 columns.add(column); 332 } 333 334 Iterator<Entry<String, List<column>>> iterator = columnMap 335 .entrySet().iterator(); 336 for (int k = 0; k < columnMap.size(); k++) { 337 Entry<String, List<column>> entry = iterator.next(); 338 nodes.add(entry.getValue()); 339 String content = columnContent; 340 341 String columnId = "column-" 342 + currentTable.getId() 343 + "-index-" 344 + k; 345 if(columnSet.contains(columnId)){ 346 continue; 347 } 348 columnSet.add(columnId); 349 350 content = content.replace("{columnId}", columnId); 351 content = content.replace("{columnPosY}", 352 String.valueOf(35 * k)); 353 String columnLabel = entry.getKey(); 354 if (columnLabel.length() > 25) { 355 String shortLabel = getShortLabel(columnLabel, 25); 356 if (tooltipMap != null) { 357 tooltipMap.put(shortLabel.replace("\r\n", "\n") 358 .replace("\n", " "), columnLabel); 359 } 360 columnLabel = shortLabel; 361 362 } 363 content = content.replace("{columnLabel}", 364 StringEscapeUtils.escapeXml(columnLabel)); 365 columnBuffer.append(content).append("\n"); 366 } 367 } else { 368 for (int k = 0; k < currentTable.getColumns().size(); k++) { 369 column column = currentTable.getColumns().get(k); 370 nodes.add(column); 371 String content = new String(columnContent); 372 373 String columnParentId = currentTable.getId(); 374 String columnId = column.getId(); 375 columnId = convertColumnId(tableColumns, 376 columnId, 377 columnParentId); 378 379 columnId = "column-" + columnId; 380 if(columnSet.contains(columnId)){ 381 continue; 382 } 383 columnSet.add(columnId); 384 385 content = content.replace("{columnId}", columnId); 386 content = content.replace("{columnPosY}", 387 String.valueOf(35 * k)); 388 String columnLabel = column.getName(); 389 if (columnLabel.length() > 25) { 390 String shortLabel = getShortLabel(columnLabel, 25); 391 if (tooltipMap != null) { 392 tooltipMap.put(shortLabel.replace("\r\n", "\n") 393 .replace("\n", " "), columnLabel); 394 } 395 columnLabel = shortLabel; 396 397 } 398 content = content.replace("{columnLabel}", 399 StringEscapeUtils.escapeXml(columnLabel)); 400 columnBuffer.append(content).append("\n"); 401 } 402 } 403 String content = new String(tableContent); 404 content = content.replace("{tableId}", 405 "table-" + currentTable.getId()); 406 407 String tableLabel = currentTable.getName(); 408 if (tableLabel.length() > 25) { 409 String shortLabel = getShortLabel(tableLabel, 25); 410 if (tooltipMap != null) { 411 tooltipMap.put(shortLabel.replace("\r\n", "\n") 412 .replace("\n", " "), 413 tableLabel); 414 } 415 tableLabel = shortLabel; 416 417 } 418 419 if(columnBuffer.length() == 0){ 420 String columnId = "column-" + currentTable.getId(); 421 String content1 = new String(columnContent); 422 content1 = content1.replace("{columnId}", columnId); 423 content1 = content1.replace("{columnPosY}", "0"); 424 content1 = content1.replace("{columnLabel}", "hide-table-column"); 425 content1 = content1.replace("height=\"16\"", "height=\"0\""); 426 columnBuffer.append(content1).append("\n"); 427 } 428 429 content = content.replace("{tableLabel}", 430 StringEscapeUtils.escapeXml(tableLabel)); 431 432 String columnString = columnBuffer.toString(); 433 if (hideColumn) { 434 columnString = columnString.replace("height=\"16\"", "height=\"0\""); 435 } 436 content = content.replace("{columns}", columnString); 437 if (currentTable.isView()) { 438 content = content.replace("{contentColor}", "#ff99cc"); 439 content = content.replace("{labelColor}", "#ffccff"); 440 } else if (currentTable.isStage()) { 441 content = content.replace("{contentColor}", "#87CEFA"); 442 content = content.replace("{labelColor}", "#87CEFA"); 443 } else if (currentTable.isSequence()) { 444 content = content.replace("{contentColor}", "#87CEFA"); 445 content = content.replace("{labelColor}", "#87CEFA"); 446 } else if (currentTable.isDataSource()) { 447 content = content.replace("{contentColor}", "#87CEFA"); 448 content = content.replace("{labelColor}", "#87CEFA"); 449 } else if (currentTable.isDatabaseType()) { 450 content = content.replace("{contentColor}", "#87CEFA"); 451 content = content.replace("{labelColor}", "#87CEFA"); 452 } else if (currentTable.isSchemaType()) { 453 content = content.replace("{contentColor}", "#87CEFA"); 454 content = content.replace("{labelColor}", "#87CEFA"); 455 } else if (currentTable.isStream()) { 456 content = content.replace("{contentColor}", "#87CEFA"); 457 content = content.replace("{labelColor}", "#87CEFA"); 458 } else if (currentTable.isFile()) { 459 content = content.replace("{contentColor}", "#87CEFA"); 460 content = content.replace("{labelColor}", "#87CEFA"); 461 } else if (currentTable.isCursor()) { 462 content = content.replace("{contentColor}", "#87CEFA"); 463 content = content.replace("{labelColor}", "#87CEFA"); 464 } else if (currentTable.isVariable()) { 465 content = content.replace("{contentColor}", "#87CEFA"); 466 content = content.replace("{labelColor}", "#87CEFA"); 467 } else if (currentTable.isResultSet()) { 468 content = content.replace("{contentColor}", "#009944"); 469 content = content.replace("{labelColor}", "#aaffcc"); 470 } else { 471 content = content.replace("{contentColor}", "#9999ff"); 472 content = content.replace("{labelColor}", "#DBDADA"); 473 } 474 tableFullBuffer.append(content).append("\n"); 475 476 containGroup = true; 477 } 478 479 StringBuffer linkBuffer = new StringBuffer(); 480 List<relationship> relationships = dataflow.getRelationships(); 481 if (relationshipTypes.contains(RelationshipType.join)) { 482 relationships = relationships.stream().filter(t -> t.getType().equals("join") || t.getType().equals("fdd")) 483 .collect(Collectors.toList()); 484 } 485 else if (relationshipTypes.contains(RelationshipType.call)) { 486 relationships = relationships.stream().filter(t -> t.getType().equals("call")) 487 .collect(Collectors.toList()); 488 } 489 490 if (relationships != null) { 491 List<String> links = new ArrayList<String>(); 492 for (int i = 0; i < relationships.size(); i++) { 493 relationship relationship = relationships.get(i); 494 495 if (relationship.getTarget() == null || relationship.getSources() == null || relationship.getSources().isEmpty()) 496 continue; 497 if (!relationshipTypes.contains(RelationshipType.valueOf(relationship.getType()))) { 498 if (relationshipTypes.contains(RelationshipType.join) 499 && relationship.getType() 500 .equals(RelationshipType.fdd.name())) { 501 if (!traceJoin(relationship, relationships, tableColumns, 0)) { 502 continue; 503 } 504 } else { 505 continue; 506 } 507 } 508 509 if (RelationshipType.call.equals(RelationshipType.valueOf(relationship.getType()))) { 510 targetColumn target = relationship.getCaller(); 511 String targetColumnId = target.getId(); 512 if (relationship.getCallees() != null) { 513 List<sourceColumn> linkTables = relationship.getCallees(); 514 for (int k = 0; k < linkTables.size(); k++) { 515 sourceColumn source = linkTables.get(k); 516 String sourceColumnId = source.getId(); 517 String content = linkContent; 518 String sourceId = "column-" + sourceColumnId; 519// if (sourceColumnId != null && sourceColumnId.indexOf("-") == -1) { 520// sourceId = "table-" + sourceColumnId; 521// } 522 String targetId = "column-" + targetColumnId; 523// if (targetColumnId != null && targetColumnId.indexOf("-") == -1) { 524// targetId = "table-" + targetColumnId; 525// } 526 527 //call relation的箭头方向和fdd是相反的 528 content = content.replace("{sourceId}", targetId); 529 content = content.replace("{targetId}", sourceId); 530 531 if (columnSet.contains(sourceId) && columnSet.contains(targetId)) { 532 String temp = content; 533 if (!links.contains(temp)) { 534 links.add(temp); 535 536 linkColumnSet.add(sourceId); 537 linkColumnSet.add(targetId); 538 539 String linkId = "link_" + relationship.getId() + "_" + sourceColumnId + "_" 540 + targetColumnId; 541 content = content.replace("{linkId}", linkId); 542 linkIds.add(linkId); 543 linkRelations.add(relationship); 544 linkBuffer.append(content).append("\n"); 545 } 546 } else { 547 System.err.println("Can't get " + "link_" + relationship.getId() + "_" + sourceColumnId + "_" 548 + targetColumnId); 549 } 550 } 551 } 552 } else { 553 targetColumn target = relationship.getTarget(); 554 String targetColumnId = target.getId(); 555 String targetParentId = target.getParent_id(); 556 557 targetColumnId = convertColumnId(tableColumns, 558 targetColumnId, 559 targetParentId); 560 if (targetParentId == null) { 561 targetColumnId = target.getTarget_id(); 562 } 563 564 if (relationship.getSources() != null) { 565 List<sourceColumn> linkTables = relationship.getSources(); 566 for (int k = 0; k < linkTables.size(); k++) { 567 sourceColumn source = linkTables.get(k); 568 569 String sourceColumnId = source.getId(); 570 String sourceParentId = source.getParent_id(); 571 sourceColumnId = convertColumnId(tableColumns, 572 sourceColumnId, 573 sourceParentId); 574 if (sourceParentId == null) { 575 sourceColumnId = source.getSource_id(); 576 } 577 578 String content = linkContent; 579 580 if (relationship.getType() 581 .equals(RelationshipType.join.name())) { 582 content = content.replace("type=\"line\"", 583 "type=\"dashed\""); 584 } 585 586 String sourceId = "column-" + sourceColumnId; 587 if (sourceColumnId != null && sourceColumnId.indexOf("-") == -1) { 588 sourceId = "table-" + sourceColumnId; 589 } 590 String targetId = "column-" + targetColumnId; 591 if (targetColumnId != null && targetColumnId.indexOf("-") == -1) { 592 targetId = "table-" + targetColumnId; 593 } 594 content = content.replace("{sourceId}", sourceId); 595 content = content.replace("{targetId}", targetId); 596 597 if (columnSet.contains(sourceId) 598 && columnSet.contains(targetId)) { 599 String temp = content; 600 if (!links.contains(temp)) { 601 links.add(temp); 602 603 linkColumnSet.add(sourceId); 604 linkColumnSet.add(targetId); 605 606 String linkId = "link_" 607 + relationship.getId() 608 + "_" 609 + sourceColumnId 610 + "_" 611 + targetColumnId; 612 content = content.replace("{linkId}", linkId); 613 linkIds.add(linkId); 614 linkRelations.add(relationship); 615 linkBuffer.append(content).append("\n"); 616 } else { 617 linkRelations.add(relationship); 618 } 619 } else { 620 System.err.println("Can't get " 621 + "link_" 622 + relationship.getId() 623 + "_" 624 + sourceColumnId 625 + "_" 626 + targetColumnId); 627 } 628 } 629 } 630 } 631 } 632 } 633 634 if (showLinkOnly) { 635 nodes.clear(); 636 StringBuffer tableLinkBuffer = new StringBuffer(); 637 int showColumnCount = 0; 638 639 if (relationshipTypes.contains(RelationshipType.call)) { 640 Iterator<String> procedureIter = procedureMap.keySet().iterator(); 641 while (procedureIter.hasNext()) { 642 procedure procedure = procedureMap.get(procedureIter.next()); 643 String tableId = "table-" + procedure.getId(); 644 columnSet.add(tableId); 645 nodes.add(procedure); 646 String content = new String(tableContent); 647 content = content.replace("{tableId}", "table-" + procedure.getId()); 648 649 String tableLabel = procedure.getName(); 650 if (tableLabel.length() > 25) { 651 String shortLabel = getShortLabel(tableLabel, 25); 652 if (tooltipMap != null) { 653 tooltipMap.put(shortLabel.replace("\r\n", "\n").replace("\n", " "), tableLabel); 654 } 655 tableLabel = shortLabel; 656 657 } 658 659 content = content.replace("{tableLabel}", StringEscapeUtils.escapeXml(tableLabel)); 660 661 StringBuffer columnBuffer = new StringBuffer(); 662 String columnId = "column-" + procedure.getId(); 663 String content1 = new String(columnContent); 664 content1 = content1.replace("{columnId}", columnId); 665 content1 = content1.replace("{columnPosY}", "0"); 666 content1 = content1.replace("{columnLabel}", getProcedureType(procedure)); 667// content1 = content1.replace("height=\"16\"", "height=\"0\""); 668 columnBuffer.append(content1).append("\n"); 669 670 content = content.replace("{columns}", columnBuffer.toString()); 671 { 672 content = content.replace("{contentColor}", "#9999ff"); 673 content = content.replace("{labelColor}", "#DBDADA"); 674 } 675 tableFullBuffer.append(content).append("\n"); 676 tableLinkBuffer.append(content).append("\n"); 677 } 678 679 Iterator<String> dbObjIter = tableMap.keySet().iterator(); 680 while (dbObjIter.hasNext()) { 681 table table = tableMap.get(dbObjIter.next()); 682 String tableId = "table-" + table.getId(); 683 nodes.add(table); 684 String content = new String(tableContent); 685 content = content.replace("{tableId}", "table-" + table.getId()); 686 687 String tableLabel = table.getName(); 688 if (tableLabel.length() > 25) { 689 String shortLabel = getShortLabel(tableLabel, 25); 690 if (tooltipMap != null) { 691 tooltipMap.put(shortLabel.replace("\r\n", "\n").replace("\n", " "), tableLabel); 692 } 693 tableLabel = shortLabel; 694 695 } 696 697 content = content.replace("{tableLabel}", StringEscapeUtils.escapeXml(tableLabel)); 698 699 StringBuffer columnBuffer = new StringBuffer(); 700 String columnId = "column-" + table.getId(); 701 columnSet.add(columnId); 702 String content1 = new String(columnContent); 703 content1 = content1.replace("{columnId}", columnId); 704 content1 = content1.replace("{columnPosY}", "0"); 705 content1 = content1.replace("{columnLabel}", table.getType()); 706 columnBuffer.append(content1).append("\n"); 707 708 content = content.replace("{columns}", columnBuffer.toString()); 709 { 710 content = content.replace("{contentColor}", "#9999ff"); 711 content = content.replace("{labelColor}", "#DBDADA"); 712 } 713 tableFullBuffer.append(content).append("\n"); 714 tableLinkBuffer.append(content).append("\n"); 715 } 716 } 717 718 if(dataflow.getProcesses()!=null){ 719 Iterator<String> processIter = processMap.keySet().iterator(); 720 while (processIter.hasNext()) { 721 process process = processMap.get(processIter.next()); 722 if(!linkColumnSet.contains("table-" + process.getId())) { 723 continue; 724 } 725 nodes.add(process); 726 String tableId = "table-"+process.getId(); 727 columnSet.add(tableId); 728 String content = new String(tableContent); 729 content = content.replace("{tableId}", "table-" + process.getId()); 730 731 String tableLabel = process.getName(); 732 if (tableLabel.length() > 25) { 733 String shortLabel = getShortLabel(tableLabel, 25); 734 if (tooltipMap != null) { 735 tooltipMap.put(shortLabel.replace("\r\n", "\n").replace("\n", " "), tableLabel); 736 } 737 tableLabel = shortLabel; 738 739 } 740 741 content = content.replace("{tableLabel}", StringEscapeUtils.escapeXml(tableLabel)); 742 743 StringBuffer columnBuffer = new StringBuffer(); 744 String columnId = "column-" + process.getId(); 745 String content1 = new String(columnContent); 746 content1 = content1.replace("{columnId}", columnId); 747 content1 = content1.replace("{columnPosY}", "0"); 748 content1 = content1.replace("{columnLabel}", "hide-table-column"); 749 content1 = content1.replace("height=\"16\"", "height=\"0\""); 750 columnBuffer.append(content1).append("\n"); 751 752 753 content = content.replace("{columns}", columnBuffer.toString()); 754 { 755 content = content.replace("{contentColor}", "#9999ff"); 756 content = content.replace("{labelColor}", "#DBDADA"); 757 } 758 tableFullBuffer.append(content).append("\n"); 759 tableLinkBuffer.append(content).append("\n"); 760 } 761 } 762 763 tableIter = tableMap.keySet().iterator(); 764 while (tableIter.hasNext()) { 765 table currentTable = tableMap.get(tableIter.next()); 766 if(showCallRelation){ 767 continue; 768 } 769 if (currentTable.getColumns() == null || currentTable.getColumns().isEmpty()) { 770 if(!linkColumnSet.contains("table-" + currentTable.getId())) { 771 continue; 772 } 773 } 774 775 //包含在TableLevelLineage中则不删除,不包含如无link则删除 776 boolean removeTable = !linkColumnSet.contains("table-" + currentTable.getId()); 777 778 nodes.add(currentTable); 779 StringBuffer columnBuffer = new StringBuffer(); 780 if (currentTable.isTable() || currentTable.isView() || currentTable.isCursor() || currentTable.isDatabaseType() || currentTable.isSchemaType() || currentTable.isStage() || currentTable.isSequence() || currentTable.isDataSource() || currentTable.isStream() || currentTable.isFile()|| currentTable.isVariable()) { 781 Map<String, List<column>> columnMap = new LinkedHashMap<String, List<column>>(); 782 for (int k = 0; k < currentTable.getColumns().size(); k++) { 783 column column = currentTable.getColumns().get(k); 784 String columnLabel = column.getName(); 785 List<column> columns; 786 if (!columnMap.containsKey(columnLabel)) { 787 columns = new ArrayList<column>(); 788 columnMap.put(columnLabel, columns); 789 } else { 790 columns = columnMap.get(columnLabel); 791 } 792 columns.add(column); 793 } 794 795 Iterator<Entry<String, List<column>>> iterator = columnMap.entrySet() 796 .iterator(); 797 for (int k = 0; k < columnMap.size(); k++) { 798 Entry<String, List<column>> entry = iterator.next(); 799 String columnId = "column-" 800 + currentTable.getId() 801 + "-index-" 802 + k; 803 if ((currentTable.isTable() || currentTable.isView() || currentTable.isCursor() || currentTable.isDatabaseType() || currentTable.isSchemaType() || currentTable.isStage() || currentTable.isSequence() || currentTable.isDataSource() || currentTable.isStream() || currentTable.isFile()|| currentTable.isVariable()) 804 && !linkColumnSet.contains(columnId)) 805 continue; 806 807 removeTable = false; 808 nodes.add(entry.getValue()); 809 810 String content = new String(columnContent); 811 content = content.replace("{columnId}", columnId); 812 content = content.replace("{columnPosY}", 813 String.valueOf(35 * showColumnCount)); 814 String columnLabel = entry.getKey(); 815 if (columnLabel.length() > 25) { 816 String shortLabel = getShortLabel(columnLabel, 25); 817 if (tooltipMap != null) { 818 tooltipMap.put(shortLabel.replace("\r\n", 819 "\n").replace("\n", " "), 820 columnLabel); 821 } 822 columnLabel = shortLabel; 823 824 } 825 content = content.replace("{columnLabel}", 826 StringEscapeUtils.escapeXml(columnLabel)); 827 columnBuffer.append(content).append("\n"); 828 showColumnCount++; 829 } 830 } else { 831 for (int k = 0; k < currentTable.getColumns().size(); k++) { 832 column column = currentTable.getColumns().get(k); 833 834 String columnParentId = currentTable.getId(); 835 String columnId = column.getId(); 836 columnId = convertColumnId(tableColumns, 837 columnId, 838 columnParentId); 839 840 columnId = "column-" + columnId; 841 if (!(currentTable.isTable() || currentTable.isView() || currentTable.isCursor() || currentTable.isDatabaseType() || currentTable.isSchemaType() || currentTable.isStage() || currentTable.isSequence() || currentTable.isDataSource() || currentTable.isStream() || currentTable.isFile()|| currentTable.isVariable()) 842 && !linkColumnSet.contains(columnId)) 843 continue; 844 845 removeTable = false; 846 nodes.add(column); 847 848 String content = new String(columnContent); 849 content = content.replace("{columnId}", columnId); 850 content = content.replace("{columnPosY}", 851 String.valueOf(35 * showColumnCount)); 852 String columnLabel = column.getName(); 853 if (columnLabel.length() > 25) { 854 String shortLabel = getShortLabel(columnLabel, 25); 855 if (tooltipMap != null) { 856 tooltipMap.put(shortLabel.replace("\r\n", 857 "\n").replace("\n", " "), 858 columnLabel); 859 } 860 columnLabel = shortLabel; 861 862 } 863 content = content.replace("{columnLabel}", 864 StringEscapeUtils.escapeXml(columnLabel)); 865 columnBuffer.append(content).append("\n"); 866 showColumnCount++; 867 } 868 } 869 870 if (removeTable) { 871 nodes.remove(currentTable); 872 continue; 873 } else { 874 if (columnBuffer.toString().trim().length() == 0) { 875 String columnId = "column-" + currentTable.getId(); 876 String content1 = new String(columnContent); 877 content1 = content1.replace("{columnId}", columnId); 878 content1 = content1.replace("{columnPosY}", "0"); 879 content1 = content1.replace("{columnLabel}", "hide-table-column"); 880 content1 = content1.replace("height=\"16\"", "height=\"0\""); 881 columnBuffer.append(content1).append("\n"); 882 } 883 } 884 885 String content = new String(tableContent); 886 content = content.replace("{tableId}", 887 "table-" + currentTable.getId()); 888 889 String tableLabel = currentTable.getName(); 890 if (tableLabel.length() > 25) { 891 String shortLabel = getShortLabel(tableLabel, 25); 892 if (tooltipMap != null) { 893 tooltipMap.put(shortLabel.replace("\r\n", "\n") 894 .replace("\n", " "), tableLabel); 895 } 896 tableLabel = shortLabel; 897 } 898 899 content = content.replace("{tableLabel}", 900 StringEscapeUtils.escapeXml(tableLabel)); 901 String columnString = columnBuffer.toString(); 902 if (hideColumn) { 903 columnString = columnString.replace("height=\"16\"", "height=\"0\""); 904 } 905 content = content.replace("{columns}", columnString); 906 907 if (currentTable.isView()) { 908 content = content.replace("{contentColor}", "#ff99cc"); 909 content = content.replace("{labelColor}", "#ffccff"); 910 } else if (currentTable.isStage()) { 911 content = content.replace("{contentColor}", "#87CEFA"); 912 content = content.replace("{labelColor}", "#87CEFA"); 913 } else if (currentTable.isSequence()) { 914 content = content.replace("{contentColor}", "#87CEFA"); 915 content = content.replace("{labelColor}", "#87CEFA"); 916 } else if (currentTable.isDataSource()) { 917 content = content.replace("{contentColor}", "#87CEFA"); 918 content = content.replace("{labelColor}", "#87CEFA"); 919 } else if (currentTable.isDatabaseType()) { 920 content = content.replace("{contentColor}", "#87CEFA"); 921 content = content.replace("{labelColor}", "#87CEFA"); 922 } else if (currentTable.isSchemaType()) { 923 content = content.replace("{contentColor}", "#87CEFA"); 924 content = content.replace("{labelColor}", "#87CEFA"); 925 } else if (currentTable.isStream()) { 926 content = content.replace("{contentColor}", "#87CEFA"); 927 content = content.replace("{labelColor}", "#87CEFA"); 928 } else if (currentTable.isFile()) { 929 content = content.replace("{contentColor}", "#87CEFA"); 930 content = content.replace("{labelColor}", "#87CEFA"); 931 } else if (currentTable.isVariable()) { 932 content = content.replace("{contentColor}", "#87CEFA"); 933 content = content.replace("{labelColor}", "#87CEFA"); 934 } else if (currentTable.isCursor()) { 935 content = content.replace("{contentColor}", "#87CEFA"); 936 content = content.replace("{labelColor}", "#87CEFA"); 937 } else if (currentTable.isResultSet()) { 938 content = content.replace("{contentColor}", "#009944"); 939 content = content.replace("{labelColor}", "#aaffcc"); 940 } else { 941 content = content.replace("{contentColor}", "#9999ff"); 942 content = content.replace("{labelColor}", "#DBDADA"); 943 } 944 tableLinkBuffer.append(content).append("\n"); 945 containGroup = true; 946 } 947 948 graphContent = graphContent.replace("{nodes}", 949 tableLinkBuffer.toString()); 950 } else { 951 graphContent = graphContent.replace("{nodes}", 952 tableFullBuffer.toString()); 953 } 954 955 nodes.addAll(linkIds); 956 graphContent = graphContent.replace("{links}", linkBuffer.toString()); 957 Set<String> dbObjIds = new LinkedHashSet<>(); 958 dbObjIds.addAll(tableMap.keySet()); 959 dbObjIds.addAll(processMap.keySet()); 960 dbObjIds.addAll(procedureMap.keySet()); 961 return new Pair3<String, Boolean, Set<String>>(graphContent, containGroup, dbObjIds); 962 } 963 964 private CharSequence getProcedureType(procedure procedure) { 965 String type = procedure.getType().toLowerCase(); 966 if (type.indexOf("procedure") != -1) { 967 return "procedure"; 968 } else if (type.indexOf("function") != -1) { 969 return "function"; 970 } else if (type.indexOf("trigger") != -1) { 971 return "trigger"; 972 } else if (type.indexOf("package") != -1) { 973 return "package"; 974 } else if (type.indexOf("macro") != -1) { 975 return "macro"; 976 } else { 977 return type; 978 } 979 } 980 981 private boolean traceJoin(relationship relationship, List<relationship> relationships, 982 Map<String, Map<String, List<column>>> tableColumns, int level) { 983 targetColumn target = relationship.getTarget(); 984 String targetColumnId = target.getId(); 985 String targetParentId = target.getParent_id(); 986 987 targetColumnId = convertColumnId(tableColumns, 988 targetColumnId, 989 targetParentId); 990 991 for (int i = 0; i < relationships.size(); i++) { 992 relationship tempRelation = relationships.get(i); 993 994 if (relationship == tempRelation) 995 continue; 996 997 List<sourceColumn> sources = tempRelation.getSources(); 998 if (sources != null) { 999 if (relationships.size() * sources.size() > 5000) { 1000 System.out.println("The relationship is too huge, skip the join trace."); 1001 continue; 1002 } 1003 } 1004 1005 String tempColumnId = tempRelation.getTarget().getId(); 1006 String tempParentId = tempRelation.getTarget().getParent_id(); 1007 tempColumnId = convertColumnId(tableColumns, 1008 tempColumnId, 1009 tempParentId); 1010 if (tempColumnId.equals(targetColumnId)) { 1011 if (tempRelation.getType().equals(RelationshipType.join.name())) { 1012 return true; 1013 } else if (tempRelation.getType() 1014 .equals(RelationshipType.fdd.name())) { 1015 if (level < 2 1016 && traceJoin(tempRelation, 1017 relationships, 1018 tableColumns, 1019 level + 1)) { 1020 return true; 1021 } 1022 } 1023 } 1024 1025 if (sources != null) { 1026 for (int j = 0; j < sources.size(); j++) { 1027 if ("constant".equals(sources.get(j).getColumn_type())) { 1028 continue; 1029 } 1030 tempColumnId = sources.get(j).getId(); 1031 tempParentId = sources.get(j).getParent_id(); 1032 tempColumnId = convertColumnId(tableColumns, 1033 tempColumnId, 1034 tempParentId); 1035 if (tempColumnId.equals(targetColumnId)) { 1036 if (tempRelation.getType() 1037 .equals(RelationshipType.join.name())) { 1038 return true; 1039 } else if (tempRelation.getType() 1040 .equals(RelationshipType.fdd.name())) { 1041 if (level < 2 1042 && traceJoin(tempRelation, 1043 relationships, 1044 tableColumns, 1045 level + 1)) { 1046 return true; 1047 } 1048 } 1049 } 1050 } 1051 } 1052 } 1053 1054 return false; 1055 } 1056 1057 private String convertColumnId( 1058 Map<String, Map<String, List<column>>> tableColumns, 1059 String columnId, String parentId) { 1060 if (tableColumns.containsKey(parentId)) { 1061 Map<String, List<column>> columnMap = tableColumns.get(parentId); 1062 Iterator<List<column>> iter = columnMap.values().iterator(); 1063 for (int i = 0; i < columnMap.size(); i++) { 1064 List<column> columns = iter.next(); 1065 for (int j = 0; j < columns.size(); j++) { 1066 column column = columns.get(j); 1067 if (column.getId().equals(columnId)) { 1068 return parentId + "-index-" + i; 1069 } 1070 } 1071 } 1072 } 1073 if (parentId != null) { 1074 return parentId + "-id-" + columnId; 1075 } else 1076 return columnId; 1077 } 1078 1079 private String getShortLabel(String label, int length) { 1080 int index = length / 2 - 1; 1081 return (label.substring(0, index - 1) + "..." + label.substring(label.length() 1082 - (index + 1))); 1083 } 1084 1085}