Пример #1
0
 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)
Пример #2
0
 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)
Пример #3
0
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:
Пример #4
0
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: