mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-25 20:40:36 +03:00
138 lines
4.0 KiB
Python
138 lines
4.0 KiB
Python
''' Models: Constituenta. '''
|
||
import re
|
||
|
||
from django.core.validators import MinValueValidator
|
||
from django.db.models import (
|
||
CASCADE,
|
||
CharField,
|
||
ForeignKey,
|
||
JSONField,
|
||
Model,
|
||
PositiveIntegerField,
|
||
TextChoices,
|
||
TextField
|
||
)
|
||
from django.urls import reverse
|
||
|
||
from ..utils import apply_pattern
|
||
|
||
_REF_ENTITY_PATTERN = re.compile(r'@{([^0-9\-].*?)\|.*?}')
|
||
_GLOBAL_ID_PATTERN = re.compile(r'([XCSADFPT][0-9]+)') # cspell:disable-line
|
||
|
||
|
||
def _empty_forms():
|
||
return []
|
||
|
||
|
||
class CstType(TextChoices):
|
||
''' Type of constituenta. '''
|
||
BASE = 'basic'
|
||
CONSTANT = 'constant'
|
||
STRUCTURED = 'structure'
|
||
AXIOM = 'axiom'
|
||
TERM = 'term'
|
||
FUNCTION = 'function'
|
||
PREDICATE = 'predicate'
|
||
THEOREM = 'theorem'
|
||
|
||
|
||
class Constituenta(Model):
|
||
''' Constituenta is the base unit for every conceptual schema. '''
|
||
schema: ForeignKey = ForeignKey(
|
||
verbose_name='Концептуальная схема',
|
||
to='rsform.RSForm',
|
||
on_delete=CASCADE
|
||
)
|
||
order: PositiveIntegerField = PositiveIntegerField(
|
||
verbose_name='Позиция',
|
||
validators=[MinValueValidator(1)],
|
||
default=-1,
|
||
)
|
||
alias: CharField = CharField(
|
||
verbose_name='Имя',
|
||
max_length=8,
|
||
default='undefined'
|
||
)
|
||
cst_type: CharField = CharField(
|
||
verbose_name='Тип',
|
||
max_length=10,
|
||
choices=CstType.choices,
|
||
default=CstType.BASE
|
||
)
|
||
convention: TextField = TextField(
|
||
verbose_name='Комментарий/Конвенция',
|
||
default='',
|
||
blank=True
|
||
)
|
||
term_raw: TextField = TextField(
|
||
verbose_name='Термин (с отсылками)',
|
||
default='',
|
||
blank=True
|
||
)
|
||
term_resolved: TextField = TextField(
|
||
verbose_name='Термин',
|
||
default='',
|
||
blank=True
|
||
)
|
||
term_forms: JSONField = JSONField(
|
||
verbose_name='Словоформы',
|
||
default=_empty_forms
|
||
)
|
||
definition_formal: TextField = TextField(
|
||
verbose_name='Родоструктурное определение',
|
||
default='',
|
||
blank=True
|
||
)
|
||
definition_raw: TextField = TextField(
|
||
verbose_name='Текстовое определение (с отсылками)',
|
||
default='',
|
||
blank=True
|
||
)
|
||
definition_resolved: TextField = TextField(
|
||
verbose_name='Текстовое определение',
|
||
default='',
|
||
blank=True
|
||
)
|
||
|
||
class Meta:
|
||
''' Model metadata. '''
|
||
verbose_name = 'Конституента'
|
||
verbose_name_plural = 'Конституенты'
|
||
|
||
def get_absolute_url(self):
|
||
''' URL access. '''
|
||
return reverse('constituenta-detail', kwargs={'pk': self.pk})
|
||
|
||
def __str__(self) -> str:
|
||
return f'{self.alias}'
|
||
|
||
def set_term_resolved(self, new_term: str):
|
||
''' Set term and reset forms if needed. '''
|
||
if new_term == self.term_resolved:
|
||
return
|
||
self.term_resolved = new_term
|
||
self.term_forms = []
|
||
|
||
def apply_mapping(self, mapping: dict[str, str], change_aliases: bool = False):
|
||
modified = False
|
||
if change_aliases and self.alias in mapping:
|
||
modified = True
|
||
self.alias = mapping[self.alias]
|
||
expression = apply_pattern(self.definition_formal, mapping, _GLOBAL_ID_PATTERN)
|
||
if expression != self.definition_formal:
|
||
modified = True
|
||
self.definition_formal = expression
|
||
convention = apply_pattern(self.convention, mapping, _GLOBAL_ID_PATTERN)
|
||
if convention != self.convention:
|
||
modified = True
|
||
self.convention = convention
|
||
term = apply_pattern(self.term_raw, mapping, _REF_ENTITY_PATTERN)
|
||
if term != self.term_raw:
|
||
modified = True
|
||
self.term_raw = term
|
||
definition = apply_pattern(self.definition_raw, mapping, _REF_ENTITY_PATTERN)
|
||
if definition != self.definition_raw:
|
||
modified = True
|
||
self.definition_raw = definition
|
||
return modified
|