history.py 9.46 KB
#-*- coding:utf-8 -*-

from django.core.exceptions import ObjectDoesNotExist
from dictionary.models import Lexeme, LexemeInflectionPattern, \
  Pattern, InflectionCharacteristic, ClassificationValue, Qualifier, History, \
  CrossReferenceType

attribute_translation = {
  # Leksem
  ('leksemy', 'haslo'): u'hasło',
  ('leksemy', 'haslosuf'): u'sufiks hasła',
  ('leksemy', 'glosa'): u'glosa',
  ('leksemy', 'pos'): u'część mowy',
  ('leksemy', 'slownik'): u'słownik właściciel',
  ('leksemy', 'status'): u'status',
  ('leksemy', 'komentarz'): u'komentarz',
  # Odmiana
  ('odmieniasie', 'oind'): u'kolejność',
  ('odmieniasie', 'charfl'): u'charakterystyka fleksyjna',
  ('odmieniasie', 'w_id'): u'wzór',
}

# brzydkie - do pokazywania usuniętych leksemów
attribute_translation_list = [
  # Leksem
  ('leksemy', 'haslo', u'hasło'),
  ('leksemy', 'haslosuf', u'sufiks hasła'),
  ('leksemy', 'glosa', u'glosa'),
  ('leksemy', 'pos', u'część mowy'),
  ('leksemy', 'slownik', u'słownik właściciel'),
  ('leksemy', 'status', u'status'),
  ('leksemy', 'komentarz', u'komentarz'),
  # Odmiana
  ('odmieniasie', 'oind', u'kolejność'),
  ('odmieniasie', 'charfl', u'charakterystyka fleksyjna'),
  ('odmieniasie', 'w_id', u'wzór'),
]

lexeme_attribute_order = [
  u'hasło',
  u'sufiks hasła',
  u'glosa',
  u'część mowy',
  u'słownik właściciel',
  u'status',
  u'komentarz',
  #u'kwalifikator',
  #u'klasyfikacja',
  #u'slownik',
  #u'odsyłacz',
]

def get_lexeme_attr(attr, lexeme):
  if attr == 'haslo':
    return lexeme.entry
  elif attr == 'haslosuf':
    return lexeme.entry_suffix
  elif attr == 'glosa':
    return lexeme.gloss
  elif attr == 'pos':
    return lexeme.part_of_speech.symbol
  elif attr == 'slownik':
    return lexeme.owner_vocabulary.id
  elif attr == 'status':
    return lexeme.status
  elif attr == 'komentarz':
    return lexeme.comment

def get_lip_attr(attr, lip):
  if attr == 'oind':
    return lip.index
  elif attr == 'charfl':
    return lip.inflection_characteristic.entry
  elif attr == 'w_id':
    return lip.pattern.name

lip_attribute_order = [
  u'kolejność',
  u'charakterystyka fleksyjna',
  u'wzór',
  #u'kwalifikator',
]

def prepare_value(table, column, value):
  try:
    if column == 'qualifier_id':
      prepared = Qualifier.all_objects.get(pk=int(value)).label
    elif column == 'status':
      prepared = dict(Lexeme.STATUS_CHOICES).get(value)
    elif column == 'charfl':
      prepared = InflectionCharacteristic.objects.get(pk=int(value)).entry
    elif column == 'w_id':
      prepared = Pattern.objects.get(pk=int(value)).name
    elif column == 'classificationvalue_id':
      cv = ClassificationValue.all_objects.get(pk=int(value))
      prepared = (cv.label, cv.classification.name)
    else:
      prepared = value
  except ObjectDoesNotExist:
    prepared = None
  except ValueError:
    prepared = None
  return prepared

def transaction_table(transaction_data):
  transaction_dict = {}
  lips = {}
  classifications = []
  qualifiers = []
  vocabs = []
  crs = {}
  lip_qualifiers = {}
  deleted = False
  for item1 in transaction_data:
    table = item1.table_name
    column = item1.column_name
    if (table == 'leksemy' and column == 'usuniety' and
        item1.new_value == 'true' and item1.old_value == 'false'):
      deleted = True
    attr = None
    if (table, column) in attribute_translation:
      attr = attribute_translation[(table, column)]
    before, after = tuple(
      prepare_value(table, column, v)
      for v in (item1.old_value, item1.new_value))
    before_after = (
      before if item1.operation != 'INSERT' else None,
      after if item1.operation != 'DELETE' else None)
    if attr:
      if table not in ('odmieniasie', 'kwalifikatory_odmieniasiow'):
        transaction_dict[attr] = before_after
      elif table == 'odmieniasie':
        if item1.row_id not in lips:
          lips[item1.row_id] = {}
        lips[item1.row_id][attr] = before_after
    if column == 'classificationvalue_id':
      classifications.append(before_after)
    if table == 'kwalifikatory_leksemow' and column == 'qualifier_id':
      qualifiers.append(before_after)
    if table == 'leksemy_w_slownikach' and column == 'slownik':
      vocabs.append(before_after)
    if table == 'odsylacze':
      if item1.row_id not in crs:
        crs[item1.row_id] = {}
      crs[item1.row_id][column] = before_after
    if table == 'kwalifikatory_odmieniasiow':
      if item1.row_id not in lip_qualifiers:
        lip_qualifiers[item1.row_id] = {}
      if column: # stare DELETE nie będą widoczne
        lip_qualifiers[item1.row_id][column] = before_after
  if deleted:
    return deleted_lexeme_table(transaction_data[0].lexeme)
  rows = []
  for attr in lexeme_attribute_order:
    if attr in transaction_dict:
      rows.append((attr, transaction_dict[attr]))
  for before_after in qualifiers:
    rows.append((u'kwalifikator', before_after))
  for before, after in classifications:
    if before:
      classification_name = before[1]
      before = before[0]
    if after:
      classification_name = after[1]
      after = after[0]
    attr = u'klasyfikacja: %s' % classification_name
    rows.append((attr, (before, after)))
  for before_after in vocabs:
    rows.append((u'słownik', before_after))
  for cr_data in crs.itervalues():
    attr = u'odsyłacz'
    before_after = []
    for i in (0, 1):
      try:
        if cr_data['l_id_do'][i] is not None:
          l = Lexeme.all_objects.get(pk=int(cr_data['l_id_do'][i]))
          ic = l.lip_data()['inflection_characteristics']
          cr_type = CrossReferenceType.objects.get(pk=cr_data['typods_id'][i])
          prepared = ' '.join((cr_type.symbol, unicode(l), ic))
        else:
          prepared = None
      except Lexeme.DoesNotExist:
        prepared = None
      before_after.append(prepared)
    rows.append((attr, tuple(before_after)))
  lip_dict = {}
  for lip_id, lip_data in lips.iteritems():
    lip_dict[lip_id] = []
    for attr in lip_attribute_order:
      if attr in lip_data:
        lip_dict[lip_id].append((attr, lip_data[attr]))
  for q_data in lip_qualifiers.itervalues():
    if q_data: # stare DELETE...
      attr = u'kwalifikator'
      lip_data = q_data['lexemeinflectionpattern_id']
      lip_id = int(lip_data[0] or lip_data[1])
      if lip_id not in lips:
        lip_dict[lip_id] = []
      lip_dict[lip_id].append((attr, q_data['qualifier_id']))
  lip_tables = []
  for lip_id, lip_data in lip_dict.iteritems():
    lip = LexemeInflectionPattern.all_objects.filter(pk=lip_id)
    if lip:
      lip = lip[0]
      header = '%s/%s' % (lip.inflection_characteristic.entry, lip.pattern.name)
    else:
      records = History.objects.filter(
        operation='DELETE', table_name='odmieniasie', row_id=lip_id)
      try:
        ic_id = records.get(column_name='charfl').old_value
        pattern_id = records.get(column_name='w_id').old_value
        ic = InflectionCharacteristic.objects.get(pk=ic_id)
        pattern = Pattern.objects.get(pk=pattern_id)
        header = u'%s/%s ' % (ic.entry, pattern.name)
      except ObjectDoesNotExist: # stare DELETE...
        header = ''
      header += u'(usunięta)'
    lip_tables.append((header, lip_data))
  return rows, lip_tables

def deleted_lexeme_table(lexeme):
  rows = []
  for table, column, attr in attribute_translation_list:
    if table == 'leksemy':
      rows.append(
        (attr,
         (prepare_value(table, column, get_lexeme_attr(column, lexeme)),
          None)))
  for q in lexeme.qualifiers.all():
    rows.append((u'kwalifikator', (q.label, None)))
  for classification in lexeme.owner_vocabulary.classifications.all():
    attr = u'klasyfikacja: %s' % classification.name
    cvs = lexeme.classification_values(classification)
    for cv in cvs:
      rows.append((attr, (cv.label, None)))
  for vocab in lexeme.vocabularies.all():
    rows.append((u'słownik', (vocab.id, None)))
  for cr in lexeme.refs_to.all():
    attr = u'odsyłacz'
    rows.append((attr, (
      ' '.join([cr.type.symbol, cr.to_lexeme.entry,
                cr.to_lexeme.lip_data()['inflection_characteristics']]), None)))
  lip_tables = []
  for lip in lexeme.lexemeinflectionpattern_set.all():
    lip_data = []
    for table, column, attr in attribute_translation_list:
      if table == 'odmieniasie':
        lip_data.append((attr, (get_lip_attr(column, lip), None)))
    for q in lip.qualifiers.all():
      attr = u'kwalifikator'
      lip_data.append((attr, (q.label, None)))
    header = '%s/%s' % (lip.inflection_characteristic.entry, lip.pattern.name)
    lip_tables.append((header, lip_data))
  return rows, lip_tables

def lexeme_table(transaction_data, last_tb):
  rows, lip_tables = transaction_table(transaction_data)
  try:
    lexeme = transaction_data[0].lexeme
  except Lexeme.DoesNotExist:
    lexeme = u'(usunięty)' # aktualnie niemożliwe
  return {
    'rows': rows,
    'lip_tables': lip_tables,
    'user': transaction_data[0].user,
    'date': last_tb,
    'lexeme': lexeme,
  }

def lexeme_table_from_row(row):
  transaction_data = History.objects.filter(
    lexeme__pk=row['lexeme'], user__pk=row['user'],
    transaction_began=row['transaction_began'])
  return lexeme_table(transaction_data, row['transaction_began'])

def lexeme_tables(history_items):
  transaction_data = []
  last_tb = None
  for item in history_items:
    if last_tb and item.transaction_began != last_tb:
      yield lexeme_table(transaction_data, last_tb)
      transaction_data = []
    last_tb = item.transaction_began
    transaction_data.append(item)
  if transaction_data:
    yield lexeme_table(transaction_data, last_tb)