package com.onthegomap.planetiler; import com.onthegomap.planetiler.geo.GeometryException; import com.onthegomap.planetiler.geo.TileCoord; import com.onthegomap.planetiler.mbtiles.Mbtiles; import com.onthegomap.planetiler.reader.SourceFeature; import com.onthegomap.planetiler.reader.osm.OsmElement; import com.onthegomap.planetiler.reader.osm.OsmRelationInfo; import com.onthegomap.planetiler.util.Wikidata; import java.util.List; import java.util.Map; import java.util.function.Consumer; /** * Provides methods for implementations to control how maps are generated. *
* This includes: *
* {@link Profile#processFeature(SourceFeature, FeatureCollector)} only handles a single element at a time. To "join" * elements across or within sources, implementations can store data in instance fields and wait to process them until * an element is encountered in a later source, or the * {@link Profile#finish(String, FeatureCollector.Factory, Consumer)} method is called for a source. All methods may be * called concurrently by multiple threads, so implementations must be careful to ensure access to instance fields is * thread-safe. *
* For complex profiles, {@link ForwardingProfile} provides a framework for splitting the logic up into several handlers * (i.e. one per layer) and forwarding each element/event to the handlers that care about it. */ public interface Profile { // TODO might want to break this apart into sub-interfaces that ForwardingProfile (and TileArchiveMetadata) can use too /** * Allows profile to extract any information it needs from a {@link OsmElement.Node} during the first pass through OSM * elements. *
* The default implementation does nothing. * * @param node the OSM node */ default void preprocessOsmNode(OsmElement.Node node) {} /** * Allows profile to extract any information it needs from a {@link OsmElement.Way} during the first pass through OSM * elements. *
* The default implementation does nothing. * * @param way the OSM way */ default void preprocessOsmWay(OsmElement.Way way) {} /** * Extracts information from OSM relations that will be * passed along to {@link #processFeature(SourceFeature, FeatureCollector)} for any OSM element in that relation. *
* The result of this method is stored in memory. *
* The default implementation returns {@code null} to ignore all relations
*
* @param relation the OSM relation
* @return a list of relation info instances with information extracted from the relation to pass to
* {@link #processFeature(SourceFeature, FeatureCollector)}, or {@code null} to ignore.
*/
default List
* Multiple threads may invoke this method concurrently for a single data source so implementations should ensure
* thread-safe access to any shared data structures. Separate data sources are processed sequentially.
*
* All OSM nodes are processed first, then ways, then relations.
*
* @param sourceFeature the input feature from a source dataset (OSM element, shapefile element, etc.)
* @param features a collector for generating output map features to emit
*/
void processFeature(SourceFeature sourceFeature, FeatureCollector features);
/** Free any resources associated with this profile (i.e. shared data structures) */
default void release() {}
/**
* Apply any post-processing to features in an output layer of a tile before writing it to the output file
*
* These transformations may add, remove, or change the tags, geometry, or ordering of output features based on other
* features present in this tile. See {@link FeatureMerge} class for a set of common transformations that merge
* linestrings/polygons.
*
* Many threads invoke this method concurrently so ensure thread-safe access to any shared data structures.
*
* The default implementation passes through input features unaltered
*
* @param layer the output layer name
* @param zoom zoom level of the tile
* @param items all the output features in this layer in this tile
* @return the new list of output features or {@code null} to not change anything. Set any elements of the list to
* {@code null} if they should be ignored.
* @throws GeometryException for any recoverable geometric operation failures - the framework will log the error, emit
* the original input features, and continue processing other layers
*/
default List
* This is called before {@link #postProcessLayerFeatures(String, int, List)} gets called for each layer. Use this
* method if features in one layer should influence features in another layer, to create new layers from existing
* ones, or if you need to remove a layer entirely from the output.
*
* These transformations may add, remove, or change the tags, geometry, or ordering of output features based on other
* features present in this tile. See {@link FeatureMerge} class for a set of common transformations that merge
* linestrings/polygons.
*
* Many threads invoke this method concurrently so ensure thread-safe access to any shared data structures.
*
* The default implementation passes through input features unaltered
*
* @param tileCoord the tile being post-processed
* @param layers all the output features in each layer on this tile
* @return the new map from layer to features or {@code null} to not change anything. Set any elements of the lists to
* {@code null} if they should be ignored.
* @throws GeometryException for any recoverable geometric operation failures - the framework will log the error, emit
* the original input features, and continue processing other tiles
*/
default Map
* The default implementation sets {@code type="baselayer"}
*
* @see MBTiles specification
*/
default boolean isOverlay() {
return false;
}
default Map
* The default implementation returns {@code true} for all elements
*
* @param elem the input OSM element
* @return {@code true} to fetch wikidata translations for {@code elem}, {@code false} to ignore
*/
default boolean caresAboutWikidataTranslation(OsmElement elem) {
return true;
}
/**
* Invoked once for each source after all elements for that source have been processed.
*
* @param sourceName the name of the source that just finished
* @param featureCollectors a supplier for new {@link FeatureCollector} instances for a {@link SourceFeature}.
* @param next a consumer to pass finished map features to
*/
default void finish(String sourceName, FeatureCollector.Factory featureCollectors,
Consumer
* The default implementation returns true.
*
* @param name the input source name
* @return {@code true} if this profile uses that source, {@code false} if it is safe to ignore
*/
default boolean caresAboutSource(String name) {
return true;
}
/**
* Returns an estimate for how many bytes of disk this profile will use for intermediate feature storage to warn when
* running with insufficient disk space.
*/
default long estimateIntermediateDiskBytes(long osmFileSize) {
return 0L;
}
/**
* Returns an estimate for how many bytes the output file will be to warn when running with insufficient disk space.
*/
default long estimateOutputBytes(long osmFileSize) {
return 0L;
}
/**
* Returns an estimate for how many bytes of RAM this will use to warn when running with insufficient memory.
*
* This should include memory for things the profile stores in memory, as well as relations and multipolygons.
*/
default long estimateRamRequired(long osmFileSize) {
return 0L;
}
/**
* A default implementation of {@link Profile} that emits no output elements.
*/
class NullProfile implements Profile {
@Override
public void processFeature(SourceFeature sourceFeature, FeatureCollector features) {}
@Override
public List