summaryrefslogtreecommitdiffstats
path: root/Monitoring/src/main/python/DataProcessing/DataHeader.py.old
blob: 722094eb03a19211d6511a9a42505236e32c64e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
'''
Created on Sep 1, 2011

@author: steger, jozsef
@organization: ELTE
@contact: steger@complex.elte.hu
@author: laki, sandor
'''

from DataProcessing.Dimension import DimensionManager
from DataProcessing.DataError import DataError
from DataProcessing.DataHeaderCell import DataHeaderCell, CellRequestByName,\
    CellRequestByFeature

class DataHeader(object):
    '''
    @author: steger, jozsef
    @summary: 
    This class represents the full header of a table.
    One can construct the header as a single step, 
    if they provide a header description or they can use
    methods to add new columns.
    
    In order to be able to represent a wide variety of data and relationship
    between them, a column can refer to another table.
    In that latter case a specific column refer to another DataHeader. 
    '''

    def __init__(self, name):
        '''
        @summary: Constructor
        @param name: the name of the table
        @type name: string
        @raise DataError: corrupt header description
        '''
        self._name = name
        self._cellnames = []
        self._cells = {}
    
    def __iter__(self):
        for cn in self._cellnames:
            yield self._cells[cn]
    
    def __len__(self):
        '''
        @summary: Return the number of columns
        @return: the number of columns currently set
        @rtype: integer
        '''
        return len(self._cellnames)

    def __eq__(self, header):
        '''
        @summary: Comparison operator of table headers.
        Two tables are declared equal, if all the columns' names and their unit models are the same. 
        Two headers are still regarded equal if the order of their columns are different 
        or the current unit of the corresponding columns are not the same.
        @raise DataError: if not DataHeader instances are compared
        @return: True if both the header name and all columns match, their order may vary
        @rtype: boolean
        '''
        if not isinstance(header, DataHeader):
            raise DataError("wrong type to compare")
        if self.name != header.name:
            return False
        if len(self._cellnames) != len(header._cellnames):
            return False
        if self._cells.keys() != header._cells.keys():
            return False
        for n in self._cellnames:
            if self._cells[n] != header._cells[n]:
                return False
        return True
    
    def __ne__(self, header):
        '''
        @summary: comparison operator of table headers.
        @return: True if tables headers differ
        @rtype: boolean
        '''
        return not self.__eq__(header)
    
    @property
    def name(self):
        return self._name
    
    def has_name(self, name):
        '''
        @summary: Check for the existence of a given column name
        @param name: the name of the column looking for
        @type name: string
        @return: true if such a name exists
        @rtype: boolean
        '''
        return name in self._cellnames
    
    def addColumn(self, cell):
        '''
        @summary: Append a new column at the end of the current table header structure
        @param cell: pointer to the header of the new column
        @type cell: DataHeader or DataHeaderCell
        @raise DataError: cell is of a wrong type  
        '''
        ishdr = isinstance(cell, DataHeader)
        if ishdr or isinstance(cell, DataHeaderCell):
            name = cell.name
            if self.has_name(name):
                raise DataError("attempt to add a column with an already existing name (%s)" % cell.name)
            self._cells[name] = cell
            self._cellnames.append(name)
        else:
            raise DataError("attempt to add a wrong type of header cell")
    
    def removeColumn(self, name):
        '''
        @summary: remove a named column if it exists in the header. Otherwise do silently nothing
        @param name: the name of the column to remove
        @type name: string
        '''
        if self.has_name(name):
            self._cells.pop(name)
            self._cellnames.pop(self._cellnames.index(name))
    
    def getHeader(self, name):
        '''
        @summary: Return a pointer to the named sub header in the naming hierarchy
        @param name: the name of the sub header searched
        @type name: string
        @raise DataError: name not found
        '''
        if name.count('.') == 0:
            if name == self.name:
                return self
            if self.has_name(name) and isinstance(self._cells[name], DataHeader):
                return self._cells[name]
        elif name.count('.') == 1:
            n_pre, n_post = name.split('.', 1)
            if n_pre == self.name and self.has_name(n_post) and isinstance(self._cells[n_post], DataHeader):
                return self._cells[n_post]
        else:
            n_pre, n, n_post = name.split('.', 2)
            if n_pre == self.name and self.has_name(n) and isinstance(self._cells[n], DataHeader):
                return self._cells[n].getHeader(n_post)
        raise DataError("Lost in the naming hierarchy: %s < %s" % (self.name, name))

#FIXME: complex table lookup is not implemented    
    def getCell(self, cellrequest):
        '''
        @summary: Return the index and the cell referenced by a name
        @param cellrequest: 
        @type name: CellRequest
        @return: index and the cell
        @rtype: (int, Cell)
        @raise DataError: name not found
        '''
        if isinstance(cellrequest, CellRequestByName):
            name = cellrequest.name
            try:
                yield (self._cellnames.index(name), self._cells[name])
            except:
                DataError("Cell with name %s not found" % name)
        elif isinstance(cellrequest, CellRequestByFeature):
            for c in self:
                try:
                    if cellrequest == c:
                        yield (self._cellnames.index(c.name), c)
                except DataError:
                    continue
        else:
            raise DataError("wrong request type")



class DataHeaderGeneratedByDescription(DataHeader):
    def __init__(self, name, headerdescription):
        '''
        @summary: Constructor
        @param name: the name of the table
        @type name: string
        @param headerdescription: the description of a full table header
        @param headerdescription: list or None
        @raise DataError: corrupt header description
        '''
        DataHeader.__init__(self, name)
        for item in headerdescription:
            if len(item) == 2:
                name, description = item
                unit = None
            else:
                name, description, unit = item
            if self.has_name(name):
                raise DataError("Duplicate column name declaration (%s)" % name)
            if description is None or isinstance(description, DimensionManager.Dimension):
                cell = DataHeaderCell(name = name, dimension = description, unit = unit)
                self.addColumn(cell)
            elif isinstance(description, list):
                hdr = DataHeaderGeneratedByDescription(name = name, headerdescription = description)
                self.addColumn(hdr)
            else:
                raise DataError("corrupt header description (%s)" % name)