diff --git a/cypher/Topological_Sort/Topological_Sort_List.cypher b/cypher/Topological_Sort/Topological_Sort_List.cypher new file mode 100644 index 000000000..4d3a19cd4 --- /dev/null +++ b/cypher/Topological_Sort/Topological_Sort_List.cypher @@ -0,0 +1,22 @@ +// Topological Sort to list the properties topologicalSortIndex (e.g. build order) and maxDistanceFromSource (build level) for each code unit node. +// Needs graph-data-science plugin version >= 2.5.0 + +CALL gds.dag.topologicalSort.stream( + $dependencies_projection + '-without-empty', { + computeMaxDistanceFromSource: true +}) YIELD nodeId, maxDistanceFromSource + WITH nodeId + ,gds.util.asNode(nodeId) AS codeUnit + ,toInteger(maxDistanceFromSource) AS maxDistanceFromSource + SET codeUnit.maxDistanceFromSource = maxDistanceFromSource + WITH collect(nodeId) AS sortedNodeIds + ,collect({codeUnit: codeUnit, maxDistanceFromSource: maxDistanceFromSource}) AS topologicalSortedCodeUnits + ,max(maxDistanceFromSource) AS overallMaxDistance +FOREACH (i IN range(0, SIZE(sortedNodeIds)-1) | + SET gds.util.asNode(sortedNodeIds[i]).topologicalSortIndex = i) + WITH topologicalSortedCodeUnits + ,overallMaxDistance + UNWIND topologicalSortedCodeUnits AS sorted + RETURN coalesce(sorted.codeUnit.fqn, sorted.codeUnit.fileName, sorted.codeUnit.name) AS codeUnitName + ,sorted.codeUnit.maxDistanceFromSource AS maxDistanceFromSource + ,overallMaxDistance AS overalNumberOfBuildLevels \ No newline at end of file diff --git a/cypher/Topological_Sort/Topological_Sort_Query.cypher b/cypher/Topological_Sort/Topological_Sort_Query.cypher new file mode 100644 index 000000000..474548b3f --- /dev/null +++ b/cypher/Topological_Sort/Topological_Sort_Query.cypher @@ -0,0 +1,18 @@ +// Topological Sort to query the properties topologicalSortIndex (e.g. build order) and maxDistanceFromSource (build level) for each code unit node in topologicalSortIndex order. +// Needs graph-data-science plugin version >= 2.5.0 + +MATCH (codeUnit) + WHERE codeUnit.maxDistanceFromSource IS NOT NULL + AND codeUnit.topologicalSortIndex IS NOT NULL + AND $dependencies_projection_node IN LABELS(codeUnit) + WITH collect(codeUnit) AS codeUnits + ,max(codeUnit.maxDistanceFromSource) AS overallMaxDistanceFromSource +UNWIND codeUnits AS codeUnit +RETURN coalesce(codeUnit.fqn, codeUnit.fileName, codeUnit.name) AS codeUnitName + ,coalesce(replace(last(split(codeUnit.fileName, '/')), '.jar', ''), codeUnit.name) AS shortName + ,codeUnit.topologicalSortIndex AS topologicalSortIndex + ,codeUnit.maxDistanceFromSource AS maxDistanceFromSource + ,overallMaxDistanceFromSource + ,codeUnit.incomingDependencies AS incomingDependencies + ,codeUnit.outgoingDependencies AS outgoingDependencies +ORDER BY codeUnit.topologicalSortIndex \ No newline at end of file diff --git a/cypher/Topological_Sort/Topological_Sort_Write.cypher b/cypher/Topological_Sort/Topological_Sort_Write.cypher new file mode 100644 index 000000000..09c518554 --- /dev/null +++ b/cypher/Topological_Sort/Topological_Sort_Write.cypher @@ -0,0 +1,17 @@ +// Topological Sort to write the properties topologicalSortIndex (e.g. build order) and maxDistanceFromSource (build level) into the graph. +// Needs graph-data-science plugin version >= 2.5.0 + +CALL gds.dag.topologicalSort.stream( + $dependencies_projection + '-without-empty', { + computeMaxDistanceFromSource: true +}) YIELD nodeId, maxDistanceFromSource + WITH nodeId + ,gds.util.asNode(nodeId) AS codeUnit + ,toInteger(maxDistanceFromSource) AS maxDistanceFromSource + SET codeUnit.maxDistanceFromSource = maxDistanceFromSource + WITH collect(nodeId) AS sortedNodeIds + ,collect(codeUnit) AS sortedArtifacts + ,max(maxDistanceFromSource) AS overallMaxDistance +FOREACH (i IN range(0, SIZE(sortedArtifacts)-1) | + SET gds.util.asNode(sortedNodeIds[i]).topologicalSortIndex = i) + RETURN size(sortedArtifacts) AS numberOfArtifacts, overallMaxDistance \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/0_Delete_Projections_for_directed_artifact_dependencies.cypher b/cypher/Topological_Sort_Artifacts/0_Delete_Projections_for_directed_artifact_dependencies.cypher deleted file mode 100644 index 685f11973..000000000 --- a/cypher/Topological_Sort_Artifacts/0_Delete_Projections_for_directed_artifact_dependencies.cypher +++ /dev/null @@ -1,5 +0,0 @@ -//0 Delete Projections for directed artifact dependencies - - CALL gds.graph.drop('artifact-dependencies-directed', false) - YIELD graphName, nodeCount, relationshipCount, creationTime, modificationTime -RETURN graphName, nodeCount, relationshipCount, creationTime, modificationTime \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/0b_Delete_Projections_for_directed_artifact_dependencies.cypher b/cypher/Topological_Sort_Artifacts/0b_Delete_Projections_for_directed_artifact_dependencies.cypher deleted file mode 100644 index c621d56ac..000000000 --- a/cypher/Topological_Sort_Artifacts/0b_Delete_Projections_for_directed_artifact_dependencies.cypher +++ /dev/null @@ -1,5 +0,0 @@ -//0b Delete Projections for directed artifact dependencies - - CALL gds.graph.drop('artifact-dependencies-directed-without-empty', false) - YIELD graphName, nodeCount, relationshipCount, creationTime, modificationTime -RETURN graphName, nodeCount, relationshipCount, creationTime, modificationTime \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/1_Create_directed_Projection.cypher b/cypher/Topological_Sort_Artifacts/1_Create_directed_Projection.cypher deleted file mode 100644 index 2f2164e03..000000000 --- a/cypher/Topological_Sort_Artifacts/1_Create_directed_Projection.cypher +++ /dev/null @@ -1,9 +0,0 @@ -//1 Create directed Projection -CALL gds.graph.project('artifact-dependencies-directed', 'Artifact', 'DEPENDS_ON', - { - relationshipProperties: ['weight'], - nodeProperties: ['incomingDependencies', 'outgoingDependencies'] - } -) - YIELD graphName, nodeCount, relationshipCount -RETURN graphName, nodeCount, relationshipCount \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/2_Create_directed_subgraph_without_empty_artifacts.cypher b/cypher/Topological_Sort_Artifacts/2_Create_directed_subgraph_without_empty_artifacts.cypher deleted file mode 100644 index 85b5e1841..000000000 --- a/cypher/Topological_Sort_Artifacts/2_Create_directed_subgraph_without_empty_artifacts.cypher +++ /dev/null @@ -1,10 +0,0 @@ -//2 Create directed subgraph without empty artifacts - -CALL gds.beta.graph.project.subgraph( - 'artifact-dependencies-directed-without-empty', - 'artifact-dependencies-directed', - 'n.outgoingDependencies > 0 OR n.incomingDependencies > 0', - '*' -) - YIELD graphName, fromGraphName, nodeCount, relationshipCount, nodeFilter -RETURN graphName, fromGraphName, nodeCount, relationshipCount, nodeFilter \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/3_Topological_Sort_Artifacts.cypher b/cypher/Topological_Sort_Artifacts/3_Topological_Sort_Artifacts.cypher deleted file mode 100644 index 9454a1bbb..000000000 --- a/cypher/Topological_Sort_Artifacts/3_Topological_Sort_Artifacts.cypher +++ /dev/null @@ -1,16 +0,0 @@ -//3 Topological Sort Artifacts -//Needs graph-data-science plugin version >= 2.5.0 - -CALL gds.dag.topologicalSort.stream('artifact-dependencies-directed-without-empty',{ - computeMaxDistanceFromSource: true -}) YIELD nodeId, maxDistanceFromSource - WITH nodeId - ,gds.util.asNode(nodeId) AS artifact - ,toInteger(maxDistanceFromSource) AS maxDistanceFromSource - SET artifact.maxDistanceFromSource = maxDistanceFromSource - WITH COLLECT(nodeId) AS sortedNodeIds - ,COLLECT(artifact) AS sortedArtifacts - ,MAX(maxDistanceFromSource) AS overallMaxDistance -FOREACH (i IN RANGE(0, SIZE(sortedArtifacts)-1) | - SET gds.util.asNode(sortedNodeIds[i]).topologicalSortIndex = i) - RETURN size(sortedArtifacts) AS numberOfArtifacts, overallMaxDistance \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/3b_Topological_Sort_Artifacts_as_list.cypher b/cypher/Topological_Sort_Artifacts/3b_Topological_Sort_Artifacts_as_list.cypher deleted file mode 100644 index 6b0a9e729..000000000 --- a/cypher/Topological_Sort_Artifacts/3b_Topological_Sort_Artifacts_as_list.cypher +++ /dev/null @@ -1,21 +0,0 @@ -//3 Topological Sort Artifacts as list -//Needs graph-data-science plugin version >= 2.5.0 - -CALL gds.dag.topologicalSort.stream('artifact-dependencies-directed-without-empty',{ - computeMaxDistanceFromSource: true -}) YIELD nodeId, maxDistanceFromSource - WITH nodeId - ,gds.util.asNode(nodeId) AS artifact - ,toInteger(maxDistanceFromSource) AS maxDistanceFromSource - SET artifact.maxDistanceFromSource = maxDistanceFromSource - WITH COLLECT(nodeId) AS sortedNodeIds - ,COLLECT({artifact: artifact, maxDistanceFromSource: maxDistanceFromSource}) AS topologicalSortedArtifacts - ,MAX(maxDistanceFromSource) AS overallMaxDistance -FOREACH (i IN RANGE(0, SIZE(sortedNodeIds)-1) | - SET gds.util.asNode(sortedNodeIds[i]).topologicalSortIndex = i) - WITH topologicalSortedArtifacts - ,overallMaxDistance - UNWIND topologicalSortedArtifacts AS topologicalSortedArtifact - RETURN replace(last(split(topologicalSortedArtifact.artifact.fileName, '/')), '.jar', '') AS artifactName - ,topologicalSortedArtifact.maxDistanceFromSource AS buildLevel - ,overallMaxDistance AS overalNumberOfBuildLevels \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/4_Query_artifacts_in_topological_order.cypher b/cypher/Topological_Sort_Artifacts/4_Query_artifacts_in_topological_order.cypher deleted file mode 100644 index abda069f9..000000000 --- a/cypher/Topological_Sort_Artifacts/4_Query_artifacts_in_topological_order.cypher +++ /dev/null @@ -1,14 +0,0 @@ -//4 Artifacts in topological order - -MATCH (artifact:Artifact) -WHERE artifact.topologicalSortIndex IS NOT NULL - WITH COLLECT(artifact) AS artifacts - ,MAX(artifact.maxDistanceFromSource) AS maxBuildLevel -UNWIND artifacts AS artifact -RETURN replace(last(split(artifact.fileName, '/')), '.jar', '') AS artifactName - ,artifact.topologicalSortIndex AS topologicalSortIndex - ,artifact.maxDistanceFromSource AS buildLevel - ,maxBuildLevel - ,artifact.incomingDependencies AS incomingDependencies - ,artifact.outgoingDependencies AS outgoingDependencies -ORDER BY artifact.topologicalSortIndex \ No newline at end of file diff --git a/cypher/Topological_Sort_Artifacts/5_Experimental_Depth_First_Search_Artifacts_Index.cypher b/cypher/Topological_Sort_Artifacts/5_Experimental_Depth_First_Search_Artifacts_Index.cypher deleted file mode 100644 index 12a355c5f..000000000 --- a/cypher/Topological_Sort_Artifacts/5_Experimental_Depth_First_Search_Artifacts_Index.cypher +++ /dev/null @@ -1,46 +0,0 @@ -//5 Experimental Depth First Search Artifacts Index -//depthFirstSearchLevel is not correct - -// Depth First Search starting from a node with no incoming dependencies -MATCH (source:Artifact{fileName:'/axon-configuration-4.8.0.jar'}) - CALL gds.dfs.stream('artifact-dependencies-directed-without-empty', { - sourceNode: source -}) - YIELD nodeIds -// Generate an index to iterate through the searched nodes -UNWIND range(0, size(nodeIds)-1) AS nodeIndex - WITH nodeIndex - ,nodeIds - ,gds.util.asNodes(nodeIds) AS searchedNodes - WITH nodeIndex - ,nodeIds - ,searchedNodes - ,searchedNodes[nodeIndex] AS indexedNode - // Get the previous node to be able to detect where depth first search went back - ,CASE WHEN nodeIndex > 0 - THEN searchedNodes[nodeIndex - 1] - ELSE NULL - END AS previousNode -// Get the parent node of the indexed one - OPTIONAL MATCH (indexedNode)<-[:DEPENDS_ON]-(parent:Artifact) - WITH nodeIndex - ,nodeIds - ,searchedNodes - ,indexedNode - ,previousNode - ,COLLECT(parent.fileName) AS parentFilenames - ,(previousNode IN COLLECT(parent)) AS previousIsParent - ,COLLECT(apoc.coll.indexOf(searchedNodes[0..nodeIndex], parent)) AS previousParentIndizes - ,apoc.coll.max(COLLECT(apoc.coll.indexOf(searchedNodes[0..nodeIndex], parent))) + 1 AS topologyLevel - // Set the property 'depthFirstSearchIndex' to the index - // TODO Set 'depthFirstSearchLevel' relative to the level of the parent, not its dfs index - SET indexedNode.depthFirstSearchIndex = nodeIndex - ,indexedNode.depthFirstSearchLevel = topologyLevel -RETURN indexedNode.fileName - ,nodeIndex - ,previousNode.fileName - ,previousIsParent - ,previousParentIndizes - ,topologyLevel - ,parentFilenames -//FOREACH (i IN RANGE(0, SIZE(nodeIds)-1) | SET gds.util.asNode(nodeIds[i]).depthFirstSearchIndex = i) \ No newline at end of file diff --git a/scripts/reports/ArtifactTopologicalSortCsv.sh b/scripts/reports/ArtifactTopologicalSortCsv.sh deleted file mode 100755 index 6ff4fa0ab..000000000 --- a/scripts/reports/ArtifactTopologicalSortCsv.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash - -# Applies the Topological Sorting algorithm to order the artifacts by their artifacts (build order/level) using Graph Data Science Library of Neo4j and creates CSV reports. -# It requires an already running Neo4j graph database with already scanned analyzed artifacts. -# The reports (csv files) will be written into the sub directory reports/artifact-topology-csv. -# Note that "scripts/prepareAnalysis.sh" is required to run prior to this script. - -# Requires executeQueryFunctions.sh - -# Overrideable constants (defaults also defined in sub scripts) -REPORTS_DIRECTORY=${REPORTS_DIRECTORY:-"reports"} - -## Get this "scripts/reports" directory if not already set -# Even if $BASH_SOURCE is made for Bourne-like shells it is also supported by others and therefore here the preferred solution. -# CDPATH reduces the scope of the cd command to potentially prevent unintended directory changes. -# This way non-standard tools like readlink aren't needed. -REPORTS_SCRIPT_DIR=${REPORTS_SCRIPT_DIR:-$( CDPATH=. cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P )} -echo "artifactTopologicalSortCsv: REPORTS_SCRIPT_DIR=${REPORTS_SCRIPT_DIR}" - -# Get the "scripts" directory by taking the path of this script and going one directory up. -SCRIPTS_DIR=${SCRIPTS_DIR:-"${REPORTS_SCRIPT_DIR}/.."} # Repository directory containing the shell scripts -echo "artifactTopologicalSortCsv: SCRIPTS_DIR=${SCRIPTS_DIR}" - -# Get the "cypher" directory by taking the path of this script and going two directory up and then to "cypher". -CYPHER_DIR=${CYPHER_DIR:-"${REPORTS_SCRIPT_DIR}/../../cypher"} -echo "artifactTopologicalSortCsv: CYPHER_DIR=$CYPHER_DIR" - -# Define functions to execute a cypher query from within the given file (first and only argument) -source "${SCRIPTS_DIR}/executeQueryFunctions.sh" - -# Create report directory -REPORT_NAME="artifact-topology-csv" -FULL_REPORT_DIRECTORY="${REPORTS_DIRECTORY}/${REPORT_NAME}" -mkdir -p "${FULL_REPORT_DIRECTORY}" - -# Local Constants -TOPOLOGICAL_SORT_DIR="$CYPHER_DIR/Topological_Sort_Artifacts" - -# Preparation for Topological Sort - Create artifact dependencies projections -execute_cypher "${TOPOLOGICAL_SORT_DIR}/0_Delete_Projections_for_directed_artifact_dependencies.cypher" -execute_cypher "${TOPOLOGICAL_SORT_DIR}/0b_Delete_Projections_for_directed_artifact_dependencies.cypher" -execute_cypher "${TOPOLOGICAL_SORT_DIR}/1_Create_directed_Projection.cypher" -execute_cypher "${TOPOLOGICAL_SORT_DIR}/2_Create_directed_subgraph_without_empty_artifacts.cypher" - -# Topological Sort Artifacts -execute_cypher "${TOPOLOGICAL_SORT_DIR}/3_Topological_Sort_Artifacts.cypher" - -# Query topological sorted Artifacts (CSV) -execute_cypher "${TOPOLOGICAL_SORT_DIR}/4_Query_artifacts_in_topological_order.cypher" > "${FULL_REPORT_DIRECTORY}/TopologicalSortedArtifacts.csv" \ No newline at end of file diff --git a/scripts/reports/CentralityCsv.sh b/scripts/reports/CentralityCsv.sh index 74fdd5ce6..17a8cbeb3 100755 --- a/scripts/reports/CentralityCsv.sh +++ b/scripts/reports/CentralityCsv.sh @@ -318,7 +318,7 @@ TYPE_NODE="dependencies_projection_node=Type" TYPE_WEIGHT="dependencies_projection_weight_property=weight" # Type Centrality -echo "centralityCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Processing package dependencies..." +echo "centralityCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Processing type dependencies..." createProjection "${TYPE_PROJECTION}" "${TYPE_NODE}" "${TYPE_WEIGHT}" time centralityWithPageRank "${TYPE_PROJECTION}" "${TYPE_NODE}" "${TYPE_WEIGHT}" time centralityWithArticleRank "${TYPE_PROJECTION}" "${TYPE_NODE}" "${TYPE_WEIGHT}" diff --git a/scripts/reports/TopologicalSortCsv.sh b/scripts/reports/TopologicalSortCsv.sh new file mode 100755 index 000000000..42d26c4d8 --- /dev/null +++ b/scripts/reports/TopologicalSortCsv.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +# Applies the Topological Sorting algorithm for directed acyclic graphs (DAG) to order code units by their dependencies +# using Graph Data Science Library of Neo4j and creates CSV reports. +# This is useful to get the build order and build levels for modules that depend on each other. +# It requires an already running Neo4j graph database with already scanned and analyzed artifacts. +# The reports (csv files) will be written into the sub directory reports/topology-csv. +# Note that "scripts/prepareAnalysis.sh" is required to run prior to this script. + +# Requires executeQueryFunctions.sh + +# Overrideable constants (defaults also defined in sub scripts) +REPORTS_DIRECTORY=${REPORTS_DIRECTORY:-"reports"} + +## Get this "scripts/reports" directory if not already set +# Even if $BASH_SOURCE is made for Bourne-like shells it is also supported by others and therefore here the preferred solution. +# CDPATH reduces the scope of the cd command to potentially prevent unintended directory changes. +# This way non-standard tools like readlink aren't needed. +REPORTS_SCRIPT_DIR=${REPORTS_SCRIPT_DIR:-$( CDPATH=. cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P )} +echo "topologicalSortCsv: REPORTS_SCRIPT_DIR=${REPORTS_SCRIPT_DIR}" + +# Get the "scripts" directory by taking the path of this script and going one directory up. +SCRIPTS_DIR=${SCRIPTS_DIR:-"${REPORTS_SCRIPT_DIR}/.."} # Repository directory containing the shell scripts +echo "topologicalSortCsv: SCRIPTS_DIR=${SCRIPTS_DIR}" + +# Get the "cypher" directory by taking the path of this script and going two directory up and then to "cypher". +CYPHER_DIR=${CYPHER_DIR:-"${REPORTS_SCRIPT_DIR}/../../cypher"} +echo "topologicalSortCsv: CYPHER_DIR=$CYPHER_DIR" + +# Define functions to execute a cypher query from within the given file (first and only argument) +source "${SCRIPTS_DIR}/executeQueryFunctions.sh" + +# Create report directory +REPORT_NAME="topology-csv" +FULL_REPORT_DIRECTORY="${REPORTS_DIRECTORY}/${REPORT_NAME}" +mkdir -p "${FULL_REPORT_DIRECTORY}" + +# Topological Sort Preparation +# Selects the nodes and relationships for the algorithm and creates an in-memory projection. +# Nodes without incoming and outgoing dependencies (zero degree) will be filtered out with a subgraph. +# +# Required Parameters: +# - dependencies_projection=... +# Name prefix for the in-memory projection name for dependencies. Example: "package" +# - dependencies_projection_node=... +# Label of the nodes that will be used for the projection. Example: "Package" +# - dependencies_projection_weight_property=... +# Name of the node property that contains the dependency weight. Example: "weight" +createProjection() { + local PROJECTION_CYPHER_DIR="$CYPHER_DIR/Dependencies_Projection" + + execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_1_Delete_Projection.cypher" "${@}" + execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_2_Delete_Subgraph.cypher" "${@}" + execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_3_Create_Projection.cypher" "${@}" + execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_5_Create_Subgraph.cypher" "${@}" +} + +# Apply the algorithm "Topological Sort". +# +# Required Parameters: +# - dependencies_projection=... +# Name prefix for the in-memory projection name for dependencies. Example: "package" +# - dependencies_projection_node=... +# Label of the nodes that will be used for the projection. Example: "Package" +# - dependencies_projection_weight_property=... +# Name of the node property that contains the dependency weight. Example: "weight" +topologicalSort() { + local TOPOLOGICAL_SORT_DIR="$CYPHER_DIR/Topological_Sort" + + # Update Graph (node properties) + execute_cypher "${TOPOLOGICAL_SORT_DIR}/Topological_Sort_Write.cypher" "${@}" + + # Stream to CSV + local nodeLabel + nodeLabel=$( extractQueryParameter "dependencies_projection_node" "${@}" ) + execute_cypher "${TOPOLOGICAL_SORT_DIR}/Topological_Sort_Query.cypher" "${@}" > "${FULL_REPORT_DIRECTORY}/${nodeLabel}_Topolical_Sort.csv" +} + +# --------------------------------------------------------------- + +# Artifact Query Parameters +ARTIFACT_PROJECTION="dependencies_projection=artifact-topology" +ARTIFACT_NODE="dependencies_projection_node=Artifact" +ARTIFACT_WEIGHT="dependencies_projection_weight_property=weight" + +# Artifact Topology +echo "topologicalSortCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Processing artifact dependencies..." +createProjection "${ARTIFACT_PROJECTION}" "${ARTIFACT_NODE}" "${ARTIFACT_WEIGHT}" +time topologicalSort "${ARTIFACT_PROJECTION}" "${ARTIFACT_NODE}" "${ARTIFACT_WEIGHT}" + +# --------------------------------------------------------------- + +# Package Query Parameters +PACKAGE_PROJECTION="dependencies_projection=package-topology" +PACKAGE_NODE="dependencies_projection_node=Package" +PACKAGE_WEIGHT="dependencies_projection_weight_property=weight25PercentInterfaces" + +# Package Topology +echo "topologicalSortCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Processing package dependencies..." +createProjection "${PACKAGE_PROJECTION}" "${PACKAGE_NODE}" "${PACKAGE_WEIGHT}" +time topologicalSort "${PACKAGE_PROJECTION}" "${PACKAGE_NODE}" "${PACKAGE_WEIGHT}" + +# --------------------------------------------------------------- + +# Type Query Parameters +TYPE_PROJECTION="dependencies_projection=type-topology" +TYPE_NODE="dependencies_projection_node=Type" +TYPE_WEIGHT="dependencies_projection_weight_property=weight" + +# Type Topology +echo "topologicalSortCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Processing type dependencies..." +createProjection "${TYPE_PROJECTION}" "${TYPE_NODE}" "${TYPE_WEIGHT}" +time topologicalSort "${TYPE_PROJECTION}" "${TYPE_NODE}" "${TYPE_WEIGHT}" + +echo "topologicalSortCsv: $(date +'%Y-%m-%dT%H:%M:%S%z') Successfully finished" \ No newline at end of file