Skip to content

Commit

Permalink
OpenConceptLab/ocl_issues#818 | collection version with expansions an…
Browse files Browse the repository at this point in the history
…d parameters
  • Loading branch information
snyaggarwal committed Sep 6, 2021
1 parent 4ce3622 commit acc308f
Show file tree
Hide file tree
Showing 10 changed files with 336 additions and 58 deletions.
176 changes: 140 additions & 36 deletions core/collections/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
DEFAULT_REPOSITORY_TYPE, ACCESS_TYPE_VIEW, ACCESS_TYPE_EDIT
)
from core.common.models import ConceptContainerModel, BaseResourceModel
from core.common.utils import is_valid_uri, drop_version
from core.common.utils import is_valid_uri, drop_version, to_owner_uri, generate_temp_version
from core.concepts.constants import LOCALES_FULLY_SPECIFIED
from core.concepts.models import Concept
from core.concepts.views import ConceptListView
Expand Down Expand Up @@ -369,13 +369,10 @@ def get_cascaded_mapping_uris_from_concept_expressions(self, expressions):

return mapping_uris

def cascade_children_to_expansion(self, index=True):
expansion = self.expansions.create()
expansion.mnemonic = expansion.id
expansion.save()
expansion.seed_concepts(index=index)
expansion.seed_mappings(index=index)
expansion.seed_references()
def cascade_children_to_expansion(self, expansion_data=None, index=True):
if not expansion_data:
expansion_data = dict()
return Expansion.persist(index=index, **expansion_data, collection_version=self)

@property
def latest_expansion_url(self):
Expand Down Expand Up @@ -443,12 +440,18 @@ def save(self, force_insert=False, force_update=False, using=None, update_fields
self.internal_reference_id = str(self.id)
super().save(force_insert, force_update, using, update_fields)

@property
def is_concept(self):
return is_concept(self.expression)

@property
def is_mapping(self):
return is_mapping(self.expression)

def create_entities_from_expressions(self):
__is_concept = is_concept(self.expression)
__is_mapping = is_mapping(self.expression)
if __is_concept:
if self.is_concept:
self.concepts = self.get_concepts()
elif __is_mapping:
elif self.is_mapping:
self.mappings = self.get_mappings()

if self.concepts and self.concepts.exists():
Expand Down Expand Up @@ -507,10 +510,6 @@ class Meta:
def default_parameters():
return default_expansion_parameters()

@property
def expansion(self):
return self.mnemonic

@staticmethod
def get_resource_url_kwarg():
return 'expansion'
Expand All @@ -519,29 +518,134 @@ def get_resource_url_kwarg():
def get_url_kwarg():
return 'expansion'

def seed_concepts(self, index=True):
head = self.collection_version.head
if head:
self.concepts.set(head.concepts.all())
if index:
from core.concepts.documents import ConceptDocument
self.batch_index(self.concepts, ConceptDocument)
@property
def expansion(self):
return self.mnemonic

def seed_mappings(self, index=True):
head = self.collection_version.head
if head:
self.mappings.set(head.mappings.all())
if index:
from core.mappings.documents import MappingDocument
self.batch_index(self.mappings, MappingDocument)
@property
def active_concepts(self):
return self.concepts.count()

@property
def active_mappings(self):
return self.mappings.count()

@property
def active_references(self):
return self.references.count()

@property
def owner_url(self):
return to_owner_uri(self.uri)

def apply_parameters(self, queryset):
parameters = ExpansionParameters(self.parameters)
return parameters.apply(queryset)

def populate(self, index=True):
self.seed_references()
self.seed_children(index=index)

def index_concepts(self):
if self.concepts.exists():
from core.concepts.documents import ConceptDocument
self.batch_index(self.concepts, ConceptDocument)

def index_mappings(self):
if self.mappings.exists():
from core.mappings.documents import MappingDocument
self.batch_index(self.mappings, MappingDocument)

def index_all(self):
self.index_concepts()
self.index_mappings()

def seed_children(self, index=True):
version = self.collection_version
for reference in version.references.all():
if reference.is_concept:
concepts = reference.get_concepts()
if concepts.exists():
self.concepts.add(*self.apply_parameters(concepts))
elif reference.is_mapping:
mappings = reference.get_mappings()
if mappings.exists():
self.mappings.add(*self.apply_parameters(mappings))

if index:
self.index_all()

def seed_references(self):
head = self.collection_version.head
if head:
references = CollectionReference.objects.bulk_create(
[CollectionReference(expression=ref.expression) for ref in head.references.all()]
)
self.references.set(references)
version = self.collection_version
references = CollectionReference.objects.bulk_create(
[CollectionReference(expression=ref.expression) for ref in version.references.all()]
)
self.references.set(references)

def calculate_uri(self):
return self.collection_version.uri + 'expansions/{}/'.format(self.mnemonic)

def clean(self):
if not self.parameters:
self.parameters = default_expansion_parameters()

super().clean()

@classmethod
def persist(cls, index, **kwargs):
expansion = cls(**kwargs)
temp_version = not bool(expansion.mnemonic)
if temp_version:
expansion.mnemonic = generate_temp_version()
expansion.clean()
expansion.full_clean()
expansion.save()
if temp_version and expansion.id:
expansion.mnemonic = expansion.id
expansion.save()

expansion.populate(index=index)
return expansion


class ExpansionParameters:
ACTIVE = 'activeOnly'

def __init__(self, parameters):
self.parameters = parameters
self.parameter_classes = dict()
self.filters = dict()
self.to_parameter_classes()
self.get_filters()

def to_parameter_classes(self):
for parameter, value in self.parameters.items():
if parameter == self.ACTIVE:
self.parameter_classes[parameter] = ExpansionActiveParameter(value=value)

def apply(self, queryset):
queryset = queryset.filter(**self.filters)
return queryset

def get_filters(self):
for _, klass in self.parameter_classes.items():
if klass.can_apply_filters:
self.filters = {**self.filters, **klass.filters}


class ExpansionParameter:
can_apply_filters = True

def __init__(self, value):
self.value = value


class ExpansionActiveParameter(ExpansionParameter):
default_filters = dict(is_active=True, retired=False)

@property
def filters(self):
if self.value is True:
return self.default_filters

return dict()
48 changes: 46 additions & 2 deletions core/collections/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,22 @@ def create_version(self, validated_data):
return collection


class ExpansionSummarySerializer(ModelSerializer):
concepts = IntegerField(source='active_concepts', read_only=True)
mappings = IntegerField(source='active_mappings', read_only=True)
references = IntegerField(source='active_references', read_only=True)

class Meta:
model = Expansion
fields = ('concepts', 'mappings', 'references')


class ExpansionSummaryDetailSerializer(ExpansionSummarySerializer):
class Meta:
model = Expansion
fields = ExpansionSummarySerializer.Meta.fields + ('id', 'mnemonic')


class CollectionSummarySerializer(ModelSerializer):
versions = IntegerField(source='num_versions')

Expand Down Expand Up @@ -290,6 +306,7 @@ class CollectionVersionDetailSerializer(CollectionCreateOrUpdateSerializer):
updated_by = CharField(read_only=True, source='updated_by.username')
summary = SerializerMethodField()
autoexpand = SerializerMethodField()
expansion_url = CharField(source='latest_expansion_url', read_only=True)

class Meta:
model = Collection
Expand All @@ -302,7 +319,7 @@ class Meta:
'version', 'concepts_url', 'mappings_url', 'is_processing', 'released', 'retired',
'canonical_url', 'identifier', 'publisher', 'contact', 'jurisdiction', 'purpose', 'copyright', 'meta',
'immutable', 'revision_date', 'summary', 'text', 'experimental', 'locked_date', 'internal_reference_id',
'autoexpand',
'autoexpand', 'expansion_url'
)

def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -361,6 +378,33 @@ class Meta:


class ExpansionSerializer(ModelSerializer):
summary = SerializerMethodField()
url = CharField(source='uri', read_only=True)
parameters = JSONField()

class Meta:
model = Expansion
fields = ('id', 'parameters', 'canonical_url', 'uri')
fields = ('mnemonic', 'id', 'parameters', 'canonical_url', 'url', 'summary')

def __init__(self, *args, **kwargs):
params = get(kwargs, 'context.request.query_params')
self.include_summary = False
if params:
self.query_params = params.dict()
self.include_summary = self.query_params.get(INCLUDE_SUMMARY) in ['true', True]

try:
if not self.include_summary:
self.fields.pop('summary', None)
except: # pylint: disable=bare-except
pass

super().__init__(*args, **kwargs)

def get_summary(self, obj):
summary = None

if self.include_summary:
summary = ExpansionSummarySerializer(obj).data

return summary
18 changes: 18 additions & 0 deletions core/collections/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@
views.CollectionVersionExpansionView.as_view(),
name='collection-version-expansion-detail'
),
re_path(
r'^(?P<collection>{pattern})/(?P<version>{pattern})/expansions/(?P<expansion>{pattern})/references/$'.format(
pattern=NAMESPACE_PATTERN),
views.CollectionVersionExpansionReferencesView.as_view(),
name='collection-version-expansion-references'
),
re_path(
r'^(?P<collection>{pattern})/(?P<version>{pattern})/expansions/(?P<expansion>{pattern})/concepts/$'.format(
pattern=NAMESPACE_PATTERN),
views.CollectionVersionExpansionConceptsView.as_view(),
name='collection-version-expansion-concepts'
),
re_path(
r'^(?P<collection>{pattern})/(?P<version>{pattern})/expansions/(?P<expansion>{pattern})/mappings/$'.format(
pattern=NAMESPACE_PATTERN),
views.CollectionVersionExpansionMappingsView.as_view(),
name='collection-version-expansion-mappings'
),
re_path(
r"^(?P<collection>{pattern})/extras/(?P<extra>{pattern})/$".format(pattern=NAMESPACE_PATTERN),
views.CollectionExtraRetrieveUpdateDestroyView.as_view(),
Expand Down
Loading

0 comments on commit acc308f

Please sign in to comment.