Search in sources :

Example 1 with CrsTransformationException

use of de.ii.xtraplatform.crs.domain.CrsTransformationException in project ldproxy by interactive-instruments.

the class TilesHelper method buildTileSet.

// TODO: move to TileSet as static of()
/**
 * generate the tile set metadata according to the OGC Tile Matrix Set standard (version 2.0.0, draft from June 2021)
 * @param api the API
 * @param tileMatrixSet the tile matrix set
 * @param zoomLevels the range of zoom levels
 * @param center the center point
 * @param collectionId the collection, empty = all collections in the dataset
 * @param dataType vector, map or coverage
 * @param links links to include in the object
 * @param uriCustomizer optional URI of the resource
 * @param limitsGenerator helper to generate the limits for each zoom level based on the bbox of the data
 * @param providers helper to access feature providers
 * @return the tile set metadata
 */
public static TileSet buildTileSet(OgcApi api, TileMatrixSet tileMatrixSet, MinMax zoomLevels, List<Double> center, Optional<String> collectionId, TileSet.DataType dataType, List<Link> links, Optional<URICustomizer> uriCustomizer, CrsTransformerFactory crsTransformerFactory, TileMatrixSetLimitsGenerator limitsGenerator, FeaturesCoreProviders providers, EntityRegistry entityRegistry) {
    OgcApiDataV2 apiData = api.getData();
    Builder builder = ImmutableTileSet.builder().dataType(dataType);
    builder.tileMatrixSetId(tileMatrixSet.getId());
    if (tileMatrixSet.getURI().isPresent())
        builder.tileMatrixSetURI(tileMatrixSet.getURI().get().toString());
    else
        builder.tileMatrixSet(tileMatrixSet.getTileMatrixSetData());
    uriCustomizer.ifPresent(uriCustomizer1 -> builder.tileMatrixSetDefinition(uriCustomizer1.removeLastPathSegments(collectionId.isPresent() ? 3 : 1).clearParameters().ensureLastPathSegments("tileMatrixSets", tileMatrixSet.getId()).toString()));
    if (Objects.isNull(zoomLevels))
        builder.tileMatrixSetLimits(ImmutableList.of());
    else
        builder.tileMatrixSetLimits(collectionId.isPresent() ? limitsGenerator.getCollectionTileMatrixSetLimits(api, collectionId.get(), tileMatrixSet, zoomLevels) : limitsGenerator.getTileMatrixSetLimits(api, tileMatrixSet, zoomLevels));
    try {
        BoundingBox boundingBox = api.getSpatialExtent(collectionId).orElse(tileMatrixSet.getBoundingBoxCrs84(crsTransformerFactory));
        builder.boundingBox(ImmutableTilesBoundingBox.builder().lowerLeft(BigDecimal.valueOf(boundingBox.getXmin()).setScale(7, RoundingMode.HALF_UP), BigDecimal.valueOf(boundingBox.getYmin()).setScale(7, RoundingMode.HALF_UP)).upperRight(BigDecimal.valueOf(boundingBox.getXmax()).setScale(7, RoundingMode.HALF_UP), BigDecimal.valueOf(boundingBox.getYmax()).setScale(7, RoundingMode.HALF_UP)).crs(OgcCrs.CRS84.toUriString()).build());
    } catch (CrsTransformationException e) {
    // ignore, just skip the boundingBox
    }
    if ((Objects.nonNull(zoomLevels) && zoomLevels.getDefault().isPresent()) || !center.isEmpty()) {
        ImmutableTilePoint.Builder builder2 = new ImmutableTilePoint.Builder();
        if (Objects.nonNull(zoomLevels))
            zoomLevels.getDefault().ifPresent(def -> builder2.tileMatrix(String.valueOf(def)));
        if (!center.isEmpty())
            builder2.coordinates(center);
        builder.centerPoint(builder2.build());
    }
    // prepare a map with the JSON schemas of the feature collections used in the style
    JsonSchemaCache schemas = new SchemaCacheTileSet(() -> entityRegistry.getEntitiesForType(Codelist.class));
    Map<String, JsonSchemaDocument> schemaMap = collectionId.isPresent() ? apiData.getCollectionData(collectionId.get()).filter(collectionData -> {
        Optional<TilesConfiguration> config = collectionData.getExtension(TilesConfiguration.class);
        return collectionData.getEnabled() && config.isPresent() && config.get().isEnabled();
    }).map(collectionData -> {
        Optional<FeatureSchema> schema = providers.getFeatureSchema(apiData, collectionData);
        if (schema.isPresent())
            return ImmutableMap.of(collectionId.get(), schemas.getSchema(schema.get(), apiData, collectionData, Optional.empty()));
        return null;
    }).filter(Objects::nonNull).orElse(ImmutableMap.of()) : apiData.getCollections().entrySet().stream().filter(entry -> {
        Optional<TilesConfiguration> config = entry.getValue().getExtension(TilesConfiguration.class);
        return entry.getValue().getEnabled() && config.isPresent() && config.get().isMultiCollectionEnabled();
    }).map(entry -> {
        Optional<FeatureSchema> schema = providers.getFeatureSchema(apiData, entry.getValue());
        if (schema.isPresent())
            return new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), schemas.getSchema(schema.get(), apiData, entry.getValue(), Optional.empty()));
        return null;
    }).filter(Objects::nonNull).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
    // TODO: replace with SchemaDeriverTileLayers
    schemaMap.entrySet().stream().forEach(entry -> {
        String collectionId2 = entry.getKey();
        FeatureTypeConfigurationOgcApi collectionData = apiData.getCollections().get(collectionId2);
        JsonSchemaDocument schema = entry.getValue();
        ImmutableTileLayer.Builder builder2 = ImmutableTileLayer.builder().id(collectionId2).title(collectionData.getLabel()).description(collectionData.getDescription()).dataType(dataType);
        collectionData.getExtension(TilesConfiguration.class).map(config -> config.getZoomLevelsDerived().get(tileMatrixSet.getId())).ifPresent(minmax -> builder2.minTileMatrix(String.valueOf(minmax.getMin())).maxTileMatrix(String.valueOf(minmax.getMax())));
        final JsonSchema geometry = schema.getProperties().get("geometry");
        if (Objects.nonNull(geometry)) {
            String geomAsString = geometry.toString();
            boolean point = geomAsString.contains("GeoJSON Point") || geomAsString.contains("GeoJSON MultiPoint");
            boolean line = geomAsString.contains("GeoJSON LineString") || geomAsString.contains("GeoJSON MultiLineString");
            boolean polygon = geomAsString.contains("GeoJSON Polygon") || geomAsString.contains("GeoJSON MultiPolygon");
            if (point && !line && !polygon)
                builder2.geometryType(TileLayer.GeometryType.points);
            else if (!point && line && !polygon)
                builder2.geometryType(TileLayer.GeometryType.lines);
            else if (!point && !line && polygon)
                builder2.geometryType(TileLayer.GeometryType.polygons);
        }
        final JsonSchemaObject properties = (JsonSchemaObject) schema.getProperties().get("properties");
        builder2.propertiesSchema(ImmutableJsonSchemaObject.builder().required(properties.getRequired()).properties(properties.getProperties()).patternProperties(properties.getPatternProperties()).build());
        builder.addLayers(builder2.build());
    });
    builder.links(links);
    return builder.build();
}
Also used : ImmutableTileSet(de.ii.ogcapi.tiles.domain.ImmutableTileSet) SimpleFeatureGeometry(de.ii.xtraplatform.geometries.domain.SimpleFeatureGeometry) CrsTransformationException(de.ii.xtraplatform.crs.domain.CrsTransformationException) Link(de.ii.ogcapi.foundation.domain.Link) LoggerFactory(org.slf4j.LoggerFactory) EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) JsonSchemaObject(de.ii.ogcapi.features.core.domain.JsonSchemaObject) VectorLayer(de.ii.ogcapi.tiles.domain.VectorLayer) TileLayer(de.ii.ogcapi.tiles.domain.TileLayer) BigDecimal(java.math.BigDecimal) JsonSchemaDocument(de.ii.ogcapi.features.core.domain.JsonSchemaDocument) Locale(java.util.Locale) Map(java.util.Map) JsonSchemaCache(de.ii.ogcapi.features.core.domain.JsonSchemaCache) FeatureSchema(de.ii.xtraplatform.features.domain.FeatureSchema) RoundingMode(java.math.RoundingMode) FeaturesCoreProviders(de.ii.ogcapi.features.core.domain.FeaturesCoreProviders) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableVectorLayer(de.ii.ogcapi.tiles.domain.ImmutableVectorLayer) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) Collectors(java.util.stream.Collectors) TilePoint(de.ii.ogcapi.tiles.domain.TilePoint) Objects(java.util.Objects) List(java.util.List) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) TileMatrixSet(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSet) CrsTransformerFactory(de.ii.xtraplatform.crs.domain.CrsTransformerFactory) Optional(java.util.Optional) BoundingBox(de.ii.xtraplatform.crs.domain.BoundingBox) FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) EntityRegistry(de.ii.xtraplatform.store.domain.entities.EntityRegistry) TileMatrixSetLimits(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimits) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer) TileSet(de.ii.ogcapi.tiles.domain.TileSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) TilesConfiguration(de.ii.ogcapi.tiles.domain.TilesConfiguration) ImmutableTileLayer(de.ii.ogcapi.tiles.domain.ImmutableTileLayer) ImmutableTilePoint(de.ii.ogcapi.tiles.domain.ImmutableTilePoint) TileMatrixSetLimitsGenerator(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimitsGenerator) SchemaBase(de.ii.xtraplatform.features.domain.SchemaBase) ImmutableList(com.google.common.collect.ImmutableList) OgcCrs(de.ii.xtraplatform.crs.domain.OgcCrs) ImmutableFields(de.ii.ogcapi.tiles.domain.ImmutableFields) Builder(de.ii.ogcapi.tiles.domain.ImmutableTileSet.Builder) Logger(org.slf4j.Logger) ImmutableJsonSchemaObject(de.ii.ogcapi.features.core.domain.ImmutableJsonSchemaObject) MinMax(de.ii.ogcapi.tiles.domain.MinMax) TilesBoundingBox(de.ii.ogcapi.tiles.domain.tileMatrixSet.TilesBoundingBox) URICustomizer(de.ii.ogcapi.foundation.domain.URICustomizer) FeaturesCoreConfiguration(de.ii.ogcapi.features.core.domain.FeaturesCoreConfiguration) GeoJsonConfiguration(de.ii.ogcapi.features.geojson.domain.GeoJsonConfiguration) JsonSchema(de.ii.ogcapi.features.core.domain.JsonSchema) ImmutableTilesBoundingBox(de.ii.ogcapi.tiles.domain.tileMatrixSet.ImmutableTilesBoundingBox) AbstractMap(java.util.AbstractMap) SchemaInfo(de.ii.ogcapi.features.core.domain.SchemaInfo) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) Builder(de.ii.ogcapi.tiles.domain.ImmutableTileSet.Builder) JsonSchema(de.ii.ogcapi.features.core.domain.JsonSchema) TilesConfiguration(de.ii.ogcapi.tiles.domain.TilesConfiguration) ImmutableTilePoint(de.ii.ogcapi.tiles.domain.ImmutableTilePoint) FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) ImmutableTileLayer(de.ii.ogcapi.tiles.domain.ImmutableTileLayer) BoundingBox(de.ii.xtraplatform.crs.domain.BoundingBox) TilesBoundingBox(de.ii.ogcapi.tiles.domain.tileMatrixSet.TilesBoundingBox) ImmutableTilesBoundingBox(de.ii.ogcapi.tiles.domain.tileMatrixSet.ImmutableTilesBoundingBox) JsonSchemaDocument(de.ii.ogcapi.features.core.domain.JsonSchemaDocument) Optional(java.util.Optional) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) JsonSchemaCache(de.ii.ogcapi.features.core.domain.JsonSchemaCache) CrsTransformationException(de.ii.xtraplatform.crs.domain.CrsTransformationException) Objects(java.util.Objects) JsonSchemaObject(de.ii.ogcapi.features.core.domain.JsonSchemaObject) ImmutableJsonSchemaObject(de.ii.ogcapi.features.core.domain.ImmutableJsonSchemaObject)

Example 2 with CrsTransformationException

use of de.ii.xtraplatform.crs.domain.CrsTransformationException in project ldproxy by interactive-instruments.

the class CapabilityFeaturesCore method computeBbox.

private Optional<BoundingBox> computeBbox(OgcApiDataV2 apiData, String collectionId) {
    FeatureTypeConfigurationOgcApi collectionData = apiData.getCollections().get(collectionId);
    Optional<FeatureProvider2> featureProvider = providers.getFeatureProvider(apiData, collectionData);
    if (featureProvider.map(FeatureProvider2::supportsExtents).orElse(false)) {
        Optional<BoundingBox> spatialExtent = featureProvider.get().extents().getSpatialExtent(collectionId);
        if (spatialExtent.isPresent()) {
            BoundingBox boundingBox = spatialExtent.get();
            if (!boundingBox.getEpsgCrs().equals(OgcCrs.CRS84) && !boundingBox.getEpsgCrs().equals(OgcCrs.CRS84h)) {
                Optional<CrsTransformer> transformer = crsTransformerFactory.getTransformer(boundingBox.getEpsgCrs(), OgcCrs.CRS84);
                if (transformer.isPresent()) {
                    try {
                        boundingBox = transformer.get().transformBoundingBox(boundingBox);
                    } catch (CrsTransformationException e) {
                        LOGGER.error("Error while computing spatial extent of collection '{}' while transforming the CRS of the bounding box: {}", collectionId, e.getMessage());
                        return Optional.empty();
                    }
                }
            }
            return Optional.of(boundingBox);
        }
    }
    return Optional.empty();
}
Also used : FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) BoundingBox(de.ii.xtraplatform.crs.domain.BoundingBox) CrsTransformationException(de.ii.xtraplatform.crs.domain.CrsTransformationException) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer)

Example 3 with CrsTransformationException

use of de.ii.xtraplatform.crs.domain.CrsTransformationException in project ldproxy by interactive-instruments.

the class AbstractEndpointTileSingleCollection method getTile.

protected Response getTile(OgcApi api, ApiRequestContext requestContext, UriInfo uriInfo, String definitionPath, String collectionId, String tileMatrixSetId, String tileMatrix, String tileRow, String tileCol, TileProvider tileProvider) throws CrsTransformationException, IOException, NotFoundException {
    OgcApiDataV2 apiData = api.getData();
    Map<String, String> queryParams = toFlatMap(uriInfo.getQueryParameters());
    FeatureTypeConfigurationOgcApi featureType = apiData.getCollections().get(collectionId);
    TilesConfiguration tilesConfiguration = featureType.getExtension(TilesConfiguration.class).orElseThrow();
    checkPathParameter(extensionRegistry, apiData, definitionPath, "collectionId", collectionId);
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileMatrixSetId", tileMatrixSetId);
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileMatrix", tileMatrix);
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileRow", tileRow);
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileCol", tileCol);
    final List<OgcApiQueryParameter> allowedParameters = getQueryParameters(extensionRegistry, apiData, definitionPath, collectionId);
    int row;
    int col;
    int level;
    try {
        level = Integer.parseInt(tileMatrix);
        row = Integer.parseInt(tileRow);
        col = Integer.parseInt(tileCol);
    } catch (NumberFormatException e) {
        throw new ServerErrorException("Could not convert tile coordinates that have been validated to integers", 500);
    }
    MinMax zoomLevels = tilesConfiguration.getZoomLevelsDerived().get(tileMatrixSetId);
    if (zoomLevels.getMax() < level || zoomLevels.getMin() > level)
        throw new NotFoundException("The requested tile is outside the zoom levels for this tile set.");
    TileMatrixSet tileMatrixSet = tileMatrixSetRepository.get(tileMatrixSetId).orElseThrow(() -> new NotFoundException("Unknown tile matrix set: " + tileMatrixSetId));
    TileMatrixSetLimits tileLimits = limitsGenerator.getCollectionTileMatrixSetLimits(api, collectionId, tileMatrixSet, zoomLevels).stream().filter(limits -> limits.getTileMatrix().equals(tileMatrix)).findAny().orElse(null);
    if (tileLimits != null) {
        if (tileLimits.getMaxTileCol() < col || tileLimits.getMinTileCol() > col || tileLimits.getMaxTileRow() < row || tileLimits.getMinTileRow() > row)
            // return 404, if outside the range
            throw new NotFoundException("The requested tile is outside of the limits for this zoom level and tile set.");
    }
    String path = definitionPath.replace("{collectionId}", collectionId).replace("{tileMatrixSetId}", tileMatrixSetId).replace("{tileMatrix}", tileMatrix).replace("{tileRow}", tileRow).replace("{tileCol}", tileCol);
    TileFormatExtension outputFormat = requestContext.getApi().getOutputFormat(TileFormatExtension.class, requestContext.getMediaType(), path, Optional.of(collectionId)).orElseThrow(() -> new NotAcceptableException(MessageFormat.format("The requested media type ''{0}'' is not supported for this resource.", requestContext.getMediaType())));
    Optional<FeatureProvider2> featureProvider = providers.getFeatureProvider(apiData);
    // check, if the cache can be used (no query parameters except f)
    boolean useCache = tileProvider.tilesMayBeCached() && tilesConfiguration.getCache() != TilesConfiguration.TileCacheType.NONE && (queryParams.isEmpty() || (queryParams.size() == 1 && queryParams.containsKey("f")));
    // don't store the tile in the cache if it is outside the range
    MinMax cacheMinMax = tilesConfiguration.getZoomLevelsDerived().get(tileMatrixSetId);
    useCache = useCache && (Objects.isNull(cacheMinMax) || (level <= cacheMinMax.getMax() && level >= cacheMinMax.getMin()));
    Tile tile = new ImmutableTile.Builder().tileMatrixSet(tileMatrixSet).tileLevel(level).tileRow(row).tileCol(col).api(api).apiData(apiData).outputFormat(outputFormat).featureProvider(featureProvider).collectionIds(ImmutableList.of(collectionId)).temporary(!useCache).isDatasetTile(false).build();
    QueryInput queryInput = null;
    // if cache can be used and the tile is cached for the requested format, return the cache
    if (useCache) {
        // get the tile from the cache and return it
        Optional<InputStream> tileStream = Optional.empty();
        try {
            tileStream = cache.getTile(tile);
        } catch (Exception e) {
            LOGGER.warn("Failed to retrieve tile {}/{}/{}/{} for collection '{}' from the cache. Reason: {}", tile.getTileMatrixSet().getId(), tile.getTileLevel(), tile.getTileRow(), tile.getTileCol(), collectionId, e.getMessage());
        }
        if (tileStream.isPresent()) {
            queryInput = new Builder().from(getGenericQueryInput(apiData)).tile(tile).tileContent(tileStream.get()).build();
        }
    }
    // not cached or cache access failed
    if (Objects.isNull(queryInput))
        queryInput = tileProvider.getQueryInput(apiData, requestContext.getUriCustomizer(), queryParams, allowedParameters, getGenericQueryInput(apiData), tile);
    TilesQueriesHandler.Query query = null;
    if (queryInput instanceof TilesQueriesHandler.QueryInputTileMbtilesTile)
        query = TilesQueriesHandler.Query.MBTILES_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileTileServerTile)
        query = TilesQueriesHandler.Query.TILESERVER_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileEmpty)
        query = TilesQueriesHandler.Query.EMPTY_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileStream)
        query = TilesQueriesHandler.Query.TILE_STREAM;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileMultiLayer)
        query = TilesQueriesHandler.Query.MULTI_LAYER_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileSingleLayer)
        query = TilesQueriesHandler.Query.SINGLE_LAYER_TILE;
    return queryHandler.handle(query, queryInput, requestContext);
}
Also used : TilesQueriesHandler(de.ii.ogcapi.tiles.domain.TilesQueriesHandler) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) Builder(de.ii.ogcapi.tiles.domain.ImmutableQueryInputTileStream.Builder) TilesConfiguration(de.ii.ogcapi.tiles.domain.TilesConfiguration) NotFoundException(javax.ws.rs.NotFoundException) MinMax(de.ii.ogcapi.tiles.domain.MinMax) FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) QueryInput(de.ii.ogcapi.foundation.domain.QueryInput) TileMatrixSetLimits(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimits) TileMatrixSet(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSet) TileFormatExtension(de.ii.ogcapi.tiles.domain.TileFormatExtension) InputStream(java.io.InputStream) Tile(de.ii.ogcapi.tiles.domain.Tile) ImmutableTile(de.ii.ogcapi.tiles.domain.ImmutableTile) OgcApiQueryParameter(de.ii.ogcapi.foundation.domain.OgcApiQueryParameter) CrsTransformationException(de.ii.xtraplatform.crs.domain.CrsTransformationException) NotAcceptableException(javax.ws.rs.NotAcceptableException) IOException(java.io.IOException) NotFoundException(javax.ws.rs.NotFoundException) ServerErrorException(javax.ws.rs.ServerErrorException) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) NotAcceptableException(javax.ws.rs.NotAcceptableException) ServerErrorException(javax.ws.rs.ServerErrorException)

Example 4 with CrsTransformationException

use of de.ii.xtraplatform.crs.domain.CrsTransformationException in project ldproxy by interactive-instruments.

the class AbstractEndpointTileMultiCollection method getTile.

protected Response getTile(OgcApi api, ApiRequestContext requestContext, UriInfo uriInfo, String definitionPath, String tileMatrixSetId, String tileMatrix, String tileRow, String tileCol, TileProvider tileProvider) throws CrsTransformationException, IOException, NotFoundException {
    OgcApiDataV2 apiData = api.getData();
    Map<String, String> queryParams = toFlatMap(uriInfo.getQueryParameters());
    TilesConfiguration tilesConfiguration = apiData.getExtension(TilesConfiguration.class).orElseThrow();
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileMatrixSetId", tileMatrixSetId);
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileMatrix", tileMatrix);
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileRow", tileRow);
    checkPathParameter(extensionRegistry, apiData, definitionPath, "tileCol", tileCol);
    final List<OgcApiQueryParameter> allowedParameters = getQueryParameters(extensionRegistry, apiData, definitionPath);
    int row;
    int col;
    int level;
    try {
        level = Integer.parseInt(tileMatrix);
        row = Integer.parseInt(tileRow);
        col = Integer.parseInt(tileCol);
    } catch (NumberFormatException e) {
        throw new ServerErrorException("Could not convert tile coordinates that have been validated to integers", 500);
    }
    MinMax zoomLevels = tilesConfiguration.getZoomLevelsDerived().get(tileMatrixSetId);
    if (zoomLevels.getMax() < level || zoomLevels.getMin() > level)
        throw new NotFoundException("The requested tile is outside the zoom levels for this tile set.");
    TileMatrixSet tileMatrixSet = tileMatrixSetRepository.get(tileMatrixSetId).orElseThrow(() -> new NotFoundException("Unknown tile matrix set: " + tileMatrixSetId));
    TileMatrixSetLimits tileLimits = limitsGenerator.getTileMatrixSetLimits(api, tileMatrixSet, zoomLevels).stream().filter(limits -> limits.getTileMatrix().equals(tileMatrix)).findAny().orElse(null);
    if (tileLimits != null) {
        if (tileLimits.getMaxTileCol() < col || tileLimits.getMinTileCol() > col || tileLimits.getMaxTileRow() < row || tileLimits.getMinTileRow() > row)
            // return 404, if outside the range
            throw new NotFoundException("The requested tile is outside of the limits for this zoom level and tile set.");
    }
    String path = definitionPath.replace("{tileMatrixSetId}", tileMatrixSetId).replace("{tileMatrix}", tileMatrix).replace("{tileRow}", tileRow).replace("{tileCol}", tileCol);
    TileFormatExtension outputFormat = requestContext.getApi().getOutputFormat(TileFormatExtension.class, requestContext.getMediaType(), path, Optional.empty()).orElseThrow(() -> new NotAcceptableException(MessageFormat.format("The requested media type ''{0}'' is not supported for this resource.", requestContext.getMediaType())));
    Optional<FeatureProvider2> featureProvider = providers.getFeatureProvider(apiData);
    List<String> collections = queryParams.containsKey("collections") ? Splitter.on(",").splitToList(queryParams.get("collections")) : apiData.getCollections().values().stream().filter(collection -> apiData.isCollectionEnabled(collection.getId())).filter(collection -> {
        Optional<TilesConfiguration> layerConfiguration = collection.getExtension(TilesConfiguration.class);
        if (layerConfiguration.isEmpty() || !layerConfiguration.get().isEnabled() || !layerConfiguration.get().isMultiCollectionEnabled())
            return false;
        MinMax levels = layerConfiguration.get().getZoomLevelsDerived().get(tileMatrixSetId);
        return !Objects.nonNull(levels) || (levels.getMax() >= level && levels.getMin() <= level);
    }).map(FeatureTypeConfiguration::getId).collect(Collectors.toList());
    // check, if the cache can be used (no query parameters except f)
    boolean useCache = tileProvider.tilesMayBeCached() && tilesConfiguration.getCache() != TilesConfiguration.TileCacheType.NONE && (queryParams.isEmpty() || (queryParams.size() == 1 && queryParams.containsKey("f")));
    // don't store the tile in the cache if it is outside the range
    MinMax cacheMinMax = tilesConfiguration.getZoomLevelsDerived().get(tileMatrixSetId);
    useCache = useCache && (Objects.isNull(cacheMinMax) || (level <= cacheMinMax.getMax() && level >= cacheMinMax.getMin()));
    Tile tile = new ImmutableTile.Builder().tileMatrixSet(tileMatrixSet).tileLevel(level).tileRow(row).tileCol(col).api(api).apiData(apiData).outputFormat(outputFormat).featureProvider(featureProvider).collectionIds(collections).temporary(!useCache).isDatasetTile(true).build();
    QueryInput queryInput = null;
    // if cache can be used and the tile is cached for the requested format, return the cache
    if (useCache) {
        // get the tile from the cache and return it
        Optional<InputStream> tileStream = Optional.empty();
        try {
            tileStream = cache.getTile(tile);
        } catch (Exception e) {
            LOGGER.warn("Failed to retrieve multi-collection tile {}/{}/{}/{} from the cache. Reason: {}", tile.getTileMatrixSet().getId(), tile.getTileLevel(), tile.getTileRow(), tile.getTileCol(), e.getMessage());
        }
        if (tileStream.isPresent()) {
            queryInput = new Builder().from(getGenericQueryInput(apiData)).tile(tile).tileContent(tileStream.get()).build();
        }
    }
    // not cached or cache access failed
    if (Objects.isNull(queryInput))
        queryInput = tileProvider.getQueryInput(apiData, requestContext.getUriCustomizer(), queryParams, allowedParameters, getGenericQueryInput(apiData), tile);
    TilesQueriesHandler.Query query = null;
    if (queryInput instanceof TilesQueriesHandler.QueryInputTileMbtilesTile)
        query = TilesQueriesHandler.Query.MBTILES_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileTileServerTile)
        query = TilesQueriesHandler.Query.TILESERVER_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileEmpty)
        query = TilesQueriesHandler.Query.EMPTY_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileStream)
        query = TilesQueriesHandler.Query.TILE_STREAM;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileMultiLayer)
        query = TilesQueriesHandler.Query.MULTI_LAYER_TILE;
    else if (queryInput instanceof TilesQueriesHandler.QueryInputTileSingleLayer)
        query = TilesQueriesHandler.Query.SINGLE_LAYER_TILE;
    return queryHandler.handle(query, queryInput, requestContext);
}
Also used : Endpoint(de.ii.ogcapi.foundation.domain.Endpoint) CrsTransformationException(de.ii.xtraplatform.crs.domain.CrsTransformationException) LoggerFactory(org.slf4j.LoggerFactory) EndpointTileMultiCollection(de.ii.ogcapi.tiles.infra.EndpointTileMultiCollection) Map(java.util.Map) TileMatrixSetRepository(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetRepository) ImmutableOgcApiResourceData(de.ii.ogcapi.collections.domain.ImmutableOgcApiResourceData) Tile(de.ii.ogcapi.tiles.domain.Tile) ExtensionRegistry(de.ii.ogcapi.foundation.domain.ExtensionRegistry) Splitter(com.google.common.base.Splitter) ApiOperation(de.ii.ogcapi.foundation.domain.ApiOperation) ApiRequestContext(de.ii.ogcapi.foundation.domain.ApiRequestContext) FeaturesCoreProviders(de.ii.ogcapi.features.core.domain.FeaturesCoreProviders) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) HttpMethods(de.ii.ogcapi.foundation.domain.HttpMethods) Collectors(java.util.stream.Collectors) NotFoundException(javax.ws.rs.NotFoundException) ImmutableApiEndpointDefinition(de.ii.ogcapi.foundation.domain.ImmutableApiEndpointDefinition) Objects(java.util.Objects) ApiEndpointDefinition(de.ii.ogcapi.foundation.domain.ApiEndpointDefinition) List(java.util.List) TilesQueriesHandler(de.ii.ogcapi.tiles.domain.TilesQueriesHandler) Response(javax.ws.rs.core.Response) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) TileMatrixSet(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSet) CrsTransformerFactory(de.ii.xtraplatform.crs.domain.CrsTransformerFactory) TileProvider(de.ii.ogcapi.tiles.domain.TileProvider) Optional(java.util.Optional) FormatExtension(de.ii.ogcapi.foundation.domain.FormatExtension) ImmutableTile(de.ii.ogcapi.tiles.domain.ImmutableTile) UriInfo(javax.ws.rs.core.UriInfo) TileMatrixSetLimits(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimits) ExtensionConfiguration(de.ii.ogcapi.foundation.domain.ExtensionConfiguration) OgcApiPathParameter(de.ii.ogcapi.foundation.domain.OgcApiPathParameter) QueryInput(de.ii.ogcapi.foundation.domain.QueryInput) TilesConfiguration(de.ii.ogcapi.tiles.domain.TilesConfiguration) MessageFormat(java.text.MessageFormat) TileMatrixSetLimitsGenerator(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimitsGenerator) FeatureTypeConfiguration(de.ii.xtraplatform.features.domain.FeatureTypeConfiguration) OgcApiQueryParameter(de.ii.ogcapi.foundation.domain.OgcApiQueryParameter) TileCache(de.ii.ogcapi.tiles.domain.TileCache) NotAcceptableException(javax.ws.rs.NotAcceptableException) Logger(org.slf4j.Logger) MinMax(de.ii.ogcapi.tiles.domain.MinMax) IOException(java.io.IOException) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) StaticTileProviderStore(de.ii.ogcapi.tiles.domain.StaticTileProviderStore) ServerErrorException(javax.ws.rs.ServerErrorException) TileFormatExtension(de.ii.ogcapi.tiles.domain.TileFormatExtension) Builder(de.ii.ogcapi.tiles.domain.ImmutableQueryInputTileStream.Builder) InputStream(java.io.InputStream) TilesQueriesHandler(de.ii.ogcapi.tiles.domain.TilesQueriesHandler) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) Builder(de.ii.ogcapi.tiles.domain.ImmutableQueryInputTileStream.Builder) TilesConfiguration(de.ii.ogcapi.tiles.domain.TilesConfiguration) NotFoundException(javax.ws.rs.NotFoundException) MinMax(de.ii.ogcapi.tiles.domain.MinMax) QueryInput(de.ii.ogcapi.foundation.domain.QueryInput) TileMatrixSetLimits(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimits) TileMatrixSet(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSet) TileFormatExtension(de.ii.ogcapi.tiles.domain.TileFormatExtension) Optional(java.util.Optional) InputStream(java.io.InputStream) Tile(de.ii.ogcapi.tiles.domain.Tile) ImmutableTile(de.ii.ogcapi.tiles.domain.ImmutableTile) OgcApiQueryParameter(de.ii.ogcapi.foundation.domain.OgcApiQueryParameter) Endpoint(de.ii.ogcapi.foundation.domain.Endpoint) CrsTransformationException(de.ii.xtraplatform.crs.domain.CrsTransformationException) NotFoundException(javax.ws.rs.NotFoundException) NotAcceptableException(javax.ws.rs.NotAcceptableException) IOException(java.io.IOException) ServerErrorException(javax.ws.rs.ServerErrorException) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) NotAcceptableException(javax.ws.rs.NotAcceptableException) FeatureTypeConfiguration(de.ii.xtraplatform.features.domain.FeatureTypeConfiguration) ServerErrorException(javax.ws.rs.ServerErrorException)

Example 5 with CrsTransformationException

use of de.ii.xtraplatform.crs.domain.CrsTransformationException in project ldproxy by interactive-instruments.

the class TilesHelper method getBoundingBoxInTargetCrs.

// TODO: move to TileSet as @Value.Lazy
/**
 * convert a bounding box to a bounding box in another CRS
 * @param bbox the bounding box in some CRS
 * @param targetCrs the target CRS
 * @param crsTransformerFactory the factory for CRS transformations
 * @return the converted bounding box
 */
public static Optional<BoundingBox> getBoundingBoxInTargetCrs(BoundingBox bbox, EpsgCrs targetCrs, CrsTransformerFactory crsTransformerFactory) {
    EpsgCrs sourceCrs = bbox.getEpsgCrs();
    if (sourceCrs.getCode() == targetCrs.getCode() && sourceCrs.getForceAxisOrder() == targetCrs.getForceAxisOrder())
        return Optional.of(bbox);
    Optional<CrsTransformer> transformer = crsTransformerFactory.getTransformer(sourceCrs, targetCrs, true);
    if (transformer.isPresent()) {
        try {
            return Optional.ofNullable(transformer.get().transformBoundingBox(bbox));
        } catch (CrsTransformationException e) {
            LOGGER.error(String.format(Locale.US, "Cannot convert bounding box (%f, %f, %f, %f) from %s to %s. Reason: %s", bbox.getXmin(), bbox.getYmin(), bbox.getXmax(), bbox.getYmax(), sourceCrs, targetCrs, e.getMessage()));
            return Optional.empty();
        }
    }
    LOGGER.error(String.format(Locale.US, "Cannot convert bounding box (%f, %f, %f, %f) from %s to %s. Reason: no applicable transformer found.", bbox.getXmin(), bbox.getYmin(), bbox.getXmax(), bbox.getYmax(), sourceCrs, targetCrs));
    return Optional.empty();
}
Also used : EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) CrsTransformationException(de.ii.xtraplatform.crs.domain.CrsTransformationException) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer)

Aggregations

CrsTransformationException (de.ii.xtraplatform.crs.domain.CrsTransformationException)5 FeatureTypeConfigurationOgcApi (de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi)3 OgcApiDataV2 (de.ii.ogcapi.foundation.domain.OgcApiDataV2)3 MinMax (de.ii.ogcapi.tiles.domain.MinMax)3 TilesConfiguration (de.ii.ogcapi.tiles.domain.TilesConfiguration)3 TileMatrixSet (de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSet)3 TileMatrixSetLimits (de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimits)3 FeaturesCoreProviders (de.ii.ogcapi.features.core.domain.FeaturesCoreProviders)2 OgcApi (de.ii.ogcapi.foundation.domain.OgcApi)2 OgcApiQueryParameter (de.ii.ogcapi.foundation.domain.OgcApiQueryParameter)2 QueryInput (de.ii.ogcapi.foundation.domain.QueryInput)2 Builder (de.ii.ogcapi.tiles.domain.ImmutableQueryInputTileStream.Builder)2 ImmutableTile (de.ii.ogcapi.tiles.domain.ImmutableTile)2 Tile (de.ii.ogcapi.tiles.domain.Tile)2 TileFormatExtension (de.ii.ogcapi.tiles.domain.TileFormatExtension)2 TilesQueriesHandler (de.ii.ogcapi.tiles.domain.TilesQueriesHandler)2 TileMatrixSetLimitsGenerator (de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimitsGenerator)2 BoundingBox (de.ii.xtraplatform.crs.domain.BoundingBox)2 CrsTransformer (de.ii.xtraplatform.crs.domain.CrsTransformer)2 FeatureProvider2 (de.ii.xtraplatform.features.domain.FeatureProvider2)2