Exemplo n.º 1
0
def query_features(lang, layers, query):
    features = []
    max_features_pro_layer = int(10 / len(layers))
    terms = query.split()
    terms1 = ' & '.join([term + ('' if term.isdigit() else ':*')  for term in terms])
    if lang == 'fr' or lang == 'it':
       bodsearch = BodLayerFr
    else:
       bodsearch = BodLayerDe

    c.baseUrl = ''
    c.lang = lang
    c.path_url = ''

    for layer in layers:
        bodlayer = Session.query(bodsearch).get(layer)
        for model in models_from_name(layer):
            if hasattr(model, '__queryable_attributes__'):
                ftsFilter = 'to_tsvector(\'english\',' + ' || \' \' || '.join(["coalesce(%s::text,'') " % s for s in
                                                                   model.__queryable_attributes__]) + ") @@ to_tsquery('english','%s')" % terms1

                for feature in Session.query(model).filter(ftsFilter).limit(max_features_pro_layer).all():
                    feature.compute_attribute()
                    feature.compute_template(layer, bodlayer)

                    layername = _(layer)
                    html = '<b>%s </b><br>%s' % (layername[0:35]+'...' if len(layername) > 35 else layername,
                       feature.preview)
                    feature.attributes['html'] = html
                    feature.layer_id = layer
                    features.append(feature)
    return features
Exemplo n.º 2
0
def get_features(layer, ids):
    features = []
    for model in models_from_name(layer):
        for fid in ids:
            if len(features) < MAX_FEATURES:
                try:
                    feature = Session.query(model).get(fid)
                    if feature:
                        features.append(feature)
                except exc.SQLAlchemyError:
                    pass
            else:
                break
    return features
Exemplo n.º 3
0
    def datenstand(self, layer_id, datenstand):
        """
        if the value in bod.dataset.datenstand == TAG_DATENSTAND, return the most recent date of the data table,
        else return the regular value datenstand.
        """

        if datenstand == self.TAG_DATENSTAND:
            try:
                for model in models_from_name(layer_id):
                    modified = Session.query(func.max(model.bgdi_created))
                return modified.first()[0].strftime("%Y%m%d")
            except:
                return datenstand
        else:
            return datenstand
Exemplo n.º 4
0
    def search(self):
        # optional paramater "extent"
        # Get current map extent or calculate a 'sensitive' default based on available information  (scale !) 
        extent = request.params.get('extent')
        if extent is not None:
            try:
                extent = map(float, extent.split(','))
            except ValueError:
                abort(400, "Parameter 'extent' is invalid. Use extent=656430,254350,657930,25585 for instance.")
        else:
            resolution = 1 / ((1 / (c.scale > 0 or 1000.0)) * 39.3701 * 72)
            meters = 300 * resolution
            cx, cy = c.bbox[0:2]
            extent = (cx - meters, cy - meters, cx + meters, cy + meters)

        c.extent = Polygon(((extent[0], extent[1]), (extent[0], extent[3]),
                                (extent[2], extent[3]), (extent[2], extent[1]),
                                (extent[0], extent[1])))

        c.baseUrl = request.params.get('baseUrl')  or ''

        # Request features
        features = []
        layerCounter = 0
        for layer_name in c.layers:
            layerCounter = layerCounter + 1
            for model in models_from_name(layer_name):
                geom_filter = model.bbox_filter(c.scale, c.bbox)
                if c.timestamps is not None:
                    time_filter = model.time_filter(c.timestamps[layerCounter-1])
                else:
                    time_filter = None
                if geom_filter is not None:
                    query = Session.query(model).filter(geom_filter)
                    if time_filter is not None:
                        query = query.filter(time_filter)
                    bodlayer = Session.query(self.bodsearch).get(layer_name)

                    for feature in query.limit(MAX_FEATURES).all():
                        properties = {}
                        feature.compute_template(layer_name, bodlayer)
                        if self.format == 'raw':
                            feature.compute_attribute()
                            properties = feature.attributes
                        properties['html'] = feature.html
                        properties['layer_id'] = feature.layer_id
                        properties['preview'] = feature.preview
                        if (self.no_geom or layer_name == 'ch.kantone.cadastralwebmap-farbe') and 'print' not in request.params:
                            features.append(Feature(id=feature.id,
                                                    bbox=feature.geometry.bounds,
                                                    properties=properties))
                        else:
                            features.append(feature)

        # Send features back 
        if 'print' in request.params:
            c.features = features
            return render('/tooltips/_print.mako')
        else:
            output = simplejson.dumps(FeatureCollection(features), cls=MapFishEncoder)
            cb_name = request.params.get('cb')
            if cb_name is not None:
                response.headers['Content-Type'] = 'text/javascript'
                return str(cb_name) + '(' + output + ');'
            else:
                response.headers['Content-Type'] = 'application/json'
                return output
Exemplo n.º 5
0
    def index(self):
    # if a list of layers was provided the first layer in the
    # list will be taken
        layer = c.layers[0]

        features = []
        urlContent = request.url.split("?")
        id = urlContent[0].split("/")[len(urlContent[0].split("/")) - 1]

        # extended infos
        if '.html' in id:
            id = id.strip('.html')
            ids = id.split(',')
            if len(ids) > 1:
                innerHtml = ''
                for model in models_from_name(layer):
                    items_nb = len(ids)
                    item_count = 0
                    for fid in ids:
                        feature = Session.query(model).get(fid)
                        bodlayer = Session.query(self.bodsearch).get(layer)
                        if feature is not None:
                            feature.compute_template(layer, bodlayer)
                            feature.compute_attribute()
                            c.html_type = 'extended'
                            c.feature = feature
                            item_count = item_count + 1
                            if items_nb == item_count:
                                c.last = True
                            else:
                                c.last = False
                            innerHtml = innerHtml + render(feature.__template__)
                        else:
                            abort(404, 'One of the id you provided is not valid')
                feature.html = innerHtml
                body_tooltip = render('/tooltips/extended_tooltips.mako')
                feature.html = body_tooltip.encode('utf8')
            else:
                c.last = True
                for model in models_from_name(layer):
                    if len(features) < MAX_FEATURES:
                        feature = Session.query(model).get(id)
                        bodlayer = Session.query(self.bodsearch).get(layer)
       
                        if feature is not None:
                            properties = {}
                            feature.compute_template(layer, bodlayer)
                            feature.compute_attribute()
                            properties = feature.attributes
                            c.html_type = 'extended'
                            feature.html = render(feature.__template__)
                            body_tooltip = render('/tooltips/extended_tooltips.mako')
                            feature.html = body_tooltip.encode('utf8')
    
    
                            if (self.no_geom):
                                features.append(Feature(id=feature.id,
                                                    bbox=feature.geometry.bounds,
                                                    properties=feature.attributes))
                            else:
                                features.append(feature)
                            response.headers['Content-Type'] = 'text/html'
                            return feature.html
                        else:
                            abort(404, 'One of the id you provided is not valid')
                    else:
                        break

            response.headers['Content-Type'] = 'text/html'
            return feature.html
        # not extended info
        for model in models_from_name(layer):
            if len(features) < MAX_FEATURES:
                feature = Session.query(model).get(id)
                if feature:
                    properties = {}
                    if self.format =='html':
                        bodlayer = Session.query(self.bodsearch).get(layer)
                        feature.compute_template(layer, bodlayer)
                        c.html_type = 'full'
                        feature.html = render(feature.__template__)
                        properties['html'] = feature.html
                    else:
                        feature.compute_attribute()
                        properties = feature.attributes
                    if (self.no_geom):
                        features.append(Feature(id=feature.id,
                                                bbox=feature.geometry.bounds,
                                                properties=properties))
                    else:
                        features.append(feature)

            else:
                break

        output = simplejson.dumps(FeatureCollection(features), cls=MapFishEncoder)
        cb_name = request.params.get('cb')

        if cb_name is not None:
            response.headers['Content-Type'] = 'text/javascript'
            return str(cb_name) + '(' + output + ');'
        else:
            response.headers['Content-Type'] = 'application/json'
            return output
Exemplo n.º 6
0
    def index(self, id=None):

##----------------------------------------Session----------------------------------------##     	
    	  # Define which view are taken into account
        if self.mode in ['all','legend','bodsearch','preview','mobile']:
            query = Session.query(self.BodLayer)
            # Global variable defined in the config files
            Geodata_staging  = config['geodata_staging'].split(',')
        # Query only view_bod_wmts_getcapabilities_{lang}
        elif self.mode == 'wmts':
            query = Session.query(self.GetCap)
            self.BodLayer = self.GetCap
            # random variable so that no filter is applied 
            Geodata_staging = ['geodata_staging']
        else:
            abort(400, 'The parameter provided for mode is not valid') 
            
##----------------------------------------Properties----------------------------------------##    	
        # Per default all the properties are returned
        properties = request.params.get('properties','all')
        if properties == 'all':
            # Create a list with all the properties 
            properties = []
            # Create a list with all the properties of the selected table(s)
            for key in self.map_properties.keys():
                # Populate the list of the properties with all the available keys
                properties.append(key)
        else:
            properties = properties.split(',')
            # Check if the property exists
            for prop in properties:
                if prop not in self.map_properties.keys():
                    abort(400, 'The property(-ies) you provided is not valid')
        if not isinstance(properties,list):
            abort(400, 'An error occured while parsing the properties')             

##----------------------------------------Project----------------------------------------##            
        # Per default the project api is selected
        if self.mode == 'legend':
           project = ['all']
        else:
           project = request.params.get('project','api')
           project = project.split(',')
        if not isinstance(project,list):
            abort(400, 'An error occured while parsing the projects')           

##----------------------------------------Layer_id----------------------------------------##
        if id is None:        
            # Per default all layers are taken into account
            layer_id = request.params.get('layer','all')
            layer_id = layer_id.split(',')
            if not isinstance(layer_id,list):
                abort(400, 'An error occured while parsing the layer Id(s)')
        else:
            layer_id = id
            layer_id = layer_id.split(',')
            if not isinstance(layer_id,list):
                abort(400, 'An error occured while parsing the layer Id(s)')        

##----------------------------------------SecureWMTS----------------------------------------##
        # This parameter is only used in mode = wmts

##----------------------------------------QueryString----------------------------------------##                 
        # Per default no query string are applied 
        query_string = request.params.get('query') 

##----------------------------------------Filters----------------------------------------##    
        # Filter by staging attribute
        # If one if these 3 layers are in the list do not filter by staging mode 
        if 'ch.swisstopo.pixelkarte-farbe' in layer_id or 'ch.swisstopo.pixelkarte-grau' in layer_id or 'ch.swisstopo.tml3d-hintergrund-karte' in layer_id and self.mode == 'legend':
            pass
        elif self.mode in ['all','legend','bodsearch','preview','mobile']:
            if 'integration' in Geodata_staging:
                query = query.filter(or_(self.BodLayer.staging == 'integration', self.BodLayer.staging == 'prod'))
            elif 'prod' in Geodata_staging:
                query = query.filter(self.BodLayer.staging == 'prod')
        
        if self.mode in ['bodsearch']:
            query = query.filter(self.BodLayer.bodsearch == 'true')
             
        # Filter by layer_id
        if layer_id[0] != 'all':
            list_layers = []
            for l_id in layer_id:
                list_layers.append(self.BodLayer.bod_layer_id == l_id)
            query = query.filter(or_(*list_layers))

        # Filter by project
        if project[0] != 'all':
            list_projects = []
            for proj in project:
                 list_projects.append(self.BodLayer.projekte.ilike('%%%s%%' % proj))
            query = query.filter(or_(*list_projects))

        # Filter by query string
        if query_string is not None:
            columns = []
            # Iterate on the properties we are intrested in
            for prop in properties:
                columns.append(column_from_name(prop, self.map_properties).ilike('%%%s%%' % query_string))
            # Full text search
            query = query.filter(or_(*columns))
        
##----------------------------------------ResultsPreparation----------------------------------------##           
                         
        if self.mode == 'bodsearch':
            if query_string is None:
                abort(400, 'Please provide a query parameter')
            # Order the results
            query = query.order_by(self.BodLayer.kurzbezeichnung).order_by(self.BodLayer.bezeichnung).order_by(self.BodLayer.geobasisdatensatz_name)
            results = [r.json(query_string) for r in query]    
        elif self.mode == 'legend':
            c.host = request.params.get('h', '%s://api.geo.admin.ch' % c.scheme)
            c.full = True
            c.hilight = ''
            for r in query:
                c.layer = r
                c.legend = r
            # If value in bod.dataset.datenstand == bgdi_created, return the most recent date of the data table
            if c.legend.datenstand == 'bgdi_created':
                for model in models_from_name(c.layer.bod_layer_id):
                    modified = Session.query(func.max(model.bgdi_created))
                c.legend.datenstand = modified.first()[0].strftime("%Y%m%d")
        elif self.mode == 'mobile':
            results = [r.json(query_string) for r in query]
        elif self.mode == 'wmts':
            c.layers = query
            c.themes = Session.query(self.GetCapThemes).all() 
            # Per default the parameter secure wmts is set to false
            c.is_swisstopowmts = False 
            c.service_metadata = Session.query(self.ServiceMetadata).filter(self.ServiceMetadata.pk_map_name.like('%wmts-bgdi%')).first()
            request_uri = request.environ.get("REQUEST_URI", "")
            if request_uri.find("1.0.0"): # new bucket WMTS
                c.onlineressource = "%s://wmts.geo.admin.ch" % c.scheme
            else:
                c.onlineressource = "%s://api.geo.admin.ch/wmts" % c.scheme
        elif self.mode == 'all':
            results = [q.layers_results(properties) for q in query]
        elif self.mode == 'preview':
            result = [q.layers_results(['bod_layer_id']) for q in query]
        
##----------------------------------------Results----------------------------------------##
        cb_name = request.params.get('cb')
        print_legend = request.params.get('print', False)
        #self.format = request.params.get('format','json')

        if self.mode == 'bodsearch' or self.mode == 'mobile':    
            if cb_name is not None:
                response.headers['Content-Type'] = 'text/javascript'
                results = simplejson.dumps({"results": results})
                return str(cb_name) + '(' + results + ');' 
            else:
                response.headers['Content-Type'] = 'application/json'
                return simplejson.dumps({'results': results})        
        elif self.mode == 'legend':
            # Query only one layer at a time in legend mode
            if len(layer_id) != 1 or layer_id[0] == 'all':
                abort(400, "Please provide only one layer at a time")
            if not hasattr(c, 'layer'):
                abort(400, "The parameters you provided didn't return any layer")
            if print_legend == "true":
                return render('/bod-details-print.mako')
            else:
                response.headers['Content-Type'] = 'text/javascript'
                results = simplejson.dumps(render('/bod-details.mako'))
                if cb_name is not None:
                    return str(cb_name) + '(' + results + ');'
                else:
                    return results
        elif self.mode == 'wmts':
            response.headers['Content-Type'] = 'text/xml'
            response.headers['Pragma'] = 'public'
            response.headers['Expires'] = '0'
            response.headers['Cache-Control'] = 'no-cache'
            response.charset = 'utf-8'
            return render('/WMTSCapabilities.mako')
        elif self.mode == 'all':
            if cb_name is not None:
                response.headers['Content-Type'] = 'text/javascript'
                results = simplejson.dumps({"results": results})
                return str(cb_name) + '(' + results + ');'
            else:
                response.headers['Content-Type'] = 'application/json'             
                return simplejson.dumps({'results': results})
        elif self.mode == 'preview':
            c.layers = []
            for object in result:
                for id,bodLayerId in object.iteritems():
                    if bodLayerId not in c.layers:
                       c.layers.append(bodLayerId)
            response.headers['Content-Type'] = mimetypes.types_map['.html']
            response.charset = 'utf8'
            map_width = request.params.get('width',250)
            c.map_width = map_width
            return render('/layersPreview.mako')