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}