ConceptPortal-public/rsconcept/backend/apps/oss/serializers/data_access.py

208 lines
7.3 KiB
Python
Raw Normal View History

2024-07-19 19:29:27 +03:00
''' Serializers for persistent data manipulation. '''
2024-07-29 22:31:11 +03:00
import re
2024-07-19 19:29:27 +03:00
from typing import cast
from django.db.models import F
from rest_framework import serializers
from rest_framework.serializers import PrimaryKeyRelatedField as PKField
2024-07-28 21:30:10 +03:00
from apps.library.models import LibraryItem, LibraryItemType
from apps.library.serializers import LibraryItemDetailsSerializer
2024-07-29 22:31:11 +03:00
from apps.rsform.models import Constituenta
from apps.rsform.serializers import SubstitutionSerializerBase
2024-07-19 19:29:27 +03:00
from shared import messages as msg
from ..models import Argument, Operation, OperationSchema, OperationType
2024-07-21 15:19:57 +03:00
from .basics import OperationPositionSerializer, SubstitutionExSerializer
2024-07-19 19:29:27 +03:00
class OperationSerializer(serializers.ModelSerializer):
''' Serializer: Operation data. '''
class Meta:
''' serializer metadata. '''
model = Operation
fields = '__all__'
read_only_fields = ('id', 'oss')
class ArgumentSerializer(serializers.ModelSerializer):
''' Serializer: Operation data. '''
class Meta:
''' serializer metadata. '''
model = Argument
fields = ('operation', 'argument')
class OperationCreateSerializer(serializers.Serializer):
''' Serializer: Operation creation. '''
class OperationData(serializers.ModelSerializer):
''' Serializer: Operation creation data. '''
alias = serializers.CharField()
operation_type = serializers.ChoiceField(OperationType.choices)
class Meta:
''' serializer metadata. '''
model = Operation
fields = \
2024-07-24 22:23:35 +03:00
'alias', 'operation_type', 'title', 'sync_text', \
2024-07-21 15:19:57 +03:00
'comment', 'result', 'position_x', 'position_y'
2024-07-19 19:29:27 +03:00
2024-07-26 17:31:57 +03:00
create_schema = serializers.BooleanField(default=False, required=False)
2024-07-19 19:29:27 +03:00
item_data = OperationData()
2024-07-21 15:19:57 +03:00
arguments = PKField(many=True, queryset=Operation.objects.all(), required=False)
2024-07-29 22:31:11 +03:00
2024-07-19 19:29:27 +03:00
positions = serializers.ListField(
child=OperationPositionSerializer(),
default=[]
)
2024-07-29 22:31:11 +03:00
class OperationUpdateSerializer(serializers.Serializer):
''' Serializer: Operation creation. '''
class OperationData(serializers.ModelSerializer):
''' Serializer: Operation creation data. '''
class Meta:
''' serializer metadata. '''
model = Operation
fields = 'alias', 'title', 'sync_text', 'comment'
target = PKField(many=False, queryset=Operation.objects.all())
item_data = OperationData()
arguments = PKField(many=True, queryset=Operation.objects.all(), required=False)
substitutions = serializers.ListField(
child=SubstitutionSerializerBase(),
required=False
)
positions = serializers.ListField(
child=OperationPositionSerializer(),
default=[]
)
def validate(self, attrs):
if 'arguments' not in attrs:
return attrs
oss = cast(LibraryItem, self.context['oss'])
for operation in attrs['arguments']:
if operation.oss != oss:
raise serializers.ValidationError({
'arguments': msg.operationNotInOSS(oss.title)
})
if 'substitutions' not in attrs:
return attrs
schemas = [arg.result.pk for arg in attrs['arguments'] if arg.result is not None]
deleted = set()
for item in attrs['substitutions']:
original_cst = cast(Constituenta, item['original'])
substitution_cst = cast(Constituenta, item['substitution'])
if original_cst.schema.pk not in schemas:
raise serializers.ValidationError({
f'{original_cst.id}': msg.constituentaNotFromOperation()
})
if substitution_cst.schema.pk not in schemas:
raise serializers.ValidationError({
f'{substitution_cst.id}': msg.constituentaNotFromOperation()
})
if original_cst.pk in deleted:
raise serializers.ValidationError({
f'{original_cst.id}': msg.substituteDouble(original_cst.alias)
})
if original_cst.schema == substitution_cst.schema:
raise serializers.ValidationError({
'alias': msg.substituteTrivial(original_cst.alias)
})
deleted.add(original_cst.pk)
return attrs
class OperationTargetSerializer(serializers.Serializer):
2024-07-19 19:29:27 +03:00
''' Serializer: Delete operation. '''
target = PKField(many=False, queryset=Operation.objects.all())
positions = serializers.ListField(
child=OperationPositionSerializer(),
default=[]
)
def validate(self, attrs):
oss = cast(LibraryItem, self.context['oss'])
operation = cast(Operation, attrs['target'])
if oss and operation.oss != oss:
raise serializers.ValidationError({
2024-07-28 21:30:10 +03:00
'target': msg.operationNotInOSS(oss.title)
})
return attrs
class SetOperationInputSerializer(serializers.Serializer):
''' Serializer: Set input schema for operation. '''
target = PKField(many=False, queryset=Operation.objects.all())
input = PKField(
many=False,
queryset=LibraryItem.objects.filter(item_type=LibraryItemType.RSFORM),
allow_null=True,
default=None
)
sync_text = serializers.BooleanField(default=False, required=False)
positions = serializers.ListField(
child=OperationPositionSerializer(),
default=[]
)
def validate(self, attrs):
oss = cast(LibraryItem, self.context['oss'])
operation = cast(Operation, attrs['target'])
if oss and operation.oss != oss:
raise serializers.ValidationError({
'target': msg.operationNotInOSS(oss.title)
})
if operation.operation_type != OperationType.INPUT:
raise serializers.ValidationError({
'target': msg.operationNotInput(operation.alias)
2024-07-19 19:29:27 +03:00
})
return attrs
class OperationSchemaSerializer(serializers.ModelSerializer):
''' Serializer: Detailed data for OSS. '''
items = serializers.ListField(
child=OperationSerializer()
)
2024-07-21 15:19:57 +03:00
arguments = serializers.ListField(
2024-07-19 19:29:27 +03:00
child=ArgumentSerializer()
)
2024-07-21 15:19:57 +03:00
substitutions = serializers.ListField(
child=SubstitutionExSerializer()
)
2024-07-19 19:29:27 +03:00
class Meta:
''' serializer metadata. '''
model = LibraryItem
2024-07-19 19:29:27 +03:00
fields = '__all__'
def to_representation(self, instance: LibraryItem):
2024-07-19 19:29:27 +03:00
result = LibraryItemDetailsSerializer(instance).data
oss = OperationSchema(instance)
2024-07-19 19:29:27 +03:00
result['items'] = []
for operation in oss.operations():
2024-07-19 19:29:27 +03:00
result['items'].append(OperationSerializer(operation).data)
2024-07-21 15:19:57 +03:00
result['arguments'] = []
for argument in oss.arguments():
2024-07-21 15:19:57 +03:00
result['arguments'].append(ArgumentSerializer(argument).data)
2024-07-19 19:29:27 +03:00
result['substitutions'] = []
for substitution in oss.substitutions().values(
2024-07-19 19:29:27 +03:00
'operation',
'original',
'substitution',
2024-07-21 15:19:57 +03:00
'transfer_term',
2024-07-19 19:29:27 +03:00
original_alias=F('original__alias'),
original_term=F('original__term_resolved'),
substitution_alias=F('substitution__alias'),
substitution_term=F('substitution__term_resolved'),
):
result['substitutions'].append(substitution)
return result