def filter_queryset(self, queryset): """ Filters the queryset Args: queryset (Queryset): Unfiltered queryset Returns: queryset (Queryset): Filtered queryset """ # filter by dimensions time_min = self.request.query_params.get("time-min", None) or None time_max = self.request.query_params.get("time-max", None) or None elevation_unit = self.request.query_params.get("elevation-unit", None) or None elevation_min = self.request.query_params.get("elevation-min", None) or None elevation_max = self.request.query_params.get("elevation-max", None) or None queryset = view_helper.filter_queryset_metadata_dimension_time( queryset, time_min, time_max) queryset = view_helper.filter_queryset_metadata_dimension_elevation( queryset, elevation_min, elevation_max, elevation_unit) # filter by bbox extent. fully-inside and partially-inside are mutually exclusive bbox = self.request.query_params.get("bbox", None) or None bbox_srs = self.request.query_params.get("bbox-srs", DEFAULT_SRS_STRING) bbox_strict = utils.resolve_boolean_attribute_val( self.request.query_params.get("bbox-strict", False) or False) queryset = view_helper.filter_queryset_metadata_bbox( queryset, bbox, bbox_srs, bbox_strict) # filter by service type type = self.request.query_params.get("type", None) queryset = view_helper.filter_queryset_metadata_type(queryset, type) # filter by category category = self.request.query_params.get("cat", None) category_strict = utils.resolve_boolean_attribute_val( self.request.query_params.get("cat-strict", False) or False) queryset = view_helper.filter_queryset_metadata_category( queryset, category, category_strict) # filter by query query = self.request.query_params.get("q", None) q_test = self.request.query_params.get("q-test", False) queryset = view_helper.filter_queryset_metadata_query( queryset, query, q_test) # order by order_by = self.request.query_params.get("order", CATALOGUE_DEFAULT_ORDER) if order_by not in self.orderable_fields: order_by = CATALOGUE_DEFAULT_ORDER queryset = view_helper.order_queryset(queryset, order_by) return queryset
def active_state(self, request, pk=None): """ Activates a service via remote access Args: request: The incoming request pk: The service id Returns: Response """ user = user_helper.get_user(request) parameter_name = "active" new_status = request.POST.dict().get(parameter_name, None) new_status = utils.resolve_boolean_attribute_val(new_status) response = APIResponse() if new_status is None or not isinstance(new_status, bool): response.data["msg"] = PARAMETER_ERROR.format(parameter_name) return Response(data=response.data, status=500) try: md = Metadata.objects.get(service__id=pk) response.data["oldStatus"] = md.is_active md.is_active = new_status md.save() response.data["newStatus"] = md.is_active response.data["success"] = True return Response(data=response.data, status=200) except ObjectDoesNotExist: response.data["msg"] = SERVICE_NOT_FOUND return Response(data=response.data, status=404)
def parse_cascaded(self, layer, layer_obj): try: is_opaque = layer.get("cascaded") if is_opaque is None: is_opaque = False else: is_opaque = utils.resolve_boolean_attribute_val(is_opaque) layer_obj.is_cascaded = is_opaque except AttributeError: pass
def parse_queryable(self, layer, layer_obj): try: is_queryable = layer.get("queryable") if is_queryable is None: is_queryable = False else: is_queryable = utils.resolve_boolean_attribute_val(is_queryable) layer_obj.is_queryable = is_queryable except AttributeError: pass
def get_queryset(self): """ Specifies if the queryset shall be filtered or not Returns: The queryset """ self.queryset = Organization.objects.all() # filter by real or auto generated organizations auto_generated = self.request.query_params.get("ag", None) auto_generated = utils.resolve_boolean_attribute_val(auto_generated) self.queryset = view_helper.filter_queryset_real_organization( self.queryset, auto_generated) # order by order_by = self.request.query_params.get("order", ORGANIZATION_DEFAULT_ORDER) if order_by not in self.orderable_fields: order_by = ORGANIZATION_DEFAULT_ORDER self.queryset = view_helper.order_queryset(self.queryset, order_by) return self.queryset
def parse_xml(self): """ Reads the needed data from the xml and writes to an ISOMetadata instance (self) Returns: nothing """ xml = self.raw_metadata xml_obj = xml_helper.parse_xml(xml) self.file_identifier = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:fileIdentifier/gco:CharacterString") self.character_set_code = xml_helper.try_get_attribute_from_xml_element( xml_elem=xml_obj, attribute="codeListValue", elem="//gmd:MD_Metadata/gmd:characterSet/gmd:MD_CharacterSetCode") if self.file_identifier is None: self.file_identifier = uuid.uuid4() self.date_stamp = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:dateStamp/gco:Date") self.last_change_date = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:dateStamp/gco:Date") self.md_standard_name = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:metadataStandardName/gco:CharacterString") self.md_standard_version = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:metadataStandardVersion/gco:CharacterString") self._parse_xml_legal_dates(xml_obj) self._parse_xml_legal_reports(xml_obj) # try to transform the last_change_date into a datetime object try: self.last_change_date = parse(self.last_change_date, tzinfo=timezone.utc) except (ValueError, OverflowError, TypeError): # if this is not possible due to wrong input, just use the current time... self.last_change_date = timezone.now() self.hierarchy_level = xml_helper.try_get_attribute_from_xml_element( xml_obj, "codeListValue", "//gmd:MD_Metadata/gmd:hierarchyLevel/gmd:MD_ScopeCode") if self.hierarchy_level == "service": xpath_type = "srv:SV_ServiceIdentification" else: xpath_type = "gmd:MD_DataIdentification" self.title = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:citation/gmd:CI_Citation/gmd:title/gco:CharacterString" .format(xpath_type)) self._parse_xml_dataset_id(xml_obj, xpath_type) self.abstract = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:abstract/gco:CharacterString" .format(xpath_type)) keywords = xml_helper.try_get_element_from_xml( xml_elem=xml_obj, elem= "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:descriptiveKeywords/gmd:MD_Keywords/gmd:keyword/gco:CharacterString" .format(xpath_type)) for keyword in keywords: if keyword.text is not None and keyword not in self.keywords: self.keywords.append( xml_helper.try_get_text_from_xml_element(keyword)) language = xml_helper.try_get_single_element_from_xml( xml_elem=xml_obj, elem= "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:language/gmd:LanguageCode" .format(xpath_type)) if language and language.text is not None: self.language = xml_helper.try_get_text_from_xml_element(language) iso_categories = xml_helper.try_get_element_from_xml( xml_elem=xml_obj, elem= "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:topicCategory/gmd:MD_TopicCategoryCode" .format(xpath_type)) if iso_categories: for iso_category in iso_categories: self.iso_categories.append( xml_helper.try_get_text_from_xml_element(iso_category)) # Get all values from <gmd:distributionInfo> which declares the distributionFormat formats = xml_helper.try_get_element_from_xml( xml_elem=xml_obj, elem="//" + GENERIC_NAMESPACE_TEMPLATE.format("distributionFormat")) if formats: for format_elem in formats: # get the character value per format name_elem = xml_helper.try_get_single_element_from_xml( xml_elem=format_elem, elem=".//" + GENERIC_NAMESPACE_TEMPLATE.format("name")) if name_elem is None: continue val = xml_helper.try_get_text_from_xml_element( xml_elem=name_elem, elem=".//" + GENERIC_NAMESPACE_TEMPLATE.format("CharacterString")) self.formats.append(val) self.download_link = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource[gmd:function/gmd:CI_OnLineFunctionCode/@codeListValue="download"]/gmd:linkage/gmd:URL' ) self.transfer_size = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:transferSize/gco:Real' ) self.preview_image = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:graphicOverview/gmd:MD_BrowseGraphic/gmd:fileName/gco:CharacterString" .format(xpath_type)) try: self.bounding_box["min_x"] = float( xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:westBoundLongitude/gco:Decimal".format(xpath_type))) self.bounding_box["min_y"] = float( xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:southBoundLatitude/gco:Decimal".format(xpath_type))) self.bounding_box["max_x"] = float( xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:eastBoundLongitude/gco:Decimal".format(xpath_type))) self.bounding_box["max_y"] = float( xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:northBoundLatitude/gco:Decimal".format(xpath_type))) except TypeError: self.bounding_box = None self._parse_xml_polygons(xml_obj, xpath_type) self.tmp_extent_begin = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:beginPosition" .format(xpath_type)) if self.tmp_extent_begin is None: self.tmp_extent_begin = "1900-01-01" self.tmp_extent_end = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:endPosition" .format(xpath_type)) if self.tmp_extent_end is None: self.tmp_extent_end = "1900-01-01" equivalent_scale = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:spatialResolution/gmd:MD_Resolution/gmd:equivalentScale/gmd:MD_RepresentativeFraction/gmd:denominator/gco:Integer" .format(xpath_type)) ground_res = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:spatialResolution/gmd:MD_Resolution/gmd:distance/gco:Distance" .format(xpath_type)) if equivalent_scale is not None and int(equivalent_scale) > 0: self.spatial_res_val = equivalent_scale self.spatial_res_type = "scaleDenominator" elif ground_res is not None and len(ground_res) > 0: self.spatial_res_val = ground_res self.spatial_res_type = "groundDistance" self.ref_system = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:code/gco:CharacterString" ) self.ref_system_version = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:version/gco:CharacterString" ) self.ref_system_authority = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:authority/gmd:CI_Citation/gmd:title/gco:CharacterString" ) epsg_api = EpsgApi() if self.ref_system is not None: self.ref_system = "EPSG:{}".format( epsg_api.get_subelements(self.ref_system).get("code")) # gmd:CI_OnLineFunctionCode dist_func_elem = xml_helper.try_get_single_element_from_xml( "//" + GENERIC_NAMESPACE_TEMPLATE.format("CI_OnLineFunctionCode"), xml_obj) self.distribution_function = xml_helper.try_get_attribute_from_xml_element( dist_func_elem, "codeListValue", ) del dist_func_elem # gmd:MD_RepresentativeFraction fraction_elem = xml_helper.try_get_single_element_from_xml( "//" + GENERIC_NAMESPACE_TEMPLATE.format("MD_RepresentativeFraction"), xml_obj) self.fraction_denominator = xml_helper.try_get_text_from_xml_element( fraction_elem, ".//" + GENERIC_NAMESPACE_TEMPLATE.format("Integer")) del fraction_elem # gmd:useLimitation limit_elem = xml_helper.try_get_single_element_from_xml( "//" + GENERIC_NAMESPACE_TEMPLATE.format("useLimitation"), xml_obj) self.use_limitation = xml_helper.try_get_text_from_xml_element( limit_elem, ".//" + GENERIC_NAMESPACE_TEMPLATE.format("CharacterString")) del limit_elem self.lineage = xml_helper.try_get_text_from_xml_element( xml_obj, "//gmd:MD_Metadata/gmd:dataQualityInfo/gmd:DQ_DataQuality/gmd:lineage/gmd:LI_Lineage/gmd:statement/gco:CharacterString" ) restriction_code_attr_val = xml_helper.try_get_element_from_xml( xml_elem=xml_obj, elem= '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:useConstraints/gmd:MD_RestrictionCode/@codeListValue' .format(xpath_type)) if len(restriction_code_attr_val) >= 2: legal_constraints = "" if restriction_code_attr_val[ 0] == 'license' and restriction_code_attr_val[ 1] == 'otherRestrictions': other_constraints = xml_helper.try_get_element_from_xml( xml_elem=xml_obj, elem= '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:resourceConstraints/gmd:MD_LegalConstraints[gmd:useConstraints/gmd:MD_RestrictionCode/@codeListValue="otherRestrictions"]/gmd:otherConstraints/gco:CharacterString' .format(xpath_type)) for constraint in other_constraints: try: tmp_constraint = xml_helper.try_get_text_from_xml_element( xml_elem=constraint) constraint_json = json.loads(tmp_constraint) self.license_source_note = constraint_json.get( "quelle", None) self.license_json = constraint_json except ValueError: # no, this is not a json! # handle it is a normal text legal_constraints += tmp_constraint + ";" self.fees = legal_constraints self.access_constraints = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:resourceConstraints/gmd:MD_LegalConstraints[gmd:accessConstraints/gmd:MD_RestrictionCode/@codeListValue="otherRestrictions"]/gmd:otherConstraints/gco:CharacterString' .format(xpath_type)) self.responsible_party = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:pointOfContact/gmd:CI_ResponsibleParty/gmd:organisationName/gco:CharacterString' .format(xpath_type)) self.contact_person = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:pointOfContact/gmd:CI_ResponsibleParty/gmd:individualName/gco:CharacterString' .format(xpath_type)) self.contact_phone = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:pointOfContact/gmd:CI_ResponsibleParty/gmd:contactInfo/gmd:CI_Contact/gmd:phone/gmd:CI_Telephone/gmd:voice/gco:CharacterString' .format(xpath_type)) self.contact_email = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:pointOfContact/gmd:CI_ResponsibleParty/gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:electronicMailAddress/gco:CharacterString' .format(xpath_type)) update_frequency = xml_helper.try_get_attribute_from_xml_element( xml_elem=xml_obj, attribute="codeListValue", elem= '//gmd:MD_Metadata/gmd:identificationInfo/{}/gmd:resourceMaintenance/gmd:MD_MaintenanceInformation/gmd:maintenanceAndUpdateFrequency/gmd:MD_MaintenanceFrequencyCode' .format(xpath_type)) if update_frequency in self.valid_update_frequencies: self.update_frequency = update_frequency # inspire regulations regislations = {"inspire_rules": []} with open(INSPIRE_LEGISLATION_FILE, "r", encoding="utf-8") as _file: regislations = json.load(_file) for regislation in regislations["inspire_rules"]: reg = { "name": regislation.get("name", None), "date": regislation.get("date", "1900-01-01"), "pass": None, } statement = xml_helper.try_get_text_from_xml_element( xml_obj, '//gmd:MD_Metadata/gmd:dataQualityInfo/gmd:DQ_DataQuality/gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult[gmd:specification/gmd:CI_Citation/gmd:title/gco:CharacterString="{}" and gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:date/gco:Date="{}"]/gmd:pass/gco:Boolean' .format(reg["name"], reg["date"])) statement_val = utils.resolve_boolean_attribute_val(statement) if statement_val is None: reg["pass"] = "******" self.inspire_interoperability = False else: reg["pass"] = statement_val # if only one regislation is not fullfilled, we do not have interoperability if not statement_val: self.inspire_interoperability = False self.interoperability_list.append(reg)
def get_resource_capabilities(request: HttpRequest, md: Metadata): """ Logic for retrieving a capabilities document. If no capabilities document can be provided by the given parameter, a fallback document will be returned. Args: request: md: Returns: """ from service.tasks import async_increase_hits stored_version = md.get_service_version().value # move increasing hits to background process to speed up response time! # todo: after refactoring of md.increase_hits() maybe we don't need to start async tasks... test it!!! async_increase_hits.delay(md.id) if not md.is_active: return HttpResponse(content=SERVICE_DISABLED, status=423) # check that we have the requested version in our database version_param = None version_tag = None request_param = None request_tag = None use_fallback = None for k, v in request.GET.dict().items(): if k.upper() == "VERSION": version_param = v version_tag = k elif k.upper() == "REQUEST": request_param = v request_tag = k elif k.upper() == "FALLBACK": use_fallback = resolve_boolean_attribute_val(v) # No version parameter has been provided by the request - we simply use the one we have. if version_param is None or len(version_param) == 0: version_param = stored_version if version_param not in [data.value for data in OGCServiceVersionEnum]: # version number not valid return HttpResponse(content=PARAMETER_ERROR.format(version_tag), status=404) elif request_param is not None and request_param != OGCOperationEnum.GET_CAPABILITIES.value: # request not valid return HttpResponse(content=PARAMETER_ERROR.format(request_tag), status=404) else: pass if md.is_catalogue_metadata: doc = md.get_remote_original_capabilities_document(version_param) elif stored_version == version_param or use_fallback is True or not md.is_root(): # This is the case if # 1) a version is requested, which we have in our database # 2) the fallback parameter is set explicitly # 3) a subelement is requested, which normally do not have capability documents # We can check the cache for this document or we need to generate it! doc = md.get_current_capability_xml(version_param) else: # we have to fetch the remote document # fetch the requested capabilities document from remote - we do not provide this as our default (registered) one xml = md.get_remote_original_capabilities_document(version_param) tmp = xml_helper.parse_xml(xml) if tmp is None: raise ValueError("No xml document was retrieved. Content was :'{}'".format(xml)) # we fake the persisted service version, so the document setters will change the correct elements in the xml # md.service.service_type.version = version_param doc = Document( content=xml, metadata=md, document_type=DocumentEnum.CAPABILITY.value, is_original=True ) doc.set_capabilities_secured(auto_save=False) if md.use_proxy_uri: doc.set_proxy(True, auto_save=False, force_version=version_param) doc = doc.content return doc