This is an automated email from the ASF dual-hosted git repository.
bchapuis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
The following commit(s) were added to refs/heads/main by this push:
new 6e0da543 Refactor the openstreetmap handlers (#564)
6e0da543 is described below
commit 6e0da543fd03fcd45f6532e15e3849003776f46d
Author: Bertil Chapuis <[email protected]>
AuthorDate: Fri Dec 23 11:12:11 2022 +0100
Refactor the openstreetmap handlers (#564)
* Split the coordinate and reference map builders
* Improve way geometry creation
* Add a consumer that collects geometries in a map
* Simplify the coordinate and reference map builders
* Improve projection transformer
---
.../baremaps/collection/type/GeometryDataType.java | 42 ++++++++++++++++
.../apache/baremaps/database/ImportService.java | 22 ++++++---
.../openstreetmap/function/CacheBuilder.java | 57 ----------------------
.../function/CoordinateMapBuilder.java | 44 +++++++++++++++++
.../function/EntityProjectionTransformer.java | 18 +++++--
.../openstreetmap/function/GeometryMapBuilder.java | 51 +++++++++++++++++++
.../function/ReferenceMapBuilder.java | 44 +++++++++++++++++
.../openstreetmap/function/WayGeometryBuilder.java | 5 +-
.../baremaps/openstreetmap/pbf/PbfBlockReader.java | 16 ++++--
.../baremaps/collection/type/DataTypeProvider.java | 6 +++
codestyle.xml | 2 +-
11 files changed, 230 insertions(+), 77 deletions(-)
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/collection/type/GeometryDataType.java
b/baremaps-core/src/main/java/org/apache/baremaps/collection/type/GeometryDataType.java
new file mode 100644
index 00000000..4227eb37
--- /dev/null
+++
b/baremaps-core/src/main/java/org/apache/baremaps/collection/type/GeometryDataType.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+
+package org.apache.baremaps.collection.type;
+
+
+
+import java.nio.ByteBuffer;
+import org.apache.baremaps.openstreetmap.utils.GeometryUtils;
+import org.locationtech.jts.geom.Geometry;
+
+public class GeometryDataType implements DataType<Geometry> {
+
+ @Override
+ public int size(Geometry value) {
+ return 4 + GeometryUtils.serialize(value).length;
+ }
+
+ @Override
+ public void write(ByteBuffer buffer, int position, Geometry value) {
+ byte[] bytes = GeometryUtils.serialize(value);
+ buffer.putInt(position, bytes.length);
+ buffer.put(position + 4, bytes);
+ }
+
+ @Override
+ public Geometry read(ByteBuffer buffer, int position) {
+ int length = buffer.getInt(position);
+ byte[] bytes = new byte[length];
+ buffer.get(position + 4, bytes);
+ return GeometryUtils.deserialize(bytes);
+ }
+}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/database/ImportService.java
b/baremaps-core/src/main/java/org/apache/baremaps/database/ImportService.java
index ab1b58ad..e3af0a56 100644
---
a/baremaps-core/src/main/java/org/apache/baremaps/database/ImportService.java
+++
b/baremaps-core/src/main/java/org/apache/baremaps/database/ImportService.java
@@ -23,10 +23,7 @@ import java.util.concurrent.Callable;
import org.apache.baremaps.collection.LongDataMap;
import org.apache.baremaps.database.repository.HeaderRepository;
import org.apache.baremaps.database.repository.Repository;
-import org.apache.baremaps.openstreetmap.function.BlockEntitiesHandler;
-import org.apache.baremaps.openstreetmap.function.CacheBuilder;
-import org.apache.baremaps.openstreetmap.function.EntityGeometryBuilder;
-import org.apache.baremaps.openstreetmap.function.EntityProjectionTransformer;
+import org.apache.baremaps.openstreetmap.function.*;
import org.apache.baremaps.openstreetmap.model.Node;
import org.apache.baremaps.openstreetmap.model.Relation;
import org.apache.baremaps.openstreetmap.model.Way;
@@ -60,17 +57,26 @@ public class ImportService implements Callable<Void> {
@Override
public Void call() throws Exception {
- var cacheBuilder = new CacheBuilder(coordinateMap, referenceMap);
+ // Initialize and chain the entity handlers
+ var coordinateMapBuilder = new CoordinateMapBuilder(coordinateMap);
+ var referenceMapBuilder = new ReferenceMapBuilder(referenceMap);
var entityGeometryBuilder = new EntityGeometryBuilder(coordinateMap,
referenceMap);
var entityProjectionTransformer = new EntityProjectionTransformer(4326,
databaseSrid);
- var blockEntitiesHandler =
- new
BlockEntitiesHandler(entityGeometryBuilder.andThen(entityProjectionTransformer));
- var blockMapper =
consumeThenReturn(cacheBuilder.andThen(blockEntitiesHandler));
+ var entityHandler = coordinateMapBuilder
+ .andThen(referenceMapBuilder)
+ .andThen(entityGeometryBuilder)
+ .andThen(entityProjectionTransformer);
+
+ // Initialize the block mapper
+ var blockMapper = consumeThenReturn(new
BlockEntitiesHandler(entityHandler));
var blockImporter =
new BlockImporter(headerRepository, nodeRepository, wayRepository,
relationRepository);
+
+ // Process the blocks
try (InputStream inputStream = Files.newInputStream(path)) {
batch(new
PbfBlockReader().stream(inputStream).map(blockMapper)).forEach(blockImporter);
}
+
return null;
}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/CacheBuilder.java
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/CacheBuilder.java
deleted file mode 100644
index 435867eb..00000000
---
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/CacheBuilder.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
- * or implied. See the License for the specific language governing permissions
and limitations under
- * the License.
- */
-
-package org.apache.baremaps.openstreetmap.function;
-
-
-
-import java.util.List;
-import java.util.function.Consumer;
-import org.apache.baremaps.collection.LongDataMap;
-import org.apache.baremaps.openstreetmap.model.Block;
-import org.apache.baremaps.openstreetmap.model.DataBlock;
-import org.apache.baremaps.stream.StreamException;
-import org.locationtech.jts.geom.Coordinate;
-
-/** A consumer that caches openstreetmap coordinates and references. */
-public class CacheBuilder implements Consumer<Block> {
-
- private final LongDataMap<Coordinate> coordinateMap;
- private final LongDataMap<List<Long>> referenceMap;
-
- /**
- * Constructs a {@code CacheBlockConsumer} with the provided caches.
- *
- * @param coordinateMap the map of coordinates
- * @param referenceMap the map of references
- */
- public CacheBuilder(LongDataMap<Coordinate> coordinateMap,
LongDataMap<List<Long>> referenceMap) {
- this.coordinateMap = coordinateMap;
- this.referenceMap = referenceMap;
- }
-
- /** {@inheritDoc} */
- @Override
- public void accept(Block block) {
- try {
- if (block instanceof DataBlock dataBlock) {
- dataBlock.getDenseNodes().stream().forEach(
- node -> coordinateMap.put(node.getId(), new
Coordinate(node.getLon(), node.getLat())));
- dataBlock.getNodes().stream().forEach(
- node -> coordinateMap.put(node.getId(), new
Coordinate(node.getLon(), node.getLat())));
- dataBlock.getWays().stream().forEach(way ->
referenceMap.put(way.getId(), way.getNodes()));
- }
- } catch (Exception e) {
- throw new StreamException(e);
- }
- }
-}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/CoordinateMapBuilder.java
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/CoordinateMapBuilder.java
new file mode 100644
index 00000000..b0e1492b
--- /dev/null
+++
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/CoordinateMapBuilder.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+
+package org.apache.baremaps.openstreetmap.function;
+
+
+
+import java.util.function.Consumer;
+import org.apache.baremaps.collection.LongDataMap;
+import org.apache.baremaps.openstreetmap.model.Entity;
+import org.apache.baremaps.openstreetmap.model.Node;
+import org.locationtech.jts.geom.Coordinate;
+
+/** A consumer that stores openstreetmap coordinates in a map. */
+public class CoordinateMapBuilder implements Consumer<Entity> {
+
+ private final LongDataMap<Coordinate> coordinateMap;
+
+ /**
+ * Constructs a {@code CacheBlockConsumer} with the provided map.
+ *
+ * @param coordinateMap the map of coordinates
+ */
+ public CoordinateMapBuilder(LongDataMap<Coordinate> coordinateMap) {
+ this.coordinateMap = coordinateMap;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void accept(Entity entity) {
+ if (entity instanceof Node node) {
+ coordinateMap.put(node.getId(), new Coordinate(node.getLon(),
node.getLat()));
+ }
+ }
+}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/EntityProjectionTransformer.java
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/EntityProjectionTransformer.java
index beb1a010..41a0096c 100644
---
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/EntityProjectionTransformer.java
+++
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/EntityProjectionTransformer.java
@@ -22,22 +22,30 @@ import org.locationtech.jts.geom.Geometry;
/** Changes the projection of the geometry of an entity via side-effects. */
public class EntityProjectionTransformer implements Consumer<Entity> {
+ private final int sourceSrid;
+
+ private final int targetSrid;
+
private final ProjectionTransformer projectionTransformer;
/**
* Creates a consumer that reproject geometries with the provided SRIDs.
*
- * @param inputSRID the input SRID
- * @param outputSRID the output SRID
+ * @param sourceSrid the source SRID
+ * @param targetSrid the target SRID
*/
- public EntityProjectionTransformer(int inputSRID, int outputSRID) {
- this.projectionTransformer = new ProjectionTransformer(inputSRID,
outputSRID);
+ public EntityProjectionTransformer(int sourceSrid, int targetSrid) {
+ this.sourceSrid = sourceSrid;
+ this.targetSrid = targetSrid;
+ this.projectionTransformer = new ProjectionTransformer(sourceSrid,
targetSrid);
}
/** {@inheritDoc} */
@Override
public void accept(Entity entity) {
- if (entity instanceof Element element && element.getGeometry() != null) {
+ if (sourceSrid != targetSrid
+ && entity instanceof Element element
+ && element.getGeometry() != null) {
Geometry geometry =
projectionTransformer.transform(element.getGeometry());
element.setGeometry(geometry);
}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/GeometryMapBuilder.java
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/GeometryMapBuilder.java
new file mode 100644
index 00000000..2828b496
--- /dev/null
+++
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/GeometryMapBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+
+package org.apache.baremaps.openstreetmap.function;
+
+
+
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import org.apache.baremaps.collection.LongDataMap;
+import org.apache.baremaps.openstreetmap.model.Element;
+import org.apache.baremaps.openstreetmap.model.Entity;
+import org.locationtech.jts.geom.Geometry;
+
+/**
+ * A consumer that stores the geometry of an element in a map.
+ */
+public class GeometryMapBuilder implements Consumer<Entity> {
+
+ private final LongDataMap<Geometry> geometryMap;
+
+ private final Predicate<Entity> filter;
+
+ /**
+ * Constructs a {@code GeometryMapBuilder} with the provided map.
+ *
+ * @param geometryMap the geometry map
+ * @param filter the entity filter
+ */
+ public GeometryMapBuilder(LongDataMap<Geometry> geometryMap,
Predicate<Entity> filter) {
+ this.geometryMap = geometryMap;
+ this.filter = filter;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void accept(Entity entity) {
+ if (filter.test(entity) && entity instanceof Element element) {
+ geometryMap.put(element.getId(), element.getGeometry());
+ }
+ }
+}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/ReferenceMapBuilder.java
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/ReferenceMapBuilder.java
new file mode 100644
index 00000000..6f720b1d
--- /dev/null
+++
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/ReferenceMapBuilder.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+
+package org.apache.baremaps.openstreetmap.function;
+
+
+
+import java.util.List;
+import java.util.function.Consumer;
+import org.apache.baremaps.collection.LongDataMap;
+import org.apache.baremaps.openstreetmap.model.Entity;
+import org.apache.baremaps.openstreetmap.model.Way;
+
+/** A consumer that stores openstreetmap references in a map. */
+public class ReferenceMapBuilder implements Consumer<Entity> {
+
+ private final LongDataMap<List<Long>> referenceMap;
+
+ /**
+ * Constructs a {@code CacheBlockConsumer} with the provided map.
+ *
+ * @param referenceMap the map of references
+ */
+ public ReferenceMapBuilder(LongDataMap<List<Long>> referenceMap) {
+ this.referenceMap = referenceMap;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void accept(Entity entity) {
+ if (entity instanceof Way way) {
+ referenceMap.put(way.getId(), way.getNodes());
+ }
+ }
+}
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/WayGeometryBuilder.java
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/WayGeometryBuilder.java
index 392cb909..3d6f21bc 100644
---
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/WayGeometryBuilder.java
+++
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/function/WayGeometryBuilder.java
@@ -50,7 +50,10 @@ public class WayGeometryBuilder implements Consumer<Way> {
Coordinate[] array = list.toArray(new Coordinate[list.size()]);
LineString line = GEOMETRY_FACTORY_WGS84.createLineString(array);
if (!line.isEmpty()) {
- if (!line.isClosed()) {
+ // Ways can be open or closed depending on the geometry or the tags:
+ // https://wiki.openstreetmap.org/wiki/Way
+ if (!line.isClosed() || way.getTags().containsKey("highway")
+ || way.getTags().containsKey("barrier")) {
way.setGeometry(line);
} else {
Polygon polygon =
GEOMETRY_FACTORY_WGS84.createPolygon(line.getCoordinates());
diff --git
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/pbf/PbfBlockReader.java
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/pbf/PbfBlockReader.java
index 7e74c969..42c442ca 100644
---
a/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/pbf/PbfBlockReader.java
+++
b/baremaps-core/src/main/java/org/apache/baremaps/openstreetmap/pbf/PbfBlockReader.java
@@ -147,13 +147,19 @@ public class PbfBlockReader implements OsmReader<Block> {
var blocks = StreamUtils.bufferInSourceOrder(StreamUtils.stream(new
BlobIterator(inputStream)),
new BlobToBlockMapper(), Runtime.getRuntime().availableProcessors());
if (geometry) {
- var cacheBuilder = new CacheBuilder(coordinateMap, referenceMap);
+ // Initialize and chain the entity handlers
+ var coordinateMapBuilder = new CoordinateMapBuilder(coordinateMap);
+ var referenceMapBuilder = new ReferenceMapBuilder(referenceMap);
var entityGeometryBuilder = new EntityGeometryBuilder(coordinateMap,
referenceMap);
var entityProjectionTransformer = new EntityProjectionTransformer(4326,
srid);
- var entityHandler = srid == 4326 ? entityGeometryBuilder
- : entityGeometryBuilder.andThen(entityProjectionTransformer);
- var blockEntitiesHandler = new BlockEntitiesHandler(entityHandler);
- var blockMapper =
consumeThenReturn(cacheBuilder.andThen(blockEntitiesHandler));
+ var entityHandler = coordinateMapBuilder
+ .andThen(referenceMapBuilder)
+ .andThen(entityGeometryBuilder)
+ .andThen(entityProjectionTransformer);
+
+ // Initialize the block mapper
+ var blockMapper = consumeThenReturn(new
BlockEntitiesHandler(entityHandler));
+
blocks = blocks.map(blockMapper);
}
return blocks;
diff --git
a/baremaps-core/src/test/java/org/apache/baremaps/collection/type/DataTypeProvider.java
b/baremaps-core/src/test/java/org/apache/baremaps/collection/type/DataTypeProvider.java
index 1d3b8eae..f6d53d92 100644
---
a/baremaps-core/src/test/java/org/apache/baremaps/collection/type/DataTypeProvider.java
+++
b/baremaps-core/src/test/java/org/apache/baremaps/collection/type/DataTypeProvider.java
@@ -18,6 +18,7 @@ import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.params.provider.Arguments;
import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.GeometryFactory;
public class DataTypeProvider {
@@ -29,6 +30,11 @@ public class DataTypeProvider {
Arguments.of(new DoubleListDataType(), List.of((double) 1, (double) 2,
(double) 3)),
Arguments.of(new FloatDataType(), (float) 1),
Arguments.of(new FloatListDataType(), List.of((float) 1, (float) 2,
(float) 3)),
+ Arguments.of(new GeometryDataType(),
+ new GeometryFactory().createPoint(new Coordinate(1, 1))),
+ Arguments.of(new GeometryDataType(),
+ new GeometryFactory()
+ .createLineString(new Coordinate[] {new Coordinate(1, 1), new
Coordinate(2, 2)})),
Arguments.of(new IntegerDataType(), 1),
Arguments.of(new IntegerListDataType(), List.of(1, 2, 3)),
Arguments.of(new LongDataType(), (long) 1),
diff --git a/codestyle.xml b/codestyle.xml
index 75a4c877..e7c3770e 100644
--- a/codestyle.xml
+++ b/codestyle.xml
@@ -65,7 +65,7 @@
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments"
value="true"/>
<setting
id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
value="do not insert"/>
<setting
id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations"
value="insert"/>
- <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines"
value="true"/>
+ <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines"
value="false"/>
<setting
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block"
value="insert"/>
<setting
id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call"
value="16"/>
<setting
id="org.eclipse.jdt.core.formatter.wrap_non_simple_local_variable_annotation"
value="true"/>