added spying on overall OFJ backpressure on/off operations
[openflowplugin.git] / test-scripts / tools / xml_parser_tools.py
1 '''
2 Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3
4 This program and the accompanying materials are made available under the
5 terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 and is available at http://www.eclipse.org/legal/epl-v10.html
7
8 Created on May 21, 2014
9
10 @author: <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
11 '''
12 from xml.dom.minidom import Element
13
14
15 KEY_NOT_FOUND = '<KEY_NOT_FOUND>'  # KeyNotFound for dictDiff
16
17 class XMLtoDictParserTools():
18
19
20     @staticmethod
21     def parseDOM_ToDict( node, returnedDict = None, ignoreList = [] ):
22         """
23         Return Dictionary representation of the xml DOM Element.
24         Repeated tags are put to the array sorted by key (id or order)
25         otherwise is the value represented by tag key name.
26         @param node: DOM Element 
27         @param returnedDict : dictionary (default value None)
28         @param ignereList : list of ignored tags for the xml DOM Element
29                             (default value is empty list)
30         @return: dict representation for the input DOM Element
31         """
32         returnedDict = {} if returnedDict is None else returnedDict
33         if ( node.nodeType == Element.ELEMENT_NODE ) :
34             nodeKey = ( node.localName ).encode( 'utf-8', 'ignore' )
35             if nodeKey not in ignoreList :
36                 if node.childNodes is not None :
37                     childDict = {}
38                     for child in node.childNodes :
39                         if child.nodeType == Element.TEXT_NODE :
40                             nodeValue = ( child.nodeValue ).encode( 'utf-8', 'ignore' )
41                             if ( len( nodeValue.strip( ' \t\n\r' ) ) ) > 0 :
42                                 XMLtoDictParserTools.addDictValue( returnedDict, nodeKey, nodeValue )
43                                 nodeKey = None
44                                 break
45                         elif child.nodeType == Element.ELEMENT_NODE :
46                             childDict = XMLtoDictParserTools.parseDOM_ToDict( child, childDict, ignoreList )
47
48                     XMLtoDictParserTools.addDictValue( returnedDict, nodeKey, childDict )
49
50         return returnedDict
51
52
53     @staticmethod
54     def addDictValue( m_dict, key, value ):
55         '''
56         Method add key and value to input dict. If the dict 
57         contain the key, we are creating array for the values 
58         and sort array by sort_key ('order' tag or '*-id' tag )
59         @param m_dict: dictionary for key and value
60         @param key: dict key
61         @param value: dict value
62         '''
63         if key is not None :
64             if ( isinstance( value, str ) ) :
65                 # we need to predict possible differences
66                 # for same value in upper or lower case
67                 value = value.lower()
68             if key not in m_dict :
69                 m_dict[key] = value
70             else :
71                 exist_value = m_dict.get( key )
72                 if ( type( exist_value ) is dict ) :
73                     list_values = [exist_value, value]
74                     key_for_sort = XMLtoDictParserTools.searchKey( exist_value )
75                     if key_for_sort is not None :
76                         list_values = sorted( list_values, key = lambda k: k[key_for_sort] )
77                     m_dict[key] = list_values
78                 elif ( isinstance( exist_value, list ) ) :
79                     exist_value.append( value )
80                     list_values = exist_value
81                     key_for_sort = XMLtoDictParserTools.searchKey( value )
82                     if key_for_sort is not None :
83                         list_values = sorted( list_values, key = lambda k: k[key_for_sort] )
84                     m_dict[key] = list_values
85                 else :
86                     m_dict[key] += value
87
88
89     @staticmethod
90     def searchKey( dictionary ):
91         """
92         Return an order key for the array ordering. OF_13
93         allows only two possible kind of the order keys
94         'order' or '*-id'
95         @param dictionary: dictionary with data
96         @return: the array order key 
97         """
98         subKeyStr = ['-id', 'order']
99         for substr in subKeyStr :
100             for key in dictionary:
101                 if key == substr :
102                     return key
103                 elif key.endswith( substr ):
104                     return key
105         return None
106
107
108     @staticmethod
109     def getDifferenceDict( original_dict, responded_dict ):
110         """ 
111         Return a dict of keys that differ with another config object.  If a value is
112         not found in one fo the configs, it will be represented by KEY_NOT_FOUND.
113         @param original_dict:   Fist dictionary to diff.
114         @param responded_dict:  Second dictionary to diff.
115         @return diff:   Dict of Key => (original_dict.val, responded_dict.val)
116                         Dict of Key => (original_key, KEY_NOT_FOUND)
117                         Dict of Key => (KEY_NOT_FOUND, original_key)
118         """
119         diff = {}
120         # Check all keys in original_dict dict
121         for key in original_dict.keys():
122             if ( not responded_dict.has_key( key ) ):
123                 # missing key in responded dict
124                 diff[key] = ( key, KEY_NOT_FOUND )
125             # check values of the dictionaries
126             elif ( original_dict[key] != responded_dict[key] ):
127                 # values are not the same #
128
129                 orig_dict_val = original_dict[key]
130                 resp_dict_val = responded_dict[key]
131
132                 # check value is instance of dictionary
133                 if isinstance( orig_dict_val, dict ) and isinstance( resp_dict_val, dict ):
134                     sub_dif = XMLtoDictParserTools.getDifferenceDict( orig_dict_val, resp_dict_val )
135                     if sub_dif :
136                         diff[key] = sub_dif
137
138                 # check value is instance of list
139                 # TODO - > change a basic comparator to compare by id or order
140                 elif isinstance( orig_dict_val, list ) and isinstance( resp_dict_val, list ) :
141                     sub_list_diff = {}
142                     # the list lengths
143                     orig_i, resp_i = len( orig_dict_val ), len( resp_dict_val )
144                     # define a max iteration length (less from both)
145                     min_index = orig_i if orig_i < resp_i else resp_i
146                     for index in range ( 0, min_index, 1 ) :
147                         if ( orig_dict_val[index] != resp_dict_val[index] ) :
148                             if isinstance( orig_dict_val, dict ) and isinstance( resp_dict_val, dict ) :
149                                 sub_list_diff[index] = ( XMLtoDictParserTools.getDifferenceDict( orig_dict_val[index], resp_dict_val[index] ) )
150                             else :
151                                 sub_list_diff[index] = ( orig_dict_val[index], resp_dict_val[index] )
152                     if ( orig_i > min_index ) :
153                         # original is longer as responded dict
154                         for index in range ( min_index, orig_i, 1 ):
155                             sub_list_diff[index] = ( orig_dict_val[index], None )
156                     elif ( resp_i > min_index ) :
157                         # responded dict is longer as original
158                         for index in range ( min_index, resp_i, 1 ) :
159                             sub_list_diff[index] = ( None, resp_dict_val[index] )
160                     if sub_list_diff :
161                         diff[key] = sub_list_diff
162
163                 else :
164                     diff[key] = ( original_dict[key], responded_dict[key] )
165
166         # Check all keys in responded_dict dict to find missing
167         for key in responded_dict.keys():
168             if ( not original_dict.has_key( key ) ):
169                 diff[key] = ( KEY_NOT_FOUND, key )
170         return diff