Browse Source

start of lodel1 migration tool

ArnAud 8 years ago
parent
commit
f303c0c241
2 changed files with 8273 additions and 0 deletions
  1. 247
    0
      EditorialModel/backend/lodel1_backend.py
  2. 8026
    0
      EditorialModel/test/model-lodel-1.0.xml

+ 247
- 0
EditorialModel/backend/lodel1_backend.py View File

@@ -0,0 +1,247 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+## @package EditorialModel.backend.lodel1_backend
4
+# @brief Handle convertion of lodel 1.0 model.xml
5
+#
6
+
7
+import xml.etree.ElementTree as ET
8
+import datetime
9
+import re
10
+from Lodel.utils.mlstring import MlString
11
+from EditorialModel.backend.dummy_backend import EmBackendDummy
12
+
13
+
14
+## Manages a Json file based backend structure
15
+class EmBackendLodel1(EmBackendDummy):
16
+    def __init__(self, xml_file=None, xml_string=None):
17
+        if (not xml_file and not xml_string) or (xml_file and xml_string):
18
+            raise AttributeError
19
+        self._xml_file = xml_file
20
+        self._xml_string = xml_string
21
+        self.lodel2_components = self._components = {'uids': {}, 'EmClass': [], 'EmType': [], 'EmField': [], 'EmFieldGroup': []}
22
+        self._uids = []
23
+        self._fieldgroups_map = {}
24
+
25
+    ## Loads the data from given file or string
26
+    #
27
+    # @return list
28
+    def load(self):
29
+        xml_string = self._load_from_file() if self._xml_file else self._xml_string
30
+
31
+        root_element = ET.fromstring(xml_string)
32
+        self._import_components(root_element)
33
+
34
+        # change uid of EmField and EmFieldGroup DONE
35
+        # take care of fieldgroup_id 0 !!
36
+
37
+        # add relational fields and rel_to_type_id
38
+
39
+        # add superiors_list in types
40
+
41
+        # create dict with all components DONE
42
+
43
+        #print (self.lodel2_components)
44
+        return self.lodel2_components['uids']
45
+
46
+    ## Import the four basic components
47
+    def _import_components(self, root_element):
48
+        # component name and xpath to find them in the xml model
49
+        # the order is very important
50
+        # class and type first, they put their uid in self._uids
51
+        # fieldgroups must change their uid, it will be used by fields later
52
+        to_import = [
53
+            ('EmClass', "./table[@name='#_TP_classes']/datas/row"),
54
+            ('EmType', "./table[@name='##_TP_types']/datas/row"),
55
+            ('EmFieldGroup', "./table[@name='#_TP_tablefieldgroups']/datas/row"),
56
+            ('EmField', "./table[@name='#_TP_tablefields']/datas/row")
57
+        ]
58
+        for comp in to_import:
59
+            component_name, xpath = comp
60
+            #print (component_name, xpath)
61
+            components = root_element.findall(xpath)
62
+            for lodel1_component in components:
63
+                cols = lodel1_component.findall('*')
64
+                fields = self._dom_elements_to_dict(cols)
65
+                #print(fields)
66
+                lodel2_component = self._map_component(component_name, fields)
67
+                lodel2_component['component'] = component_name
68
+                #print(lodel2_component)
69
+                uid = lodel2_component['uid']
70
+                self.lodel2_components[component_name].append(lodel2_component)
71
+                #if component_name in ['EmClass', 'EmType']:
72
+                self._uids.append(uid)
73
+                #del lodel2_component['uid']
74
+                self.lodel2_components['uids'][uid] = lodel2_component
75
+                #print ('————')
76
+
77
+    def _get_uid(self):
78
+        uid = 1
79
+        while True:
80
+            if uid not in self._uids:
81
+                return uid
82
+            uid += 1
83
+
84
+    ## map lodel1 values to lodel2 values
85
+    def _map_component(self, component, fields):
86
+        new_dic = {}
87
+        for mapping in ONE_TO_TWO[component]:
88
+            lodel1_fieldname, lodel2_fieldname = mapping[0:2]
89
+            if len(mapping) == 3:
90
+                cast_function = mapping[2]
91
+                if callable(cast_function):
92
+                    value = cast_function(fields[lodel1_fieldname])
93
+                    values = {lodel2_fieldname: value}
94
+                else:
95
+                    values = getattr(self, cast_function)(lodel2_fieldname, fields[lodel1_fieldname], fields)
96
+            else:
97
+                values = {lodel2_fieldname: fields[lodel1_fieldname]}
98
+            if values:
99
+                for name, value in values.items():
100
+                    new_dic[name] = value
101
+            #print (lodel1_fieldname, lodel2_fieldname, value)
102
+        return new_dic
103
+
104
+    ## convert collection of dom element to a dict
105
+    # <col name="id">252</col> => {'id':'252'}
106
+    def _dom_elements_to_dict(self, elements):
107
+        fields = {}
108
+        for element in elements:
109
+            if 'name' in element.attrib:
110
+                fields[element.attrib['name']] = element.text if element.text is not None else ''
111
+        return fields
112
+
113
+    def _load_from_file(self):
114
+        with open(self._xml_file) as content:
115
+            data = content.read()
116
+        return data
117
+
118
+    def save(self, model, filename=None):
119
+        pass
120
+
121
+    # Map methods lodel1 to lodel2
122
+
123
+    ## combine title and altertitle into one MlString
124
+    def title_to_mlstring(self, name, value, fields):
125
+        title = MlString({'fre': value})
126
+        if 'altertitle' in fields:
127
+            langs = re.findall('lang="(..)">([^<]*)', fields['altertitle'])
128
+            for string in langs:
129
+                title.set(string[0], string[1])
130
+        return {name: title}
131
+
132
+    ## set a new unused uid for EmFieldGroup
133
+    # save the oldid to apply to fields
134
+    def new_fieldgroup_id(self, name, value, fields):
135
+        uid = self._get_uid()
136
+        print(value)
137
+        self._fieldgroups_map[int(value)] = uid
138
+        return {name: uid}
139
+
140
+    # give a new unused uid
141
+    def new_uid(self, name, value, fields):
142
+        uid = self._get_uid()
143
+        return {name: uid}
144
+
145
+    # return the new fieldgroup_id given the old one
146
+    def fieldgroup_id(self, name, value, fields):
147
+        old_id = int(value)
148
+        try:
149
+            new_id = self._fieldgroups_map[old_id]
150
+        except KeyError:
151
+            print(old_id, fields)
152
+            return False
153
+        return {name: new_id}
154
+
155
+    def mlstring_cast(self, name, value, fields):
156
+        return {name: MlString({'fre': value})}
157
+
158
+    def to_classid(self, name, value, fields):
159
+        for em_class in self.lodel2_components['EmClass']:
160
+            if em_class['name'] == value:
161
+                return {name: em_class['uid']}
162
+        return False
163
+
164
+    def date_cast(self, name, value, fields):
165
+        date = None
166
+        if len(value):
167
+            try:  # 2015-09-14 14:20:28
168
+                date = datetime.datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
169
+            except ValueError:
170
+                pass
171
+        return {name: date}
172
+
173
+    def classtype_cast(self, name, value, fields):
174
+        classtype_map = {'entries': 'entry', 'entities': 'entity', 'persons': 'person'}
175
+        if value in classtype_map:
176
+            return {name: classtype_map[value]}
177
+        return False
178
+
179
+    def map_fieldtypes(self, name, value, fields):
180
+        fieldtypes = {
181
+            'longtext': 'text',
182
+            'date': 'datetime',
183
+            'tinytext': 'text',
184
+            'lang': 'char',
185
+            'boolean': 'bool',
186
+            'email': 'char',
187
+            'url': 'char',
188
+            'mltext': 'text',
189
+            'image': 'text',
190
+            'number': 'int',
191
+            #'persons': 'rel2type',
192
+            #'entries': 'rel2type',
193
+            #'entities': 'rel2type',
194
+            'persons': 'text',
195
+            'entries': 'text',
196
+            'entities': 'text'
197
+        }
198
+        if value in fieldtypes:
199
+            return {name: fieldtypes[value]}
200
+        return {name: value}
201
+
202
+
203
+ONE_TO_TWO = {
204
+    'EmClass': [
205
+        ("id", "uid", int),
206
+        ("icon", "icon"),
207
+        ("class", "name"),
208
+        ("title", "string", 'title_to_mlstring'),
209
+        ("classtype", "classtype", 'classtype_cast'),
210
+        ("comment", "help_text", 'mlstring_cast'),
211
+        #("status",""),
212
+        ("rank", "rank", int),
213
+        ("upd", "date_update", 'date_cast')
214
+    ],
215
+    'EmFieldGroup': [
216
+        ("id", "uid", 'new_fieldgroup_id'),
217
+        ("name", "name"),
218
+        ("class", "class_id", 'to_classid'),
219
+        ("title", "string", 'title_to_mlstring'),
220
+        ("comment", "help_text", 'mlstring_cast'),
221
+        #("status",""),
222
+        ("rank", "rank", int),
223
+        ("upd", "date_update", 'date_cast')
224
+    ],
225
+    'EmType': [
226
+        ("id", "uid", int),
227
+        ("icon", "icon"),
228
+        ("type", "name"),
229
+        ("title", "string", 'title_to_mlstring'),
230
+        ("class", "class_id", 'to_classid'),
231
+        ("comment", "help_text", 'mlstring_cast'),
232
+        #("status",""),
233
+        ("rank", "rank", int),
234
+        ("upd", "date_update", 'date_cast')
235
+    ],
236
+    'EmField': [
237
+        ("id", "uid", 'new_uid'),
238
+        ("name", "name"),
239
+        ("idgroup", "fieldgroup_id", 'fieldgroup_id'),
240
+        ("type", "fieldtype", 'map_fieldtypes'),
241
+        ("title", "string", 'title_to_mlstring'),
242
+        ("comment", "help_text", 'mlstring_cast'),
243
+        #("status",""),
244
+        ("rank", "rank", int),
245
+        ("upd", "date_update", 'date_cast')
246
+    ]
247
+}

+ 8026
- 0
EditorialModel/test/model-lodel-1.0.xml
File diff suppressed because it is too large
View File


Loading…
Cancel
Save