Source code for inspire_eu.models.core

import logging

from django.contrib.gis.db import models
try:
    from django.utils.translation import gettext_lazy as _
except ImportError:
    from django.utils.translation import ugettext_lazy as _
try:
    from slugify import slugify
except ImportError:
    from django.utils.text import slugify

from ..utils import get_inspire_eu_base_model

log = logging.getLogger(__name__)


###############################################################################
#                             ____                                            #
#                            / ___|___  _ __ ___                              #
#                           | |   / _ \| '__/ _ \                             #
#                           | |__| (_) | | |  __/                             #
#                            \____\___/|_|  \___|                             #
#                                                                             #
###############################################################################

try:
    BaseInspireEUModel = get_inspire_eu_base_model()
except AttributeError:

[docs] class BaseInspireEUModel(models.Model): """Base Model Definition Abstract class that appends common fields """ class Meta: abstract = True
[docs] class Namespace(BaseInspireEUModel): """Namespace Definition Namespace uniquely identifying the data source of the spatial object. Description NOTE The namespace value will be owned by the data provider of the spatial object and will be registered in the INSPIRE External Object Identifier Namespaces Register. """ code = models.CharField(max_length=32, help_text=_("Namespace")) name = models.CharField(max_length=64, blank=True) class Meta: verbose_name = _("Namespace") verbose_name_plural = _("Namespaces") ordering = ["code", "name"] def __str__(self): return "%s %s" % (self.code, self.name)
[docs] class Status(BaseInspireEUModel): """Status Description Possible values: Valid, Invalid References * https://inspire.ec.europa.eu/registry/status/valid * https://inspire.ec.europa.eu/registry/status/invalid """ code = models.CharField(max_length=32, db_index=True) slug = models.CharField(max_length=32, blank=True, db_index=True) label = models.CharField(max_length=128) definition = models.TextField(blank=True) link = models.URLField() is_valid = models.BooleanField(default=True) class Meta: verbose_name = _("Status") verbose_name_plural = _("Status") ordering = ["is_valid", "label"] def __str__(self): return "%s: %s" % (self.code, self.label) def save(self, *args, **kwargs): self.link = self.link.replace("http://", "https://") if not self.code: self.code = self.link.split("/")[-1] self.slug = slugify(self.code)[:32] return super().save(*args, **kwargs)
[docs] class Theme(BaseInspireEUModel): """INSPIRE theme register Definition The INSPIRE theme register contains all spatial data themes, as defined in the Annexes of the INSPIRE Directive (Directive 2007/2/EC of the European Parliament and of the Council of 14 March 2007 establishing an Infrastructure for Spatial Information in the European Community (INSPIRE)). The descriptions of the themes are based on version 3.0 of the Definition of Annex Themes and Scope (D 2.3) by the data specifications drafting team and subsequent updates by the INSPIRE Thematic Working Groups (TWGs). Owner European Union Register manager European Commission, Joint Research Centre Control body Control body for the central INSPIRE registers and INSPIRE register federation Submitter Nominated submitting organizations for the central INSPIRE registers and INSPIRE register federation Contact point JRC INSPIRE Registry Team <inspire-registry-dev@jrc.ec.europa.eu> Licence Europa Legal Notice References https://inspire.ec.europa.eu/theme """ code = models.CharField(max_length=32, db_index=True) slug = models.CharField(max_length=32, blank=True, db_index=True) link = models.URLField() version = models.SmallIntegerField(blank=True, default=0) status = models.ForeignKey(Status, on_delete=models.PROTECT) label = models.CharField(max_length=128) definition = models.TextField(blank=True) description = models.TextField(blank=True) class Meta: verbose_name = _("Theme") verbose_name_plural = _("Themes") ordering = ["code", "label"] def __str__(self): return "%s: %s" % (self.code, self.label) def save(self, *args, **kwargs): self.link = self.link.replace("http://", "https://") if not self.code: self.code = self.link.split("/")[-1] self.slug = slugify(self.code)[:32] return super().save(*args, **kwargs)
[docs] class ApplicationSchema(BaseInspireEUModel): """INSPIRE Application schema register Definition The INSPIRE application schema register contains all application schemas of the consolidated INSPIRE UML data model. Owner European Union Register manager European Commission, Joint Research Centre Control body Control body for the central INSPIRE registers and INSPIRE register federation Submitter Nominated submitting organizations for the central INSPIRE registers and INSPIRE register federation Contact point JRC INSPIRE Registry Team <inspire-registry-dev@jrc.ec.europa.eu> Licence Europa Legal Notice References https://inspire.ec.europa.eu/applicationschema """ code = models.CharField(max_length=32, db_index=True) slug = models.CharField(max_length=32, blank=True, db_index=True) link = models.URLField() version = models.SmallIntegerField(blank=True, default=0) status = models.ForeignKey(Status, on_delete=models.PROTECT) label = models.CharField(max_length=128) definition = models.TextField(blank=True) description = models.TextField(blank=True) themes = models.ManyToManyField(Theme) class Meta: verbose_name = _("Application Schema") verbose_name_plural = _("Application Schemes") ordering = ["code", "label"] def __str__(self): return "%s: %s" % (self.code, self.label) def save(self, *args, **kwargs): self.link = self.link.replace("http://", "https://") if not self.code: self.code = self.link.split("/")[-1] self.slug = slugify(self.code)[:32] return super().save(*args, **kwargs)
[docs] class CodeList(BaseInspireEUModel): """INSPIRE Code List Register Definition The INSPIRE code list register contains the code lists and their values, as defined in the INSPIRE implementing rules on interoperability of spatial data sets and services (Commission Regulation (EU) No 1089/2010). NOTE: It does not yet include references to external code lists and the additional code lists and extended values proposed in the Data Specification Technical Guidelines. Owner European Union Register manager European Commission, Joint Research Centre Control body Control body for the central INSPIRE registers and INSPIRE register federation Submitter Nominated submitting organizations for the central INSPIRE registers and INSPIRE register federation Contact point JRC INSPIRE Registry Team <inspire-registry-dev@jrc.ec.europa.eu> Licence Europa Legal Notice https://ec.europa.eu/info/legal-notice_en References https://inspire.ec.europa.eu/codelist """ application_schema = models.ForeignKey(ApplicationSchema, on_delete=models.PROTECT) code = models.CharField(max_length=64, db_index=True) slug = models.CharField(max_length=64, blank=True, db_index=True) link = models.URLField(blank=True) status = models.ForeignKey(Status, on_delete=models.PROTECT) label = models.CharField(max_length=128) definition = models.TextField(blank=True) description = models.TextField(blank=True) parent = models.ForeignKey("self", blank=True, null=True, on_delete=models.PROTECT) themes = models.ManyToManyField(Theme) class Meta: verbose_name = _("Code list") verbose_name_plural = _("Code lists") ordering = ["code", "label"] def __str__(self): return "%s: %s" % (self.code, self.label) def save(self, *args, **kwargs): self.link = self.link.replace("http://", "https://") if not self.code: self.code = self.link.split("/")[-1] self.slug = slugify(self.code)[:64] return super().save(*args, **kwargs)
[docs] class CodeListValue(BaseInspireEUModel): code_list = models.ForeignKey(CodeList, on_delete=models.PROTECT) code = models.CharField(max_length=96, db_index=True) slug = models.CharField(max_length=96, blank=True, db_index=True) link = models.URLField() status = models.ForeignKey(Status, on_delete=models.PROTECT) label = models.CharField(max_length=200) definition = models.TextField(blank=True) description = models.TextField(blank=True) class Meta: verbose_name = _("Code list value") verbose_name_plural = _("Code list values") ordering = ["code_list__code", "code", "label"] def __str__(self): return "%s (%s): %s" % (self.code, self.code_list.code, self.label) def save(self, *args, **kwargs): if self.link: self.link = self.link.replace("http://", "https://") if not self.code: self.code = self.link.split("/")[-1] self.slug = slugify(self.code)[:96] return super().save(*args, **kwargs)
[docs] @classmethod def search(cls, slug, code_list_slug=None, create=True): """Search CodeListValue Args: slug (str): Slug of CodeList code_list_slug (str, optional): Slug of CodeList foreign key. Defaults to None. create (bool, optional): If it does not exist, create a new one. Defaults to True. Raises: CodeList.DoesNotExist: When his foreign key does not exist CodeListValue.DoesNotExist: Only when `create` param is false Returns: CodeListValue: Row founded, or created """ clv = None slug_list = slug.split("/") if not code_list_slug: code_list_slug = slug_list[-2] kw = dict( { "code_list__slug": slugify(code_list_slug), "slug": slugify(slug_list[-1]), }, ) try: clv = CodeListValue.objects.get(**kw) except CodeListValue.DoesNotExist: if create: kw_new = dict( { "code": slug_list[-1], "label": slug_list[-1], "definition": slug_list[-1], "description": _("Created ad-hoc"), }, ) try: kw_new["code_list"] = CodeList.objects.get( slug=kw["code_list__slug"], ) except CodeList.DoesNotExist: msg = _(f"There is no CodeList with code '{code_list_slug}'") raise CodeList.DoesNotExist(msg) kw_new["status"] = Status.objects.get(slug="valid") clv = CodeListValue.objects.create(**kw_new) msg = _(f"Created new CodeListValue: '{slug}' at '{code_list_slug}'") log.warning(msg) else: msg = _(f"There is no CodeListValue '{slug}' at '{code_list_slug}'") raise CodeListValue.DoesNotExist(msg) return clv
[docs] class UnitOfMeasure(BaseInspireEUModel): """Unit Of Measure Definition Any of the systems devised to measure some physical quantity such distance or area or a system devised to measure such things as the passage of time. The classes of UnitOfMeasure are determined by the member "measureType." Subclasses are not needed for implementation, but their use makes type constraints on measure valued attributes easier to specify. -- conversionToISOstandardUnit is not null only if the conversion is a simple scale References * `UnitOfMeasure Class <https://inspire.ec.europa.eu/data-model/approved/r4618-ir/html/index.htm?goto=1:3:7:1:1:1:1397>`_ * `MeasureType Class <https://inspire.ec.europa.eu/data-model/approved/r4618-ir/html/index.htm?goto=1:3:7:1:1:1:1392>`_ """ # noqa MEASURE_TYPE_UNKNOWN = "" MEASURE_TYPE_AREA = _("area") MEASURE_TYPE_LENGTH = _("length") MEASURE_TYPE_ANGLE = _("angle") MEASURE_TYPE_TIME = _("time") MEASURE_TYPE_VELOCITY = _("velocity") MEASURE_TYPE_VOLUME = _("volume") MEASURE_TYPE_SCALE = _("scale") MEASURE_TYPE_WEIGHT = _("weight") MEASURE_TYPE_CHOICES = ( (MEASURE_TYPE_UNKNOWN, _("Unknown")), (MEASURE_TYPE_AREA, _("Area")), (MEASURE_TYPE_LENGTH, _("Length")), (MEASURE_TYPE_ANGLE, _("Angle")), (MEASURE_TYPE_TIME, _("Time")), (MEASURE_TYPE_VELOCITY, _("Velocity")), (MEASURE_TYPE_VOLUME, _("Volume")), (MEASURE_TYPE_SCALE, _("Scale")), (MEASURE_TYPE_WEIGHT, _("Weight")), ) name = models.CharField( max_length=32, blank=True, help_text=_( "The name(s) of a particular unit of measure. Examples would include the following: " "1) for uomArea - square feet <br />" "2) for uomTime - seconds <br />" "3) for uomArea - miles<br />" "4) uomAngle - degrees.", ), ) slug = models.CharField(max_length=32, blank=True, db_index=True) symbol = models.CharField( max_length=8, help_text=_( """The symbol used for this unit of measure, such at "ft" for feet, or "m" for meter.""", ), ) measure_type = models.CharField( max_length=8, choices=MEASURE_TYPE_CHOICES, help_text=_("Measure Type"), ) name_standard_unit = models.CharField( max_length=8, blank=True, help_text=_( "Name of the standard units to which this unit of measure can be directly converted. " "If this variable is NULL, then the standard unit for this measure type given by the local " "copy of the StandardsUnits code list.", ), ) scale_to_standard_unit = models.FloatField( blank=True, null=True, help_text=_( "If the implementation system used for this object does not support NULL, the scale set to 0 " "is equivalent to NULL for both scale and offset.<br />" "If X is the current unit, and S is the standard one the of two variables scale(ToStandardUnit) " "and offset(ToStandardUnit) can be used to make the conversion from X to S by:<br />" "S = offset + scale*X <br />" "and, conversely, <br />" "X = (S-offset)/scale", ), ) offset_to_standard_unit = models.FloatField( blank=True, null=True, help_text=_( "See scaleToStandardUnit for a description. Again, this variable is NULL is no linear conversion " "is possible. If the two units are only a scale in difference, then this number is zero (0). " "If the implementation system used for this object does not support NULL, the then scale set " "to 0 is equivalent to NULL for both scale and offset.", ), ) formula = models.CharField( blank=True, max_length=32, help_text=_( "An algebraic formula (probably in some programming language) converting this unit of measure " "(represented in the formula by its uomSymbol) to the ISO standard (represented by its symbol. " "This member attribute is not required, but it is a valuable piece of documentation. ", ), ) # objects = models.Manager() # uom_length = models.Manager() # uom_area = models.Manager() # uom_length = models.Manager() # uom_angle = models.Manager() # uom_time = models.Manager() # uom_velocity = models.Manager() # uom_volume = models.Manager() # uom_scale = models.Manager() # uom_weight = models.Manager() class Meta: verbose_name = _("Unit Of Measure") verbose_name_plural = _("Units Of Measure") ordering = ["symbol", "name"] def __str__(self): return "%s %s" % (self.symbol, self.name) def save(self, *args, **kwargs): self.slug = slugify(self.name)[:32] return super().save(*args, **kwargs)