diff --git a/.gitignore b/.gitignore
index 51daf4b..9faf990 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,4 @@ target/
*.iml
# screenshots folder
-/Screenshots/
\ No newline at end of file
+/Screenshots/
diff --git a/README.md b/README.md
index 4dcc4ae..1a695ff 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,21 @@
-# Call Stack Graph Tool
-This tool generate a tree graph for the call stack using the information in log files for you code. A specific format of log file is required for the tool to parse and process the logs. Please see _**How to generate Log files for you code**_ section below to generate log files for your own code.
-### Instruction to run tool using IntelliJ:
+# Java Call Stack Graph Tool
+#### A tool to generate a graphical representation of the Java call stack.
+This tool generate a tree graph for the call stack using the information in log files for you code. A specific format of log files are required for the tool to parse and process the logs. Please see _**How to generate Log files for you code**_ section below to generate log files for your own code.
+
+### Instruction to run tool using Maven.
+1. Download or clone the repository.
+`git clone https://github.com/OmerKhureshi/JavaCallStackGraphTool.git`
+
+2. Since this is a Maven project, use the command below to run the tool from root folder of the repo.
+`mvn exec:java -Dexec.mainClass=com.csgt.Main`
+
+### Instruction to run tool using intelliJ.
1. Download or clone the repository.
2. In IntelliJ, create a new project and choose `Create Project from Existing Sources...`. Choose the cloned repository to import all the files.
Or.
-
- Right click pom.xml file and click open with then choose IntelliJ.
+
+ Right click `pom.xml` file and click open with then choose IntelliJ.
3. Ensure that this project is recognized as a Maven project inside IntelliJ and all the dependencies are downloaded.
6. Run the Main java class at `/src/main/java/com/csgt/Main.java`.
@@ -15,15 +24,14 @@ This tool generate a tree graph for the call stack using the information in log
For the first time, the tool requires the log files that should be used to generate the graph.
1. Click `File -> Select Method Definition log file` (⎇ + m).
2. Click `File -> Select Call Trace file` (⎇ + c).
-3. Click `Run -> Run` (⎇ + r).
-4. To start over, click `Run -> Reset` (⎇ + ⇧ + r) and redo steps 1 to 3 above.
+3. Click `Render -> Run` (⎇ + r).
+4. To start over, click `Render -> Reset` (⎇ + ⇧ + r) and redo steps 1 to 3 above.
#### For consecutive uses:
The tool uses an embedded database to store the parsed information from the log files. Therefore for consecutive uses of the same log files, you can point to the previously generated database to generate the graph without processing the log files. The database file can be found at `/Databases`. The file is suffixed with the time stamp.
1. Click `File -> Load existing database` (⎇ + d).
-2. Click ` Run -> Run` (⎇ + r)
-3. To start over, click `Run -> Reset` (⎇ + ⇧ + r).
+2. Click `Render -> Run` (⎇ + r)
+3. To start over, click `Render -> Reset` (⎇ + ⇧ + r).
### How to generate Log files for your code?
-Call Trace and Method Definition log files can be generated by following the instructions [here](https://github.com/omersalar/LogWeaver).
-
+Call Trace and Method Definition log files can be generated by following the instructions [here](https://github.com/omerkhureshi/LogWeaver).
diff --git a/pom.xml b/pom.xml
index 455a7d0..00fbe35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,4 +43,4 @@
-
\ No newline at end of file
+
diff --git a/src/main/java/com/csgt/Main.java b/src/main/java/com/csgt/Main.java
index f43b179..5ad1605 100644
--- a/src/main/java/com/csgt/Main.java
+++ b/src/main/java/com/csgt/Main.java
@@ -1,21 +1,11 @@
package com.csgt;
import com.csgt.controller.ControllerUtil;
-import javafx.animation.*;
import javafx.application.Application;
-import javafx.application.Platform;
-import javafx.beans.property.DoubleProperty;
-import javafx.beans.property.SimpleDoubleProperty;
-import javafx.event.ActionEvent;
-import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
-import javafx.scene.*;
-import javafx.scene.paint.Color;
-import javafx.scene.shape.Circle;
-import javafx.scene.shape.Rectangle;
-import javafx.scene.shape.RectangleBuilder;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
import javafx.stage.Stage;
-import javafx.util.Duration;
import java.io.IOException;
diff --git a/src/main/java/com/csgt/controller/EventHandlers.java b/src/main/java/com/csgt/controller/EventHandlers.java
index 6125083..29ff67b 100644
--- a/src/main/java/com/csgt/controller/EventHandlers.java
+++ b/src/main/java/com/csgt/controller/EventHandlers.java
@@ -559,7 +559,7 @@ private void minMaxButtonOnClick(NodeCell clickedCell, String threadId) {
// <0 -> not visible AND collapsed
if (collapsed == 0) {
- System.out.println("Minimizing node: " + clickedCellID);
+ // System.out.println("Minimizing node: " + clickedCellID);
// visible and un-collapsed --> visible and collapsed
// this cell only: 0 -> 2
// all other cells: >2 -> ++1
@@ -587,7 +587,7 @@ private void minMaxButtonOnClick(NodeCell clickedCell, String threadId) {
new Thread(task).start();
// clickedCell.setCollapsed(2);
} else if (collapsed == 2) {
- System.out.println("Maximizing node: " + clickedCellID);
+ // System.out.println("Maximizing node: " + clickedCellID);
// visible and collapsed --> visible and un-collapsed
// this cell only : 2 -> 0
// all other cells: >2 -> --1
@@ -628,6 +628,9 @@ private Task expandTreeAt(ElementDTO clickedEleDTO, String threadId, boole
private void expandParentTreeChain(ElementDTO elementDTO , String threadId) {
List parentElementDTOs = ElementDAOImpl.getAllParentElementDTOs(elementDTO, threadId);
+ if (parentElementDTOs == null) {
+ return;
+ }
ExecutorService es = Executors.newSingleThreadExecutor();
parentElementDTOs.forEach(eleDTO -> {
Task task = expandTreeAt(eleDTO, threadId, true);
@@ -638,7 +641,7 @@ private void expandParentTreeChain(ElementDTO elementDTO , String threadId) {
}
public void jumpTo(String cellId, String threadId, int collapsed) {
- System.out.println("EventHandlers.jumpTo");
+ // System.out.println("EventHandlers.jumpTo");
if (collapsed != 0) {
ElementDTO elementDTO = ElementDAOImpl.getElementDTO(cellId);
expandParentTreeChain(elementDTO, threadId);
@@ -661,10 +664,10 @@ public void jumpTo(String cellId, String threadId, int collapsed) {
Platform.runLater(() -> {
ControllerLoader.canvasController.clearAndUpdate();
- System.out.println("EventHandlers.jumpTo here.");
+ // System.out.println("EventHandlers.jumpTo here.");
// blink node
if (ControllerLoader.canvasController.nodeCellsOnUI.containsKey(cellId)) {
- System.out.println("EventHandlers.jumpTo going to blink.");
+ // System.out.println("EventHandlers.jumpTo going to blink.");
ControllerLoader.canvasController.nodeCellsOnUI.get(cellId).blink();
}
});
@@ -723,9 +726,9 @@ protected Void call() {
addChildrenHighlightResizeQueries(clickedEleDTO, isCollapsing, queryList, nextCellIdNew, threadId);
// >> Uncomment to print all the queries in the query list
- System.out.println("EventHandlers.call: printing queries");
- queryList.forEach(query -> System.out.println(query));
- System.out.println();
+ // System.out.println("EventHandlers.call: printing queries");
+ // queryList.forEach(query -> System.out.println(query));
+ // System.out.println();
DatabaseUtil.executeQueryList(queryList);
@@ -814,10 +817,14 @@ private List getSubTreeUpdateQueries(ElementDTO elementDTO, boolean isCo
"AND ELE.COLLAPSED NOT IN (0, 2) " +
")";
- updateHighlightsQuery = "UPDATE " + TableNames.HIGHLIGHT_ELEMENT + " " +
- "SET COLLAPSED = 1 " +
- "WHERE ELEMENT_ID > " + startCellId + " " +
- "AND ELEMENT_ID < " + endCellId;
+ updateHighlightsQuery = "UPDATE " + TableNames.HIGHLIGHT_ELEMENT + " AS H " +
+ "SET H.COLLAPSED = 1 " +
+ "WHERE H.ELEMENT_ID > " + startCellId + " " +
+ "AND H.ELEMENT_ID < " + endCellId + " " +
+ "AND EXISTS (SELECT * FROM " + TableNames.CALL_TRACE_TABLE + " AS CT " +
+ "JOIN " + TableNames.ELEMENT_TABLE + " AS E ON CT.ID = E.ID_ENTER_CALL_TRACE " +
+ "WHERE H.ELEMENT_ID = E.ID AND " +
+ "CT.THREAD_ID = " + threadId + ")";
} else {
updateCellQuery = "UPDATE " + TableNames.ELEMENT_TABLE + " AS E " +
"SET E.COLLAPSED = " +
diff --git a/src/main/java/com/csgt/controller/MenuController.java b/src/main/java/com/csgt/controller/MenuController.java
index 96aef0d..e800c79 100644
--- a/src/main/java/com/csgt/controller/MenuController.java
+++ b/src/main/java/com/csgt/controller/MenuController.java
@@ -117,7 +117,7 @@ public class MenuController {
private Button applyButton;
private Button cancelButton;
- private Map firstCBMap;
+ // private Map firstCBMap;
private Map secondCBMap;
private Map colorsMap;
private boolean anyColorChange = false;
@@ -354,6 +354,8 @@ public void onReset() {
ControllerLoader.instructionsPaneController.setErrorGraphics(false);
ControllerLoader.mainController.alertShown = false;
+
+ firstTimeSetUpHighlightsWindowCall = true;
}
private void setUpBookmarksMenu() {
@@ -423,7 +425,7 @@ private void firstTimeSetUpHighlightsWindow() {
firstTimeSetUpHighlightsWindowCall = false;
- firstCBMap = new HashMap<>();
+ // firstCBMap = new HashMap<>();
secondCBMap = new HashMap<>();
colorsMap = new HashMap<>();
anyColorChange = false;
@@ -625,14 +627,14 @@ protected Void call() throws Exception {
// For each of the selected methods, insert the bound box properties into Highlights table if not already present.
Statement statement = DatabaseUtil.getConnection().createStatement();
- firstCBMap.forEach((fullName, checkBox) -> addInsertQueryToStatement(fullName, statement, "SINGLE"));
+ // firstCBMap.forEach((fullName, checkBox) -> addInsertQueryToStatement(fullName, statement, "SINGLE"));
secondCBMap.forEach((fullName, checkBox) -> addInsertQueryToStatement(fullName, statement, "FULL"));
// Delete records from HIGHLIGHT_ELEMENT if that method is not checked in the stage.
StringJoiner firstSJ = new StringJoiner("','", "'", "'");
- firstCBMap.forEach((fullName, checkBox) -> firstSJ.add(fullName));
- addDeleteQueryToStatement(firstSJ.toString(), statement, "SINGLE");
+ // firstCBMap.forEach((fullName, checkBox) -> firstSJ.add(fullName));
+ // addDeleteQueryToStatement(firstSJ.toString(), statement, "SINGLE");
StringJoiner secondSJ = new StringJoiner("','", "'", "'");
secondCBMap.forEach((fullName, checkBox) -> secondSJ.add(fullName));
@@ -648,7 +650,7 @@ protected Void call() throws Exception {
@Override
protected void succeeded() {
super.succeeded();
- System.out.println("MenuController.showHighlightsWindow.succeeded: ");
+ // System.out.println("MenuController.showHighlightsWindow.succeeded: ");
ControllerLoader.canvasController.clearAndUpdate();
// Stack highlights so that the larger ones are behind smaller ones.
@@ -673,7 +675,6 @@ private void addInsertQueryToStatement(String fullName, Statement statement, Str
String[] arr = fullName.split("\\.");
String methodName = arr[arr.length - 1];
String packageName = fullName.substring(0, fullName.length() - methodName.length() - 1);
-
HighlightDAOImpl.insert(startXOffset, startYOffset, widthOffset, heightOffset, methodName, packageName, highlightType, colorsMap, fullName, statement);
}
diff --git a/src/main/java/com/csgt/dataaccess/DAO/CallTraceDAOImpl.java b/src/main/java/com/csgt/dataaccess/DAO/CallTraceDAOImpl.java
index 56548b3..48ec005 100644
--- a/src/main/java/com/csgt/dataaccess/DAO/CallTraceDAOImpl.java
+++ b/src/main/java/com/csgt/dataaccess/DAO/CallTraceDAOImpl.java
@@ -90,7 +90,7 @@ public static int insert(List val) {
"{ts '" + timestamp + "'}" +
")";
- // System.out.println("Inserting into call trace the statement: " + sql);
+ // System.out.println("Inserting into call trace the statement: " + sql);
ps.execute(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
diff --git a/src/main/java/com/csgt/dataaccess/DAO/ElementDAOImpl.java b/src/main/java/com/csgt/dataaccess/DAO/ElementDAOImpl.java
index a5c3381..befc066 100644
--- a/src/main/java/com/csgt/dataaccess/DAO/ElementDAOImpl.java
+++ b/src/main/java/com/csgt/dataaccess/DAO/ElementDAOImpl.java
@@ -18,8 +18,6 @@
public class ElementDAOImpl {
- private static Map lowestCellInThreadMap = new HashMap<>();
-
public static boolean isTableCreated() {
return DatabaseUtil.isTableCreated(ELEMENT_TABLE);
}
@@ -231,6 +229,9 @@ public static ElementDTO getElementDTO(String id) {
}
public static List getElementDTOs(List ids) {
+ if (ids == null || ids.size() == 0) {
+ return null;
+ }
List elementDTOs = new ArrayList<>();
StringJoiner stringJoiner = new StringJoiner(",", "(", ")");
@@ -391,7 +392,7 @@ public static int getMaxLeafCount(String threadId) {
" from " + TableNames.CALL_TRACE_TABLE + " " +
" where THREAD_ID = " + threadId + ")))";
- System.out.println(">>> " + SQLMaxLeafCount);
+ // System.out.println(">>> " + SQLMaxLeafCount);
int leafCount = DatabaseUtil.executeSelectForInt(SQLMaxLeafCount);
return leafCount;
}
@@ -432,29 +433,20 @@ public static double getMaxHeight(String threadId) {
"ON CT.ID = E2.ID_ENTER_CALL_TRACE " +
"where E2.PARENT_ID = E1.ID and CT.THREAD_ID = " + threadId + ")";
- System.out.println(">>> " + SQLMaxLeafCount);
+ // System.out.println(">>> " + SQLMaxLeafCount);
double height = DatabaseUtil.executeSelectForDouble(SQLMaxLeafCount);
return height;
}
public static int getLowestCellInThread(String threadId) {
- if (lowestCellInThreadMap.containsKey(threadId)) {
- System.out.println("ElementDAOImpl.getLowestCellInThread: in if loop");
- return lowestCellInThreadMap.get(threadId);
- }
- System.out.println("ElementDAOImpl.getLowestCellInThread: outside if loop");
String maxEleIdQuery = "SELECT MAX(E.ID) AS MAXID " +
"FROM " + TableNames.ELEMENT_TABLE + " AS E JOIN " + TableNames.CALL_TRACE_TABLE + " AS CT " +
"ON E.ID_ENTER_CALL_TRACE = CT.ID " +
"WHERE CT.THREAD_ID = " + threadId;
- System.out.println("ElementDAOImpl.getLowestCellInThread: maxEleIdQuery: " + maxEleIdQuery);
try (ResultSet eleIdRS = DatabaseUtil.select(maxEleIdQuery)){
if (eleIdRS.next()) {
int eleId = eleIdRS.getInt("MAXID");
- System.out.println("ElementDAOImpl.getLowestCellInThread: put lowestCellInThreadMap: " +threadId + " : " + eleId);
- lowestCellInThreadMap.put(threadId, eleId);
- System.out.println("ElementDAOImpl.getLowestCellInThread: eleId = " + eleId);
return eleId;
}
} catch (SQLException e) {
diff --git a/src/main/java/com/csgt/dataaccess/DatabaseUtil.java b/src/main/java/com/csgt/dataaccess/DatabaseUtil.java
index 192b6fe..9cbb642 100644
--- a/src/main/java/com/csgt/dataaccess/DatabaseUtil.java
+++ b/src/main/java/com/csgt/dataaccess/DatabaseUtil.java
@@ -33,7 +33,7 @@ public static boolean isTableCreated(String tableName) {
} catch (SQLException e) {
e.printStackTrace();
}
- System.out.println("DatabaseUtil.isTableCreated: table not created tableName: " + tableName);
+ // System.out.println("DatabaseUtil.isTableCreated: table not created tableName: " + tableName);
return false;
}
@@ -127,7 +127,7 @@ public static boolean createCallTrace()
/*" FOREIGN KEY(\"methodID\") REFERENCES METHOD(\"methdID\")"+ */
")";
- System.out.println("Created call trace table now. ");
+ // System.out.println("Created call trace table now. ");
ps.executeUpdate(sql);
ps.close();
ps = null;
@@ -193,7 +193,7 @@ public static boolean createMethodDefn()
ps = null;
cn.close();
cn = null;
- System.out.println("Method defn table created.");
+ // System.out.println("Method defn table created.");
methodDefnTableCreated = true;
} catch (SQLException e) {
String sqlError = e.getSQLState();