Beispiel #1
0
    def get_metadata(self,
                     dataset,
                     server_url,
                     layer=None,
                     tileset=None,
                     tilejson=True,
                     **kwargs):
        """
        Gets tile metadata

        :param dataset: dataset name
        :param server_url: server base url
        :param layer: mvt tile layer name
        :param tileset: mvt tileset name
        :param tilejson: `bool` for the returning json structure
                        if True it returns MapBox TileJSON 3.0
                        otherwise the raw JSON is served

        :returns: `dict` of JSON metadata
        """

        if is_url(self.data):
            url = urlparse(self.data)
            base_url = '{}://{}'.format(url.scheme, url.netloc)
            with requests.Session() as session:
                session.get(base_url)
                resp = session.get('{base_url}/{lyr}/metadata.json'.format(
                    base_url=base_url, lyr=layer))
                resp.raise_for_status()
            content = resp.json()
        else:
            if not isinstance(self.service_metadata_url, Path):
                msg = 'Wrong data path configuration: {}'.format(
                    self.service_metadata_url)
                LOGGER.error(msg)
                raise ProviderConnectionError(msg)
            with open(self.service_metadata_url, 'r') as md_file:
                content = json.loads(md_file.read())
        if tilejson:
            service_url = urljoin(
                server_url,
                'collections/{}/tiles/{}/{{{}}}/{{{}}}/{{{}}}{}'.format(
                    dataset, tileset, 'tileMatrix', 'tileRow', 'tileCol',
                    '?f=mvt'))
            content = {
                "tilejson": "3.0.0",
                "name": content["name"],
                "tiles": service_url,
                "minzoom": content["minzoom"],
                "maxzoom": content["maxzoom"],
                "bounds": content["bounds"],
                "center": content["center"],
                "attribution": None,
                "description": None,
                "vector_layers": json.loads(content["json"])["vector_layers"]
            }
        else:
            content['json'] = json.loads(content['json'])

        return content
Beispiel #2
0
    def get_layer(self):

        if is_url(self.data):
            url = urlparse(self.data)
            return url.path.split("/{z}/{x}/{y}")[0][1:]
        else:
            return None
Beispiel #3
0
def geojson2geojsonld(config, data, dataset, identifier=None):
    """
    Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be
    read from, and extended by, the pygeoapi configuration for a particular
    dataset.

    :param config: dict of configuration
    :param data: dict of data:
    :param dataset: dataset identifier
    :param identifier: item identifier (optional)

    :returns: string of rendered JSON (GeoJSON-LD)
    """
    context = config['resources'][dataset].get('context', [])
    data['id'] = ('{}/collections/{}/items/{}'
                  if identifier else '{}/collections/{}/items').format(
                      *[config['server']['url'], dataset, identifier])
    if data.get('timeStamp', False):
        data['https://schema.org/sdDatePublished'] = data.pop('timeStamp')
    defaultVocabulary = "https://geojson.org/geojson-ld/geojson-context.jsonld"
    ldjsonData = {"@context": [defaultVocabulary, *(context or [])], **data}
    isCollection = identifier is None
    if isCollection:
        for i, feature in enumerate(data['features']):
            featureId = feature.get('id', None) or feature.get(
                'properties', {}).get('id', None)
            if featureId is None:
                continue
            # Note: @id or https://schema.org/url or both or something else?
            if is_url(str(featureId)):
                feature['id'] = featureId
            else:
                feature['id'] = '{}/{}'.format(data['id'], featureId)

    return json.dumps(ldjsonData)
Beispiel #4
0
    def get_tiles(self,
                  layer=None,
                  tileset=None,
                  z=None,
                  y=None,
                  x=None,
                  format_=None):
        """
        Gets tile

        :param layer: mvt tile layer
        :param tileset: mvt tileset
        :param z: z index
        :param y: y index
        :param x: x index
        :param format_: tile format

        :returns: an encoded mvt tile
        """
        if format_ == "mvt":
            format_ = self.format_type
        if is_url(self.data):
            url = urlparse(self.data)
            base_url = '{}://{}'.format(url.scheme, url.netloc)
            with requests.Session() as session:
                session.get(base_url)
                resp = session.get('{base_url}/{lyr}/{z}/{y}/{x}.{f}'.format(
                    base_url=base_url, lyr=layer, z=z, y=y, x=x, f=format_))
                resp.raise_for_status()
                return resp.content
        else:
            if not isinstance(self.service_url, Path):
                msg = 'Wrong data path configuration: {}'.format(
                    self.service_url)
                LOGGER.error(msg)
                raise ProviderConnectionError(msg)
            else:
                try:
                    with open(
                            self.service_url.joinpath('{z}/{y}/{x}.{f}'.format(
                                z=z, y=y, x=x, f=format_)), 'rb') as tile:
                        return tile.read()
                except FileNotFoundError as err:
                    raise ProviderTileNotFoundError(err)
Beispiel #5
0
    def __init__(self, provider_def):
        """
        Initialize object

        :param provider_def: provider definition

        :returns: pygeoapi.provider.MVT.MVTProvider
        """

        super().__init__(provider_def)

        if is_url(self.data):
            url = urlparse(self.data)
            baseurl = '{}://{}'.format(url.scheme, url.netloc)
            param_type = '?f=mvt'
            servicepath = \
                '{}/tiles/{{{}}}/{{{}}}/{{{}}}/{{{}}}{}'.format(
                    url.path.split('/{z}/{x}/{y}')[0],
                    'tileMatrixSetId',
                    'tileMatrix',
                    'tileRow',
                    'tileCol',
                    param_type)

            self._service_url = url_join(baseurl, servicepath)
            self._service_metadata_url = urljoin(
                self.service_url.split('{tileMatrix}/{tileRow}/{tileCol}')[0],
                'metadata')
        else:
            data_path = Path(self.data)
            if not data_path.exists():
                msg = 'Service does not exist: {}'.format(self.data)
                LOGGER.error(msg)
                raise ProviderConnectionError(msg)
            self._service_url = data_path
            metadata_path = data_path.joinpath('metadata.json')
            if not metadata_path.exists():
                msg = 'Service metadata does not exist: {}'.format(
                    metadata_path.name)
                LOGGER.error(msg)
                raise ProviderConnectionError(msg)
            self._service_metadata_url = metadata_path
Beispiel #6
0
def geojson2jsonld(config, data, dataset, identifier=None, id_field='id'):
    """
        Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be
        read from, and extended by, the pygeoapi configuration for a particular
        dataset.

        :param config: dict of configuration
        :param data: dict of data:
        :param dataset: dataset identifier
        :param identifier: item identifier (optional)
        :param id_field: item identifier_field (optional)

        :returns: string of rendered JSON (GeoJSON-LD)
    """
    context = config['resources'][dataset].get('context', []).copy()
    defaultVocabulary = {
        'schema': 'https://schema.org/',
        id_field: '@id',
        'type': '@type'
    }

    if identifier:
        # Single jsonld
        defaultVocabulary.update(
            {'geosparql': 'http://www.opengis.net/ont/geosparql#'})

        # Expand properties block
        data.update(data.pop('properties'))

        # Include multiple geometry encodings
        data['type'] = 'schema:Place'
        jsonldify_geometry(data)
        data[id_field] = identifier

    else:
        # Collection of jsonld
        defaultVocabulary.update({
            'features': 'schema:itemListElement',
            'FeatureCollection': 'schema:itemList'
        })

        data['@id'] = '{}/collections/{}/items/'.format(
            config['server']['url'], dataset)

        for i, feature in enumerate(data['features']):
            # Get URI for each feature
            identifier = feature.get(id_field,
                                     feature['properties'].get(id_field, ''))
            if not is_url(str(identifier)):
                identifier = '{}/collections/{}/items/{}'.format(
                    config['server']['url'], dataset, feature['id'])

            data['features'][i] = {
                id_field: identifier,
                'type': 'schema:Place'
            }

    if data.get('timeStamp', False):
        data['https://schema.org/sdDatePublished'] = data.pop('timeStamp')

    data['links'] = data.pop('links')

    ldjsonData = {'@context': [defaultVocabulary, *(context or [])], **data}

    return ldjsonData
Beispiel #7
0
def geojson2geojsonld(config, data, dataset, identifier=None, id_field='id'):
    """
    Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be
    read from, and extended by, the pygeoapi configuration for a particular
    dataset.

    :param config: dict of configuration
    :param data: dict of data:
    :param dataset: dataset identifier
    :param identifier: item identifier (optional)
    :param id_field: item identifier_field (optional)

    :returns: string of rendered JSON (GeoJSON-LD)
    """
    context = config['resources'][dataset].get('context', [])
    geojsonld = config['resources'][dataset].get('geojsonld', True)

    if identifier:
        # Single geojsonld
        if not geojsonld:
            data, geocontext = make_jsonld(data)
            data[id_field] = identifier
        else:
            data['id'] = identifier

    else:
        # Collection of geojsonld
        data['@id'] = '{}/collections/{}/items/'.format(
            config['server']['url'], dataset)
        for i, feature in enumerate(data['features']):
            identifier = feature.get(id_field,
                                     feature['properties'].get(id_field, ''))
            if not is_url(str(identifier)):
                identifier = '{}/collections/{}/items/{}'.format(
                    config['server']['url'], dataset, feature['id'])

            if not geojsonld:
                feature, geocontext = make_jsonld(feature)
                geocontext.append({
                    "features": "schema:itemListElement",
                    "FeatureCollection": "schema:itemList"
                })
                # Note: @id or https://schema.org/url, both or something else?
                feature[id_field] = identifier
            else:
                feature['id'] = identifier

            data['features'][i] = feature

    if data.get('timeStamp', False):
        data['https://schema.org/sdDatePublished'] = data.pop('timeStamp')

    defaultVocabulary = "https://geojson.org/geojson-ld/geojson-context.jsonld"
    if not geojsonld:
        ldjsonData = {
            "@context": [{
                "schema": "https://schema.org/",
                id_field: "@id",
                "type": "@type",
            }, *(context or []), *(geocontext or [])],
            **data
        }
    else:
        ldjsonData = {
            "@context": [defaultVocabulary, *(context or [])],
            **data
        }

    return ldjsonData