001package gudusoft.gsqlparser.dlineage.util;
002
003import java.util.List;
004import java.util.Map;
005
006import gudusoft.gsqlparser.EDbVendor;
007import gudusoft.gsqlparser.TCustomSqlStatement;
008import gudusoft.gsqlparser.TGSqlParser;
009import gudusoft.gsqlparser.TSourceToken;
010import gudusoft.gsqlparser.TStatementList;
011import gudusoft.gsqlparser.dlineage.DataFlowAnalyzer;
012import gudusoft.gsqlparser.dlineage.ParallelDataFlowAnalyzer;
013import gudusoft.gsqlparser.dlineage.dataflow.model.DbObjectPosition;
014import gudusoft.gsqlparser.dlineage.dataflow.model.SqlInfo;
015import gudusoft.gsqlparser.dlineage.dataflow.model.json.Coordinate;
016import gudusoft.gsqlparser.dlineage.dataflow.model.xml.PositionUtil;
017import gudusoft.gsqlparser.util.IndexedLinkedHashMap;
018import gudusoft.gsqlparser.util.SQLUtil;
019import gudusoft.gsqlparser.util.json.JSON;
020
021@SuppressWarnings("unchecked")
022public class SqlInfoHelper {
023
024        private IndexedLinkedHashMap<String, Object> sqlInfo;
025
026        public static String getSqlInfoJson(DataFlowAnalyzer analyzer) {
027                return analyzer.generateSqlInfos();
028        }
029
030        public static String getSqlInfoJson(ParallelDataFlowAnalyzer analyzer) {
031                return analyzer.generateSqlInfos();
032        }
033
034        public SqlInfoHelper(String sqlInfoJson) {
035                sqlInfo = (IndexedLinkedHashMap<String, Object>) JSON.parseObject(sqlInfoJson);
036        }
037
038        @SuppressWarnings("rawtypes")
039        public SqlInfoHelper(DataFlowAnalyzer analyzer) {
040                if (sqlInfo == null) {
041                        sqlInfo = (IndexedLinkedHashMap) analyzer.getSqlInfos();
042                }
043        }
044
045        public static Coordinate[][] parseCoordinateString(String coordinate) {
046                if (coordinate.indexOf("{") != -1 && coordinate.indexOf("}") != -1) {
047                        List<Map<String, Object>> items = (List<Map<String, Object>>) JSON.parseObject(coordinate);
048                        Coordinate[][] coordinates = new Coordinate[items.size() / 2][2];
049                        for (int i = 0; i < coordinates.length; i++) {
050                                Map<String, Object> startMap = items.get(2 * i);
051                                Map<String, Object> endMap = items.get(2 * i + 1);
052                                Coordinate start = new Coordinate(Long.valueOf(startMap.get("x").toString()),
053                                                Long.valueOf(startMap.get("y").toString()), (String) startMap.get("hashCode"));
054                                Coordinate end = new Coordinate(Long.valueOf(endMap.get("x").toString()),
055                                                Long.valueOf(endMap.get("y").toString()), (String) endMap.get("hashCode"));
056                                Coordinate[] pair = new Coordinate[] { start, end };
057                                coordinates[i] = pair;
058                        }
059                        return coordinates;
060                } else {
061                        int count = PositionUtil.getOccurrencesNumber(coordinate);
062                        Coordinate[][] coordinates = new Coordinate[count][2];
063                        for (int i = 0; i < count; i++) {
064                                Coordinate start = PositionUtil.getStartPos(coordinate, i);
065                                Coordinate end = PositionUtil.getEndPos(coordinate, i);
066
067                                Coordinate[] pair = new Coordinate[] { start, end };
068                                coordinates[i] = pair;
069                        }
070                        return coordinates;
071                }
072        }
073
074        @SuppressWarnings("rawtypes")
075        public DbObjectPosition getSelectedDbObjectInfo(Coordinate start, Coordinate end) {
076                if(start == null || end == null){
077                        throw new IllegalArgumentException("Coordinate can't be null.");
078                }
079                
080                String hashCode = start.getHashCode();
081                int dbObjectStartLine = (int) start.getX() - 1;
082                int dbObjectStarColumn = (int) start.getY() - 1;
083                int dbObjectEndLine = (int) end.getX() - 1;
084                int dbObjectEndColumn = (int) end.getY() - 1;
085                
086                if(hashCode == null){
087                        throw new IllegalArgumentException("Coordinate hashcode can't be null.");
088                }
089                
090                List sqlInfoList;
091                if (hashCode.matches("\\d+")) {
092                        sqlInfoList = (List) sqlInfo.getValueAtIndex(Integer.valueOf(hashCode));
093                } else {
094                        sqlInfoList = (List) sqlInfo.get(hashCode);
095                }
096                if (sqlInfoList == null) {
097                        return null;
098                }
099                for (int j = 0; j < sqlInfoList.size(); j++) {
100                        Object item = sqlInfoList.get(j);
101                        if (item instanceof Map) {
102                                Map<String, Object> sqlInfo = (Map<String, Object>) item;
103                                int startLine = Integer.valueOf(sqlInfo.get("lineStart").toString());
104                                int endLine = Integer.valueOf(sqlInfo.get("lineEnd").toString());
105                                if (dbObjectStartLine >= startLine && dbObjectStartLine <= endLine) {
106                                        DbObjectPosition position = new DbObjectPosition();
107                                        position.setFile((String) sqlInfo.get("fileName"));
108                                        position.setFilePath((String) sqlInfo.get("filePath"));
109                                        position.setSql((String) sqlInfo.get("sql"));
110                                        position.setIndex(Integer.valueOf(sqlInfo.get("originIndex").toString()));
111                                        List<Pair<Integer, Integer>> positions = position.getPositions();
112                                        int originLineStart = Integer.valueOf(sqlInfo.get("originLineStart").toString());
113                                        positions.add(new Pair<Integer, Integer>(dbObjectStartLine - startLine + originLineStart + 1,
114                                                        dbObjectStarColumn + 1));
115                                        positions.add(new Pair<Integer, Integer>(dbObjectEndLine - startLine + originLineStart + 1,
116                                                        dbObjectEndColumn + 1));
117                                        return position;
118                                }
119                        } else if (item instanceof SqlInfo) {
120                                SqlInfo sqlInfo = (SqlInfo) item;
121                                int startLine = sqlInfo.getLineStart();
122                                int endLine = sqlInfo.getLineEnd();
123                                if (dbObjectStartLine >= startLine && dbObjectStartLine <= endLine) {
124                                        DbObjectPosition position = new DbObjectPosition();
125                                        position.setFile(sqlInfo.getFileName());
126                                        position.setFilePath(sqlInfo.getFilePath());
127                                        position.setSql(sqlInfo.getSql());
128                                        position.setIndex(sqlInfo.getOriginIndex());
129                                        List<Pair<Integer, Integer>> positions = position.getPositions();
130                                        int originLineStart = sqlInfo.getOriginLineStart();
131                                        positions.add(new Pair<Integer, Integer>(dbObjectStartLine - startLine + originLineStart + 1,
132                                                        dbObjectStarColumn + 1));
133                                        positions.add(new Pair<Integer, Integer>(dbObjectEndLine - startLine + originLineStart + 1,
134                                                        dbObjectEndColumn + 1));
135                                        return position;
136                                }
137                        }
138                }
139                return null;
140        }
141
142        @SuppressWarnings("rawtypes")
143        public DbObjectPosition getSelectedDbObjectStatementInfo(EDbVendor vendor, Coordinate start, Coordinate end) {
144                if(start == null || end == null){
145                        throw new IllegalArgumentException("Coordinate can't be null.");
146                }
147                
148                String hashCode = start.getHashCode();
149                
150                if(hashCode == null){
151                        throw new IllegalArgumentException("Coordinate hashcode can't be null.");
152                }
153                
154                int dbObjectStartLine = (int) start.getX() - 1;
155                int dbObjectStarColumn = (int) start.getY() - 1;
156                int dbObjectEndLine = (int) end.getX() - 1;
157                int dbObjectEndColumn = (int) end.getY() - 1;
158                List sqlInfoList;
159                if (hashCode.matches("\\d+")) {
160                        sqlInfoList = (List) sqlInfo.getValueAtIndex(Integer.valueOf(hashCode));
161                } else {
162                        sqlInfoList = (List) sqlInfo.get(hashCode);
163                }
164                if (sqlInfoList == null) {
165                        return null;
166                }
167                for (int j = 0; j < sqlInfoList.size(); j++) {
168                        Object item = sqlInfoList.get(j);
169                        if (item instanceof Map) {
170                                Map<String, Object> sqlInfo = (Map<String, Object>) sqlInfoList.get(j);
171                                int startLine = Integer.valueOf(sqlInfo.get("lineStart").toString());
172                                int endLine = Integer.valueOf(sqlInfo.get("lineEnd").toString());
173                                if (dbObjectStartLine >= startLine && dbObjectStartLine <= endLine) {
174                                        DbObjectPosition position = new DbObjectPosition();
175                                        position.setFile((String) sqlInfo.get("fileName"));
176                                        position.setFilePath((String) sqlInfo.get("filePath"));
177                                        position.setSql((String) sqlInfo.get("sql"));
178                                        position.setIndex(Integer.valueOf(sqlInfo.get("originIndex").toString()));
179                                        List<Pair<Integer, Integer>> positions = position.getPositions();
180                                        int originLineStart = Integer.valueOf(sqlInfo.get("originLineStart").toString());
181
182                                        int startX = dbObjectStartLine - startLine + originLineStart + 1;
183                                        int startY = dbObjectStarColumn + 1;
184
185                                        int endX = dbObjectEndLine - startLine + originLineStart + 1;
186                                        int endY = dbObjectEndColumn + 1;
187
188                                        TGSqlParser parser = new TGSqlParser(vendor);
189                                        parser.setSqltext(position.getSql());
190                                        parser.getrawsqlstatements();
191                                        TStatementList stmts = parser.getSqlstatements();
192                                        for (int i = 0; i < stmts.size(); i++) {
193                                                TCustomSqlStatement stmt = stmts.get(i);
194                                                TSourceToken startToken = stmt.getStartToken();
195                                                TSourceToken endToken = stmt.getEndToken();
196                                                long startPosX = startToken.lineNo;
197                                                long startPosY = startToken.columnNo;
198
199                                                long endPosX = endToken.lineNo;
200                                                long endPosY = endToken.columnNo + SQLUtil.endTrim(endToken.astext).length();
201                                                String[] segments = endToken.astext.split("\n");
202                                                if (segments.length > 1) {
203                                                        endPosX = endToken.lineNo + segments.length - 1;
204                                                        endPosY = segments[segments.length - 1].length() + 1;
205                                                }
206
207                                                if (startPosX <= startX && endPosX >= endX) {
208                                                        if (startPosX == startX && startPosY > startY) {
209                                                                continue;
210                                                        }
211                                                        if (endPosX == endX && endPosY < endY) {
212                                                                continue;
213                                                        }
214
215                                                        position.setIndex(i);
216                                                        StringBuffer buffer = new StringBuffer();
217                                                        if (startPosY > 1) {
218                                                                for (int z = 0; z < startPosY - 1; z++) {
219                                                                        buffer.append(" ");
220                                                                }
221                                                        }
222                                                        buffer.append(stmt.toString());
223                                                        position.setSql(buffer.toString());
224
225                                                        int offset = (int) startPosX - 1;
226
227                                                        positions.add(new Pair<Integer, Integer>(
228                                                                        dbObjectStartLine - startLine + originLineStart + 1 - offset,
229                                                                        dbObjectStarColumn + 1));
230                                                        positions.add(new Pair<Integer, Integer>(
231                                                                        dbObjectEndLine - startLine + originLineStart + 1 - offset, dbObjectEndColumn + 1));
232
233                                                        return position;
234                                                } else {
235                                                        continue;
236                                                }
237                                        }
238                                }
239                        } else if (item instanceof SqlInfo) {
240                                SqlInfo sqlInfo = (SqlInfo) item;
241                                int startLine = sqlInfo.getLineStart();
242                                int endLine = sqlInfo.getLineEnd();
243                                if (dbObjectStartLine >= startLine && dbObjectStartLine <= endLine) {
244                                        DbObjectPosition position = new DbObjectPosition();
245                                        position.setFile(sqlInfo.getFileName());
246                                        position.setFilePath(sqlInfo.getFilePath());
247                                        position.setSql(sqlInfo.getSql());
248                                        position.setIndex(sqlInfo.getOriginIndex());
249                                        List<Pair<Integer, Integer>> positions = position.getPositions();
250                                        int originLineStart = sqlInfo.getOriginLineStart();
251
252                                        int startX = dbObjectStartLine - startLine + originLineStart + 1;
253                                        int startY = dbObjectStarColumn + 1;
254
255                                        int endX = dbObjectEndLine - startLine + originLineStart + 1;
256                                        int endY = dbObjectEndColumn + 1;
257
258                                        TGSqlParser parser = new TGSqlParser(vendor);
259                                        parser.setSqltext(position.getSql());
260                                        parser.getrawsqlstatements();
261                                        TStatementList stmts = parser.getSqlstatements();
262                                        for (int i = 0; i < stmts.size(); i++) {
263                                                TCustomSqlStatement stmt = stmts.get(i);
264                                                TSourceToken startToken = stmt.getStartToken();
265                                                TSourceToken endToken = stmt.getEndToken();
266                                                long startPosX = startToken.lineNo;
267                                                long startPosY = startToken.columnNo;
268
269                                                long endPosX = endToken.lineNo;
270                                                long endPosY = endToken.columnNo + SQLUtil.endTrim(endToken.astext).length();
271                                                String[] segments = endToken.astext.split("\n");
272                                                if (segments.length > 1) {
273                                                        endPosX = endToken.lineNo + segments.length - 1;
274                                                        endPosY = segments[segments.length - 1].length() + 1;
275                                                }
276
277                                                if (startPosX <= startX && endPosX >= endX) {
278                                                        if (startPosX == startX && startPosY > startY) {
279                                                                continue;
280                                                        }
281                                                        if (endPosX == endX && endPosY < endY) {
282                                                                continue;
283                                                        }
284
285                                                        position.setIndex(i);
286                                                        StringBuffer buffer = new StringBuffer();
287                                                        if (startPosY > 1) {
288                                                                for (int z = 0; z < startPosY - 1; z++) {
289                                                                        buffer.append(" ");
290                                                                }
291                                                        }
292                                                        buffer.append(stmt.toString());
293                                                        position.setSql(buffer.toString());
294
295                                                        int offset = (int) startPosX - 1;
296
297                                                        positions.add(new Pair<Integer, Integer>(
298                                                                        dbObjectStartLine - startLine + originLineStart + 1 - offset,
299                                                                        dbObjectStarColumn + 1));
300                                                        positions.add(new Pair<Integer, Integer>(
301                                                                        dbObjectEndLine - startLine + originLineStart + 1 - offset, dbObjectEndColumn + 1));
302
303                                                        return position;
304                                                } else {
305                                                        continue;
306                                                }
307                                        }
308                                }
309                        }
310                }
311                return null;
312        }
313}