|
@@ -0,0 +1,105 @@
|
|
1
|
+#-*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+import itertools
|
|
4
|
+
|
|
5
|
+from lodel.utils.mlstring import MlString
|
|
6
|
+
|
|
7
|
+from lodel.editorial_model.exceptions import *
|
|
8
|
+
|
|
9
|
+## @brief Abstract class to represent editorial model components
|
|
10
|
+# @see EmClass EmField
|
|
11
|
+class EmComponent(object):
|
|
12
|
+
|
|
13
|
+ ## @brief Instanciate an EmComponent
|
|
14
|
+ # @param uid str : uniq identifier
|
|
15
|
+ # @param display_name MlString|str|dict : component display_name
|
|
16
|
+ # @param help_text MlString|str|dict : help_text
|
|
17
|
+ def __init__(self, uid, display_name = None, help_text = None, group = None):
|
|
18
|
+ if self.__class__ == EmComponent:
|
|
19
|
+ raise NotImplementedError('EmComponent is an abstract class')
|
|
20
|
+ self.uid = uid
|
|
21
|
+ self.display_name = None if display_name is None else MlString(display_name)
|
|
22
|
+ self.help_text = None if help_text is None else MlString(help_text)
|
|
23
|
+ self.group = group
|
|
24
|
+
|
|
25
|
+ def __str__(self):
|
|
26
|
+ if self.display_name is None:
|
|
27
|
+ return str(self.uid)
|
|
28
|
+ return str(self.display_name)
|
|
29
|
+
|
|
30
|
+## @brief Handles editorial model objects classes
|
|
31
|
+#
|
|
32
|
+# @note The inheritance system allow child classes to overwrite parents EmField. But it's maybe not a good idea
|
|
33
|
+class EmClass(EmComponent):
|
|
34
|
+
|
|
35
|
+ ## @brief Instanciate a new EmClass
|
|
36
|
+ # @param uid str : uniq identifier
|
|
37
|
+ # @param display_name MlString|str|dict : component display_name
|
|
38
|
+ # @param abstract bool : set the class as asbtract if True
|
|
39
|
+ # @param parents list: parent EmClass list or uid list
|
|
40
|
+ # @param help_text MlString|str|dict : help_text
|
|
41
|
+ def __init__(self, uid, display_name = None, help_text = None, abstract = False, parents = None, group = None):
|
|
42
|
+ super().__init__(uid, display_name, help_text, group)
|
|
43
|
+ self.abstract = bool(abstract)
|
|
44
|
+ if parents is not None:
|
|
45
|
+ if not isinstance(parents, list):
|
|
46
|
+ parents = [parents]
|
|
47
|
+ for parent in parents:
|
|
48
|
+ if not isinstance(parent, EmClass):
|
|
49
|
+ raise ValueError("<class EmClass> expected in parents list, but %s found" % type(parent))
|
|
50
|
+ self.parents = parents
|
|
51
|
+ ## @brief Stores EmFields instances indexed by field uid
|
|
52
|
+ self.__fields = dict()
|
|
53
|
+
|
|
54
|
+ ## @brief Property that represent a dict of all fields (the EmField defined in this class and all its parents)
|
|
55
|
+ @property
|
|
56
|
+ def __all_fields(self):
|
|
57
|
+ res = dict()
|
|
58
|
+ for pfields in [ p.__all_fields for p in self.parents]:
|
|
59
|
+ res.update(pfields)
|
|
60
|
+ res.update(self.__fields)
|
|
61
|
+ return res
|
|
62
|
+
|
|
63
|
+ ## @brief EmField getter
|
|
64
|
+ # @param uid None | str : If None returns an iterator on EmField instances else return an EmField instance
|
|
65
|
+ # @param no_parents bool : If True returns only fields defined is this class and not the one defined in parents classes
|
|
66
|
+ # @return An iterator on EmFields instances (if uid is None) else return an EmField instance
|
|
67
|
+ def fields(self, uid = None, no_parents = False):
|
|
68
|
+ fields = self.__fields if no_parents else self.__all_fields
|
|
69
|
+ try:
|
|
70
|
+ return iter(fields.values()) if uid is None else fields[uid]
|
|
71
|
+ except KeyError:
|
|
72
|
+ raise EditorialModelError("No such EmField '%s'" % uid)
|
|
73
|
+
|
|
74
|
+ ## @brief Add a field to the EmClass
|
|
75
|
+ # @param emfield EmField : an EmField instance
|
|
76
|
+ # @warning do not add an EmField allready in another class !
|
|
77
|
+ # @throw EditorialModelException if an EmField with same uid allready in this EmClass (overwritting allowed from parents)
|
|
78
|
+ def add_field(self, emfield):
|
|
79
|
+ if emfield.uid in self.__fields:
|
|
80
|
+ raise EditorialModelException("Duplicated uid '%s' for EmField in this class ( %s )" % (emfield.uid, self))
|
|
81
|
+ self.__fields[emfield.uid] = emfield
|
|
82
|
+
|
|
83
|
+ ## @brief Create a new EmField and add it to the EmClass
|
|
84
|
+ # @param uid str : the EmField uniq id
|
|
85
|
+ # @param **field_kwargs : EmField constructor parameters ( see @ref EmField.__init__() )
|
|
86
|
+ def new_field(self, uid, **field_kwargs):
|
|
87
|
+ return self.add_field(EmField(uid, **kwargs))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+## @brief Handles editorial model classes fields
|
|
91
|
+class EmField(EmComponent):
|
|
92
|
+
|
|
93
|
+ ## @brief Instanciate a new EmField
|
|
94
|
+ # @param uid str : uniq identifier
|
|
95
|
+ # @param display_name MlString|str|dict : field display_name
|
|
96
|
+ # @param data_handler class|str : A DataHandler class or display_name
|
|
97
|
+ # @param help_text MlString|str|dict : help text
|
|
98
|
+ # @param group EmGroup :
|
|
99
|
+ # @param **handler_kwargs : data handler arguments
|
|
100
|
+ def __init__(self, uid, data_handler, display_name = None, help_text = None, group = None, **handler_kwargs):
|
|
101
|
+ super().__init__(uid, display_name, help_text, group)
|
|
102
|
+ self.data_handler = data_handler
|
|
103
|
+ self.data_handler_options = data_handler_options
|
|
104
|
+
|
|
105
|
+
|