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

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

attribute_translation = {
  # Leksem
  ('leksemy', 'haslo'): u'hasło',
  ('leksemy', 'haslosuf'): u'sufiks hasła',
  ('leksemy', 'glosa'): u'glosa',
  ('leksemy', 'nota'): u'nota',
  ('leksemy', 'wymowa'): u'wymowa',
  ('leksemy', 'valence'): u'łączliwość',
  ('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', 'nota', u'nota'),
  ('leksemy', 'wymowa', u'wymowa'),
  ('leksemy', 'valence', u'łączliwość'),
  ('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'nota',
  u'wymowa',
  u'łączliwość',
  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 == 'wymowa':
    return lexeme.pronunciation
  elif attr == 'nota':
    return lexeme.note
  elif attr == 'valence':
    return lexeme.valence
  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.symbol
  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)).symbol
    elif column == 'w_id':
      prepared = Pattern.objects.get(pk=int(value)).name
    elif column in ('classification_value_id', 'classificationvalue_id'):
      cv = ClassificationValue.all_objects.get(pk=int(value))
      prepared = (cv.label, cv.classification.name)
    elif column == 'attribute_value_id':
      av = LexemeAttributeValue.objects.get(pk=int(value))
      prepared = (av.value, av.attribute.name)
    else:
      prepared = value
  except ObjectDoesNotExist:
    prepared = None
  except ValueError:
    prepared = None
  return prepared

def transaction_table(transaction_data):
  transaction_dict = {}
  lips = GroupDict()
  extra_attributes = {}
  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 == 'attribute_value_id':
      if before:
        value, attr = before
        which = 0
      else: # after
        value, attr = after
        which = 1
      if attr not in extra_attributes:
        extra_attributes[attr] = ([], [])
      extra_attributes[attr][which].append(value)
    if column in ('classification_value_id', 'classificationvalue_id'):
      if before:
        value, classification_name = before
        which = 0
      else: # after
        value, classification_name = after
        which = 1
      if classification_name not in classifications:
        classifications[classification_name] = ([], [])
      classifications[classification_name][which].append(value)
    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 attr, (before, after) in extra_attributes.iteritems():
    rows.append((attr, (', '.join(before) or None, ', '.join(after) or None)))
  for before_after in qualifiers:
    rows.append((u'kwalifikator', before_after))
  for name, (before, after) in classifications.iteritems():
    attr = u'klasyfikacja: %s' % name
    rows.append((attr, (', '.join(before) or None, ', '.join(after) or None)))
  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 = GroupDict()
  for lip_id, lip_data in lips.iteritems():
    for attr in lip_attribute_order:
      if attr in lip_data:
        lip_dict.add(lip_id, (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])
      lip_dict.add(lip_id, (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.symbol, 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.symbol, 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.symbol, 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)