abide_dev_utils 0.9.5 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbideDevUtils
4
+ module XCCDF
5
+ module Parser
6
+ module Objects
7
+ # Methods for interacting with objects that have numbers (e.g. Group, Rule, etc.)
8
+ # This module is included in the Benchmark class and Group / Rule classes
9
+ module NumberedObject
10
+ include ::Comparable
11
+
12
+ def <=>(other)
13
+ return 0 if number_eq(number, other.number)
14
+ return 1 if number_gt(number, other.number)
15
+ return -1 if number_lt(number, other.number)
16
+ end
17
+
18
+ def number_eq(this_num, other_num)
19
+ this_num == other_num
20
+ end
21
+
22
+ def number_parent_of?(this_num, other_num)
23
+ return false if number_eq(this_num, other_num)
24
+
25
+ # We split the numbers into parts and compare the resulting arrays
26
+ num1_parts = this_num.to_s.split('.')
27
+ num2_parts = other_num.to_s.split('.')
28
+ # For this_num to be a parent of other_num, the number of parts in
29
+ # this_num must be less than the number of parts in other_num.
30
+ # Additionally, each part of this_num must be equal to the parts of
31
+ # other_num at the same index.
32
+ # Example: this_num = '1.2.3' and other_num = '1.2.3.4'
33
+ # In this case, num1_parts = ['1', '2', '3'] and num2_parts = ['1', '2', '3', '4']
34
+ # So, this_num is a parent of other_num because at indexes 0, 1, and 2
35
+ # of num1_parts and num2_parts, the parts are equal.
36
+ num1_parts.length < num2_parts.length &&
37
+ num2_parts[0..(num1_parts.length - 1)] == num1_parts
38
+ end
39
+
40
+ def number_child_of?(this_num, other_num)
41
+ number_parent_of?(other_num, this_num)
42
+ end
43
+
44
+ def number_gt(this_num, other_num)
45
+ return false if number_eq(this_num, other_num)
46
+ return true if number_parent_of?(this_num, other_num)
47
+
48
+ num1_parts = this_num.to_s.split('.')
49
+ num2_parts = other_num.to_s.split('.')
50
+ num1_parts.zip(num2_parts).each do |num1_part, num2_part|
51
+ next if num1_part == num2_part # we skip past equal parts
52
+
53
+ # If num1_part is nil that means that we've had equal numbers so far.
54
+ # Therfore, this_num is greater than other num because of the
55
+ # hierarchical nature of the numbers.
56
+ # Example: this_num = '1.2' and other_num = '1.2.3'
57
+ # In this case, num1_part is nil and num2_part is '3'
58
+ # So, this_num is greater than other_num
59
+ return true if num1_part.nil?
60
+ # If num2_part is nil that means that we've had equal numbers so far.
61
+ # Therfore, this_num is less than other num because of the
62
+ # hierarchical nature of the numbers.
63
+ # Example: this_num = '1.2.3' and other_num = '1.2'
64
+ # In this case, num1_part is '3' and num2_part is nil
65
+ # So, this_num is less than other_num
66
+ return false if num2_part.nil?
67
+
68
+ return num1_part.to_i > num2_part.to_i
69
+ end
70
+ end
71
+
72
+ def number_lt(this_num, other_num)
73
+ number_gt(other_num, this_num)
74
+ end
75
+
76
+ # This method will recursively walk the tree to find the first
77
+ # child, grandchild, etc. that has a number method and returns the
78
+ # matching number.
79
+ # @param [String] number The number to find in the tree
80
+ # @return [Group] The first child, grandchild, etc. that has a matching number
81
+ # @return [Rule] The first child, grandchild, etc. that has a matching number
82
+ # @return [nil] If no child, grandchild, etc. has a matching number
83
+ def search_children_by_number(number)
84
+ find_children_that_respond_to(:number).find do |child|
85
+ if number_eq(child.number, number)
86
+ child
87
+ elsif number_parent_of?(child.number, number)
88
+ # We recursively search the child for its child with the number
89
+ # if our number is a parent of the child's number
90
+ return child.search_children_by_number(number)
91
+ end
92
+ end
93
+ end
94
+
95
+ def find_child_by_number(number)
96
+ find_children_that_respond_to(:number).find do |child|
97
+ number_eq(child.number, number)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end