|
@@ -6,6 +6,7 @@ import sqlalchemy as sql
|
6
|
6
|
import EditorialModel
|
7
|
7
|
from EditorialModel.components import EmComponent, EmComponentNotExistError
|
8
|
8
|
from EditorialModel.fieldgroups import EmFieldGroup
|
|
9
|
+from EditorialModel.fields import EmField
|
9
|
10
|
from EditorialModel.classtypes import EmNature, EmClassType
|
10
|
11
|
import EditorialModel.fieldtypes as ftypes
|
11
|
12
|
import EditorialModel.classes
|
|
@@ -18,13 +19,14 @@ import EditorialModel.classes
|
18
|
19
|
# @see EditorialModel::components::EmComponent
|
19
|
20
|
class EmType(EmComponent):
|
20
|
21
|
table = 'em_type'
|
|
22
|
+ table_hierarchy = 'em_type_hierarchy'
|
21
|
23
|
ranked_in = 'class_id'
|
22
|
24
|
|
23
|
25
|
## @brief Specific EmClass fields
|
24
|
26
|
# @see EditorialModel::components::EmComponent::_fields
|
25
|
27
|
_fields = [
|
26
|
28
|
('class_id', ftypes.EmField_integer),
|
27
|
|
- ('icon', ftypes.EmField_integer),
|
|
29
|
+ ('icon', ftypes.EmField_icon),
|
28
|
30
|
('sortcolumn', ftypes.EmField_char)
|
29
|
31
|
]
|
30
|
32
|
|
|
@@ -37,22 +39,37 @@ class EmType(EmComponent):
|
37
|
39
|
# @throw EmComponentExistError if an EmType with this name but different attributes exists
|
38
|
40
|
# @see EmComponent::__init__()
|
39
|
41
|
#
|
40
|
|
- # @todo Remove hardcoded default value for icon
|
41
|
|
- # @todo check that em_class is an EmClass object
|
|
42
|
+ # @todo check that em_class is an EmClass object (fieldtypes can handle it)
|
42
|
43
|
def create(c, name, em_class, **em_component_args):
|
43
|
|
- return super(EmType, c).create(name=name, class_id=em_class.uid, icon=0, **em_component_args)
|
44
|
|
-
|
|
44
|
+ return super(EmType, c).create(name=name, class_id=em_class.uid, **em_component_args)
|
|
45
|
+
|
|
46
|
+ @property
|
|
47
|
+ ## Return an sqlalchemy table for type hierarchy
|
|
48
|
+ # @return sqlalchemy em_type_hierarchy table object
|
|
49
|
+ # @todo Don't hardcode table name
|
|
50
|
+ def _table_hierarchy(self):
|
|
51
|
+ return sql.Table(self.__class__.table_hierarchy, sqlutils.meta(self.db_engine()))
|
|
52
|
+
|
|
53
|
+ @property
|
|
54
|
+ ## Return the EmClassType of the type
|
|
55
|
+ # @return EditorialModel.classtypes.*
|
|
56
|
+ def classtype(self):
|
|
57
|
+ return getattr(EmClassType, EditorialModel.classes.EmClass(self.class_id).classtype)
|
|
58
|
+
|
45
|
59
|
## @brief Delete an EmType
|
46
|
60
|
# The deletion is only possible if a type is not linked by any EmClass
|
47
|
61
|
# and if it has no subordinates
|
48
|
62
|
# @return True if delete False if not deleted
|
49
|
63
|
# @todo Check if the type is not linked by any EmClass
|
50
|
64
|
# @todo Check if there is no other ''non-deletion'' conditions
|
51
|
|
- # @todo Delete it as subordinates for all its superiors
|
52
|
65
|
def delete(self):
|
53
|
66
|
subs = self.subordinates()
|
54
|
67
|
if sum([len(subs[subnat]) for subnat in subs]) > 0:
|
55
|
68
|
return False
|
|
69
|
+ #Delete all relation with superiors
|
|
70
|
+ for nature,sups in self.superiors().items():
|
|
71
|
+ for sup in sups:
|
|
72
|
+ self.del_superior(sup, nature)
|
56
|
73
|
return super(EmType, self).delete()
|
57
|
74
|
|
58
|
75
|
|
|
@@ -103,8 +120,10 @@ class EmType(EmComponent):
|
103
|
120
|
#
|
104
|
121
|
# @param field EmField: The optional field to select
|
105
|
122
|
# @return True if success False if failed
|
106
|
|
- # @throw TypeError
|
107
|
|
- # @todo change exception type and define return value and raise condition
|
|
123
|
+ #
|
|
124
|
+ # @throw TypeError if field is not an EmField instance
|
|
125
|
+ # @throw ValueError if field is not optional or is not associated with this type
|
|
126
|
+ # @see EmType::_opt_field_act()
|
108
|
127
|
def select_field(self, field):
|
109
|
128
|
return self._opt_field_act(field, True)
|
110
|
129
|
|
|
@@ -114,7 +133,10 @@ class EmType(EmComponent):
|
114
|
133
|
#
|
115
|
134
|
# @param field EmField: The optional field to unselect
|
116
|
135
|
# @return True if success False if fails
|
117
|
|
- # @throw TypeError
|
|
136
|
+ #
|
|
137
|
+ # @throw TypeError if field is not an EmField instance
|
|
138
|
+ # @throw ValueError if field is not optional or is not associated with this type
|
|
139
|
+ # @see EmType::_opt_field_act()
|
118
|
140
|
def unselect_field(self, field):
|
119
|
141
|
return self._opt_field_act(field, False)
|
120
|
142
|
|
|
@@ -123,9 +145,12 @@ class EmType(EmComponent):
|
123
|
145
|
# @param field EmField: The EmField to select or unselect
|
124
|
146
|
# @param select bool: If True select field, else unselect it
|
125
|
147
|
# @return True if success False if fails
|
|
148
|
+ #
|
126
|
149
|
# @throw TypeError if field is not an EmField instance
|
127
|
150
|
# @throw ValueError if field is not optional or is not associated with this type
|
128
|
151
|
def _opt_field_act(self, field, select=True):
|
|
152
|
+ if not isinstance(field, EmField):
|
|
153
|
+ raise TypeError("Excepted <class EmField> as field argument. But got "+str(type(field)))
|
129
|
154
|
if not field in self.all_fields():
|
130
|
155
|
raise ValueError("This field is not part of this type")
|
131
|
156
|
if not field.optional:
|
|
@@ -149,7 +174,7 @@ class EmType(EmComponent):
|
149
|
174
|
# @note Not conceptualized yet
|
150
|
175
|
# @todo Conception
|
151
|
176
|
def hooks(self):
|
152
|
|
- pass
|
|
177
|
+ raise NotImplementedError()
|
153
|
178
|
|
154
|
179
|
## Add a new hook
|
155
|
180
|
# @param hook EmHook: An EmHook instance
|
|
@@ -157,7 +182,7 @@ class EmType(EmComponent):
|
157
|
182
|
# @note Not conceptualized yet
|
158
|
183
|
# @todo Conception
|
159
|
184
|
def add_hook(self, hook):
|
160
|
|
- pass
|
|
185
|
+ raise NotImplementedError()
|
161
|
186
|
|
162
|
187
|
## Delete a hook
|
163
|
188
|
# @param hook EmHook: An EmHook instance
|
|
@@ -166,22 +191,9 @@ class EmType(EmComponent):
|
166
|
191
|
# @todo Conception
|
167
|
192
|
# @todo Maybe we don't need a EmHook instance but just a hook identifier
|
168
|
193
|
def del_hook(self,hook):
|
169
|
|
- pass
|
170
|
|
-
|
171
|
|
-
|
172
|
|
- @classmethod
|
173
|
|
- ## Return an sqlalchemy table for type hierarchy
|
174
|
|
- # @return sqlalchemy em_type_hierarchy table object
|
175
|
|
- # @todo Don't hardcode table name
|
176
|
|
- def _tableHierarchy(cl):
|
177
|
|
- return sql.Table('em_type_hierarchy', sqlutils.meta(cl.db_engine()))
|
178
|
|
-
|
179
|
|
- @property
|
180
|
|
- ## Return the EmClassType of the type
|
181
|
|
- # @return EditorialModel.classtypes.*
|
182
|
|
- def classtype(self):
|
183
|
|
- return getattr(EmClassType, EditorialModel.classes.EmClass(self.class_id).classtype)
|
|
194
|
+ raise NotImplementedError()
|
184
|
195
|
|
|
196
|
+
|
185
|
197
|
## @brief Get the list of subordinates EmType
|
186
|
198
|
# Get a list of EmType instance that have this EmType for superior
|
187
|
199
|
# @return Return a dict with relation nature as keys and values as a list of subordinates
|
|
@@ -207,7 +219,7 @@ class EmType(EmComponent):
|
207
|
219
|
# @see EmType::subordinates(), EmType::superiors()
|
208
|
220
|
def _subOrSup(self, sup = True):
|
209
|
221
|
conn = self.db_engine().connect()
|
210
|
|
- htable = self.__class__._tableHierarchy()
|
|
222
|
+ htable = self._table_hierarchy
|
211
|
223
|
req = htable.select()
|
212
|
224
|
if sup:
|
213
|
225
|
req = req.where(htable.c.subordinate_id == self.uid)
|
|
@@ -255,7 +267,7 @@ class EmType(EmComponent):
|
255
|
267
|
raise ValueError("Not allowed to put a different em_type as superior in a relation of nature '"+relation_nature+"'")
|
256
|
268
|
|
257
|
269
|
conn = self.db_engine().connect()
|
258
|
|
- htable = self.__class__._tableHierarchy()
|
|
270
|
+ htable = self._table_hierarchy
|
259
|
271
|
values = { 'subordinate_id': self.uid, 'superior_id': em_type.uid, 'nature': relation_nature }
|
260
|
272
|
req = htable.insert(values=values)
|
261
|
273
|
|
|
@@ -280,7 +292,7 @@ class EmType(EmComponent):
|
280
|
292
|
raise ValueError("Invalid nature for add_superior : '"+relation_nature+"'. Allowed relations for this type are "+str(EmClassType.natures(self.classtype['name'])))
|
281
|
293
|
|
282
|
294
|
conn = self.db_engine().connect()
|
283
|
|
- htable = self.__class__._tableHierarchy()
|
|
295
|
+ htable = self._table_hierarchy
|
284
|
296
|
req = htable.delete(htable.c.superior_id == em_type.uid and htable.c.nature == relation_nature)
|
285
|
297
|
conn.execute(req)
|
286
|
298
|
conn.close()
|
|
@@ -296,7 +308,7 @@ class EmType(EmComponent):
|
296
|
308
|
# @return A list of EmType objects
|
297
|
309
|
def _linked_types_Db(self):
|
298
|
310
|
conn = self.db_engine().connect()
|
299
|
|
- htable = self.__class__._tableHierarchy()
|
|
311
|
+ htable = self._table_hierarchy
|
300
|
312
|
req = htable.select(htable.c.superior_id, htable.c.subordinate_id)
|
301
|
313
|
req = req.where(sql.or_(htable.c.subordinate_id == self.uid, htable.c.superior_id == self.uid))
|
302
|
314
|
|