Search in sources :

Example 1 with CrsTransformer

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

the class TilesQueriesHandlerImpl method getMultiLayerTileResponse.

private Response getMultiLayerTileResponse(QueryInputTileMultiLayer queryInput, ApiRequestContext requestContext) {
    OgcApi api = requestContext.getApi();
    OgcApiDataV2 apiData = api.getData();
    Tile multiLayerTile = queryInput.getTile();
    List<String> collectionIds = multiLayerTile.getCollectionIds();
    Map<String, FeatureQuery> queryMap = queryInput.getQueryMap();
    Map<String, Tile> singleLayerTileMap = queryInput.getSingleLayerTileMap();
    FeatureProvider2 featureProvider = multiLayerTile.getFeatureProvider().get();
    TileMatrixSet tileMatrixSet = multiLayerTile.getTileMatrixSet();
    int tileLevel = multiLayerTile.getTileLevel();
    int tileRow = multiLayerTile.getTileRow();
    int tileCol = multiLayerTile.getTileCol();
    if (!(multiLayerTile.getOutputFormat() instanceof TileFormatWithQuerySupportExtension))
        throw new RuntimeException(String.format("Unexpected tile format without query support. Found: %s", multiLayerTile.getOutputFormat().getClass().getSimpleName()));
    TileFormatWithQuerySupportExtension outputFormat = (TileFormatWithQuerySupportExtension) multiLayerTile.getOutputFormat();
    // process parameters and generate query
    Optional<CrsTransformer> crsTransformer = Optional.empty();
    EpsgCrs targetCrs = tileMatrixSet.getCrs();
    if (featureProvider.supportsCrs()) {
        EpsgCrs sourceCrs = featureProvider.crs().getNativeCrs();
        crsTransformer = crsTransformerFactory.getTransformer(sourceCrs, targetCrs);
    }
    List<Link> links = new DefaultLinksGenerator().generateLinks(requestContext.getUriCustomizer(), requestContext.getMediaType(), requestContext.getAlternateMediaTypes(), i18n, requestContext.getLanguage());
    Map<String, ByteArrayOutputStream> byteArrayMap = new HashMap<>();
    for (String collectionId : collectionIds) {
        // TODO limitation of the current model: all layers have to come from the same feature provider and use the same CRS
        Tile tile = singleLayerTileMap.get(collectionId);
        if (!multiLayerTile.getTemporary()) {
            // use cached tile
            try {
                Optional<InputStream> tileContent = tileCache.getTile(tile);
                if (tileContent.isPresent()) {
                    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                    ByteStreams.copy(tileContent.get(), buffer);
                    byteArrayMap.put(collectionId, buffer);
                    continue;
                }
            } catch (SQLException | IOException e) {
            // could not read the cache, generate the tile
            }
        }
        String featureTypeId = apiData.getCollections().get(collectionId).getExtension(FeaturesCoreConfiguration.class).map(cfg -> cfg.getFeatureType().orElse(collectionId)).orElse(collectionId);
        FeatureQuery query = queryMap.get(collectionId);
        ImmutableFeatureTransformationContextTiles transformationContext;
        try {
            transformationContext = new ImmutableFeatureTransformationContextTiles.Builder().api(api).apiData(apiData).featureSchema(featureProvider.getData().getTypes().get(featureTypeId)).tile(tile).tileCache(tileCache).collectionId(collectionId).ogcApiRequest(requestContext).crsTransformer(crsTransformer).codelists(entityRegistry.getEntitiesForType(Codelist.class).stream().collect(Collectors.toMap(PersistentEntity::getId, c -> c))).defaultCrs(queryInput.getDefaultCrs()).links(links).isFeatureCollection(true).fields(query.getFields()).limit(query.getLimit()).offset(0).i18n(i18n).outputStream(new OutputStreamToByteConsumer()).build();
        } catch (Exception e) {
            throw new RuntimeException("Error building the tile transformation context.", e);
        }
        Optional<FeatureTokenEncoder<?>> encoder = outputFormat.getFeatureEncoder(transformationContext);
        if (outputFormat.supportsFeatureQuery() && encoder.isPresent()) {
            FeatureStream featureStream = featureProvider.queries().getFeatureStream(query);
            ResultReduced<byte[]> result = generateTile(featureStream, encoder.get(), transformationContext, outputFormat);
            if (result.isSuccess()) {
                byte[] bytes = result.reduced();
                ByteArrayOutputStream buffer = new ByteArrayOutputStream(bytes.length);
                buffer.write(bytes, 0, bytes.length);
                byteArrayMap.put(collectionId, buffer);
            }
        } else {
            throw new NotAcceptableException(MessageFormat.format("The requested media type {0} cannot be generated, because it does not support streaming.", requestContext.getMediaType().type()));
        }
    }
    TileFormatWithQuerySupportExtension.MultiLayerTileContent result;
    try {
        result = outputFormat.combineSingleLayerTilesToMultiLayerTile(tileMatrixSet, singleLayerTileMap, byteArrayMap);
    } catch (IOException e) {
        throw new RuntimeException("Error accessing the tile cache.", e);
    }
    // try to write/update tile in cache, if all collections have been processed
    if (result.isComplete) {
        try {
            tileCache.storeTile(multiLayerTile, result.byteArray);
        } catch (Throwable e) {
            String msg = "Failure to write the multi-layer file of tile {}/{}/{}/{} in dataset '{}', format '{}' to the cache";
            LogContext.errorAsInfo(LOGGER, e, msg, tileMatrixSet.getId(), tileLevel, tileRow, tileCol, api.getId(), outputFormat.getExtension());
        }
    }
    Date lastModified = null;
    EntityTag etag = getEtag(result.byteArray);
    Response.ResponseBuilder response = evaluatePreconditions(requestContext, lastModified, etag);
    if (Objects.nonNull(response))
        return response.build();
    return prepareSuccessResponse(requestContext, queryInput.getIncludeLinkHeader() ? links : null, lastModified, etag, queryInput.getCacheControl().orElse(null), queryInput.getExpires().orElse(null), null, true, String.format("%s_%d_%d_%d.%s", tileMatrixSet.getId(), tileLevel, tileRow, tileCol, outputFormat.getMediaType().fileExtension())).entity(result.byteArray).build();
}
Also used : Date(java.util.Date) Link(de.ii.ogcapi.foundation.domain.Link) LoggerFactory(org.slf4j.LoggerFactory) TileSetFormatExtension(de.ii.ogcapi.tiles.domain.TileSetFormatExtension) EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) TileSetsFormatExtension(de.ii.ogcapi.tiles.domain.TileSetsFormatExtension) ApiMediaType(de.ii.ogcapi.foundation.domain.ApiMediaType) MediaType(javax.ws.rs.core.MediaType) ByteArrayInputStream(java.io.ByteArrayInputStream) Map(java.util.Map) TileMatrixSetRepository(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetRepository) Tile(de.ii.ogcapi.tiles.domain.Tile) ExtensionRegistry(de.ii.ogcapi.foundation.domain.ExtensionRegistry) OutputStreamToByteConsumer(de.ii.xtraplatform.streams.domain.OutputStreamToByteConsumer) PersistentEntity(de.ii.xtraplatform.store.domain.entities.PersistentEntity) HtmlConfiguration(de.ii.ogcapi.html.domain.HtmlConfiguration) ApiRequestContext(de.ii.ogcapi.foundation.domain.ApiRequestContext) FeaturesCoreProviders(de.ii.ogcapi.features.core.domain.FeaturesCoreProviders) ImmutableMap(com.google.common.collect.ImmutableMap) FeatureTokenEncoder(de.ii.xtraplatform.features.domain.FeatureTokenEncoder) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) DefaultLinksGenerator(de.ii.ogcapi.foundation.domain.DefaultLinksGenerator) CompletionException(java.util.concurrent.CompletionException) StreamingOutput(javax.ws.rs.core.StreamingOutput) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) ImmutableFeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.ImmutableFeatureTransformationContextTiles) NotFoundException(javax.ws.rs.NotFoundException) Objects(java.util.Objects) List(java.util.List) TilesQueriesHandler(de.ii.ogcapi.tiles.domain.TilesQueriesHandler) Builder(de.ii.ogcapi.tiles.domain.ImmutableTileSets.Builder) 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) ByteStreams(com.google.common.io.ByteStreams) Sink(de.ii.xtraplatform.streams.domain.Reactive.Sink) Optional(java.util.Optional) WebApplicationException(javax.ws.rs.WebApplicationException) FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) EntityRegistry(de.ii.xtraplatform.store.domain.entities.EntityRegistry) QueryHandler(de.ii.ogcapi.foundation.domain.QueryHandler) FeatureQuery(de.ii.xtraplatform.features.domain.FeatureQuery) TileFormatWithQuerySupportExtension(de.ii.ogcapi.tiles.domain.TileFormatWithQuerySupportExtension) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer) QueryInput(de.ii.ogcapi.foundation.domain.QueryInput) PropertyTransformations(de.ii.xtraplatform.features.domain.transform.PropertyTransformations) HashMap(java.util.HashMap) Singleton(javax.inject.Singleton) TileSet(de.ii.ogcapi.tiles.domain.TileSet) LogContext(de.ii.xtraplatform.base.domain.LogContext) DataType(de.ii.ogcapi.tiles.domain.TileSet.DataType) AutoBind(com.github.azahnen.dagger.annotations.AutoBind) MessageFormat(java.text.MessageFormat) Inject(javax.inject.Inject) ClientBuilder(javax.ws.rs.client.ClientBuilder) TileMatrixSetLimitsGenerator(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimitsGenerator) SQLException(java.sql.SQLException) ImmutableList(com.google.common.collect.ImmutableList) QueriesHandler(de.ii.ogcapi.foundation.domain.QueriesHandler) ImmutableTileSets(de.ii.ogcapi.tiles.domain.ImmutableTileSets) FeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.FeatureTransformationContextTiles) TileCache(de.ii.ogcapi.tiles.domain.TileCache) NotAcceptableException(javax.ws.rs.NotAcceptableException) Logger(org.slf4j.Logger) MinMax(de.ii.ogcapi.tiles.domain.MinMax) I18n(de.ii.ogcapi.foundation.domain.I18n) IOException(java.io.IOException) FeatureStream(de.ii.xtraplatform.features.domain.FeatureStream) EntityTag(javax.ws.rs.core.EntityTag) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) StaticTileProviderStore(de.ii.ogcapi.tiles.domain.StaticTileProviderStore) FeaturesCoreConfiguration(de.ii.ogcapi.features.core.domain.FeaturesCoreConfiguration) SinkReduced(de.ii.xtraplatform.streams.domain.Reactive.SinkReduced) ServerErrorException(javax.ws.rs.ServerErrorException) ResultReduced(de.ii.xtraplatform.features.domain.FeatureStream.ResultReduced) TileSets(de.ii.ogcapi.tiles.domain.TileSets) TileFormatExtension(de.ii.ogcapi.tiles.domain.TileFormatExtension) WebTarget(javax.ws.rs.client.WebTarget) Comparator(java.util.Comparator) InputStream(java.io.InputStream) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) FeatureStream(de.ii.xtraplatform.features.domain.FeatureStream) HashMap(java.util.HashMap) SQLException(java.sql.SQLException) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) PersistentEntity(de.ii.xtraplatform.store.domain.entities.PersistentEntity) FeatureQuery(de.ii.xtraplatform.features.domain.FeatureQuery) OutputStreamToByteConsumer(de.ii.xtraplatform.streams.domain.OutputStreamToByteConsumer) DefaultLinksGenerator(de.ii.ogcapi.foundation.domain.DefaultLinksGenerator) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer) EntityTag(javax.ws.rs.core.EntityTag) ImmutableFeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.ImmutableFeatureTransformationContextTiles) TileMatrixSet(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSet) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) Tile(de.ii.ogcapi.tiles.domain.Tile) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) NotFoundException(javax.ws.rs.NotFoundException) WebApplicationException(javax.ws.rs.WebApplicationException) SQLException(java.sql.SQLException) NotAcceptableException(javax.ws.rs.NotAcceptableException) IOException(java.io.IOException) ServerErrorException(javax.ws.rs.ServerErrorException) Date(java.util.Date) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) Response(javax.ws.rs.core.Response) FeatureTokenEncoder(de.ii.xtraplatform.features.domain.FeatureTokenEncoder) EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) NotAcceptableException(javax.ws.rs.NotAcceptableException) TileFormatWithQuerySupportExtension(de.ii.ogcapi.tiles.domain.TileFormatWithQuerySupportExtension) Link(de.ii.ogcapi.foundation.domain.Link)

Example 2 with CrsTransformer

use of de.ii.xtraplatform.crs.domain.CrsTransformer 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 CrsTransformer

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

the class TilesQueriesHandlerImpl method getSingleLayerTileResponse.

private Response getSingleLayerTileResponse(QueryInputTileSingleLayer queryInput, ApiRequestContext requestContext) {
    OgcApi api = requestContext.getApi();
    OgcApiDataV2 apiData = api.getData();
    Tile tile = queryInput.getTile();
    String collectionId = tile.getCollectionId();
    FeatureProvider2 featureProvider = tile.getFeatureProvider().get();
    FeatureQuery query = queryInput.getQuery();
    if (!(tile.getOutputFormat() instanceof TileFormatWithQuerySupportExtension))
        throw new RuntimeException(String.format("Unexpected tile format without query support. Found: %s", tile.getOutputFormat().getClass().getSimpleName()));
    TileFormatWithQuerySupportExtension outputFormat = (TileFormatWithQuerySupportExtension) tile.getOutputFormat();
    // process parameters and generate query
    Optional<CrsTransformer> crsTransformer = Optional.empty();
    EpsgCrs targetCrs = query.getCrs().orElse(queryInput.getDefaultCrs());
    if (featureProvider.supportsCrs()) {
        EpsgCrs sourceCrs = featureProvider.crs().getNativeCrs();
        crsTransformer = crsTransformerFactory.getTransformer(sourceCrs, targetCrs);
    }
    List<Link> links = new DefaultLinksGenerator().generateLinks(requestContext.getUriCustomizer(), requestContext.getMediaType(), requestContext.getAlternateMediaTypes(), i18n, requestContext.getLanguage());
    String featureTypeId = apiData.getCollections().get(collectionId).getExtension(FeaturesCoreConfiguration.class).map(cfg -> cfg.getFeatureType().orElse(collectionId)).orElse(collectionId);
    FeatureTransformationContextTiles transformationContext;
    try {
        transformationContext = new ImmutableFeatureTransformationContextTiles.Builder().api(api).apiData(apiData).featureSchema(featureProvider.getData().getTypes().get(featureTypeId)).tile(tile).tileCache(tileCache).collectionId(collectionId).ogcApiRequest(requestContext).crsTransformer(crsTransformer).codelists(entityRegistry.getEntitiesForType(Codelist.class).stream().collect(Collectors.toMap(PersistentEntity::getId, c -> c))).defaultCrs(queryInput.getDefaultCrs()).links(links).isFeatureCollection(true).fields(query.getFields()).limit(query.getLimit()).offset(0).i18n(i18n).outputStream(new OutputStreamToByteConsumer()).build();
    } catch (Exception e) {
        throw new RuntimeException("Error building the tile transformation context.", e);
    }
    Optional<FeatureTokenEncoder<?>> encoder = outputFormat.getFeatureEncoder(transformationContext);
    if (outputFormat.supportsFeatureQuery() && encoder.isPresent()) {
        FeatureStream featureStream = featureProvider.queries().getFeatureStream(query);
        ResultReduced<byte[]> result = generateTile(featureStream, encoder.get(), transformationContext, outputFormat);
        // internal processing, no need to process headers
        return prepareSuccessResponse(requestContext.getApi(), requestContext, null).entity(result.reduced()).build();
    } else {
        throw new NotAcceptableException(MessageFormat.format("The requested media type {0} cannot be generated, because it does not support streaming.", requestContext.getMediaType().type()));
    }
}
Also used : Date(java.util.Date) Link(de.ii.ogcapi.foundation.domain.Link) LoggerFactory(org.slf4j.LoggerFactory) TileSetFormatExtension(de.ii.ogcapi.tiles.domain.TileSetFormatExtension) EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) TileSetsFormatExtension(de.ii.ogcapi.tiles.domain.TileSetsFormatExtension) ApiMediaType(de.ii.ogcapi.foundation.domain.ApiMediaType) MediaType(javax.ws.rs.core.MediaType) ByteArrayInputStream(java.io.ByteArrayInputStream) Map(java.util.Map) TileMatrixSetRepository(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetRepository) Tile(de.ii.ogcapi.tiles.domain.Tile) ExtensionRegistry(de.ii.ogcapi.foundation.domain.ExtensionRegistry) OutputStreamToByteConsumer(de.ii.xtraplatform.streams.domain.OutputStreamToByteConsumer) PersistentEntity(de.ii.xtraplatform.store.domain.entities.PersistentEntity) HtmlConfiguration(de.ii.ogcapi.html.domain.HtmlConfiguration) ApiRequestContext(de.ii.ogcapi.foundation.domain.ApiRequestContext) FeaturesCoreProviders(de.ii.ogcapi.features.core.domain.FeaturesCoreProviders) ImmutableMap(com.google.common.collect.ImmutableMap) FeatureTokenEncoder(de.ii.xtraplatform.features.domain.FeatureTokenEncoder) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) DefaultLinksGenerator(de.ii.ogcapi.foundation.domain.DefaultLinksGenerator) CompletionException(java.util.concurrent.CompletionException) StreamingOutput(javax.ws.rs.core.StreamingOutput) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) ImmutableFeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.ImmutableFeatureTransformationContextTiles) NotFoundException(javax.ws.rs.NotFoundException) Objects(java.util.Objects) List(java.util.List) TilesQueriesHandler(de.ii.ogcapi.tiles.domain.TilesQueriesHandler) Builder(de.ii.ogcapi.tiles.domain.ImmutableTileSets.Builder) 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) ByteStreams(com.google.common.io.ByteStreams) Sink(de.ii.xtraplatform.streams.domain.Reactive.Sink) Optional(java.util.Optional) WebApplicationException(javax.ws.rs.WebApplicationException) FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) EntityRegistry(de.ii.xtraplatform.store.domain.entities.EntityRegistry) QueryHandler(de.ii.ogcapi.foundation.domain.QueryHandler) FeatureQuery(de.ii.xtraplatform.features.domain.FeatureQuery) TileFormatWithQuerySupportExtension(de.ii.ogcapi.tiles.domain.TileFormatWithQuerySupportExtension) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer) QueryInput(de.ii.ogcapi.foundation.domain.QueryInput) PropertyTransformations(de.ii.xtraplatform.features.domain.transform.PropertyTransformations) HashMap(java.util.HashMap) Singleton(javax.inject.Singleton) TileSet(de.ii.ogcapi.tiles.domain.TileSet) LogContext(de.ii.xtraplatform.base.domain.LogContext) DataType(de.ii.ogcapi.tiles.domain.TileSet.DataType) AutoBind(com.github.azahnen.dagger.annotations.AutoBind) MessageFormat(java.text.MessageFormat) Inject(javax.inject.Inject) ClientBuilder(javax.ws.rs.client.ClientBuilder) TileMatrixSetLimitsGenerator(de.ii.ogcapi.tiles.domain.tileMatrixSet.TileMatrixSetLimitsGenerator) SQLException(java.sql.SQLException) ImmutableList(com.google.common.collect.ImmutableList) QueriesHandler(de.ii.ogcapi.foundation.domain.QueriesHandler) ImmutableTileSets(de.ii.ogcapi.tiles.domain.ImmutableTileSets) FeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.FeatureTransformationContextTiles) TileCache(de.ii.ogcapi.tiles.domain.TileCache) NotAcceptableException(javax.ws.rs.NotAcceptableException) Logger(org.slf4j.Logger) MinMax(de.ii.ogcapi.tiles.domain.MinMax) I18n(de.ii.ogcapi.foundation.domain.I18n) IOException(java.io.IOException) FeatureStream(de.ii.xtraplatform.features.domain.FeatureStream) EntityTag(javax.ws.rs.core.EntityTag) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) StaticTileProviderStore(de.ii.ogcapi.tiles.domain.StaticTileProviderStore) FeaturesCoreConfiguration(de.ii.ogcapi.features.core.domain.FeaturesCoreConfiguration) SinkReduced(de.ii.xtraplatform.streams.domain.Reactive.SinkReduced) ServerErrorException(javax.ws.rs.ServerErrorException) ResultReduced(de.ii.xtraplatform.features.domain.FeatureStream.ResultReduced) TileSets(de.ii.ogcapi.tiles.domain.TileSets) TileFormatExtension(de.ii.ogcapi.tiles.domain.TileFormatExtension) WebTarget(javax.ws.rs.client.WebTarget) Comparator(java.util.Comparator) InputStream(java.io.InputStream) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) FeatureStream(de.ii.xtraplatform.features.domain.FeatureStream) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) FeatureTypeConfigurationOgcApi(de.ii.ogcapi.foundation.domain.FeatureTypeConfigurationOgcApi) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) PersistentEntity(de.ii.xtraplatform.store.domain.entities.PersistentEntity) FeatureQuery(de.ii.xtraplatform.features.domain.FeatureQuery) OutputStreamToByteConsumer(de.ii.xtraplatform.streams.domain.OutputStreamToByteConsumer) DefaultLinksGenerator(de.ii.ogcapi.foundation.domain.DefaultLinksGenerator) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer) ImmutableFeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.ImmutableFeatureTransformationContextTiles) Tile(de.ii.ogcapi.tiles.domain.Tile) ImmutableFeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.ImmutableFeatureTransformationContextTiles) FeatureTransformationContextTiles(de.ii.ogcapi.tiles.domain.FeatureTransformationContextTiles) CompletionException(java.util.concurrent.CompletionException) NotFoundException(javax.ws.rs.NotFoundException) WebApplicationException(javax.ws.rs.WebApplicationException) SQLException(java.sql.SQLException) NotAcceptableException(javax.ws.rs.NotAcceptableException) IOException(java.io.IOException) ServerErrorException(javax.ws.rs.ServerErrorException) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) FeatureTokenEncoder(de.ii.xtraplatform.features.domain.FeatureTokenEncoder) EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) NotAcceptableException(javax.ws.rs.NotAcceptableException) TileFormatWithQuerySupportExtension(de.ii.ogcapi.tiles.domain.TileFormatWithQuerySupportExtension) Link(de.ii.ogcapi.foundation.domain.Link)

Example 4 with CrsTransformer

use of de.ii.xtraplatform.crs.domain.CrsTransformer 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)

Example 5 with CrsTransformer

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

the class QueryHandlerRoutesImpl method computeRoute.

private Response computeRoute(QueryInputComputeRoute queryInput, ApiRequestContext requestContext) {
    OgcApi api = requestContext.getApi();
    OgcApiDataV2 apiData = api.getData();
    RouteDefinition routeDefinition = queryInput.getDefinition();
    String routeId = queryInput.getRouteId();
    FeatureQuery query = queryInput.getQuery();
    FeatureProvider2 featureProvider = queryInput.getFeatureProvider();
    RoutingConfiguration config = apiData.getExtension(RoutingConfiguration.class).orElseThrow(() -> new IllegalStateException("No routing configuration found for the API."));
    RoutesConfiguration providerConfig = featureProvider.getData().getExtension(RoutesConfiguration.class).orElseThrow(() -> new IllegalStateException("No routing configuration found for the feature provider of this API."));
    RouteFormatExtension outputFormat = api.getOutputFormat(RouteFormatExtension.class, requestContext.getMediaType(), "/routes", Optional.empty()).orElseThrow(() -> new NotAcceptableException(MessageFormat.format("The requested media type ''{0}'' is not supported for this resource.", requestContext.getMediaType())));
    RouteDefinitionInputs inputs = routeDefinition.getInputs();
    ImmutableRouteQuery.Builder routeQueryBuilder = ImmutableRouteQuery.builder().start(routeDefinition.getStart()).end(routeDefinition.getEnd()).wayPoints(routeDefinition.getWaypoints());
    String preference = inputs.getPreference().orElse(config.getDefaultPreference());
    routeQueryBuilder = processPreference(preference, providerConfig.getPreferences(), routeQueryBuilder);
    String mode = inputs.getMode().orElse(config.getDefaultMode());
    routeQueryBuilder = processMode(mode, providerConfig.getModes(), routeQueryBuilder);
    ImmutableList.Builder<String> flagBuilder = new ImmutableList.Builder<>();
    for (String flag : inputs.getAdditionalFlags()) {
        flagBuilder = processFlag(flag, config.getAdditionalFlags(), flagBuilder);
    }
    routeQueryBuilder.flags(flagBuilder.build());
    if (!inputs.getWeight().isEmpty() && !config.supportsWeightRestrictions()) {
        throw new IllegalArgumentException("This API does not support weight restrictions as part of the definition of a route.");
    }
    routeQueryBuilder.weight(inputs.getWeight());
    if (!inputs.getHeight().isEmpty() && !config.supportsHeightRestrictions()) {
        throw new IllegalArgumentException("This API does not support weight restrictions as part of the definition of a route.");
    }
    routeQueryBuilder.height(inputs.getHeight());
    Optional<Geometry.MultiPolygon> obstacles = routeDefinition.getObstacles();
    if (!obstacles.isEmpty() && !config.supportsObstacles()) {
        throw new IllegalArgumentException("This API does not support obstacles as part of the definition of a route.");
    }
    routeQueryBuilder.obstacles(obstacles);
    EpsgCrs waypointCrs = routeDefinition.getWaypointsCrs();
    if (!crsSupport.isSupported(apiData, waypointCrs)) {
        throw new IllegalArgumentException(String.format("The parameter 'coordRefSys' in the route definition is invalid: the crs '%s' is not supported", waypointCrs.toUriString()));
    }
    if (!routeDefinition.getWaypoints().isEmpty() && !config.supportsIntermediateWaypoints()) {
        throw new IllegalArgumentException(String.format("This API does not support waypoints in addition to the start and end location. The following waypoints were provided: %s", routeDefinition.getWaypoints().stream().map(p -> p.getCoordinates().get(0).toString()).collect(Collectors.joining(","))));
    }
    RouteQuery routeQuery = routeQueryBuilder.build();
    LOGGER.debug("Route Query: {}", routeQuery);
    query = ImmutableFeatureQuery.builder().from(query).addExtensions(routeQuery).build();
    Optional<CrsTransformer> crsTransformer = Optional.empty();
    boolean swapCoordinates = false;
    EpsgCrs sourceCrs = null;
    EpsgCrs targetCrs = query.getCrs().orElse(queryInput.getDefaultCrs());
    if (featureProvider.supportsCrs()) {
        sourceCrs = featureProvider.crs().getNativeCrs();
        crsTransformer = crsTransformerFactory.getTransformer(sourceCrs, targetCrs);
    }
    List<ApiMediaType> alternateMediaTypes = requestContext.getAlternateMediaTypes();
    List<Link> links = ImmutableList.of();
    if (config.isManageRoutesEnabled()) {
        links = new RoutesLinksGenerator().generateRouteLinks(routeId, inputs.getName(), requestContext.getUriCustomizer(), requestContext.getMediaType(), i18n, requestContext.getLanguage());
    }
    FeatureTransformationContextRoutes transformationContext = ImmutableFeatureTransformationContextRoutes.builder().api(api).apiData(api.getData()).featureSchema(featureProvider.getData().getTypes().get(queryInput.getFeatureTypeId())).collectionId("not_applicable").ogcApiRequest(requestContext).crsTransformer(crsTransformer).codelists(entityRegistry.getEntitiesForType(Codelist.class).stream().collect(Collectors.toMap(PersistentEntity::getId, c -> c))).defaultCrs(queryInput.getDefaultCrs()).sourceCrs(Optional.ofNullable(sourceCrs)).crs(targetCrs).links(links).isFeatureCollection(true).isHitsOnly(query.hitsOnly()).isPropertyOnly(query.propertyOnly()).fields(query.getFields()).limit(query.getLimit()).offset(query.getOffset()).maxAllowableOffset(query.getMaxAllowableOffset()).geometryPrecision(query.getGeometryPrecision()).isHitsOnlyIfMore(false).showsFeatureSelfLink(false).name(inputs.getName()).format(outputFormat).outputStream(new OutputStreamToByteConsumer()).startTimeNano(System.nanoTime()).speedLimitUnit(queryInput.getSpeedLimitUnit()).elevationProfileSimplificationTolerance(queryInput.getElevationProfileSimplificationTolerance()).crsInfo(crsInfo).build();
    Optional<FeatureTokenEncoder<?>> encoder = outputFormat.getFeatureEncoder(transformationContext, Optional.empty());
    if (encoder.isEmpty()) {
        throw new NotAcceptableException(MessageFormat.format("The requested media type {0} cannot be generated, because it does not support streaming.", requestContext.getMediaType().type()));
    }
    FeatureStream featureStream = featureProvider.queries().getFeatureStream(query);
    StreamingOutput streamingOutput = stream(featureStream, encoder.get());
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
        streamingOutput.write(baos);
    } catch (IOException e) {
        throw new IllegalStateException("Feature stream error.", e);
    }
    byte[] result = baos.toByteArray();
    Date lastModified = null;
    EntityTag etag = getEtag(result);
    Response.ResponseBuilder response = evaluatePreconditions(requestContext, lastModified, etag);
    if (Objects.nonNull(response))
        return response.build();
    // write routeDefinition and route if managing routes is enabled
    if (config.isManageRoutesEnabled()) {
        try {
            List<Link> definitionLinks = new RoutesLinksGenerator().generateRouteDefinitionLinks(routeId, inputs.getName(), requestContext.getUriCustomizer(), RouteDefinitionFormatJson.MEDIA_TYPE, i18n, requestContext.getLanguage());
            routeRepository.writeRouteAndDefinition(apiData, routeId, outputFormat, result, routeDefinition, definitionLinks);
        } catch (IOException e) {
            LOGGER.error("Could not store route in route repository.", e);
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Stacktrace: ", e);
        }
    }
    return prepareSuccessResponse(requestContext, queryInput.getIncludeLinkHeader() ? links : null, lastModified, etag, queryInput.getCacheControl().orElse(null), queryInput.getExpires().orElse(null), targetCrs, true, String.format("%s.%s", inputs.getName().orElse("Route"), outputFormat.getMediaType().fileExtension())).entity(result).build();
}
Also used : RouteRepository(de.ii.ogcapi.routes.domain.RouteRepository) Date(java.util.Date) Link(de.ii.ogcapi.foundation.domain.Link) EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) ImmutableRouteQuery(de.ii.xtraplatform.routes.sql.domain.ImmutableRouteQuery) ApiMediaType(de.ii.ogcapi.foundation.domain.ApiMediaType) CrsInfo(de.ii.xtraplatform.crs.domain.CrsInfo) RoutesConfiguration(de.ii.xtraplatform.routes.sql.domain.RoutesConfiguration) ImmutableRoutes(de.ii.ogcapi.routes.domain.ImmutableRoutes) MediaType(javax.ws.rs.core.MediaType) Map(java.util.Map) OutputStreamToByteConsumer(de.ii.xtraplatform.streams.domain.OutputStreamToByteConsumer) PersistentEntity(de.ii.xtraplatform.store.domain.entities.PersistentEntity) HtmlConfiguration(de.ii.ogcapi.html.domain.HtmlConfiguration) ApiRequestContext(de.ii.ogcapi.foundation.domain.ApiRequestContext) Geometry(de.ii.xtraplatform.cql.domain.Geometry) ImmutableMap(com.google.common.collect.ImmutableMap) FeatureTokenEncoder(de.ii.xtraplatform.features.domain.FeatureTokenEncoder) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) CompletionException(java.util.concurrent.CompletionException) StreamingOutput(javax.ws.rs.core.StreamingOutput) NotNull(javax.validation.constraints.NotNull) Collectors(java.util.stream.Collectors) NotFoundException(javax.ws.rs.NotFoundException) RouteDefinitionInputs(de.ii.ogcapi.routes.domain.RouteDefinitionInputs) Objects(java.util.Objects) List(java.util.List) Response(javax.ws.rs.core.Response) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) RoutesFormatExtension(de.ii.ogcapi.routes.domain.RoutesFormatExtension) RoutingConfiguration(de.ii.ogcapi.routes.domain.RoutingConfiguration) CrsTransformerFactory(de.ii.xtraplatform.crs.domain.CrsTransformerFactory) Optional(java.util.Optional) WebApplicationException(javax.ws.rs.WebApplicationException) EntityRegistry(de.ii.xtraplatform.store.domain.entities.EntityRegistry) RoutingFlag(de.ii.ogcapi.routes.domain.RoutingFlag) Preference(de.ii.xtraplatform.routes.sql.domain.Preference) QueryHandler(de.ii.ogcapi.foundation.domain.QueryHandler) Route(de.ii.ogcapi.routes.domain.Route) FeatureQuery(de.ii.xtraplatform.features.domain.FeatureQuery) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer) QueryInput(de.ii.ogcapi.foundation.domain.QueryInput) RouteFormatExtension(de.ii.ogcapi.routes.domain.RouteFormatExtension) Reactive(de.ii.xtraplatform.streams.domain.Reactive) Singleton(javax.inject.Singleton) AutoBind(com.github.azahnen.dagger.annotations.AutoBind) MessageFormat(java.text.MessageFormat) Inject(javax.inject.Inject) ImmutableList(com.google.common.collect.ImmutableList) RouteDefinition(de.ii.ogcapi.routes.domain.RouteDefinition) QueriesHandler(de.ii.ogcapi.foundation.domain.QueriesHandler) Routes(de.ii.ogcapi.routes.domain.Routes) CrsSupport(de.ii.ogcapi.crs.domain.CrsSupport) RouteQuery(de.ii.xtraplatform.routes.sql.domain.RouteQuery) NotAcceptableException(javax.ws.rs.NotAcceptableException) I18n(de.ii.ogcapi.foundation.domain.I18n) QueryHandlerRoutes(de.ii.ogcapi.routes.domain.QueryHandlerRoutes) RoutesLinksGenerator(de.ii.ogcapi.routes.domain.RoutesLinksGenerator) IOException(java.io.IOException) FeatureStream(de.ii.xtraplatform.features.domain.FeatureStream) EntityTag(javax.ws.rs.core.EntityTag) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) RouteDefinitionFormatJson(de.ii.ogcapi.routes.app.json.RouteDefinitionFormatJson) RouteDefinitionFormatExtension(de.ii.ogcapi.routes.domain.RouteDefinitionFormatExtension) ImmutableFeatureQuery(de.ii.xtraplatform.features.domain.ImmutableFeatureQuery) FeatureTransformationContextRoutes(de.ii.ogcapi.routes.domain.FeatureTransformationContextRoutes) ImmutableFeatureTransformationContextRoutes(de.ii.ogcapi.routes.domain.ImmutableFeatureTransformationContextRoutes) Codelist(de.ii.xtraplatform.codelists.domain.Codelist) FeatureStream(de.ii.xtraplatform.features.domain.FeatureStream) FeatureTransformationContextRoutes(de.ii.ogcapi.routes.domain.FeatureTransformationContextRoutes) ImmutableFeatureTransformationContextRoutes(de.ii.ogcapi.routes.domain.ImmutableFeatureTransformationContextRoutes) ImmutableList(com.google.common.collect.ImmutableList) OgcApi(de.ii.ogcapi.foundation.domain.OgcApi) FeatureProvider2(de.ii.xtraplatform.features.domain.FeatureProvider2) PersistentEntity(de.ii.xtraplatform.store.domain.entities.PersistentEntity) StreamingOutput(javax.ws.rs.core.StreamingOutput) FeatureQuery(de.ii.xtraplatform.features.domain.FeatureQuery) ImmutableFeatureQuery(de.ii.xtraplatform.features.domain.ImmutableFeatureQuery) OutputStreamToByteConsumer(de.ii.xtraplatform.streams.domain.OutputStreamToByteConsumer) RouteDefinitionInputs(de.ii.ogcapi.routes.domain.RouteDefinitionInputs) CrsTransformer(de.ii.xtraplatform.crs.domain.CrsTransformer) EntityTag(javax.ws.rs.core.EntityTag) RoutesLinksGenerator(de.ii.ogcapi.routes.domain.RoutesLinksGenerator) ImmutableRouteQuery(de.ii.xtraplatform.routes.sql.domain.ImmutableRouteQuery) RouteQuery(de.ii.xtraplatform.routes.sql.domain.RouteQuery) ApiMediaType(de.ii.ogcapi.foundation.domain.ApiMediaType) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) ImmutableRouteQuery(de.ii.xtraplatform.routes.sql.domain.ImmutableRouteQuery) Date(java.util.Date) OgcApiDataV2(de.ii.ogcapi.foundation.domain.OgcApiDataV2) Response(javax.ws.rs.core.Response) FeatureTokenEncoder(de.ii.xtraplatform.features.domain.FeatureTokenEncoder) RouteFormatExtension(de.ii.ogcapi.routes.domain.RouteFormatExtension) RouteDefinition(de.ii.ogcapi.routes.domain.RouteDefinition) EpsgCrs(de.ii.xtraplatform.crs.domain.EpsgCrs) RoutingConfiguration(de.ii.ogcapi.routes.domain.RoutingConfiguration) NotAcceptableException(javax.ws.rs.NotAcceptableException) RoutesConfiguration(de.ii.xtraplatform.routes.sql.domain.RoutesConfiguration) Link(de.ii.ogcapi.foundation.domain.Link)

Aggregations

CrsTransformer (de.ii.xtraplatform.crs.domain.CrsTransformer)7 FeatureProvider2 (de.ii.xtraplatform.features.domain.FeatureProvider2)5 AutoBind (com.github.azahnen.dagger.annotations.AutoBind)4 ImmutableList (com.google.common.collect.ImmutableList)4 ImmutableMap (com.google.common.collect.ImmutableMap)4 ApiMediaType (de.ii.ogcapi.foundation.domain.ApiMediaType)4 ApiRequestContext (de.ii.ogcapi.foundation.domain.ApiRequestContext)4 I18n (de.ii.ogcapi.foundation.domain.I18n)4 Link (de.ii.ogcapi.foundation.domain.Link)4 OgcApi (de.ii.ogcapi.foundation.domain.OgcApi)4 OgcApiDataV2 (de.ii.ogcapi.foundation.domain.OgcApiDataV2)4 QueriesHandler (de.ii.ogcapi.foundation.domain.QueriesHandler)4 QueryHandler (de.ii.ogcapi.foundation.domain.QueryHandler)4 QueryInput (de.ii.ogcapi.foundation.domain.QueryInput)4 HtmlConfiguration (de.ii.ogcapi.html.domain.HtmlConfiguration)4 EpsgCrs (de.ii.xtraplatform.crs.domain.EpsgCrs)4 Codelist (de.ii.xtraplatform.codelists.domain.Codelist)3 CrsTransformerFactory (de.ii.xtraplatform.crs.domain.CrsTransformerFactory)3 FeatureQuery (de.ii.xtraplatform.features.domain.FeatureQuery)3 FeatureStream (de.ii.xtraplatform.features.domain.FeatureStream)3