001package gudusoft.gsqlparser.dlineage.dataflow.metadata.grabit; 002 003import gudusoft.gsqlparser.dlineage.util.DlineageUtil; 004import java.util.Collections; 005import java.util.Comparator; 006import java.util.LinkedHashMap; 007import java.util.List; 008import java.util.Map; 009 010import gudusoft.gsqlparser.EDbVendor; 011import gudusoft.gsqlparser.dlineage.dataflow.metadata.MetadataAnalyzer; 012import gudusoft.gsqlparser.dlineage.dataflow.model.ModelBindingManager; 013import gudusoft.gsqlparser.dlineage.dataflow.model.xml.column; 014import gudusoft.gsqlparser.dlineage.dataflow.model.xml.dataflow; 015import gudusoft.gsqlparser.dlineage.dataflow.model.xml.procedure; 016import gudusoft.gsqlparser.dlineage.dataflow.model.xml.table; 017import gudusoft.gsqlparser.dlineage.util.Pair3; 018import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType; 019import gudusoft.gsqlparser.sqlenv.TSQLEnv; 020import gudusoft.gsqlparser.util.SQLUtil; 021import gudusoft.gsqlparser.util.json.JSON; 022 023public class GrabitMetadataAnalyzer implements MetadataAnalyzer<String> { 024 025 private Map<String, procedure> procedureMap = new LinkedHashMap<String, procedure>(); 026 private Map<String, table> tableMap = new LinkedHashMap<String, table>(); 027 private Map<String, column> columnMap = new LinkedHashMap<String, column>(); 028 private EDbVendor vendor; 029 030 @Override 031 public synchronized dataflow analyzeMetadata(EDbVendor vendor, String metadata) { 032 init(vendor); 033 dataflow dataflow = new dataflow(); 034 Map json = (Map) JSON.parseObject(metadata.trim()); 035 if (json.containsKey("createdBy")) { 036 String createdBy = (String) json.get("createdBy"); 037 if (createdBy.toLowerCase(java.util.Locale.ROOT).indexOf("grabit") != -1) { 038 List databases = (List) json.get("databases"); 039 if (databases != null) { 040 041 for (int i = 0; i < databases.size(); i++) { 042 Map jsonDatabase = (Map) databases.get(i); 043 String databaseName = (String) jsonDatabase.get("name"); 044 List tables = (List) jsonDatabase.get("tables"); 045 for (int j = 0; j < tables.size(); j++) { 046 Map jsonTable = (Map) tables.get(j); 047 databaseName = (String) jsonTable.get("database"); 048 if(databaseName.indexOf(".")!=-1) { 049 databaseName = SQLUtil.quoteDottedName(vendor, ESQLDataObjectType.dotCatalog, databaseName); 050 } 051 String schemeName = (String) jsonTable.get("schema"); 052 if(schemeName.indexOf(".")!=-1) { 053 schemeName = SQLUtil.quoteDottedName(vendor, ESQLDataObjectType.dotSchema, schemeName); 054 } 055 String tableName = (String) jsonTable.get("name"); 056 if(tableName.indexOf(".")!=-1) { 057 tableName = SQLUtil.quoteDottedName(vendor, ESQLDataObjectType.dotTable, tableName); 058 } 059 boolean isView = false; 060 if (jsonTable.containsKey("isView")) { 061 isView = Boolean.parseBoolean((String) jsonTable.get("isView")); 062 } 063 List columns = (List) jsonTable.get("columns"); 064 for (int k = 0; k < columns.size(); k++) { 065 Map jsonColumn = (Map) columns.get(k); 066 String columnName = (String) jsonColumn.get("name"); 067 appendTable(dataflow, databaseName, schemeName, tableName, isView, columnName); 068 } 069 } 070 } 071 } 072 } 073 } 074 sortTableColumns(dataflow); 075 return dataflow; 076 } 077 078 private void init(EDbVendor vendor) { 079 this.vendor = vendor; 080 procedureMap.clear(); 081 tableMap.clear(); 082 columnMap.clear(); 083 if (ModelBindingManager.get() == null) { 084 ModelBindingManager.set(new ModelBindingManager()); 085 } 086 } 087 088 private void sortTableColumns(dataflow dataflow) { 089 if (dataflow.getTables() != null) { 090 for (table table : dataflow.getTables()) { 091 Collections.sort(table.getColumns(), new Comparator<column>() { 092 public int compare(column t1, column t2) { 093 if (t1.getName().equalsIgnoreCase("RelationRows")) 094 return 1; 095 if (t2.getName().equalsIgnoreCase("RelationRows")) 096 return -1; 097 return 0; 098 } 099 }); 100 } 101 } 102 103 if (dataflow.getResultsets() != null) { 104 for (table table : dataflow.getResultsets()) { 105 Collections.sort(table.getColumns(), new Comparator<column>() { 106 public int compare(column t1, column t2) { 107 if (t1.getName().equalsIgnoreCase("RelationRows")) 108 return 1; 109 if (t2.getName().equalsIgnoreCase("RelationRows")) 110 return -1; 111 return 0; 112 } 113 }); 114 } 115 } 116 } 117 118 private void appendTable(dataflow dataflow, String databaseName, String schemaName, String tableName, 119 boolean isView, String columnName) { 120 String tableKey = getFullName(databaseName, schemaName, tableName); 121 if (!tableMap.containsKey(tableKey)) { 122 table table = new table(); 123 // This reader publishes SQL spellings (its input names, converted by their declared form). 124 table.setPublishedNameSqlSpelling(true); 125 table.setDatabase(databaseName); 126 table.setSchema(schemaName); 127 table.setName(tableName); 128 if (!SQLUtil.isEmpty(table.getSchema()) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(table.getSchema())) { 129 table.setName(table.getSchema() + "." + table.getName()); 130 } 131 if (!SQLUtil.isEmpty(table.getDatabase()) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(table.getDatabase())) { 132 table.setName(table.getDatabase() + "." + table.getName()); 133 } 134 table.setId(String.valueOf(++ModelBindingManager.get().TABLE_COLUMN_ID)); 135 table.setCoordinate(new Pair3<Long, Long, Integer>(-1L, -1L, 136 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash())) + "," 137 + new Pair3<Long, Long, Integer>(-1L, -1L, 138 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash()))); 139 if (isView) { 140 table.setType("view"); 141 dataflow.getViews().add(table); 142 } else { 143 table.setType("table"); 144 dataflow.getTables().add(table); 145 } 146 tableMap.put(tableKey, table); 147 } 148 149 table table = tableMap.get(tableKey); 150 String sourceColumnKey = getFullName(databaseName, schemaName, tableName, columnName); 151 if (!columnMap.containsKey(sourceColumnKey)) { 152 column column = new column(); 153 column.setId(String.valueOf(++ModelBindingManager.get().TABLE_COLUMN_ID)); 154 column.setName(columnName); 155 if ("*".equals(columnName)) { 156 // a metadata column named *, not a star 157 column.setStar(Boolean.FALSE); 158 } 159 column.setIdentifierKey(DlineageUtil.lexicalColumnKey(vendor, columnName)); 160 if ("RelationRows".equalsIgnoreCase(columnName)) { 161 column.setSource("system"); 162 } 163 column.setCoordinate(new Pair3<Long, Long, Integer>(-1L, -1L, 164 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash())) + "," 165 + new Pair3<Long, Long, Integer>(-1L, -1L, 166 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash()))); 167 table.getColumns().add(column); 168 columnMap.put(sourceColumnKey, column); 169 } 170 } 171 172 private String getFullName(String... segments) { 173 StringBuilder builder = new StringBuilder(); 174 for (int i = 0; i < segments.length; i++) { 175 builder.append(segments[i]); 176 if (i < segments.length - 1) { 177 builder.append("."); 178 } 179 } 180 return builder.toString().replace("null.", ""); 181 } 182}