Skip to content
Snippets Groups Projects
models.py 6.52 KiB
from copy import deepcopy
from typing import List, Optional

from django.db import models, transaction

from meanings.models import LexicalUnit, Synset
from semantics.models import PredefinedSelectionalPreference, RelationalSelectionalPreference, ArgumentRole, \
    RoleType, Argument, Frame, SelectionalPreferenceRelation

from . import choices


class UnifiedFrameQueryset(models.QuerySet):
    def for_lexical_unit(self, lexical_unit):
        return self.filter(unified_frame_2_slowal_frame__slowal_frame__lexical_units=lexical_unit)


class UnifiedFrame(models.Model):
    status = models.TextField(
        max_length=10,
        choices=choices.UnifiedFrameStatus.choices,
        default=choices.UnifiedFrameStatus.PROCESSING,
    )
    title = models.CharField(max_length=200, default=None, blank=True, null=True)

    objects = models.Manager.from_queryset(UnifiedFrameQueryset)()

    def sorted_arguments(self):  # TODO: zaimplementowac wlasciwe sortowanie
        return UnifiedFrameArgument.objects.filter(frame=self)

    def __str__(self):
        return '%s: %s' % (self.opinion, ' + '.join([str(arg) for arg in self.sorted_arguments()]))
    
    @transaction.atomic
    def extract_frames_to(
            self, slowal_frames: List[Frame], new_frame: Optional["UnifiedFrame"] = None
    ) -> "UnifiedFrame":
        new_unified_frame_arguments = None
        if not new_frame:
            new_frame = UnifiedFrame.objects.create()
            new_frame.save()
            unified_frame_arguments = UnifiedFrameArgument.objects.filter(unified_frame=self)
            old_2_new_argument_mapping = {}
            for unified_frame_argument in unified_frame_arguments:
                new_unified_frame_argument = UnifiedFrameArgument.objects.create(
                                                                  role_type=unified_frame_argument.role_type,
                                                                  role=unified_frame_argument.role,
                                                                  unified_frame=new_frame)
                new_unified_frame_argument.proposed_roles.set(unified_frame_argument.proposed_roles.all())
                new_unified_frame_argument.save()
                old_2_new_argument_mapping[unified_frame_argument.id] = new_unified_frame_argument.id
        else:
            new_unified_frame_arguments = UnifiedFrameArgument.objects.filter(unified_frame=new_frame).all()
            unified_frame_arguments = UnifiedFrameArgument.objects.filter(unified_frame=self).all()
            if len(new_unified_frame_arguments) < len(unified_frame_arguments):
                raise Exception('Target frame has to little arguments, required: ' + len(unified_frame_arguments)+', but found: '+len(new_unified_frame_arguments))

        for slowal_frame in slowal_frames:
            mapping = UnifiedFrame2SlowalFrameMapping.objects.get(unified_frame=self, slowal_frame=slowal_frame)
            mapping.unified_frame = new_frame
            mapping.save()
            argument_mappings = UnifiedFrameArgumentSlowalFrameMapping.objects.filter(unified_frame_mapping=mapping)
            for i, argument_mapping in enumerate(argument_mappings):
                if new_unified_frame_arguments is None:
                    argument_mapping.unified_agrument_id = old_2_new_argument_mapping[argument_mapping.unified_agrument_id]
                else:
                    argument_mapping.unified_agrument_id = new_unified_frame_arguments[i]
                argument_mapping.save()

        # curr_mapping = UnifiedFrame2SlowalFrameMapping.objects.filter(unified_frame=self).all()
        # if len(curr_mapping) == 0:
        #     unified_frame_arguments = UnifiedFrameArgument.objects.filter(unified_frame=self).all()
        #     unified_frame_arguments.delete()
        #     self.delete()

        return new_frame

    @transaction.atomic
    def duplicate(
            self, new_frame_title: Optional = None
    ) -> "UnifiedFrame":
        new_frame = UnifiedFrame.objects.create(title=new_frame_title)
        new_frame.save()
        unified_frame_arguments = UnifiedFrameArgument.objects.filter(unified_frame=self)
        for unified_frame_argument in unified_frame_arguments:
            new_unified_frame_argument = UnifiedFrameArgument.objects.create(
                role_type=unified_frame_argument.role_type,
                role=unified_frame_argument.role,
                unified_frame=new_frame)
            new_unified_frame_argument.proposed_roles.set(unified_frame_argument.proposed_roles.all())
            new_unified_frame_argument.save()

        return new_frame


class UnifiedFrameArgument(models.Model):
    role_type = models.ForeignKey(RoleType, on_delete=models.PROTECT, default=None, blank=True, null=True)
    #rola - wybrana przez użytkownika
    role = models.ForeignKey(ArgumentRole, on_delete=models.PROTECT, default=None, blank=True, null=True)
    #role zaproponowane przez system unifikacyjny
    proposed_roles = models.ManyToManyField(ArgumentRole, related_name='proposed_roles')

    #3 typy preferencji - wybrane przez użytkownika
    predefined = models.ManyToManyField(PredefinedSelectionalPreference)
    synsets = models.ManyToManyField(Synset)
    relations = models.ManyToManyField('UnifiedRelationalSelectionalPreference')

    #odwołanie do ramy
    unified_frame = models.ForeignKey(UnifiedFrame, related_name='unified_arguments', default=None, blank=True, null=True, on_delete=models.PROTECT)

    def __str__(self):
        return str(self.role)

class UnifiedRelationalSelectionalPreference(models.Model):
    relation = models.ForeignKey(SelectionalPreferenceRelation, on_delete=models.PROTECT)
    to = models.ForeignKey(UnifiedFrameArgument,on_delete=models.PROTECT)

    def __str__(self):
        return '%s -> %s' % (self.relation, self.to)


class UnifiedFrame2SlowalFrameMapping(models.Model):
    removed = models.BooleanField(default=False)
    unified_frame = models.ForeignKey(UnifiedFrame, related_name='unified_frame_2_slowal_frame', on_delete=models.PROTECT)
    slowal_frame = models.OneToOneField(Frame, related_name='slowal_frame_2_unified_frame', on_delete=models.PROTECT)

class UnifiedFrameArgumentSlowalFrameMapping(models.Model):
    unified_agrument = models.ForeignKey(UnifiedFrameArgument, related_name='unified_agrument_mapping', on_delete=models.PROTECT)
    slowal_agrument = models.ForeignKey(Argument, related_name='slowal_agrument_mapping', on_delete=models.PROTECT)
    unified_frame_mapping = models.ForeignKey(UnifiedFrame2SlowalFrameMapping, related_name='unified_frame_argument_mapping', on_delete=models.PROTECT)