mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-11-15 17:21:38 +03:00
R: Refactor constituenta insertion
This commit is contained in:
parent
48de17acc7
commit
e9f31c0e7a
|
|
@ -54,7 +54,7 @@ class LibraryItemCloneSerializer(StrictSerializer):
|
||||||
model = LibraryItem
|
model = LibraryItem
|
||||||
exclude = ['id', 'item_type', 'owner', 'read_only']
|
exclude = ['id', 'item_type', 'owner', 'read_only']
|
||||||
|
|
||||||
items = PKField(many=True, queryset=Constituenta.objects.all().only('pk', 'schema_id'))
|
items = PKField(many=True, queryset=Constituenta.objects.all().only('schema_id'))
|
||||||
item_data = ItemCloneData()
|
item_data = ItemCloneData()
|
||||||
|
|
||||||
def validate_items(self, value):
|
def validate_items(self, value):
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from apps.oss.models import Layout, Operation, OperationSchema, PropagationFacade
|
from apps.oss.models import Layout, Operation, OperationSchema, PropagationFacade
|
||||||
from apps.rsform.models import Attribution, RSFormCached
|
from apps.rsform.models import RSFormCached
|
||||||
from apps.rsform.serializers import RSFormParseSerializer
|
from apps.rsform.serializers import RSFormParseSerializer
|
||||||
from apps.users.models import User
|
from apps.users.models import User
|
||||||
from shared import permissions
|
from shared import permissions
|
||||||
|
|
@ -172,22 +172,7 @@ class LibraryViewSet(viewsets.ModelViewSet):
|
||||||
clone.location = data.get('location', m.LocationHead.USER)
|
clone.location = data.get('location', m.LocationHead.USER)
|
||||||
clone.save()
|
clone.save()
|
||||||
|
|
||||||
cst_map: dict[int, int] = {}
|
RSFormCached(clone).insert_from(item.pk, request.data['items'] if 'items' in request.data else None)
|
||||||
cst_list: list[int] = []
|
|
||||||
need_filter = 'items' in request.data and request.data['items']
|
|
||||||
for cst in RSFormCached(item).constituentsQ():
|
|
||||||
if not need_filter or cst.pk in request.data['items']:
|
|
||||||
old_pk = cst.pk
|
|
||||||
cst.pk = None
|
|
||||||
cst.schema = clone
|
|
||||||
cst.save()
|
|
||||||
cst_map[old_pk] = cst.pk
|
|
||||||
cst_list.append(old_pk)
|
|
||||||
for attr in Attribution.objects.filter(container__in=cst_list, attribute__in=cst_list):
|
|
||||||
attr.pk = None
|
|
||||||
attr.container_id = cst_map[attr.container_id]
|
|
||||||
attr.attribute_id = cst_map[attr.attribute_id]
|
|
||||||
attr.save()
|
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_201_CREATED,
|
status=c.HTTP_201_CREATED,
|
||||||
|
|
|
||||||
|
|
@ -137,11 +137,10 @@ class OperationSchema:
|
||||||
parents: dict = {}
|
parents: dict = {}
|
||||||
children: dict = {}
|
children: dict = {}
|
||||||
for operand in schemas:
|
for operand in schemas:
|
||||||
items = list(Constituenta.objects.filter(schema_id=operand).order_by('order'))
|
new_items = receiver.insert_from(operand)
|
||||||
new_items = receiver.insert_copy(items)
|
for (old_cst, new_cst) in new_items:
|
||||||
for (i, cst) in enumerate(new_items):
|
parents[new_cst.pk] = old_cst
|
||||||
parents[cst.pk] = items[i]
|
children[old_cst.pk] = new_cst
|
||||||
children[items[i].pk] = cst
|
|
||||||
|
|
||||||
translated_substitutions: list[tuple[Constituenta, Constituenta]] = []
|
translated_substitutions: list[tuple[Constituenta, Constituenta]] = []
|
||||||
for sub in substitutions:
|
for sub in substitutions:
|
||||||
|
|
|
||||||
|
|
@ -178,11 +178,10 @@ class OperationSchemaCached:
|
||||||
parents: dict = {}
|
parents: dict = {}
|
||||||
children: dict = {}
|
children: dict = {}
|
||||||
for operand in schemas:
|
for operand in schemas:
|
||||||
items = list(Constituenta.objects.filter(schema_id=operand).order_by('order'))
|
new_items = receiver.insert_from(operand)
|
||||||
new_items = receiver.insert_copy(items)
|
for (old_cst, new_cst) in new_items:
|
||||||
for (i, cst) in enumerate(new_items):
|
parents[new_cst.pk] = old_cst
|
||||||
parents[cst.pk] = items[i]
|
children[old_cst.pk] = new_cst
|
||||||
children[items[i].pk] = cst
|
|
||||||
|
|
||||||
translated_substitutions: list[tuple[Constituenta, Constituenta]] = []
|
translated_substitutions: list[tuple[Constituenta, Constituenta]] = []
|
||||||
for sub in substitutions:
|
for sub in substitutions:
|
||||||
|
|
@ -223,7 +222,7 @@ class OperationSchemaCached:
|
||||||
Inheritance.objects.filter(operation_id=operation.pk, parent_id__in=items).delete()
|
Inheritance.objects.filter(operation_id=operation.pk, parent_id__in=items).delete()
|
||||||
|
|
||||||
def relocate_up(self, source: RSFormCached, destination: RSFormCached,
|
def relocate_up(self, source: RSFormCached, destination: RSFormCached,
|
||||||
items: list[Constituenta]) -> list[Constituenta]:
|
item_ids: list[int]) -> list[Constituenta]:
|
||||||
''' Move list of Constituents upstream to destination Schema. '''
|
''' Move list of Constituents upstream to destination Schema. '''
|
||||||
self.cache.ensure_loaded_subs()
|
self.cache.ensure_loaded_subs()
|
||||||
self.cache.insert_schema(source)
|
self.cache.insert_schema(source)
|
||||||
|
|
@ -237,17 +236,18 @@ class OperationSchemaCached:
|
||||||
destination_cst = destination.cache.by_id[item.parent_id]
|
destination_cst = destination.cache.by_id[item.parent_id]
|
||||||
alias_mapping[source_cst.alias] = destination_cst.alias
|
alias_mapping[source_cst.alias] = destination_cst.alias
|
||||||
|
|
||||||
new_items = destination.insert_copy(items, initial_mapping=alias_mapping)
|
new_items = destination.insert_from(source.model.pk, item_ids, alias_mapping)
|
||||||
for index, cst in enumerate(new_items):
|
for (cst, new_cst) in new_items:
|
||||||
new_inheritance = Inheritance.objects.create(
|
new_inheritance = Inheritance.objects.create(
|
||||||
operation=operation,
|
operation=operation,
|
||||||
child=items[index],
|
child=cst,
|
||||||
parent=cst
|
parent=new_cst
|
||||||
)
|
)
|
||||||
self.cache.insert_inheritance(new_inheritance)
|
self.cache.insert_inheritance(new_inheritance)
|
||||||
self.after_create_cst(destination, new_items, exclude=[operation.pk])
|
new_constituents = [item[1] for item in new_items]
|
||||||
|
self.after_create_cst(destination, new_constituents, exclude=[operation.pk])
|
||||||
destination.model.save(update_fields=['time_update'])
|
destination.model.save(update_fields=['time_update'])
|
||||||
return new_items
|
return new_constituents
|
||||||
|
|
||||||
def after_create_cst(
|
def after_create_cst(
|
||||||
self, source: RSFormCached,
|
self, source: RSFormCached,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from typing import Optional
|
||||||
|
|
||||||
from rest_framework.serializers import ValidationError
|
from rest_framework.serializers import ValidationError
|
||||||
|
|
||||||
from apps.rsform.models import INSERT_LAST, Attribution, Constituenta, CstType, RSFormCached
|
from apps.rsform.models import Attribution, Constituenta, CstType, RSFormCached
|
||||||
|
|
||||||
from .Inheritance import Inheritance
|
from .Inheritance import Inheritance
|
||||||
from .Operation import Operation
|
from .Operation import Operation
|
||||||
|
|
@ -76,11 +76,11 @@ class PropagationEngine:
|
||||||
alias_mapping = cst_mapping_to_alias(new_mapping)
|
alias_mapping = cst_mapping_to_alias(new_mapping)
|
||||||
insert_where = self._determine_insert_position(items[0].pk, operation, source, destination)
|
insert_where = self._determine_insert_position(items[0].pk, operation, source, destination)
|
||||||
new_cst_list = destination.insert_copy(items, insert_where, alias_mapping)
|
new_cst_list = destination.insert_copy(items, insert_where, alias_mapping)
|
||||||
for index, cst in enumerate(new_cst_list):
|
for (cst, new_cst) in zip(items, new_cst_list):
|
||||||
new_inheritance = Inheritance.objects.create(
|
new_inheritance = Inheritance.objects.create(
|
||||||
operation=operation,
|
operation=operation,
|
||||||
child=cst,
|
child=new_cst,
|
||||||
parent=items[index]
|
parent=cst
|
||||||
)
|
)
|
||||||
self.cache.insert_inheritance(new_inheritance)
|
self.cache.insert_inheritance(new_inheritance)
|
||||||
new_mapping = {alias_mapping[alias]: cst for alias, cst in new_mapping.items()}
|
new_mapping = {alias_mapping[alias]: cst for alias, cst in new_mapping.items()}
|
||||||
|
|
@ -145,28 +145,28 @@ class PropagationEngine:
|
||||||
|
|
||||||
self.cache.ensure_loaded_subs()
|
self.cache.ensure_loaded_subs()
|
||||||
|
|
||||||
existing_associations = set(
|
existing_attributions = set(
|
||||||
Attribution.objects.filter(
|
Attribution.objects.filter(
|
||||||
container__schema_id=operation.result_id,
|
container__schema_id=operation.result_id,
|
||||||
).values_list('container_id', 'attribute_id')
|
).values_list('container_id', 'attribute_id')
|
||||||
)
|
)
|
||||||
|
|
||||||
new_associations: list[Attribution] = []
|
new_attributions: list[Attribution] = []
|
||||||
for assoc in items:
|
for attrib in items:
|
||||||
new_container = self.cache.get_inheritor(assoc.container_id, target)
|
new_container = self.cache.get_inheritor(attrib.container_id, target)
|
||||||
new_attribute = self.cache.get_inheritor(assoc.attribute_id, target)
|
new_attribute = self.cache.get_inheritor(attrib.attribute_id, target)
|
||||||
if new_container is None or new_attribute is None \
|
if new_container is None or new_attribute is None \
|
||||||
or new_attribute == new_container \
|
or new_attribute == new_container \
|
||||||
or (new_container, new_attribute) in existing_associations:
|
or (new_container, new_attribute) in existing_attributions:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
new_associations.append(Attribution(
|
new_attributions.append(Attribution(
|
||||||
container_id=new_container,
|
container_id=new_container,
|
||||||
attribute_id=new_attribute
|
attribute_id=new_attribute
|
||||||
))
|
))
|
||||||
if new_associations:
|
if new_attributions:
|
||||||
new_associations = Attribution.objects.bulk_create(new_associations)
|
new_attributions = Attribution.objects.bulk_create(new_attributions)
|
||||||
self.on_inherit_attribution(target, new_associations)
|
self.on_inherit_attribution(target, new_attributions)
|
||||||
|
|
||||||
def on_before_substitute(self, operationID: int, substitutions: CstSubstitution) -> None:
|
def on_before_substitute(self, operationID: int, substitutions: CstSubstitution) -> None:
|
||||||
''' Trigger cascade resolutions when Constituenta substitution is executed. '''
|
''' Trigger cascade resolutions when Constituenta substitution is executed. '''
|
||||||
|
|
@ -286,7 +286,7 @@ class PropagationEngine:
|
||||||
operation: Operation,
|
operation: Operation,
|
||||||
source: RSFormCached,
|
source: RSFormCached,
|
||||||
destination: RSFormCached
|
destination: RSFormCached
|
||||||
) -> int:
|
) -> Optional[int]:
|
||||||
''' Determine insert_after for new constituenta. '''
|
''' Determine insert_after for new constituenta. '''
|
||||||
prototype = source.cache.by_id[prototype_id]
|
prototype = source.cache.by_id[prototype_id]
|
||||||
prototype_index = source.cache.constituents.index(prototype)
|
prototype_index = source.cache.constituents.index(prototype)
|
||||||
|
|
@ -295,7 +295,7 @@ class PropagationEngine:
|
||||||
prev_cst = source.cache.constituents[prototype_index - 1]
|
prev_cst = source.cache.constituents[prototype_index - 1]
|
||||||
inherited_prev_id = self.cache.get_successor(prev_cst.pk, operation.pk)
|
inherited_prev_id = self.cache.get_successor(prev_cst.pk, operation.pk)
|
||||||
if inherited_prev_id is None:
|
if inherited_prev_id is None:
|
||||||
return INSERT_LAST
|
return None
|
||||||
prev_cst = destination.cache.by_id[inherited_prev_id]
|
prev_cst = destination.cache.by_id[inherited_prev_id]
|
||||||
prev_index = destination.cache.constituents.index(prev_cst)
|
prev_index = destination.cache.constituents.index(prev_cst)
|
||||||
return prev_index + 1
|
return prev_index + 1
|
||||||
|
|
|
||||||
|
|
@ -602,7 +602,7 @@ class RelocateConstituentsSerializer(StrictSerializer):
|
||||||
items = PKField(
|
items = PKField(
|
||||||
many=True,
|
many=True,
|
||||||
allow_empty=False,
|
allow_empty=False,
|
||||||
queryset=Constituenta.objects.all()
|
queryset=Constituenta.objects.all().only('schema_id')
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from rest_framework.response import Response
|
||||||
|
|
||||||
from apps.library.models import LibraryItem, LibraryItemType
|
from apps.library.models import LibraryItem, LibraryItemType
|
||||||
from apps.library.serializers import LibraryItemSerializer
|
from apps.library.serializers import LibraryItemSerializer
|
||||||
from apps.rsform.models import Attribution, Constituenta, RSFormCached
|
from apps.rsform.models import Constituenta, RSFormCached
|
||||||
from apps.rsform.serializers import CstTargetSerializer
|
from apps.rsform.serializers import CstTargetSerializer
|
||||||
from shared import messages as msg
|
from shared import messages as msg
|
||||||
from shared import permissions
|
from shared import permissions
|
||||||
|
|
@ -23,40 +23,6 @@ from .. import models as m
|
||||||
from .. import serializers as s
|
from .. import serializers as s
|
||||||
|
|
||||||
|
|
||||||
def _create_clone(prototype: LibraryItem, operation: m.Operation, oss: LibraryItem) -> LibraryItem:
|
|
||||||
''' Create clone of prototype schema for operation. '''
|
|
||||||
clone = deepcopy(prototype)
|
|
||||||
clone.pk = None
|
|
||||||
clone.owner = oss.owner
|
|
||||||
clone.title = operation.title
|
|
||||||
clone.alias = operation.alias
|
|
||||||
clone.description = operation.description
|
|
||||||
clone.visible = False
|
|
||||||
clone.read_only = False
|
|
||||||
clone.access_policy = oss.access_policy
|
|
||||||
clone.location = oss.location
|
|
||||||
clone.save()
|
|
||||||
|
|
||||||
cst_map: dict[int, int] = {}
|
|
||||||
cst_list: list[int] = []
|
|
||||||
|
|
||||||
for cst in Constituenta.objects.filter(schema_id=prototype.pk):
|
|
||||||
old_pk = cst.pk
|
|
||||||
cst_copy = deepcopy(cst)
|
|
||||||
cst_copy.pk = None
|
|
||||||
cst_copy.schema = clone
|
|
||||||
cst_copy.save()
|
|
||||||
cst_map[old_pk] = cst_copy.pk
|
|
||||||
cst_list.append(old_pk)
|
|
||||||
|
|
||||||
for attr in Attribution.objects.filter(container__in=cst_list, attribute__in=cst_list):
|
|
||||||
attr.pk = None
|
|
||||||
attr.container_id = cst_map[attr.container_id]
|
|
||||||
attr.attribute_id = cst_map[attr.attribute_id]
|
|
||||||
attr.save()
|
|
||||||
return clone
|
|
||||||
|
|
||||||
|
|
||||||
@extend_schema(tags=['OSS'])
|
@extend_schema(tags=['OSS'])
|
||||||
@extend_schema_view()
|
@extend_schema_view()
|
||||||
class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.RetrieveAPIView):
|
class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.RetrieveAPIView):
|
||||||
|
|
@ -442,7 +408,21 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
||||||
|
|
||||||
if serializer.validated_data['clone_source']:
|
if serializer.validated_data['clone_source']:
|
||||||
prototype: LibraryItem = serializer.validated_data['source']
|
prototype: LibraryItem = serializer.validated_data['source']
|
||||||
new_operation.result = _create_clone(prototype, new_operation, item)
|
|
||||||
|
schema_clone = deepcopy(prototype)
|
||||||
|
schema_clone.pk = None
|
||||||
|
schema_clone.owner = item.owner
|
||||||
|
schema_clone.title = new_operation.title
|
||||||
|
schema_clone.alias = new_operation.alias
|
||||||
|
schema_clone.description = new_operation.description
|
||||||
|
schema_clone.visible = False
|
||||||
|
schema_clone.read_only = False
|
||||||
|
schema_clone.access_policy = item.access_policy
|
||||||
|
schema_clone.location = item.location
|
||||||
|
schema_clone.save()
|
||||||
|
RSFormCached(schema_clone).insert_from(prototype.pk)
|
||||||
|
|
||||||
|
new_operation.result = schema_clone
|
||||||
new_operation.save(update_fields=["result"])
|
new_operation.save(update_fields=["result"])
|
||||||
|
|
||||||
item.save(update_fields=['time_update'])
|
item.save(update_fields=['time_update'])
|
||||||
|
|
@ -860,7 +840,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
||||||
m.PropagationFacade.before_delete_cst(data['source'], ids)
|
m.PropagationFacade.before_delete_cst(data['source'], ids)
|
||||||
source.delete_cst(ids)
|
source.delete_cst(ids)
|
||||||
else:
|
else:
|
||||||
new_items = oss.relocate_up(source, destination, data['items'])
|
new_items = oss.relocate_up(source, destination, ids)
|
||||||
m.PropagationFacade.after_create_cst(destination, new_items, exclude=[oss.model.pk])
|
m.PropagationFacade.after_create_cst(destination, new_items, exclude=[oss.model.pk])
|
||||||
|
|
||||||
return Response(status=c.HTTP_200_OK)
|
return Response(status=c.HTTP_200_OK)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ from .api_RSLanguage import get_type_prefix, guess_type
|
||||||
from .Attribution import Attribution
|
from .Attribution import Attribution
|
||||||
from .Constituenta import Constituenta, CstType, extract_entities, extract_globals
|
from .Constituenta import Constituenta, CstType, extract_entities, extract_globals
|
||||||
|
|
||||||
INSERT_LAST: int = -1
|
|
||||||
DELETED_ALIAS = 'DEL'
|
DELETED_ALIAS = 'DEL'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from shared import messages as msg
|
||||||
from .api_RSLanguage import generate_structure, get_type_prefix, guess_type
|
from .api_RSLanguage import generate_structure, get_type_prefix, guess_type
|
||||||
from .Attribution import Attribution
|
from .Attribution import Attribution
|
||||||
from .Constituenta import Constituenta, CstType
|
from .Constituenta import Constituenta, CstType
|
||||||
from .RSForm import DELETED_ALIAS, INSERT_LAST, RSForm
|
from .RSForm import DELETED_ALIAS, RSForm
|
||||||
|
|
||||||
|
|
||||||
class RSFormCached:
|
class RSFormCached:
|
||||||
|
|
@ -76,7 +76,7 @@ class RSFormCached:
|
||||||
def create_cst(self, data: dict, insert_after: Optional[Constituenta] = None) -> Constituenta:
|
def create_cst(self, data: dict, insert_after: Optional[Constituenta] = None) -> Constituenta:
|
||||||
''' Create constituenta from data. '''
|
''' Create constituenta from data. '''
|
||||||
self.cache.ensure_loaded_terms()
|
self.cache.ensure_loaded_terms()
|
||||||
if insert_after is not None:
|
if insert_after:
|
||||||
position = self.cache.by_id[insert_after.pk].order + 1
|
position = self.cache.by_id[insert_after.pk].order + 1
|
||||||
else:
|
else:
|
||||||
position = len(self.cache.constituents)
|
position = len(self.cache.constituents)
|
||||||
|
|
@ -109,52 +109,77 @@ class RSFormCached:
|
||||||
RSForm.resolve_term_change(self.cache.constituents, [result.pk], self.cache.by_alias, self.cache.by_id)
|
RSForm.resolve_term_change(self.cache.constituents, [result.pk], self.cache.by_alias, self.cache.by_id)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def insert_from(
|
||||||
|
self, sourceID: int,
|
||||||
|
items_list: Optional[list[int]] = None,
|
||||||
|
initial_mapping: Optional[dict[str, str]] = None
|
||||||
|
) -> list[tuple[Constituenta, Constituenta]]:
|
||||||
|
''' Insert copy of constituents from source schema. '''
|
||||||
|
if not items_list:
|
||||||
|
items = list(Constituenta.objects.filter(schema_id=sourceID).order_by('order'))
|
||||||
|
else:
|
||||||
|
items = list(Constituenta.objects.filter(pk__in=items_list, schema_id=sourceID).order_by('order'))
|
||||||
|
if not items:
|
||||||
|
return []
|
||||||
|
new_constituents = self.insert_copy(items=items, initial_mapping=initial_mapping)
|
||||||
|
return list(zip(items, new_constituents))
|
||||||
|
|
||||||
def insert_copy(
|
def insert_copy(
|
||||||
self,
|
self,
|
||||||
items: list[Constituenta],
|
items: list[Constituenta],
|
||||||
position: int = INSERT_LAST,
|
position: Optional[int] = None,
|
||||||
initial_mapping: Optional[dict[str, str]] = None
|
initial_mapping: Optional[dict[str, str]] = None
|
||||||
) -> list[Constituenta]:
|
) -> list[Constituenta]:
|
||||||
''' Insert copy of target constituents updating references. '''
|
''' Insert copy of target constituents updating references. '''
|
||||||
count = len(items)
|
if not items:
|
||||||
if count == 0:
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.cache.ensure_loaded()
|
self.cache.ensure_loaded()
|
||||||
lastPosition = len(self.cache.constituents)
|
last_position = len(self.cache.constituents)
|
||||||
if position == INSERT_LAST:
|
if not position:
|
||||||
position = lastPosition
|
position = last_position
|
||||||
else:
|
else:
|
||||||
position = max(0, min(position, lastPosition))
|
position = max(0, min(position, last_position))
|
||||||
RSForm.shift_positions(position, count, self.cache.constituents)
|
|
||||||
|
|
||||||
|
was_empty = last_position == 0
|
||||||
|
if not was_empty and position != last_position:
|
||||||
|
RSForm.shift_positions(position, len(items), self.cache.constituents)
|
||||||
|
|
||||||
|
mapping_alias: dict[str, str] = initial_mapping.copy() if initial_mapping else {}
|
||||||
|
if not was_empty:
|
||||||
indices: dict[str, int] = {}
|
indices: dict[str, int] = {}
|
||||||
for (value, _) in CstType.choices:
|
for (value, _) in CstType.choices:
|
||||||
indices[value] = -1
|
indices[value] = self._get_max_index(value)
|
||||||
|
|
||||||
mapping: dict[str, str] = initial_mapping.copy() if initial_mapping else {}
|
|
||||||
for cst in items:
|
for cst in items:
|
||||||
if indices[cst.cst_type] == -1:
|
|
||||||
indices[cst.cst_type] = self._get_max_index(cst.cst_type)
|
|
||||||
indices[cst.cst_type] = indices[cst.cst_type] + 1
|
indices[cst.cst_type] = indices[cst.cst_type] + 1
|
||||||
newAlias = f'{get_type_prefix(cst.cst_type)}{indices[cst.cst_type]}'
|
newAlias = f'{get_type_prefix(cst.cst_type)}{indices[cst.cst_type]}'
|
||||||
mapping[cst.alias] = newAlias
|
mapping_alias[cst.alias] = newAlias
|
||||||
|
|
||||||
result = deepcopy(items)
|
source_ids = [cst.id for cst in items]
|
||||||
for cst in result:
|
new_constituents = deepcopy(items)
|
||||||
|
for cst in new_constituents:
|
||||||
cst.pk = None
|
cst.pk = None
|
||||||
cst.schema = self.model
|
cst.schema = self.model
|
||||||
cst.order = position
|
cst.order = position
|
||||||
cst.alias = mapping[cst.alias]
|
if mapping_alias:
|
||||||
cst.apply_mapping(mapping)
|
cst.alias = mapping_alias[cst.alias]
|
||||||
|
cst.apply_mapping(mapping_alias)
|
||||||
position = position + 1
|
position = position + 1
|
||||||
|
|
||||||
new_cst = Constituenta.objects.bulk_create(result)
|
new_constituents = Constituenta.objects.bulk_create(new_constituents)
|
||||||
|
|
||||||
# TODO: duplicate attributions
|
mapping_id: dict[int, int] = {source_ids[i]: new_constituents[i].id for i in range(len(source_ids))}
|
||||||
|
attributions = list(Attribution.objects.filter(container__in=source_ids, attribute__in=source_ids))
|
||||||
|
for attr in attributions:
|
||||||
|
attr.pk = None
|
||||||
|
attr.container_id = mapping_id[attr.container_id]
|
||||||
|
attr.attribute_id = mapping_id[attr.attribute_id]
|
||||||
|
|
||||||
self.cache.insert_multi(new_cst)
|
Attribution.objects.bulk_create(attributions)
|
||||||
return result
|
|
||||||
|
self.cache.insert_multi(new_constituents)
|
||||||
|
return new_constituents
|
||||||
|
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
def update_cst(self, target: int, data: dict) -> dict:
|
def update_cst(self, target: int, data: dict) -> dict:
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
from .Attribution import Attribution
|
from .Attribution import Attribution
|
||||||
from .Constituenta import Constituenta, CstType, extract_globals, replace_entities, replace_globals
|
from .Constituenta import Constituenta, CstType, extract_globals, replace_entities, replace_globals
|
||||||
from .OrderManager import OrderManager
|
from .OrderManager import OrderManager
|
||||||
from .RSForm import DELETED_ALIAS, INSERT_LAST, RSForm
|
from .RSForm import DELETED_ALIAS, RSForm
|
||||||
from .RSFormCached import RSFormCached
|
from .RSFormCached import RSFormCached
|
||||||
|
|
|
||||||
|
|
@ -436,7 +436,7 @@ class InlineSynthesisSerializer(StrictSerializer):
|
||||||
''' Serializer: Inline synthesis operation input. '''
|
''' Serializer: Inline synthesis operation input. '''
|
||||||
receiver = PKField(many=False, queryset=LibraryItem.objects.all().only('owner_id'))
|
receiver = PKField(many=False, queryset=LibraryItem.objects.all().only('owner_id'))
|
||||||
source = PKField(many=False, queryset=LibraryItem.objects.all().only('owner_id')) # type: ignore
|
source = PKField(many=False, queryset=LibraryItem.objects.all().only('owner_id')) # type: ignore
|
||||||
items = PKField(many=True, queryset=Constituenta.objects.all())
|
items = PKField(many=True, queryset=Constituenta.objects.all().only('schema_id'))
|
||||||
substitutions = serializers.ListField(
|
substitutions = serializers.ListField(
|
||||||
child=SubstitutionSerializerBase()
|
child=SubstitutionSerializerBase()
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -732,25 +732,24 @@ def inline_synthesis(request: Request) -> HttpResponse:
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
receiver = m.RSFormCached(serializer.validated_data['receiver'])
|
receiver = m.RSFormCached(serializer.validated_data['receiver'])
|
||||||
items = cast(list[m.Constituenta], serializer.validated_data['items'])
|
target_cst = cast(list[m.Constituenta], serializer.validated_data['items'])
|
||||||
if not items:
|
|
||||||
source = cast(LibraryItem, serializer.validated_data['source'])
|
source = cast(LibraryItem, serializer.validated_data['source'])
|
||||||
items = list(m.Constituenta.objects.filter(schema=source).order_by('order'))
|
target_ids = [item.pk for item in target_cst] if target_cst else None
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
new_items = receiver.insert_copy(items)
|
new_items = receiver.insert_from(source.pk, target_ids)
|
||||||
PropagationFacade.after_create_cst(receiver, new_items)
|
target_ids = [item[0].pk for item in new_items]
|
||||||
|
mapping_ids = {cst.pk: new_cst for (cst, new_cst) in new_items}
|
||||||
|
PropagationFacade.after_create_cst(receiver, [item[1] for item in new_items])
|
||||||
|
|
||||||
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
|
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
|
||||||
for substitution in serializer.validated_data['substitutions']:
|
for substitution in serializer.validated_data['substitutions']:
|
||||||
original = cast(m.Constituenta, substitution['original'])
|
original = cast(m.Constituenta, substitution['original'])
|
||||||
replacement = cast(m.Constituenta, substitution['substitution'])
|
replacement = cast(m.Constituenta, substitution['substitution'])
|
||||||
if original in items:
|
if original.pk in target_ids:
|
||||||
index = next(i for (i, cst) in enumerate(items) if cst.pk == original.pk)
|
original = mapping_ids[original.pk]
|
||||||
original = new_items[index]
|
|
||||||
else:
|
else:
|
||||||
index = next(i for (i, cst) in enumerate(items) if cst.pk == replacement.pk)
|
replacement = mapping_ids[replacement.pk]
|
||||||
replacement = new_items[index]
|
|
||||||
substitutions.append((original, replacement))
|
substitutions.append((original, replacement))
|
||||||
|
|
||||||
PropagationFacade.before_substitute(receiver.model.pk, substitutions)
|
PropagationFacade.before_substitute(receiver.model.pk, substitutions)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user