Skip to content
This repository was archived by the owner on Nov 6, 2024. It is now read-only.

Commit 4da4466

Browse files
authored
Merge pull request #11 from bridgecrewio/fix_comparator
fix comparator
2 parents fb1d30d + f8159cc commit 4da4466

File tree

1 file changed

+33
-41
lines changed

1 file changed

+33
-41
lines changed

src/main/kotlin/com/bridgecrew/services/CheckovResultsComparatorGenerator.kt

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)