def DELETE(self, map_name, l_name, s_name, format): mf = get_mapfile(map_name) with webapp.mightNotFound("layer", mapfile=map_name): layer = mf.get_layer(l_name) with webapp.mightNotFound("style", layer=l_name): layer.remove_style(s_name) mf.save()
def DELETE(self, l_name, s_name, format): """Remove style <s> from layer <l>.""" mf = mra.get_available() with webapp.mightNotFound(): layer = mf.get_layer(l_name) with webapp.mightNotFound("style", layer=l_name): layer.remove_style(s_name) mf.save()
def GET(self, map_name, ws_name, ds_name, ft_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) ds = ws.get_datastore(ds_name) with webapp.mightNotFound("dataStore", datastore=ds_name): dsft = ds[ft_name] with webapp.mightNotFound("featureType", datastore=ds_name): ft = ws.get_featuretypemodel(ft_name, ds_name) extent = ft.get_extent() latlon_extent = ft.get_latlon_extent() return {"featureType": ({ "name": ft.name, "nativeName": ft.name, "namespace": None, # TODO "title": ft.get_mra_metadata("title", ft.name), "abstract": ft.get_mra_metadata("abstract", None), "keywords": ft.get_mra_metadata("keywords", []), "srs": "%s:%s" % (ft.get_authority()[0], ft.get_authority()[1]), "nativeCRS": ft.get_wkt(), "attributes": [{ "name": f.get_name(), "minOccurs": 0 if f.is_nullable() else 1, "maxOccurs": 1, "nillable": f.is_nullable(), "binding": f.get_type_name(), "length": f.get_width(), } for f in dsft.iterfields()], "nativeBoundingBox": { "minx": extent.minX(), "miny": extent.minY(), "maxx": extent.maxX(), "maxy": extent.maxY(), "crs": "%s:%s" % (ft.get_authority_name(), ft.get_authority_code()), }, "latLonBoundingBox": { "minx": latlon_extent.minX(), "miny": latlon_extent.minY(), "maxx": latlon_extent.maxX(), "maxy": latlon_extent.maxY(), "crs": "EPSG:4326", }, "projectionPolicy": None, # TODO "enabled": True, # TODO "store": { # TODO: add key: class="dataStore" "name": ds_name, "href": "%s/maps/%s/workspaces/%s/datastores/%s.%s" % ( web.ctx.home, map_name, ws_name, ds_name, format) }, "maxFeatures": 0, # TODO "numDecimals": 0, # TODO }) }
def PUT(self, l_name, format): """Modify layer <l>.""" mf = mra.get_available() data = get_data(name="layer", mandatory=[], authorized=["name", "title", "abstract", "resource", "enabled", "defaultStyle"]) if l_name != data.get("name", l_name): raise webapp.Forbidden("Can't change the name of a layer.") l_enabled = data.pop("enabled", True) mf = mra.get_available() with webapp.mightNotFound(): layer = mf.get_layer(l_name) # update resource if changed href = data.get("resource", {}).get("href") if href: try: ws_name, st_type, st_name, r_type, r_name = mra.href_parse(href, 5) except ValueError: raise webapp.NotFound(message="resource \"%s\" was not found." % href) st_type, r_type = st_type[:-1], r_type[:-1] # Remove trailing s. ws = get_workspace(ws_name) with webapp.mightNotFound(r_type, workspace=ws_name): try: model = ws.get_layermodel(r_type, st_name, r_name) except ValueError: raise KeyError(r_type) if layer.get_mra_metadata("type") != r_type: raise webapp.BadRequest("Can't change a \"%s\" layer into a \"%s\"." % (layer.get_mra_metadata("type"), r_type)) model.configure_layer(layer, l_enabled) # If we have a defaultStyle apply it. s_name = data.get("defaultStyle", {}).get("name") if s_name: with webapp.mightNotFound(): style = mra.get_style(s_name) layer.add_style_sld(mf, s_name, style) # Remove the automatic default style. for s_name in layer.iter_styles(): if s_name == tools.get_dflt_sld_name(layer.ms.type): layer.remove_style(s_name) mf.save()
def PUT(self, l_name, format): """Modify layer <l>.""" mf = mra.get_available() data = get_data(name="layer", mandatory=[], authorized=["name", "resource", "defaultStyle"]) if l_name != data.get("name", l_name): raise webapp.Forbidden("Can't change the name of a layer.") l_enabled = True # TODO: => data.pop("enabled", True) mf = mra.get_available() with webapp.mightNotFound(): layer = mf.get_layer(l_name) # update resource if changed href = data.get("resource", {}).get("href") if href: try: ws_name, st_type, st_name, r_type, r_name = mra.href_parse(href, 5) except ValueError: raise webapp.NotFound(message="resource \"%s\" was not found." % href) st_type, r_type = st_type[:-1], r_type[:-1] # Remove trailing s. ws = get_workspace(ws_name) with webapp.mightNotFound(r_type, workspace=ws_name): try: model = ws.get_layermodel(r_type, st_name, r_name) except ValueError: raise KeyError(r_type) if layer.get_mra_metadata("type") != r_type: raise webapp.BadRequest("Can't change a \"%s\" layer into a \"%s\"." % (layer.get_mra_metadata("type"), r_type)) model.configure_layer(layer, l_enabled) # If we have a defaultStyle apply it. s_name = data.get("defaultStyle", {}).get("name") if s_name: with webapp.mightNotFound(): style = mra.get_style(s_name) layer.add_style_sld(mf, s_name, style) # Remove the automatic default style. for s_name in layer.iter_styles(): if s_name == tools.get_dflt_sld_name(layer.ms.type): layer.remove_style(s_name) mf.save()
def DELETE(self, lg_name, format): """Delete layergroup <lg>.""" mf = mra.get_available() with webapp.mightNotFound(): mf.delete_layergroup(lg_name) mf.save()
def GET(self, map_name, ws_name, cs_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) with webapp.mightNotFound("coverageStore", workspace=ws_name): info = ws.get_coveragestore_info(cs_name) return {"coverageStore": { "name": info["name"], "type": None, # TODO "enabled": True, # TODO "__default": False, # TODO "workspace": { "name": ws.name, "href": "%s/maps/%s/workspaces/%s.%s" % ( web.ctx.home, map_name, ws.name, format), }, "coverages": href("%s/maps/%s/workspaces/%s/coveragestores/%s/coverages.%s" % ( web.ctx.home, map_name, ws.name, cs_name, format) ), "connectionParameters": Entries({ "url": info["connectionParameters"]["url"], "namespace": None, # TODO }, tag_name="entry") } }
def POST(self, map_name, l_name, format): data = get_data(name="style", mandatory=["resource"], authorized=["name", "title", "abstract", "resource"]) url = urlparse.urlparse(data["resource"]["href"]) if url.path.startswith(web.ctx.homepath): path = url.path[len(web.ctx.homepath):] else: raise webapp.BadRequest(message="Resource href (%s) is not handled by MRA." % url.path) try: _, map_name, _, s_name = path.rsplit("/", 3) except ValueError: raise webapp.NotFound(message="ressource '%s' was not found." % path) s_name = s_name.rsplit(".", 1)[0] # Get the new style. mf = get_mapfile(map_name) try: style = open(tools.get_style_path(s_name)).read() except IOError, OSError: with webapp.mightNotFound("style", mapfile=map_name): style = mf.get_style_sld(s_name)
def POST(self, map_name, format): data = get_data(name="layer", mandatory=["name", "resource"], authorized=["name", "title", "abstract", "resource", "enabled"]) l_name = data.pop("name") l_enabled = data.pop("enabled", True) # This means we can have one mapfile for each workspace # and if eveything uses urls it should work *almost* as is. url = urlparse.urlparse(data["resource"]["href"]) if url.path.startswith(web.ctx.homepath): path = url.path[len(web.ctx.homepath):] else: raise webapp.BadRequest(message="Resource href is not handled by MRA.") try: _, map_name, _, ws_name, st_type, st_name, r_type, r_name = path.rsplit("/", 7) except ValueError: raise webapp.NotFound(message="ressource '%s' was not found." % path) r_name = r_name.rsplit(".", 1)[0] mf, ws = get_mapfile_workspace(map_name, ws_name) with webapp.mightNotFound(r_type, workspace=ws_name): try: model = ws.get_model(r_name, r_type[:-1], st_name) except ValueError: webapp.NotFound("Invalid layer model '%s'" % r_type[:-1]) with webapp.mightConflict("layer", mapfile=map_name): mf.create_layer(ws, model, l_name, l_enabled) mf.save() webapp.Created("%s/maps/%s/layers/%s%s" % (web.ctx.home, map_name, l_name, (".%s" % format) if format else ""))
def GET(self, map_name, l_name, format): mf = get_mapfile(map_name) with webapp.mightNotFound("layer", mapfile=map_name): layer = mf.get_layer(l_name) data_type, store_type = { "featuretype": ("featuretype", "datastore"), "coverage": ("coverage", "coveragestore") }[layer.get_mra_metadata("type")] return {"layer" : { "name": l_name, "path": "/", # TODO "type": layer.get_type_name(), "defaultStyle": { "name": layer.ms.classgroup, "href": "%s/maps/%s/styles/%s.%s" % (web.ctx.home, map_name, layer.ms.classgroup, format), }, "styles": [{ # TODO: Add attr class="linked-hash-set" "name": s_name, "href": "%s/maps/%s/styles/%s.%s" % (web.ctx.home, map_name, s_name, format), } for s_name in layer.iter_styles()], "resource": { # TODO: Add attr class="featureType|coverage" "name": layer.get_mra_metadata("name"), "href": "%s/maps/%s/workspaces/%s/%ss/%s/%ss/%s.%s" % ( web.ctx.home, map_name, layer.get_mra_metadata("workspace"), store_type, layer.get_mra_metadata("storage"), data_type, layer.get_mra_metadata("name"), format), }, "enabled": bool(layer.ms.status), "attribution": { # TODO "logoWidth": 0, "logoHeight": 0, }, } }
def GET(self, ws_name, cs_name, format): """Return coverage store <cs>.""" ws = get_workspace(ws_name) with webapp.mightNotFound("coverageStore", workspace=ws_name): info = ws.get_coveragestore_info(cs_name) connectionParameters = info.get("connectionParameters", {}) return {"coverageStore": { "name": info["name"], "enabled": True, # Always enabled # TODO: Handle enabled/disabled states "workspace": { "name": ws.name, "href": "%s/workspaces/%s.%s" % ( web.ctx.home, ws.name, format), }, "coverages": href("%s/workspaces/%s/coveragestores/%s/coverages.%s" % ( web.ctx.home, ws.name, cs_name, format) ), "connectionParameters": connectionParameters and Entries({ "url": info["connectionParameters"]["url"], # "namespace": None, # TODO }, tag_name="entry"), # TODO: type } }
def GET(self, l_name, format): mf = mra.get_available() with webapp.mightNotFound(): layer = mf.get_layer(l_name) if layer.get_type_name() == "RASTER": return {"fields": []} fields = [{ "name": layer.get_metadata("gml_%s_alias" % field, None), "type": layer.get_metadata("gml_%s_type" % field, None), } for field in layer.iter_fields()] geom = layer.get_metadata("gml_geometries", False) if geom: type = layer.get_metadata("gml_%s_type" % geom, "undefined") occurs = layer.get_metadata("gml_%s_occurances" % geom, "0,1").split(",") min_occurs, max_occurs = int(occurs[0]), int(occurs[1]) else: geom, type, min_occurs, max_occurs = "undefined", "undefined", 0, 1 fields.append({ "name": geom, "type": type, "minOccurs": min_occurs, "maxOccurs": max_occurs, }) return {"fields": fields}
def GET(self, lg_name, format): """Return layergroup <lg>.""" mf = mra.get_available() with webapp.mightNotFound(): lg = mf.get_layergroup(lg_name) latlon_extent = lg.get_latlon_extent() bounds = {"minx": latlon_extent.minX(), "miny": latlon_extent.minY(), "maxx": latlon_extent.maxX(), "maxy": latlon_extent.maxY(), "crs": "EPSG:4326", } return {"layerGroup": ({ "name": lg.name, "mode": "NAMED", # Only available mode in MRA. "publishables": Entries([{ "name": layer.ms.name, "href": "%s/layers/%s.%s" % (web.ctx.home, layer.ms.name, format), } for layer in lg.iter_layers()], tag_name="published"), "bounds": Entries(bounds), # TODO: Styles # "styles": [], }) }
def PUT(self, s_name, format): """Modify style <s>.""" # TODO: Also update layers using this style. with webapp.mightNotFound(message="Style \"%s\" does not exist." % s_name): mra.delete_style(s_name) data = web.data() mra.create_style(s_name, data)
def POST(self, format): """Create a new layer.""" data = get_data(name="layer", mandatory=["name", "resource"], authorized=["name", "title", "abstract", "resource", "enabled", "defaultStyle"]) l_name = data.pop("name") l_enabled = data.pop("enabled", True) href = data["resource"]["href"] try: ws_name, st_type, st_name, r_type, r_name = mra.href_parse(href, 5) except ValueError: raise webapp.NotFound(message="resource \"%s\" was not found." % href) st_type, r_type = st_type[:-1], r_type[:-1] # Remove trailing s. ws = get_workspace(ws_name) with webapp.mightNotFound(r_type, workspace=ws_name): try: model = ws.get_layermodel(r_type, st_name, r_name) except ValueError: raise KeyError(r_type) mf = mra.get_available() with webapp.mightConflict(): mf.create_layer(model, l_name, l_enabled) # If we have a defaultStyle apply it. s_name = data.get("defaultStyle", {}).get("name") if s_name: with webapp.mightNotFound(): style = mra.get_style(s_name) layer = mf.get_layer(l_name) layer.add_style_sld(mf, s_name, style) # Remove the automatic default style. for s_name in layer.iter_styles(): if s_name == tools.get_dflt_sld_name(layer.ms.type): layer.remove_style(s_name) mf.save() webapp.Created("%s/layers/%s.%s" % (web.ctx.home, l_name, format))
def PUT(self, map_name, ws_name, st_type, st_name, f_type, format): import zipfile mf, ws = get_mapfile_workspace(map_name, ws_name) # TODO: According to geoserv's examples we might have to handle # directories as well as files, in that case we want to upload # all the files from the directory. # Lets first try to get the file. if f_type == "file": # Check if zip or not... data = web.data() elif f_type == "url": raise NotImplemented() elif f_type == "external": raise NotImplemented() # Now we make sure the store exists. with webapp.mightNotFound(message="Store {exception} does not exist " "and automatic creation is not yet suported."): ws.get_store_info(st_type, st_name) # TODO: Create the store if it does not exist. # Then we store the file. ext = web.ctx.env.get('CONTENT_TYPE', '').split("/")[-1] path = tools.mk_st_data_path(ws_name, st_type, st_name, st_name + (".%s" % ext) if ext else "") with open(path, "w") as f: f.write(data) # We also unzip it if its ziped. ctype = web.ctx.env.get('CONTENT_TYPE', None) if ctype == "application/zip": z = zipfile.ZipFile(path) for f in z.namelist(): fp = tools.mk_st_data_path(ws_name, st_type, st_name, f) # If the file has the correct target we might want it. if format and fp.endswith(format) and not tools.is_hidden(fp): path = fp z.extract(f, path=tools.get_st_data_path(ws_name, st_type, st_name)) # Set new connection parameters: ws.update_store(st_type, st_name, {"connectionParameters":{"url":"file:"+tools.no_res_root(path)}}) ws.save() # Finally we might have to configure it. params = web.input(configure="none") if params.configure == "first": raise NotImplemented() elif params.configure == "none": pass elif params.configure == "all": raise NotImplemented() else: raise webapp.BadRequest(message="configure must be one of first, none or all.")
def DELETE(self, map_name, ws_name, cs_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) # We need to check if this datatore is empty. assert_is_empty(ws.iter_coverages(cs_name=cs_name), "coveragestore", ds_name) with webapp.mightNotFound("coverageStore", workspace=ws_name): ws.delete_coveragestore(cs_name) ws.save()
def DELETE(self, map_name, ws_name, ds_name, ft_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) # We need to check if there are any layers using this. assert_is_empty(mf.iter_layers(mra={"name":ft_name, "workspace":ws_name, "storage":ds_name, "type":"featuretype"}),"featuretype", ft_name) with webapp.mightNotFound("featureType", datastore=ds_name): ws.delete_featuretypemodel(ft_name, ds_name) ws.save()
def DELETE(self, map_name, ws_name, ds_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) # We need to check if this datatore is empty. assert_is_empty(ws.iter_featuretypemodels(ds_name=ds_name), "datastore", ds_name) with webapp.mightNotFound("dataStore", workspace=ws_name): ws.delete_datastore(ds_name) ws.save()
def PUT(self, map_name, ws_name, cs_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) data = get_data(name="coverageStore", mandatory=["name"], authorized=["name", "title", "abstract", "connectionParameters"]) if cs_name != data.pop("name"): raise webapp.Forbidden("Can't change the name of a coverage store.") with webapp.mightNotFound("coverageStore", workspace=ws_name): ws.update_coveragestore(cs_name, data) ws.save()
def DELETE(self, map_name, ws_name, cs_name, c_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) # We need to check if there are any layers using this. assert_is_empty(mf.iter_layers(mra={"name":c_name, "workspace":ws_name, "storage":cs_name, "type":"coverage"}), "coverage", ft_name) with webapp.mightNotFound("coverage", coveragestore=cs_name): ws.delete_coveragemodel(c_name, cs_name) ws.save()
def GET(self, map_name, s_name, format): mf = get_mapfile(map_name) if format == "sld": # We look for styles on disk and in the mapfiles. try: return open(tools.get_style_path(s_name)).read() except IOError, OSError: with webapp.mightNotFound("style", mapfile=map_name): return mf.get_style_sld(s_name)
def GET(self, map_name, l_name, format): mf = get_mapfile(map_name) with webapp.mightNotFound("layer", mapfile=map_name): layer = mf.get_layer(l_name) return {"fields": [{ "name": layer.get_metadata("gml_%s_alias" % field, None), "fieldType": layer.get_metadata("gml_%s_type" % field, None), } for field in layer.iter_fields()] }
def POST(self, map_name, ws_name, ds_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) data = get_data(name="featureType", mandatory=["name"], authorized=["name", "title", "abstract"]) with webapp.mightConflict("featureType", datastore=ds_name): with webapp.mightNotFound("featureType", datastore=ds_name): ws.create_featuretypemodel(data["name"], ds_name, data) ws.save() webapp.Created("%s/maps/%s/workspaces/%s/datastores/%s/featuretypes/%s%s" % ( web.ctx.home, map_name, ws.name, ds_name, data["name"], (".%s" % format) if format else ""))
def DELETE(self, ws_name, cs_name, format): """Delete coverage store <cs>.""" ws = get_workspace(ws_name) # TODO: check, this is not consistent between ds/cs. # We need to check if this datastore is empty. assert_is_empty(ws.iter_coveragemodels(cs_name=cs_name), "coveragestore", cs_name) with webapp.mightNotFound("coverageStore", workspace=ws_name): ws.delete_coveragestore(cs_name) ws.save()
def DELETE(self, ws_name, ds_name, format): """Delete data store <ds>.""" ws = get_workspace(ws_name) # TODO: check, this is not consistent between ds/cs. # We need to check if this datastore is empty. assert_is_empty(ws.iter_featuretypemodels(ds_name=ds_name), "datastore", ds_name) with webapp.mightNotFound("dataStore", workspace=ws_name): ws.delete_datastore(ds_name) ws.save()
def PUT(self, map_name, ws_name, ds_name, ft_name, format): mf, ws = get_mapfile_workspace(map_name, ws_name) data = get_data(name="featureType", mandatory=["name"], authorized=["name", "title", "abstract"]) if ft_name != data["name"]: raise webapp.Forbidden("Can't change the name of a feature type.") metadata = dict((k, v) for k, v in data.iteritems() if k in ["title", "abstract"]) with webapp.mightNotFound("featureType", datastore=ds_name): ws.update_featuretypemodel(ft_name, ds_name, metadata) ws.save()
def DELETE(self, ws_name, cs_name, c_name, format): """Delete coverage <c>.""" ws = get_workspace(ws_name) # We need to check if there are any layers using this. mf = mra.get_available() assert_is_empty(mf.iter_layers(mra={"name":c_name, "workspace":ws_name, "storage":cs_name, "type":"coverage"}), "coverage", c_name) with webapp.mightNotFound("coverage", coveragestore=cs_name): ws.delete_coveragemodel(c_name, cs_name) ws.save()
def DELETE(self, ws_name, ds_name, ft_name, format): """Delete feature type <ft>.""" ws = get_workspace(ws_name) # We need to check if there are any layers using this. mf = mra.get_available() assert_is_empty(mf.iter_layers(mra={"name":ft_name, "workspace":ws_name, "storage":ds_name, "type":"featuretype"}),"featuretype", ft_name) with webapp.mightNotFound("featureType", datastore=ds_name): ws.delete_featuretypemodel(ds_name, ft_name) ws.save()
def PUT(self, ws_name, ds_name, format): """Modify data store <ds>.""" ws = get_workspace(ws_name) data = get_data(name="dataStore", mandatory=["name"], authorized=["name", "title", "abstract", "connectionParameters"]) if ds_name != data.pop("name"): raise webapp.Forbidden("Can't change the name of a data store.") with webapp.mightNotFound("dataStore", workspace=ws_name): ws.update_datastore(ds_name, data) ws.save()
def GET(self, map_name, l_name, format): mf = get_mapfile(map_name) with webapp.mightNotFound("layer", mapfile=map_name): layer = mf.get_layer(l_name) if format == "sld": return layer.getSLD() return {"styles": [{ "name": s_name, "href": "%s/maps/%s/styles/%s.%s" % (web.ctx.home, map_name, s_name, format), } for s_name in layer.iter_styles()], }
def PUT(self, ws_name, cs_name, format): """Modify coverage store <ds>.""" ws = get_workspace(ws_name) data = get_data(name="coverageStore", mandatory=["name"], authorized=["name", "title", "abstract", "connectionParameters"]) if cs_name != data.pop("name"): raise webapp.Forbidden("Can't change the name of a coverage store.") with webapp.mightNotFound("coverageStore", workspace=ws_name): ws.update_coveragestore(cs_name, data) ws.save()
def PUT(self, ws_name, ds_name, ft_name, format): """Modify feature type <ft>.""" ws = get_workspace(ws_name) data = get_data(name="featureType", mandatory=["name"], authorized=["name", "title", "abstract"]) if ft_name != data["name"]: raise webapp.Forbidden("Can't change the name of a feature type.") metadata = dict((k, v) for k, v in data.iteritems() if k in ["title", "abstract"]) with webapp.mightNotFound("featureType", datastore=ds_name): ws.update_featuretypemodel(ds_name, ft_name, metadata) ws.save()
def GET(self, l_name, format): """Return layer <l>.""" mf = mra.get_available() with webapp.mightNotFound(): layer = mf.get_layer(l_name) data_type, store_type = { "featuretype": ("featuretype", "datastore"), "coverage": ("coverage", "coveragestore") }[layer.get_mra_metadata("type")] response = {"layer": { "name": l_name, "title": layer.get_metadata("ows_title", None), "abstract": layer.get_metadata("ows_abstract", None), "type": layer.get_type_name(), "resource": { # TODO: Add attr class="featureType|coverage" "name": layer.get_mra_metadata("name"), "href": "%s/workspaces/%s/%ss/%s/%ss/%s.%s" % ( web.ctx.home, layer.get_mra_metadata("workspace"), store_type, layer.get_mra_metadata("storage"), data_type, layer.get_mra_metadata("name"), format), }, "enabled": bool(layer.ms.status), # TODO because it's fictitious... # "attribution" => TODO? # "path" => TODO? }} # Check CLASSGROUP dflt_style = layer.ms.classgroup if dflt_style == None: # If is 'None': take the first style as would MapServer. for s_name in layer.iter_styles(): dflt_style = s_name break if dflt_style == None: return response response["layer"].update({"defaultStyle": {"name": dflt_style, "href": "%s/styles/%s.%s" % (web.ctx.home, dflt_style, format)},}) styles = [{"name": s_name, "href": "%s/styles/%s.%s" % (web.ctx.home, s_name, format), } for s_name in layer.iter_styles() if s_name != dflt_style] if not styles: return response return response["layer"].update({"styles": styles})
def PUT(self, ws_name, cs_name, c_name, format): """Modify coverage <c>.""" ws = get_workspace(ws_name) data = get_data(name="coverage", mandatory=["name"], authorized=["name", "title", "abstract"]) if c_name != data["name"]: raise webapp.Forbidden("Can't change the name of a coverage.") metadata = dict((k, v) for k, v in data.iteritems() if k in ["title", "abstract"]) with webapp.mightNotFound("coverage", coveragestore=cs_name): ws.update_coveragemodel(c_name, cs_name, metadata) ws.save()
def GET(self, l_name, format): """Return all style from layer <l>.""" mf = mra.get_available() with webapp.mightNotFound(): layer = mf.get_layer(l_name) if format == "sld": return layer.getSLD() return {"styles": [{ "name": s_name, "href": "%s/styles/%s.%s" % (web.ctx.home, s_name, format), } for s_name in layer.iter_styles()], }
def GET(self, s_name, format): """Return style <s>.""" with webapp.mightNotFound(message="Style \"%s\" does not exist." % s_name): style = mra.get_style(s_name) if format == "sld": return style return {"style": { "name": s_name, "sldVersion": Entries(["1.0.0"], tag_name="version"), "filename": s_name + ".sld", } }
def POST(self, format): """Create a new layer group.""" mf = mra.get_available() data = get_data(name="layerGroup", mandatory=["name"], authorized=["name", "title", "abstract", "layers"]) lg_name = data.pop("name") with webapp.mightNotFound(): layers = [mf.get_layer(l_name) for l_name in data.pop("layers", [])] with webapp.mightConflict(): lg = mf.create_layergroup(lg_name, data) lg.add(*layers) mf.save() webapp.Created("%s/layergroups/%s.%s" % (web.ctx.home, lg.name, format))
def POST(self, ws_name, cs_name, format): """Create a new coverage.""" ws = get_workspace(ws_name) data = get_data(name="coverage", mandatory=["name"], authorized=["name", "title", "abstract"]) with webapp.mightConflict("coverage", coveragestore=cs_name): with webapp.mightNotFound("coverage", coveragestore=cs_name): ws.create_coveragemodel(data["name"], cs_name, data) ws.save() # Then creates the associated layer by default: model = ws.get_coveragemodel(cs_name, data["name"]) mf = mra.get_available() with webapp.mightConflict(): mf.create_layer(model, data["name"], True) mf.save() webapp.Created("%s/workspaces/%s/coveragestores/%s/coverages/%s.%s" % ( web.ctx.home, ws.name, cs_name, data["name"], format))
def PUT(self, lg_name, format): """Modify layergroup <lg>.""" mf = mra.get_available() with webapp.mightNotFound(): lg = mf.get_layergroup(lg_name) data = get_data(name="layerGroup", mandatory=["name"], authorized=["name", "title", "abstract", "layers"]) if lg_name != data.pop("name"): raise webapp.Forbidden("Can't change the name of a layergroup.") layers = data.pop("layers", []) if not isinstance(layers, list) or any(not isinstance(x, basestring) for x in layers): raise webapp.BadRequest("layers must be a list of layer names.") lg.clear() lg.add(*layers) mf.save()
def GET(self, ws_name, ds_name, format): """Return data store <ds>.""" ws = get_workspace(ws_name) with webapp.mightNotFound("dataStore", workspace=ws_name): info = ws.get_datastore_info(ds_name) connectionParameters = info.get("connectionParameters", {}) return {"dataStore": { "name": info["name"], "enabled": True, # Always enabled # TODO: Handle enabled/disabled states "workspace": { "name": ws.name, "href": "%s/workspaces/%s.%s" % ( web.ctx.home, ws.name, format), }, "featureTypes": href("%s/workspaces/%s/datastores/%s/featuretypes.%s" % ( web.ctx.home, ws.name, ds_name, format) ), "connectionParameters": Entries(connectionParameters, tag_name="entry"), } }
def POST(self, ws_name, ds_name, format): """Create a new feature type. It create the associated layer by defaut. This layer is added in the mapfile: <layer.map> """ ws = get_workspace(ws_name) data = get_data(name="featureType", mandatory=["name"], authorized=["name", "title", "abstract"]) # Creates first the feature type: with webapp.mightConflict("featureType", datastore=ds_name): with webapp.mightNotFound("featureType", datastore=ds_name): ws.create_featuretypemodel(ds_name, data["name"], data) ws.save() # Then creates the associated layer by default: model = ws.get_featuretypemodel(ds_name, data["name"]) mf = mra.get_available() with webapp.mightConflict(): mf.create_layer(model, data["name"], True) mf.save() webapp.Created("%s/workspaces/%s/datastores/%s/featuretypes/%s.%s" % ( web.ctx.home, ws.name, ds_name, data["name"], format))
def GET(self, ws_name, ds_name, ft_name, format): """Return feature type <ft>.""" ws = get_workspace(ws_name) ds = ws.get_datastore(ds_name) with webapp.mightNotFound("dataStore", datastore=ds_name): dsft = ds[ft_name] with webapp.mightNotFound("featureType", datastore=ds_name): ft = ws.get_featuretypemodel(ds_name, ft_name) extent = ft.get_extent() latlon_extent = ft.get_latlon_extent() # About attributs, we apply just values handled by # MapServer in a GetFeature response... attributes = [{ "name": f.get_name(), "type": f.get_type_name(), "length": f.get_width(), # "minOccurs": 0, "maxOccurs": 1, "nillable": f.is_nullable(), # binding? } for f in dsft.iterfields()] if dsft.get_geometry_column() is not None: attributes.append({ "name": dsft.get_geometry_column(), "type": dsft.get_geomtype_gml(), "minOccurs": 0, "maxOccurs": 1, # "nillable": True, # binding? }) else: attributes.append({ "name": "geometry", "type": dsft.get_geomtype_gml(), "minOccurs": 0, "maxOccurs": 1, # "nillable": True, # binding? }) return {"featureType": ({ # Why the name would it be different from nativeName? "name": ft.name, "nativeName": ft.name, "title": ft.get_mra_metadata("title", ft.name), "abstract": ft.get_mra_metadata("abstract", None), # TODO: keywords "nativeCRS": ft.get_wkt(), "attributes": attributes, "nativeBoundingBox": { "minx": extent.minX(), "miny": extent.minY(), "maxx": extent.maxX(), "maxy": extent.maxY(), "crs": "%s:%s" % (ft.get_authority_name(), ft.get_authority_code()), }, "latLonBoundingBox": { "minx": latlon_extent.minX(), "miny": latlon_extent.minY(), "maxx": latlon_extent.maxX(), "maxy": latlon_extent.maxY(), "crs": "EPSG:4326", }, # "srs": "%s:%s" % (ft.get_authority()[0], ft.get_authority()[1]), "projectionPolicy": "NONE", # About srs & projectionPolicy: (TODO: Handle the other cases) # In MRA, it is easier (or more logical?) to keep native CRS, # Or there is a problem of understanding on our part. # So, i prefer to comment 'srs' entry cause we force the # value of 'projectionPolicy' to 'NONE'... but it is something # we should investigate... "enabled": True, # Always enabled => TODO "store": { # TODO: add key: class="dataStore" "name": ds_name, "href": "%s/workspaces/%s/datastores/%s.%s" % ( web.ctx.home, ws_name, ds_name, format) }, # TODO: maxFeatures }) }
def get_workspace(ws_name): with webapp.mightNotFound(): return mra.get_workspace(ws_name)
def GET(self, ws_name, cs_name, c_name, format): """Return coverage <c>.""" ws = get_workspace(ws_name) # with webapp.mightNotFound("coveragestore", workspace=ws_name): # cs = ws.get_coveragestore(cs_name) with webapp.mightNotFound("coverage", coveragestore=cs_name): c = ws.get_coveragemodel(c_name, cs_name) extent = c.get_extent() latlon_extent = c.get_latlon_extent() return {"coverage": ({ "name": c.name, "nativeName": c.name, "title": c.get_mra_metadata("title", c.name), "abstract": c.get_mra_metadata("abstract", None), # TODO: Keywords "nativeCRS": c.get_wkt(), # TODO: Add key class="projected" if projected... "srs": "%s:%s" % (c.get_authority_name(), c.get_authority_code()), "nativeBoundingBox": { "minx": extent.minX(), "miny": extent.minY(), "maxx": extent.maxX(), "maxy": extent.maxY(), "crs": "%s:%s" % (c.get_authority_name(), c.get_authority_code()), # TODO: Add key class="projected" if projected... }, "latLonBoundingBox":{ "minx": latlon_extent.minX(), "miny": latlon_extent.minY(), "maxx": latlon_extent.maxX(), "maxy": latlon_extent.maxY(), "crs": "EPSG:4326" }, "enabled": True, # Always enabled => TODO "store": { # TODO: Add attr class="coverageStore" "name": cs_name, "href": "%s/workspaces/%s/coveragestores/%s.%s" % ( web.ctx.home, ws_name, cs_name, format) }, # TODO: # "nativeFormat": None, # "grid": { # "range": { # "low": None, # "high": None, # }, # "transform": { # "scaleX": None, # "scaleY": None, # "shearX": None, # "shearY": None, # "translateX": None, # "translateY": None, # }, # "crs": None, # }, # "supportedFormats": [], # "interpolationMethods": [], # "defaultInterpolationMethod": None, # "dimensions": [], # "projectionPolicy": None, # "requestSRS": None, # "responseSRS": None, # "parameters": None, }) }
def PUT(self, ws_name, st_type, st_name, f_type, format): """Uploads a file from a local source. The body of the request is the file itself.""" import zipfile # TODO: According to geoserv's examples we might have to handle # directories as well as files, in that case we want to upload # all the files from the directory. # Lets first try to get the file. if f_type == "file": # Check if zip or not... data = web.data() elif f_type == "url": raise webapp.NotImplemented() elif f_type == "external": raise webapp.NotImplemented() ws = get_workspace(ws_name) # Now we make sure the store exists. try: ws.get_store_info(st_type, st_name) except KeyError: # Create the store if it seems legit and it does not exist. if st_type == "datastores" or st_type == "coveragestores": st_type = st_type[:-1] # Remove trailing 's' with webapp.mightConflict("Workspace", workspace=ws_name): ws.create_store(st_type, st_name, {}) # Finaly check if its OK now. with webapp.mightNotFound(message="Store {exception} does not exist " "and it could not be created."): ws.get_store_info(st_type, st_name) # Then we store the file. ext = web.ctx.env.get('CONTENT_TYPE', '').split("/")[-1] path = mra.create_file(st_name + (".%s" % ext) if ext else "", data=data) dest = os.path.join(os.path.split(path)[0], st_name) # We also unzip it if its ziped. ctype = web.ctx.env.get('CONTENT_TYPE', None) if ctype == "application/zip": z = zipfile.ZipFile(path) for f in z.namelist(): fp = mra.mk_path(mra.get_file_path(st_name, f)) # If the file has the correct target we might want it. if format and fp.endswith(format) and not tools.is_hidden(fp): path = fp z.extract(f, path=dest) # Set new connection parameters: ws.update_store(st_type, st_name, {"connectionParameters":{"url":"file:"+mra.pub_file_path(path)}}) ws.save() # Finally we might have to configure it. params = web.input(configure="none") if params.configure == "first": raise webapp.NotImplemented() elif params.configure == "none": pass elif params.configure == "all": raise webapp.NotImplemented() else: raise webapp.BadRequest(message="configure must be one of 'first', 'none' or 'all'.")