def _identify(request): params = _get_features_params(request) if params.layers == 'all': model = get_bod_model(params.lang) query = params.request.db.query(model) layerIds = [] for layer in get_layers_metadata_for_params(params, query, model): layerIds.append(layer['layerBodId']) else: layerIds = params.layers models = [ models_from_name(layerId) for layerId in layerIds if models_from_name(layerId) is not None ] if models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % ' '.join(layerIds)) maxFeatures = 50 features = [] for feature in _get_features_for_extent(params, models, maxFeatures=maxFeatures): f = _process_feature(feature, params) features.append(f) if len(features) > maxFeatures: break return {'results': features}
def _identify(request): params = FeaturesParams(request) if params.layers == 'all': model = get_bod_model(params.lang) query = params.request.db.query(model) layerIds = [] for layer in _get_layers_metadata_for_params(params, query, model): layerIds.append(layer['idBod']) else: layerIds = params.layers models = [ models_from_name(layerId) for layerId in layerIds if models_from_name(layerId) is not None ] if models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % ' '.join(layerIds)) maxFeatures = 50 features = [] for feature in _get_features_for_extent(params, models, maxFeatures=maxFeatures): f = feature.__geo_interface__ if params.returnGeometry else feature.__interface__ if hasattr(f, 'extra'): layerBodId = f.extra['layerBodId'] f.extra['layerName'] = params.translate(layerBodId) else: layerBodId = f.get('layerBodId') f['layerName'] = params.translate(layerBodId) features.append(f) if len(features) > maxFeatures: break return {'results': features}
def _get_models_from_layername(self): if self.layers == 'all': layers = self._get_layer_list_from_map() else: layers = self.layers models = [ models_from_name(layer) for layer in layers if models_from_name(layer) is not None ] return models
def _get_features(params, extended=False): ''' Returns exactly one feature or raises an excpetion ''' featureIds = params.featureIds.split(',') models = models_from_name(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) for featureId in featureIds: # One layer can have several models for model in models: query = params.request.db.query(model) query = query.filter(model.id == featureId) try: feature = query.one() except NoResultFound: feature = None except MultipleResultsFound: raise exc.HTTPInternalServerError( 'Multiple features found for the same id %s' % featureId) if feature is not None: vectorModel = model break if feature is None: raise exc.HTTPNotFound('No feature with id %s' % featureId) feature = _process_feature(feature, params) feature = {'feature': feature} yield feature, vectorModel
def test_all_htmlpopups(self): from chsdi.models import models_from_name from chsdi.models.bod import LayersConfig from sqlalchemy import distinct from sqlalchemy.orm import scoped_session, sessionmaker val = True DBSession = scoped_session(sessionmaker()) query = DBSession.query(distinct(LayersConfig.layerBodId)).filter( LayersConfig.queryable == val).filter( LayersConfig.staging == 'prod') features = [] try: for layer in getLayers(query): try: FeatDBSession = scoped_session(sessionmaker()) model = models_from_name(layer)[0] query = FeatDBSession.query( model.primary_key_column()).limit(1) ID = [q[0] for q in query] if ID: features.append((layer, str(ID[0]))) finally: FeatDBSession.close() finally: DBSession.close() for f in features: for lang in ('de', 'fr', 'it', 'rm', 'en'): link = '/rest/services/all/MapServer/' + f[0] + '/' + f[ 1] + '/htmlPopup?callback=cb&lang=' + lang resp = self.testapp.get(link) self.failUnless(resp.status_int == 200, link)
def _find(request): MaxFeatures = 50 params = _get_find_params(request) if params.searchText is None: raise exc.HTTPBadRequest('Please provide a searchText') models = models_from_name(params.layer) features = [] findColumn = lambda x: (x, x.get_column_by_name(params.searchField)) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layer) for model in models: vectorModel, searchColumn = findColumn(model) if searchColumn is None: raise exc.HTTPBadRequest('Please provide an existing searchField') query = request.db.query(vectorModel) if params.contains: query = full_text_search(query, [searchColumn], params.searchText) else: if isinstance(searchColumn.type, Date): query = query.filter( cast(searchColumn, Date) == params.searchText) else: searchText = _format_search_text(searchColumn.type, params.searchText) query = query.filter(searchColumn == searchText) query = query.limit(MaxFeatures) for feature in query: f = _process_feature(feature, params) features.append(f) return {'results': features}
def releases(request): params = _get_releases_params(request) # For this sevice, we have to use different models based # on specially sorted views. We add the _meta part to the given # layer name # Note that only zeitreihen is currently supported for this service models = models_from_name(params.layer + '_meta') if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layer) # Default timestamp timestamps = [] for f in _get_features_for_filters(params, [models]): if hasattr(f, 'release_year') and f.release_year is not None: for x in f.release_year: timestamps.append(str(x)) if len(timestamps) > 0: # remove duplicates timestamps = list(set(timestamps)) # add day to have full timestamp timestamps = sorted([int(ts + '1231') for ts in timestamps]) # transform back to string timestamps = [str(ts) for ts in timestamps] return {'results': timestamps}
def test_all_htmlpopups(self): from chsdi.models import models_from_name from chsdi.models.bod import LayersConfig from sqlalchemy import distinct from sqlalchemy.orm import scoped_session, sessionmaker val = True DBSession = scoped_session(sessionmaker()) valnone = None query = DBSession.query(distinct(LayersConfig.layerBodId)).filter(LayersConfig.staging == 'prod').filter(LayersConfig.queryable == val).filter(LayersConfig.parentLayerId == valnone) features = [] try: for layer in getLayers(query): try: FeatDBSession = scoped_session(sessionmaker()) models = models_from_name(layer) self.failUnless(models is not None and len(models) > 0, layer) model = models[0] query = FeatDBSession.query(model.primary_key_column()).limit(1) ID = [q[0] for q in query] if ID: features.append((layer, str(ID[0]))) finally: FeatDBSession.close() finally: DBSession.close() for f in features: for lang in ('de', 'fr', 'it', 'rm', 'en'): link = '/rest/services/all/MapServer/' + f[0] + '/' + f[1] + '/htmlPopup?callback=cb&lang=' + lang resp = self.testapp.get(link) self.failUnless(resp.status_int == 200, link)
def legend(self): idlayer = self.request.matchdict.get('idlayer') layer = self._get_layer_resource(idlayer) # only stored layers_config table at the moment query = self.request.db.query(LayersConfig) query = query.filter(LayersConfig.idBod == idlayer) query = query.one() config = query.getLayerConfig(self.request) hasLegend = config[idlayer]['hasLegend'] if 'attributes' in layer.keys() and 'dataStatus' in layer['attributes'].keys(): status = layer['attributes']['dataStatus'] if status == u'bgdi_created': self.layers = idlayer models = models_from_name(idlayer) for model in models: modified = self.request.db.query(func.max(model.bgdi_created)) datenstand = modified.first()[0].strftime("%Y%m%d") layer['attributes']['dataStatus'] = datenstand legend = { 'layer': layer, 'hasLegend': hasLegend } response = render_to_response( 'chsdi:templates/legend.mako', legend, request=self.request ) if self.cbName is None: return response return response.body
def test_all_htmlpopups(self): from chsdi.models import models_from_name from chsdi.models.bod import LayersConfig from sqlalchemy import distinct from sqlalchemy.orm import scoped_session, sessionmaker val = True DBSession = scoped_session(sessionmaker()) query = DBSession.query(distinct(LayersConfig.idBod)).filter(LayersConfig.queryable == val).filter(LayersConfig.staging == 'prod') # Get a list of all the queryable layers layers = [q[0] for q in query] DBSession.close() # Get a list of feature ids features = [] for layer in layers: try: model = models_from_name(layer)[0] DBSession = scoped_session(sessionmaker()) query = DBSession.query(model.primary_key_column()).limit(1) ID = [q[0] for q in query] # If tables are empty ID is an empty list if ID: features.append((layer, str(ID[0]))) DBSession.close() except Exception as e: print e finally: DBSession.close() for f in features: for lang in ('de', 'fr', 'it', 'rm', 'en'): self.testapp.get('/rest/services/all/MapServer/%s/%s/htmlPopup' % (f[0], f[1]), params={'callback': 'cb', 'lang': '%s' % lang}, status=200)
def _find(request): params = FindFeaturesParams(request) if params.searchText is None: raise exc.HTTPBadRequest('Please provide a searchText') models = models_from_name(params.layer) features = [] findColumn = lambda x: (x, x.get_column_by_name(params.searchField)) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layer) for model in models: vectorModel, searchColumn = findColumn(model) if searchColumn is None: raise exc.HTTPBadRequest('Please provide an existing searchField') query = request.db.query(vectorModel) query = _full_text_search( query, [searchColumn], params.searchText ).limit(50) for feature in query: f = feature.__geo_interface__ if params.returnGeometry else feature.__interface__ # TODO find a way to use translate directly in the model if hasattr(f, 'extra'): layerBodId = f.extra['layerBodId'] f.extra['layerName'] = params.translate(layerBodId) else: layerBodId = f.get('layerBodId') f['layerName'] = params.translate(layerBodId) features.append(f) return {'results': features}
def _get_html_response(self, htmlType): defaultExtent = '42000,30000,350000,900000' defaultImageDisplay = '400,600,96' self.imageDisplay = self.request.params.get('imageDisplay', defaultImageDisplay) self.mapExtent = self.request.params.get('mapExtent', defaultExtent) scale = getScale(self.imageDisplay, self.mapExtent) idlayer = self.request.matchdict.get('idlayer') idfeature = self.request.matchdict.get('idfeature') models = models_from_name(idlayer) if models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % idlayer) layer = self._get_layer_resource(idlayer) # One layer can have several models for model in models: if htmlType == 'extended' and not hasattr(model, '__extended_info__'): raise exc.HTTPNotFound('No extended info has been found for %s' % idlayer) feature = self._get_feature_resource(idlayer, idfeature, model) if feature != 'No Result Found': # One layer can have several templates model_containing_feature_id = model # Exit the loop when a feature is found break if feature == 'No Result Found': raise exc.HTTPNotFound('No feature with id %s' % idfeature) template = 'chsdi:%s' % model_containing_feature_id.__template__ feature.update({'attribution': layer.get('attributes')['dataOwner']}) feature.update({'fullName': layer.get('fullName')}) feature.update({'bbox': self.mapExtent.bounds}) feature.update({'scale': scale}) return template, feature
def extendedhtmlpopup(request): params = FeatureParams(request) params.returnGeometry = False models = models_from_name(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) feature, template, hasExtendedInfo = _get_feature( params, models, params.layerId, params.featureId, extended=True) modelLayer = get_bod_model(params.lang) layer = next(_get_layers_metadata_for_params( params, request.db.query(modelLayer), modelLayer, layerIds=[params.layerId] )) feature.update({'attribution': layer.get('attributes')['dataOwner']}) feature.update({'fullName': layer.get('fullName')}) feature.update({'extended': True}) response = render_to_response( template, { 'feature': feature, 'hasExtendedInfo': hasExtendedInfo }, request=request) if params.cbName is None: return response return response.body
def _attributes(request): ''' This service exposes preview values based on a layer Id and an attribute name (mapped in the model) ''' MAX_ATTR_VALUES = 50 attributesValues = [] params = _get_attributes_params(request) models = models_from_name(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) # Check that the attribute provided is found at least in one model modelToQuery = None for model in models: attributes = model().getAttributesKeys() if params.attribute in attributes: modelToQuery = model break if modelToQuery is None: raise exc.HTTPBadRequest('No attribute %s was found for %s' % (params.attribute, params.layerId)) col = modelToQuery.get_column_by_property_name(params.attribute) colType = str(col.type) if colType in ['DATE', 'INTEGER', 'NUMERIC']: query = request.db.query(func.max(col).label('max'), func.min(col).label('min')) res = query.one() return {'values': [res.min, res.max]} else: query = request.db.query(col).distinct().order_by(col) query = query.limit(MAX_ATTR_VALUES) for attr in query: if len(attr): attributesValues.append(attr[0]) return {'values': sorted(attributesValues)}
def _get_features(params, extended=False): ''' Returns exactly one feature or raises an excpetion ''' featureIds = params.featureIds.split(',') models = models_from_name(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) for featureId in featureIds: # One layer can have several models for model in models: query = params.request.db.query(model) query = query.filter(model.id == featureId) try: feature = query.one() except NoResultFound: feature = None except MultipleResultsFound: raise exc.HTTPInternalServerError('Multiple features found for the same id %s' % featureId) if feature is not None: vectorModel = model break if feature is None: raise exc.HTTPNotFound('No feature with id %s' % featureId) feature = _process_feature(feature, params) feature = {'feature': feature} yield feature, vectorModel
def feature_attributes(request): ''' This service is used to expose the attributes of vector layers. ''' params = LayersParams(request) layerId = request.matchdict.get('layerId') models = models_from_name(layerId) # Models for the same layer have the same attributes if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % layerId) attributes = models[0]().getAttributesKeys() return attributes
def _get_layer_list_from_map(self): model = get_bod_model(self.lang) query = self.request.db.query(model) query = self._map_name_filter(query, model.maps) # only return layers which have geometries layerList = [ q.idBod for q in query if models_from_name(q.idBod) is not None ] return layerList
def _get_layer_list_from_map(self): model = get_bod_model(self.lang) query = self.request.db.query(model).filter( model.maps.ilike('%%%s%%' % self.mapName) ) # only return layers which have a model layerList = [ q.idBod for q in query if models_from_name(q.idBod) is not None ] return layerList
def layerConfig(self, params): config = {} translate = params.translate excludedAttrs = ('geojsonUrlde', 'geojsonUrlfr', 'geojsonUrlit', 'geojsonUrlrm', 'geojsonUrlen') wmsHost = params.request.registry.settings['wmshost'] for k in self.__dict__.keys(): if not k.startswith("_") and k not in excludedAttrs and \ self.__dict__[k] is not None and \ k not in ('staging'): if k == 'maps': config['topics'] = self.__dict__[k] elif k == 'layerBodId': config['label'] = translate(self.__dict__[k]) elif k == 'attribution': config[k] = translate(self.__dict__[k]) elif k == 'matrixSet': if self.__dict__[k] != '21781_26': config[ 'resolutions'] = self._getResolutionsFromMatrixSet( self.__dict__[k]) else: config[k] = self.__dict__[k] layerStaging = self.__dict__['staging'] if config['type'] == 'wmts': del config['singleTile'] elif config['type'] == 'wms': if layerStaging != 'prod': config['wmsUrl'] = make_agnostic(config['wmsUrl'].replace( 'wms.geo.admin.ch', wmsHost)) elif config['type'] == 'geojson': api_url = params.request.registry.settings['api_url'] config['styleUrl'] = make_agnostic(api_url + '/static/vectorStyles/' + self.layerBodId + '.json') config['geojsonUrl'] = self._getGeoJsonUrl(params.lang) # sublayers don't have attributions if 'attribution' in config: config['attributionUrl'] = translate(self.__dict__['attribution'] + '.url') # adding __queryable_attributes__ if they have them models = models_from_name(self.layerBodId) if models is not None: queryable_attributes = get_models_attributes_keys( models, params.lang, True) if len(queryable_attributes) > 0: config['queryableAttributes'] = queryable_attributes return {self.layerBodId: config}
def ilayersWithFeatures(self): for layer in self.ilayers(queryable=True): models = models_from_name(layer) assert (models is not None and len(models) > 0), layer model = models[0] query = self.session.query(model.primary_key_column()) # Depending on db size, random row is slow if self.randomFeatures: query = query.order_by(func.random()) if isinstance(self.nrOfFeatures, (int, long)): query = query.limit(self.nrOfFeatures) hasExtended = model.__extended_info__ if hasattr(model, '__extended_info__') else False for q in query: yield (layer, str(q[0]), hasExtended)
def _get_feature_service(request): params = FeatureParams(request) models = models_from_name(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) feature, template, hasExtendedInfo = _get_feature( params, models, params.layerId, params.featureId ) return feature
def _identify(request): params = _get_features_params(request) if params.layers == 'all': model = get_bod_model(params.lang) query = params.request.db.query(model) layerIds = [] for layer in get_layers_metadata_for_params(params, query, model): layerIds.append(layer['layerBodId']) else: layerIds = params.layers models = [ models_from_name(layerId) for layerId in layerIds if models_from_name(layerId) is not None ] if models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % ' '.join(layerIds)) maxFeatures = 201 features = [] feature_gen = _get_features_for_filters(params, models, maxFeatures=maxFeatures, where=params.where) while True: try: feature = next(feature_gen) except InternalError as e: raise exc.HTTPBadRequest('Your request generated the following database error: %s' % e) except StopIteration: break else: f = _process_feature(feature, params) features.append(f) if len(features) > maxFeatures: break return {'results': features}
def feature_attributes(request): """ This service is used to expose the attributes of vector layers. """ params = LayersParams(request) layerId = request.matchdict.get("layerId") models = models_from_name(layerId) # Models for the same layer have the same attributes if models is None: raise exc.HTTPBadRequest("No Vector Table was found for %s" % layerId) # Take into account all models and remove duplicated keys attributes = _get_models_attributes_keys(models, params.lang) trackAttributesNames = [] fields = [] def insertValueAt(field, attrName, value): if field["name"] == attrName: if len(field["values"]) < MAX_ATTRIBUTES_VALUES and value not in field["values"]: field["values"].append(value) field["values"].sort() return field for model in models: query = params.request.db.query(model) query = query.limit(SAMPLE_SIZE) for rowIndex, row in enumerate(query): # attrName as defined in the model for attrIndex, attrName in enumerate(attributes): featureAttrs = row.getAttributes(excludePkey=False) if attrName not in trackAttributesNames and attrName in featureAttrs: fieldType = _find_type(model(), attrName) fields.append( { "name": attrName, "type": str(fieldType), "alias": params.translate("%s.%s" % (layerId, attrName)), "values": [], } ) trackAttributesNames.append(attrName) if attrName in featureAttrs: for fieldsIndex, field in enumerate(fields): value = featureAttrs[attrName] if isinstance(value, (decimal.Decimal, datetime.date, datetime.datetime)): value = str(value) fields[fieldsIndex] = insertValueAt(field, attrName, value) return {"id": layerId, "name": params.translate(layerId), "fields": fields}
def layerConfig(self, params): config = {} translate = params.translate excludedAttrs = ('geojsonUrlde', 'geojsonUrlfr', 'geojsonUrlit', 'geojsonUrlrm', 'geojsonUrlen') wmsHost = params.request.registry.settings['wmshost'] for k in self.__dict__.keys(): if not k.startswith("_") and k not in excludedAttrs and \ self.__dict__[k] is not None and \ k not in ('staging'): if k == 'maps': config['topics'] = self.__dict__[k] elif k == 'layerBodId': config['label'] = translate(self.__dict__[k]) elif k == 'attribution': config[k] = translate(self.__dict__[k]) elif k == 'matrixSet': if self.__dict__[k] != '21781_26': config['resolutions'] = self._getResolutionsFromMatrixSet( self.__dict__[k] ) else: config[k] = self.__dict__[k] layerStaging = self.__dict__['staging'] if config['type'] == 'wmts': del config['singleTile'] elif config['type'] == 'wms': if layerStaging != 'prod': config['wmsUrl'] = make_agnostic( config['wmsUrl'].replace('wms.geo.admin.ch', wmsHost)) elif config['type'] == 'geojson': api_url = params.request.registry.settings['api_url'] config['styleUrl'] = make_agnostic( api_url + '/static/vectorStyles/' + self.layerBodId + '.json') config['geojsonUrl'] = self._getGeoJsonUrl(params.lang) # sublayers don't have attributions if 'attribution' in config: config['attributionUrl'] = translate(self.__dict__['attribution'] + '.url') # adding __queryable_attributes__ if they have them models = models_from_name(self.layerBodId) if models is not None: queryable_attributes = get_models_attributes_keys(models, params.lang, True) if len(queryable_attributes) > 0: config['queryableAttributes'] = queryable_attributes return {self.layerBodId: config}
def _get_feature(self): self.returnGeometry = self.request.params.get('returnGeometry') idlayer = self.request.matchdict.get('idlayer') idfeature = self.request.matchdict.get('idfeature') models = models_from_name(idlayer) if models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % idlayer) # One layer can have several models for model in models: feature = self._get_feature_resource(idlayer, idfeature, model) if feature != 'No Result Found': # One layer can have several templates break if feature == 'No Result Found': raise exc.HTTPNotFound('No feature with id %s' % idfeature) feature = self._get_feature_resource(idlayer, idfeature, model) return feature
def _find(request): MaxFeatures = 50 params = _get_find_params(request) if params.searchText is None: raise exc.HTTPBadRequest('Please provide a searchText') models = models_from_name(params.layer) features = [] findColumn = lambda x: (x, x.get_column_by_property_name(params.searchField)) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layer) for model in models: vectorModel, searchColumn = findColumn(model) if searchColumn is None: raise exc.HTTPBadRequest('Please provide an existing searchField') query = request.db.query(vectorModel) if params.contains: query = full_text_search( query, [searchColumn], params.searchText ) else: if isinstance(searchColumn.type, Date): query = query.filter( cast(searchColumn, Date) == params.searchText ) else: searchText = _format_search_text(searchColumn.type, params.searchText) query = query.filter( searchColumn == searchText ) query = query.limit(MaxFeatures) for feature in query: f = _process_feature(feature, params) features.append(f) return {'results': features}
def validateLayerId(idlayer): models = models_from_name(idlayer) if models is None: raise exc.HTTPBadRequest('Please provide a valid layer Id (what you provided: %s)' %idlayer) return models