@@ -21,70 +21,62 @@ class CheckovResultsComparatorGenerator {
2121 .thenComparing(generateNameComparator(CheckovResultProperty .NAME ))
2222 }
2323
24- fun generateResourceComparator (): Comparator <BaseCheckovResult > {
24+ private fun generateResourceComparator (): Comparator <BaseCheckovResult > {
2525 return Comparator { result1, result2 ->
2626
2727 if (result1.category != Category .SECRETS && result2.category != Category .SECRETS ) {
28- return @Comparator compareResultsByName (CheckovResultProperty .RESOURCE , result1, result2)
28+ return @Comparator generateNameComparator (CheckovResultProperty .RESOURCE ).compare( result1, result2)
2929 }
3030
3131 return @Comparator result1.category.compareTo(result2.category)
3232 }
3333 }
3434
35- fun generateNameComparator (property : CheckovResultProperty ): Comparator <BaseCheckovResult > {
35+ private fun generateNameComparator (property : CheckovResultProperty ): Comparator <BaseCheckovResult > {
3636 return Comparator { result1, result2 ->
37- return @Comparator compareResultsByName(property, result1, result2)
37+ val name1 = extractNameByProperty(property, result1)
38+ val name2 = extractNameByProperty(property, result2)
39+ return @Comparator try {
40+ getAlphanumericComparator().compare(name1, name2)
41+ } catch (e: Exception ) {
42+ LOG .warn(" Error while comparing ${property.name.lowercase()} " , e)
43+ name1.compareTo(name2, true )
44+ }
3845 }
3946 }
4047
41- fun compareResultsByName (property : CheckovResultProperty , result1 : BaseCheckovResult , result2 : BaseCheckovResult ): Int {
42-
43- val name1 = extractNameByProperty(property, result1)
44- val name2 = extractNameByProperty(property, result2)
45- try {
46- if (name1.equals(name2, true ))
47- return 0
48+ // compare file names alphanumerically and also account for special characters like " ' / : . - _
49+ private fun getAlphanumericComparator (): Comparator <String > {
50+ return Comparator { a, b ->
51+ val regex = Regex (" (\\ d+)|(\\ D+)" )
52+ val partsA = regex.findAll(a).map { it.value }
53+ val partsB = regex.findAll(b).map { it.value }
4854
49- val regex = Regex ( """ \d+|\D+ """ )
55+ val minSize = minOf(partsA.count(), partsB.count() )
5056
51- val tokens1: List <String > = regex.findAll(name1).map { it.groupValues.first() }.toList()
52- val tokens2: List <String > = regex.findAll(name2).map { it.groupValues.first() }.toList()
57+ for (i in 0 until minSize) {
58+ val partA = partsA.elementAt(i)
59+ val partB = partsB.elementAt(i)
5360
54- if (tokens1.isEmpty() && tokens2.isEmpty())
55- return name1.compareTo(name2, true )
61+ val result = when {
62+ partA.matches(" \\ d+" .toRegex()) && partB.matches(" \\ d+" .toRegex()) -> {
63+ partA.toBigInteger().compareTo(partB.toBigInteger())
64+ }
5665
57- if (tokens1.size == 1 || tokens2.size == 1 )
58- return name1.compareTo(name2, true )
66+ partA == partB -> 0
67+ else -> partA.compareTo(partB, ignoreCase = true )
68+ }
5969
60- var i = 0
61- while (i < tokens1.size && i < tokens2.size && tokens1[i].equals(tokens2[i], true )) {
62- i ++
70+ if (result ! = 0 ) {
71+ return @Comparator result
72+ }
6373 }
6474
65- if (i >= tokens1.size)
66- return 1
67- else if (i >= tokens2.size)
68- return - 1
69-
70-
71- if (tokens1[i].isEmpty() || tokens2[i].isEmpty())
72- LOG .info(" empty..." )
73- val numberStr1 = tokens1[i].replace(" \\ D" .toRegex(), " " )
74- val numberStr2 = tokens2[i].replace(" \\ D" .toRegex(), " " )
75-
76- if (numberStr1.isEmpty() || numberStr2.isEmpty())
77- return name1.compareTo(name2, true )
78-
79- return (numberStr1.toLong() - numberStr2.toLong()).toInt()
80- } catch (e: Exception ) {
81- LOG .warn(" Error while comparing ${property.name.lowercase()} " , e)
82- return name1.compareTo(name2, true )
75+ return @Comparator partsA.count().compareTo(partsB.count())
8376 }
84-
8577 }
8678
87- fun extractNameByProperty (property : CheckovResultProperty , checkovResult : BaseCheckovResult ): String {
79+ private fun extractNameByProperty (property : CheckovResultProperty , checkovResult : BaseCheckovResult ): String {
8880 return when (property) {
8981 CheckovResultProperty .FILE_PATH -> {
9082 checkovResult.filePath
0 commit comments