l10nobject.py

Go to the documentation of this file.
00001 from silme.core.object import Blob, L10nObject, Comment
00002 from silme.core.entity import Entity
00003 from entitylist import EntityListDiff
00004 from entity import EntityDiff
00005 from difflib import *
00006 
00007 def compare_lists(list1, list2):
00008     resultlist = []
00009     s = SequenceMatcher(None, list1, list2)
00010     for tag, i1, i2, j1, j2 in s.get_opcodes():
00011         resultlist.append((tag, i1, i2, j1, j2))
00012     return resultlist
00013 
00014 def compare_structures (l10nobject1, l10nobject2):
00015     structure1 = []
00016     structure2 = []
00017     for i in l10nobject1:
00018         if isinstance(i, Entity):
00019             structure1.append(u'E'+i.id)
00020         elif isinstance(i, unicode):
00021             structure1.append(u'U')
00022         elif isinstance(i, Comment):
00023             structure1.append(u'C')
00024     for i in l10nobject2:
00025         if isinstance(i, Entity):
00026             structure2.append(u'E'+i.id)
00027         elif isinstance(i, unicode):
00028             structure2.append(u'U')
00029         elif isinstance(i, Comment):
00030             structure2.append(u'C')
00031     difftype = compare_lists(structure1, structure2)
00032     return difftype
00033 
00034 class L10nObjectDiff(list):
00035     def __init__(self):
00036         list.__init__(self)
00037         self.id = None
00038         self.uri = None
00039 
00040     def empty(self):
00041         return not bool(len(self))
00042 
00043     def get_entitylistdiff(self):
00044         entitylistdiff = EntityListDiff()
00045         entitylistdiff.id = self.id
00046         entitylistdiff.uri = self.uri
00047         entities = self.get_entities(type='all')
00048         for entity in entities.values():
00049             flags = entity.params['diff_flags']
00050             if 'modified' in flags:
00051                 entitylistdiff.add('modified', entity=entity, id=entity.id)
00052             elif 'added' in flags:
00053                 entitylistdiff.add('added', entity=entity, id=entity.id)
00054             elif 'removed' in flags:
00055                 entitylistdiff.add('removed', entity=entity, id=entity.id)
00056         return entitylistdiff
00057 
00058     def get_entity(self, id):
00059         entityList = self.get_entitylistdiff()
00060         try:
00061             return entityList.get_entity(id)
00062         except KeyError:
00063             raise KeyError('No such id: '+id)
00064 
00065     def get_entities(self, type='all'):
00066         (added, removed, modified) = {},{},{}
00067 
00068         def _get_entities_of_type(chunks, type):
00069             current = added if type=='added' else removed
00070             opposite = added if type=='removed' else removed
00071             for elem in chunks:
00072                 if isinstance(elem, Entity):
00073                     if opposite.has_key(elem.id):
00074                         entitydiff = elem.diff(opposite[elem.id])
00075                         if not entitydiff.empty():
00076                             entitydiff.params['diff_flags'] = ['modified']
00077                             modified[elem.id] = entitydiff
00078                         del opposite[elem.id]
00079                     else:
00080                         elem.params['diff_flags'] = type
00081                         current[elem.id] = elem
00082 
00083         for i in self:
00084             if 'modified' in i['flags'] and isinstance(i['elements'][1], EntityDiff):
00085                 if i['elements'][1].has_key('value'):
00086                     modified[i['elements'][0]] = i['elements'][1]
00087                     modified[i['elements'][0]].params['diff_flags'] = i['flags']
00088             elif 'added' in i['flags']:
00089                 _get_entities_of_type(i['elements'], 'added')
00090             elif 'removed' in i['flags']:
00091                 _get_entities_of_type(i['elements'], 'removed')
00092             elif 'replaced' in i['flags']:
00093                 _get_entities_of_type(i['elements'], 'removed')
00094                 _get_entities_of_type(i['elements2'], 'added')
00095         
00096         entities = {}
00097         if type == 'all' or 'modified' in type:
00098             entities.update(modified)
00099         if type == 'all' or 'added' in type:
00100             entities.update(added)
00101         if type == 'all' or 'removed' in type:
00102             entities.update(removed)
00103         return entities
00104 
00105     def get_entities2(self, type='all'):
00106         entities = {}
00107         for i in self:
00108             if 'modified' in i['flags'] and (type=='all' or type=='modified') and isinstance(i['elements'][1], EntityDiff):
00109                 if i['elements'][1].has_key('value'):
00110                     entities[i['elements'][0]] = i['elements'][1]
00111             elif 'added' in i['flags'] and (type=='all' or type=='added'):
00112                 for elem in i['elements']:
00113                     if isinstance(elem, Entity):
00114                         if entities.has_key(elem.id) and \
00115                         isinstance(entities[elem.id], Entity) and \
00116                         'removed' in entities[elem.id].params['diff_flags']:
00117                             entitydiff = elem.diff(entities[elem.id])
00118                             if entitydiff.empty():
00119                                 del entities[elem.id]
00120                             else:
00121                                 entities[elem.id] = entitydiff
00122                         else:
00123                             elem.params['diff_flags'] = i['flags']
00124                             entities[elem.id] = elem
00125             elif 'removed' in i['flags'] and (type=='all' or type=='removed'):
00126                 for elem in i['elements']:
00127                     if isinstance(elem, Entity):
00128                         if entities.has_key(elem.id) and \
00129                              isinstance(entities[elem.id], Entity) and \
00130                              'added' in entities[elem.id].params['diff_flags']:
00131                             entitydiff = elem.diff(entities[elem.id])
00132                             if entitydiff.empty():
00133                                 del entities[elem.id]
00134                             else:
00135                                 entities[elem.id] = entitydiff
00136                         else:
00137                             elem.params['diff_flags'] = i['flags']
00138                             entities[elem.id] = elem
00139             elif 'replaced' in i['flags']:
00140                 if (type=='all' or type=='removed'):
00141                     for elem in i['elements']:
00142                         if isinstance(elem, Entity):
00143                             if entities.has_key(elem.id) and \
00144                             isinstance(entities[elem.id], Entity) and \
00145                             'added' in entities[elem.id].params['diff_flags']:
00146                                 entitydiff = elem.diff(entities[elem.id])
00147                                 if entitydiff.empty():
00148                                     del entities[elem.id]
00149                                 else:
00150                                     entities[elem.id] = entitydiff
00151                             else:
00152                                 elem.params['diff_flags'] = ['removed']
00153                                 entities[elem.id] = elem
00154                 if (type=='all' or type=='added'):
00155                     for elem in i['elements2']:
00156                         if isinstance(elem, Entity):
00157                             if entities.has_key(elem.id) and \
00158                             isinstance(entities[elem.id], Entity) and \
00159                             'removed' in entities[elem.id].params['diff_flags']:
00160                                 entitydiff = elem.diff(entities[elem.id])
00161                                 if entitydiff.empty():
00162                                     del entities[elem.id]
00163                                 else:
00164                                     entities[elem.id] = entitydiff
00165                             else:
00166                                 elem.params['diff_flags'] = ['added']
00167                                 entities[elem.id] = elem
00168         return entities
00169 
00170     def add(self, type, element):
00171         chunk = {'flags':[type]}
00172         chunk['elements'] = element
00173         self.append(chunk)
00174 
00175 def get_prev_elements (self, pos):
00176     prev_elements = []
00177     while len(prev_elements) < 3:
00178         if pos > 0:
00179             pos = pos-1
00180             prev_elements.append(self[pos])
00181         else:
00182             prev_elements.append('BEGIN')
00183             break
00184     return prev_elements
00185 
00186 L10nObject.get_prev_elements = get_prev_elements
00187 
00188 def get_next_elements (self, pos):
00189     next_elements = []
00190     while len(next_elements) < 3:
00191         if pos < len(self):
00192             next_elements.append(self[pos])
00193             pos = pos+1
00194         else:
00195             next_elements.append('END')
00196             break
00197     return next_elements
00198 
00199 L10nObject.get_next_elements = get_next_elements
00200 
00201 
00202 def locate_position (self, prev_elements, next_elements, chunk_size=None, by='any', mode=''):
00203     pos = None
00204     if by == 'any':
00205         pos = self.locate_position(prev_elements, next_elements, chunk_size=chunk_size, by='entity', mode=mode)
00206         if pos == None:
00207             pos = self.locate_position(prev_elements, next_elements, chunk_size=chunk_size, by= 'marker', mode=mode)
00208         return pos
00209 
00210     for p, elem in enumerate(prev_elements):
00211         if by == 'entity' and isinstance(elem, Entity):
00212             pos = self.locate_entity(elem)
00213             if pos != None:
00214                 pos = pos+p+1
00215                 break
00216         elif by == 'marker' and elem == 'BEGIN':
00217             pos = p
00218             break
00219     if pos == None and chunk_size != None:
00220         for p, elem in enumerate(next_elements):
00221             if by == 'entity' and isinstance(elem, Entity):
00222                 pos = self.locate_entity(elem)
00223                 if pos != None:
00224                     pos = pos-p
00225                     break
00226             elif by == 'marker' and elem == 'END':
00227                 pos = len(self)-p
00228                 break
00229         if pos != None and mode == 'added':
00230             pos = pos + 1 # in case we're adding following the nextElements we need to set up position +1
00231         if pos != None:
00232             pos = pos - chunkSize + 1
00233     return pos
00234 
00235 L10nObject.locate_position = locate_position
00236 
00237 
00238 def locate_entity (self, entity):
00239     pos = self.get_entity_position(entity.id)
00240     return pos
00241 
00242 L10nObject.locate_entity = locate_entity
00243 
00244 def locate_comment (cls, l10nobject, comment):
00245     pos = None
00246     for p, i in enumerate(l10nobject.structure):
00247         if isinstance(i, Comment):
00248             pos = p
00249             break
00250     return pos
00251 
00252 L10nObject.locate_comment = locate_comment
00253 
00254 def guess_spacing (cls, l10nobject, pos, spc_num=3, ext='dtd', entity=None):
00255     spacing = 1
00256     return spacing
00257 
00258 L10nObject.guess_spacing = guess_spacing
00259 
00260 def l10nobject_diff (self, l10nobject, flags=None, values=True):
00261     if flags == None:
00262         flags = ['added','removed','modified','replaced']
00263     l10nobject_diff = L10nObjectDiff()
00264     if self.id is not None:
00265         l10nobject_diff.id = self.id
00266     l10nobject_diff.uri = (self.uri, l10nobject.uri)
00267     structure_diff = compare_structures(self, l10nobject)
00268     for pos, elem in enumerate(structure_diff):
00269         if elem[0] == 'insert' and 'added' in flags:
00270             chunk = {'flags':['added']}
00271             chunk['elements'] = l10nobject[elem[3]:elem[4]]
00272             chunk['prev'] = l10nobject.get_prev_elements(elem[3])
00273             chunk['next'] = self.get_next_elements(elem[2])
00274             l10nobject_diff.append(chunk)
00275         elif elem[0] == 'equal' and ('modified' in flags or 'unmodified' in flags):
00276             for i in range(0, elem[2]-elem[1]):
00277                 key = (elem[1]+i, elem[3]+i)
00278                 rec = (self[key[0]], l10nobject[key[1]])
00279                 if isinstance(rec[0], unicode):
00280                     if values is False or rec[0]==rec[1]:
00281                         if 'unmodified' in flags:
00282                             chunk = {'flags': ['unmodified'], 'elements': rec[0]}
00283                         else:
00284                             continue
00285                     else:
00286                         if 'modified' in flags:
00287                             chunk = {'flags': ['modified'], 'elements': (rec[0], rec[1])}
00288                         else:
00289                             continue
00290                     chunk['prev'] = l10nobject.get_prev_elements(key[1])
00291                     chunk['next'] = self.get_next_elements(key[0]+1)
00292                 elif isinstance(rec[0], Entity):
00293                     if values is True:
00294                         entity_diff = rec[0].diff(rec[1], struct=True)
00295                         if entity_diff.empty():
00296                             if 'unmodified' in flags:
00297                                 chunk = {'flags': ['unmodified'], 'elements': rec[0]}
00298                             else:
00299                                 continue
00300                         else:
00301                             if 'modified' in flags:
00302                                 chunk = {'flags': ['modified'], 'elements': (rec[0].id, entity_diff)}
00303                             else:
00304                                 continue
00305                     else:
00306                         if 'unmodified' in flags:
00307                             chunk = {'flags': ['unmodified'], 'elements': rec[0]}
00308                         else:
00309                             continue
00310                     chunk['prev'] = l10nobject.get_prev_elements(key[1])
00311                     chunk['next'] = self.get_next_elements(key[0]+1)
00312                 elif isinstance(rec[0], Comment):
00313                     comment_diff = rec[0].diff(rec[1], flags=flags, values=values)
00314                     if comment_diff.empty():
00315                         if 'unmodified' in flags:
00316                             chunk = {'flags': ['unmodified'], 'elements': rec[0]}
00317                         else:
00318                             continue
00319                     else:
00320                         if 'modified' in flags:
00321                             chunk = {'flags': ['modified'], 'elements': ('comment', comment_diff)}
00322                         else:
00323                             continue
00324                     chunk['prev'] = l10nobject.get_prev_elements(key[1])
00325                     chunk['next'] = self.get_next_elements(key[0]+1)
00326                 l10nobject_diff.append(chunk)
00327         elif elem[0] == 'replace' and 'replaced' in flags:
00328             chunk = {'flags': ['replaced']}
00329             chunk['elements'] = []
00330             chunk['elements2'] = []
00331             chunk['prev'] = l10nobject.get_prev_elements(elem[3])
00332             chunk['next'] = self.get_next_elements(elem[2])
00333             for i in range(0, elem[2]-elem[1]):
00334                 chunk['elements'].append(self[elem[1]+i])
00335             for i in range(0, elem[4]-elem[3]):
00336                 chunk['elements2'].append(l10nobject[elem[3]+i])
00337             l10nobject_diff.append(chunk)
00338         elif elem[0] == 'delete' and 'removed' in flags:
00339             chunk = {'flags': ['removed']}
00340             chunk['elements'] = self[elem[1]:elem[2]]
00341             chunk['prev'] = l10nobject.get_prev_elements(elem[3])
00342             chunk['next'] = self.get_next_elements(elem[2])
00343             l10nobject_diff.append(chunk)
00344     return l10nobject_diff
00345 
00346 L10nObject.diff = l10nobject_diff
00347 
00348 def apply_entitylist_diff(self, entitylist_diff):
00349     for i in entitylist_diff:
00350         if 'modified' in entitylist_diff[i]['flags']:
00351             for el in self:
00352                 if isinstance(el, Entity) and el.id == i:
00353                     el.set_value(entitylist_diff[i]['elem'].get_value()[1])
00354         elif 'added' in entitylist_diff[i]['flags']:
00355             self.addEntity(entitylist_diff[i]['elem'])
00356         elif 'removed' in entitylist_diff[i]['type']:
00357             self.removeEntity(i)
00358 
00359 L10nObject.apply_entitylist_diff = apply_entitylist_diff
00360 
00361 def apply_l10nobject_diff (self, l10nobject_diff):
00362     if isinstance(l10nobject_diff, EntityListDiff):
00363         self.apply_entitylist_diff(l10nobject_diff)
00364         return
00365     for i in l10nobject_diff:
00366         if 'added' in i["flags"]:
00367             pos = self.locate_position(i['prev'], i['next'], chunk_size=len(i['elements']), mode='added')
00368             if pos != None:
00369                 self[pos:pos] = i['elements']
00370         if 'modified' in i["flags"]:
00371             element = i['elements']
00372             if isinstance(element[1], EntityDiff):
00373                 pos = self.get_entity_position(element[0])
00374                 self[pos].apply_diff(element[1])
00375             elif isinstance(element[0], Comment):
00376                 pos = self.locate_position(i['prev'], i['next'], chunk_size=len(i['elements']))
00377                 self[pos] = element[1]
00378             elif isinstance(element[0], unicode):
00379                 pos = self.locate_position(i['prev'], i['next'], chunk_size=len(i['elements']))
00380                 if self[pos] == element[0]:
00381                     self[pos] = element[1]
00382         if 'replaced' in i["flags"]:
00383             pos = self.locate_position(i['prev'], i['next'], chunk_size=len(i['elements']))
00384             if pos != None:
00385                 self[pos:pos+1] = i['elements2']
00386         if 'removed' in i['flags']:
00387             pos = self.locate_position(i['prev'], i['next'], chunk_size=len(i['elements']))
00388             self[pos:pos+len(i['elements'])] = []
00389 
00390 L10nObject.apply_diff = apply_l10nobject_diff

Generated on Tue May 12 17:37:27 2009 for silme by  doxygen 1.5.8