Skip to content
Snippets Groups Projects
views.py 47.37 KiB
import json
import requests
import simplejson
from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.http import JsonResponse, HttpResponse
from django.shortcuts import get_object_or_404
from django.test import override_settings
from django.views.decorators.csrf import csrf_exempt

from common.decorators import ajax_required, ajax
from connections.models import SchemaHook, ExampleConnection
from entries.polish_strings import EXAMPLE_SOURCE, EXAMPLE_OPINION
from entries.views import get_scroller_params, get_alternations, get_prefs_list, schema2dict, \
    frame2dict, collect_forms, get_filtered_objects, get_local_schema_filter_form, get_local_frame_filter_form
from financial_settlement.models import FinStatement
from importer.unification.UnificationPreprocessXML import UnificationPreprocessHandler
from meanings.models import LexicalUnit
from semantics.choices import FrameStatus
from semantics.models import Frame, ArgumentRole, SemanticRole, RoleAttribute, RoleType, RoleSubAttribute, \
    PredefinedSelectionalPreference, Argument
from syntax.models import Schema
from unifier.models import UnifiedFrameArgument, UnifiedRelationalSelectionalPreference, UnifiedFrame, \
    UnifiedFrame2SlowalFrameMapping, UnifiedFrameArgumentSlowalFrameMapping, HierarchyModel
from users.models import Assignment
from . import choices
from xml.etree.ElementTree import Element, SubElement, tostring
import io
from xml.sax import handler, make_parser
from django.db.models import Q, Prefetch

from django.conf import settings
import logging

from django.views.decorators.csrf import csrf_exempt

import urllib3

from .apps import synset_hierarchy_dict, SynsetHierarchy
from .choices import UnifiedFrameStatus


def get_predefined_preference_synsets(predefined, list_to_fill):
    for pp in predefined:
        if pp.members:
            synsets_all = pp.members.synsets.all()
            list_to_fill.extend(list(map(lambda s: s.id, synsets_all)))
            generals_all = pp.members.generals.all()
            if generals_all:
                get_predefined_preference_synsets(generals_all, list_to_fill)


@ajax_required
@transaction.atomic
def save_synset_preference(request):
    if request.method == 'POST':
        frame_id = request.POST['frame_id']
        complement_id = request.POST['complement_id']
        synset_preference_id = request.POST['synset_preference_id']

        check_sysnet_hierarchy_constraints_ret = save_synset_preference_base(frame_id, complement_id, synset_preference_id)

        return JsonResponse(check_sysnet_hierarchy_constraints_ret)

    return JsonResponse({})


def save_synset_preference_base(frame_id, complement_id, synset_preference_id):

    unified_frame_argument = UnifiedFrameArgument.objects.get(unified_frame_id=int(frame_id), id=int(complement_id))

    check_sysnet_hierarchy_constraints_ret = check_sysnet_hierarchy_constraints([synset_preference_id], unified_frame_argument)

    if check_sysnet_hierarchy_constraints_ret['succ'] is True:
        unified_frame_argument.synsets.add(int(synset_preference_id))
        unified_frame_argument.save()
        update_argument_preferences_count(unified_frame_argument)

    return check_sysnet_hierarchy_constraints_ret


def check_sysnet_hierarchy_constraints(synset_preference_ids, unified_frame_argument):
    synset_ids_map = map(lambda s: s.id, unified_frame_argument.synsets.all())
    predefined_synset_ids = []
    get_predefined_preference_synsets(unified_frame_argument.predefined.all(), predefined_synset_ids)
    synset_ids_list = list(synset_ids_map)
    synset_ids_list.extend(predefined_synset_ids)

    for synset_preference_id in synset_preference_ids:
        conflict_hyponym, conflict_hyperonym, conflict_exists = synset_hierarchy_constraint_check(int(synset_preference_id),
                                                                                 set(synset_ids_list))
        if conflict_hyponym is None and conflict_hyperonym is None and conflict_exists is None:
            return {"succ": True}
        else:
            conflict_exists_lu_str = conflict_lu_to_str(conflict_exists)
            conflict_hyponym_lu_str = conflict_lu_to_str(conflict_hyponym)
            conflict_hyperonym_lu_str = conflict_lu_to_str(conflict_hyperonym)

            ret = {"succ": False, "conflict_hyponym": conflict_hyponym_lu_str,
                                   "conflict_hyperonym": conflict_hyperonym_lu_str,
                                   "conflict_exists": "Wybrana preferencja selekcyjna nie mogła zostać zapisana ponieważ widnieje już na liście preferencji selekcyjnych: " + conflict_exists_lu_str if conflict_exists_lu_str is not None else None}

    return ret


def conflict_lu_to_str(conflict_lu):
    conflict_hyponym_lu = LexicalUnit.objects.filter(
        synset_id=conflict_lu) if conflict_lu is not None else None
    return ','.join(
        map(lambda s: str(s), conflict_hyponym_lu.all())) if conflict_lu is not None else None


# class MyException(Exception):
#     def __init__(self, message, errors):
#         super().__init__(message)
#         self.errors = errors


@ajax_required
@transaction.atomic
def save_bunch_of_preferences(request):
    if request.method == 'POST':
        frame_id = request.POST['frame_id']
        complement_id = request.POST['complement_id']
        predefined_preference_ids = json.loads(request.POST['predefined_preference_ids'])
        synset_ids = json.loads(request.POST['synset_preference_ids'])

        check_sysnet_hierarchy_constraints_ret = save_bunch_of_preferences_base(frame_id, complement_id, predefined_preference_ids, synset_ids)
        return JsonResponse(check_sysnet_hierarchy_constraints_ret)

    return JsonResponse({})


@transaction.atomic
def save_bunch_of_preferences_base(frame_id, complement_id, predefined_preference_ids, synset_ids):
    for predefined_preference_id in predefined_preference_ids:
        check_sysnet_hierarchy_constraints_ret = save_predefined_preference_base(frame_id, complement_id, predefined_preference_id)
        if check_sysnet_hierarchy_constraints_ret['succ'] is False:
            transaction.set_rollback(True)
            return check_sysnet_hierarchy_constraints_ret

    for synset_id in synset_ids:
        check_sysnet_hierarchy_constraints_ret = save_synset_preference_base(frame_id, complement_id, synset_id)
        if check_sysnet_hierarchy_constraints_ret['succ'] is False:
            transaction.set_rollback(True)
            return check_sysnet_hierarchy_constraints_ret

    return {'succ': True}

@ajax_required
@transaction.atomic
def save_predefined_preference(request):
    if request.method == 'POST':
        frame_id = request.POST['frame_id']
        complement_id = request.POST['complement_id']
        predefined_preference_id = request.POST['predefined_preference_id']

        check_sysnet_hierarchy_constraints_ret = save_predefined_preference_base(frame_id, complement_id, predefined_preference_id)

        return JsonResponse(check_sysnet_hierarchy_constraints_ret)

    return JsonResponse({})


@transaction.atomic
def save_predefined_preference_base(frame_id, complement_id, predefined_preference_id):
    unified_frame_argument = UnifiedFrameArgument.objects.get(unified_frame_id=int(frame_id), id=int(complement_id))

    predefined_synset_ids = []
    pred_sel_pref = PredefinedSelectionalPreference.objects.get(id=predefined_preference_id)
    if pred_sel_pref.name == 'ALL' and len(unified_frame_argument.predefined.all()) > 0:
        return {"succ": False, "conflict_hyponym": None,
                                            "conflict_hyperonym": None,
                                            "conflict_exists": "Predefiniowana preferencja selekcyjna ALL może być dodana tylko, gdy nie na liście nie widnieją inne preferencje selekcyjne."}
    else:
        get_predefined_preference_synsets([pred_sel_pref], predefined_synset_ids)

        check_sysnet_hierarchy_constraints_ret = check_sysnet_hierarchy_constraints(predefined_synset_ids, unified_frame_argument)

        if check_sysnet_hierarchy_constraints_ret['succ'] is True:
            unified_frame_argument.predefined.add(int(predefined_preference_id))
            unified_frame_argument.save()
            update_argument_preferences_count(unified_frame_argument)

        return check_sysnet_hierarchy_constraints_ret


@ajax_required
@transaction.atomic
def save_relational_selectional_preference(request):
    if request.method == 'POST':
        frame_id = request.POST['frame_id']
        complement_id_from = request.POST['complement_id_from']
        complement_id_to = request.POST['complement_id_to']
        relation_id = request.POST['relation_id']

        unified_frame_argument = UnifiedFrameArgument.objects.get(unified_frame_id=int(frame_id),
                                                                  id=int(complement_id_from))
        relational_selectional_preference = UnifiedRelationalSelectionalPreference(to_id=complement_id_to,
                                                                                   relation_id=relation_id)
        relational_selectional_preference.save()
        unified_frame_argument.relations.add(relational_selectional_preference)
        unified_frame_argument.save()

        update_argument_preferences_count(unified_frame_argument)

    return JsonResponse({})


@ajax_required
def get_unified_frames(request):
    if request.method == 'POST':
        scroller_params = get_scroller_params(request.POST)
        exclude_status = request.GET.get('exclude_status')
        restrict_to_user = request.GET.get('restrict_to_user')

        scroller_params = get_scroller_params(request.POST)

        first_index, last_index = scroller_params['start'], scroller_params['start'] + scroller_params['length']
        order_field, order_dir = scroller_params['order']
        if order_field == 0:
            order_field = 'title'
        elif order_field == 1:
            order_field = 'status'
        else:
            order_field = None

        if order_dir == 'desc' and order_field is not None:
            order_field = '-' + order_field

        errors_dict = dict()

        if 'unified_frame_form' in request.session:
            forms = collect_forms(request.session['unified_frame_form'], errors_dict)
            unified_frames = get_filtered_objects(forms).filter()
        else:
            unified_frames = UnifiedFrame.objects

        records_total = unified_frames.count()

        if order_field is not None:
            unified_frames = unified_frames.order_by(order_field)

        unified_frames = unified_frames.all()

        if scroller_params['filter']:
            unified_frames = unified_frames.filter(title__startswith=scroller_params['filter'])

        # TODO: zapytać, czy mamy zaciągać powiązane ramy zunifikowane poprzez Enrty (slowal_frame -> lexical_units -> entries -> related_entries)
        # linked_ids = set()
        # if request.session['show_linked_entries']:
        #     entries_linked = Entry.objects.filter(pk__in=(
        #         Entry.objects
        #             .filter(subentries__schema_hooks__argument_connections__schema_connections__subentry__entry__in=entries)
        #             .exclude(id__in=entries)
        #     )).distinct()
        #     entries = entries | entries_linked
        #     linked_ids = set(entries_linked.values_list('id', flat=True))

        res = {}

        for unifiedFrame in unified_frames:
            user = assignment.user.username if (
                assignment := unifiedFrame.assignments.first()) else None
            res[unifiedFrame.id] = {
                'id': str(unifiedFrame.id),
                'title': unifiedFrame.title,
                'status': unifiedFrame.status,
                'assignee_username': user,
                'hierarchy_exists': unifiedFrame.hasHierarchyElems,
            }

        res_processed = []
        for key, value in res.items():
            if ((exclude_status is None or value['status'] != exclude_status) and
                    (restrict_to_user is None or value['assignee_username'] == restrict_to_user)) or \
                    value['status'] == choices.UnifiedFrameStatus.VERIFIED:
                res_processed.append(value)

        records_filtered = len(res_processed)

        res_processed = res_processed[first_index:last_index]

        ret = {
            'draw': scroller_params['draw'],
            'recordsTotal': records_total,
            'recordsFiltered': records_filtered,
            'data': res_processed
        }

        return JsonResponse(ret)
    return JsonResponse({})


def unified_frame_2_dict(frame):
    return {
        'id': frame.id,
        'title': frame.title,
        'status': str(frame.status),
        'assignee_username': assignment.user.username if (assignment := frame.assignments.first()) else None,
        'arguments': [
            {
                'str': str(a),
                'id': a.id,
                'role': {
                    'str': '{}{}{}'.format(a.role.role.role.lower(),
                                           ' ' + a.role.attribute.attribute.lower() if a.role.attribute else '',
                                           ' (' + a.role.sub_attribute.sub_attribute.lower() + ')'
                                           if a.role.sub_attribute else '')
                    if a.role is not None else None,
                    'id': str(a.role.id)
                } if a.role is not None else None,
                'role_type': a.role_type.type.lower() if a.role_type is not None else '',
                'preferences': get_prefs_list(a),
                'proposed_roles': [{
                    'str': '{}{}'.format(r.role.role.lower(),
                                         ' ' + r.attribute.attribute.lower() if r.attribute else ''),
                    'id': str(r.id)
                } for r in a.proposed_roles.all()],
            } for a in sorted(frame.unified_arguments.all(), key=lambda x: x.id)
        ],

        'slowal_frame_mapping': [
            {
                'slowal_frame_id': slowal_frame_mapping.slowal_frame.id,
                'slowal_frame_argument_mapping': [
                    {
                        'unified_frame_agrument_id': slowal_frame_arg_mapping.unified_agrument.id,
                        'slowal_frame_agrument_id': slowal_frame_arg_mapping.slowal_agrument.id,
                    } for slowal_frame_arg_mapping in slowal_frame_mapping.unified_frame_argument_mapping.all()
                ]
            } for slowal_frame_mapping in frame.unified_frame_2_slowal_frame.all()
        ]

    }


def get_examples(frames):
    examples = []
    for frame in frames:
        for argument in frame.arguments.all():
            for connection in argument.example_connections.all():
                example = connection.example
                frame_ids, argument_ids, lu_ids = set(), set(), set()
                schema_ids, phrases, phrases_syntax = set(), set(), set()
                positions = set()
                for example_connection in example.example_connections.all():
                    for conn_argument in example_connection.arguments.all():
                        frame_ids.add(conn_argument.frame.id)
                        argument_ids.add('{}-{}'.format(conn_argument.frame.id, conn_argument.id))
                    if example_connection.lexical_unit:
                        lu_ids.add(example_connection.lexical_unit.id)
                    for hook in example_connection.schema_connections.all():
                        schema_ids.add(hook.schema.id)
                        phrases.add('{}-{}-{}-{}'.format(hook.schema.id, hook.position.id, hook.phrase_type.id,
                                                         hook.alternation - 1))
                        phrases_syntax.add('{}-{}-{}'.format(hook.schema.id, hook.position.id, hook.phrase_type.id))
                        positions.add('{}-{}'.format(hook.schema.id, hook.position.id))
                elem = {
                    'id': str(example.id),
                    'sentence': example.sentence,
                    'source': EXAMPLE_SOURCE()[example.source.key],
                    'opinion': EXAMPLE_OPINION()[example.opinion.key],
                    'note': example.note,
                    'frame_ids': sorted(frame_ids),
                    'argument_ids': sorted(argument_ids),
                    'lu_ids': sorted(lu_ids),
                    'schema_ids': sorted(schema_ids),
                    'phrases': sorted(phrases),
                    'phrases_syntax': sorted(phrases_syntax),
                    'positions': sorted(positions),
                }
                if elem not in examples:
                    examples.append(elem)
    return sorted(examples, key=lambda x: x['sentence'])


def to_lemma(lexical_units):
    return ", ".join(map(lambda l: l['str'], lexical_units))


# @override_settings(DEBUG=True)
def get_unified_frame_json(unified_frame, request):
    local_schema_filter_form = None
    local_frame_filter_form = None

    if 'no_filters' in request.POST:
        apply_filters = not simplejson.loads(request.POST['no_filters'])
        local_schema_filter_form = get_local_schema_filter_form(apply_filters, request)
        local_frame_filter_form = get_local_frame_filter_form(apply_filters, request)

    slowal_frames_db = Frame.objects.filter(
        id__in=unified_frame.unified_frame_2_slowal_frame.values("slowal_frame_id")).distinct()

    if local_frame_filter_form:
        slowal_frames_db = get_filtered_objects(local_frame_filter_form, slowal_frames_db)

    slowal_frames_db = slowal_frames_db.select_related("opinion")

    # slowal_frames_db = slowal_frames_db.prefetch_related(
    #     Prefetch(
    #         'lexical_units',
    #         queryset=LexicalUnit.objects
    #     ),
    #     Prefetch(
    #         'arguments',
    #         queryset=Argument.objects.select_related("role", "role__role", "role__attribute", "role__sub_attribute").prefetch_related(
    #             Prefetch(
    #                 'example_connections',
    #                 queryset=ExampleConnection.objects.select_related('example', 'lexical_unit').prefetch_related(
    #                     Prefetch(
    #                         'arguments',
    #                         queryset=Argument.objects
    #                     ),
    #                     Prefetch(
    #                         'schema_connections',
    #                         queryset=SchemaHook.objects
    #                     )
    #                 )
    #             )
    #         )
    #     )
    # )

    slowal_frames_db = slowal_frames_db.prefetch_related("arguments__role__role")
    slowal_frames_db = slowal_frames_db.prefetch_related("arguments__role__attribute")
    slowal_frames_db = slowal_frames_db.prefetch_related("arguments__role__sub_attribute")
    slowal_frames_db = slowal_frames_db.prefetch_related("arguments__example_connections__example")
    slowal_frames_db = slowal_frames_db.prefetch_related("arguments__example_connections__example__example_connections__arguments")
    slowal_frames_db = slowal_frames_db.prefetch_related("arguments__example_connections__example__example_connections__lexical_unit")
    slowal_frames_db = slowal_frames_db.prefetch_related("arguments__example_connections__example__example_connections__schema_connections")

    slowal_frames = slowal_frames_db.all()

    slowal_frames_dict = []
    for slowal_frame in slowal_frames:
        dict = frame2dict(slowal_frame, slowal_frame.lexical_units.all())
        slowal_frames_dict.append(dict)

    all_schema_objects = Schema.objects.filter(
        schema_hooks__argument_connections__argument__frame__in=slowal_frames).distinct()

    if local_schema_filter_form:
        all_schema_objects = get_filtered_objects(local_schema_filter_form, all_schema_objects)

    all_schema_objects = all_schema_objects.select_related("opinion")
    all_schema_objects = all_schema_objects.prefetch_related("positions")
    all_schema_objects = all_schema_objects.prefetch_related("schema_hooks")
    all_schema_objects = all_schema_objects.prefetch_related("schema_hooks__argument_connections")

    all_schema_objects = all_schema_objects.prefetch_related("positions__function")
    all_schema_objects = all_schema_objects.prefetch_related("positions__control")
    all_schema_objects = all_schema_objects.prefetch_related("positions__pred_control")
    all_schema_objects = all_schema_objects.prefetch_related("positions__phrase_types")

    all_schema_objects = all_schema_objects.prefetch_related("positions__phrase_types__main_type")
    all_schema_objects = all_schema_objects.prefetch_related("positions__phrase_types__attributes")
    all_schema_objects = all_schema_objects.prefetch_related("positions__phrase_types__lexicalized_phrase")
    all_schema_objects = all_schema_objects.prefetch_related("positions__phrase_types__lemma_operator")
    all_schema_objects = all_schema_objects.prefetch_related("positions__phrase_types__lemma_cooccur")
    all_schema_objects = all_schema_objects.prefetch_related("positions__phrase_types__lemmata")

    slowal_frames_dict = sorted(slowal_frames_dict, key=lambda x: to_lemma(x['lexical_units']))

    alternations, realisation_phrases, realisation_descriptions = get_alternations(all_schema_objects, slowal_frames)

    examples = get_examples(slowal_frames)

    all_schema_objects_dict = [schema2dict(schema, schema.subentries.all()[0].negativity, request.LANGUAGE_CODE) for
                               schema in all_schema_objects]

    subentries = [{
        'str': None,
        'schemata': all_schema_objects_dict
    }]

    unified_frame_dict = unified_frame_2_dict(unified_frame)

    return {'unified_frame_id': unified_frame.id, 'unified_frame': unified_frame_dict, 'subentries': subentries,
            'frames': slowal_frames_dict, 'alternations': alternations, 'realisation_phrases': realisation_phrases,
            'realisation_descriptions': realisation_descriptions, 'examples': examples,
            'last_visited': request.session['last_visited']}


@ajax_required
@login_required
def get_unified_frame(request):
    if request.method == 'POST':
        # TODO (*)
        # form = EntryForm(request.POST)
        unified_frame_id = request.POST['unified_frame_id']
        # TODO (*)
        if unified_frame_id.isdigit():  # and form.is_valid():
            unified_frame_id = int(unified_frame_id)
            request.session.modified = True
            unified_frame = UnifiedFrame.objects.get(id=unified_frame_id)
            return JsonResponse(get_unified_frame_json(unified_frame, request))

    return JsonResponse({})


@ajax_required
@transaction.atomic
def extract_frames_to_new_frame(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        target_unified_frame_id = request.POST['target_unified_frame_id']
        slowal_frame_ids = json.loads(request.POST['slowal_frame_ids'])

        unified_frame = UnifiedFrame.objects.get(id=unified_frame_id)
        slowal_frames = Frame.objects.filter(id__in=slowal_frame_ids)
        new_unified_frame = None
        if target_unified_frame_id != '':
            new_unified_frame = UnifiedFrame.objects.get(id=target_unified_frame_id)
        new_frame_fullfiled_and_saved = unified_frame.extract_frames_to(slowal_frames=slowal_frames,
                                                                        new_frame=new_unified_frame)
        return JsonResponse(get_unified_frame_json(new_frame_fullfiled_and_saved, request))
    return JsonResponse({})


@ajax_required
@transaction.atomic
def remove_selectional_preference(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        argument_id = request.POST['argument_id']
        preference_ids = json.loads(request.POST['preference_ids'])

        unified_frame_argument = UnifiedFrameArgument.objects.get(id=argument_id, unified_frame=unified_frame_id)
        unified_frame_argument.predefined.set(unified_frame_argument.predefined.exclude(id__in=preference_ids))
        unified_frame_argument.synsets.set(unified_frame_argument.synsets.exclude(id__in=preference_ids))
        unified_frame_argument.relations.set(unified_frame_argument.relations.exclude(id__in=preference_ids))
        unified_frame_argument.save()

        update_argument_preferences_count(unified_frame_argument)

        return JsonResponse({})
    return JsonResponse({})


def update_argument_preferences_count(unified_frame_argument):
    unified_frame_argument.preferences_count = unified_frame_argument.predefined.count() + \
                                               unified_frame_argument.synsets.count() + \
                                               unified_frame_argument.relations.count()
    unified_frame_argument.save()


@ajax_required
@transaction.atomic
def duplicate_unified_frame(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        target_unified_frame_title = request.POST['target_unified_frame_title']

        unified_frame = UnifiedFrame.objects.get(id=unified_frame_id)
        new_frame = unified_frame.duplicate(new_frame_title=target_unified_frame_title)

        Assignment.assign(user=request.user, subject=new_frame)

        return JsonResponse(get_unified_frame_json(new_frame, request))
    return JsonResponse({})


@ajax_required
@transaction.atomic
def change_slowal2unified_fram_argument_mapping(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        slowal_frame_id = request.POST['slowal_frame_id']
        slowal_frame_selected_arguments = json.loads(request.POST['slowal_frame_selected_arguments'])

        unified_frame2_slowal_frame_mapping = UnifiedFrame2SlowalFrameMapping.objects.get(
            unified_frame_id=unified_frame_id, slowal_frame=slowal_frame_id)

        arg1_id = int(slowal_frame_selected_arguments[0])
        arg2_id = int(slowal_frame_selected_arguments[1])

        unified_frame_argument_mapping1 = UnifiedFrameArgumentSlowalFrameMapping.objects.get(
            unified_frame_mapping=unified_frame2_slowal_frame_mapping,
            slowal_agrument_id=arg1_id) if arg1_id >= 0 else None
        unified_frame_argument_mapping2 = UnifiedFrameArgumentSlowalFrameMapping.objects.get(
            unified_frame_mapping=unified_frame2_slowal_frame_mapping,
            slowal_agrument_id=arg2_id) if arg2_id >= 0 else None

        if unified_frame_argument_mapping1 is not None and unified_frame_argument_mapping2 is not None:
            # mamy oba argumenty, zamieniamy miescami
            unified_frame_argument_mapping1.slowal_agrument_id = arg2_id
            unified_frame_argument_mapping2.slowal_agrument_id = arg1_id
            unified_frame_argument_mapping1.save()
            unified_frame_argument_mapping2.save()
        elif unified_frame_argument_mapping1 is not None and unified_frame_argument_mapping2 is None:
            # mamy lewy argument, prawy jest Empty
            unified_frame_argument_mapping1.unified_agrument_id = -arg2_id
            unified_frame_argument_mapping1.save()
        elif unified_frame_argument_mapping1 is None and unified_frame_argument_mapping2 is not None:
            # mamy prawy argument, lewy jest Empty
            unified_frame_argument_mapping2.unified_agrument_id = -arg1_id
            unified_frame_argument_mapping2.save()

        return JsonResponse({})
    return JsonResponse({})


@ajax_required
@transaction.atomic
def change_slowal_frame_status(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        slowal_frame_id = request.POST['slowal_frame_id']
        status = request.POST['status']

        frame = Frame.objects.get(pk=slowal_frame_id)
        frame.status = status
        frame.save()

        return JsonResponse({})
    return JsonResponse({})


@ajax_required
@transaction.atomic
def save_unified_frame_title(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        unified_frame_title = request.POST['unified_frame_title']

        unified_frame = UnifiedFrame.objects.get(id=unified_frame_id)

        if unified_frame:
            unified_frame.title = unified_frame_title
            unified_frame.save()
    return JsonResponse({})


@ajax_required
@transaction.atomic
def check_unified_frame_title_uniq(request):
    if request.method == 'POST':
        unified_frame_title = request.POST['unified_frame_title']
        unified_frames = UnifiedFrame.objects.filter(title=unified_frame_title)

        return JsonResponse({"exists": len(unified_frames) > 0})
    return JsonResponse({})


@ajax_required
@transaction.atomic
def save_selected_role(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        complement_id = request.POST['complement_id']
        role_id = request.POST['role_id']

        unified_frame_argument = UnifiedFrameArgument.objects.get(unified_frame_id=int(unified_frame_id),
                                                                  id=int(complement_id))
        unified_frame_argument.role_id = role_id
        unified_frame_argument.save()
    return JsonResponse({})


@ajax_required
@transaction.atomic
def save_new_role(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        complement_id = request.POST['complement_id']
        role_id = request.POST['role_id']
        role_type = request.POST['role_type']
        attribute_id = request.POST.get('attribute_id', None)
        sub_attribute_id = request.POST.get('sub_attribute_id', None)

        argument_role = ArgumentRole.objects.filter(role_id=role_id, attribute_id=attribute_id,
                                                    sub_attribute_id=sub_attribute_id).first()
        if argument_role is None:
            argument_role = ArgumentRole(role=SemanticRole.objects.get(pk=role_id),
                                         attribute=None if attribute_id is None else RoleAttribute.objects.get(pk=attribute_id),
                                         sub_attribute=RoleSubAttribute.objects.get(pk=sub_attribute_id))
            argument_role.save()

        unified_frame_argument = UnifiedFrameArgument.objects.get(unified_frame_id=unified_frame_id, id=complement_id)
        unified_frame_argument.role = argument_role
        unified_frame_argument.role_type = RoleType.objects.get(type=role_type)
        unified_frame_argument.save()
    return JsonResponse({})


@ajax_required
@transaction.atomic
def add_argument(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']

        unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id)
        new_unified_frame_argument = UnifiedFrameArgument.objects.create(unified_frame=unified_frame)
        new_unified_frame_argument.save()
        unified_frame.arguments_count = unified_frame.arguments_count + 1
        unified_frame.save()
    return JsonResponse({})


@ajax_required
@transaction.atomic
def remove_argument(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        complement_id = request.POST['complement_id']

        new_unified_frame_argument = UnifiedFrameArgument.objects.get(id=complement_id)
        new_unified_frame_argument.delete()
        unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id)
        unified_frame.arguments_count = unified_frame.arguments_count - 1
        unified_frame.save()
    return JsonResponse({})


@ajax_required
@transaction.atomic
def change_unified_frame_status_to_ready(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id)
        unified_frame.status = UnifiedFrameStatus.READY
        unified_frame.save()
    return JsonResponse({})


@ajax_required
@transaction.atomic
def reject_unified_frame_ready_status(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        slowal_frame_id = int(request.POST['slowal_frame_id'])
        unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id)
        unified_frame.status = UnifiedFrameStatus.PROCESSING
        unified_frame.save()

        if slowal_frame_id != -1:
            # Gdy -1 to zmieniamy tylko status ramy zunikowanej pozwalajac leksykografai na dlasza prace nad nia
            slowal_frame = Frame.objects.get(pk=slowal_frame_id)
            slowal_frame.status = FrameStatus.PROCESSING
            slowal_frame.save()

        mappings = UnifiedFrame2SlowalFrameMapping.objects.filter(unified_frame=unified_frame)
        for mapping in mappings.all():
            id = mapping.slowal_frame.id
            if id != mapping.slowal_frame.id and mapping.slowal_frame.status == 'S':
                # Umozliwiamy ponowna prace nad rama dla leksykografa
                loaded_slowal_frame = Frame.objects.get(pk=id)
                loaded_slowal_frame.status = FrameStatus.READY
                loaded_slowal_frame.save()

    return JsonResponse({})


@ajax_required
@transaction.atomic
def change_unified_frame_status_to_verified_by_superleksykograf(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id)
        unified_frame.status = choices.UnifiedFrameStatus.VERIFIED

        # save fin statement info for current active fin statement
        fin_statements = FinStatement.objects.filter(is_active=True)
        if fin_statements.count() == 1:
            active_fin_statement = fin_statements[0]
            unified_frame.fin_statement = active_fin_statement

        unified_frame.save()
    return JsonResponse({})


@csrf_exempt
def create_unified_frame(frame_id):
    print('Requesting unified frame creation service, frame_id: {}, service_url: {}'
          .format(frame_id, settings.UNIFIED_FRAME_SERVICE_URL + str(frame_id) +
                  settings.SLOWAL_FRAME_SERVICE_SYSTEM_TYPE_ARG))

    http = urllib3.PoolManager()

    r = http.request('GET', settings.UNIFIED_FRAME_SERVICE_URL + str(frame_id) +
                     settings.SLOWAL_FRAME_SERVICE_SYSTEM_TYPE_ARG)

    response = r.data.decode('utf-8')

    print("Received xml data from api: {}".format(response))

    parser = make_parser()
    parser.setFeature(handler.feature_external_ges, False)

    unified_frame_xml_handler = UnificationPreprocessHandler()
    parser.setContentHandler(unified_frame_xml_handler)

    f = io.StringIO(response)

    parser.parse(f)

    unified_frame_id = unified_frame_xml_handler.unified_frame_ids[0]

    return unified_frame_id


@csrf_exempt
def frame_statuses_free(request):
    if request.method == 'GET':
        return HttpResponse()


@csrf_exempt
def frame_statuses_take(request):
    if request.method == 'GET':
        return HttpResponse()


@csrf_exempt
def build_unified_frame_xml(request):
    if request.method == 'GET':
        frame_id = request.GET.get('frame_id')

        frames = Frame.objects.filter(id=frame_id)
        # lu = LexicalUnit.objects.get(pk=lu_id)
        # frames = list(lu.frames.all())
        if len(frames) > 0:
            matching_elem = Element('matching')
            unifier_frame_elem = SubElement(matching_elem, 'unifier_frame')

            frame = frames[0]

            arguments = list(frame.arguments.all())
            arg_cnt = len(arguments)
            for id in range(arg_cnt):
                argument_elem = SubElement(unifier_frame_elem, 'argument', attrib={'id': str(id)})
                semantic_role_type_elem = SubElement(argument_elem, 'semantic_role', attrib={'type': 'role'})
                roles_elem = SubElement(argument_elem, 'roles')
                role_elem1 = SubElement(roles_elem, 'role', attrib={'name': 'Initiator'})
                role_elem2 = SubElement(roles_elem, 'role', attrib={'name': 'Manner'})

            connections_elem = SubElement(unifier_frame_elem, 'connections')

            slowal_frame_elem = SubElement(connections_elem, 'slowal_frame', attrib={'id': str(frame.id)})

            arguments_connections_elem = SubElement(slowal_frame_elem, 'argument_connections')

            for id, argument in enumerate(arguments):
                arguments_connection_elem = SubElement(arguments_connections_elem, 'argument_connection',
                                                       attrib={'unifier_argument_id': str(id),
                                                               'slowal_id': str(argument.id)})
            xml = tostring(matching_elem)
            return HttpResponse(xml)

    return HttpResponse()


# @ajax_required
# @transaction.atomic
# def save_unified_frame_title(request):
#     if request.method == 'POST':
#         unified_frame_id = request.POST['unified_frame_id']
#         unified_frame_title = request.POST['unified_frame_title']
#
#         unified_frame = UnifiedFrame.objects.get(id=unified_frame_id)
#
#         if unified_frame:
#             unified_frame.title = unified_frame_title
#             unified_frame.save()
#     return JsonResponse({})


@ajax_required
@transaction.atomic
def frame_assign(request):
    if request.method == 'POST':

        lu_id = request.POST['lu_id']
        frame_id = request.POST['frame_id']
        unified_frame_title = request.POST['unified_frame_title']

        unified_frame_pk = create_unified_frame(frame_id)

        unified_frame = get_object_or_404(
            UnifiedFrame.objects,
            pk=unified_frame_pk,
        )
        unified_frame.title = unified_frame_title
        unified_frame.save()

        Assignment.assign(user=request.user, subject=unified_frame)

        slowal_frames = [connection.slowal_frame for connection in unified_frame.unified_frame_2_slowal_frame.all()]

        for slowal_frame in slowal_frames:
            slowal_frame.status = FrameStatus.PROCESSING
            Assignment.assign(user=request.user, subject=slowal_frame)
            slowal_frame.save()

        ret = {
            'unified_frame_id': unified_frame_pk
        }

        return JsonResponse(ret)
    return JsonResponse({})


def remove_unified_frame_mappings_and_assigments(unified_frame):
    unified_frame_id = unified_frame.pk
    # odpianie z ramy zunifikowanej
    unified_frame2_slowal_frame_mappings = UnifiedFrame2SlowalFrameMapping.objects.filter(
        unified_frame_id=unified_frame_id)
    for unifiedFrame2SlowalFrameMapping in unified_frame2_slowal_frame_mappings:
        unifiedFrame2SlowalFrameMapping.slowal_frame.status = 'N'
        unifiedFrame2SlowalFrameMapping.slowal_frame.save()
        Assignment.delete(subject=unifiedFrame2SlowalFrameMapping.slowal_frame)
        unified_frame_argument_slowal_frame_mappings = UnifiedFrameArgumentSlowalFrameMapping.objects.filter(
            unified_frame_mapping=unifiedFrame2SlowalFrameMapping)
        unified_frame_argument_slowal_frame_mappings.delete()
        unifiedFrame2SlowalFrameMapping.delete()
    Assignment.delete(subject=unified_frame)


@ajax(login_required=True, method='post')
@transaction.atomic
def delete_unified_frame(request, unified_frame_id):

    unified_frame = UnifiedFrame.objects.get(id=unified_frame_id)

    remove_unified_frame_mappings_and_assigments(unified_frame)
    UnifiedFrameArgument.objects.filter(unified_frame_id=unified_frame_id).delete()

    slowal_frames = UnifiedFrame2SlowalFrameMapping.objects.filter(unified_frame_id=unified_frame_id).all()
    slowal_frames_ids = ','.join(list(map(lambda slowal_frame: slowal_frame.id, slowal_frames)))

    if len(slowal_frames_ids) > 0:
        http = urllib3.PoolManager()
        r = http.request('GET', settings.SLOWAL_FRAME_REMOVE_SERVICE_URL + slowal_frames_ids +
                         settings.SLOWAL_FRAME_SERVICE_SYSTEM_TYPE_ARG)

    unified_frame.delete()

    return {}


@ajax_required
@transaction.atomic
def hierarchy_assign(request):
    """
    Assign hierarchy relationship.
    The request has to contain 'hyponym_id' and 'hypernym_id' that represent
    unified frames taking part in the relationship.
    :param request: http request
    :return: Json response containg single field 'succ': (true|false) or 'exists': 'true'
    """
    if request.method == 'POST':

        hyponym_id = request.POST['hyponym_id']
        hyperonym_id = request.POST['hyperonym_id']

        curr1 = HierarchyModel.objects.filter(hyponym_id=hyponym_id, hyperonym_id=hyperonym_id)
        curr2 = HierarchyModel.objects.filter(hyponym_id=hyperonym_id, hyperonym_id=hyponym_id)

        if curr1 or curr2:
            return JsonResponse({'exists': 'true'})

        hierarchy = HierarchyModel()
        hierarchy.hyponym_id = hyponym_id
        hierarchy.hyperonym_id = hyperonym_id
        hierarchy.save()

        set_hierarchy_exists_info(hyponym_id)
        set_hierarchy_exists_info(hyperonym_id)

        return JsonResponse({'succ': 'true'})
    return JsonResponse({})


def set_hierarchy_exists_info(unified_fram_id):
    unified_frame = UnifiedFrame.objects.get(pk=unified_fram_id)
    unified_frame.hasHierarchyElems = True
    unified_frame.save()


@ajax_required
@transaction.atomic
def hierarchy_unassign(request):
    """
    Unassign hierarchy relationship.
    The request has to contain 'rel1_id' and 'rel2_id' that represent unified frame IDs hierarchy pair.
    :param request: http request
    :return: Json response containg single field 'succ' = (true|false)
    """
    if request.method == 'POST':

        rel1_id = request.POST['rel1_id']
        rel2_id = request.POST['rel2_id']

        curr1 = HierarchyModel.objects.filter(hyponym_id=rel1_id, hyperonym_id=rel2_id)

        succ = False

        if curr1:
            curr1.delete()
            succ = True
        else:
            curr2 = HierarchyModel.objects.filter(hyponym_id=rel2_id, hyperonym_id=rel1_id)
            if curr2:
                curr2.delete()
                succ = True

        # check if there is any heierarchy elements for unified frames from request
        set_no_hierarchy_exists_info(rel1_id)
        set_no_hierarchy_exists_info(rel2_id)

        return JsonResponse({'succ': succ})


def set_no_hierarchy_exists_info(unified_frame_id):
    """
    Set unified frame field 'hasHierarchyElems' as false if needed.
    :param unified_frame_id: Unified frame id
    """
    rel_1_hierarchy_count = HierarchyModel.objects.filter(Q(hyponym_id=unified_frame_id) |
                                                          Q(hyperonym_id=unified_frame_id)).count()
    if rel_1_hierarchy_count == 0:
        # set info of no hierarchy elems in unified frame -> used to color unified frame list component
        unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id)
        unified_frame.hasHierarchyElems = False
        unified_frame.save()


@ajax_required
@transaction.atomic
def get_hierarchy_hyponyms(request, unified_frame_id):
    """
        Returning hierarchy hyponyms for a given unified_frame_id
    :param request: http request
    :param unified_frame_id: Unifird fram id for witch hyponyms will be returned
    :return: Json response containing list of unified frames as hyponyms
    """
    hyponyms = HierarchyModel.objects.filter(hyperonym_id=unified_frame_id)

    res = []
    for unifiedFrame in hyponyms:
        res.append(get_unified_frame_json(unifiedFrame.hyponym, request))
    res = {
        'hyponyms': res
    }

    return JsonResponse(res)


@ajax_required
@transaction.atomic
def get_hierarchy_hyperonyms(request, unified_frame_id):
    """
        Returning hierarchy hypernyms for a given unified_frame_id.
    :param request: http request
    :param unified_frame_id: Unifird fram id for witch hyperonyms will be returned
    :return: Json response containing list of unified frames as hyperonyms
    """
    hyperonyms = HierarchyModel.objects.filter(hyponym_id=unified_frame_id)

    res = []
    for unifiedFrame in hyperonyms:
        res.append(get_unified_frame_json(unifiedFrame.hyperonym, request))
    res = {
        'hyperonyms': res
    }

    return JsonResponse(res)


@ajax_required
@transaction.atomic
def attach_lu_to_unified_frame(request):
    if request.method == 'POST':
        unified_frame_id = request.POST['unified_frame_id']
        lu_base_sense = request.POST['lu_base']
        lu_base_sense_split = lu_base_sense.split('-')
        lu_base = lu_base_sense_split[0]
        lu_sense = lu_base_sense_split[1]

        unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id)
        lu = LexicalUnit.objects.get(base=lu_base, sense=lu_sense, entry__isnull=False)
        frames = list(lu.frames.all())
        for frame in frames:

            frame.status = FrameStatus.PROCESSING
            Assignment.assign(user=request.user, subject=frame)
            frame.save()

            mapping = UnifiedFrame2SlowalFrameMapping(unified_frame=unified_frame, slowal_frame=frame)
            UnifiedFrame2SlowalFrameMapping.save(mapping)

            slowal_frame_arguments = list(frame.arguments.all())
            unified_frame_arguments = list(unified_frame.unified_arguments.all())
            slowal_frame_argument_cnt = len(slowal_frame_arguments)
            for ind in range(slowal_frame_argument_cnt):
                if ind >= len(unified_frame_arguments):
                    # create additional argument in unified frame
                    unified_frame_argument = UnifiedFrameArgument(unified_frame=unified_frame)
                    UnifiedFrameArgument.save(unified_frame_argument)
                else:
                    unified_frame_argument = unified_frame_arguments[ind]

                unified_frame_argument_slowal_frame_mapping = \
                    UnifiedFrameArgumentSlowalFrameMapping(unified_frame_mapping=mapping,
                                                           unified_agrument=unified_frame_argument,
                                                           slowal_agrument=slowal_frame_arguments[ind])
                UnifiedFrameArgumentSlowalFrameMapping.save(unified_frame_argument_slowal_frame_mapping)

        for frame in frames:
            http = urllib3.PoolManager()
            r = http.request('GET', settings.SLOWAL_FRAME_TAKE_SERVICE_URL + str(frame.id) +
                             settings.SLOWAL_FRAME_SERVICE_SYSTEM_TYPE_ARG)

        return JsonResponse({})
    return JsonResponse({})


def synset_hierarchy_constraint_check(lu_id, pref_lu_ids):

    conflict_exists = None
    if lu_id in pref_lu_ids:
        conflict_exists = lu_id

    conflict_hyponym = None
    if lu_id in synset_hierarchy_dict:
        synset_hierarchy = synset_hierarchy_dict[lu_id]
        conflict_hyponym = hierarchy_constraint_check_hypo(synset_hierarchy, lu_id, pref_lu_ids)

    conflict_hyperonym = None
    if lu_id in synset_hierarchy_dict:
        synset_hierarchy = synset_hierarchy_dict[lu_id]
        conflict_hyperonym = hierarchy_constraint_check_hyperonyms(synset_hierarchy, lu_id, pref_lu_ids)

    return conflict_hyponym, conflict_hyperonym, conflict_exists


def hierarchy_constraint_check_hyperonyms(synset_hierarchy: SynsetHierarchy, lu_id: int, pref_lu_ids: []):
    for synset in synset_hierarchy.hyperonyms:
        if synset.id in pref_lu_ids:
            return synset.id
    for synset in synset_hierarchy.hyperonyms:
        ret = hierarchy_constraint_check_hyperonyms(synset_hierarchy_dict[synset.id], lu_id, pref_lu_ids)
        if ret is not None:
            return ret

    return None


def hierarchy_constraint_check_hypo(synset_hierarchy: SynsetHierarchy, lu_id: int, pref_lu_ids: []):
    for synset in synset_hierarchy.hyponyms:
        if synset.id in pref_lu_ids:
            return synset.id
    for synset in synset_hierarchy.hyponyms:
        ret = hierarchy_constraint_check_hypo(synset_hierarchy_dict[synset.id], lu_id, pref_lu_ids)
        if ret is not None:
            return ret

    return None