No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lodel1_backend.py 8.5KB

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