|
@@ -0,0 +1,328 @@
|
|
1
|
+#-*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+import lxml
|
|
4
|
+import os
|
|
5
|
+from lxml import etree
|
|
6
|
+from lodel.editorial_model.model import EditorialModel
|
|
7
|
+from lodel.editorial_model.components import *
|
|
8
|
+from lodel.utils.mlstring import MlString
|
|
9
|
+
|
|
10
|
+##@brief Saves a model in a xml file
|
|
11
|
+# @param model EditorialModel : the model to save
|
|
12
|
+# @param filename str|None : if None display on stdout
|
|
13
|
+
|
|
14
|
+def save(model, **kwargs):
|
|
15
|
+ Em = etree.Element("editorial_model")
|
|
16
|
+ em_name = etree.SubElement(Em, 'name')
|
|
17
|
+ write_mlstring_xml(etree, em_name, model.name)
|
|
18
|
+
|
|
19
|
+ em_description = etree.SubElement(Em, 'description')
|
|
20
|
+ write_mlstring_xml(etree, em_description, model.description)
|
|
21
|
+
|
|
22
|
+ em_classes = etree.SubElement(Em, 'classes')
|
|
23
|
+ classes = model.all_classes()
|
|
24
|
+ for emclass in classes:
|
|
25
|
+ write_emclass_xml(etree, em_classes, classes[emclass].uid, classes[emclass].display_name,
|
|
26
|
+ classes[emclass].help_text, classes[emclass].group,
|
|
27
|
+ classes[emclass].fields(), classes[emclass].parents,
|
|
28
|
+ classes[emclass].abstract, classes[emclass].pure_abstract)
|
|
29
|
+
|
|
30
|
+ em_groups = etree.SubElement(Em, 'groups')
|
|
31
|
+ groups = model.all_groups()
|
|
32
|
+ for group in groups:
|
|
33
|
+ requires = groups[group].dependencies()
|
|
34
|
+ write_emgroup_xml(etree, em_groups, groups[group].uid, groups[group].display_name, groups[group].help_text,
|
|
35
|
+ list(requires.keys()), groups[group].components())
|
|
36
|
+
|
|
37
|
+ emodel = etree.tostring(Em, encoding='utf-8', xml_declaration=True, method='xml', pretty_print= True)
|
|
38
|
+ if len(kwargs) == 0:
|
|
39
|
+ print(emodel.decode())
|
|
40
|
+ else:
|
|
41
|
+ outfile = open(kwargs['filename'], "w")
|
|
42
|
+ outfile.write(emodel.decode())
|
|
43
|
+ outfile.close()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+##@brief Writes a representation of a MlString in xml
|
|
47
|
+# @param etree : the xml object
|
|
48
|
+# @param elem : the element which represents a MlString
|
|
49
|
+# @param mlstr : the mlstr to write
|
|
50
|
+def write_mlstring_xml(etree, elem, mlstr):
|
|
51
|
+ for lang in mlstr.values:
|
|
52
|
+ ss_mlstr = etree.SubElement(elem,lang)
|
|
53
|
+ ss_mlstr.text = mlstr.get(lang)
|
|
54
|
+
|
|
55
|
+##@brief Writes the definition of a datahandler in xml
|
|
56
|
+# @param etree : the xml object
|
|
57
|
+# @param elem : the element which defines a datahandler
|
|
58
|
+# @param dhdl_name : the name of the datahandler
|
|
59
|
+# @param kwargs : the options of the datahandler
|
|
60
|
+def write_datahandler_xml(etree, elem, dhdl_name, **kwargs):
|
|
61
|
+ dhdl = etree.SubElement(elem,'datahandler_name')
|
|
62
|
+ dhdl.text = dhdl_name
|
|
63
|
+ dhdl_opt = etree.SubElement(elem, 'datahandler_options')
|
|
64
|
+ for argname, argval in kwargs.items():
|
|
65
|
+ arg = etree.SubElement(dhdl_opt, argname)
|
|
66
|
+ arg.text = argval
|
|
67
|
+
|
|
68
|
+##@brief Writes a representation in xml of a EmField
|
|
69
|
+# @param etree : the xml object
|
|
70
|
+# @param elem : the element for the EmField
|
|
71
|
+# @param uid : the uid of the EmField
|
|
72
|
+# @param name : the name of the field
|
|
73
|
+# @param help_text : explanations of the EmField
|
|
74
|
+# @param group_uid : the uid of a group, can be None
|
|
75
|
+# @datahandler_name
|
|
76
|
+# @**kwargs : options of the datahandler
|
|
77
|
+def write_emfield_xml(etree, elem, uid, name, help_text, group, datahandler_name, **kwargs):
|
|
78
|
+ emfield = etree.SubElement(elem,'field')
|
|
79
|
+ emfield_uid = etree.SubElement(emfield, 'uid')
|
|
80
|
+ emfield_uid.text = uid
|
|
81
|
+ emfield_name = etree.SubElement(emfield, 'display_name')
|
|
82
|
+ if name is None:
|
|
83
|
+ pass
|
|
84
|
+ else:
|
|
85
|
+ write_mlstring_xml(etree, emfield_name, name)
|
|
86
|
+ emfield_help = etree.SubElement(emfield, 'help_text')
|
|
87
|
+ if help_text is None:
|
|
88
|
+ pass
|
|
89
|
+ else:
|
|
90
|
+ write_mlstring_xml(etree, emfield_help, help_text)
|
|
91
|
+ emfield_group = etree.SubElement(emfield, 'group')
|
|
92
|
+ if group is not None:
|
|
93
|
+ emfield_group.text = group.uid #write_emgroup_xml(etree, emfield_group, group.uid, group.display_name, group.help_text, group.requires)
|
|
94
|
+ write_datahandler_xml(etree,emfield,datahandler_name, **kwargs)
|
|
95
|
+
|
|
96
|
+##@brief Writes a representation of a EmGroup in xml
|
|
97
|
+# @param etree : the xml object
|
|
98
|
+# @param elem : the element for the EmGroup
|
|
99
|
+# @param name : the name of the group
|
|
100
|
+# @param help_text : explanations of the EmGroup
|
|
101
|
+# @param requires : a list of the group's uids whose this group depends
|
|
102
|
+
|
|
103
|
+def write_emgroup_xml(etree, elem, uid, name, help_text, requires, components):
|
|
104
|
+ emgroup = etree.SubElement(elem, 'group')
|
|
105
|
+ emgroup_uid = etree.SubElement(emgroup, 'uid')
|
|
106
|
+ emgroup_uid.text = uid
|
|
107
|
+ emgroup_name = etree.SubElement(emgroup, 'display_name')
|
|
108
|
+ if name is None:
|
|
109
|
+ pass
|
|
110
|
+ else:
|
|
111
|
+ write_mlstring_xml(etree, emgroup_name, name)
|
|
112
|
+ emgroup_help = etree.SubElement(emgroup, 'help_text')
|
|
113
|
+ if help_text is None:
|
|
114
|
+ pass
|
|
115
|
+ else:
|
|
116
|
+ write_mlstring_xml(etree, emgroup_help, help_text)
|
|
117
|
+ emgroup_requires = etree.SubElement(emgroup, 'requires')
|
|
118
|
+ emgroup_requires.text = ",".join(requires)
|
|
119
|
+ emgroup_comp = etree.SubElement(emgroup, 'components')
|
|
120
|
+ emgroup_comp_cls = etree.SubElement(emgroup_comp, 'emclasses')
|
|
121
|
+ emgroup_comp_fld = etree.SubElement(emgroup_comp, 'emfields')
|
|
122
|
+
|
|
123
|
+ for component in components:
|
|
124
|
+ if isinstance(component, EmField):
|
|
125
|
+ emgroup_comp_fld_ins = etree.SubElement(emgroup_comp_fld, 'emfield')
|
|
126
|
+ em_group_comp_fld_ins_uid = etree.SubElement(emgroup_comp_fld_ins,'uid')
|
|
127
|
+ em_group_comp_fld_ins_uid.text = component.uid
|
|
128
|
+ em_group_comp_fld_ins_cls = etree.SubElement(emgroup_comp_fld_ins,'class')
|
|
129
|
+ em_group_comp_fld_ins_cls.text = component.get_emclass_uid()
|
|
130
|
+ #write_emfield_xml(etree, emgroup_comp_fld, component.uid, component.display_name,
|
|
131
|
+ # component.help_text, component.group, component.data_handler_name, **(component.data_handler_options))
|
|
132
|
+ elif isinstance(component, EmClass):
|
|
133
|
+ em_group_comp_cls_ins = etree.SubElement(emgroup_comp_cls, 'emclass')
|
|
134
|
+ em_group_comp_cls_ins.text = component.uid
|
|
135
|
+ #write_emclass_xml(etree, emgroup_comp_cls, component.uid, component.display_name, component.help_text, component.group,
|
|
136
|
+ # component.fields(), component.parents, component.abstract, component.pure_abstract)
|
|
137
|
+
|
|
138
|
+##@brief Writes a representation of a EmClass in xml
|
|
139
|
+# @param etree : the xml object
|
|
140
|
+# @param elem : the element for the EmClass
|
|
141
|
+# @param name : the name of the group
|
|
142
|
+# @param help_text : explanations of the EmClass
|
|
143
|
+# @param fields : a dict
|
|
144
|
+# @param parents : a list of EmClass uids
|
|
145
|
+# @param abstract : a boolean
|
|
146
|
+# @param pure_abstract : a boolean
|
|
147
|
+
|
|
148
|
+def write_emclass_xml(etree, elem, uid, name, help_text, group, fields, parents, abstract = False, pure_abstract = False):
|
|
149
|
+ emclass = etree.SubElement(elem, 'class')
|
|
150
|
+ emclass_uid = etree.SubElement(emclass, 'uid')
|
|
151
|
+ emclass_uid.text = uid
|
|
152
|
+ emclass_name = etree.SubElement(emclass, 'display_name')
|
|
153
|
+ if name is None:
|
|
154
|
+ pass
|
|
155
|
+ else:
|
|
156
|
+ write_mlstring_xml(etree, emclass_name, name)
|
|
157
|
+ emclass_help = etree.SubElement(emclass, 'help_text')
|
|
158
|
+ if help_text is None:
|
|
159
|
+ pass
|
|
160
|
+ else:
|
|
161
|
+ write_mlstring_xml(etree, emclass_help, help_text)
|
|
162
|
+ emclass_abstract = etree.SubElement(emclass, 'abstract')
|
|
163
|
+ emclass_abstract.text ="True" if abstract else "False"
|
|
164
|
+ emclass_pure_abstract = etree.SubElement(emclass, 'pure_abstract')
|
|
165
|
+ emclass_pure_abstract.text = "True" if pure_abstract else "False"
|
|
166
|
+ emclass_group = etree.SubElement(emclass, 'group')
|
|
167
|
+ if group is not None:
|
|
168
|
+ emclass_group.text = group.uid #write_emgroup_xml(etree, emclass_group, group.uid, group.name, group.help_text, group.require, group.components)
|
|
169
|
+ emclass_fields = etree.SubElement(emclass, 'fields')
|
|
170
|
+ for field in fields:
|
|
171
|
+ write_emfield_xml(etree, emclass_fields, field.uid, field.display_name, field.help_text,
|
|
172
|
+ field.group,field.data_handler_name, **field.data_handler_options)
|
|
173
|
+ parents_list=list()
|
|
174
|
+ for parent in parents:
|
|
175
|
+ parents_list.append(parent['uid'])
|
|
176
|
+ emclass_parents = etree.SubElement(emclass, 'parents')
|
|
177
|
+ emclass_parents.text = ",".join(parents_list)
|
|
178
|
+
|
|
179
|
+##@brief Loads a model from a xml file
|
|
180
|
+# @param model EditorialModel : the model to load
|
|
181
|
+
|
|
182
|
+def load(**kwargs):
|
|
183
|
+
|
|
184
|
+ Em = etree.parse(kwargs['filename'])
|
|
185
|
+ emodel = Em.getroot()
|
|
186
|
+ name = emodel.find('name')
|
|
187
|
+ description = emodel.find('description')
|
|
188
|
+
|
|
189
|
+ model = EditorialModel(load_mlstring_xml(name), load_mlstring_xml(description))
|
|
190
|
+
|
|
191
|
+ classes = emodel.find('classes')
|
|
192
|
+ for emclass in classes:
|
|
193
|
+ model.add_class(load_class_xml(model, emclass))
|
|
194
|
+
|
|
195
|
+ groups = emodel.find('groups')
|
|
196
|
+ for group in groups:
|
|
197
|
+ grp = load_group_xml(model, group)
|
|
198
|
+ grp = model.add_group(grp)
|
|
199
|
+
|
|
200
|
+ return model;
|
|
201
|
+
|
|
202
|
+def load_class_xml(model, elem):
|
|
203
|
+ uid = elem.find('uid').text
|
|
204
|
+ name = load_mlstring_xml(elem.find('display_name'))
|
|
205
|
+ help_text = load_mlstring_xml(elem.find('help_text'))
|
|
206
|
+ abstract = True if elem.find('abstract').text == 'True' else False
|
|
207
|
+ pure_abstract = True if elem.find('pure_abstract').text == 'True' else False
|
|
208
|
+ requires = list()
|
|
209
|
+ classes = model.all_classes()
|
|
210
|
+ req = elem.find('parents')
|
|
211
|
+ if req.text is not None:
|
|
212
|
+ l_req = req.text.split(',')
|
|
213
|
+ for r in l_req:
|
|
214
|
+ if r in classes:
|
|
215
|
+ requires.append(model.all_classes_ref(r))
|
|
216
|
+ else:
|
|
217
|
+ requires.append(model.add_class(EmClass(r)))
|
|
218
|
+ group = elem.find('group')
|
|
219
|
+ if group:
|
|
220
|
+ grp = model.add_group(EmGroup(group.text))
|
|
221
|
+ else:
|
|
222
|
+ grp = None
|
|
223
|
+
|
|
224
|
+ if uid in classes:
|
|
225
|
+ emclass = model.all_classes_ref(uid)
|
|
226
|
+ emclass.display_name = name
|
|
227
|
+ emclass.help_text = help_text
|
|
228
|
+ emclass.parents=requires
|
|
229
|
+ emclass.group = grp
|
|
230
|
+ else:
|
|
231
|
+ emclass = EmClass(uid, name, help_text, abstract,requires, grp, pure_abstract)
|
|
232
|
+
|
|
233
|
+ fields = elem.find('fields')
|
|
234
|
+ for field in fields:
|
|
235
|
+ emfield = load_field_xml(model, field)
|
|
236
|
+ l_emfields = emclass.fields()
|
|
237
|
+ incls = False
|
|
238
|
+ for emf in l_emfields:
|
|
239
|
+ if emfield.uid == emf.uid:
|
|
240
|
+ incls = True
|
|
241
|
+ if not incls:
|
|
242
|
+ emclass.add_field(emfield)
|
|
243
|
+
|
|
244
|
+ return emclass
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+def load_field_xml(model, elem):
|
|
248
|
+ uid = elem.find('uid').text
|
|
249
|
+ if elem.find('display_name').text is None:
|
|
250
|
+ name = None
|
|
251
|
+ else:
|
|
252
|
+ name = load_mlstring_xml(elem.find('display_name'))
|
|
253
|
+
|
|
254
|
+ if elem.find('help_text').text is None:
|
|
255
|
+ help_text = None
|
|
256
|
+ else:
|
|
257
|
+ help_text = load_mlstring_xml(elem.find('help_text'))
|
|
258
|
+ emgroup = elem.find('group')
|
|
259
|
+ if emgroup:
|
|
260
|
+ group = model.add_group(EmGroup(emgroup.text))
|
|
261
|
+ else:
|
|
262
|
+ group = None
|
|
263
|
+ dhdl = elem.find('datahandler_name')
|
|
264
|
+ if elem.find('datahandler_options').text is not None:
|
|
265
|
+ dhdl_options = elem.find('datahandler_options').text.split()
|
|
266
|
+ emfield = EmField(uid, dhdl, name, help_text, group, **dhdl_options)
|
|
267
|
+ else:
|
|
268
|
+ emfield = EmField(uid, dhdl.text, name, help_text, group)
|
|
269
|
+
|
|
270
|
+ return emfield
|
|
271
|
+
|
|
272
|
+def load_group_xml(model, elem):
|
|
273
|
+ uid = elem.find('uid')
|
|
274
|
+
|
|
275
|
+ if elem.find('display_name').text is None:
|
|
276
|
+ name = None
|
|
277
|
+ else:
|
|
278
|
+ name = load_mlstring_xml(elem.find('display_name'))
|
|
279
|
+
|
|
280
|
+ if elem.find('help_text').text is None:
|
|
281
|
+ help_text = None
|
|
282
|
+ else:
|
|
283
|
+ help_text = load_mlstring_xml(elem.find('help_text'))
|
|
284
|
+
|
|
285
|
+ requires = list()
|
|
286
|
+ groups = model.all_groups()
|
|
287
|
+ req = elem.find('requires')
|
|
288
|
+ if req.text is not None:
|
|
289
|
+ l_req = req.text.split(',')
|
|
290
|
+ for r in l_req:
|
|
291
|
+ if r in groups:
|
|
292
|
+ requires.append(model.all_groups_ref(r))
|
|
293
|
+ else:
|
|
294
|
+ grp = model.new_group(r)
|
|
295
|
+ requires.append(grp)
|
|
296
|
+ if uid in groups:
|
|
297
|
+ group = model.all_groups_ref(uid)
|
|
298
|
+ group.display_name = name
|
|
299
|
+ group.help_text = help_text
|
|
300
|
+ group.add_dependencie(requires)
|
|
301
|
+ else:
|
|
302
|
+ group = EmGroup(uid.text, requires, name, help_text)
|
|
303
|
+
|
|
304
|
+ comp= list()
|
|
305
|
+ components = elem.find('components')
|
|
306
|
+ fields = components.find('emfields')
|
|
307
|
+ for field in fields:
|
|
308
|
+ fld_uid = field.find('uid').text
|
|
309
|
+ fld_class = field.find('class').text
|
|
310
|
+ fld = model.all_classes_ref(fld_class).fields(fld_uid)
|
|
311
|
+ comp.append(fld)
|
|
312
|
+ classes = components.find('emclasses')
|
|
313
|
+ for classe in classes:
|
|
314
|
+ comp.append(model.all_classes_ref(classe.text))
|
|
315
|
+ group.add_components(comp)
|
|
316
|
+
|
|
317
|
+ return group
|
|
318
|
+
|
|
319
|
+def load_mlstring_xml(elem):
|
|
320
|
+ mlstr = dict()
|
|
321
|
+ for lang in elem:
|
|
322
|
+ mlstr[lang.tag] = lang.text
|
|
323
|
+ return MlString(mlstr)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|