""" Module allowing the flexible communication with geoserver """ import json import re import requests from geoserver.catalog import Catalog from geoserver.catalog import FailedRequestError from django.conf import settings # Fix gdal 2.40 and 3.3 integration problems try: import ogr except ModuleNotFoundError: from osgeo import ogr from GMS.tools.gdal_python import get_EPSG from tools.envConf.def_conf import GS_USER, GS_URL, GS_URL_PUBLIC, GS_PASSW class Geoserver: """ Class to communicate with Geoserver Attributes ---------- WMS_KEY: str Constant WMS service id string. TMS_KEY: str Constant TMS service id string. GJSON_KEY: str Constant GJSON service id string. MAPBOX_KEY: str Constant MAPBOX service id string. CSV_KEY: str Constant CSV_KEY service id string. _available_services: list List of available drivers Raises ------ NotSupportedFormatError: The service is not in the list """ WMS_KEY = "WMS" TMS_KEY = "TMS" GJSON_KEY = "GeoJSON" MAPBOX_KEY = "mapBox" CSV_KEY = "CSV" _available_services = [WMS_KEY, TMS_KEY, GJSON_KEY, MAPBOX_KEY, CSV_KEY] not_supported_format = type('NotSupportedFormatError', (Exception, ), {}) def __init__(self): env_conf = settings.ENV_CONF self.url = env_conf[GS_URL] self.url_pbl = env_conf[GS_URL_PUBLIC] self.user = env_conf[GS_USER] self.passw = env_conf[GS_PASSW] # url_signed = re.sub(r'(https?://)(.*)$', r'\g<1>{user}:{password}@\g<2>' # .format(user=self.user, # password=self.passw), # self.url) url_signed = re.sub(r'(https?://)(.*)$', r'\g<1>\g<2>', self.url) self.url_base = r"{url_signed}/geoserver/rest/".\ format(url_signed=url_signed) self.cat = Catalog(self.url_base, username=self.user, password=self.passw) # self.cat = Catalog(self.url_base) def get_service(self, service, workspace, layer_name): """ Get service url by service key, worskpace and layer name. Parameters ---------- service: str Service key id. workspace: str Workspace id layer_name: str Layer name ID. Returns ------- str: Url of the service. """ if service not in self._available_services: raise self.not_supported_format("{} not supported".format(service)) return self.__getattribute__("_service_{}".format(service.lower()))\ (workspace, layer_name) def _service_wms(self, workspace, layer_name): return "{url}/geoserver/{workspace}/wms?layer={layer_name}". \ format(url=self.url_pbl, workspace=workspace, layer_name=layer_name) def _service_tms(self, workspace, layer_name): return "{url}/geoserver/gwc/service/tms/1.0.0/{workspace}:" \ "{layer_name}EPSG:900913@png/{{z}}/{{x}}/{{-y}}.png". \ format(url=self.url_pbl, workspace=workspace, layer_name=layer_name) def _service_geojson(self, workspace, layer_name): return "{url}/geoserver/{workspace}/wfs?request=GetFeature&" \ "service=WFS&version=1.0.0&typeName={workspace}:{layer_name}" \ "&outputFormat=application/json".\ format(url=self.url_pbl, workspace=workspace, layer_name=layer_name) def _service_mapbox(self, workspace, layer_name): return "{url}/geoserver/gwc/service/tms/1.0.0/{workspace}:" \ "{layer_name}@EPSG%3A900913@pbf/{{z}}/{{x}}/{{-y}}.pbf". \ format(url=self.url_pbl, workspace=workspace, layer_name=layer_name) def _service_csv(self, workspace, layer_name): return "{url}/geoserver/{workspace}/ows?service=WFS&version=1.0.0" \ "&request=GetFeature&typeName={workspace}:{layer_name}" \ "&outputFormat=csv".format(url=self.url_pbl, workspace=workspace, layer_name=layer_name) def publish_vec_pg(self, user, ip_pg, port_pg, user_pg, passw_pg, database_pg, schema_pg, table_pg): """ Función que conecta PG con geoserver Parameters ---------- user : str Usuario de maps ip_pg : str Ip PG port_pg : str puerto PG user_pg : str Usuario PG passw_pg : str Contraseña PG database_pg : str Base de datos PG schema_pg : str Esquema PG table_pg : str Tabla/vista/vista_materializada PG Returns ------- str: devuelve un string que indica si existe o se ha creado la capa """ cat = self.cat if cat.get_workspace(user) is None: cat.create_workspace(user) cat.reload() work_space = cat.get_workspace(user) st = cat.get_stores(work_space) exist_flag = 1 for store in st: if ((store.name in database_pg+'_'+user) and (schema_pg == user)) or \ ((store.name in database_pg+'_ext_'+user) and (schema_pg != user)): exist_flag = 0 break if exist_flag == 0: ds = cat.get_store(store.name, work_space) ds.connection_parameters.update(host=ip_pg, port=port_pg, database=database_pg, user=user_pg, passwd=passw_pg, dbtype='postgis', schema=schema_pg) else: ds = cat.create_datastore(database_pg+'_ext_'+user, work_space) \ if schema_pg != user \ else cat.create_datastore(database_pg + '_' + user, work_space) ds.connection_parameters.update(host=ip_pg, port=port_pg, database=database_pg, user=user_pg, passwd=passw_pg, dbtype='postgis', schema=schema_pg) response = requests.get("{base_url}/workspaces/{workspaceName}/" "datastores/{storeName}" .format(base_url=self.url_base, workspaceName=work_space, storeName=ds.name)) if response.status_code == 200: json_res = json.loads(response.content.decode()) for i in json_res["dataStore"]["connectionParameters"]["entry"]: if i["@key"] == 'max connections': i["$"] = 1 headers = {"Accept": "*/*", 'Content-Type': 'application/json'} requests.put(url="""{base_url}/workspaces/{workspaceName}/ datastores/{storeName}""".format(base_url=self.url_base, workspaceName=work_space, storeName=ds.name), headers=headers, data=json.dumps(json_res)) cat.save(ds) conn_string = 'PG: host=%s dbname=%s user=%s password=%s port=%s ' \ 'schemas=%s tables=%s' % \ (ip_pg, database_pg, user_pg, passw_pg, port_pg, schema_pg, table_pg) conn = ogr.Open(conn_string) layer = conn.GetLayerByName(schema_pg+'.'+table_pg) try: spatial_ref = layer.GetSpatialRef() epsg = spatial_ref.GetAttrValue("AUTHORITY", 0)+":" + \ spatial_ref.GetAttrValue("AUTHORITY", 1) except TypeError: spatial_ref = str(layer.GetSpatialRef().ExportToWkt()) epsg = get_EPSG(spatial_ref) epsg = 'EPSG:'+epsg except AttributeError: epsg = 'EPSG:4326' if cat.get_resource(table_pg, ds, work_space) is None: # Si da error, debajo de resource_url = # store.resource_url (701) --> params = dict() ft = cat.publish_featuretype(name=table_pg, store=ds, native_crs=epsg, srs='EPSG:4326') ft.projection_policy = "REPROJECT_TO_DECLARED" cat.save(ft) result = "Capa creada" else: cat.reload() result = "Ya existe la capa" return result # , self.ip_fuera, self.port, user, table_pg def delete_layer_server(self, layer_gs): """ Función que elimina una capa o layer server en iMaps Función que conecta PG con geoserver Parameters ---------- layer_gs : str capa alojada en geoserver Returns ------- bool: If success return True """ cat = self.cat try: layer = cat.get_layer(layer_gs) cat.delete(config_object=layer) cat.reload() return True except FailedRequestError: return False