Skip to content

Commit f269a41

Browse files
committed
Add longest path visualizations for Java Artifacts and TypeScript Modules
1 parent f8128f6 commit f269a41

File tree

3 files changed

+123
-1
lines changed

3 files changed

+123
-1
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Path Finding - Longest path - Stream - Find the top 100 dependencies contributing to the longest paths for Visualization with GraphViz
2+
3+
MATCH (sourceNodeForStatistics)-[dependencyForStatistics:DEPENDS_ON]->(targetNodeForStatistics)
4+
WHERE $dependencies_projection_node IN LABELS(sourceNodeForStatistics)
5+
AND $dependencies_projection_node IN LABELS(targetNodeForStatistics)
6+
WITH min(dependencyForStatistics[$dependencies_projection_weight_property]) AS minWeight
7+
,max(dependencyForStatistics[$dependencies_projection_weight_property]) AS maxWeight
8+
,max(targetNodeForStatistics.maxDistanceFromSource) AS maxLevel
9+
WITH *, 1.0 / toFloat(maxWeight - minWeight) AS weightNormalizationFactor
10+
CALL gds.dag.longestPath.stream($dependencies_projection + '-cleaned')
11+
YIELD index, totalCost, path
12+
WITH *, toInteger(totalCost) AS distance
13+
ORDER BY distance DESC, index ASC
14+
UNWIND relationships(path) AS pathRelationship
15+
WITH *
16+
,startNode(pathRelationship) AS startNode
17+
,endNode(pathRelationship) AS endNode
18+
MATCH (startNode)-[dependency:DEPENDS_ON]->(endNode)
19+
WITH *, dependency[$dependencies_projection_weight_property] AS weight
20+
WITH *, toFloat(weight - minWeight) * weightNormalizationFactor AS normalizedWeight
21+
WITH *, round((normalizedWeight * 5) + 1, 2) AS penWidth
22+
WITH *, startNode.name + "\\n(level " + startNode.maxDistanceFromSource + "/" + maxLevel + ")" AS startNodeTitle
23+
WITH *, endNode.name + "\\n(level " + endNode.maxDistanceFromSource + "/" + maxLevel + ")" AS endNodeTitle
24+
WITH *, "[label=" + weight + "; penwidth=" + penWidth + "; ];" AS graphVizEdgeAttributes
25+
WITH *, "\"" + startNodeTitle + "\" -> \"" + endNodeTitle + "\" " + graphVizEdgeAttributes AS graphVizDotNotationLine
26+
RETURN graphVizDotNotationLine
27+
// Debugging
28+
// RETURN startNode.name AS startNodeName
29+
// ,endNode.name AS endNodeName
30+
// ,dependency[$dependencies_projection_weight_property] AS dependencyWeight
31+
// ,max(distance) AS partOfLongestPathLength
32+
// ,count(DISTINCT index) AS partOfLongestPathCounts
33+
// ,startNode.maxDistanceFromSource AS startNodeLevel
34+
// ,endNode.maxDistanceFromSource AS endNodeLevel
35+
LIMIT 100

cypher/Path_Finding/Set_Parameters.cypher

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Example on how to set the parameters for centrality in this case for Packages and PageRank
1+
// Example on how to set the parameters for path finding in this case for Packages and PageRank
22

33
:params {
44
"dependencies_projection": "package-path-finding",
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env bash
2+
3+
# Executes selected "Path_Finding" Cypher queries for GraphViz visualization.
4+
# For example, the Java Artifact and TypeScript Module dependencies with the longest paths are visualized.
5+
# It requires an already running Neo4j graph database with already scanned and analyzed artifacts.
6+
# The reports (csv, dot and svg files) will be written into the sub directory reports/path-finding-visualization.
7+
8+
# Requires executeQueryFunctions.sh, projectionFunctions.sh, cleanupAfterReportGeneration.sh
9+
10+
# Fail on any error ("-e" = exit on first error, "-o pipefail" exist on errors within piped commands)
11+
set -o errexit -o pipefail
12+
13+
# Overrideable Constants (defaults also defined in sub scripts)
14+
REPORTS_DIRECTORY=${REPORTS_DIRECTORY:-"reports"}
15+
16+
## Get this "scripts/reports" directory if not already set
17+
# Even if $BASH_SOURCE is made for Bourne-like shells it is also supported by others and therefore here the preferred solution.
18+
# CDPATH reduces the scope of the cd command to potentially prevent unintended directory changes.
19+
# This way non-standard tools like readlink aren't needed.
20+
REPORTS_SCRIPT_DIR=${REPORTS_SCRIPT_DIR:-$( CDPATH=. cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P )}
21+
echo "PathFindingVisualization: REPORTS_SCRIPT_DIR=${REPORTS_SCRIPT_DIR}"
22+
23+
# Get the "scripts" directory by taking the path of this script and going one directory up.
24+
SCRIPTS_DIR=${SCRIPTS_DIR:-"${REPORTS_SCRIPT_DIR}/.."} # Repository directory containing the shell scripts
25+
echo "PathFindingVisualization SCRIPTS_DIR=${SCRIPTS_DIR}"
26+
27+
# Get the "scripts/visualization" directory.
28+
VISUALIZATION_SCRIPTS_DIR=${VISUALIZATION_SCRIPTS_DIR:-"${SCRIPTS_DIR}/visualization"} # Repository directory containing the shell scripts for visualization
29+
echo "PathFindingVisualization VISUALIZATION_SCRIPTS_DIR=${VISUALIZATION_SCRIPTS_DIR}"
30+
31+
# Get the "cypher" directory by taking the path of this script and going two directory up and then to "cypher".
32+
CYPHER_DIR=${CYPHER_DIR:-"${REPORTS_SCRIPT_DIR}/../../cypher"}
33+
echo "PathFindingVisualization CYPHER_DIR=${CYPHER_DIR}"
34+
35+
PATH_FINDINGS_CYPHER_DIR="${CYPHER_DIR}/Path_Finding"
36+
37+
if ! command -v "npx" &> /dev/null ; then
38+
echo "PathFindingVisualization: Error: Command npx (run npm locally) not found. It's needed for Graph visualization with GraphViz." >&2
39+
exit 1
40+
fi
41+
42+
# Define functions to execute cypher queries from within a given file
43+
source "${SCRIPTS_DIR}/executeQueryFunctions.sh"
44+
45+
# Define functions to create and delete Graph Projections like "createDirectedDependencyProjection"
46+
source "${SCRIPTS_DIR}/projectionFunctions.sh"
47+
48+
# Create report directory
49+
REPORT_NAME="path-finding-visualization"
50+
FULL_REPORT_DIRECTORY="${REPORTS_DIRECTORY}/${REPORT_NAME}"
51+
mkdir -p "${FULL_REPORT_DIRECTORY}"
52+
53+
visualizeGraphAndGenerateSvg() {
54+
local name="${1}"
55+
echo "PathFindingVisualization: Generating Visualization ${name}..."
56+
source "${VISUALIZATION_SCRIPTS_DIR}/convertQueryResultCsvToGraphVizDotFile.sh" --filename "${name}.csv"
57+
58+
if [ -f "${name}.gv" ]; then
59+
# Run GraphViz command line interface (CLI) wrapped utilizing WASM (WebAssembly)
60+
# to convert the DOT file to SVG operating system independently.
61+
npx --yes @hpcc-js/[email protected] -T svg "${name}.gv" > "${name}.svg"
62+
fi
63+
}
64+
65+
# Java Artifacts: Longest Paths Visualization
66+
ARTIFACT_PROJECTION="dependencies_projection=artifact-path-finding"
67+
ARTIFACT_NODE="dependencies_projection_node=Artifact"
68+
ARTIFACT_WEIGHT="dependencies_projection_weight_property=weight"
69+
reportName="${FULL_REPORT_DIRECTORY}/JavaArtifactLongestPaths"
70+
if createDirectedDependencyProjection "${ARTIFACT_PROJECTION}" "${ARTIFACT_NODE}" "${ARTIFACT_WEIGHT}"; then
71+
execute_cypher "${PATH_FINDINGS_CYPHER_DIR}/Path_Finding_6_Longest_paths_for_graphviz.cypher" "${ARTIFACT_PROJECTION}" "${ARTIFACT_NODE}" "${ARTIFACT_WEIGHT}" > "${reportName}.csv"
72+
visualizeGraphAndGenerateSvg "${reportName}"
73+
fi
74+
75+
# TypeScript Modules: Longest Paths Visualization
76+
MODULE_LANGUAGE="dependencies_projection_language=Typescript"
77+
MODULE_PROJECTION="dependencies_projection=typescript-module-path-finding"
78+
MODULE_NODE="dependencies_projection_node=Module"
79+
MODULE_WEIGHT="dependencies_projection_weight_property=lowCouplingElement25PercentWeight"
80+
reportName="${FULL_REPORT_DIRECTORY}/TypeScriptModuleLongestPaths"
81+
if createDirectedDependencyProjection "${MODULE_LANGUAGE}" "${MODULE_PROJECTION}" "${MODULE_NODE}" "${MODULE_WEIGHT}"; then
82+
execute_cypher "${PATH_FINDINGS_CYPHER_DIR}/Path_Finding_6_Longest_paths_for_graphviz.cypher" "${MODULE_PROJECTION}" "${MODULE_NODE}" "${MODULE_WEIGHT}" > "${reportName}.csv"
83+
visualizeGraphAndGenerateSvg "${reportName}"
84+
fi
85+
86+
# Clean-up after report generation. Empty reports will be deleted.
87+
source "${SCRIPTS_DIR}/cleanupAfterReportGeneration.sh" "${FULL_REPORT_DIRECTORY}"

0 commit comments

Comments
 (0)