use of de.ii.ogcapi.tiles.domain.TileProvider 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);
}
Aggregations