Passed
Branch graph-look (6770c2)
by Jan
01:38
created

graph.oval_graph.OvalNode.createNodesInRows()   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nop 2
crap 2
1
'''
2
    Module for create ID
3
'''
4 1
import graph.xml_parser
5 1
import graph.evaluate
6 1
import uuid
7 1
import collections
8
9
'''
10
    Modules form my lib
11
'''
12
13
'''
14
    This module contains methods and classes for
15
    constructing and controlling an oval tree.
16
'''
17
18
19 1
class OvalNode(object):
20
    '''
21
    The OvalNode object is one node of oval graph.
22
23
    Args:
24
        node_id (str|int): identifies node
25
        input_node_type (str): type of node (value or operator)
26
        input_value (str): value of node
27
        children ([OvalNode]): array of children of node
28
29
    Attributes:
30
        node_id (str): id of node
31
        node_type (str): type node
32
        value (str): value of node for operator and,
33
        or, one etc... and for value true, false, error etc...
34
        children ([OvalNode]): children of node
35
    '''
36
37 1
    def __init__(self, node_id, input_node_type, input_value, children=None):
38 1
        self.node_id = node_id
39 1
        value = input_value.lower()
40 1
        node_type = input_node_type.lower()
41 1
        if node_type == "value" or node_type == "operator":
42 1
            self.node_type = node_type
43
        else:
44 1
            raise ValueError("err- unknown type")
45 1
        allowed_operators = [
46
            "or",
47
            "and",
48
            "one",
49
            "xor"]
50 1
        allowed_values = [
51
            "true",
52
            "false",
53
            "error",
54
            "unknown",
55
            "noteval",
56
            "notappl"]
57 1
        if self.node_type == "value":
58 1
            if value in allowed_values:
59 1
                self.value = value
60
            else:
61 1
                raise ValueError("err- unknown value")
62 1
        if self.node_type == "operator":
63 1
            if value in allowed_operators:
64 1
                self.value = value
65
            else:
66 1
                raise ValueError("err- unknown operator")
67 1
        self.children = []
68 1
        if children is not None:
69 1
            for child in children:
70 1
                self.add_child(child)
71
        else:
72 1
            if self.node_type == "operator":
73 1
                raise ValueError('err- OR, XOR, ONE, AND have child!')
74
75 1
    def __repr__(self):
76 1
        return self.value
77
78 1
    def add_child(self, node):
79 1
        if self.node_type == "operator":
80 1
            assert isinstance(node, OvalNode)
81 1
            self.children.append(node)
82
        else:
83 1
            self.children = None
84 1
            raise ValueError(
85
                "err- true, false, error, unknown. noteval, notappl have not child!")
86
87 1
    def evaluate_tree(self):
88 1
        result = {
89
            'true_cnt': 0,
90
            'false_cnt': 0,
91
            'error_cnt': 0,
92
            'unknown_cnt': 0,
93
            'noteval_cnt': 0,
94
            'notappl_cnt': 0
95
        }
96
97 1
        for child in self.children:
98 1
            if child.value == 'true':
99 1
                result['true_cnt'] += 1
100 1
            elif child.value == 'false':
101 1
                result['false_cnt'] += 1
102 1
            elif child.value == 'error':
103 1
                result['error_cnt'] += 1
104 1
            elif child.value == 'unknown':
105 1
                result['unknown_cnt'] += 1
106 1
            elif child.value == 'noteval':
107 1
                result['noteval_cnt'] += 1
108 1
            elif child.value == 'notappl':
109 1
                result['notappl_cnt'] += 1
110
            else:
111 1
                if self.node_type == "operator":
112 1
                    result[child.evaluate_tree() + "_cnt"] += 1
113
114 1
        if result['notappl_cnt'] > 0\
115
                and graph.evaluate.eq_zero(result, 'false_cnt')\
116
                and graph.evaluate.error_unknown_noteval_eq_zero(result)\
117
                and graph.evaluate.eq_zero(result, 'true_cnt'):
118 1
            return "notappl"
119
        else:
120 1
            if self.value == "or":
121 1
                return graph.evaluate.oval_operator_or(result)
122 1
            elif self.value == "and":
123 1
                return graph.evaluate.oval_operator_and(result)
124 1
            elif self.value == "one":
125 1
                return graph.evaluate.oval_operator_one(result)
126 1
            elif self.value == "xor":
127 1
                return graph.evaluate.oval_operator_xor(result)
128
129 1
    def save_tree_to_dict(self):
130 1
        if not self.children:
131 1
            return {
132
                'node_id': self.node_id,
133
                'type': self.node_type,
134
                'value': self.value,
135
                'child': None
136
            }
137 1
        return {
138
            'node_id': self.node_id,
139
            'type': self.node_type,
140
            'value': self.value,
141
            'child': [child.save_tree_to_dict() for child in self.children]
142
        }
143
144 1
    def find_node_with_ID(self, node_id):
145 1
        if self.node_id == node_id:
146 1
            return self
147
        else:
148 1
            for child in self.children:
149 1
                if child.node_id == node_id:
150 1
                    return child
151 1
            for child in self.children:
152 1
                if child.children != []:
153 1
                    return child.find_node_with_ID(node_id)
154
155 1
    def add_to_tree(self, node_id, newNode):
156 1
        self.find_node_with_ID(node_id).add_child(newNode)
157
158 1
    def change_tree_value(self, node_id, value):
159 1
        self.find_node_with_ID(node_id).value = value
160
161
    # Methods for interpreting oval tree with SigmaJS
162
163 1
    def _create_node(self, x, y):
164
        # print(self.evaluate_tree(),self.value)
165 1
        if self.value == 'true':
166 1
            return {
167
                'id': self.node_id,
168
                'label': self.value,
169
                'label': str(self.node_id).replace(
170
                    'xccdf_org.ssgproject.content_rule_',
171
                    '').replace(
172
                    'oval:ssg-',
173
                    '').replace(
174
                    ':def:1',
175
                    '').replace(
176
                    ':tst:1',
177
                    '').replace('test_', ''),
178
                'url': 'null',
179
                'text': 'null',
180
                'title': self.node_id,
181
                "x": x,
182
                "y": y,
183
                "size": 3,
184
                "color": '#00ff00'}
185 1
        elif self.value == 'false':
186 1
            return {
187
                'id': self.node_id,
188
                'label': self.value,
189
                'label': str(self.node_id).replace(
190
                    'xccdf_org.ssgproject.content_rule_',
191
                    '').replace(
192
                    'oval:ssg-',
193
                    '').replace(
194
                    ':def:1',
195
                    '').replace(
196
                    ':tst:1',
197
                    '').replace('test_', ''),
198
                'url': 'null',
199
                'text': 'null',
200
                'title': self.node_id,
201
                "x": x,
202
                "y": y,
203
                "size": 3,
204
                "color": '#ff0000'}
205
        else:
206 1
            if self.evaluate_tree() == 'true':
207 1
                return {
208
                    'id': self.node_id,
209
                    'label': self.value,
210
                    'url': 'null',
211
                    'text': 'null',
212
                    'title': self.node_id,
213
                    "x": x,
214
                    "y": y,
215
                    "size": 3,
216
                    "color": '#00ff00'
217
                }
218 1
            elif self.evaluate_tree() == 'false':
219 1
                return {
220
                    'id': self.node_id,
221
                    'label': self.value,
222
                    'url': 'null',
223
                    'text': 'null',
224
                    'title': self.node_id,
225
                    "x": x,
226
                    "y": y,
227
                    "size": 3,
228
                    "color": '#ff0000'
229
                }
230
            else:
231 1
                return {
232
                    'id': self.node_id,
233
                    'label': self.value,
234
                    'url': 'null',
235
                    'text': 'null',
236
                    'title': str(self.node_id) + ' ' + self.value,
237
                    "x": x,
238
                    "y": y,
239
                    "size": 3,
240
                    "color": '#000000'
241
                }
242
243 1
    def _create_edge(self, id_source, id_target):
244 1
        return {
245
            "id": str(uuid.uuid4()),
246
            "source": id_source,
247
            "target": id_target
248
        }
249
250 1
    def create_list_of_id(self, array_of_ids=None):
251 1
        if array_of_ids is None:
252 1
            array_of_ids = []
253 1
            array_of_ids.append(self.node_id)
254 1
        for child in self.children:
255 1
            if child.node_type != "operator":
256 1
                array_of_ids.append(child.node_id)
257
            else:
258 1
                array_of_ids.append(child.node_id)
259 1
                child.create_list_of_id(array_of_ids)
260 1
        return array_of_ids
261
262 1
    def _remove_Duplication(self, graph_data):
263 1
        array_of_ids = self.create_list_of_id()
264 1
        out = dict(nodes=[], edges=graph_data['edges'])
265 1
        duplicate_ids = [item for item, count in collections.Counter(
266
            array_of_ids).items() if count > 1]
267
268 1
        for node in graph_data['nodes']:
269 1
            if node['id'] not in duplicate_ids:
270 1
                out['nodes'].append(node)
271
272 1
        for id in duplicate_ids:
273 1
            for node in graph_data['nodes']:
274 1
                if node['id'] == id:
275 1
                    out['nodes'].append(node)
276 1
                    break
277 1
        return out
278
279 1
    def _fix_graph(self, preprocessed_graph_data):
280 1
        for node in preprocessed_graph_data['nodes']:
281 1
            for node1 in preprocessed_graph_data['nodes']:
282 1
                if node['x'] == node1['x'] and node['y'] == node1['y']:
283 1
                    node['x'] = node['x'] - 1
284 1
        return preprocessed_graph_data
285
286 1
    def _help_to_sigma_dict(self, x, y, preprocessed_graph_data=None):
287 1
        if preprocessed_graph_data is None:
288 1
            preprocessed_graph_data = dict(nodes=[], edges=[])
289 1
            preprocessed_graph_data['nodes'].append(self._create_node(x, y))
290 1
        y_row = y + 1
291 1
        x_row = x
292 1
        for node in self.children:
293 1
            preprocessed_graph_data['nodes'].append(
294
                node._create_node(x_row, y_row))
295 1
            preprocessed_graph_data['edges'].append(
296
                node._create_edge(self.node_id, node.node_id))
297 1
            x_row = x_row + 1
298 1
            if node.children is not None:
299 1
                preprocessed_graph_data = node._help_to_sigma_dict(
300
                    x_row + 1, y_row + 1, preprocessed_graph_data)
301 1
        return self._fix_graph(preprocessed_graph_data)
302
303 1
    def countMaxY(self, out):
304 1
        maxY = 0
305
306 1
        for node in out['nodes']:
307 1
            if(maxY < node['y']):
308 1
                maxY = node['y']
309 1
        return maxY
310
311 1
    def createNodesInRows(self, rows):
312 1
        nodesInRows = dict()
313
314 1
        for i in range(rows + 1):
315 1
            nodesInRows[i] = []
316 1
        return nodesInRows
317
318 1
    def pushNodesToNodesInRow(self, out, nodesInRows):
319 1
        for node in out['nodes']:
320 1
            nodesInRows[node['y']].append(node)
321
322 1
    def removeEmptyRows(self, nodesInRows,maxY):
323 1
        for row in range(maxY + 1):
324 1
            if not nodesInRows[row]:
325 1
                del nodesInRows[row]
326
327 1
    def moveRows(self, nodesInRows):
328 1
        count = 0
329 1
        nodesInRows1 = dict()
330
331 1
        for row in nodesInRows:
332 1
            nodesInRows1[count] = nodesInRows[row]
333 1
            for node in nodesInRows1[count]:
334 1
                node['y'] = count
335 1
            count += 1
336 1
        return nodesInRows1
337
338 1
    def createPositions(self, nodesInRows):
339 1
        for row in nodesInRows:
340 1
            lenOfRow = len(nodesInRows[row])
341 1
            if lenOfRow > 1:
342 1
                if (lenOfRow % 2) == 1:
343 1
                    lenOfRow += 1
344 1
                positions = []
345
346 1
                for i in range((int(-(lenOfRow / 2))) * 2,
347
                               (int(+(lenOfRow / 2)) + 1) * 2, 2):
348 1
                    positions.append(i)
349
350 1
                if lenOfRow == 2:
351 1
                    positions.remove(0)
352
                
353 1
                if len(nodesInRows[row]) < len(positions):
354 1
                    positions.pop()
355 1
                    if len(nodesInRows[row]) < len(positions):
356 1
                        positions.pop(0)
357
358 1
                count1 = 0
359
360 1
                for pos in positions:
361 1
                    nodesInRows[row][count1]['x'] = pos
362 1
                    count1 += 1
363
            else:
364 1
                nodesInRows[row][0]['x'] = 0
365 1
        return positions
0 ignored issues
show
introduced by
The variable positions does not seem to be defined in case the for loop on line 339 is not entered. Are you sure this can never be the case?
Loading history...
366 1
    def convertNodesInRowsToNodes(self, nodesInRows):
367 1
        nodes = []
368 1
        for row in nodesInRows:
369 1
            for node in nodesInRows[row]:
370 1
                nodes.append(node)
371 1
        return nodes
372
373 1
    def center_graph(self, out):
374 1
        maxY = self.countMaxY(out)
375 1
        nodesInRows = self.createNodesInRows(maxY)
376 1
        self.pushNodesToNodesInRow(out, nodesInRows)
377 1
        self.removeEmptyRows(nodesInRows, maxY)
378 1
        nodesInRows = self.moveRows(nodesInRows)
379
380 1
        positions=self.createPositions(nodesInRows)
381
        
382 1
        x = 0.6
383 1
        upAndDown = True
384 1
        down = False
385 1
        downRow = False
386 1
        saveX = 0
387
388 1
        for row in nodesInRows:
389 1
            for node in nodesInRows[row]:
390 1
                if len(node['label']) > 6 and len(node['label']) < 40:
391 1
                    if upAndDown:
392 1
                        node['y'] = node['y'] + (0.6 * x)
393 1
                        upAndDown = False
394
                    else:
395 1
                        upAndDown = True
396 1
                elif len(node['label']) > 30:
397 1
                    node['y'] = node['y'] + (0.6 * x)
398 1
                    x += 0.6
399 1
                    saveX = x
400 1
                    down = True
401
                else:
402 1
                    if down:
403 1
                        node['y'] = node['y'] + (0.6 * saveX)
404
405 1
                    if downRow:
406 1
                        node['y'] = node['y'] + (0.6 * saveX) - 0.7
407 1
            if down:
408 1
                down = False
409 1
                downRow = True
410 1
            x = 0.6
411
        
412 1
        out['nodes'] = self.convertNodesInRowsToNodes(nodesInRows)
413
414 1
        return out
415
416 1
    def to_sigma_dict(self, x, y):
417 1
        return self.center_graph(
418
            self._remove_Duplication(
419
                self._help_to_sigma_dict(
420
                    x, y)))
421
422
423 1
def build_nodes_form_xml(xml_src, rule_id):
424 1
    parser = graph.xml_parser.xml_parser(xml_src)
425 1
    return parser.get_oval_graph(rule_id)
426
427
428 1
def restore_dict_to_tree(dict_of_tree):
429 1
    if dict_of_tree["child"] is None:
430 1
        return OvalNode(
431
            dict_of_tree["node_id"],
432
            dict_of_tree["type"],
433
            dict_of_tree["value"])
434 1
    return OvalNode(
435
        dict_of_tree["node_id"],
436
        dict_of_tree["type"],
437
        dict_of_tree["value"],
438
        [restore_dict_to_tree(i) for i in dict_of_tree["child"]])
439