def __init__(self, catalog): self.catalog = catalog #we also create a Client object pointing to the same url self.client = Client(str(catalog.service_url), catalog.username, catalog.password)
class OGCatalog(object): ''' This class is a wrapper for a catalog object, with convenience methods to use it with QGIS layers ''' def __init__(self, catalog): self.catalog = catalog #we also create a Client object pointing to the same url self.client = Client(str(catalog.service_url), catalog.username, catalog.password) def clean(self): self.cleanUnusedStyles() self.cleanUnusedResources() def cleanUnusedStyles(self): '''cleans styles that are not used by any layer''' usedStyles = set() styles = self.catalog.get_styles() layers = self.catalog.get_layers() for layer in layers: usedStyles.add(layer.default_style.name) usedStyles.update([s.name for s in layer.styles if s is not None]) toDelete = [s for s in styles if s.name not in usedStyles] for style in toDelete: style.catalog.delete(style, purge = True) def cleanUnusedResources(self): '''cleans resources that are not published through any layer in the catalog''' usedResources = set() resources = self.catalog.get_resources() layers = self.catalog.get_layers() for layer in layers: usedResources.add(layer.resource.name) toDelete = [r for r in resources if r.name not in usedResources] for resource in toDelete: resource.catalog.delete(resource) for store in self.catalog.get_stores(): if len(store.get_resources()) == 0: self.catalog.delete(store) def consolidateStyles(self): ''' Deletes styles that are redundant and just keeps one copy of them in the catalog, configuring the corresponding layers to use that copy ''' used = {} allstyles = self.catalog.get_styles() for style in allstyles: sld = style.sld_body.replace("<sld:Name>%s</sld:Name>" % style.name, "") if sld in used.keys(): used[sld].append(style) else: used[sld] = [style] for sld, styles in used.iteritems(): if len(styles) == 1: continue #find the layers that use any of the secondary styles in the list, and make them use the first one styleNames = [s.name for s in styles[1:]] layers = self.catalog.get_layers() for layer in layers: changed = False if layer.default_style.name in styleNames: layer.default_style = styles[0] changed = True alternateStyles = layer.styles newAlternateStyles = set() for alternateStyle in alternateStyles: if alternateStyle.name in styleNames: newAlternateStyles.add(styles[0]) else: newAlternateStyles.add(alternateStyle) newAlternateStyles = list(newAlternateStyles) if newAlternateStyles != alternateStyles: layer.styles = newAlternateStyles changed = True if changed: self.catalog.save(layer) def publishStyle(self, layer, overwrite = True, name = None): ''' Publishes the style of a given layer style in the specified catalog. If the overwrite parameter is True, it will overwrite a style with that name in case it exists ''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) sld = getGsCompatibleSld(layer) if sld is not None: name = name if name is not None else layer.name() name = name.replace(" ", "_") self.catalog.create_style(name, sld, overwrite) return sld def getDataFromLayer(self, layer): ''' Returns the data corresponding to a given layer, ready to be passed to the method in the Catalog class for uploading to the server. If needed, it performs an export to ensure that the file format is supported by the upload API to be used for import. In that case, the data returned will point to the exported copy of the data, not the original data source ''' if layer.type() == layer.RasterLayer: data = exporter.exportRasterLayer(layer) else: filename = exporter.exportVectorLayer(layer) basename, extension = os.path.splitext(filename) data = { 'shp': basename + '.shp', 'shx': basename + '.shx', 'dbf': basename + '.dbf', 'prj': basename + '.prj' } return data def upload(self, layer, workspace=None, overwrite=True, name=None): '''uploads the specified layer''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) name = name if name is not None else layer.name() title = name name = name.replace(" ", "_") try: settings = QSettings() restApi = bool(settings.value("/OpenGeo/Settings/GeoServer/UseRestApi", True, bool)) restApi = True # importer api is disabled for now if layer.type() == layer.RasterLayer: path = self.getDataFromLayer(layer) if restApi: self.catalog.create_coveragestore(name, path, workspace=workspace, overwrite=overwrite) else: session = self.client.upload(path) session.commit() elif layer.type() == layer.VectorLayer: provider = layer.dataProvider() if provider.name() == 'postgres': connName = self.getConnectionNameFromLayer(layer) uri = QgsDataSourceURI(provider.dataSourceUri()) self.catalog.create_pg_featurestore(connName, workspace = workspace, overwrite = overwrite, host = uri.host(), database = uri.database(), schema = uri.schema(), port = uri.port(), user = uri.username(), passwd = uri.password()) self.catalog.create_pg_featuretype(uri.table(), connName, workspace, layer.crs().authid()) else: path = self.getDataFromLayer(layer) if restApi: try: self.catalog.create_shp_featurestore(name, path, workspace=workspace, overwrite=overwrite) except WindowsError: #this might be thrown by the create_shp_featurestore method #when trying to unlink the temp zip file pass except Exception, e: raise e else: shpFile = path['shp'] session = self.client.upload(shpFile) session.commit() else:
class OGCatalog(object): ''' This class is a wrapper for a catalog object, with convenience methods to use it with QGIS layers ''' def __init__(self, catalog): self.catalog = catalog #we also create a Client object pointing to the same url self.client = Client(str(catalog.service_url), catalog.username, catalog.password) def clean(self): self.cleanUnusedStyles() self.cleanUnusedResources() def cleanUnusedStyles(self): '''cleans styles that are not used by any layer''' usedStyles = set() styles = self.catalog.get_styles() layers = self.catalog.get_layers() for layer in layers: usedStyles.add(layer.default_style.name) usedStyles.update([s.name for s in layer.styles if s is not None]) toDelete = [s for s in styles if s.name not in usedStyles] for style in toDelete: style.catalog.delete(style, purge=True) def cleanUnusedResources(self): '''cleans resources that are not published through any layer in the catalog''' usedResources = set() resources = self.catalog.get_resources() layers = self.catalog.get_layers() for layer in layers: usedResources.add(layer.resource.name) toDelete = [r for r in resources if r.name not in usedResources] for resource in toDelete: resource.catalog.delete(resource) for store in self.catalog.get_stores(): if len(store.get_resources()) == 0: self.catalog.delete(store) def consolidateStyles(self): ''' Deletes styles that are redundant and just keeps one copy of them in the catalog, configuring the corresponding layers to use that copy ''' used = {} allstyles = self.catalog.get_styles() for style in allstyles: sld = style.sld_body.replace( "<sld:Name>%s</sld:Name>" % style.name, "") if sld in used.keys(): used[sld].append(style) else: used[sld] = [style] for sld, styles in used.iteritems(): if len(styles) == 1: continue #find the layers that use any of the secondary styles in the list, and make them use the first one styleNames = [s.name for s in styles[1:]] layers = self.catalog.get_layers() for layer in layers: changed = False if layer.default_style.name in styleNames: layer.default_style = styles[0] changed = True alternateStyles = layer.styles newAlternateStyles = set() for alternateStyle in alternateStyles: if alternateStyle.name in styleNames: newAlternateStyles.add(styles[0]) else: newAlternateStyles.add(alternateStyle) newAlternateStyles = list(newAlternateStyles) if newAlternateStyles != alternateStyles: layer.styles = newAlternateStyles changed = True if changed: self.catalog.save(layer) def publishStyle(self, layer, overwrite=True, name=None): ''' Publishes the style of a given layer style in the specified catalog. If the overwrite parameter is True, it will overwrite a style with that name in case it exists ''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) sld = getGsCompatibleSld(layer) if sld is not None: name = name if name is not None else layer.name() name = name.replace(" ", "_") self.catalog.create_style(name, sld, overwrite) return sld def getDataFromLayer(self, layer): ''' Returns the data corresponding to a given layer, ready to be passed to the method in the Catalog class for uploading to the server. If needed, it performs an export to ensure that the file format is supported by the upload API to be used for import. In that case, the data returned will point to the exported copy of the data, not the original data source ''' if layer.type() == layer.RasterLayer: data = exporter.exportRasterLayer(layer) else: filename = exporter.exportVectorLayer(layer) basename, extension = os.path.splitext(filename) data = { 'shp': basename + '.shp', 'shx': basename + '.shx', 'dbf': basename + '.dbf', 'prj': basename + '.prj' } return data def upload(self, layer, workspace=None, overwrite=True, name=None): '''uploads the specified layer''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) name = name if name is not None else layer.name() title = name name = name.replace(" ", "_") try: settings = QSettings() restApi = bool( settings.value("/OpenGeo/Settings/GeoServer/UseRestApi", True, bool)) restApi = True # importer api is disabled for now if layer.type() == layer.RasterLayer: path = self.getDataFromLayer(layer) if restApi: self.catalog.create_coveragestore(name, path, workspace=workspace, overwrite=overwrite) else: session = self.client.upload(path) session.commit() elif layer.type() == layer.VectorLayer: provider = layer.dataProvider() if provider.name() == 'postgres': connName = self.getConnectionNameFromLayer(layer) uri = QgsDataSourceURI(provider.dataSourceUri()) self.catalog.create_pg_featurestore( connName, workspace=workspace, overwrite=overwrite, host=uri.host(), database=uri.database(), schema=uri.schema(), port=uri.port(), user=uri.username(), passwd=uri.password()) self.catalog.create_pg_featuretype(uri.table(), connName, workspace, layer.crs().authid()) else: path = self.getDataFromLayer(layer) if restApi: try: self.catalog.create_shp_featurestore( name, path, workspace=workspace, overwrite=overwrite) except WindowsError: #this might be thrown by the create_shp_featurestore method #when trying to unlink the temp zip file pass except Exception, e: raise e else: shpFile = path['shp'] session = self.client.upload(shpFile) session.commit() else: